aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus38
-rw-r--r--Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus66
-rw-r--r--Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra73
-rw-r--r--Documentation/ABI/testing/dev-kmsg2
-rw-r--r--Documentation/ABI/testing/sysfs-bus-mdio9
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci34
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-batman-adv11
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-grcan35
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-mesh40
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power2
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-isku8
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus48
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus69
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-lua7
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra76
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-savu3
-rw-r--r--Documentation/ABI/testing/sysfs-driver-ppi2
-rw-r--r--Documentation/ABI/testing/sysfs-profiling6
-rw-r--r--Documentation/DocBook/writing-an-alsa-driver.tmpl85
-rw-r--r--Documentation/HOWTO2
-rw-r--r--Documentation/PCI/pci-iov-howto.txt48
-rw-r--r--Documentation/accounting/getdelays.c1
-rw-r--r--Documentation/bus-devices/ti-gpmc.txt122
-rw-r--r--Documentation/devicetree/bindings/arm/exynos/power_domain.txt15
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.txt4
-rw-r--r--Documentation/devicetree/bindings/ata/exynos-sata-phy.txt14
-rw-r--r--Documentation/devicetree/bindings/ata/exynos-sata.txt17
-rw-r--r--Documentation/devicetree/bindings/clock/imx25-clock.txt162
-rw-r--r--Documentation/devicetree/bindings/clock/zynq-7000.txt55
-rw-r--r--Documentation/devicetree/bindings/drm/exynos/hdmi.txt22
-rw-r--r--Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt12
-rw-r--r--Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt12
-rw-r--r--Documentation/devicetree/bindings/drm/exynos/mixer.txt15
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-poweroff.txt22
-rw-r--r--Documentation/devicetree/bindings/hwmon/vexpress.txt23
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/bu21013.txt28
-rw-r--r--Documentation/devicetree/bindings/media/s5p-mfc.txt23
-rw-r--r--Documentation/devicetree/bindings/misc/atmel-ssc.txt15
-rw-r--r--Documentation/devicetree/bindings/net/can/grcan.txt28
-rw-r--r--Documentation/devicetree/bindings/net/cdns-emac.txt23
-rw-r--r--Documentation/devicetree/bindings/net/cpsw.txt48
-rw-r--r--Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt39
-rw-r--r--Documentation/devicetree/bindings/regulator/gpio-regulator.txt37
-rw-r--r--Documentation/devicetree/bindings/regulator/max8925-regulator.txt40
-rw-r--r--Documentation/devicetree/bindings/regulator/max8997-regulator.txt146
-rw-r--r--Documentation/devicetree/bindings/regulator/vexpress.txt32
-rw-r--r--Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt19
-rw-r--r--Documentation/devicetree/bindings/sound/ak4104.txt22
-rw-r--r--Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt26
-rw-r--r--Documentation/devicetree/bindings/sound/cs4271.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt4
-rw-r--r--Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt21
-rw-r--r--Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt23
-rw-r--r--Documentation/devicetree/bindings/usb/ehci-orion.txt15
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/devicetree/bindings/watchdog/atmel-wdt.txt15
-rw-r--r--Documentation/dma-buf-sharing.txt4
-rw-r--r--Documentation/dontdiff1
-rw-r--r--Documentation/fault-injection/notifier-error-inject.txt4
-rw-r--r--Documentation/hid/uhid.txt2
-rw-r--r--Documentation/hwmon/pmbus2
-rw-r--r--Documentation/hwmon/vexpress34
-rw-r--r--Documentation/input/alps.txt2
-rw-r--r--Documentation/input/event-codes.txt11
-rw-r--r--Documentation/kbuild/modules.txt2
-rw-r--r--Documentation/kernel-doc-nano-HOWTO.txt13
-rw-r--r--Documentation/kernel-parameters.txt18
-rw-r--r--Documentation/misc-devices/mei/mei-amt-version.c4
-rw-r--r--Documentation/networking/batman-adv.txt3
-rw-r--r--Documentation/networking/ip-sysctl.txt56
-rw-r--r--Documentation/networking/packet_mmap.txt246
-rw-r--r--Documentation/networking/stmmac.txt28
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt3
-rw-r--r--Documentation/video4linux/bttv/Cards2
-rw-r--r--Documentation/video4linux/bttv/Sound-FAQ2
-rw-r--r--Documentation/vm/frontswap.txt2
-rw-r--r--MAINTAINERS29
-rw-r--r--README4
-rw-r--r--arch/alpha/include/asm/mmzone.h2
-rw-r--r--arch/alpha/include/asm/socket.h1
-rw-r--r--arch/alpha/kernel/pci_iommu.c12
-rw-r--r--arch/arm/Kconfig27
-rw-r--r--arch/arm/Kconfig.debug82
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/boot/dts/Makefile17
-rw-r--r--arch/arm/boot/dts/am335x-bone.dts8
-rw-r--r--arch/arm/boot/dts/am335x-evm.dts8
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi47
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi14
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi22
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_common.dtsi32
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi22
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi8
-rw-r--r--arch/arm/boot/dts/ccu9540.dts72
-rw-r--r--arch/arm/boot/dts/cros5250-common.dtsi184
-rw-r--r--arch/arm/boot/dts/dbx5x0.dtsi56
-rw-r--r--arch/arm/boot/dts/dove-cubox.dts10
-rw-r--r--arch/arm/boot/dts/dove.dtsi19
-rw-r--r--arch/arm/boot/dts/evk-pro3.dts12
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi54
-rw-r--r--arch/arm/boot/dts/exynos4210-origen.dts70
-rw-r--r--arch/arm/boot/dts/exynos4210-pinctrl.dtsi56
-rw-r--r--arch/arm/boot/dts/exynos4210-smdkv310.dts16
-rw-r--r--arch/arm/boot/dts/exynos4210-trats.dts87
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi12
-rw-r--r--arch/arm/boot/dts/exynos4212.dtsi28
-rw-r--r--arch/arm/boot/dts/exynos4412-smdk4412.dts45
-rw-r--r--arch/arm/boot/dts/exynos4412.dtsi28
-rw-r--r--arch/arm/boot/dts/exynos4x12-pinctrl.dtsi965
-rw-r--r--arch/arm/boot/dts/exynos4x12.dtsi69
-rw-r--r--arch/arm/boot/dts/exynos5250-smdk5250.dts56
-rw-r--r--arch/arm/boot/dts/exynos5250-snow.dts43
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi62
-rw-r--r--arch/arm/boot/dts/href.dtsi273
-rw-r--r--arch/arm/boot/dts/hrefprev60.dts48
-rw-r--r--arch/arm/boot/dts/hrefv60plus.dts217
-rw-r--r--arch/arm/boot/dts/imx23-olinuxino.dts23
-rw-r--r--arch/arm/boot/dts/imx23.dtsi13
-rw-r--r--arch/arm/boot/dts/imx25-karo-tx25.dts44
-rw-r--r--arch/arm/boot/dts/imx25.dtsi515
-rw-r--r--arch/arm/boot/dts/imx27-apf27.dts89
-rw-r--r--arch/arm/boot/dts/imx27.dtsi5
-rw-r--r--arch/arm/boot/dts/imx28-apf28.dts85
-rw-r--r--arch/arm/boot/dts/imx28-apf28dev.dts154
-rw-r--r--arch/arm/boot/dts/imx28-cfa10036.dts46
-rw-r--r--arch/arm/boot/dts/imx28-cfa10049.dts33
-rw-r--r--arch/arm/boot/dts/imx28-evk.dts13
-rw-r--r--arch/arm/boot/dts/imx28-sps1.dts169
-rw-r--r--arch/arm/boot/dts/imx28.dtsi35
-rw-r--r--arch/arm/boot/dts/imx51.dtsi43
-rw-r--r--arch/arm/boot/dts/imx53-qsb.dts62
-rw-r--r--arch/arm/boot/dts/imx53.dtsi92
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts64
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd.dts18
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi119
-rw-r--r--arch/arm/boot/dts/kirkwood-6281.dtsi44
-rw-r--r--arch/arm/boot/dts/kirkwood-6282.dtsi45
-rw-r--r--arch/arm/boot/dts/kirkwood-98dx4122.dtsi31
-rw-r--r--arch/arm/boot/dts/kirkwood-dnskw.dtsi140
-rw-r--r--arch/arm/boot/dts/kirkwood-dockstar.dts37
-rw-r--r--arch/arm/boot/dts/kirkwood-dreamplug.dts21
-rw-r--r--arch/arm/boot/dts/kirkwood-goflexnet.dts73
-rw-r--r--arch/arm/boot/dts/kirkwood-ib62x0.dts40
-rw-r--r--arch/arm/boot/dts/kirkwood-iconnect.dts51
-rw-r--r--arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts89
-rw-r--r--arch/arm/boot/dts/kirkwood-km_kirkwood.dts17
-rw-r--r--arch/arm/boot/dts/kirkwood-lsxl.dtsi95
-rw-r--r--arch/arm/boot/dts/kirkwood-mplcec4.dts59
-rw-r--r--arch/arm/boot/dts/kirkwood-openblocks_a6.dts59
-rw-r--r--arch/arm/boot/dts/kirkwood-ts219-6281.dts31
-rw-r--r--arch/arm/boot/dts/kirkwood-ts219-6282.dts31
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi17
-rw-r--r--arch/arm/boot/dts/lpc32xx.dtsi7
-rw-r--r--arch/arm/boot/dts/snowball.dts140
-rw-r--r--arch/arm/boot/dts/stuib.dtsi78
-rw-r--r--arch/arm/boot/dts/tegra20-harmony.dts25
-rw-r--r--arch/arm/boot/dts/tegra20-plutux.dts6
-rw-r--r--arch/arm/boot/dts/tegra20-seaboard.dts6
-rw-r--r--arch/arm/boot/dts/tegra20-tamonten.dtsi88
-rw-r--r--arch/arm/boot/dts/tegra20-tec.dts9
-rw-r--r--arch/arm/boot/dts/tegra20-trimslice.dts54
-rw-r--r--arch/arm/boot/dts/tegra20-ventana.dts90
-rw-r--r--arch/arm/boot/dts/tegra20-whistler.dts21
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi158
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu-a02.dts6
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu-a04.dts6
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu.dtsi37
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi170
-rw-r--r--arch/arm/boot/dts/u9540.dts72
-rw-r--r--arch/arm/boot/dts/zynq-7000.dtsi166
-rw-r--r--arch/arm/boot/dts/zynq-ep107.dts63
-rw-r--r--arch/arm/boot/dts/zynq-zc702.dts44
-rw-r--r--arch/arm/configs/marzen_defconfig14
-rw-r--r--arch/arm/configs/mxs_defconfig6
-rw-r--r--arch/arm/configs/omap2plus_defconfig3
-rw-r--r--arch/arm/configs/u8500_defconfig1
-rw-r--r--arch/arm/include/debug/imx.S20
-rw-r--r--arch/arm/include/debug/tegra.S223
-rw-r--r--arch/arm/include/debug/zynq.S (renamed from arch/arm/mach-zynq/include/mach/debug-macro.S)23
-rw-r--r--arch/arm/kernel/kprobes-test.c2
-rw-r--r--arch/arm/mach-at91/Kconfig4
-rw-r--r--arch/arm/mach-at91/at91rm9200.c9
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c6
-rw-r--r--arch/arm/mach-at91/at91sam9260.c3
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9261.c9
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c6
-rw-r--r--arch/arm/mach-at91/at91sam9263.c6
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c4
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c6
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c4
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c6
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c4
-rw-r--r--arch/arm/mach-at91/at91sam9x5.c1
-rw-r--r--arch/arm/mach-at91/board-csb337.c2
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek.c11
-rw-r--r--arch/arm/mach-at91/include/mach/at91rm9200_emac.h138
-rw-r--r--arch/arm/mach-davinci/Makefile.boot2
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c24
-rw-r--r--arch/arm/mach-exynos/Kconfig1
-rw-r--r--arch/arm/mach-exynos/Makefile1
-rw-r--r--arch/arm/mach-exynos/clock-exynos4.c4
-rw-r--r--arch/arm/mach-exynos/clock-exynos5.c21
-rw-r--r--arch/arm/mach-exynos/common.c9
-rw-r--r--arch/arm/mach-exynos/cpuidle.c3
-rw-r--r--arch/arm/mach-exynos/dev-drm.c29
-rw-r--r--arch/arm/mach-exynos/hotplug.c45
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h3
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h2
-rw-r--r--arch/arm/mach-exynos/mach-armlex4210.c1
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c4
-rw-r--r--arch/arm/mach-exynos/mach-exynos5-dt.c42
-rw-r--r--arch/arm/mach-exynos/mach-nuri.c3
-rw-r--r--arch/arm/mach-exynos/mach-origen.c3
-rw-r--r--arch/arm/mach-exynos/mach-smdk4x12.c3
-rw-r--r--arch/arm/mach-exynos/mach-smdkv310.c4
-rw-r--r--arch/arm/mach-exynos/mach-universal_c210.c3
-rw-r--r--arch/arm/mach-exynos/pm.c7
-rw-r--r--arch/arm/mach-exynos/pm_domains.c93
-rw-r--r--arch/arm/mach-imx/Kconfig18
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/clk-imx25.c119
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c1
-rw-r--r--arch/arm/mach-imx/common.h1
-rw-r--r--arch/arm/mach-imx/imx25-dt.c48
-rw-r--r--arch/arm/mach-imx/lluart.c28
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c47
-rw-r--r--arch/arm/mach-imx/mx6q.h4
-rw-r--r--arch/arm/mach-kirkwood/Kconfig5
-rw-r--r--arch/arm/mach-kirkwood/board-dnskw.c54
-rw-r--r--arch/arm/mach-kirkwood/board-dockstar.c16
-rw-r--r--arch/arm/mach-kirkwood/board-dreamplug.c15
-rw-r--r--arch/arm/mach-kirkwood/board-goflexnet.c24
-rw-r--r--arch/arm/mach-kirkwood/board-ib62x0.c35
-rw-r--r--arch/arm/mach-kirkwood/board-iconnect.c18
-rw-r--r--arch/arm/mach-kirkwood/board-iomega_ix2_200.c26
-rw-r--r--arch/arm/mach-kirkwood/board-km_kirkwood.c13
-rw-r--r--arch/arm/mach-kirkwood/board-lsxl.c28
-rw-r--r--arch/arm/mach-kirkwood/board-mplcec4.c36
-rw-r--r--arch/arm/mach-kirkwood/board-ns2.c1
-rw-r--r--arch/arm/mach-kirkwood/board-nsa310.c4
-rw-r--r--arch/arm/mach-kirkwood/board-openblocks_a6.c5
-rw-r--r--arch/arm/mach-kirkwood/board-ts219.c26
-rw-r--r--arch/arm/mach-kirkwood/board-usi_topkick.c1
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c56
-rw-r--r--arch/arm/mach-mxs/timer.c10
-rw-r--r--arch/arm/mach-netx/xc.c2
-rw-r--r--arch/arm/mach-nomadik/Kconfig2
-rw-r--r--arch/arm/mach-nomadik/board-nhk8815.c10
-rw-r--r--arch/arm/mach-nomadik/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-omap1/board-h2.c2
-rw-r--r--arch/arm/mach-omap1/board-h3.c2
-rw-r--r--arch/arm/mach-omap1/board-palmte.c2
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c2
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c2
-rw-r--r--arch/arm/mach-omap1/board-sx1.c2
-rw-r--r--arch/arm/mach-omap1/dma.c2
-rw-r--r--arch/arm/mach-omap1/io.c2
-rw-r--r--arch/arm/mach-omap1/lcd_dma.c2
-rw-r--r--arch/arm/mach-omap1/mcbsp.c2
-rw-r--r--arch/arm/mach-omap1/pm.c2
-rw-r--r--arch/arm/mach-omap2/Kconfig5
-rw-r--r--arch/arm/mach-omap2/Makefile10
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-h4.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51.c2
-rw-r--r--arch/arm/mach-omap2/cclock2420_data.c1950
-rw-r--r--arch/arm/mach-omap2/cclock2430_data.c2065
-rw-r--r--arch/arm/mach-omap2/cclock33xx_data.c961
-rw-r--r--arch/arm/mach-omap2/cclock3xxx_data.c3595
-rw-r--r--arch/arm/mach-omap2/cclock44xx_data.c1987
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_apll.c62
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_dpll.c8
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_dpllcore.c13
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_osc.c13
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_sys.c7
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c9
-rw-r--r--arch/arm/mach-omap2/clkt34xx_dpll3m2.c8
-rw-r--r--arch/arm/mach-omap2/clkt_clksel.c194
-rw-r--r--arch/arm/mach-omap2/clkt_dpll.c28
-rw-r--r--arch/arm/mach-omap2/clkt_iclk.c30
-rw-r--r--arch/arm/mach-omap2/clock.c910
-rw-r--r--arch/arm/mach-omap2/clock.h329
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c1972
-rw-r--r--arch/arm/mach-omap2/clock2430.c8
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c2071
-rw-r--r--arch/arm/mach-omap2/clock2xxx.c1
-rw-r--r--arch/arm/mach-omap2/clock2xxx.h41
-rw-r--r--arch/arm/mach-omap2/clock33xx_data.c1109
-rw-r--r--arch/arm/mach-omap2/clock34xx.c51
-rw-r--r--arch/arm/mach-omap2/clock3517.c24
-rw-r--r--arch/arm/mach-omap2/clock36xx.c22
-rw-r--r--arch/arm/mach-omap2/clock36xx.h2
-rw-r--r--arch/arm/mach-omap2/clock3xxx.c6
-rw-r--r--arch/arm/mach-omap2/clock3xxx.h6
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c3613
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c3398
-rw-r--r--arch/arm/mach-omap2/clock_common_data.c22
-rw-r--r--arch/arm/mach-omap2/clockdomain.c89
-rw-r--r--arch/arm/mach-omap2/cm-regbits-24xx.h5
-rw-r--r--arch/arm/mach-omap2/cm-regbits-34xx.h31
-rw-r--r--arch/arm/mach-omap2/cm2xxx_3xxx.h1
-rw-r--r--arch/arm/mach-omap2/control.h1
-rw-r--r--arch/arm/mach-omap2/devices.c2
-rw-r--r--arch/arm/mach-omap2/dma.c2
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c183
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c21
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c26
-rw-r--r--arch/arm/mach-omap2/gpmc-onenand.c143
-rw-r--r--arch/arm/mach-omap2/gpmc-smc91x.c43
-rw-r--r--arch/arm/mach-omap2/gpmc.c373
-rw-r--r--arch/arm/mach-omap2/gpmc.h113
-rw-r--r--arch/arm/mach-omap2/io.c18
-rw-r--r--arch/arm/mach-omap2/mcbsp.c2
-rw-r--r--arch/arm/mach-omap2/omap_device.c87
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c145
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.h12
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_33xx_data.c31
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c3
-rw-r--r--arch/arm/mach-omap2/omap_opp_data.h9
-rw-r--r--arch/arm/mach-omap2/omap_phy_internal.c32
-rw-r--r--arch/arm/mach-omap2/omap_twl.c73
-rw-r--r--arch/arm/mach-omap2/opp4xxx_data.c98
-rw-r--r--arch/arm/mach-omap2/pm.c32
-rw-r--r--arch/arm/mach-omap2/pm.h10
-rw-r--r--arch/arm/mach-omap2/pm24xx.c6
-rw-r--r--arch/arm/mach-omap2/pm34xx.c3
-rw-r--r--arch/arm/mach-omap2/pm44xx.c7
-rw-r--r--arch/arm/mach-omap2/prm-regbits-24xx.h2
-rw-r--r--arch/arm/mach-omap2/prm-regbits-34xx.h1
-rw-r--r--arch/arm/mach-omap2/prm.h11
-rw-r--r--arch/arm/mach-omap2/prm2xxx.c3
-rw-r--r--arch/arm/mach-omap2/prm2xxx.h3
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h1
-rw-r--r--arch/arm/mach-omap2/prm3xxx.c17
-rw-r--r--arch/arm/mach-omap2/prm3xxx.h1
-rw-r--r--arch/arm/mach-omap2/prm44xx.c49
-rw-r--r--arch/arm/mach-omap2/prm44xx.h1
-rw-r--r--arch/arm/mach-omap2/prm_common.c45
-rw-r--r--arch/arm/mach-omap2/scrm44xx.h2
-rw-r--r--arch/arm/mach-omap2/serial.c2
-rw-r--r--arch/arm/mach-omap2/sr_device.c13
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c181
-rw-r--r--arch/arm/mach-omap2/vc.c453
-rw-r--r--arch/arm/mach-omap2/vc.h8
-rw-r--r--arch/arm/mach-omap2/vc3xxx_data.c22
-rw-r--r--arch/arm/mach-omap2/vc44xx_data.c28
-rw-r--r--arch/arm/mach-omap2/voltage.h44
-rw-r--r--arch/arm/mach-omap2/voltagedomains3xxx_data.c5
-rw-r--r--arch/arm/mach-omap2/voltagedomains44xx_data.c25
-rw-r--r--arch/arm/mach-omap2/vp.c19
-rw-r--r--arch/arm/mach-omap2/vp.h7
-rw-r--r--arch/arm/mach-omap2/vp3xxx_data.c10
-rw-r--r--arch/arm/mach-omap2/vp44xx_data.c15
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/bast-map.h2
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/dma.h2
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/vr1000-map.h2
-rw-r--r--arch/arm/mach-s3c24xx/mach-gta02.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-h1940.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-mini2440.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx1950.c1
-rw-r--r--arch/arm/mach-s3c24xx/pm.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c1
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c1
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c1
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c1
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c1
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c1
-rw-r--r--arch/arm/mach-shmobile/Kconfig2
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c139
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c38
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c80
-rw-r--r--arch/arm/mach-shmobile/board-marzen.c186
-rw-r--r--arch/arm/mach-tegra/Kconfig53
-rw-r--r--arch/arm/mach-tegra/common.c9
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S100
-rw-r--r--arch/arm/mach-tegra/include/mach/irqs.h182
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h65
-rw-r--r--arch/arm/mach-tegra/io.c1
-rw-r--r--arch/arm/mach-tegra/iomap.h14
-rw-r--r--arch/arm/mach-tegra/irammap.h9
-rw-r--r--arch/arm/mach-tegra/pcie.c3
-rw-r--r--arch/arm/mach-tegra/timer.c78
-rw-r--r--arch/arm/mach-ux500/Kconfig2
-rw-r--r--arch/arm/mach-ux500/board-mop500-audio.c19
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c425
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c2
-rw-r--r--arch/arm/mach-ux500/board-mop500-stuib.c22
-rw-r--r--arch/arm/mach-ux500/board-mop500.c149
-rw-r--r--arch/arm/mach-ux500/board-mop500.h10
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c110
-rw-r--r--arch/arm/mach-ux500/cpu.c3
-rw-r--r--arch/arm/mach-ux500/devices-common.c1
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c4
-rw-r--r--arch/arm/mach-ux500/devices-db8500.h1
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-ux500/include/mach/msp.h2
-rw-r--r--arch/arm/mach-ux500/timer.c5
-rw-r--r--arch/arm/mach-ux500/usb.c4
-rw-r--r--arch/arm/mach-vexpress/reset.c141
-rw-r--r--arch/arm/mach-vt8500/Kconfig12
-rw-r--r--arch/arm/mach-vt8500/common.h3
-rw-r--r--arch/arm/mach-vt8500/include/mach/entry-macro.S26
-rw-r--r--arch/arm/mach-vt8500/irq.c108
-rw-r--r--arch/arm/mach-vt8500/vt8500.c1
-rw-r--r--arch/arm/mach-zynq/Kconfig13
-rw-r--r--arch/arm/mach-zynq/common.c63
-rw-r--r--arch/arm/mach-zynq/common.h4
-rw-r--r--arch/arm/mach-zynq/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-zynq/include/mach/irqs.h21
-rw-r--r--arch/arm/mach-zynq/include/mach/timex.h23
-rw-r--r--arch/arm/mach-zynq/include/mach/uart.h25
-rw-r--r--arch/arm/mach-zynq/include/mach/uncompress.h51
-rw-r--r--arch/arm/mach-zynq/include/mach/zynq_soc.h47
-rw-r--r--arch/arm/mach-zynq/timer.c298
-rw-r--r--arch/arm/net/bpf_jit_32.c29
-rw-r--r--arch/arm/net/bpf_jit_32.h2
-rw-r--r--arch/arm/plat-nomadik/Kconfig29
-rw-r--r--arch/arm/plat-nomadik/Makefile5
-rw-r--r--arch/arm/plat-omap/dma.c2
-rw-r--r--arch/arm/plat-omap/include/plat-omap/dma-omap.h377
-rw-r--r--arch/arm/plat-orion/irq.c6
-rw-r--r--arch/arm/plat-s3c24xx/dma.c2
-rw-r--r--arch/arm/plat-samsung/devs.c10
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-core.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/mfc.h11
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h2
-rw-r--r--arch/arm/plat-samsung/s5p-dev-mfc.c34
-rw-r--r--arch/arm/plat-samsung/s5p-irq-gpioint.c8
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/avr32/include/uapi/asm/socket.h1
-rw-r--r--arch/blackfin/mach-bf609/Kconfig2
-rw-r--r--arch/blackfin/mm/sram-alloc.c2
-rw-r--r--arch/cris/include/arch-v10/arch/irq.h2
-rw-r--r--arch/cris/include/arch-v32/arch/irq.h2
-rw-r--r--arch/cris/include/asm/socket.h1
-rw-r--r--arch/frv/include/uapi/asm/socket.h1
-rw-r--r--arch/frv/mm/pgalloc.c2
-rw-r--r--arch/h8300/include/asm/socket.h1
-rw-r--r--arch/ia64/include/uapi/asm/socket.h1
-rw-r--r--arch/ia64/kvm/kvm-ia64.c2
-rw-r--r--arch/m32r/include/asm/socket.h1
-rw-r--r--arch/m68k/include/uapi/asm/socket.h1
-rw-r--r--arch/m68k/math-emu/fp_log.c2
-rw-r--r--arch/mips/bcm47xx/nvram.c4
-rw-r--r--arch/mips/bcm47xx/wgt634u.c8
-rw-r--r--arch/mips/include/uapi/asm/socket.h1
-rw-r--r--arch/mips/txx9/generic/pci.c2
-rw-r--r--arch/mn10300/include/asm/io.h3
-rw-r--r--arch/mn10300/include/uapi/asm/socket.h1
-rw-r--r--arch/mn10300/kernel/asm-offsets.c2
-rw-r--r--arch/mn10300/kernel/irq.c50
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S9
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c213
-rw-r--r--arch/mn10300/kernel/mn10300-serial.h10
-rw-r--r--arch/mn10300/kernel/smp.c10
-rw-r--r--arch/mn10300/mm/fault.c33
-rw-r--r--arch/mn10300/mm/pgtable.c2
-rw-r--r--arch/mn10300/unit-asb2305/pci-iomap.c35
-rw-r--r--arch/mn10300/unit-asb2305/pci.c5
-rw-r--r--arch/openrisc/Kconfig2
-rw-r--r--arch/parisc/include/uapi/asm/socket.h1
-rw-r--r--arch/powerpc/include/asm/oprofile_impl.h2
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h3
-rw-r--r--arch/powerpc/include/asm/pte-hash64-64k.h2
-rw-r--r--arch/powerpc/include/asm/smu.h4
-rw-r--r--arch/powerpc/include/uapi/asm/socket.h1
-rw-r--r--arch/powerpc/kernel/legacy_serial.c2
-rw-r--r--arch/powerpc/kernel/of_platform.c2
-rw-r--r--arch/powerpc/kernel/signal_64.c2
-rw-r--r--arch/powerpc/mm/slice.c2
-rw-r--r--arch/powerpc/net/bpf_jit.h6
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c25
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpt.c2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c2
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c6
-rw-r--r--arch/powerpc/platforms/powermac/pic.c2
-rw-r--r--arch/s390/include/uapi/asm/socket.h1
-rw-r--r--arch/sh/boards/board-espt.c2
-rw-r--r--arch/sparc/include/uapi/asm/socket.h1
-rw-r--r--arch/sparc/net/bpf_jit_comp.c19
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/boot/.gitignore1
-rw-r--r--arch/x86/boot/compressed/eboot.c118
-rw-r--r--arch/x86/include/asm/bootparam.h1
-rw-r--r--arch/x86/include/asm/numachip/numachip.h19
-rw-r--r--arch/x86/include/asm/pci.h12
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c2
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c2
-rw-r--r--arch/x86/kernel/setup.c4
-rw-r--r--arch/x86/mm/pgtable.c2
-rw-r--r--arch/x86/net/bpf_jit_comp.c21
-rw-r--r--arch/x86/pci/Makefile1
-rw-r--r--arch/x86/pci/acpi.c46
-rw-r--r--arch/x86/pci/common.c32
-rw-r--r--arch/x86/pci/numachip.c129
-rw-r--r--arch/xtensa/include/uapi/asm/socket.h1
-rw-r--r--drivers/acpi/acpica/dsopcode.c2
-rw-r--r--drivers/acpi/pci_bind.c12
-rw-r--r--drivers/acpi/pci_irq.c17
-rw-r--r--drivers/acpi/pci_root.c165
-rw-r--r--drivers/atm/solos-pci.c88
-rw-r--r--drivers/bcma/bcma_private.h6
-rw-r--r--drivers/bcma/driver_chipcommon.c135
-rw-r--r--drivers/bcma/driver_chipcommon_nflash.c3
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c44
-rw-r--r--drivers/bcma/driver_chipcommon_sflash.c35
-rw-r--r--drivers/bcma/driver_mips.c52
-rw-r--r--drivers/bcma/driver_pci_host.c24
-rw-r--r--drivers/bcma/host_pci.c6
-rw-r--r--drivers/bcma/main.c62
-rw-r--r--drivers/bcma/sprom.c5
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c28
-rw-r--r--drivers/bluetooth/btusb.c1
-rw-r--r--drivers/char/hw_random/Kconfig2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/ppdev.c6
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-zynq.c383
-rw-r--r--drivers/clk/ux500/u8500_clk.c11
-rw-r--r--drivers/clocksource/Kconfig17
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/nomadik-mtu.c (renamed from arch/arm/plat-nomadik/timer.c)19
-rw-r--r--drivers/crypto/omap-aes.c2
-rw-r--r--drivers/crypto/omap-sham.c2
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c3
-rw-r--r--drivers/dma/ioat/dca.c23
-rw-r--r--drivers/dma/omap-dma.c2
-rw-r--r--drivers/dma/ste_dma40.c3
-rw-r--r--drivers/dma/ste_dma40_ll.c2
-rw-r--r--drivers/eisa/eisa.ids4
-rw-r--r--drivers/firewire/init_ohci1394_dma.c4
-rw-r--r--drivers/firewire/net.c15
-rw-r--r--drivers/firewire/ohci.c2
-rw-r--r--drivers/firewire/sbp2.c2
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/gpio-samsung.c68
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c2
-rw-r--r--drivers/gpu/drm/radeon/ni.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c4
-rw-r--r--drivers/gpu/drm/radeon/si.c6
-rw-r--r--drivers/hid/Kconfig11
-rw-r--r--drivers/hid/Makefile6
-rw-r--r--drivers/hid/hid-apple.c3
-rw-r--r--drivers/hid/hid-core.c61
-rw-r--r--drivers/hid/hid-icade.c259
-rw-r--r--drivers/hid/hid-ids.h19
-rw-r--r--drivers/hid/hid-input.c97
-rw-r--r--drivers/hid/hid-multitouch.c109
-rw-r--r--drivers/hid/hid-roccat-isku.c44
-rw-r--r--drivers/hid/hid-roccat-isku.h78
-rw-r--r--drivers/hid/hid-roccat-koneplus.c348
-rw-r--r--drivers/hid/hid-roccat-koneplus.h101
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c237
-rw-r--r--drivers/hid/hid-roccat-kovaplus.h16
-rw-r--r--drivers/hid/hid-roccat-lua.c227
-rw-r--r--drivers/hid/hid-roccat-lua.h29
-rw-r--r--drivers/hid/hid-roccat-pyra.c342
-rw-r--r--drivers/hid/hid-roccat-pyra.h24
-rw-r--r--drivers/hid/hid-roccat-savu.c4
-rw-r--r--drivers/hid/hid-sensor-hub.c36
-rw-r--r--drivers/hid/hidraw.c16
-rw-r--r--drivers/hid/i2c-hid/Kconfig18
-rw-r--r--drivers/hid/i2c-hid/Makefile5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c979
-rw-r--r--drivers/hid/usbhid/hid-quirks.c3
-rw-r--r--drivers/hid/usbhid/hiddev.c10
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/vexpress.c229
-rw-r--r--drivers/i2c/busses/i2c-nuc900.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c4
-rw-r--r--drivers/input/input-mt.c2
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/arizona-haptics.c255
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c2
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c2
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c2
-rw-r--r--drivers/isdn/hisax/callc.c2
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/hfc_sx.c2
-rw-r--r--drivers/isdn/hisax/isar.c2
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c5
-rw-r--r--drivers/isdn/mISDN/tei.c20
-rw-r--r--drivers/isdn/pcbit/layer2.c2
-rw-r--r--drivers/md/md.c2
-rw-r--r--drivers/md/persistent-data/dm-block-manager.c4
-rw-r--r--drivers/md/persistent-data/dm-btree.h2
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.c2
-rw-r--r--drivers/media/platform/mx2_emmaprp.c2
-rw-r--r--drivers/media/platform/omap/omap_vout.c2
-rw-r--r--drivers/media/platform/omap/omap_vout_vrfb.c2
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h2
-rw-r--r--drivers/media/platform/soc_camera/omap1_camera.c2
-rw-r--r--drivers/message/i2o/README.ioctl12
-rw-r--r--drivers/message/i2o/i2o_block.c2
-rw-r--r--drivers/message/i2o/i2o_config.c2
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/ab8500-core.c13
-rw-r--r--drivers/mfd/arizona-core.c2
-rw-r--r--drivers/mfd/db8500-prcmu.c12
-rw-r--r--drivers/mfd/max8997.c73
-rw-r--r--drivers/mfd/tps6586x.c76
-rw-r--r--drivers/mfd/wm5102-tables.c3
-rw-r--r--drivers/mfd/wm8994-core.c35
-rw-r--r--drivers/misc/atmel-ssc.c135
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mtd/maps/plat-ram.c2
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/omap2.c1
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/onenand/omap2.c2
-rw-r--r--drivers/net/arcnet/com20020-pci.c6
-rw-r--r--drivers/net/bonding/bond_alb.c197
-rw-r--r--drivers/net/bonding/bond_alb.h28
-rw-r--r--drivers/net/bonding/bond_debugfs.c5
-rw-r--r--drivers/net/bonding/bond_main.c19
-rw-r--r--drivers/net/bonding/bonding.h15
-rw-r--r--drivers/net/can/Kconfig9
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/at91_can.c9
-rw-r--r--drivers/net/can/bfin_can.c7
-rw-r--r--drivers/net/can/c_can/c_can.c12
-rw-r--r--drivers/net/can/c_can/c_can.h3
-rw-r--r--drivers/net/can/c_can/c_can_pci.c8
-rw-r--r--drivers/net/can/c_can/c_can_platform.c36
-rw-r--r--drivers/net/can/cc770/cc770_isa.c18
-rw-r--r--drivers/net/can/cc770/cc770_platform.c18
-rw-r--r--drivers/net/can/dev.c3
-rw-r--r--drivers/net/can/flexcan.c12
-rw-r--r--drivers/net/can/grcan.c1756
-rw-r--r--drivers/net/can/janz-ican3.c28
-rw-r--r--drivers/net/can/mcp251x.c6
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c37
-rw-r--r--drivers/net/can/mscan/mscan.c8
-rw-r--r--drivers/net/can/mscan/mscan.h1
-rw-r--r--drivers/net/can/pch_can.c6
-rw-r--r--drivers/net/can/sja1000/Kconfig3
-rw-r--r--drivers/net/can/sja1000/ems_pci.c4
-rw-r--r--drivers/net/can/sja1000/ems_pcmcia.c5
-rw-r--r--drivers/net/can/sja1000/kvaser_pci.c8
-rw-r--r--drivers/net/can/sja1000/peak_pci.c7
-rw-r--r--drivers/net/can/sja1000/peak_pcmcia.c2
-rw-r--r--drivers/net/can/sja1000/plx_pci.c39
-rw-r--r--drivers/net/can/sja1000/sja1000.c8
-rw-r--r--drivers/net/can/sja1000/sja1000.h1
-rw-r--r--drivers/net/can/sja1000/sja1000_isa.c16
-rw-r--r--drivers/net/can/sja1000/sja1000_of_platform.c14
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c1
-rw-r--r--drivers/net/can/sja1000/tscan1.c8
-rw-r--r--drivers/net/can/softing/softing_cs.c11
-rw-r--r--drivers/net/can/softing/softing_main.c14
-rw-r--r--drivers/net/can/ti_hecc.c5
-rw-r--r--drivers/net/can/usb/Kconfig29
-rw-r--r--drivers/net/can/usb/Makefile1
-rw-r--r--drivers/net/can/usb/ems_usb.c7
-rw-r--r--drivers/net/can/usb/esd_usb2.c45
-rw-r--r--drivers/net/can/usb/kvaser_usb.c1627
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_core.c5
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_core.h1
-rw-r--r--drivers/net/dsa/Kconfig5
-rw-r--r--drivers/net/ethernet/3com/3c509.c29
-rw-r--r--drivers/net/ethernet/3com/3c59x.c21
-rw-r--r--drivers/net/ethernet/3com/Kconfig2
-rw-r--r--drivers/net/ethernet/3com/typhoon.c10
-rw-r--r--drivers/net/ethernet/8390/ax88796.c18
-rw-r--r--drivers/net/ethernet/8390/etherh.c14
-rw-r--r--drivers/net/ethernet/8390/hydra.c18
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c12
-rw-r--r--drivers/net/ethernet/8390/ne3210.c4
-rw-r--r--drivers/net/ethernet/8390/zorro8390.c17
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c12
-rw-r--r--drivers/net/ethernet/adi/Kconfig2
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c271
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.h13
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c6
-rw-r--r--drivers/net/ethernet/alteon/acenic.c31
-rw-r--r--drivers/net/ethernet/amd/a2065.c16
-rw-r--r--drivers/net/ethernet/amd/am79c961a.c2
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c8
-rw-r--r--drivers/net/ethernet/amd/ariadne.c10
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c6
-rw-r--r--drivers/net/ethernet/amd/declance.c8
-rw-r--r--drivers/net/ethernet/amd/depca.c10
-rw-r--r--drivers/net/ethernet/amd/hplance.c17
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c10
-rw-r--r--drivers/net/ethernet/amd/sunlance.c12
-rw-r--r--drivers/net/ethernet/apple/bmac.c4
-rw-r--r--drivers/net/ethernet/apple/mace.c4
-rw-r--r--drivers/net/ethernet/apple/macmace.c6
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c15
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c11
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_param.c7
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c17
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c17
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig1
-rw-r--r--drivers/net/ethernet/broadcom/b44.c10
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c1022
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h134
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h141
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c528
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h91
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c41
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c29
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h5
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h54
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h29
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c991
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h18
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c1186
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h59
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c61
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h3
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c189
-rw-r--r--drivers/net/ethernet/broadcom/cnic.h30
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h7
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c726
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h68
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c4
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi_enet.h1
-rw-r--r--drivers/net/ethernet/brocade/bna/bna.h2
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_hw_defs.h3
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_tx_rx.c138
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_types.h9
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c943
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h66
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c1
-rw-r--r--drivers/net/ethernet/brocade/bna/cna.h4
-rw-r--r--drivers/net/ethernet/cadence/Kconfig9
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c1283
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.h112
-rw-r--r--drivers/net/ethernet/cadence/macb.c564
-rw-r--r--drivers/net/ethernet/cadence/macb.h67
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c59
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cxgb2.c7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/sge.c17
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/subr.c13
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/tp.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/common.h7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/t3_hw.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c25
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c22
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c7
-rw-r--r--drivers/net/ethernet/cisco/Kconfig2
-rw-r--r--drivers/net/ethernet/cisco/enic/Kconfig2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c7
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c18
-rw-r--r--drivers/net/ethernet/dec/ewrk3.c3
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c16
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c18
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c11
-rw-r--r--drivers/net/ethernet/dec/tulip/eeprom.c10
-rw-r--r--drivers/net/ethernet/dec/tulip/media.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c12
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c12
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c9
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c6
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c24
-rw-r--r--drivers/net/ethernet/dlink/sundance.c95
-rw-r--r--drivers/net/ethernet/dnet.c11
-rw-r--r--drivers/net/ethernet/emulex/Kconfig2
-rw-r--r--drivers/net/ethernet/emulex/benet/Kconfig2
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h51
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c409
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h177
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c80
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h20
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c849
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.c5
-rw-r--r--drivers/net/ethernet/ethoc.c8
-rw-r--r--drivers/net/ethernet/fealnx.c12
-rw-r--r--drivers/net/ethernet/freescale/Kconfig9
-rw-r--r--drivers/net/ethernet/freescale/Makefile1
-rw-r--r--drivers/net/ethernet/freescale/fec.c171
-rw-r--r--drivers/net/ethernet/freescale/fec.h119
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c383
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c5
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c14
-rw-r--r--drivers/net/ethernet/freescale/xgmac_mdio.c4
-rw-r--r--drivers/net/ethernet/hp/hp100.c18
-rw-r--r--drivers/net/ethernet/i825xx/ether1.c20
-rw-r--r--drivers/net/ethernet/i825xx/lasi_82596.c8
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c2
-rw-r--r--drivers/net/ethernet/i825xx/sni_82596.c8
-rw-r--r--drivers/net/ethernet/ibm/Kconfig5
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c16
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c24
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c13
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.c6
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c7
-rw-r--r--drivers/net/ethernet/icplus/ipg.c7
-rw-r--r--drivers/net/ethernet/intel/Kconfig30
-rw-r--r--drivers/net/ethernet/intel/e100.c7
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c17
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c13
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_param.c14
-rw-r--r--drivers/net/ethernet/intel/e1000e/80003es2lan.c66
-rw-r--r--drivers/net/ethernet/intel/e1000e/82571.c115
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h27
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h17
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c69
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h6
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c243
-rw-r--r--drivers/net/ethernet/intel/e1000e/mac.c135
-rw-r--r--drivers/net/ethernet/intel/e1000e/manage.c9
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c331
-rw-r--r--drivers/net/ethernet/intel/e1000e/nvm.c15
-rw-r--r--drivers/net/ethernet/intel/e1000e/param.c60
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.c141
-rw-r--r--drivers/net/ethernet/intel/igb/Makefile4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c77
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h3
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h22
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.c369
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.h17
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c128
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.c99
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.h16
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.c49
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h112
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c406
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c1572
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c102
-rw-r--r--drivers/net/ethernet/intel/igbvf/defines.h1
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h2
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c41
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c10
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_param.c6
-rw-r--r--drivers/net/ethernet/intel/ixgbe/Makefile3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h15
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c160
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c100
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c115
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c109
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c22
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c418
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h31
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c164
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c470
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h12
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/defines.h7
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h16
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c403
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.h10
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c61
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h2
-rw-r--r--drivers/net/ethernet/jme.c6
-rw-r--r--drivers/net/ethernet/lantiq_etop.c4
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c7
-rw-r--r--drivers/net/ethernet/marvell/skge.c9
-rw-r--r--drivers/net/ethernet/marvell/sky2.c35
-rw-r--r--drivers/net/ethernet/mellanox/Kconfig2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Kconfig3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c155
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c28
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h27
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.c13
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c6
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c6
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c6
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c20
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c6
-rw-r--r--drivers/net/ethernet/myricom/Kconfig1
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c285
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h2
-rw-r--r--drivers/net/ethernet/natsemi/ibmlana.c4
-rw-r--r--drivers/net/ethernet/natsemi/jazzsonic.c8
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c21
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c13
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c8
-rw-r--r--drivers/net/ethernet/natsemi/xtsonic.c6
-rw-r--r--drivers/net/ethernet/neterion/Kconfig2
-rw-r--r--drivers/net/ethernet/neterion/s2io.c11
-rw-r--r--drivers/net/ethernet/neterion/s2io.h5
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.c6
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.h6
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c27
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c6
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c6
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c6
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c6
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/Kconfig17
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h2
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c14
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c12
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c12
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c6
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c93
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c10
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c24
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/Makefile3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h521
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c114
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c73
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h56
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c749
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c852
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c1309
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c1992
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c629
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c960
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_dbg.c16
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c12
-rw-r--r--drivers/net/ethernet/rdc/r6040.c9
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c75
-rw-r--r--drivers/net/ethernet/realtek/8139too.c14
-rw-r--r--drivers/net/ethernet/realtek/atp.c58
-rw-r--r--drivers/net/ethernet/realtek/atp.h2
-rw-r--r--drivers/net/ethernet/realtek/r8169.c170
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c2
-rw-r--r--drivers/net/ethernet/s6gmac.c6
-rw-r--r--drivers/net/ethernet/seeq/ether3.c22
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c2
-rw-r--r--drivers/net/ethernet/sfc/Kconfig10
-rw-r--r--drivers/net/ethernet/sfc/Makefile3
-rw-r--r--drivers/net/ethernet/sfc/efx.c16
-rw-r--r--drivers/net/ethernet/sfc/efx.h13
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c25
-rw-r--r--drivers/net/ethernet/sfc/falcon.c2
-rw-r--r--drivers/net/ethernet/sfc/io.h43
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c23
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h5
-rw-r--r--drivers/net/ethernet/sfc/nic.c81
-rw-r--r--drivers/net/ethernet/sfc/nic.h28
-rw-r--r--drivers/net/ethernet/sfc/rx.c6
-rw-r--r--drivers/net/ethernet/sfc/selftest.c4
-rw-r--r--drivers/net/ethernet/sfc/siena.c17
-rw-r--r--drivers/net/ethernet/sfc/siena_sriov.c8
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c11
-rw-r--r--drivers/net/ethernet/sgi/meth.c2
-rw-r--r--drivers/net/ethernet/silan/sc92031.c7
-rw-r--r--drivers/net/ethernet/sis/sis190.c27
-rw-r--r--drivers/net/ethernet/sis/sis900.c29
-rw-r--r--drivers/net/ethernet/smsc/epic100.c13
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c20
-rw-r--r--drivers/net/ethernet/smsc/smc911x.h16
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c22
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h20
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c32
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig25
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h39
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c100
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c261
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c134
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h46
-rw-r--r--drivers/net/ethernet/sun/cassini.c13
-rw-r--r--drivers/net/ethernet/sun/niu.c121
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c10
-rw-r--r--drivers/net/ethernet/sun/sungem.c7
-rw-r--r--drivers/net/ethernet/sun/sunhme.c20
-rw-r--r--drivers/net/ethernet/sun/sunqe.c12
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c15
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c6
-rw-r--r--drivers/net/ethernet/ti/Kconfig9
-rw-r--r--drivers/net/ethernet/ti/Makefile2
-rw-r--r--drivers/net/ethernet/ti/cpmac.c10
-rw-r--r--drivers/net/ethernet/ti/cpsw.c635
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c31
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.h1
-rw-r--r--drivers/net/ethernet/ti/cpts.c427
-rw-r--r--drivers/net/ethernet/ti/cpts.h146
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c6
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c8
-rw-r--r--drivers/net/ethernet/ti/tlan.c11
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.c22
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c10
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c6
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c18
-rw-r--r--drivers/net/ethernet/via/via-rhine.c13
-rw-r--r--drivers/net/ethernet/via/via-velocity.c28
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c10
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c10
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c8
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c8
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c8
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c4
-rw-r--r--drivers/net/fddi/defxx.c46
-rw-r--r--drivers/net/fddi/skfp/skfddi.c4
-rw-r--r--drivers/net/hippi/rrunner.c11
-rw-r--r--drivers/net/hyperv/rndis_filter.c10
-rw-r--r--drivers/net/ieee802154/at86rf230.c6
-rw-r--r--drivers/net/ieee802154/fakehard.c6
-rw-r--r--drivers/net/ieee802154/fakelb.c6
-rw-r--r--drivers/net/ieee802154/mrf24j40.c6
-rw-r--r--drivers/net/irda/au1k_ir.c8
-rw-r--r--drivers/net/irda/bfin_sir.c8
-rw-r--r--drivers/net/irda/ep7211-sir.c73
-rw-r--r--drivers/net/irda/sh_irda.c10
-rw-r--r--drivers/net/irda/sh_sir.c6
-rw-r--r--drivers/net/irda/smsc-ircc2.c6
-rw-r--r--drivers/net/irda/via-ircc.c15
-rw-r--r--drivers/net/irda/vlsi_ir.c6
-rw-r--r--drivers/net/netconsole.c6
-rw-r--r--drivers/net/phy/davicom.c6
-rw-r--r--drivers/net/phy/dp83640.c78
-rw-r--r--drivers/net/phy/mdio-gpio.c14
-rw-r--r--drivers/net/phy/mdio-mux-gpio.c6
-rw-r--r--drivers/net/phy/mdio-mux-mmioreg.c6
-rw-r--r--drivers/net/phy/mdio-octeon.c6
-rw-r--r--drivers/net/phy/mdio_bus.c14
-rw-r--r--drivers/net/phy/micrel.c44
-rw-r--r--drivers/net/phy/smsc.c95
-rw-r--r--drivers/net/phy/spi_ks8995.c6
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/sungem_phy.c8
-rw-r--r--drivers/net/tun.c875
-rw-r--r--drivers/net/usb/Kconfig22
-rw-r--r--drivers/net/usb/Makefile1
-rw-r--r--drivers/net/usb/asix_common.c117
-rw-r--r--drivers/net/usb/asix_devices.c19
-rw-r--r--drivers/net/usb/cdc_mbim.c412
-rw-r--r--drivers/net/usb/cdc_ncm.c645
-rw-r--r--drivers/net/usb/dm9601.c107
-rw-r--r--drivers/net/usb/int51x1.c52
-rw-r--r--drivers/net/usb/mcs7830.c85
-rw-r--r--drivers/net/usb/net1080.c110
-rw-r--r--drivers/net/usb/plusb.c11
-rw-r--r--drivers/net/usb/sierra_net.c47
-rw-r--r--drivers/net/usb/smsc75xx.c1406
-rw-r--r--drivers/net/usb/smsc95xx.c1088
-rw-r--r--drivers/net/usb/smsc95xx.h25
-rw-r--r--drivers/net/usb/usbnet.c196
-rw-r--r--drivers/net/veth.c3
-rw-r--r--drivers/net/virtio_net.c742
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c42
-rw-r--r--drivers/net/vxlan.c286
-rw-r--r--drivers/net/wan/Makefile4
-rw-r--r--drivers/net/wan/dscc4.c7
-rw-r--r--drivers/net/wan/farsync.c10
-rw-r--r--drivers/net/wan/hd64570.c5
-rw-r--r--drivers/net/wan/hd64572.c5
-rw-r--r--drivers/net/wan/ixp4xx_hss.c4
-rw-r--r--drivers/net/wan/lmc/lmc_main.c7
-rw-r--r--drivers/net/wan/pc300too.c4
-rw-r--r--drivers/net/wan/pci200syn.c4
-rw-r--r--drivers/net/wan/wanxl.c4
-rw-r--r--drivers/net/wan/wanxlfw.S1
-rw-r--r--drivers/net/wimax/i2400m/debugfs.c1
-rw-r--r--drivers/net/wireless/adm8211.c6
-rw-r--r--drivers/net/wireless/airo.c8
-rw-r--r--drivers/net/wireless/at76c50x-usb.c85
-rw-r--r--drivers/net/wireless/ath/Kconfig8
-rw-r--r--drivers/net/wireless/ath/Makefile1
-rw-r--r--drivers/net/wireless/ath/ar5523/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ar5523/Makefile1
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c1798
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.h152
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523_hw.h431
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c15
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c31
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c7
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c6
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c6
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig9
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c410
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c21
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h69
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.c12
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_mbox.c13
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c14
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c92
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c55
-rw-r--r--drivers/net/wireless/ath/ath6kl/recovery.c160
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c27
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c47
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c32
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c284
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h78
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h172
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c81
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c86
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c71
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c87
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h76
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9340_initvals.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h338
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h44
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c63
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c439
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h33
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c29
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c136
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c44
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c67
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c39
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c203
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c211
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.h36
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c35
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c53
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h16
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/wow.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c21
-rw-r--r--drivers/net/wireless/ath/carl9170/Kconfig1
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c5
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c21
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c53
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c7
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c7
-rw-r--r--drivers/net/wireless/ath/hw.c20
-rw-r--r--drivers/net/wireless/atmel.c2
-rw-r--r--drivers/net/wireless/atmel_pci.c6
-rw-r--r--drivers/net/wireless/b43/dma.c7
-rw-r--r--drivers/net/wireless/b43/main.c14
-rw-r--r--drivers/net/wireless/b43/pcmcia.c6
-rw-r--r--drivers/net/wireless/b43/pio.c4
-rw-r--r--drivers/net/wireless/b43/sdio.c6
-rw-r--r--drivers/net/wireless/b43/xmit.c2
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h5
-rw-r--r--drivers/net/wireless/b43legacy/main.c37
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c2
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig15
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c58
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c182
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h256
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h98
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c126
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c893
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h46
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c716
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h15
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c579
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.c447
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.h215
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil.c344
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil.h39
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c14
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c404
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.h18
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c2944
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h328
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.c723
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.h29
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/antsel.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h175
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c10
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/debug.c156
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/debug.h75
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.c345
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.h11
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c157
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c1261
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.h48
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c471
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c64
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pub.h42
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/stf.c8
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/types.h3
-rw-r--r--drivers/net/wireless/brcm80211/include/defs.h11
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c9
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.h2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c52
-rw-r--r--drivers/net/wireless/ipw2x00/libipw.h2
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_geo.c3
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c6
-rw-r--r--drivers/net/wireless/iwlegacy/3945-mac.c4
-rw-r--r--drivers/net/wireless/iwlegacy/3945.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c8
-rw-r--r--drivers/net/wireless/iwlegacy/4965.h4
-rw-r--r--drivers/net/wireless/iwlegacy/common.c10
-rw-r--r--drivers/net/wireless/iwlegacy/common.h17
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig9
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/calib.c14
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/commands.h7
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c14
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h3
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c8
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c49
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c28
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c78
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c44
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rx.c6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/scan.c13
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/sta.c12
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c76
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/ucode.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h129
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c86
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h57
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/1000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/2000.c16
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/5000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/6000.c28
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c16
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h117
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c413
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c1072
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c1233
-rw-r--r--drivers/net/wireless/libertas/cfg.c33
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c39
-rw-r--r--drivers/net/wireless/libertas/if_spi.c6
-rw-r--r--drivers/net/wireless/libertas/mesh.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c585
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c8
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c8
-rw-r--r--drivers/net/wireless/mwifiex/Kconfig1
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c89
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c24
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c10
-rw-r--r--drivers/net/wireless/mwifiex/fw.h2
-rw-r--r--drivers/net/wireless/mwifiex/init.c39
-rw-r--r--drivers/net/wireless/mwifiex/join.c6
-rw-r--r--drivers/net/wireless/mwifiex/main.c94
-rw-r--r--drivers/net/wireless/mwifiex/main.h19
-rw-r--r--drivers/net/wireless/mwifiex/scan.c55
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c39
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h1
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c4
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c10
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c49
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c26
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c38
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c11
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c7
-rw-r--r--drivers/net/wireless/mwifiex/uap_txrx.c17
-rw-r--r--drivers/net/wireless/mwifiex/usb.c4
-rw-r--r--drivers/net/wireless/mwifiex/util.c19
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c12
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h2
-rw-r--r--drivers/net/wireless/mwl8k.c71
-rw-r--r--drivers/net/wireless/orinoco/cfg.c11
-rw-r--r--drivers/net/wireless/orinoco/main.h2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c9
-rw-r--r--drivers/net/wireless/p54/eeprom.c5
-rw-r--r--drivers/net/wireless/p54/p54pci.c19
-rw-r--r--drivers/net/wireless/p54/p54spi.c6
-rw-r--r--drivers/net/wireless/p54/p54usb.c6
-rw-r--r--drivers/net/wireless/p54/txrx.c6
-rw-r--r--drivers/net/wireless/rndis_wlan.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c245
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c36
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c8
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c8
-rw-r--r--drivers/net/wireless/rtlwifi/Kconfig11
-rw-r--r--drivers/net/wireless/rtlwifi/Makefile4
-rw-r--r--drivers/net/wireless/rtlwifi/base.c24
-rw-r--r--drivers/net/wireless/rtlwifi/base.h2
-rw-r--r--drivers/net/wireless/rtlwifi/cam.c9
-rw-r--r--drivers/net/wireless/rtlwifi/core.c5
-rw-r--r--drivers/net/wireless/rtlwifi/debug.h2
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c24
-rw-r--r--drivers/net/wireless/rtlwifi/pci.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rc.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c227
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c88
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/def.h3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/dm.c30
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c93
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/phy.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/rf.c23
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c15
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c48
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/dm.c30
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c16
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c25
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/rf.c22
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/dm.c95
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/phy.c65
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/rf.c18
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/sw.c11
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.c41
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/def.h3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/dm.c97
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c9
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/phy.c64
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/rf.c11
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c20
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c23
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/Makefile22
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/btc.h41
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/def.h163
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/dm.c920
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/dm.h149
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/fw.c745
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/fw.h101
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c542
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h160
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c1786
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h151
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hw.c2380
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hw.h73
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/led.c151
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/led.h39
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/phy.c2044
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/phy.h224
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c109
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h322
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c129
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h98
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/reg.h2097
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/rf.c505
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/rf.h43
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/sw.c380
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/sw.h37
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/table.c738
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/table.h50
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/trx.c670
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/trx.h725
-rw-r--r--drivers/net/wireless/rtlwifi/stats.c268
-rw-r--r--drivers/net/wireless/rtlwifi/stats.h46
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c2
-rw-r--r--drivers/net/wireless/rtlwifi/usb.h2
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h161
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/rx.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/sdio.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/spi.c6
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c6
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c15
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c2
-rw-r--r--drivers/net/xen-netfront.c10
-rw-r--r--drivers/nfc/Makefile2
-rw-r--r--drivers/nfc/pn533.c18
-rw-r--r--drivers/nfc/pn544/Makefile7
-rw-r--r--drivers/nfc/pn544/i2c.c500
-rw-r--r--drivers/nfc/pn544/pn544.c (renamed from drivers/nfc/pn544_hci.c)679
-rw-r--r--drivers/nfc/pn544/pn544.h32
-rw-r--r--drivers/pci/bus.c5
-rw-r--r--drivers/pci/ioapic.c2
-rw-r--r--drivers/pci/iov.c87
-rw-r--r--drivers/pci/irq.c10
-rw-r--r--drivers/pci/pci-driver.c73
-rw-r--r--drivers/pci/pci-stub.c2
-rw-r--r--drivers/pci/pci-sysfs.c172
-rw-r--r--drivers/pci/pci.c48
-rw-r--r--drivers/pci/pci.h8
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h5
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c22
-rw-r--r--drivers/pci/pcie/aspm.c18
-rw-r--r--drivers/pci/pcie/portdrv_core.c3
-rw-r--r--drivers/pci/probe.c42
-rw-r--r--drivers/pci/quirks.c39
-rw-r--r--drivers/pci/remove.c36
-rw-r--r--drivers/pci/rom.c11
-rw-r--r--drivers/pci/setup-bus.c22
-rw-r--r--drivers/pci/xen-pcifront.c5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-dove.c22
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-kirkwood.c568
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c3
-rw-r--r--drivers/power/Kconfig3
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/avs/smartreflex.c54
-rw-r--r--drivers/power/reset/Kconfig15
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/gpio-poweroff.c129
-rw-r--r--drivers/pps/Kconfig1
-rw-r--r--drivers/ptp/Kconfig19
-rw-r--r--drivers/ptp/ptp_chardev.c61
-rw-r--r--drivers/regulator/88pm8607.c6
-rw-r--r--drivers/regulator/Kconfig54
-rw-r--r--drivers/regulator/Makefile6
-rw-r--r--drivers/regulator/aat2870-regulator.c4
-rw-r--r--drivers/regulator/ab3100.c6
-rw-r--r--drivers/regulator/ab8500.c12
-rw-r--r--drivers/regulator/ad5398.c6
-rw-r--r--drivers/regulator/anatop-regulator.c34
-rw-r--r--drivers/regulator/arizona-ldo1.c136
-rw-r--r--drivers/regulator/arizona-micsupp.c8
-rw-r--r--drivers/regulator/as3711-regulator.c369
-rw-r--r--drivers/regulator/core.c42
-rw-r--r--drivers/regulator/da903x.c6
-rw-r--r--drivers/regulator/da9052-regulator.c16
-rw-r--r--drivers/regulator/da9055-regulator.c641
-rw-r--r--drivers/regulator/db8500-prcmu.c6
-rw-r--r--drivers/regulator/dbx500-prcmu.c4
-rw-r--r--drivers/regulator/dummy.c2
-rw-r--r--drivers/regulator/fan53555.c6
-rw-r--r--drivers/regulator/fixed.c6
-rw-r--r--drivers/regulator/gpio-regulator.c112
-rw-r--r--drivers/regulator/isl6271a-regulator.c6
-rw-r--r--drivers/regulator/lp3971.c8
-rw-r--r--drivers/regulator/lp3972.c8
-rw-r--r--drivers/regulator/lp872x.c4
-rw-r--r--drivers/regulator/lp8788-buck.c24
-rw-r--r--drivers/regulator/lp8788-ldo.c25
-rw-r--r--drivers/regulator/max1586.c50
-rw-r--r--drivers/regulator/max77686.c170
-rw-r--r--drivers/regulator/max8649.c6
-rw-r--r--drivers/regulator/max8660.c6
-rw-r--r--drivers/regulator/max8907-regulator.c6
-rw-r--r--drivers/regulator/max8925-regulator.c78
-rw-r--r--drivers/regulator/max8952.c6
-rw-r--r--drivers/regulator/max8973-regulator.c505
-rw-r--r--drivers/regulator/max8997.c187
-rw-r--r--drivers/regulator/max8998.c6
-rw-r--r--drivers/regulator/mc13783-regulator.c6
-rw-r--r--drivers/regulator/mc13892-regulator.c6
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c4
-rw-r--r--drivers/regulator/palmas-regulator.c166
-rw-r--r--drivers/regulator/pcap-regulator.c6
-rw-r--r--drivers/regulator/pcf50633-regulator.c182
-rw-r--r--drivers/regulator/rc5t583-regulator.c6
-rw-r--r--drivers/regulator/s2mps11.c16
-rw-r--r--drivers/regulator/s5m8767.c46
-rw-r--r--drivers/regulator/tps51632-regulator.c342
-rw-r--r--drivers/regulator/tps6105x-regulator.c6
-rw-r--r--drivers/regulator/tps62360-regulator.c8
-rw-r--r--drivers/regulator/tps65023-regulator.c6
-rw-r--r--drivers/regulator/tps6507x-regulator.c6
-rw-r--r--drivers/regulator/tps65090-regulator.c254
-rw-r--r--drivers/regulator/tps65217-regulator.c6
-rw-r--r--drivers/regulator/tps6524x-regulator.c4
-rw-r--r--drivers/regulator/tps6586x-regulator.c189
-rw-r--r--drivers/regulator/tps65910-regulator.c13
-rw-r--r--drivers/regulator/tps65912-regulator.c6
-rw-r--r--drivers/regulator/tps80031-regulator.c788
-rw-r--r--drivers/regulator/twl-regulator.c6
-rw-r--r--drivers/regulator/vexpress.c147
-rw-r--r--drivers/regulator/virtual.c6
-rw-r--r--drivers/regulator/wm831x-dcdc.c31
-rw-r--r--drivers/regulator/wm831x-isink.c6
-rw-r--r--drivers/regulator/wm831x-ldo.c18
-rw-r--r--drivers/regulator/wm8400-regulator.c6
-rw-r--r--drivers/regulator/wm8994-regulator.c6
-rw-r--r--drivers/remoteproc/remoteproc_elf_loader.c4
-rw-r--r--drivers/rtc/rtc-isl1208.c2
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c2
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/ctcm_main.c2
-rw-r--r--drivers/s390/net/ctcm_mpc.c3
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c49
-rw-r--r--drivers/s390/net/qeth_l2_main.c4
-rw-r--r--drivers/s390/net/qeth_l3_main.c8
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c2
-rw-r--r--drivers/scsi/libsas/sas_expander.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c12
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c2
-rw-r--r--drivers/ssb/b43_pci_bridge.c1
-rw-r--r--drivers/ssb/driver_chipcommon.c100
-rw-r--r--drivers/ssb/driver_chipcommon_pmu.c30
-rw-r--r--drivers/ssb/driver_extif.c24
-rw-r--r--drivers/ssb/driver_mipscore.c30
-rw-r--r--drivers/ssb/embedded.c35
-rw-r--r--drivers/ssb/main.c11
-rw-r--r--drivers/ssb/ssb_private.h31
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c2
-rw-r--r--drivers/staging/tidspbridge/rmgr/node.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c2
-rw-r--r--drivers/thermal/Kconfig2
-rw-r--r--drivers/tty/hvc/hvc_opal.c2
-rw-r--r--drivers/tty/hvc/hvc_vio.c2
-rw-r--r--drivers/tty/ipwireless/setup_protocol.h2
-rw-r--r--drivers/tty/serial/8250/Kconfig2
-rw-r--r--drivers/tty/serial/bfin_uart.c2
-rw-r--r--drivers/tty/serial/icom.c2
-rw-r--r--drivers/usb/core/driver.c2
-rw-r--r--drivers/usb/gadget/at91_udc.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c2
-rw-r--r--drivers/usb/host/ehci-orion.c38
-rw-r--r--drivers/usb/musb/tusb6010_omap.c2
-rw-r--r--drivers/usb/storage/realtek_cr.c2
-rw-r--r--drivers/vhost/net.c147
-rw-r--r--drivers/vhost/tcm_vhost.c11
-rw-r--r--drivers/vhost/vhost.c59
-rw-r--r--drivers/vhost/vhost.h14
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/sossi.c2
-rw-r--r--drivers/watchdog/at91sam9_wdt.c11
-rw-r--r--drivers/watchdog/booke_wdt.c2
-rw-r--r--drivers/watchdog/omap_wdt.c2
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c2
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c2
-rw-r--r--fs/btrfs/extent_map.c3
-rw-r--r--fs/btrfs/ordered-data.h2
-rw-r--r--fs/btrfs/volumes.c2
-rw-r--r--fs/cifs/README2
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/fhandle.c4
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/jbd/transaction.c2
-rw-r--r--fs/jbd2/transaction.c2
-rw-r--r--fs/logfs/inode.c2
-rw-r--r--fs/ncpfs/mmap.c2
-rw-r--r--fs/notify/fanotify/Kconfig2
-rw-r--r--fs/notify/notification.c2
-rw-r--r--fs/proc/proc_sysctl.c9
-rw-r--r--include/acpi/acpi_drivers.h4
-rw-r--r--include/linux/ath9k_platform.h2
-rw-r--r--include/linux/atmdev.h2
-rw-r--r--include/linux/atmel-ssc.h6
-rw-r--r--include/linux/bcm47xx_wdt.h19
-rw-r--r--include/linux/bcma/bcma.h7
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h12
-rw-r--r--include/linux/bcma/bcma_driver_mips.h3
-rw-r--r--include/linux/bcma/bcma_regs.h5
-rw-r--r--include/linux/clk/zynq.h (renamed from arch/arm/mach-vt8500/include/mach/irqs.h)12
-rw-r--r--include/linux/dlm.h2
-rw-r--r--include/linux/efi.h71
-rw-r--r--include/linux/etherdevice.h20
-rw-r--r--include/linux/filter.h3
-rw-r--r--include/linux/hash.h2
-rw-r--r--include/linux/hdlc/Kbuild1
-rw-r--r--include/linux/hid-sensor-ids.h1
-rw-r--r--include/linux/hid.h6
-rw-r--r--include/linux/i2c/i2c-hid.h35
-rw-r--r--include/linux/ieee80211.h188
-rw-r--r--include/linux/if_tunnel.h17
-rw-r--r--include/linux/inetdevice.h3
-rw-r--r--include/linux/input/mt.h6
-rw-r--r--include/linux/ip.h5
-rw-r--r--include/linux/ipmi_smi.h2
-rw-r--r--include/linux/ipv6.h38
-rw-r--r--include/linux/ktime.h19
-rw-r--r--include/linux/lru_cache.h4
-rw-r--r--include/linux/mfd/arizona/core.h4
-rw-r--r--include/linux/mfd/arizona/pdata.h6
-rw-r--r--include/linux/mfd/arizona/registers.h16
-rw-r--r--include/linux/mfd/da9055/pdata.h27
-rw-r--r--include/linux/mfd/max8997-private.h1
-rw-r--r--include/linux/mfd/max8997.h1
-rw-r--r--include/linux/mfd/tps65090.h35
-rw-r--r--include/linux/mfd/tps6586x.h3
-rw-r--r--include/linux/mfd/wm8994/core.h4
-rw-r--r--include/linux/mfd/wm8994/pdata.h5
-rw-r--r--include/linux/micrel_phy.h1
-rw-r--r--include/linux/netdevice.h46
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h9
-rw-r--r--include/linux/nfc/pn544.h104
-rw-r--r--include/linux/omap-dma.h366
-rw-r--r--include/linux/openvswitch.h1
-rw-r--r--include/linux/pci.h36
-rw-r--r--include/linux/platform_data/asoc-s3c.h6
-rw-r--r--include/linux/platform_data/clocksource-nomadik-mtu.h (renamed from arch/arm/plat-nomadik/include/plat/mtu.h)2
-rw-r--r--include/linux/platform_data/cpsw.h23
-rw-r--r--include/linux/platform_data/crypto-ux500.h2
-rw-r--r--include/linux/platform_data/davinci_asp.h4
-rw-r--r--include/linux/platform_data/dma-ste-dma40.h (renamed from arch/arm/plat-nomadik/include/plat/ste_dma40.h)0
-rw-r--r--include/linux/platform_data/macb.h1
-rw-r--r--include/linux/platform_data/omap-twl4030.h26
-rw-r--r--include/linux/platform_data/pn544.h44
-rw-r--r--include/linux/power/smartreflex.h14
-rw-r--r--include/linux/regulator/consumer.h13
-rw-r--r--include/linux/regulator/driver.h5
-rw-r--r--include/linux/regulator/max8973-regulator.h72
-rw-r--r--include/linux/regulator/tps51632-regulator.h47
-rw-r--r--include/linux/regulator/tps65090-regulator.h50
-rw-r--r--include/linux/rtnetlink.h3
-rw-r--r--include/linux/skbuff.h102
-rw-r--r--include/linux/smscphy.h5
-rw-r--r--include/linux/ssb/ssb.h2
-rw-r--r--include/linux/ssb/ssb_driver_chipcommon.h5
-rw-r--r--include/linux/ssb/ssb_driver_extif.h52
-rw-r--r--include/linux/ssb/ssb_driver_mips.h10
-rw-r--r--include/linux/ssb/ssb_regs.h2
-rw-r--r--include/linux/stmmac.h3
-rw-r--r--include/linux/sysctl.h3
-rw-r--r--include/linux/tcp.h10
-rw-r--r--include/linux/timecompare.h125
-rw-r--r--include/linux/udp.h5
-rw-r--r--include/linux/usb/cdc_ncm.h134
-rw-r--r--include/linux/usb/usbnet.h10
-rw-r--r--include/linux/vgaarb.h4
-rw-r--r--include/linux/watchdog.h2
-rw-r--r--include/net/addrconf.h3
-rw-r--r--include/net/af_unix.h1
-rw-r--r--include/net/bluetooth/a2mp.h24
-rw-r--r--include/net/bluetooth/amp.h54
-rw-r--r--include/net/bluetooth/bluetooth.h1
-rw-r--r--include/net/bluetooth/hci.h69
-rw-r--r--include/net/bluetooth/hci_core.h123
-rw-r--r--include/net/bluetooth/l2cap.h50
-rw-r--r--include/net/cfg80211.h306
-rw-r--r--include/net/cls_cgroup.h6
-rw-r--r--include/net/gro_cells.h14
-rw-r--r--include/net/ieee80211_radiotap.h24
-rw-r--r--include/net/inet_hashtables.h50
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/inet_timewait_sock.h7
-rw-r--r--include/net/ip6_checksum.h35
-rw-r--r--include/net/ip6_fib.h20
-rw-r--r--include/net/ip6_route.h3
-rw-r--r--include/net/ip_vs.h195
-rw-r--r--include/net/ipip.h40
-rw-r--r--include/net/ipv6.h19
-rw-r--r--include/net/irda/irlmp.h2
-rw-r--r--include/net/mac80211.h275
-rw-r--r--include/net/ndisc.h15
-rw-r--r--include/net/net_namespace.h24
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_nat.h15
-rw-r--r--include/net/netfilter/nf_queue.h8
-rw-r--r--include/net/netns/sctp.h3
-rw-r--r--include/net/nfc/hci.h21
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--include/net/protocol.h31
-rw-r--r--include/net/request_sock.h12
-rw-r--r--include/net/route.h9
-rw-r--r--include/net/rtnetlink.h2
-rw-r--r--include/net/sch_generic.h7
-rw-r--r--include/net/sctp/command.h38
-rw-r--r--include/net/sctp/constants.h8
-rw-r--r--include/net/sctp/sctp.h12
-rw-r--r--include/net/sctp/sm.h2
-rw-r--r--include/net/sctp/structs.h39
-rw-r--r--include/net/sctp/ulpqueue.h2
-rw-r--r--include/net/sctp/user.h27
-rw-r--r--include/net/sock.h30
-rw-r--r--include/net/tcp.h1
-rw-r--r--include/sound/Kbuild10
-rw-r--r--include/sound/asequencer.h594
-rw-r--r--include/sound/asound.h935
-rw-r--r--include/sound/cs4271.h1
-rw-r--r--include/sound/emu10k1.h359
-rw-r--r--include/sound/pcm.h3
-rw-r--r--include/sound/sb16_csp.h104
-rw-r--r--include/sound/sh_fsi.h6
-rw-r--r--include/sound/tlv320aic32x4.h1
-rw-r--r--include/sound/vx_core.h6
-rw-r--r--include/uapi/asm-generic/socket.h1
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/ethtool.h11
-rw-r--r--include/uapi/linux/filter.h4
-rw-r--r--include/uapi/linux/hdlc/Kbuild1
-rw-r--r--include/uapi/linux/hdlc/ioctl.h (renamed from include/linux/hdlc/ioctl.h)7
-rw-r--r--include/uapi/linux/if_bridge.h81
-rw-r--r--include/uapi/linux/if_ether.h1
-rw-r--r--include/uapi/linux/if_link.h22
-rw-r--r--include/uapi/linux/if_packet.h1
-rw-r--r--include/uapi/linux/if_tun.h7
-rw-r--r--include/uapi/linux/if_tunnel.h20
-rw-r--r--include/uapi/linux/in6.h1
-rw-r--r--include/uapi/linux/inet_diag.h3
-rw-r--r--include/uapi/linux/input.h1
-rw-r--r--include/uapi/linux/ipv6.h1
-rw-r--r--include/uapi/linux/ipv6_route.h3
-rw-r--r--include/uapi/linux/netconf.h24
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_conntrack.h2
-rw-r--r--include/uapi/linux/netfilter_ipv6/ip6_tables.h3
-rw-r--r--include/uapi/linux/nfc.h15
-rw-r--r--include/uapi/linux/nl80211.h177
-rw-r--r--include/uapi/linux/pci_regs.h23
-rw-r--r--include/uapi/linux/ptp_clock.h14
-rw-r--r--include/uapi/linux/rtnetlink.h26
-rw-r--r--include/uapi/linux/unix_diag.h1
-rw-r--r--include/uapi/linux/usb/cdc.h23
-rw-r--r--include/uapi/linux/virtio_net.h27
-rw-r--r--include/uapi/sound/Kbuild10
-rw-r--r--include/uapi/sound/asequencer.h614
-rw-r--r--include/uapi/sound/asound.h971
-rw-r--r--include/uapi/sound/asound_fm.h (renamed from include/sound/asound_fm.h)0
-rw-r--r--include/uapi/sound/compress_offload.h (renamed from include/sound/compress_offload.h)0
-rw-r--r--include/uapi/sound/compress_params.h (renamed from include/sound/compress_params.h)0
-rw-r--r--include/uapi/sound/emu10k1.h373
-rw-r--r--include/uapi/sound/hdsp.h (renamed from include/sound/hdsp.h)0
-rw-r--r--include/uapi/sound/hdspm.h (renamed from include/sound/hdspm.h)0
-rw-r--r--include/uapi/sound/sb16_csp.h122
-rw-r--r--include/uapi/sound/sfnt_info.h (renamed from include/sound/sfnt_info.h)0
-rw-r--r--kernel/nsproxy.c2
-rw-r--r--kernel/pid.c4
-rw-r--r--kernel/profile.c7
-rw-r--r--kernel/time/Makefile2
-rw-r--r--kernel/time/timecompare.c193
-rw-r--r--kernel/trace/ftrace.c2
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace_functions.c2
-rw-r--r--kernel/trace/trace_irqsoff.c2
-rw-r--r--kernel/trace/trace_sched_wakeup.c2
-rw-r--r--kernel/wait.c2
-rw-r--r--lib/Kconfig.debug10
-rw-r--r--lib/bitmap.c2
-rw-r--r--mm/Kconfig2
-rw-r--r--mm/hugetlb.c2
-rw-r--r--mm/memory_hotplug.c6
-rw-r--r--mm/page_alloc.c4
-rw-r--r--mm/util.c2
-rw-r--r--net/8021q/vlan.c15
-rw-r--r--net/8021q/vlan_dev.c12
-rw-r--r--net/atm/br2684.c91
-rw-r--r--net/atm/common.c12
-rw-r--r--net/atm/pppoatm.c68
-rw-r--r--net/batman-adv/Kconfig11
-rw-r--r--net/batman-adv/Makefile1
-rw-r--r--net/batman-adv/bat_iv_ogm.c51
-rw-r--r--net/batman-adv/bitarray.c23
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c131
-rw-r--r--net/batman-adv/bridge_loop_avoidance.h6
-rw-r--r--net/batman-adv/debugfs.c60
-rw-r--r--net/batman-adv/distributed-arp-table.c1066
-rw-r--r--net/batman-adv/distributed-arp-table.h167
-rw-r--r--net/batman-adv/gateway_client.c19
-rw-r--r--net/batman-adv/hard-interface.c51
-rw-r--r--net/batman-adv/hash.h22
-rw-r--r--net/batman-adv/icmp_socket.c16
-rw-r--r--net/batman-adv/main.c89
-rw-r--r--net/batman-adv/main.h36
-rw-r--r--net/batman-adv/originator.c22
-rw-r--r--net/batman-adv/packet.h86
-rw-r--r--net/batman-adv/routing.c315
-rw-r--r--net/batman-adv/send.c43
-rw-r--r--net/batman-adv/send.h3
-rw-r--r--net/batman-adv/soft-interface.c94
-rw-r--r--net/batman-adv/sysfs.c58
-rw-r--r--net/batman-adv/translation-table.c526
-rw-r--r--net/batman-adv/translation-table.h8
-rw-r--r--net/batman-adv/types.h102
-rw-r--r--net/batman-adv/unicast.c143
-rw-r--r--net/batman-adv/unicast.h36
-rw-r--r--net/batman-adv/vis.c44
-rw-r--r--net/bluetooth/Kconfig2
-rw-r--r--net/bluetooth/Makefile2
-rw-r--r--net/bluetooth/a2mp.c459
-rw-r--r--net/bluetooth/af_bluetooth.c10
-rw-r--r--net/bluetooth/amp.c471
-rw-r--r--net/bluetooth/bnep/core.c3
-rw-r--r--net/bluetooth/bnep/netdev.c1
-rw-r--r--net/bluetooth/cmtp/capi.c2
-rw-r--r--net/bluetooth/cmtp/core.c2
-rw-r--r--net/bluetooth/cmtp/sock.c2
-rw-r--r--net/bluetooth/hci_conn.c76
-rw-r--r--net/bluetooth/hci_core.c233
-rw-r--r--net/bluetooth/hci_event.c562
-rw-r--r--net/bluetooth/hci_sysfs.c10
-rw-r--r--net/bluetooth/hidp/core.c17
-rw-r--r--net/bluetooth/l2cap_core.c1577
-rw-r--r--net/bluetooth/l2cap_sock.c94
-rw-r--r--net/bluetooth/lib.c14
-rw-r--r--net/bluetooth/mgmt.c105
-rw-r--r--net/bluetooth/rfcomm/core.c19
-rw-r--r--net/bluetooth/rfcomm/sock.c13
-rw-r--r--net/bluetooth/rfcomm/tty.c6
-rw-r--r--net/bluetooth/sco.c98
-rw-r--r--net/bluetooth/smp.c2
-rw-r--r--net/bridge/Makefile2
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_input.c17
-rw-r--r--net/bridge/br_ioctl.c25
-rw-r--r--net/bridge/br_mdb.c481
-rw-r--r--net/bridge/br_multicast.c81
-rw-r--r--net/bridge/br_netlink.c249
-rw-r--r--net/bridge/br_private.h46
-rw-r--r--net/bridge/br_stp.c22
-rw-r--r--net/bridge/br_stp_bpdu.c7
-rw-r--r--net/bridge/br_sysfs_br.c22
-rw-r--r--net/bridge/br_sysfs_if.c47
-rw-r--r--net/caif/caif_usb.c18
-rw-r--r--net/caif/cfctrl.c3
-rw-r--r--net/can/gw.c6
-rw-r--r--net/can/proc.c2
-rw-r--r--net/core/dev.c236
-rw-r--r--net/core/ethtool.c2
-rw-r--r--net/core/filter.c139
-rw-r--r--net/core/flow.c4
-rw-r--r--net/core/neighbour.c20
-rw-r--r--net/core/net-sysfs.c17
-rw-r--r--net/core/net_namespace.c23
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/netprio_cgroup.c2
-rw-r--r--net/core/pktgen.c47
-rw-r--r--net/core/rtnetlink.c230
-rw-r--r--net/core/scm.c6
-rw-r--r--net/core/skbuff.c34
-rw-r--r--net/core/sock.c84
-rw-r--r--net/core/sysctl_net_core.c5
-rw-r--r--net/dcb/dcbnl.c8
-rw-r--r--net/dccp/minisocks.c3
-rw-r--r--net/decnet/dn_dev.c6
-rw-r--r--net/decnet/dn_fib.c6
-rw-r--r--net/dsa/Kconfig18
-rw-r--r--net/ieee802154/6lowpan.c3
-rw-r--r--net/ipv4/af_inet.c93
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c198
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/inet_connection_sock.c25
-rw-r--r--net/ipv4/inet_diag.c5
-rw-r--r--net/ipv4/inet_hashtables.c36
-rw-r--r--net/ipv4/ip_fragment.c4
-rw-r--r--net/ipv4/ip_gre.c32
-rw-r--r--net/ipv4/ip_options.c6
-rw-r--r--net/ipv4/ip_output.c4
-rw-r--r--net/ipv4/ip_sockglue.c5
-rw-r--r--net/ipv4/ip_vti.c26
-rw-r--r--net/ipv4/ipconfig.c6
-rw-r--r--net/ipv4/ipip.c271
-rw-r--r--net/ipv4/ipmr.c137
-rw-r--r--net/ipv4/netfilter/arp_tables.c8
-rw-r--r--net/ipv4/netfilter/ip_tables.c8
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c9
-rw-r--r--net/ipv4/netfilter/iptable_nat.c8
-rw-r--r--net/ipv4/protocol.c21
-rw-r--r--net/ipv4/route.c27
-rw-r--r--net/ipv4/syncookies.c2
-rw-r--r--net/ipv4/sysctl_net_ipv4.c3
-rw-r--r--net/ipv4/tcp.c25
-rw-r--r--net/ipv4/tcp_cong.c5
-rw-r--r--net/ipv4/tcp_input.c45
-rw-r--r--net/ipv4/tcp_ipv4.c38
-rw-r--r--net/ipv4/tcp_minisocks.c8
-rw-r--r--net/ipv4/tcp_output.c5
-rw-r--r--net/ipv4/tcp_timer.c8
-rw-r--r--net/ipv6/Makefile5
-rw-r--r--net/ipv6/addrconf.c203
-rw-r--r--net/ipv6/af_inet6.c245
-rw-r--r--net/ipv6/ah6.c10
-rw-r--r--net/ipv6/anycast.c7
-rw-r--r--net/ipv6/datagram.c8
-rw-r--r--net/ipv6/exthdrs.c70
-rw-r--r--net/ipv6/exthdrs_core.c168
-rw-r--r--net/ipv6/exthdrs_offload.c41
-rw-r--r--net/ipv6/fib6_rules.c2
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/inet6_hashtables.c27
-rw-r--r--net/ipv6/ip6_fib.c57
-rw-r--r--net/ipv6/ip6_flowlabel.c3
-rw-r--r--net/ipv6/ip6_gre.c29
-rw-r--r--net/ipv6/ip6_offload.c282
-rw-r--r--net/ipv6/ip6_offload.h18
-rw-r--r--net/ipv6/ip6_output.c72
-rw-r--r--net/ipv6/ip6_tunnel.c288
-rw-r--r--net/ipv6/ip6mr.c157
-rw-r--r--net/ipv6/ipv6_sockglue.c9
-rw-r--r--net/ipv6/mcast.c7
-rw-r--r--net/ipv6/ndisc.c62
-rw-r--r--net/ipv6/netfilter/ip6_tables.c117
-rw-r--r--net/ipv6/netfilter/ip6t_rpfilter.c2
-rw-r--r--net/ipv6/netfilter/ip6table_nat.c8
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c70
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c4
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c6
-rw-r--r--net/ipv6/netfilter/nf_nat_proto_icmpv6.c2
-rw-r--r--net/ipv6/output_core.c76
-rw-r--r--net/ipv6/protocol.c25
-rw-r--r--net/ipv6/raw.c6
-rw-r--r--net/ipv6/reassembly.c4
-rw-r--r--net/ipv6/route.c210
-rw-r--r--net/ipv6/sit.c459
-rw-r--r--net/ipv6/syncookies.c2
-rw-r--r--net/ipv6/tcp_ipv6.c124
-rw-r--r--net/ipv6/tcpv6_offload.c95
-rw-r--r--net/ipv6/udp.c94
-rw-r--r--net/ipv6/udp_offload.c120
-rw-r--r--net/ipv6/xfrm6_policy.c21
-rw-r--r--net/ipv6/xfrm6_state.c4
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/l2tp/l2tp_netlink.c2
-rw-r--r--net/llc/af_llc.c2
-rw-r--r--net/mac80211/Kconfig2
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/aes_cmac.c18
-rw-r--r--net/mac80211/agg-rx.c2
-rw-r--r--net/mac80211/agg-tx.c14
-rw-r--r--net/mac80211/cfg.c499
-rw-r--r--net/mac80211/chan.c411
-rw-r--r--net/mac80211/debugfs.h6
-rw-r--r--net/mac80211/debugfs_key.c23
-rw-r--r--net/mac80211/debugfs_netdev.c78
-rw-r--r--net/mac80211/debugfs_sta.c59
-rw-r--r--net/mac80211/driver-ops.h142
-rw-r--r--net/mac80211/ht.c4
-rw-r--r--net/mac80211/ibss.c171
-rw-r--r--net/mac80211/ieee80211_i.h214
-rw-r--r--net/mac80211/iface.c143
-rw-r--r--net/mac80211/key.c15
-rw-r--r--net/mac80211/key.h11
-rw-r--r--net/mac80211/main.c150
-rw-r--r--net/mac80211/mesh.c82
-rw-r--r--net/mac80211/mesh.h18
-rw-r--r--net/mac80211/mesh_plink.c64
-rw-r--r--net/mac80211/mesh_sync.c105
-rw-r--r--net/mac80211/mlme.c735
-rw-r--r--net/mac80211/offchannel.c22
-rw-r--r--net/mac80211/pm.c46
-rw-r--r--net/mac80211/rate.c5
-rw-r--r--net/mac80211/rate.h12
-rw-r--r--net/mac80211/rc80211_minstrel.c9
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c8
-rw-r--r--net/mac80211/rx.c250
-rw-r--r--net/mac80211/scan.c61
-rw-r--r--net/mac80211/sta_info.c69
-rw-r--r--net/mac80211/sta_info.h31
-rw-r--r--net/mac80211/status.c169
-rw-r--r--net/mac80211/trace.h246
-rw-r--r--net/mac80211/tx.c291
-rw-r--r--net/mac80211/util.c363
-rw-r--r--net/mac80211/vht.c35
-rw-r--r--net/mac80211/wme.c40
-rw-r--r--net/mac80211/wpa.c5
-rw-r--r--net/mac802154/tx.c7
-rw-r--r--net/mac802154/wpan.c4
-rw-r--r--net/netfilter/core.c2
-rw-r--r--net/netfilter/ipset/ip_set_core.c245
-rw-r--r--net/netfilter/ipvs/Kconfig7
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c15
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c404
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c8
-rw-r--r--net/netfilter/ipvs/ip_vs_dh.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_nfct.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_pe_sip.c18
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_ah_esp.c9
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c42
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c40
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c41
-rw-r--r--net/netfilter/ipvs/ip_vs_sched.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c81
-rw-r--r--net/netfilter/nf_conntrack_acct.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c31
-rw-r--r--net/netfilter/nf_conntrack_ecache.c4
-rw-r--r--net/netfilter/nf_conntrack_helper.c4
-rw-r--r--net/netfilter/nf_conntrack_netlink.c118
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c2
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/nf_conntrack_timestamp.c4
-rw-r--r--net/netfilter/nf_log.c2
-rw-r--r--net/netfilter/nf_queue.c152
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/nfnetlink_queue_core.c14
-rw-r--r--net/netfilter/xt_HMARK.c8
-rw-r--r--net/netfilter/xt_ipvs.c4
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/nfc/Kconfig4
-rw-r--r--net/nfc/core.c33
-rw-r--r--net/nfc/hci/command.c28
-rw-r--r--net/nfc/hci/core.c90
-rw-r--r--net/nfc/hci/llc.c2
-rw-r--r--net/nfc/hci/llc_shdlc.c7
-rw-r--r--net/nfc/llcp/Kconfig4
-rw-r--r--net/nfc/llcp/commands.c148
-rw-r--r--net/nfc/llcp/llcp.c248
-rw-r--r--net/nfc/llcp/llcp.h13
-rw-r--r--net/nfc/llcp/sock.c42
-rw-r--r--net/nfc/nci/Kconfig4
-rw-r--r--net/nfc/nci/core.c29
-rw-r--r--net/nfc/netlink.c157
-rw-r--r--net/nfc/nfc.h6
-rw-r--r--net/nfc/rawsock.c1
-rw-r--r--net/openvswitch/actions.c97
-rw-r--r--net/openvswitch/datapath.c27
-rw-r--r--net/openvswitch/flow.c28
-rw-r--r--net/openvswitch/flow.h8
-rw-r--r--net/openvswitch/vport-netdev.c14
-rw-r--r--net/openvswitch/vport-netdev.h3
-rw-r--r--net/openvswitch/vport.c5
-rw-r--r--net/packet/af_packet.c50
-rw-r--r--net/packet/internal.h1
-rw-r--r--net/phonet/pn_netlink.c6
-rw-r--r--net/rds/ib.h2
-rw-r--r--net/rds/ib_recv.c24
-rw-r--r--net/rfkill/core.c4
-rw-r--r--net/rfkill/rfkill-gpio.c2
-rw-r--r--net/rfkill/rfkill-regulator.c6
-rw-r--r--net/sched/Kconfig2
-rw-r--r--net/sched/act_api.c3
-rw-r--r--net/sched/cls_api.c2
-rw-r--r--net/sched/cls_cgroup.c24
-rw-r--r--net/sched/sch_api.c20
-rw-r--r--net/sched/sch_cbq.c3
-rw-r--r--net/sched/sch_generic.c11
-rw-r--r--net/sched/sch_htb.c139
-rw-r--r--net/sched/sch_mq.c4
-rw-r--r--net/sched/sch_mqprio.c4
-rw-r--r--net/sched/sch_qfq.c830
-rw-r--r--net/sctp/Kconfig39
-rw-r--r--net/sctp/associola.c16
-rw-r--r--net/sctp/endpointola.c7
-rw-r--r--net/sctp/inqueue.c2
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/output.c14
-rw-r--r--net/sctp/outqueue.c12
-rw-r--r--net/sctp/proc.c21
-rw-r--r--net/sctp/protocol.c15
-rw-r--r--net/sctp/sm_make_chunk.c24
-rw-r--r--net/sctp/sm_sideeffect.c55
-rw-r--r--net/sctp/sm_statefuns.c22
-rw-r--r--net/sctp/socket.c88
-rw-r--r--net/sctp/sysctl.c59
-rw-r--r--net/sctp/transport.c20
-rw-r--r--net/sctp/tsnmap.c8
-rw-r--r--net/sctp/ulpqueue.c3
-rw-r--r--net/socket.c8
-rw-r--r--net/sysctl_net.c15
-rw-r--r--net/tipc/Kconfig13
-rw-r--r--net/tipc/bcast.c27
-rw-r--r--net/tipc/bearer.c110
-rw-r--r--net/tipc/bearer.h24
-rw-r--r--net/tipc/core.c5
-rw-r--r--net/tipc/discover.c2
-rw-r--r--net/tipc/link.c232
-rw-r--r--net/tipc/link.h4
-rw-r--r--net/tipc/name_distr.c2
-rw-r--r--net/tipc/node.c15
-rw-r--r--net/tipc/node.h6
-rw-r--r--net/tipc/port.c32
-rw-r--r--net/tipc/port.h6
-rw-r--r--net/tipc/socket.c411
-rw-r--r--net/tipc/subscr.c2
-rw-r--r--net/unix/diag.c3
-rw-r--r--net/unix/sysctl_net_unix.c4
-rw-r--r--net/wireless/Kconfig5
-rw-r--r--net/wireless/Makefile4
-rw-r--r--net/wireless/ap.c4
-rw-r--r--net/wireless/chan.c313
-rw-r--r--net/wireless/core.c23
-rw-r--r--net/wireless/core.h32
-rw-r--r--net/wireless/ethtool.c15
-rw-r--r--net/wireless/ibss.c36
-rw-r--r--net/wireless/mesh.c59
-rw-r--r--net/wireless/mlme.c116
-rw-r--r--net/wireless/nl80211.c868
-rw-r--r--net/wireless/nl80211.h8
-rw-r--r--net/wireless/rdev-ops.h878
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/reg.h2
-rw-r--r--net/wireless/scan.c615
-rw-r--r--net/wireless/sme.c25
-rw-r--r--net/wireless/sysfs.c5
-rw-r--r--net/wireless/trace.c7
-rw-r--r--net/wireless/trace.h2324
-rw-r--r--net/wireless/util.c197
-rw-r--r--net/wireless/wext-compat.c76
-rw-r--r--net/wireless/wext-sme.c19
-rw-r--r--net/xfrm/xfrm_ipcomp.c8
-rw-r--r--net/xfrm/xfrm_replay.c13
-rw-r--r--net/xfrm/xfrm_sysctl.c4
-rw-r--r--net/xfrm/xfrm_user.c2
-rwxr-xr-xscripts/kernel-doc34
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/selinux/nlmsgtab.c3
-rw-r--r--sound/arm/aaci.c18
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c2
-rw-r--r--sound/arm/pxa2xx-ac97.c6
-rw-r--r--sound/atmel/abdac.c8
-rw-r--r--sound/atmel/ac97c.c10
-rw-r--r--sound/core/oss/pcm_plugin.c6
-rw-r--r--sound/core/pcm.c3
-rw-r--r--sound/core/pcm_compat.c20
-rw-r--r--sound/core/pcm_lib.c57
-rw-r--r--sound/core/pcm_native.c4
-rw-r--r--sound/core/seq/seq_device.c2
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/aloop.c52
-rw-r--r--sound/drivers/dummy.c87
-rw-r--r--sound/drivers/ml403-ac97cr.c10
-rw-r--r--sound/drivers/mpu401/mpu401.c18
-rw-r--r--sound/drivers/mtpav.c14
-rw-r--r--sound/drivers/mts64.c40
-rw-r--r--sound/drivers/pcsp/pcsp.c14
-rw-r--r--sound/drivers/pcsp/pcsp_input.c2
-rw-r--r--sound/drivers/pcsp/pcsp_input.h2
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c2
-rw-r--r--sound/drivers/pcsp/pcsp_mixer.c10
-rw-r--r--sound/drivers/portman2x4.c18
-rw-r--r--sound/drivers/serial-u16550.c32
-rw-r--r--sound/drivers/virmidi.c6
-rw-r--r--sound/drivers/vx/vx_hwdep.c139
-rw-r--r--sound/firewire/Kconfig13
-rw-r--r--sound/firewire/Makefile2
-rw-r--r--sound/firewire/scs1x.c527
-rw-r--r--sound/firewire/speakers.c8
-rw-r--r--sound/isa/Kconfig4
-rw-r--r--sound/isa/ad1816a/ad1816a.c18
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c19
-rw-r--r--sound/isa/ad1848/ad1848.c8
-rw-r--r--sound/isa/adlib.c8
-rw-r--r--sound/isa/als100.c22
-rw-r--r--sound/isa/azt2320.c26
-rw-r--r--sound/isa/cmi8328.c8
-rw-r--r--sound/isa/cmi8330.c42
-rw-r--r--sound/isa/cs423x/cs4231.c8
-rw-r--r--sound/isa/cs423x/cs4236.c50
-rw-r--r--sound/isa/es1688/es1688.c28
-rw-r--r--sound/isa/es18xx.c80
-rw-r--r--sound/isa/galaxy/galaxy.c26
-rw-r--r--sound/isa/gus/gusclassic.c15
-rw-r--r--sound/isa/gus/gusextreme.c24
-rw-r--r--sound/isa/gus/gusmax.c16
-rw-r--r--sound/isa/gus/interwave.c54
-rw-r--r--sound/isa/msnd/msnd.h2
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c44
-rw-r--r--sound/isa/msnd/msnd_pinnacle_mixer.c2
-rw-r--r--sound/isa/opl3sa2.c40
-rw-r--r--sound/isa/opti9xx/miro.c68
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c42
-rw-r--r--sound/isa/sb/emu8000.c30
-rw-r--r--sound/isa/sb/jazz16.c18
-rw-r--r--sound/isa/sb/sb16.c26
-rw-r--r--sound/isa/sb/sb8.c8
-rw-r--r--sound/isa/sc6000.c38
-rw-r--r--sound/isa/sscape.c32
-rw-r--r--sound/isa/wavefront/wavefront.c53
-rw-r--r--sound/isa/wavefront/wavefront_fx.c2
-rw-r--r--sound/isa/wavefront/wavefront_midi.c2
-rw-r--r--sound/isa/wavefront/wavefront_synth.c14
-rw-r--r--sound/mips/au1x00.c4
-rw-r--r--sound/mips/hal2.c14
-rw-r--r--sound/mips/sgio2audio.c28
-rw-r--r--sound/oss/ad1848.c2
-rw-r--r--sound/oss/kahlua.c10
-rw-r--r--sound/oss/sb_audio.c3
-rw-r--r--sound/parisc/harmony.c12
-rw-r--r--sound/pci/Kconfig5
-rw-r--r--sound/pci/ad1889.c18
-rw-r--r--sound/pci/ak4531_codec.c10
-rw-r--r--sound/pci/ali5451/ali5451.c32
-rw-r--r--sound/pci/als300.c14
-rw-r--r--sound/pci/als4000.c12
-rw-r--r--sound/pci/asihpi/asihpi.c55
-rw-r--r--sound/pci/asihpi/hpidspcd.c22
-rw-r--r--sound/pci/asihpi/hpioctl.c23
-rw-r--r--sound/pci/asihpi/hpioctl.h6
-rw-r--r--sound/pci/atiixp.c32
-rw-r--r--sound/pci/atiixp_modem.c20
-rw-r--r--sound/pci/au88x0/au88x0.c10
-rw-r--r--sound/pci/au88x0/au88x0_a3d.c6
-rw-r--r--sound/pci/au88x0/au88x0_core.c9
-rw-r--r--sound/pci/au88x0/au88x0_eq.c10
-rw-r--r--sound/pci/au88x0/au88x0_game.c2
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c2
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c2
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c6
-rw-r--r--sound/pci/aw2/aw2-alsa.c28
-rw-r--r--sound/pci/azt3328.c22
-rw-r--r--sound/pci/bt87x.c22
-rw-r--r--sound/pci/ca0106/ca0106_main.c12
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c26
-rw-r--r--sound/pci/ca0106/ca0106_proc.c2
-rw-r--r--sound/pci/ca0106/ca_midi.c2
-rw-r--r--sound/pci/cmipci.c48
-rw-r--r--sound/pci/cs4281.c30
-rw-r--r--sound/pci/cs46xx/cs46xx.c8
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c35
-rw-r--r--sound/pci/cs5530.c16
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c18
-rw-r--r--sound/pci/cs5535audio/cs5535audio.h10
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c10
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c2
-rw-r--r--sound/pci/ctxfi/ctatc.c20
-rw-r--r--sound/pci/ctxfi/ctatc.h8
-rw-r--r--sound/pci/ctxfi/cthardware.c4
-rw-r--r--sound/pci/ctxfi/cthw20k1.c4
-rw-r--r--sound/pci/ctxfi/cthw20k2.c4
-rw-r--r--sound/pci/ctxfi/xfi.c6
-rw-r--r--sound/pci/echoaudio/echoaudio.c46
-rw-r--r--sound/pci/echoaudio/echoaudio.h4
-rw-r--r--sound/pci/echoaudio/midi.c4
-rw-r--r--sound/pci/emu10k1/emu10k1.c12
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c96
-rw-r--r--sound/pci/emu10k1/emu10k1_patch.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c29
-rw-r--r--sound/pci/emu10k1/emufx.c25
-rw-r--r--sound/pci/emu10k1/emumixer.c22
-rw-r--r--sound/pci/emu10k1/emumpu401.c6
-rw-r--r--sound/pci/emu10k1/emupcm.c11
-rw-r--r--sound/pci/emu10k1/emuproc.c2
-rw-r--r--sound/pci/emu10k1/p16v.c8
-rw-r--r--sound/pci/emu10k1/timer.c2
-rw-r--r--sound/pci/ens1370.c52
-rw-r--r--sound/pci/es1938.c20
-rw-r--r--sound/pci/es1968.c44
-rw-r--r--sound/pci/fm801.c26
-rw-r--r--sound/pci/hda/Kconfig5
-rw-r--r--sound/pci/hda/Makefile1
-rw-r--r--sound/pci/hda/hda_auto_parser.c106
-rw-r--r--sound/pci/hda/hda_codec.c214
-rw-r--r--sound/pci/hda/hda_codec.h6
-rw-r--r--sound/pci/hda/hda_hwdep.c2
-rw-r--r--sound/pci/hda/hda_intel.c435
-rw-r--r--sound/pci/hda/hda_intel_trace.h62
-rw-r--r--sound/pci/hda/hda_jack.c93
-rw-r--r--sound/pci/hda/hda_jack.h6
-rw-r--r--sound/pci/hda/hda_local.h17
-rw-r--r--sound/pci/hda/patch_analog.c73
-rw-r--r--sound/pci/hda/patch_cirrus.c47
-rw-r--r--sound/pci/hda/patch_conexant.c99
-rw-r--r--sound/pci/hda/patch_hdmi.c22
-rw-r--r--sound/pci/hda/patch_realtek.c192
-rw-r--r--sound/pci/hda/patch_sigmatel.c150
-rw-r--r--sound/pci/hda/patch_via.c186
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/amp.c7
-rw-r--r--sound/pci/ice1712/aureon.c28
-rw-r--r--sound/pci/ice1712/delta.c45
-rw-r--r--sound/pci/ice1712/ews.c33
-rw-r--r--sound/pci/ice1712/hoontech.c27
-rw-r--r--sound/pci/ice1712/ice1712.c103
-rw-r--r--sound/pci/ice1712/ice1712.h12
-rw-r--r--sound/pci/ice1712/ice1724.c85
-rw-r--r--sound/pci/ice1712/juli.c26
-rw-r--r--sound/pci/ice1712/maya44.c21
-rw-r--r--sound/pci/ice1712/phase.c25
-rw-r--r--sound/pci/ice1712/pontis.c11
-rw-r--r--sound/pci/ice1712/prodigy192.c17
-rw-r--r--sound/pci/ice1712/prodigy_hifi.c21
-rw-r--r--sound/pci/ice1712/psc724.c464
-rw-r--r--sound/pci/ice1712/psc724.h13
-rw-r--r--sound/pci/ice1712/quartet.c32
-rw-r--r--sound/pci/ice1712/revo.c29
-rw-r--r--sound/pci/ice1712/se.c31
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c11
-rw-r--r--sound/pci/ice1712/wm8766.c361
-rw-r--r--sound/pci/ice1712/wm8766.h163
-rw-r--r--sound/pci/ice1712/wm8776.c633
-rw-r--r--sound/pci/ice1712/wm8776.h226
-rw-r--r--sound/pci/ice1712/wtm.c11
-rw-r--r--sound/pci/intel8x0.c56
-rw-r--r--sound/pci/intel8x0m.c30
-rw-r--r--sound/pci/korg1212/korg1212.c12
-rw-r--r--sound/pci/lola/lola.c14
-rw-r--r--sound/pci/lola/lola_clock.c2
-rw-r--r--sound/pci/lola/lola_mixer.c32
-rw-r--r--sound/pci/lola/lola_pcm.c4
-rw-r--r--sound/pci/lola/lola_proc.c2
-rw-r--r--sound/pci/lx6464es/lx6464es.c30
-rw-r--r--sound/pci/lx6464es/lx_core.c2
-rw-r--r--sound/pci/lx6464es/lx_core.h2
-rw-r--r--sound/pci/maestro3.c24
-rw-r--r--sound/pci/mixart/mixart.c12
-rw-r--r--sound/pci/mixart/mixart_hwdep.c76
-rw-r--r--sound/pci/nm256/nm256.c18
-rw-r--r--sound/pci/oxygen/oxygen.c10
-rw-r--r--sound/pci/oxygen/virtuoso.c11
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c4
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c4
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c10
-rw-r--r--sound/pci/pcxhr/pcxhr.c14
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c86
-rw-r--r--sound/pci/riptide/riptide.c20
-rw-r--r--sound/pci/rme32.c10
-rw-r--r--sound/pci/rme96.c14
-rw-r--r--sound/pci/rme9652/hdsp.c77
-rw-r--r--sound/pci/rme9652/hdspm.c439
-rw-r--r--sound/pci/rme9652/rme9652.c22
-rw-r--r--sound/pci/sis7019.c18
-rw-r--r--sound/pci/sonicvibes.c37
-rw-r--r--sound/pci/trident/trident.c8
-rw-r--r--sound/pci/trident/trident_main.c46
-rw-r--r--sound/pci/via82xx.c50
-rw-r--r--sound/pci/via82xx_modem.c26
-rw-r--r--sound/pci/vx222/vx222.c14
-rw-r--r--sound/pci/ymfpci/ymfpci.c12
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c50
-rw-r--r--sound/ppc/awacs.c54
-rw-r--r--sound/ppc/beep.c2
-rw-r--r--sound/ppc/burgundy.c22
-rw-r--r--sound/ppc/daca.c2
-rw-r--r--sound/ppc/keywest.c4
-rw-r--r--sound/ppc/pmac.c12
-rw-r--r--sound/ppc/powermac.c6
-rw-r--r--sound/ppc/snd_ps3.c12
-rw-r--r--sound/ppc/tumbler.c16
-rw-r--r--sound/sh/aica.c13
-rw-r--r--sound/sh/sh_dac_audio.c10
-rw-r--r--sound/soc/atmel/Kconfig13
-rw-r--r--sound/soc/atmel/Makefile4
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c240
-rw-r--r--sound/soc/atmel/atmel-pcm-pdc.c401
-rw-r--r--sound/soc/atmel/atmel-pcm.c401
-rw-r--r--sound/soc/atmel/atmel-pcm.h34
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c168
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h3
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c116
-rw-r--r--sound/soc/au1x/ac97c.c6
-rw-r--r--sound/soc/au1x/db1000.c6
-rw-r--r--sound/soc/au1x/db1200.c8
-rw-r--r--sound/soc/au1x/dbdma2.c6
-rw-r--r--sound/soc/au1x/dma.c6
-rw-r--r--sound/soc/au1x/i2sc.c6
-rw-r--r--sound/soc/au1x/psc-ac97.c6
-rw-r--r--sound/soc/au1x/psc-i2s.c6
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c6
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c6
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c6
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c6
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c6
-rw-r--r--sound/soc/blackfin/bf6xx-i2s.c6
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1373.c4
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1701.c4
-rw-r--r--sound/soc/blackfin/bfin-eval-adav80x.c4
-rw-r--r--sound/soc/cirrus/edb93xx.c6
-rw-r--r--sound/soc/cirrus/ep93xx-ac97.c6
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c4
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.c6
-rw-r--r--sound/soc/cirrus/simone.c6
-rw-r--r--sound/soc/cirrus/snappercl15.c6
-rw-r--r--sound/soc/codecs/88pm860x-codec.c6
-rw-r--r--sound/soc/codecs/Kconfig16
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/ab8500-codec.c8
-rw-r--r--sound/soc/codecs/ac97.c6
-rw-r--r--sound/soc/codecs/ad1836.c6
-rw-r--r--sound/soc/codecs/ad193x.c14
-rw-r--r--sound/soc/codecs/ad1980.c6
-rw-r--r--sound/soc/codecs/ad73311.c4
-rw-r--r--sound/soc/codecs/adau1373.c8
-rw-r--r--sound/soc/codecs/adau1701.c8
-rw-r--r--sound/soc/codecs/adav80x.c20
-rw-r--r--sound/soc/codecs/ads117x.c6
-rw-r--r--sound/soc/codecs/ak4104.c69
-rw-r--r--sound/soc/codecs/ak4535.c15
-rw-r--r--sound/soc/codecs/ak4641.c8
-rw-r--r--sound/soc/codecs/ak4642.c31
-rw-r--r--sound/soc/codecs/ak4671.c8
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/alc5632.c8
-rw-r--r--sound/soc/codecs/arizona.c53
-rw-r--r--sound/soc/codecs/arizona.h71
-rw-r--r--sound/soc/codecs/cq93vc.c2
-rw-r--r--sound/soc/codecs/cs4271.c35
-rw-r--r--sound/soc/codecs/cs42l52.c2
-rw-r--r--sound/soc/codecs/cs42l73.c8
-rw-r--r--sound/soc/codecs/da7210.c38
-rw-r--r--sound/soc/codecs/da732x.c8
-rw-r--r--sound/soc/codecs/da9055.c51
-rw-r--r--sound/soc/codecs/dfbmcs320.c6
-rw-r--r--sound/soc/codecs/dmic.c6
-rw-r--r--sound/soc/codecs/isabelle.c8
-rw-r--r--sound/soc/codecs/jz4740.c148
-rw-r--r--sound/soc/codecs/lm4857.c8
-rw-r--r--sound/soc/codecs/lm49453.c18
-rw-r--r--sound/soc/codecs/max9768.c15
-rw-r--r--sound/soc/codecs/max98088.c16
-rw-r--r--sound/soc/codecs/max98090.c577
-rw-r--r--sound/soc/codecs/max98095.c4
-rw-r--r--sound/soc/codecs/max9850.c8
-rw-r--r--sound/soc/codecs/max9877.c8
-rw-r--r--sound/soc/codecs/mc13783.c2
-rw-r--r--sound/soc/codecs/ml26124.c8
-rw-r--r--sound/soc/codecs/omap-hdmi.c6
-rw-r--r--sound/soc/codecs/pcm3008.c6
-rw-r--r--sound/soc/codecs/rt5631.c6
-rw-r--r--sound/soc/codecs/sgtl5000.c8
-rw-r--r--sound/soc/codecs/si476x.c255
-rw-r--r--sound/soc/codecs/sn95031.c6
-rw-r--r--sound/soc/codecs/ssm2602.c12
-rw-r--r--sound/soc/codecs/sta32x.c8
-rw-r--r--sound/soc/codecs/sta529.c8
-rw-r--r--sound/soc/codecs/stac9766.c6
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c32
-rw-r--r--sound/soc/codecs/tlv320aic32x4.h3
-rw-r--r--sound/soc/codecs/tlv320dac33.c8
-rw-r--r--sound/soc/codecs/tpa6130a2.c8
-rw-r--r--sound/soc/codecs/twl4030.c6
-rw-r--r--sound/soc/codecs/twl6040.c6
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/uda1380.c8
-rw-r--r--sound/soc/codecs/wl1273.c6
-rw-r--r--sound/soc/codecs/wm0010.c425
-rw-r--r--sound/soc/codecs/wm1250-ev1.c10
-rw-r--r--sound/soc/codecs/wm2000.c10
-rw-r--r--sound/soc/codecs/wm2200.c277
-rw-r--r--sound/soc/codecs/wm5100.c10
-rw-r--r--sound/soc/codecs/wm5102.c144
-rw-r--r--sound/soc/codecs/wm5110.c75
-rw-r--r--sound/soc/codecs/wm8350.c10
-rw-r--r--sound/soc/codecs/wm8400.c20
-rw-r--r--sound/soc/codecs/wm8510.c17
-rw-r--r--sound/soc/codecs/wm8523.c8
-rw-r--r--sound/soc/codecs/wm8711.c14
-rw-r--r--sound/soc/codecs/wm8727.c6
-rw-r--r--sound/soc/codecs/wm8728.c14
-rw-r--r--sound/soc/codecs/wm8731.c14
-rw-r--r--sound/soc/codecs/wm8737.c14
-rw-r--r--sound/soc/codecs/wm8741.c10
-rw-r--r--sound/soc/codecs/wm8750.c100
-rw-r--r--sound/soc/codecs/wm8753.c47
-rw-r--r--sound/soc/codecs/wm8770.c223
-rw-r--r--sound/soc/codecs/wm8776.c14
-rw-r--r--sound/soc/codecs/wm8782.c6
-rw-r--r--sound/soc/codecs/wm8804.c31
-rw-r--r--sound/soc/codecs/wm8900.c14
-rw-r--r--sound/soc/codecs/wm8903.c8
-rw-r--r--sound/soc/codecs/wm8904.c8
-rw-r--r--sound/soc/codecs/wm8940.c8
-rw-r--r--sound/soc/codecs/wm8955.c19
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c79
-rw-r--r--sound/soc/codecs/wm8960.c10
-rw-r--r--sound/soc/codecs/wm8961.c8
-rw-r--r--sound/soc/codecs/wm8962.c32
-rw-r--r--sound/soc/codecs/wm8971.c88
-rw-r--r--sound/soc/codecs/wm8974.c8
-rw-r--r--sound/soc/codecs/wm8978.c24
-rw-r--r--sound/soc/codecs/wm8983.c14
-rw-r--r--sound/soc/codecs/wm8985.c44
-rw-r--r--sound/soc/codecs/wm8988.c28
-rw-r--r--sound/soc/codecs/wm8990.c8
-rw-r--r--sound/soc/codecs/wm8991.c8
-rw-r--r--sound/soc/codecs/wm8993.c22
-rw-r--r--sound/soc/codecs/wm8994.c349
-rw-r--r--sound/soc/codecs/wm8994.h13
-rw-r--r--sound/soc/codecs/wm8995.c54
-rw-r--r--sound/soc/codecs/wm8996.c8
-rw-r--r--sound/soc/codecs/wm9081.c30
-rw-r--r--sound/soc/codecs/wm9090.c24
-rw-r--r--sound/soc/codecs/wm9705.c6
-rw-r--r--sound/soc/codecs/wm9712.c6
-rw-r--r--sound/soc/codecs/wm9713.c6
-rw-r--r--sound/soc/codecs/wm_adsp.c699
-rw-r--r--sound/soc/codecs/wm_adsp.h59
-rw-r--r--sound/soc/codecs/wmfw.h128
-rw-r--r--sound/soc/davinci/davinci-evm.c5
-rw-r--r--sound/soc/davinci/davinci-mcasp.c152
-rw-r--r--sound/soc/davinci/davinci-mcasp.h15
-rw-r--r--sound/soc/davinci/davinci-pcm.c53
-rw-r--r--sound/soc/davinci/davinci-pcm.h2
-rw-r--r--sound/soc/fsl/Kconfig20
-rw-r--r--sound/soc/fsl/Makefile14
-rw-r--r--sound/soc/fsl/eukrea-tlv320.c6
-rw-r--r--sound/soc/fsl/fsl_dma.c6
-rw-r--r--sound/soc/fsl/fsl_ssi.c2
-rw-r--r--sound/soc/fsl/imx-audmux.c8
-rw-r--r--sound/soc/fsl/imx-mc13783.c6
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c6
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c6
-rw-r--r--sound/soc/fsl/imx-pcm.c4
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c7
-rw-r--r--sound/soc/fsl/imx-ssi.c4
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c8
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c8
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c4
-rw-r--r--sound/soc/fsl/mx27vis-aic32x4.c6
-rw-r--r--sound/soc/fsl/p1022_ds.c4
-rw-r--r--sound/soc/fsl/p1022_rdk.c392
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c8
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c6
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c6
-rw-r--r--sound/soc/jz4740/qi_lb60.c6
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c22
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c241
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c6
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c6
-rw-r--r--sound/soc/kirkwood/kirkwood.h11
-rw-r--r--sound/soc/mid-x86/mfld_machine.c6
-rw-r--r--sound/soc/mxs/mxs-pcm.c4
-rw-r--r--sound/soc/mxs/mxs-saif.c8
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c8
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c6
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c6
-rw-r--r--sound/soc/omap/ams-delta.c6
-rw-r--r--sound/soc/omap/mcbsp.c11
-rw-r--r--sound/soc/omap/mcbsp.h10
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c10
-rw-r--r--sound/soc/omap/omap-dmic.c6
-rw-r--r--sound/soc/omap/omap-hdmi-card.c6
-rw-r--r--sound/soc/omap/omap-hdmi.c6
-rw-r--r--sound/soc/omap/omap-mcbsp.c11
-rw-r--r--sound/soc/omap/omap-mcpdm.c6
-rw-r--r--sound/soc/omap/omap-pcm.c6
-rw-r--r--sound/soc/omap/omap-twl4030.c6
-rw-r--r--sound/soc/omap/zoom2.c7
-rw-r--r--sound/soc/pxa/brownstone.c6
-rw-r--r--sound/soc/pxa/corgi.c6
-rw-r--r--sound/soc/pxa/e740_wm9705.c6
-rw-r--r--sound/soc/pxa/e750_wm9705.c6
-rw-r--r--sound/soc/pxa/e800_wm9712.c6
-rw-r--r--sound/soc/pxa/hx4700.c6
-rw-r--r--sound/soc/pxa/imote2.c6
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c6
-rw-r--r--sound/soc/pxa/mmp-pcm.c6
-rw-r--r--sound/soc/pxa/mmp-sspa.c6
-rw-r--r--sound/soc/pxa/palm27x.c4
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa-ssp.c6
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c8
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c4
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c6
-rw-r--r--sound/soc/pxa/tosa.c6
-rw-r--r--sound/soc/pxa/ttc-dkb.c6
-rw-r--r--sound/soc/s6000/s6000-i2s.c6
-rw-r--r--sound/soc/s6000/s6000-pcm.c6
-rw-r--r--sound/soc/samsung/ac97.c22
-rw-r--r--sound/soc/samsung/bells.c228
-rw-r--r--sound/soc/samsung/dma.c24
-rw-r--r--sound/soc/samsung/dma.h3
-rw-r--r--sound/soc/samsung/goni_wm8994.c2
-rw-r--r--sound/soc/samsung/h1940_uda1380.c2
-rw-r--r--sound/soc/samsung/i2s.c33
-rw-r--r--sound/soc/samsung/idma.c6
-rw-r--r--sound/soc/samsung/jive_wm8750.c2
-rw-r--r--sound/soc/samsung/littlemill.c10
-rw-r--r--sound/soc/samsung/ln2440sbc_alc650.c2
-rw-r--r--sound/soc/samsung/lowland.c8
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c2
-rw-r--r--sound/soc/samsung/pcm.c27
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c2
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c26
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c26
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c6
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_hermes.c6
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c6
-rw-r--r--sound/soc/samsung/s3c24xx_uda134x.c2
-rw-r--r--sound/soc/samsung/smartq_wm8987.c2
-rw-r--r--sound/soc/samsung/smdk2443_wm9710.c2
-rw-r--r--sound/soc/samsung/smdk_spdif.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580.c6
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c8
-rw-r--r--sound/soc/samsung/smdk_wm8994.c10
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c8
-rw-r--r--sound/soc/samsung/smdk_wm9713.c2
-rw-r--r--sound/soc/samsung/spdif.c28
-rw-r--r--sound/soc/samsung/speyside.c8
-rw-r--r--sound/soc/samsung/tobermory.c8
-rw-r--r--sound/soc/sh/dma-sh7760.c6
-rw-r--r--sound/soc/sh/fsi.c550
-rw-r--r--sound/soc/sh/hac.c6
-rw-r--r--sound/soc/sh/siu_dai.c6
-rw-r--r--sound/soc/sh/ssi.c6
-rw-r--r--sound/soc/soc-cache.c10
-rw-r--r--sound/soc/soc-core.c243
-rw-r--r--sound/soc/soc-dapm.c134
-rw-r--r--sound/soc/soc-dmaengine-pcm.c2
-rw-r--r--sound/soc/soc-jack.c16
-rw-r--r--sound/soc/soc-pcm.c195
-rw-r--r--sound/soc/soc-utils.c6
-rw-r--r--sound/soc/spear/spear_pcm.c6
-rw-r--r--sound/soc/tegra/tegra20_das.c8
-rw-r--r--sound/soc/tegra/tegra20_i2s.c10
-rw-r--r--sound/soc/tegra/tegra20_spdif.c8
-rw-r--r--sound/soc/tegra/tegra30_ahub.c14
-rw-r--r--sound/soc/tegra/tegra30_i2s.c10
-rw-r--r--sound/soc/tegra/tegra_alc5632.c8
-rw-r--r--sound/soc/tegra/tegra_pcm.c4
-rw-r--r--sound/soc/tegra/tegra_wm8753.c8
-rw-r--r--sound/soc/tegra/tegra_wm8903.c8
-rw-r--r--sound/soc/tegra/trimslice.c8
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c6
-rw-r--r--sound/soc/txx9/txx9aclc.c6
-rw-r--r--sound/soc/ux500/mop500.c14
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c59
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h1
-rw-r--r--sound/soc/ux500/ux500_pcm.c22
-rw-r--r--sound/soc/ux500/ux500_pcm.h3
-rw-r--r--sound/sparc/amd7930.c16
-rw-r--r--sound/sparc/cs4231.c38
-rw-r--r--sound/sparc/dbri.c28
-rw-r--r--sound/spi/at73c213.c20
-rw-r--r--sound/usb/6fire/chip.c4
-rw-r--r--sound/usb/6fire/comm.c5
-rw-r--r--sound/usb/6fire/comm.h2
-rw-r--r--sound/usb/6fire/control.c8
-rw-r--r--sound/usb/6fire/control.h2
-rw-r--r--sound/usb/6fire/firmware.h2
-rw-r--r--sound/usb/6fire/midi.c2
-rw-r--r--sound/usb/6fire/midi.h2
-rw-r--r--sound/usb/6fire/pcm.c11
-rw-r--r--sound/usb/6fire/pcm.h2
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/caiaq/control.c8
-rw-r--r--sound/usb/caiaq/device.c6
-rw-r--r--sound/usb/card.c7
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/endpoint.c53
-rw-r--r--sound/usb/endpoint.h5
-rw-r--r--sound/usb/format.c10
-rw-r--r--sound/usb/midi.c91
-rw-r--r--sound/usb/mixer.c74
-rw-r--r--sound/usb/mixer.h1
-rw-r--r--sound/usb/mixer_quirks.c223
-rw-r--r--sound/usb/pcm.c175
-rw-r--r--sound/usb/quirks-table.h198
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--sound/usb/stream.c230
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--tools/firewire/nosy-dump.c4
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/virtio/virtio_test.c2
-rw-r--r--usr/gen_init_cpio.c1
2683 files changed, 131408 insertions, 62494 deletions
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
index c2a270b45b03..833fd59926a7 100644
--- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
@@ -8,3 +8,41 @@ Description: The integer value of this attribute ranges from 0-4.
When written, this file sets the number of the startup profile
and the mouse activates this profile immediately.
Please use actual_profile, it does the same thing.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
+Date: October 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When read, this file returns the raw integer version number of the
+ firmware reported by the mouse. Using the integer value eases
+ further usage in other programs. To receive the real version
+ number the decimal point has to be shifted 2 positions to the
+ left. E.g. a returned value of 121 means 1.21
+ This file is readonly.
+ Please read binary attribute info which contains firmware version.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_buttons holds information about button layout.
+ When read, these files return the respective profile buttons.
+ The returned data is 77 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_buttons instead.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_settings holds information like resolution, sensitivity
+ and light effects.
+ When read, these files return the respective profile settings.
+ The returned data is 43 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_settings instead.
+Users: http://roccat.sourceforge.net \ No newline at end of file
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
new file mode 100644
index 000000000000..4a98e02b6c6a
--- /dev/null
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
@@ -0,0 +1,66 @@
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The integer value of this attribute ranges from 1-4.
+ When read, this attribute returns the number of the active
+ cpi level.
+ This file is readonly.
+ Has never been used. If bookkeeping is done, it's done in userland tools.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The integer value of this attribute ranges from 1-10.
+ When read, this attribute returns the number of the actual
+ sensitivity in x direction.
+ This file is readonly.
+ Has never been used. If bookkeeping is done, it's done in userland tools.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The integer value of this attribute ranges from 1-10.
+ When read, this attribute returns the number of the actual
+ sensitivity in y direction.
+ This file is readonly.
+ Has never been used. If bookkeeping is done, it's done in userland tools.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When read, this file returns the raw integer version number of the
+ firmware reported by the mouse. Using the integer value eases
+ further usage in other programs. To receive the real version
+ number the decimal point has to be shifted 2 positions to the
+ left. E.g. a returned value of 121 means 1.21
+ This file is readonly.
+ Obsoleted by binary sysfs attribute "info".
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_buttons holds information about button layout.
+ When read, these files return the respective profile buttons.
+ The returned data is 23 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_buttons instead.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
+Date: January 2011
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_settings holds information like resolution, sensitivity
+ and light effects.
+ When read, these files return the respective profile settings.
+ The returned data is 16 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_settings instead.
+Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
new file mode 100644
index 000000000000..87ac87e9556d
--- /dev/null
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
@@ -0,0 +1,73 @@
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: It is possible to switch the cpi setting of the mouse with the
+ press of a button.
+ When read, this file returns the raw number of the actual cpi
+ setting reported by the mouse. This number has to be further
+ processed to receive the real dpi value.
+
+ VALUE DPI
+ 1 400
+ 2 800
+ 4 1600
+
+ This file is readonly.
+ Has never been used. If bookkeeping is done, it's done in userland tools.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When read, this file returns the number of the actual profile in
+ range 0-4.
+ This file is readonly.
+ Please use binary attribute "settings" which provides this information.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When read, this file returns the raw integer version number of the
+ firmware reported by the mouse. Using the integer value eases
+ further usage in other programs. To receive the real version
+ number the decimal point has to be shifted 2 positions to the
+ left. E.g. a returned value of 138 means 1.38
+ This file is readonly.
+ Please use binary attribute "info" which provides this information.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_buttons holds information about button layout.
+ When read, these files return the respective profile buttons.
+ The returned data is 19 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_buttons instead.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The mouse can store 5 profiles which can be switched by the
+ press of a button. A profile is split in settings and buttons.
+ profile_settings holds information like resolution, sensitivity
+ and light effects.
+ When read, these files return the respective profile settings.
+ The returned data is 13 bytes in size.
+ This file is readonly.
+ Write control to select profile and read profile_settings instead.
+Users: http://roccat.sourceforge.net
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
+Date: August 2010
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: The integer value of this attribute ranges from 0-4.
+ When read, this attribute returns the number of the profile
+ that's active when the mouse is powered on.
+ This file is readonly.
+ Please use binary attribute "settings" which provides this information.
+Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg
index 7e7e07a82e0e..bb820be48179 100644
--- a/Documentation/ABI/testing/dev-kmsg
+++ b/Documentation/ABI/testing/dev-kmsg
@@ -92,7 +92,7 @@ Description: The /dev/kmsg character device node provides userspace access
The flags field carries '-' by default. A 'c' indicates a
fragment of a line. All following fragments are flagged with
'+'. Note, that these hints about continuation lines are not
- neccessarily correct, and the stream could be interleaved with
+ necessarily correct, and the stream could be interleaved with
unrelated messages, but merging the lines in the output
usually produces better human readable results. A similar
logic is used internally when messages are printed to the
diff --git a/Documentation/ABI/testing/sysfs-bus-mdio b/Documentation/ABI/testing/sysfs-bus-mdio
new file mode 100644
index 000000000000..6349749ebc29
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-mdio
@@ -0,0 +1,9 @@
+What: /sys/bus/mdio_bus/devices/.../phy_id
+Date: November 2012
+KernelVersion: 3.8
+Contact: netdev@vger.kernel.org
+Description:
+ This attribute contains the 32-bit PHY Identifier as reported
+ by the device during bus enumeration, encoded in hexadecimal.
+ This ID is used to match the device with the appropriate
+ driver.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index dff1f48d252d..1ce5ae329c04 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -222,3 +222,37 @@ Description:
satisfied too. Reading this attribute will show the current
value of d3cold_allowed bit. Writing this attribute will set
the value of d3cold_allowed bit.
+
+What: /sys/bus/pci/devices/.../sriov_totalvfs
+Date: November 2012
+Contact: Donald Dutile <ddutile@redhat.com>
+Description:
+ This file appears when a physical PCIe device supports SR-IOV.
+ Userspace applications can read this file to determine the
+ maximum number of Virtual Functions (VFs) a PCIe physical
+ function (PF) can support. Typically, this is the value reported
+ in the PF's SR-IOV extended capability structure's TotalVFs
+ element. Drivers have the ability at probe time to reduce the
+ value read from this file via the pci_sriov_set_totalvfs()
+ function.
+
+What: /sys/bus/pci/devices/.../sriov_numvfs
+Date: November 2012
+Contact: Donald Dutile <ddutile@redhat.com>
+Description:
+ This file appears when a physical PCIe device supports SR-IOV.
+ Userspace applications can read and write to this file to
+ determine and control the enablement or disablement of Virtual
+ Functions (VFs) on the physical function (PF). A read of this
+ file will return the number of VFs that are enabled on this PF.
+ A number written to this file will enable the specified
+ number of VFs. A userspace application would typically read the
+ file and check that the value is zero, and then write the number
+ of VFs that should be enabled on the PF; the value written
+ should be less than or equal to the value in the sriov_totalvfs
+ file. A userspace application wanting to disable the VFs would
+ write a zero to this file. The core ensures that valid values
+ are written to this file, and returns errors when values are not
+ valid. For example, writing a 2 to this file when sriov_numvfs
+ is not 0 and not 2 already will return an error. Writing a 10
+ when the value of sriov_totalvfs is 8 will return an error.
diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv
index 38dd762def4b..bdc00707c751 100644
--- a/Documentation/ABI/testing/sysfs-class-net-batman-adv
+++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv
@@ -1,4 +1,10 @@
+What: /sys/class/net/<iface>/batman-adv/iface_status
+Date: May 2010
+Contact: Marek Lindner <lindner_marek@yahoo.de>
+Description:
+ Indicates the status of <iface> as it is seen by batman.
+
What: /sys/class/net/<iface>/batman-adv/mesh_iface
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
@@ -7,8 +13,3 @@ Description:
displays the batman mesh interface this <iface>
currently is associated with.
-What: /sys/class/net/<iface>/batman-adv/iface_status
-Date: May 2010
-Contact: Marek Lindner <lindner_marek@yahoo.de>
-Description:
- Indicates the status of <iface> as it is seen by batman.
diff --git a/Documentation/ABI/testing/sysfs-class-net-grcan b/Documentation/ABI/testing/sysfs-class-net-grcan
new file mode 100644
index 000000000000..f418c92ca555
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-net-grcan
@@ -0,0 +1,35 @@
+
+What: /sys/class/net/<iface>/grcan/enable0
+Date: October 2012
+KernelVersion: 3.8
+Contact: Andreas Larsson <andreas@gaisler.com>
+Description:
+ Hardware configuration of physical interface 0. This file reads
+ and writes the "Enable 0" bit of the configuration register.
+ Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+ core library documentation for details. The default value is 0
+ or set by the module parameter grcan.enable0 and can be read at
+ /sys/module/grcan/parameters/enable0.
+
+What: /sys/class/net/<iface>/grcan/enable1
+Date: October 2012
+KernelVersion: 3.8
+Contact: Andreas Larsson <andreas@gaisler.com>
+Description:
+ Hardware configuration of physical interface 1. This file reads
+ and writes the "Enable 1" bit of the configuration register.
+ Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+ core library documentation for details. The default value is 0
+ or set by the module parameter grcan.enable1 and can be read at
+ /sys/module/grcan/parameters/enable1.
+
+What: /sys/class/net/<iface>/grcan/select
+Date: October 2012
+KernelVersion: 3.8
+Contact: Andreas Larsson <andreas@gaisler.com>
+Description:
+ Configuration of which physical interface to be used. Possible
+ values: 0 or 1. See the GRCAN chapter of the GRLIB IP core
+ library documentation for details. The default value is 0 or is
+ set by the module parameter grcan.select and can be read at
+ /sys/module/grcan/parameters/select.
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index c81fe89c4c46..bc41da61608d 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -6,6 +6,14 @@ Description:
Indicates whether the batman protocol messages of the
mesh <mesh_iface> shall be aggregated or not.
+What: /sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date: May 2011
+Contact: Antonio Quartulli <ordex@autistici.org>
+Description:
+ Indicates whether the data traffic going from a
+ wireless client to another wireless client will be
+ silently dropped.
+
What: /sys/class/net/<mesh_iface>/mesh/bonding
Date: June 2010
Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
@@ -31,14 +39,6 @@ Description:
mesh will be fragmented or silently discarded if the
packet size exceeds the outgoing interface MTU.
-What: /sys/class/net/<mesh_iface>/mesh/ap_isolation
-Date: May 2011
-Contact: Antonio Quartulli <ordex@autistici.org>
-Description:
- Indicates whether the data traffic going from a
- wireless client to another wireless client will be
- silently dropped.
-
What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
Date: October 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
@@ -60,6 +60,13 @@ Description:
Defines the selection criteria this node will use
to choose a gateway if gw_mode was set to 'client'.
+What: /sys/class/net/<mesh_iface>/mesh/hop_penalty
+Date: Oct 2010
+Contact: Linus Lüssing <linus.luessing@web.de>
+Description:
+ Defines the penalty which will be applied to an
+ originator message's tq-field on every hop.
+
What: /sys/class/net/<mesh_iface>/mesh/orig_interval
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
@@ -67,19 +74,12 @@ Description:
Defines the interval in milliseconds in which batman
sends its protocol messages.
-What: /sys/class/net/<mesh_iface>/mesh/hop_penalty
-Date: Oct 2010
-Contact: Linus Lüssing <linus.luessing@web.de>
-Description:
- Defines the penalty which will be applied to an
- originator message's tq-field on every hop.
-
-What: /sys/class/net/<mesh_iface>/mesh/routing_algo
-Date: Dec 2011
-Contact: Marek Lindner <lindner_marek@yahoo.de>
+What: /sys/class/net/<mesh_iface>/mesh/routing_algo
+Date: Dec 2011
+Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
- Defines the routing procotol this mesh instance
- uses to find the optimal paths through the mesh.
+ Defines the routing procotol this mesh instance
+ uses to find the optimal paths through the mesh.
What: /sys/class/net/<mesh_iface>/mesh/vis_mode
Date: May 2010
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 7fc2997b23a6..9d43e7670841 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -164,7 +164,7 @@ Contact: Rafael J. Wysocki <rjw@sisk.pl>
Description:
The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
contains the total time the device has been preventing
- opportunistic transitions to sleep states from occuring.
+ opportunistic transitions to sleep states from occurring.
This attribute is read-only. If the device is not enabled to
wake up the system from sleep states, this attribute is not
present.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
index 189dc43891bf..9eca5a182e64 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
@@ -117,6 +117,14 @@ Description: When written, this file lets one store macros with max 500
which profile and key to read.
Users: http://roccat.sourceforge.net
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/reset
+Date: November 2012
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When written, this file lets one reset the device.
+ The data has to be 3 bytes long.
+ This file is writeonly.
+Users: http://roccat.sourceforge.net
+
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control
Date: June 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
index 65e6e5dd67e8..7bd776f9c3c7 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
@@ -9,15 +9,12 @@ Description: The integer value of this attribute ranges from 0-4.
and the mouse activates this profile immediately.
Users: http://roccat.sourceforge.net
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
-Date: October 2010
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
+Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 121 means 1.21
- This file is readonly.
+Description: When read, this file returns general data like firmware version.
+ When written, the device can be reset.
+ The data is 8 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
@@ -42,18 +39,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 77 bytes in size.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
@@ -68,19 +55,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 43 bytes in size.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
@@ -104,9 +80,9 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
Date: October 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When written a calibration process for the tracking control unit
- can be initiated/cancelled.
- The data has to be 3 bytes long.
- This file is writeonly.
+ can be initiated/cancelled. Also lets one read/write sensor
+ registers.
+ The data has to be 4 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
index 20f937c9d84f..a10404f15a54 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
@@ -1,12 +1,3 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
-Date: January 2011
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The integer value of this attribute ranges from 1-4.
- When read, this attribute returns the number of the active
- cpi level.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -18,33 +9,12 @@ Description: The integer value of this attribute ranges from 0-4.
active when the mouse is powered on.
Users: http://roccat.sourceforge.net
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
-Date: January 2011
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
+Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The integer value of this attribute ranges from 1-10.
- When read, this attribute returns the number of the actual
- sensitivity in x direction.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
-Date: January 2011
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The integer value of this attribute ranges from 1-10.
- When read, this attribute returns the number of the actual
- sensitivity in y direction.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
-Date: January 2011
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 121 means 1.21
- This file is readonly.
+Description: When read, this file returns general data like firmware version.
+ When written, the device can be reset.
+ The data is 6 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
@@ -58,18 +28,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
-Date: January 2011
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 23 bytes in size.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
@@ -84,17 +44,6 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
-Date: January 2011
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 16 bytes in size.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
new file mode 100644
index 000000000000..31c6c4c8ba2b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
@@ -0,0 +1,7 @@
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
+Date: October 2012
+Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
+Description: When written, cpi, button and light settings can be configured.
+ When read, actual cpi setting and sensor data are returned.
+ The data has to be 8 bytes long.
+Users: http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
index 3f8de50e4ff1..9fa9de30d14b 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
@@ -1,37 +1,9 @@
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: It is possible to switch the cpi setting of the mouse with the
- press of a button.
- When read, this file returns the raw number of the actual cpi
- setting reported by the mouse. This number has to be further
- processed to receive the real dpi value.
-
- VALUE DPI
- 1 400
- 2 800
- 4 1600
-
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
-Date: August 2010
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
+Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: When read, this file returns the number of the actual profile in
- range 0-4.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: When read, this file returns the raw integer version number of the
- firmware reported by the mouse. Using the integer value eases
- further usage in other programs. To receive the real version
- number the decimal point has to be shifted 2 positions to the
- left. E.g. a returned value of 138 means 1.38
- This file is readonly.
+Description: When read, this file returns general data like firmware version.
+ When written, the device can be reset.
+ The data is 6 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
@@ -46,19 +18,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_settings holds information like resolution, sensitivity
- and light effects.
- When read, these files return the respective profile settings.
- The returned data is 13 bytes in size.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
@@ -72,27 +33,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data.
Which profile to write is determined by the profile number
contained in the data.
- This file is writeonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The mouse can store 5 profiles which can be switched by the
- press of a button. A profile is split in settings and buttons.
- profile_buttons holds information about button layout.
- When read, these files return the respective profile buttons.
- The returned data is 19 bytes in size.
- This file is readonly.
-Users: http://roccat.sourceforge.net
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
-Date: August 2010
-Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
-Description: The integer value of this attribute ranges from 0-4.
- When read, this attribute returns the number of the profile
- that's active when the mouse is powered on.
- This file is readonly.
+ Before reading this file, control has to be written to select
+ which profile to read.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
index b42922cf6b1f..f1e02a98bd9d 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
@@ -40,8 +40,8 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
Date: Mai 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns general data like firmware version.
+ When written, the device can be reset.
The data is 8 bytes long.
- This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
@@ -74,4 +74,3 @@ Description: The mouse has a Avago ADNS-3090 sensor.
This file allows reading and writing of the mouse sensors registers.
The data has to be 4 bytes long.
Users: http://roccat.sourceforge.net
-
diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
index 97a003ee058b..7d1435bc976c 100644
--- a/Documentation/ABI/testing/sysfs-driver-ppi
+++ b/Documentation/ABI/testing/sysfs-driver-ppi
@@ -5,7 +5,7 @@ Contact: xiaoyan.zhang@intel.com
Description:
This folder includes the attributes related with PPI (Physical
Presence Interface). Only if TPM is supported by BIOS, this
- folder makes sence. The folder path can be got by command
+ folder makes sense. The folder path can be got by command
'find /sys/ -name 'pcrs''. For the detail information of PPI,
please refer to the PPI specification from
http://www.trustedcomputinggroup.org/
diff --git a/Documentation/ABI/testing/sysfs-profiling b/Documentation/ABI/testing/sysfs-profiling
index b02d8b8c173a..8a8e466eb2c0 100644
--- a/Documentation/ABI/testing/sysfs-profiling
+++ b/Documentation/ABI/testing/sysfs-profiling
@@ -1,13 +1,13 @@
-What: /sys/kernel/profile
+What: /sys/kernel/profiling
Date: September 2008
Contact: Dave Hansen <dave@linux.vnet.ibm.com>
Description:
- /sys/kernel/profile is the runtime equivalent
+ /sys/kernel/profiling is the runtime equivalent
of the boot-time profile= option.
You can get the same effect running:
- echo 2 > /sys/kernel/profile
+ echo 2 > /sys/kernel/profiling
as you would by issuing profile=2 on the boot
command line.
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index cab4ec58e46e..fb32aead5a0b 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -433,9 +433,9 @@
/* chip-specific constructor
* (see "Management of Cards and Components")
*/
- static int __devinit snd_mychip_create(struct snd_card *card,
- struct pci_dev *pci,
- struct mychip **rchip)
+ static int snd_mychip_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct mychip **rchip)
{
struct mychip *chip;
int err;
@@ -475,8 +475,8 @@
}
/* constructor -- see "Constructor" sub-section */
- static int __devinit snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -526,7 +526,7 @@
}
/* destructor -- see the "Destructor" sub-section */
- static void __devexit snd_mychip_remove(struct pci_dev *pci)
+ static void snd_mychip_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -542,9 +542,8 @@
<para>
The real constructor of PCI drivers is the <function>probe</function> callback.
The <function>probe</function> callback and other component-constructors which are called
- from the <function>probe</function> callback should be defined with
- the <parameter>__devinit</parameter> prefix. You
- cannot use the <parameter>__init</parameter> prefix for them,
+ from the <function>probe</function> callback cannot be used with
+ the <parameter>__init</parameter> prefix
because any PCI device could be a hotplug device.
</para>
@@ -728,7 +727,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static void __devexit snd_mychip_remove(struct pci_dev *pci)
+ static void snd_mychip_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1059,14 +1058,6 @@
</para>
<para>
- As further notes, the destructors (both
- <function>snd_mychip_dev_free</function> and
- <function>snd_mychip_free</function>) cannot be defined with
- the <parameter>__devexit</parameter> prefix, because they may be
- called from the constructor, too, at the false path.
- </para>
-
- <para>
For a device which allows hotplugging, you can use
<function>snd_card_free_when_closed</function>. This one will
postpone the destruction until all devices are closed.
@@ -1120,9 +1111,9 @@
}
/* chip-specific constructor */
- static int __devinit snd_mychip_create(struct snd_card *card,
- struct pci_dev *pci,
- struct mychip **rchip)
+ static int snd_mychip_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct mychip **rchip)
{
struct mychip *chip;
int err;
@@ -1200,7 +1191,7 @@
.name = KBUILD_MODNAME,
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
- .remove = __devexit_p(snd_mychip_remove),
+ .remove = snd_mychip_remove,
};
/* module initialization */
@@ -1465,11 +1456,6 @@
</para>
<para>
- Again, remember that you cannot
- use the <parameter>__devexit</parameter> prefix for this destructor.
- </para>
-
- <para>
We didn't implement the hardware disabling part in the above.
If you need to do this, please note that the destructor may be
called even before the initialization of the chip is completed.
@@ -1619,7 +1605,7 @@
.name = KBUILD_MODNAME,
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
- .remove = __devexit_p(snd_mychip_remove),
+ .remove = snd_mychip_remove,
};
]]>
</programlisting>
@@ -1630,11 +1616,7 @@
The <structfield>probe</structfield> and
<structfield>remove</structfield> functions have already
been defined in the previous sections.
- The <structfield>remove</structfield> function should
- be defined with the
- <function>__devexit_p()</function> macro, so that it's not
- defined for built-in (and non-hot-pluggable) case. The
- <structfield>name</structfield>
+ The <structfield>name</structfield>
field is the name string of this device. Note that you must not
use a slash <quote>/</quote> in this string.
</para>
@@ -1665,9 +1647,7 @@
<para>
Note that these module entries are tagged with
<parameter>__init</parameter> and
- <parameter>__exit</parameter> prefixes, not
- <parameter>__devinit</parameter> nor
- <parameter>__devexit</parameter>.
+ <parameter>__exit</parameter> prefixes.
</para>
<para>
@@ -1918,7 +1898,7 @@
*/
/* create a pcm device */
- static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+ static int snd_mychip_new_pcm(struct mychip *chip)
{
struct snd_pcm *pcm;
int err;
@@ -1957,7 +1937,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+ static int snd_mychip_new_pcm(struct mychip *chip)
{
struct snd_pcm *pcm;
int err;
@@ -2124,7 +2104,7 @@
....
}
- static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+ static int snd_mychip_new_pcm(struct mychip *chip)
{
struct snd_pcm *pcm;
....
@@ -3399,7 +3379,7 @@ struct _snd_pcm_runtime {
<title>Definition of a Control</title>
<programlisting>
<![CDATA[
- static struct snd_kcontrol_new my_control __devinitdata = {
+ static struct snd_kcontrol_new my_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -3415,13 +3395,6 @@ struct _snd_pcm_runtime {
</para>
<para>
- Most likely the control is created via
- <function>snd_ctl_new1()</function>, and in such a case, you can
- add the <parameter>__devinitdata</parameter> prefix to the
- definition as above.
- </para>
-
- <para>
The <structfield>iface</structfield> field specifies the control
type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
is usually <constant>MIXER</constant>.
@@ -3847,10 +3820,8 @@ struct _snd_pcm_runtime {
<para>
<function>snd_ctl_new1()</function> allocates a new
- <structname>snd_kcontrol</structname> instance (that's why the definition
- of <parameter>my_control</parameter> can be with
- the <parameter>__devinitdata</parameter>
- prefix), and <function>snd_ctl_add</function> assigns the given
+ <structname>snd_kcontrol</structname> instance,
+ and <function>snd_ctl_add</function> assigns the given
control component to the card.
</para>
</section>
@@ -3896,7 +3867,7 @@ struct _snd_pcm_runtime {
<![CDATA[
static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
- static struct snd_kcontrol_new my_control __devinitdata = {
+ static struct snd_kcontrol_new my_control = {
...
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -5761,8 +5732,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int __devinit snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
....
struct snd_card *card;
@@ -5787,8 +5758,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int __devinit snd_mychip_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+ static int snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
....
struct snd_card *card;
@@ -5825,7 +5796,7 @@ struct _snd_pcm_runtime {
.name = KBUILD_MODNAME,
.id_table = snd_my_ids,
.probe = snd_my_probe,
- .remove = __devexit_p(snd_my_remove),
+ .remove = snd_my_remove,
#ifdef CONFIG_PM
.suspend = snd_my_suspend,
.resume = snd_my_resume,
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 59c080f084ef..a9f288ff54f9 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -462,7 +462,7 @@ Differences between the kernel community and corporate structures
The kernel community works differently than most traditional corporate
development environments. Here are a list of things that you can try to
-do to try to avoid problems:
+do to avoid problems:
Good things to say regarding your proposed changes:
- "This solves multiple problems."
- "This deletes 2000 lines of code."
diff --git a/Documentation/PCI/pci-iov-howto.txt b/Documentation/PCI/pci-iov-howto.txt
index fc73ef5d65b8..cfaca7e69893 100644
--- a/Documentation/PCI/pci-iov-howto.txt
+++ b/Documentation/PCI/pci-iov-howto.txt
@@ -2,6 +2,9 @@
Copyright (C) 2009 Intel Corporation
Yu Zhao <yu.zhao@intel.com>
+ Update: November 2012
+ -- sysfs-based SRIOV enable-/disable-ment
+ Donald Dutile <ddutile@redhat.com>
1. Overview
@@ -24,10 +27,21 @@ real existing PCI device.
2.1 How can I enable SR-IOV capability
-The device driver (PF driver) will control the enabling and disabling
-of the capability via API provided by SR-IOV core. If the hardware
-has SR-IOV capability, loading its PF driver would enable it and all
-VFs associated with the PF.
+Multiple methods are available for SR-IOV enablement.
+In the first method, the device driver (PF driver) will control the
+enabling and disabling of the capability via API provided by SR-IOV core.
+If the hardware has SR-IOV capability, loading its PF driver would
+enable it and all VFs associated with the PF. Some PF drivers require
+a module parameter to be set to determine the number of VFs to enable.
+In the second method, a write to the sysfs file sriov_numvfs will
+enable and disable the VFs associated with a PCIe PF. This method
+enables per-PF, VF enable/disable values versus the first method,
+which applies to all PFs of the same device. Additionally, the
+PCI SRIOV core support ensures that enable/disable operations are
+valid to reduce duplication in multiple drivers for the same
+checks, e.g., check numvfs == 0 if enabling VFs, ensure
+numvfs <= totalvfs.
+The second method is the recommended method for new/future VF devices.
2.2 How can I use the Virtual Functions
@@ -40,13 +54,22 @@ requires device driver that is same as a normal PCI device's.
3.1 SR-IOV API
To enable SR-IOV capability:
+(a) For the first method, in the driver:
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
'nr_virtfn' is number of VFs to be enabled.
+(b) For the second method, from sysfs:
+ echo 'nr_virtfn' > \
+ /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
To disable SR-IOV capability:
+(a) For the first method, in the driver:
void pci_disable_sriov(struct pci_dev *dev);
+(b) For the second method, from sysfs:
+ echo 0 > \
+ /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
To notify SR-IOV core of Virtual Function Migration:
+(a) In the driver:
irqreturn_t pci_sriov_migration(struct pci_dev *dev);
3.2 Usage example
@@ -88,6 +111,22 @@ static void dev_shutdown(struct pci_dev *dev)
...
}
+static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
+{
+ if (numvfs > 0) {
+ ...
+ pci_enable_sriov(dev, numvfs);
+ ...
+ return numvfs;
+ }
+ if (numvfs == 0) {
+ ....
+ pci_disable_sriov(dev);
+ ...
+ return 0;
+ }
+}
+
static struct pci_driver dev_driver = {
.name = "SR-IOV Physical Function driver",
.id_table = dev_id_table,
@@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
.suspend = dev_suspend,
.resume = dev_resume,
.shutdown = dev_shutdown,
+ .sriov_configure = dev_sriov_configure,
};
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 6f706aca2049..f8ebcde43b17 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -51,7 +51,6 @@ int dbg;
int print_delays;
int print_io_accounting;
int print_task_context_switch_counts;
-__u64 stime, utime;
#define PRINTF(fmt, arg...) { \
if (dbg) { \
diff --git a/Documentation/bus-devices/ti-gpmc.txt b/Documentation/bus-devices/ti-gpmc.txt
new file mode 100644
index 000000000000..cc9ce57e0a26
--- /dev/null
+++ b/Documentation/bus-devices/ti-gpmc.txt
@@ -0,0 +1,122 @@
+GPMC (General Purpose Memory Controller):
+=========================================
+
+GPMC is an unified memory controller dedicated to interfacing external
+memory devices like
+ * Asynchronous SRAM like memories and application specific integrated
+ circuit devices.
+ * Asynchronous, synchronous, and page mode burst NOR flash devices
+ NAND flash
+ * Pseudo-SRAM devices
+
+GPMC is found on Texas Instruments SoC's (OMAP based)
+IP details: http://www.ti.com/lit/pdf/spruh73 section 7.1
+
+
+GPMC generic timing calculation:
+================================
+
+GPMC has certain timings that has to be programmed for proper
+functioning of the peripheral, while peripheral has another set of
+timings. To have peripheral work with gpmc, peripheral timings has to
+be translated to the form gpmc can understand. The way it has to be
+translated depends on the connected peripheral. Also there is a
+dependency for certain gpmc timings on gpmc clock frequency. Hence a
+generic timing routine was developed to achieve above requirements.
+
+Generic routine provides a generic method to calculate gpmc timings
+from gpmc peripheral timings. struct gpmc_device_timings fields has to
+be updated with timings from the datasheet of the peripheral that is
+connected to gpmc. A few of the peripheral timings can be fed either
+in time or in cycles, provision to handle this scenario has been
+provided (refer struct gpmc_device_timings definition). It may so
+happen that timing as specified by peripheral datasheet is not present
+in timing structure, in this scenario, try to correlate peripheral
+timing to the one available. If that doesn't work, try to add a new
+field as required by peripheral, educate generic timing routine to
+handle it, make sure that it does not break any of the existing.
+Then there may be cases where peripheral datasheet doesn't mention
+certain fields of struct gpmc_device_timings, zero those entries.
+
+Generic timing routine has been verified to work properly on
+multiple onenand's and tusb6010 peripherals.
+
+A word of caution: generic timing routine has been developed based
+on understanding of gpmc timings, peripheral timings, available
+custom timing routines, a kind of reverse engineering without
+most of the datasheets & hardware (to be exact none of those supported
+in mainline having custom timing routine) and by simulation.
+
+gpmc timing dependency on peripheral timings:
+[<gpmc_timing>: <peripheral timing1>, <peripheral timing2> ...]
+
+1. common
+cs_on: t_ceasu
+adv_on: t_avdasu, t_ceavd
+
+2. sync common
+sync_clk: clk
+page_burst_access: t_bacc
+clk_activation: t_ces, t_avds
+
+3. read async muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu, t_aavdh
+access: t_iaa, t_oe, t_ce, t_aa
+rd_cycle: t_rd_cycle, t_cez_r, t_oez
+
+4. read async non-muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu
+access: t_iaa, t_oe, t_ce, t_aa
+rd_cycle: t_rd_cycle, t_cez_r, t_oez
+
+5. read sync muxed
+adv_rd_off: t_avdp_r, t_avdh
+oe_on: t_oeasu, t_ach, cyc_aavdh_oe
+access: t_iaa, cyc_iaa, cyc_oe
+rd_cycle: t_cez_r, t_oez, t_ce_rdyz
+
+6. read sync non-muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu
+access: t_iaa, cyc_iaa, cyc_oe
+rd_cycle: t_cez_r, t_oez, t_ce_rdyz
+
+7. write async muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu, t_aavdh, cyc_aavhd_we
+we_off: t_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_wr_cycle
+
+8. write async non-muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu
+we_off: t_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_wr_cycle
+
+9. write sync muxed
+adv_wr_off: t_avdp_w, t_avdh
+we_on, wr_data_mux_bus: t_weasu, t_rdyo, t_aavdh, cyc_aavhd_we
+we_off: t_wpl, cyc_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_ce_rdyz
+
+10. write sync non-muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu, t_rdyo
+we_off: t_wpl, cyc_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_ce_rdyz
+
+
+Note: Many of gpmc timings are dependent on other gpmc timings (a few
+gpmc timings purely dependent on other gpmc timings, a reason that
+some of the gpmc timings are missing above), and it will result in
+indirect dependency of peripheral timings to gpmc timings other than
+mentioned above, refer timing routine for more details. To know what
+these peripheral timings correspond to, please see explanations in
+struct gpmc_device_timings definition. And for gpmc timings refer
+IP details (link above).
diff --git a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
index 6528e215c5fe..5216b419016a 100644
--- a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
+++ b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
@@ -4,14 +4,13 @@ Exynos processors include support for multiple power domains which are used
to gate power to one or more peripherals on the processor.
Required Properties:
-- compatiable: should be one of the following.
+- compatible: should be one of the following.
* samsung,exynos4210-pd - for exynos4210 type power domain.
- reg: physical base address of the controller and length of memory mapped
region.
-Optional Properties:
-- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
- state during boot and remains to be turned-off until explicitly turned-on.
+Node of a device using power domains must have a samsung,power-domain property
+defined with a phandle to respective power domain.
Example:
@@ -19,3 +18,11 @@ Example:
compatible = "samsung,exynos4210-pd";
reg = <0x10023C00 0x10>;
};
+
+Example of the node using power domain:
+
+ node {
+ /* ... */
+ samsung,power-domain = <&lcd0>;
+ /* ... */
+ };
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index ac9e7516756e..f79818711e83 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -41,6 +41,10 @@ i.MX6 Quad SABRE Smart Device Board
Required root node properties:
- compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+ - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
Generic i.MX boards
-------------------
diff --git a/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt
new file mode 100644
index 000000000000..37824fac688e
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt
@@ -0,0 +1,14 @@
+* Samsung SATA PHY Controller
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible : compatible list, contains "samsung,exynos5-sata-phy"
+- reg : <registers mapping>
+
+Example:
+ sata@ffe07000 {
+ compatible = "samsung,exynos5-sata-phy";
+ reg = <0xffe07000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/ata/exynos-sata.txt b/Documentation/devicetree/bindings/ata/exynos-sata.txt
new file mode 100644
index 000000000000..0849f1025e34
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/exynos-sata.txt
@@ -0,0 +1,17 @@
+* Samsung AHCI SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible : compatible list, contains "samsung,exynos5-sata"
+- interrupts : <interrupt mapping for SATA IRQ>
+- reg : <registers mapping>
+- samsung,sata-freq : <frequency in MHz>
+
+Example:
+ sata@ffe08000 {
+ compatible = "samsung,exynos5-sata";
+ reg = <0xffe08000 0x1000>;
+ interrupts = <115>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx25-clock.txt b/Documentation/devicetree/bindings/clock/imx25-clock.txt
new file mode 100644
index 000000000000..c2a3525ecb4e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx25-clock.txt
@@ -0,0 +1,162 @@
+* Clock bindings for Freescale i.MX25
+
+Required properties:
+- compatible: Should be "fsl,imx25-ccm"
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #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.MX25
+clocks and IDs.
+
+ Clock ID
+ ---------------------------
+ dummy 0
+ osc 1
+ mpll 2
+ upll 3
+ mpll_cpu_3_4 4
+ cpu_sel 5
+ cpu 6
+ ahb 7
+ usb_div 8
+ ipg 9
+ per0_sel 10
+ per1_sel 11
+ per2_sel 12
+ per3_sel 13
+ per4_sel 14
+ per5_sel 15
+ per6_sel 16
+ per7_sel 17
+ per8_sel 18
+ per9_sel 19
+ per10_sel 20
+ per11_sel 21
+ per12_sel 22
+ per13_sel 23
+ per14_sel 24
+ per15_sel 25
+ per0 26
+ per1 27
+ per2 28
+ per3 29
+ per4 30
+ per5 31
+ per6 32
+ per7 33
+ per8 34
+ per9 35
+ per10 36
+ per11 37
+ per12 38
+ per13 39
+ per14 40
+ per15 41
+ csi_ipg_per 42
+ epit_ipg_per 43
+ esai_ipg_per 44
+ esdhc1_ipg_per 45
+ esdhc2_ipg_per 46
+ gpt_ipg_per 47
+ i2c_ipg_per 48
+ lcdc_ipg_per 49
+ nfc_ipg_per 50
+ owire_ipg_per 51
+ pwm_ipg_per 52
+ sim1_ipg_per 53
+ sim2_ipg_per 54
+ ssi1_ipg_per 55
+ ssi2_ipg_per 56
+ uart_ipg_per 57
+ ata_ahb 58
+ reserved 59
+ csi_ahb 60
+ emi_ahb 61
+ esai_ahb 62
+ esdhc1_ahb 63
+ esdhc2_ahb 64
+ fec_ahb 65
+ lcdc_ahb 66
+ rtic_ahb 67
+ sdma_ahb 68
+ slcdc_ahb 69
+ usbotg_ahb 70
+ reserved 71
+ reserved 72
+ reserved 73
+ reserved 74
+ can1_ipg 75
+ can2_ipg 76
+ csi_ipg 77
+ cspi1_ipg 78
+ cspi2_ipg 79
+ cspi3_ipg 80
+ dryice_ipg 81
+ ect_ipg 82
+ epit1_ipg 83
+ epit2_ipg 84
+ reserved 85
+ esdhc1_ipg 86
+ esdhc2_ipg 87
+ fec_ipg 88
+ reserved 89
+ reserved 90
+ reserved 91
+ gpt1_ipg 92
+ gpt2_ipg 93
+ gpt3_ipg 94
+ gpt4_ipg 95
+ reserved 96
+ reserved 97
+ reserved 98
+ iim_ipg 99
+ reserved 100
+ reserved 101
+ kpp_ipg 102
+ lcdc_ipg 103
+ reserved 104
+ pwm1_ipg 105
+ pwm2_ipg 106
+ pwm3_ipg 107
+ pwm4_ipg 108
+ rngb_ipg 109
+ reserved 110
+ scc_ipg 111
+ sdma_ipg 112
+ sim1_ipg 113
+ sim2_ipg 114
+ slcdc_ipg 115
+ spba_ipg 116
+ ssi1_ipg 117
+ ssi2_ipg 118
+ tsc_ipg 119
+ uart1_ipg 120
+ uart2_ipg 121
+ uart3_ipg 122
+ uart4_ipg 123
+ uart5_ipg 124
+ reserved 125
+ wdt_ipg 126
+
+Examples:
+
+clks: ccm@53f80000 {
+ compatible = "fsl,imx25-ccm";
+ reg = <0x53f80000 0x4000>;
+ interrupts = <31>;
+ clock-output-names = ...
+ "uart_ipg",
+ "uart_serial",
+ ...;
+};
+
+uart1: serial@43f90000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x43f90000 0x4000>;
+ interrupts = <45>;
+ clocks = <&clks 79>, <&clks 50>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
new file mode 100644
index 000000000000..23ae1db1bc13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
@@ -0,0 +1,55 @@
+Device Tree Clock bindings for the Zynq 7000 EPP
+
+The Zynq EPP has several different clk providers, each with there own bindings.
+The purpose of this document is to document their usage.
+
+See clock_bindings.txt for more information on the generic clock bindings.
+See Chapter 25 of Zynq TRM for more information about Zynq clocks.
+
+== PLLs ==
+
+Used to describe the ARM_PLL, DDR_PLL, and IO_PLL.
+
+Required properties:
+- #clock-cells : shall be 0 (only one clock is output from this node)
+- compatible : "xlnx,zynq-pll"
+- reg : pair of u32 values, which are the address offsets within the SLCR
+ of the relevant PLL_CTRL register and PLL_CFG register respectively
+- clocks : phandle for parent clock. should be the phandle for ps_clk
+
+Optional properties:
+- clock-output-names : name of the output clock
+
+Example:
+ armpll: armpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x100 0x110>;
+ clock-output-names = "armpll";
+ };
+
+== Peripheral clocks ==
+
+Describes clock node for the SDIO, SMC, SPI, QSPI, and UART clocks.
+
+Required properties:
+- #clock-cells : shall be 1
+- compatible : "xlnx,zynq-periph-clock"
+- reg : a single u32 value, describing the offset within the SLCR where
+ the CLK_CTRL register is found for this peripheral
+- clocks : phandle for parent clocks. should hold phandles for
+ the IO_PLL, ARM_PLL, and DDR_PLL in order
+- clock-output-names : names of the output clock(s). For peripherals that have
+ two output clocks (for example, the UART), two clocks
+ should be listed.
+
+Example:
+ uart_clk: uart_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-periph-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x154>;
+ clock-output-names = "uart0_ref_clk",
+ "uart1_ref_clk";
+ };
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmi.txt b/Documentation/devicetree/bindings/drm/exynos/hdmi.txt
new file mode 100644
index 000000000000..589edee37394
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmi.txt
@@ -0,0 +1,22 @@
+Device-Tree bindings for drm hdmi driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmi".
+- reg: physical base address of the hdmi and length of memory mapped
+ region.
+- interrupts: interrupt number to the cpu.
+- hpd-gpio: following information about the hotplug gpio pin.
+ a) phandle of the gpio controller node.
+ b) pin number within the gpio controller.
+ c) pin function mode.
+ d) optional flags and pull up/down.
+ e) drive strength.
+
+Example:
+
+ hdmi {
+ compatible = "samsung,exynos5-hdmi";
+ reg = <0x14530000 0x100000>;
+ interrupts = <0 95 0>;
+ hpd-gpio = <&gpx3 7 0xf 1 3>;
+ };
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt b/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt
new file mode 100644
index 000000000000..fa166d945809
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt
@@ -0,0 +1,12 @@
+Device-Tree bindings for hdmiddc driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmiddc".
+- reg: I2C address of the hdmiddc device.
+
+Example:
+
+ hdmiddc {
+ compatible = "samsung,exynos5-hdmiddc";
+ reg = <0x50>;
+ };
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt b/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt
new file mode 100644
index 000000000000..858f4f9b902f
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt
@@ -0,0 +1,12 @@
+Device-Tree bindings for hdmiphy driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmiphy".
+- reg: I2C address of the hdmiphy device.
+
+Example:
+
+ hdmiphy {
+ compatible = "samsung,exynos5-hdmiphy";
+ reg = <0x38>;
+ };
diff --git a/Documentation/devicetree/bindings/drm/exynos/mixer.txt b/Documentation/devicetree/bindings/drm/exynos/mixer.txt
new file mode 100644
index 000000000000..9b2ea0343566
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/mixer.txt
@@ -0,0 +1,15 @@
+Device-Tree bindings for mixer driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-mixer".
+- reg: physical base address of the mixer and length of memory mapped
+ region.
+- interrupts: interrupt number to the cpu.
+
+Example:
+
+ mixer {
+ compatible = "samsung,exynos5-mixer";
+ reg = <0x14450000 0x10000>;
+ interrupts = <0 94 0>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
new file mode 100644
index 000000000000..558cdf3c9abc
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -0,0 +1,22 @@
+GPIO line that should be set high/low to power off a device
+
+Required properties:
+- compatible : should be "gpio-poweroff".
+- gpios : The GPIO to set high/low, see "gpios property" in
+ Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
+ low to power down the board set it to "Active Low", otherwise set
+ gpio to "Active High".
+
+Optional properties:
+- input : Initially configure the GPIO line as an input. Only reconfigure
+ it to an output when the pm_power_off function is called. If this optional
+ property is not specified, the GPIO is initialized as an output in its
+ inactive state.
+
+
+Examples:
+
+gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio 4 0>; /* GPIO 4 Active Low */
+};
diff --git a/Documentation/devicetree/bindings/hwmon/vexpress.txt b/Documentation/devicetree/bindings/hwmon/vexpress.txt
new file mode 100644
index 000000000000..9c27ed694bbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/vexpress.txt
@@ -0,0 +1,23 @@
+Versatile Express hwmon sensors
+-------------------------------
+
+Requires node properties:
+- "compatible" value : one of
+ "arm,vexpress-volt"
+ "arm,vexpress-amp"
+ "arm,vexpress-temp"
+ "arm,vexpress-power"
+ "arm,vexpress-energy"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+ (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+ for more details)
+
+Optional node properties:
+- label : string describing the monitored value
+
+Example:
+ energy@0 {
+ compatible = "arm,vexpress-energy";
+ arm,vexpress-sysreg,func = <13 0>;
+ label = "A15 Jcore";
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
new file mode 100644
index 000000000000..ca5a2c86480c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
@@ -0,0 +1,28 @@
+* Rohm BU21013 Touch Screen
+
+Required properties:
+ - compatible : "rohm,bu21013_tp"
+ - reg : I2C device address
+
+Optional properties:
+ - touch-gpio : GPIO pin registering a touch event
+ - <supply_name>-supply : Phandle to a regulator supply
+ - rohm,touch-max-x : Maximum outward permitted limit in the X axis
+ - rohm,touch-max-y : Maximum outward permitted limit in the Y axis
+ - rohm,flip-x : Flip touch coordinates on the X axis
+ - rohm,flip-y : Flip touch coordinates on the Y axis
+
+Example:
+
+ i2c@80110000 {
+ bu21013_tp@0x5c {
+ compatible = "rohm,bu21013_tp";
+ reg = <0x5c>;
+ touch-gpio = <&gpio2 20 0x4>;
+ avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+ rohm,touch-max-x = <384>;
+ rohm,touch-max-y = <704>;
+ rohm,flip-y;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
new file mode 100644
index 000000000000..67ec3d4ccc7f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -0,0 +1,23 @@
+* Samsung Multi Format Codec (MFC)
+
+Multi Format Codec (MFC) is the IP present in Samsung SoCs which
+supports high resolution decoding and encoding functionalities.
+The MFC device driver is a v4l2 driver which can encode/decode
+video raw/elementary streams and has support for all popular
+video codecs.
+
+Required properties:
+ - compatible : value should be either one among the following
+ (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
+ (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
+
+ - reg : Physical base address of the IP registers and length of memory
+ mapped region.
+
+ - interrupts : MFC interrupt number to the CPU.
+
+ - samsung,mfc-r : Base address of the first memory bank used by MFC
+ for DMA contiguous memory allocation and its size.
+
+ - samsung,mfc-l : Base address of the second memory bank used by MFC
+ for DMA contiguous memory allocation and its size.
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
new file mode 100644
index 000000000000..38e51ad2e07e
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -0,0 +1,15 @@
+* Atmel SSC driver.
+
+Required properties:
+- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
+ - atmel,at91rm9200-ssc: support pdc transfer
+ - atmel,at91sam9g45-ssc: support dma transfer
+- reg: Should contain SSC registers location and length
+- interrupts: Should contain SSC interrupt
+
+Example:
+ssc0: ssc@fffbc000 {
+ compatible = "atmel,at91rm9200-ssc";
+ reg = <0xfffbc000 0x4000>;
+ interrupts = <14 4 5>;
+};
diff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt
new file mode 100644
index 000000000000..34ef3498f887
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/grcan.txt
@@ -0,0 +1,28 @@
+Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.
+
+The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core
+library.
+
+Note: These properties are built from the AMBA plug&play in a Leon SPARC system
+(the ordinary environment for GRCAN and GRHCAN). There are no dts files for
+sparc.
+
+Required properties:
+
+- name : Should be "GAISLER_GRCAN", "01_03d", "GAISLER_GRHCAN" or "01_034"
+
+- reg : Address and length of the register set for the device
+
+- freq : Frequency of the external oscillator clock in Hz (the frequency of
+ the amba bus in the ordinary case)
+
+- interrupts : Interrupt number for this device
+
+Optional properties:
+
+- systemid : If not present or if the value of the least significant 16 bits
+ of this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION
+ a bug workaround is activated.
+
+For further information look in the documentation for the GLIB IP core library:
+http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/net/cdns-emac.txt b/Documentation/devicetree/bindings/net/cdns-emac.txt
new file mode 100644
index 000000000000..09055c2495f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cdns-emac.txt
@@ -0,0 +1,23 @@
+* Cadence EMAC Ethernet controller
+
+Required properties:
+- compatible: Should be "cdns,[<chip>-]{emac}"
+ Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
+ or the generic form: "cdns,emac".
+- reg: Address and length of the register set for the device
+- interrupts: Should contain macb interrupt
+- phy-mode: String, operation mode of the PHY interface.
+ Supported values are: "mii", "rmii".
+
+Optional properties:
+- local-mac-address: 6 bytes, mac address
+
+Examples:
+
+ macb0: ethernet@fffc4000 {
+ compatible = "cdns,at91rm9200-emac";
+ reg = <0xfffc4000 0x4000>;
+ interrupts = <21>;
+ phy-mode = "rmii";
+ local-mac-address = [3a 0e 03 04 05 06];
+ };
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index dcaabe9fe869..6ddd0286a9b7 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -9,21 +9,15 @@ Required properties:
number
- interrupt-parent : The parent interrupt controller
- cpdma_channels : Specifies number of channels in CPDMA
-- host_port_no : Specifies host port shift
-- cpdma_reg_ofs : Specifies CPDMA submodule register offset
-- cpdma_sram_ofs : Specifies CPDMA SRAM offset
-- ale_reg_ofs : Specifies ALE submodule register offset
- ale_entries : Specifies No of entries ALE can hold
-- host_port_reg_ofs : Specifies host port register offset
-- hw_stats_reg_ofs : Specifies hardware statistics register offset
-- bd_ram_ofs : Specifies internal desciptor RAM offset
- bd_ram_size : Specifies internal descriptor RAM size
- rx_descs : Specifies number of Rx descriptors
- mac_control : Specifies Default MAC control register content
for the specific platform
- slaves : Specifies number for slaves
-- slave_reg_ofs : Specifies slave register offset
-- sliver_reg_ofs : Specifies slave sliver register offset
+- cpts_active_slave : Specifies the slave to use for time stamping
+- cpts_clock_mult : Numerator to convert input clock ticks into nanoseconds
+- cpts_clock_shift : Denominator to convert input clock ticks into nanoseconds
- phy_id : Specifies slave phy id
- mac-address : Specifies slave MAC address
@@ -45,30 +39,22 @@ Examples:
interrupts = <55 0x4>;
interrupt-parent = <&intc>;
cpdma_channels = <8>;
- host_port_no = <0>;
- cpdma_reg_ofs = <0x800>;
- cpdma_sram_ofs = <0xa00>;
- ale_reg_ofs = <0xd00>;
ale_entries = <1024>;
- host_port_reg_ofs = <0x108>;
- hw_stats_reg_ofs = <0x900>;
- bd_ram_ofs = <0x2000>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
rx_descs = <64>;
mac_control = <0x20>;
slaves = <2>;
+ cpts_active_slave = <0>;
+ cpts_clock_mult = <0x80000000>;
+ cpts_clock_shift = <29>;
cpsw_emac0: slave@0 {
- slave_reg_ofs = <0x208>;
- sliver_reg_ofs = <0xd80>;
- phy_id = "davinci_mdio.16:00";
+ phy_id = <&davinci_mdio>, <0>;
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
cpsw_emac1: slave@1 {
- slave_reg_ofs = <0x308>;
- sliver_reg_ofs = <0xdc0>;
- phy_id = "davinci_mdio.16:01";
+ phy_id = <&davinci_mdio>, <1>;
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
@@ -79,30 +65,22 @@ Examples:
compatible = "ti,cpsw";
ti,hwmods = "cpgmac0";
cpdma_channels = <8>;
- host_port_no = <0>;
- cpdma_reg_ofs = <0x800>;
- cpdma_sram_ofs = <0xa00>;
- ale_reg_ofs = <0xd00>;
ale_entries = <1024>;
- host_port_reg_ofs = <0x108>;
- hw_stats_reg_ofs = <0x900>;
- bd_ram_ofs = <0x2000>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
rx_descs = <64>;
mac_control = <0x20>;
slaves = <2>;
+ cpts_active_slave = <0>;
+ cpts_clock_mult = <0x80000000>;
+ cpts_clock_shift = <29>;
cpsw_emac0: slave@0 {
- slave_reg_ofs = <0x208>;
- sliver_reg_ofs = <0xd80>;
- phy_id = "davinci_mdio.16:00";
+ phy_id = <&davinci_mdio>, <0>;
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
cpsw_emac1: slave@1 {
- slave_reg_ofs = <0x308>;
- sliver_reg_ofs = <0xdc0>;
- phy_id = "davinci_mdio.16:01";
+ phy_id = <&davinci_mdio>, <1>;
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
index 361bccb7ec89..95daf6335c37 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
@@ -7,8 +7,10 @@ Required properties:
- compatible: "marvell,88f6180-pinctrl",
"marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
"marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
+ "marvell,98dx4122-pinctrl"
This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
+It also support the 88f6281-based variant in the 98dx412x Bobcat SoCs.
Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given
@@ -277,3 +279,40 @@ mpp46 46 gpio, ts(mp10), tdm(fs), lcd(hsync)
mpp47 47 gpio, ts(mp11), tdm(drx), lcd(vsync)
mpp48 48 gpio, ts(mp12), tdm(dtx), lcd(d16)
mpp49 49 gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
+
+* Marvell Bobcat 98dx4122
+
+name pins functions
+================================================================================
+mpp0 0 gpio, nand(io2), spi(cs)
+mpp1 1 gpo, nand(io3), spi(mosi)
+mpp2 2 gpo, nand(io4), spi(sck)
+mpp3 3 gpo, nand(io5), spi(miso)
+mpp4 4 gpio, nand(io6), uart0(rxd)
+mpp5 5 gpo, nand(io7), uart0(txd)
+mpp6 6 sysrst(out), spi(mosi)
+mpp7 7 gpo, pex(rsto), spi(cs)
+mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts)
+mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts)
+mpp10 10 gpo, spi(sck), uart0(txd)
+mpp11 11 gpio, spi(miso), uart0(rxd)
+mpp13 13 gpio, uart1(txd)
+mpp14 14 gpio, uart1(rxd)
+mpp15 15 gpio, uart0(rts)
+mpp16 16 gpio, uart0(cts)
+mpp18 18 gpo, nand(io0)
+mpp19 19 gpo, nand(io1)
+mpp34 34 gpio
+mpp35 35 gpio
+mpp36 36 gpio
+mpp37 37 gpio
+mpp38 38 gpio
+mpp39 39 gpio
+mpp40 40 gpio
+mpp41 41 gpio
+mpp42 42 gpio
+mpp43 43 gpio
+mpp44 44 gpio
+mpp45 45 gpio
+mpp49 49 gpio
+
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644
index 000000000000..63c659800c03
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
@@ -0,0 +1,37 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible : Must be "regulator-gpio".
+- states : Selection of available voltages and GPIO configs.
+ if there are no states, then use a fixed regulator
+
+Optional properties:
+- enable-gpio : GPIO to use to enable/disable the regulator.
+- gpios : GPIO group used to control voltage.
+- startup-delay-us : Startup time in microseconds.
+- enable-active-high : Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+ mmciv: gpio-regulator {
+ compatible = "regulator-gpio";
+
+ regulator-name = "mmci-gpio-supply";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2600000>;
+ regulator-boot-on;
+
+ enable-gpio = <&gpio0 23 0x4>;
+ gpios = <&gpio0 24 0x4
+ &gpio0 25 0x4>;
+ states = <1800000 0x3
+ 2200000 0x2
+ 2600000 0x1
+ 2900000 0x0>;
+
+ startup-delay-us = <100000>;
+ enable-active-high;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/max8925-regulator.txt b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
new file mode 100644
index 000000000000..0057695aae8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
@@ -0,0 +1,40 @@
+Max8925 Voltage regulators
+
+Required nodes:
+-nodes:
+ - SDV1 for SDV SDV1
+ - SDV2 for SDV SDV2
+ - SDV3 for SDV SDV3
+ - LDO1 for LDO LDO1
+ - LDO2 for LDO LDO2
+ - LDO3 for LDO LDO3
+ - LDO4 for LDO LDO4
+ - LDO5 for LDO LDO5
+ - LDO6 for LDO LDO6
+ - LDO7 for LDO LDO7
+ - LDO8 for LDO LDO8
+ - LDO9 for LDO LDO9
+ - LDO10 for LDO LDO10
+ - LDO11 for LDO LDO11
+ - LDO12 for LDO LDO12
+ - LDO13 for LDO LDO13
+ - LDO14 for LDO LDO14
+ - LDO15 for LDO LDO15
+ - LDO16 for LDO LDO16
+ - LDO17 for LDO LDO17
+ - LDO18 for LDO LDO18
+ - LDO19 for LDO LDO19
+ - LDO20 for LDO LDO20
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+ SDV1 {
+ regulator-min-microvolt = <637500>;
+ regulator-max-microvolt = <1425000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
diff --git a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
new file mode 100644
index 000000000000..9fd69a18b0ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
@@ -0,0 +1,146 @@
+* Maxim MAX8997 Voltage and Current Regulator
+
+The Maxim MAX8997 is a multi-function device which includes volatage and
+current regulators, rtc, charger controller and other sub-blocks. It is
+interfaced to the host controller using a i2c interface. Each sub-block is
+addressed by the host system using different i2c slave address. This document
+describes the bindings for 'pmic' sub-block of max8997.
+
+Required properties:
+- compatible: Should be "maxim,max8997-pmic".
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck1 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck2 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck5 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+ property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
+ property should specify atleast one voltage level (which would be a
+ safe operating voltage).
+
+ If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+ property is specified, then all the eigth voltage values for the
+ 'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the interrupts from max8997 are delivered to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+ - First interrupt specifier is for 'irq1' interrupt.
+ - Second interrupt specifier is for 'alert' interrupt.
+- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
+- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
+- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
+
+Additional properties required if either of the optional properties are used:
+- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
+ multiple bucks, changing the voltage value of one of the bucks may affect
+ that of another buck, which is the side effect of the change (set_voltage).
+ Use this property to ignore such side effects and change the voltage.
+
+- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
+ the possible 8 options selectable by the dvs gpios. The value of this
+ property should be between 0 and 7. If not specified or if out of range, the
+ default value of this property is set to 0.
+
+- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
+ for dvs. The format of the gpio specifier depends in the gpio controller.
+
+Regulators: The regulators of max8997 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+ regulator_name {
+ standard regulator bindings here
+ };
+
+The following are the names of the regulators that the max8997 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of max8997.
+
+ - LDOn
+ - valid values for n are 1 to 18 and 21
+ - Example: LDO0, LD01, LDO2, LDO21
+ - BUCKn
+ - valid values for n are 1 to 7.
+ - Example: BUCK1, BUCK2, BUCK3, BUCK7
+
+ - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+ voltage type regulator
+
+ - ESAFEOUT1: (ldo19)
+ - ESAFEOUT2: (ld020)
+
+ - CHARGER_CV: main battery charger voltage control
+ - CHARGER: main battery charger current control
+ - CHARGER_TOPOFF: end of charge current threshold level
+
+The bindings inside the regulator nodes use the standard regulator bindings
+which are documented elsewhere.
+
+Example:
+
+ max8997_pmic@66 {
+ compatible = "maxim,max8997-pmic";
+ interrupt-parent = <&wakeup_eint>;
+ reg = <0x66>;
+ interrupts = <4 0>, <3 0>;
+
+ max8997,pmic-buck1-uses-gpio-dvs;
+ max8997,pmic-buck2-uses-gpio-dvs;
+ max8997,pmic-buck5-uses-gpio-dvs;
+
+ max8997,pmic-ignore-gpiodvs-side-effect;
+ max8997,pmic-buck125-default-dvs-idx = <0>;
+
+ max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+ <&gpx0 1 1 0 0>, /* SET2 */
+ <&gpx0 2 1 0 0>; /* SET3 */
+
+ max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+ <1250000>, <1200000>,
+ <1150000>, <1100000>,
+ <1000000>, <950000>;
+
+ max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+ <1100000>, <1100000>,
+ <1000000>, <1000000>,
+ <1000000>, <1000000>;
+
+ max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ABB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDD_ALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VDD_ARM_1.2V";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644
index 000000000000..d775f72487aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/vexpress.txt
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+ (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+ for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+ volt@0 {
+ compatible = "arm,vexpress-volt";
+ arm,vexpress-sysreg,func = <2 0>;
+ regulator-name = "Cores";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-always-on;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt b/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
new file mode 100644
index 000000000000..93f45e9dce7c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
@@ -0,0 +1,19 @@
+NVIDIA Tegra20 real-time clock
+
+The Tegra RTC maintains seconds and milliseconds counters, and five alarm
+registers. The alarms and other interrupts may wake the system from low-power
+state.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-rtc".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A single interrupt specifier.
+
+Example:
+
+timer {
+ compatible = "nvidia,tegra20-rtc";
+ reg = <0x7000e000 0x100>;
+ interrupts = <0 2 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644
index 000000000000..b902ee39cf89
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ak4104.txt
@@ -0,0 +1,22 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+ - compatible : "asahi-kasei,ak4104"
+
+ - reg : The chip select number on the SPI bus
+
+Optional properties:
+
+ - reset-gpio : a GPIO spec for the reset pin. If specified, it will be
+ deasserted before communication to the device starts.
+
+Example:
+
+spdif: ak4104@0 {
+ compatible = "asahi-kasei,ak4104";
+ reg = <0>;
+ spi-max-frequency = <5000000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
new file mode 100644
index 000000000000..9c5a9947b64d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
@@ -0,0 +1,26 @@
+* Atmel at91sam9g20ek wm8731 audio complex
+
+Required properties:
+ - compatible: "atmel,at91sam9g20ek-wm8731-audio"
+ - atmel,model: The user-visible name of this sound complex.
+ - atmel,audio-routing: A list of the connections between audio components.
+ - atmel,ssc-controller: The phandle of the SSC controller
+ - atmel,audio-codec: The phandle of the WM8731 audio codec
+Optional properties:
+ - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+ compatible = "atmel,at91sam9g20ek-wm8731-audio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+ atmel,model = "wm8731 @ AT91SAMG20EK";
+
+ atmel,audio-routing =
+ "Ext Spk", "LHPOUT",
+ "Int MIC", "MICIN";
+
+ atmel,ssc-controller = <&ssc0>;
+ atmel,audio-codec = <&wm8731>;
+};
diff --git a/Documentation/devicetree/bindings/sound/cs4271.txt b/Documentation/devicetree/bindings/sound/cs4271.txt
index c81b5fd5a5bc..a850fb9c88ea 100644
--- a/Documentation/devicetree/bindings/sound/cs4271.txt
+++ b/Documentation/devicetree/bindings/sound/cs4271.txt
@@ -18,6 +18,8 @@ Optional properties:
- reset-gpio: a GPIO spec to define which pin is connected to the chip's
!RESET pin
+ - cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag
+ is enabled.
Examples:
diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
index 65dec876cb2d..fd40c852d7c7 100644
--- a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
+++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
@@ -12,7 +12,7 @@ Required properties:
Optional properties:
- ti,dmic: phandle for the OMAP dmic node if the machine have it connected
-- ti,jack_detection: Need to be set to <1> if the board capable to detect jack
+- ti,jack_detection: Need to be present if the board capable to detect jack
insertion, removal.
Available audio endpoints for the audio-routing table:
@@ -59,7 +59,7 @@ sound {
compatible = "ti,abe-twl6040";
ti,model = "SDP4430";
- ti,jack-detection = <1>;
+ ti,jack-detection;
ti,mclk-freq = <38400000>;
ti,mcpdm = <&mcpdm>;
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
new file mode 100644
index 000000000000..e019fdc38773
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
@@ -0,0 +1,21 @@
+NVIDIA Tegra20 timer
+
+The Tegra20 timer provides four 29-bit timer channels and a single 32-bit free
+running counter. The first two channels may also trigger a watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 4 interrupts; one per timer channel.
+
+Example:
+
+timer {
+ compatible = "nvidia,tegra20-timer";
+ reg = <0x60005000 0x60>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
new file mode 100644
index 000000000000..906109d4c593
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
@@ -0,0 +1,23 @@
+NVIDIA Tegra30 timer
+
+The Tegra30 timer provides ten 29-bit timer channels, a single 32-bit free
+running counter, and 5 watchdog modules. The first two channels may also
+trigger a legacy watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra30-timer", "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 6 interrupts; one per each of timer channels 1
+ through 5, and one for the shared interrupt for the remaining channels.
+
+timer {
+ compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+ reg = <0x60005000 0x400>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04
+ 0 121 0x04
+ 0 122 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/usb/ehci-orion.txt b/Documentation/devicetree/bindings/usb/ehci-orion.txt
new file mode 100644
index 000000000000..6bc09ec14c4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ehci-orion.txt
@@ -0,0 +1,15 @@
+* EHCI controller, Orion Marvell variants
+
+Required properties:
+- compatible: must be "marvell,orion-ehci"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: The EHCI interrupt
+
+Example:
+
+ ehci@50000 {
+ compatible = "marvell,orion-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <19>;
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 770a0193ca1b..902b1b1f568e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -55,4 +55,5 @@ ti Texas Instruments
via VIA Technologies, Inc.
wlf Wolfson Microelectronics
wm Wondermedia Technologies, Inc.
+winbond Winbond Electronics corp.
xlnx Xilinx
diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
new file mode 100644
index 000000000000..2957ebb5aa71
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
@@ -0,0 +1,15 @@
+* Atmel Watchdog Timers
+
+** at91sam9-wdt
+
+Required properties:
+- compatible: must be "atmel,at91sam9260-wdt".
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+Example:
+
+ watchdog@fffffd40 {
+ compatible = "atmel,at91sam9260-wdt";
+ reg = <0xfffffd40 0x10>;
+ };
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
index ad86fb86c9a0..0188903bc9e1 100644
--- a/Documentation/dma-buf-sharing.txt
+++ b/Documentation/dma-buf-sharing.txt
@@ -376,7 +376,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
leaving the cpu domain and flushing caches at fault time. Note that all the
dma_buf files share the same anon inode, hence the exporter needs to replace
the dma_buf file stored in vma->vm_file with it's own if pte shootdown is
- requred. This is because the kernel uses the underlying inode's address_space
+ required. This is because the kernel uses the underlying inode's address_space
for vma tracking (and hence pte tracking at shootdown time with
unmap_mapping_range).
@@ -388,7 +388,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
Exporters that shoot down mappings (for any reasons) shall not do any
synchronization at fault time with outstanding device operations.
Synchronization is an orthogonal issue to sharing the backing storage of a
- buffer and hence should not be handled by dma-buf itself. This is explictly
+ buffer and hence should not be handled by dma-buf itself. This is explicitly
mentioned here because many people seem to want something like this, but if
different exporters handle this differently, buffer sharing can fail in
interesting ways depending upong the exporter (if userspace starts depending
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 74c25c8d8884..b89a739a3276 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -181,7 +181,6 @@ modversions.h*
nconf
ncscope.*
offset.h
-offsets.h
oui.c*
page-types
parse.c
diff --git a/Documentation/fault-injection/notifier-error-inject.txt b/Documentation/fault-injection/notifier-error-inject.txt
index c83526c364e5..09adabef513f 100644
--- a/Documentation/fault-injection/notifier-error-inject.txt
+++ b/Documentation/fault-injection/notifier-error-inject.txt
@@ -1,7 +1,7 @@
Notifier error injection
========================
-Notifier error injection provides the ability to inject artifical errors to
+Notifier error injection provides the ability to inject artificial errors to
specified notifier chain callbacks. It is useful to test the error handling of
notifier call chain failures which is rarely executed. There are kernel
modules that can be used to test the following notifiers.
@@ -14,7 +14,7 @@ modules that can be used to test the following notifiers.
CPU notifier error injection module
-----------------------------------
This feature can be used to test the error handling of the CPU notifiers by
-injecting artifical errors to CPU notifier chain callbacks.
+injecting artificial errors to CPU notifier chain callbacks.
If the notifier call chain should be failed with some events notified, write
the error code to debugfs interface
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt
index 4627c4241ece..3c741214dfbb 100644
--- a/Documentation/hid/uhid.txt
+++ b/Documentation/hid/uhid.txt
@@ -108,7 +108,7 @@ the request was handled successfully.
UHID_FEATURE_ANSWER:
If you receive a UHID_FEATURE request you must answer with this request. You
must copy the "id" field from the request into the answer. Set the "err" field
- to 0 if no error occured or to EIO if an I/O error occurred.
+ to 0 if no error occurred or to EIO if an I/O error occurred.
If "err" is 0 then you should fill the buffer of the answer with the results
of the feature request and set "size" correspondingly.
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
index f90f99920cc5..3d3a0f97f966 100644
--- a/Documentation/hwmon/pmbus
+++ b/Documentation/hwmon/pmbus
@@ -138,7 +138,7 @@ Sysfs entries
When probing the chip, the driver identifies which PMBus registers are
supported, and determines available sensors from this information.
-Attribute files only exist if respective sensors are suported by the chip.
+Attribute files only exist if respective sensors are supported by the chip.
Labels are provided to inform the user about the sensor associated with
a given sysfs entry.
diff --git a/Documentation/hwmon/vexpress b/Documentation/hwmon/vexpress
new file mode 100644
index 000000000000..557d6d5ad90d
--- /dev/null
+++ b/Documentation/hwmon/vexpress
@@ -0,0 +1,34 @@
+Kernel driver vexpress
+======================
+
+Supported systems:
+ * ARM Ltd. Versatile Express platform
+ Prefix: 'vexpress'
+ Datasheets:
+ * "Hardware Description" sections of the Technical Reference Manuals
+ for the Versatile Express boards:
+ http://infocenter.arm.com/help/topic/com.arm.doc.subset.boards.express/index.html
+ * Section "4.4.14. System Configuration registers" of the V2M-P1 TRM:
+ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0447-/index.html
+
+Author: Pawel Moll
+
+Description
+-----------
+
+Versatile Express platform (http://www.arm.com/versatileexpress/) is a
+reference & prototyping system for ARM Ltd. processors. It can be set up
+from a wide range of boards, each of them containing (apart of the main
+chip/FPGA) a number of microcontrollers responsible for platform
+configuration and control. Theses microcontrollers can also monitor the
+board and its environment by a number of internal and external sensors,
+providing information about power lines voltages and currents, board
+temperature and power usage. Some of them also calculate consumed energy
+and provide a cumulative use counter.
+
+The configuration devices are _not_ memory mapped and must be accessed
+via a custom interface, abstracted by the "vexpress_config" API.
+
+As these devices are non-discoverable, they must be described in a Device
+Tree passed to the kernel. Details of the DT binding for them can be found
+in Documentation/devicetree/bindings/hwmon/vexpress.txt.
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index ae8ba9a74ce1..3262b6e4d686 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt
@@ -133,7 +133,7 @@ number of contacts (f1 and f0 in the table below).
This packet only appears after a position packet with the mt bit set, and
usually only appears when there are two or more contacts (although
-occassionally it's seen with only a single contact).
+occasionally it's seen with only a single contact).
The final v3 packet type is the trackstick packet.
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
index 53305bd08182..f1ea2c69648d 100644
--- a/Documentation/input/event-codes.txt
+++ b/Documentation/input/event-codes.txt
@@ -196,6 +196,17 @@ EV_MSC:
EV_MSC events are used for input and output events that do not fall under other
categories.
+A few EV_MSC codes have special meaning:
+
+* MSC_TIMESTAMP:
+ - Used to report the number of microseconds since the last reset. This event
+ should be coded as an uint32 value, which is allowed to wrap around with
+ no special consequence. It is assumed that the time difference between two
+ consecutive events is reliable on a reasonable time scale (hours).
+ A reset to zero can happen, in which case the time since the last event is
+ unknown. If the device does not provide this information, the driver must
+ not provide it to user space.
+
EV_LED:
----------
EV_LED events are used for input and output to set and query the state of
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index 3fb39e0116b4..69372fb98cf8 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -470,7 +470,7 @@ build.
Sometimes, an external module uses exported symbols from
another external module. kbuild needs to have full knowledge of
- all symbols to avoid spitting out warnings about undefined
+ all symbols to avoid spliitting out warnings about undefined
symbols. Three solutions exist for this situation.
NOTE: The method with a top-level kbuild file is recommended
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 3d8a97747f77..99b57abddf8a 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -64,6 +64,8 @@ Example kernel-doc function comment:
* comment lines.
*
* The longer description can have multiple paragraphs.
+ *
+ * Return: Describe the return value of foobar.
*/
The short description following the subject can span multiple lines
@@ -78,6 +80,8 @@ If a function parameter is "..." (varargs), it should be listed in
kernel-doc notation as:
* @...: description
+The return value, if any, should be described in a dedicated section
+named "Return".
Example kernel-doc data structure comment.
@@ -222,6 +226,9 @@ only a "*").
"section header:" names must be unique per function (or struct,
union, typedef, enum).
+Use the section header "Return" for sections describing the return value
+of a function.
+
Avoid putting a spurious blank line after the function name, or else the
description will be repeated!
@@ -237,21 +244,21 @@ patterns, which are highlighted appropriately.
NOTE 1: The multi-line descriptive text you provide does *not* recognize
line breaks, so if you try to format some text nicely, as in:
- Return codes
+ Return:
0 - cool
1 - invalid arg
2 - out of memory
this will all run together and produce:
- Return codes 0 - cool 1 - invalid arg 2 - out of memory
+ Return: 0 - cool 1 - invalid arg 2 - out of memory
NOTE 2: If the descriptive text you provide has lines that begin with
some phrase followed by a colon, each of those phrases will be taken as
a new section heading, which means you should similarly try to avoid text
like:
- Return codes:
+ Return:
0: cool
1: invalid arg
2: out of memory
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 28bd0f0e32c5..20e248cc03a9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -905,6 +905,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
gpt [EFI] Forces disk with valid GPT signature but
invalid Protective MBR to be treated as GPT.
+ grcan.enable0= [HW] Configuration of physical interface 0. Determines
+ the "Enable 0" bit of the configuration register.
+ Format: 0 | 1
+ Default: 0
+ grcan.enable1= [HW] Configuration of physical interface 1. Determines
+ the "Enable 0" bit of the configuration register.
+ Format: 0 | 1
+ Default: 0
+ grcan.select= [HW] Select which physical interface to use.
+ Format: 0 | 1
+ Default: 0
+ grcan.txsize= [HW] Sets the size of the tx buffer.
+ Format: <unsigned int> such that (txsize & ~0x1fffc0) == 0.
+ Default: 1024
+ grcan.rxsize= [HW] Sets the size of the rx buffer.
+ Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
+ Default: 1024
+
hashdist= [KNL,NUMA] Large hashes allocated during boot
are distributed across NUMA nodes. Defaults on
for 64-bit NUMA, off otherwise.
diff --git a/Documentation/misc-devices/mei/mei-amt-version.c b/Documentation/misc-devices/mei/mei-amt-version.c
index 01804f216312..49e4f770864a 100644
--- a/Documentation/misc-devices/mei/mei-amt-version.c
+++ b/Documentation/misc-devices/mei/mei-amt-version.c
@@ -214,7 +214,7 @@ out:
}
/***************************************************************************
- * Intel Advanced Management Technolgy ME Client
+ * Intel Advanced Management Technology ME Client
***************************************************************************/
#define AMT_MAJOR_VERSION 1
@@ -256,7 +256,7 @@ struct amt_code_versions {
} __attribute__((packed));
/***************************************************************************
- * Intel Advanced Management Technolgy Host Interface
+ * Intel Advanced Management Technology Host Interface
***************************************************************************/
struct amt_host_if_msg_header {
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index a173d2a879f5..c1d82047a4b1 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -203,7 +203,8 @@ abled during run time. Following log_levels are defined:
2 - Enable messages related to route added / changed / deleted
4 - Enable messages related to translation table operations
8 - Enable messages related to bridge loop avoidance
-15 - enable all messages
+16 - Enable messaged related to DAT, ARP snooping and parsing
+31 - Enable all messages
The debug output can be changed at runtime using the file
/sys/class/net/bat0/mesh/log_level. e.g.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index c7fc10724948..dd52d516cb89 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -30,16 +30,24 @@ neigh/default/gc_thresh3 - INTEGER
Maximum number of neighbor entries allowed. Increase this
when using large numbers of interfaces and when communicating
with large numbers of directly-connected peers.
+ Default: 1024
neigh/default/unres_qlen_bytes - INTEGER
The maximum number of bytes which may be used by packets
queued for each unresolved address by other network layers.
(added in linux 3.3)
+ Seting negative value is meaningless and will retrun error.
+ Default: 65536 Bytes(64KB)
neigh/default/unres_qlen - INTEGER
The maximum number of packets which may be queued for each
unresolved address by other network layers.
(deprecated in linux 3.3) : use unres_qlen_bytes instead.
+ Prior to linux 3.3, the default value is 3 which may cause
+ unexpected packet loss. The current default value is calculated
+ according to default value of unres_qlen_bytes and true size of
+ packet.
+ Default: 31
mtu_expires - INTEGER
Time, in seconds, that cached PMTU information is kept.
@@ -199,15 +207,16 @@ tcp_early_retrans - INTEGER
Default: 2
tcp_ecn - INTEGER
- Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
- used when both ends of the TCP flow support it. It is useful to
- avoid losses due to congestion (when the bottleneck router supports
- ECN).
+ Control use of Explicit Congestion Notification (ECN) by TCP.
+ ECN is used only when both ends of the TCP connection indicate
+ support for it. This feature is useful in avoiding losses due
+ to congestion by allowing supporting routers to signal
+ congestion before having to drop packets.
Possible values are:
- 0 disable ECN
- 1 ECN enabled
- 2 Only server-side ECN enabled. If the other end does
- not support ECN, behavior is like with ECN disabled.
+ 0 Disable ECN. Neither initiate nor accept ECN.
+ 1 Always request ECN on outgoing connection attempts.
+ 2 Enable ECN when requested by incomming connections
+ but do not request ECN on outgoing connections.
Default: 2
tcp_fack - BOOLEAN
@@ -215,15 +224,14 @@ tcp_fack - BOOLEAN
The value is not used, if tcp_sack is not enabled.
tcp_fin_timeout - INTEGER
- Time to hold socket in state FIN-WAIT-2, if it was closed
- by our side. Peer can be broken and never close its side,
- or even died unexpectedly. Default value is 60sec.
- Usual value used in 2.2 was 180 seconds, you may restore
- it, but remember that if your machine is even underloaded WEB server,
- you risk to overflow memory with kilotons of dead sockets,
- FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
- because they eat maximum 1.5K of memory, but they tend
- to live longer. Cf. tcp_max_orphans.
+ The length of time an orphaned (no longer referenced by any
+ application) connection will remain in the FIN_WAIT_2 state
+ before it is aborted at the local end. While a perfectly
+ valid "receive only" state for an un-orphaned connection, an
+ orphaned connection in FIN_WAIT_2 state could otherwise wait
+ forever for the remote to close its end of the connection.
+ Cf. tcp_max_orphans
+ Default: 60 seconds
tcp_frto - INTEGER
Enables Forward RTO-Recovery (F-RTO) defined in RFC4138.
@@ -1514,6 +1522,20 @@ cookie_preserve_enable - BOOLEAN
Default: 1
+cookie_hmac_alg - STRING
+ Select the hmac algorithm used when generating the cookie value sent by
+ a listening sctp socket to a connecting client in the INIT-ACK chunk.
+ Valid values are:
+ * md5
+ * sha1
+ * none
+ Ability to assign md5 or sha1 as the selected alg is predicated on the
+ configuarion of those algorithms at build time (CONFIG_CRYPTO_MD5 and
+ CONFIG_CRYPTO_SHA1).
+
+ Default: Dependent on configuration. MD5 if available, else SHA1 if
+ available, else none.
+
rcvbuf_policy - INTEGER
Determines if the receive buffer is attributed to the socket or to
association. SCTP supports the capability to create multiple
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 1c08a4b0981f..94444b152fbc 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -3,9 +3,9 @@
--------------------------------------------------------------------------------
This file documents the mmap() facility available with the PACKET
-socket interface on 2.4 and 2.6 kernels. This type of sockets is used for
-capture network traffic with utilities like tcpdump or any other that needs
-raw access to network interface.
+socket interface on 2.4/2.6/3.x kernels. This type of sockets is used for
+i) capture network traffic with utilities like tcpdump, ii) transmit network
+traffic, or any other that needs raw access to network interface.
You can find the latest version of this document at:
http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap
@@ -21,19 +21,18 @@ Please send your comments to
+ Why use PACKET_MMAP
--------------------------------------------------------------------------------
-In Linux 2.4/2.6 if PACKET_MMAP is not enabled, the capture process is very
-inefficient. It uses very limited buffers and requires one system call
-to capture each packet, it requires two if you want to get packet's
-timestamp (like libpcap always does).
+In Linux 2.4/2.6/3.x if PACKET_MMAP is not enabled, the capture process is very
+inefficient. It uses very limited buffers and requires one system call to
+capture each packet, it requires two if you want to get packet's timestamp
+(like libpcap always does).
In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size
configurable circular buffer mapped in user space that can be used to either
send or receive packets. This way reading packets just needs to wait for them,
most of the time there is no need to issue a single system call. Concerning
transmission, multiple packets can be sent through one system call to get the
-highest bandwidth.
-By using a shared buffer between the kernel and the user also has the benefit
-of minimizing packet copies.
+highest bandwidth. By using a shared buffer between the kernel and the user
+also has the benefit of minimizing packet copies.
It's fine to use PACKET_MMAP to improve the performance of the capture and
transmission process, but it isn't everything. At least, if you are capturing
@@ -41,7 +40,8 @@ at high speeds (this is relative to the cpu speed), you should check if the
device driver of your network interface card supports some sort of interrupt
load mitigation or (even better) if it supports NAPI, also make sure it is
enabled. For transmission, check the MTU (Maximum Transmission Unit) used and
-supported by devices of your network.
+supported by devices of your network. CPU IRQ pinning of your network interface
+card can also be an advantage.
--------------------------------------------------------------------------------
+ How to use mmap() to improve capture process
@@ -87,9 +87,7 @@ the following process:
socket creation and destruction is straight forward, and is done
the same way with or without PACKET_MMAP:
-int fd;
-
-fd= socket(PF_PACKET, mode, htons(ETH_P_ALL))
+ int fd = socket(PF_PACKET, mode, htons(ETH_P_ALL));
where mode is SOCK_RAW for the raw interface were link level
information can be captured or SOCK_DGRAM for the cooked
@@ -163,11 +161,23 @@ As capture, each frame contains two parts:
A complete tutorial is available at: http://wiki.gnu-log.net/
+By default, the user should put data at :
+ frame base + TPACKET_HDRLEN - sizeof(struct sockaddr_ll)
+
+So, whatever you choose for the socket mode (SOCK_DGRAM or SOCK_RAW),
+the beginning of the user data will be at :
+ frame base + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+If you wish to put user data at a custom offset from the beginning of
+the frame (for payload alignment with SOCK_RAW mode for instance) you
+can set tp_net (with SOCK_DGRAM) or tp_mac (with SOCK_RAW). In order
+to make this work it must be enabled previously with setsockopt()
+and the PACKET_TX_HAS_OFF option.
+
--------------------------------------------------------------------------------
+ PACKET_MMAP settings
--------------------------------------------------------------------------------
-
To setup PACKET_MMAP from user level code is done with a call like
- Capture process
@@ -201,7 +211,6 @@ indeed, packet_set_ring checks that the following condition is true
frames_per_block * tp_block_nr == tp_frame_nr
-
Lets see an example, with the following values:
tp_block_size= 4096
@@ -227,7 +236,6 @@ be spawned across two blocks, so there are some details you have to take into
account when choosing the frame_size. See "Mapping and use of the circular
buffer (ring)".
-
--------------------------------------------------------------------------------
+ PACKET_MMAP setting constraints
--------------------------------------------------------------------------------
@@ -264,7 +272,6 @@ User space programs can include /usr/include/sys/user.h and
The pagesize can also be determined dynamically with the getpagesize (2)
system call.
-
Block number limit
--------------------
@@ -284,7 +291,6 @@ called pg_vec, its size limits the number of blocks that can be allocated.
v block #2
block #1
-
kmalloc allocates any number of bytes of physically contiguous memory from
a pool of pre-determined sizes. This pool of memory is maintained by the slab
allocator which is at the end the responsible for doing the allocation and
@@ -299,7 +305,6 @@ pointers to blocks is
131072/4 = 32768 blocks
-
PACKET_MMAP buffer size calculator
------------------------------------
@@ -340,7 +345,6 @@ and a value for <frame size> of 2048 bytes. These parameters will yield
and hence the buffer will have a 262144 MiB size. So it can hold
262144 MiB / 2048 bytes = 134217728 frames
-
Actually, this buffer size is not possible with an i386 architecture.
Remember that the memory is allocated in kernel space, in the case of
an i386 kernel's memory size is limited to 1GiB.
@@ -372,7 +376,6 @@ the following (from include/linux/if_packet.h):
- Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
- Pad to align to TPACKET_ALIGNMENT=16
*/
-
The following are conditions that are checked in packet_set_ring
@@ -413,7 +416,6 @@ and the following flags apply:
#define TP_STATUS_LOSING 4
#define TP_STATUS_CSUMNOTREADY 8
-
TP_STATUS_COPY : This flag indicates that the frame (and associated
meta information) has been truncated because it's
larger than tp_frame_size. This packet can be
@@ -462,7 +464,6 @@ packets are in the ring:
It doesn't incur in a race condition to first check the status value and
then poll for frames.
-
++ Transmission process
Those defines are also used for transmission:
@@ -494,6 +495,196 @@ The user can also use poll() to check if a buffer is available:
retval = poll(&pfd, 1, timeout);
-------------------------------------------------------------------------------
++ What TPACKET versions are available and when to use them?
+-------------------------------------------------------------------------------
+
+ int val = tpacket_version;
+ setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+ getsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+
+where 'tpacket_version' can be TPACKET_V1 (default), TPACKET_V2, TPACKET_V3.
+
+TPACKET_V1:
+ - Default if not otherwise specified by setsockopt(2)
+ - RX_RING, TX_RING available
+ - VLAN metadata information available for packets
+ (TP_STATUS_VLAN_VALID)
+
+TPACKET_V1 --> TPACKET_V2:
+ - Made 64 bit clean due to unsigned long usage in TPACKET_V1
+ structures, thus this also works on 64 bit kernel with 32 bit
+ userspace and the like
+ - Timestamp resolution in nanoseconds instead of microseconds
+ - RX_RING, TX_RING available
+ - How to switch to TPACKET_V2:
+ 1. Replace struct tpacket_hdr by struct tpacket2_hdr
+ 2. Query header len and save
+ 3. Set protocol version to 2, set up ring as usual
+ 4. For getting the sockaddr_ll,
+ use (void *)hdr + TPACKET_ALIGN(hdrlen) instead of
+ (void *)hdr + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+TPACKET_V2 --> TPACKET_V3:
+ - Flexible buffer implementation:
+ 1. Blocks can be configured with non-static frame-size
+ 2. Read/poll is at a block-level (as opposed to packet-level)
+ 3. Added poll timeout to avoid indefinite user-space wait
+ on idle links
+ 4. Added user-configurable knobs:
+ 4.1 block::timeout
+ 4.2 tpkt_hdr::sk_rxhash
+ - RX Hash data available in user space
+ - Currently only RX_RING available
+
+-------------------------------------------------------------------------------
++ AF_PACKET fanout mode
+-------------------------------------------------------------------------------
+
+In the AF_PACKET fanout mode, packet reception can be load balanced among
+processes. This also works in combination with mmap(2) on packet sockets.
+
+Minimal example code by David S. Miller (try things like "./test eth0 hash",
+"./test eth0 lb", etc.):
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+#include <net/if.h>
+
+static const char *device_name;
+static int fanout_type;
+static int fanout_id;
+
+#ifndef PACKET_FANOUT
+# define PACKET_FANOUT 18
+# define PACKET_FANOUT_HASH 0
+# define PACKET_FANOUT_LB 1
+#endif
+
+static int setup_socket(void)
+{
+ int err, fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
+ struct sockaddr_ll ll;
+ struct ifreq ifr;
+ int fanout_arg;
+
+ if (fd < 0) {
+ perror("socket");
+ return EXIT_FAILURE;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, device_name);
+ err = ioctl(fd, SIOCGIFINDEX, &ifr);
+ if (err < 0) {
+ perror("SIOCGIFINDEX");
+ return EXIT_FAILURE;
+ }
+
+ memset(&ll, 0, sizeof(ll));
+ ll.sll_family = AF_PACKET;
+ ll.sll_ifindex = ifr.ifr_ifindex;
+ err = bind(fd, (struct sockaddr *) &ll, sizeof(ll));
+ if (err < 0) {
+ perror("bind");
+ return EXIT_FAILURE;
+ }
+
+ fanout_arg = (fanout_id | (fanout_type << 16));
+ err = setsockopt(fd, SOL_PACKET, PACKET_FANOUT,
+ &fanout_arg, sizeof(fanout_arg));
+ if (err) {
+ perror("setsockopt");
+ return EXIT_FAILURE;
+ }
+
+ return fd;
+}
+
+static void fanout_thread(void)
+{
+ int fd = setup_socket();
+ int limit = 10000;
+
+ if (fd < 0)
+ exit(fd);
+
+ while (limit-- > 0) {
+ char buf[1600];
+ int err;
+
+ err = read(fd, buf, sizeof(buf));
+ if (err < 0) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+ if ((limit % 10) == 0)
+ fprintf(stdout, "(%d) \n", getpid());
+ }
+
+ fprintf(stdout, "%d: Received 10000 packets\n", getpid());
+
+ close(fd);
+ exit(0);
+}
+
+int main(int argc, char **argp)
+{
+ int fd, err;
+ int i;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s INTERFACE {hash|lb}\n", argp[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (!strcmp(argp[2], "hash"))
+ fanout_type = PACKET_FANOUT_HASH;
+ else if (!strcmp(argp[2], "lb"))
+ fanout_type = PACKET_FANOUT_LB;
+ else {
+ fprintf(stderr, "Unknown fanout type [%s]\n", argp[2]);
+ exit(EXIT_FAILURE);
+ }
+
+ device_name = argp[1];
+ fanout_id = getpid() & 0xffff;
+
+ for (i = 0; i < 4; i++) {
+ pid_t pid = fork();
+
+ switch (pid) {
+ case 0:
+ fanout_thread();
+
+ case -1:
+ perror("fork");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ int status;
+
+ wait(&status);
+ }
+
+ return 0;
+}
+
+-------------------------------------------------------------------------------
+ PACKET_TIMESTAMP
-------------------------------------------------------------------------------
@@ -519,6 +710,13 @@ the networking stack is used (the behavior before this setting was added).
See include/linux/net_tstamp.h and Documentation/networking/timestamping
for more information on hardware timestamps.
+-------------------------------------------------------------------------------
++ Miscellaneous bits
+-------------------------------------------------------------------------------
+
+- Packet sockets work well together with Linux socket filters, thus you also
+ might want to have a look at Documentation/networking/filter.txt
+
--------------------------------------------------------------------------------
+ THANKS
--------------------------------------------------------------------------------
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index ef9ee71b4d7f..f9fa6db40a52 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -29,11 +29,9 @@ The kernel configuration option is STMMAC_ETH:
dma_txsize: DMA tx ring size;
buf_sz: DMA buffer size;
tc: control the HW FIFO threshold;
- tx_coe: Enable/Disable Tx Checksum Offload engine;
watchdog: transmit timeout (in milliseconds);
flow_ctrl: Flow control ability [on/off];
pause: Flow Control Pause Time;
- tmrate: timer period (only if timer optimisation is configured).
3) Command line options
Driver parameters can be also passed in command line by using:
@@ -60,17 +58,19 @@ Then the poll method will be scheduled at some future point.
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
buffers in order to avoid the memcpy (Zero-copy).
-4.3) Timer-Driver Interrupt
-Instead of having the device that asynchronously notifies the frame receptions,
-the driver configures a timer to generate an interrupt at regular intervals.
-Based on the granularity of the timer, the frames that are received by the
-device will experience different levels of latency. Some NICs have dedicated
-timer device to perform this task. STMMAC can use either the RTC device or the
-TMU channel 2 on STLinux platforms.
-The timers frequency can be passed to the driver as parameter; when change it,
-take care of both hardware capability and network stability/performance impact.
-Several performance tests on STM platforms showed this optimisation allows to
-spare the CPU while having the maximum throughput.
+4.3) Interrupt Mitigation
+The driver is able to mitigate the number of its DMA interrupts
+using NAPI for the reception on chips older than the 3.50.
+New chips have an HW RX-Watchdog used for this mitigation.
+
+On Tx-side, the mitigation schema is based on a SW timer that calls the
+tx function (stmmac_tx) to reclaim the resource after transmitting the
+frames.
+Also there is another parameter (like a threshold) used to program
+the descriptors avoiding to set the interrupt on completion bit in
+when the frame is sent (xmit).
+
+Mitigation parameters can be tuned by ethtool.
4.4) WOL
Wake up on Lan feature through Magic and Unicast frames are supported for the
@@ -121,6 +121,7 @@ struct plat_stmmacenet_data {
int bugged_jumbo;
int pmt;
int force_sf_dma_mode;
+ int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev);
@@ -156,6 +157,7 @@ Where:
o pmt: core has the embedded power module (optional).
o force_sf_dma_mode: force DMA to use the Store and Forward mode
instead of the Threshold.
+ o riwt_off: force to disable the RX watchdog feature and switch to NAPI mode.
o fix_mac_speed: this callback is used for modifying some syscfg registers
(on ST SoCs) according to the link speed negotiated by the
physical layer .
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index d90d8ec2853d..b9cfd339a6fa 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1905,7 +1905,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
vid - Vendor ID for the device (optional)
pid - Product ID for the device (optional)
nrpacks - Max. number of packets per URB (default: 8)
- async_unlink - Use async unlink mode (default: yes)
device_setup - Device specific magic number (optional)
- Influence depends on the device
- Default: 0x0000
@@ -1917,8 +1916,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
NB: nrpacks parameter can be modified dynamically via sysfs.
Don't put the value over 20. Changing via sysfs has no sanity
check.
- NB: async_unlink=0 would cause Oops. It remains just for
- debugging purpose (if any).
NB: ignore_ctl_error=1 may help when you get an error at accessing
the mixer element such as URB error -22. This happens on some
buggy USB device or the controller.
diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards
index db833ced2cb8..a8fb6e2d3c8b 100644
--- a/Documentation/video4linux/bttv/Cards
+++ b/Documentation/video4linux/bttv/Cards
@@ -43,7 +43,7 @@ Very nice card if you only have satellite TV but several tuners connected
to the card via composite.
Many thanks to Matrix-Vision for giving us 2 cards for free which made
-Bt848a/Bt849 single crytal operation support possible!!!
+Bt848a/Bt849 single crystal operation support possible!!!
diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ
index 395f6c6fdd98..d3f1d7783d1c 100644
--- a/Documentation/video4linux/bttv/Sound-FAQ
+++ b/Documentation/video4linux/bttv/Sound-FAQ
@@ -82,7 +82,7 @@ card installed, you might to check out if you can read these registers
values used by the windows driver. A tool to do this is available
from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it
does'nt work with bt878 boards according to some reports I received.
-Another one with bt878 suport is available from
+Another one with bt878 support is available from
http://btwincap.sourceforge.net/Files/btspy2.00.zip
You might also dig around in the *.ini files of the Windows applications.
diff --git a/Documentation/vm/frontswap.txt b/Documentation/vm/frontswap.txt
index 5ef2d1366425..c71a019be600 100644
--- a/Documentation/vm/frontswap.txt
+++ b/Documentation/vm/frontswap.txt
@@ -193,7 +193,7 @@ faster.
or maybe swap-over-nbd/NFS)?
No. First, the existing swap subsystem doesn't allow for any kind of
-swap hierarchy. Perhaps it could be rewritten to accomodate a hierarchy,
+swap hierarchy. Perhaps it could be rewritten to accommodate a hierarchy,
but this would require fairly drastic changes. Even if it were
rewritten, the existing swap subsystem uses the block I/O layer which
assumes a swap device is fixed size and any page in it is linearly
diff --git a/MAINTAINERS b/MAINTAINERS
index 386fce6715c4..b0b880da6e5c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1680,10 +1680,9 @@ F: drivers/net/ethernet/broadcom/tg3.*
BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
M: Brett Rudley <brudley@broadcom.com>
-M: Roland Vossen <rvossen@broadcom.com>
M: Arend van Spriel <arend@broadcom.com>
M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
-M: Kan Yan <kanyan@broadcom.com>
+M: Hante Meuleman <meuleman@broadcom.com>
L: linux-wireless@vger.kernel.org
L: brcm80211-dev-list@broadcom.com
S: Supported
@@ -3597,7 +3596,7 @@ S: Maintained
F: drivers/input/touchscreen/htcpen.c
HUGETLB FILESYSTEM
-M: William Irwin <wli@holomorphy.com>
+M: Nadia Yvette Chambers <nyc@holomorphy.com>
S: Maintained
F: fs/hugetlbfs/
@@ -3949,7 +3948,9 @@ 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/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
@@ -4833,6 +4834,14 @@ F: Documentation/scsi/megaraid.txt
F: drivers/scsi/megaraid.*
F: drivers/scsi/megaraid/
+MELLANOX ETHERNET DRIVER (mlx4_en)
+M: Amir Vadai <amirv@mellanox.com>
+L: netdev@vger.kernel.org
+S: Supported
+W: http://www.mellanox.com
+Q: http://patchwork.ozlabs.org/project/netdev/list/
+F: drivers/net/ethernet/mellanox/mlx4/en_*
+
MEMORY MANAGEMENT
L: linux-mm@kvack.org
W: http://www.linux-mm.org
@@ -5075,7 +5084,7 @@ NETWORKING [GENERAL]
M: "David S. Miller" <davem@davemloft.net>
L: netdev@vger.kernel.org
W: http://www.linuxfoundation.org/en/Net
-W: http://patchwork.ozlabs.org/project/netdev/list/
+Q: http://patchwork.ozlabs.org/project/netdev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
S: Maintained
@@ -5135,6 +5144,7 @@ F: drivers/net/wireless/
NETWORKING DRIVERS
L: netdev@vger.kernel.org
W: http://www.linuxfoundation.org/en/Net
+Q: http://patchwork.ozlabs.org/project/netdev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
S: Odd Fixes
@@ -5167,6 +5177,7 @@ F: net/nfc/
F: include/linux/nfc.h
F: include/net/nfc/
F: drivers/nfc/
+F: include/linux/platform_data/pn544.h
NFS, SUNRPC, AND LOCKD CLIENTS
M: Trond Myklebust <Trond.Myklebust@netapp.com>
@@ -6442,6 +6453,7 @@ F: drivers/scsi/st*
SCTP PROTOCOL
M: Vlad Yasevich <vyasevich@gmail.com>
M: Sridhar Samudrala <sri@us.ibm.com>
+M: Neil Horman <nhorman@tuxdriver.com>
L: linux-sctp@vger.kernel.org
W: http://lksctp.sourceforge.net
S: Maintained
@@ -7469,8 +7481,7 @@ S: Maintained
F: drivers/net/ethernet/dec/tulip/
TUN/TAP driver
-M: Maxim Krasnyansky <maxk@qualcomm.com>
-L: vtun@office.satix.net
+M: Maxim Krasnyansky <maxk@qti.qualcomm.com>
W: http://vtun.sourceforge.net/tun
S: Maintained
F: Documentation/networking/tuntap.txt
@@ -7592,6 +7603,12 @@ S: Maintained
F: Documentation/usb/acm.txt
F: drivers/usb/class/cdc-acm.*
+USB AR5523 WIRELESS DRIVER
+M: Pontus Fuchs <pontus.fuchs@gmail.com>
+L: linux-wireless@vger.kernel.org
+S: Maintained
+F: drivers/net/wireless/ath/ar5523/
+
USB ATTACHED SCSI
M: Matthew Wilcox <willy@linux.intel.com>
M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
diff --git a/README b/README
index f32710a817fc..a24ec89ba442 100644
--- a/README
+++ b/README
@@ -180,6 +180,10 @@ CONFIGURING the kernel:
with questions already answered.
Additionally updates the dependencies.
+ "make olddefconfig"
+ Like above, but sets new symbols to their default
+ values without prompting.
+
"make defconfig" Create a ./.config file by using the default
symbol values from either arch/$ARCH/defconfig
or arch/$ARCH/configs/${PLATFORM}_defconfig,
diff --git a/arch/alpha/include/asm/mmzone.h b/arch/alpha/include/asm/mmzone.h
index 445dc42e0334..c5b5d6bac9ed 100644
--- a/arch/alpha/include/asm/mmzone.h
+++ b/arch/alpha/include/asm/mmzone.h
@@ -66,7 +66,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
((unsigned long)__va(NODE_DATA(kvaddr_to_nid(kaddr))->node_start_pfn \
<< PAGE_SHIFT))
-/* XXX: FIXME -- wli */
+/* XXX: FIXME -- nyc */
#define kern_addr_valid(kaddr) (0)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 7d2f75be932e..0087d053b77f 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -47,6 +47,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 3f844d26d2c7..a21d0ab3b19e 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -354,8 +354,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
int dac_allowed;
- if (dir == PCI_DMA_NONE)
- BUG();
+ BUG_ON(dir == PCI_DMA_NONE);
dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
return pci_map_single_1(pdev, (char *)page_address(page) + offset,
@@ -378,8 +377,7 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
struct pci_iommu_arena *arena;
long dma_ofs, npages;
- if (dir == PCI_DMA_NONE)
- BUG();
+ BUG_ON(dir == PCI_DMA_NONE);
if (dma_addr >= __direct_map_base
&& dma_addr < __direct_map_base + __direct_map_size) {
@@ -662,8 +660,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
dma_addr_t max_dma;
int dac_allowed;
- if (dir == PCI_DMA_NONE)
- BUG();
+ BUG_ON(dir == PCI_DMA_NONE);
dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
@@ -742,8 +739,7 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
dma_addr_t max_dma;
dma_addr_t fbeg, fend;
- if (dir == PCI_DMA_NONE)
- BUG();
+ BUG_ON(dir == PCI_DMA_NONE);
if (! alpha_mv.mv_pci_tbi)
return;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 08330d9e6a9c..2277f9530b00 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -536,6 +536,8 @@ config ARCH_DOVE
select CPU_V7
select GENERIC_CLOCKEVENTS
select MIGHT_HAVE_PCI
+ select PINCTRL
+ select PINCTRL_DOVE
select PLAT_ORION_LEGACY
select USB_ARCH_HAS_EHCI
help
@@ -548,6 +550,8 @@ config ARCH_KIRKWOOD
select GENERIC_CLOCKEVENTS
select PCI
select PCI_QUIRKS
+ select PINCTRL
+ select PINCTRL_KIRKWOOD
select PLAT_ORION_LEGACY
help
Support for the following Marvell Kirkwood series SoCs:
@@ -646,6 +650,7 @@ config ARCH_TEGRA
select HAVE_CLK
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
+ select SPARSE_IRQ
select USE_OF
help
This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -887,6 +892,7 @@ config ARCH_U8500
select GENERIC_CLOCKEVENTS
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
+ select SPARSE_IRQ
help
Support for ST-Ericsson's Ux500 architecture
@@ -901,6 +907,7 @@ config ARCH_NOMADIK
select MIGHT_HAVE_CACHE_L2X0
select PINCTRL
select PINCTRL_STN8815
+ select SPARSE_IRQ
help
Support for the Nomadik platform by ST-Ericsson
@@ -944,7 +951,7 @@ config ARCH_OMAP
help
Support for TI's OMAP platform (OMAP1/2/3/4).
-config ARCH_VT8500
+config ARCH_VT8500_SINGLE
bool "VIA/WonderMedia 85xx"
select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
@@ -954,21 +961,12 @@ config ARCH_VT8500
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
select HAVE_CLK
+ select MULTI_IRQ_HANDLER
+ select SPARSE_IRQ
select USE_OF
help
Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
-config ARCH_ZYNQ
- bool "Xilinx Zynq ARM Cortex A9 Platform"
- select ARM_AMBA
- select ARM_GIC
- select CPU_V7
- select GENERIC_CLOCKEVENTS
- select ICST
- select MIGHT_HAVE_CACHE_L2X0
- select USE_OF
- help
- Support for Xilinx Zynq ARM Cortex A9 Platform
endchoice
menu "Multiple platform selection"
@@ -1069,7 +1067,6 @@ source "arch/arm/mach-mxs/Kconfig"
source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-nomadik/Kconfig"
-source "arch/arm/plat-nomadik/Kconfig"
source "arch/arm/plat-omap/Kconfig"
@@ -1132,8 +1129,12 @@ source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-vexpress/Kconfig"
source "arch/arm/plat-versatile/Kconfig"
+source "arch/arm/mach-vt8500/Kconfig"
+
source "arch/arm/mach-w90x900/Kconfig"
+source "arch/arm/mach-zynq/Kconfig"
+
# Definitions to make life easier
config ARCH_ACORN
bool
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 04a3f0d1d053..661030d6bc6c 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -132,6 +132,23 @@ choice
their output to UART1 serial port on DaVinci TNETV107X
devices.
+ config DEBUG_ZYNQ_UART0
+ bool "Kernel low-level debugging on Xilinx Zynq using UART0"
+ depends on ARCH_ZYNQ
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART0 on the Zynq platform.
+
+ config DEBUG_ZYNQ_UART1
+ bool "Kernel low-level debugging on Xilinx Zynq using UART1"
+ depends on ARCH_ZYNQ
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART1 on the Zynq platform.
+
+ If you have a ZC702 board and want early boot messages to
+ appear on the USB serial adaptor, select this option.
+
config DEBUG_DC21285_PORT
bool "Kernel low-level debugging messages via footbridge serial port"
depends on FOOTBRIDGE
@@ -209,20 +226,12 @@ choice
Say Y here if you want kernel low-level debugging support
on i.MX50 or i.MX53.
- config DEBUG_IMX6Q_UART2
- bool "i.MX6Q Debug UART2"
+ config DEBUG_IMX6Q_UART
+ bool "i.MX6Q Debug UART"
depends on SOC_IMX6Q
help
Say Y here if you want kernel low-level debugging support
- on i.MX6Q UART2. This is correct for e.g. the SabreLite
- board.
-
- config DEBUG_IMX6Q_UART4
- bool "i.MX6Q Debug UART4"
- depends on SOC_IMX6Q
- help
- Say Y here if you want kernel low-level debugging support
- on i.MX6Q UART4.
+ on i.MX6Q.
config DEBUG_MMP_UART2
bool "Kernel low-level debugging message via MMP UART2"
@@ -370,6 +379,13 @@ choice
Say Y here if you want kernel low-level debugging support
on Allwinner A1X based platforms on the UART1.
+ config DEBUG_TEGRA_UART
+ depends on ARCH_TEGRA
+ bool "Use Tegra UART for low-level debug"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Tegra based platforms.
+
config DEBUG_VEXPRESS_UART0_DETECT
bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
depends on ARCH_VEXPRESS && CPU_CP15_MMU
@@ -434,6 +450,45 @@ choice
endchoice
+config DEBUG_IMX6Q_UART_PORT
+ int "i.MX6Q Debug UART Port (1-5)" if DEBUG_IMX6Q_UART
+ range 1 5
+ default 1
+ depends on SOC_IMX6Q
+ help
+ Choose UART port on which kernel low-level debug messages
+ should be output.
+
+choice
+ prompt "Low-level debug console UART"
+ depends on DEBUG_LL && DEBUG_TEGRA_UART
+
+ config TEGRA_DEBUG_UART_AUTO_ODMDATA
+ bool "Via ODMDATA"
+ help
+ Automatically determines which UART to use for low-level debug based
+ on the ODMDATA value. This value is part of the BCT, and is written
+ to the boot memory device using nvflash, or other flashing tool.
+ When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
+ 0/1/2/3/4 are UART A/B/C/D/E.
+
+ config TEGRA_DEBUG_UARTA
+ bool "UART A"
+
+ config TEGRA_DEBUG_UARTB
+ bool "UART B"
+
+ config TEGRA_DEBUG_UARTC
+ bool "UART C"
+
+ config TEGRA_DEBUG_UARTD
+ bool "UART D"
+
+ config TEGRA_DEBUG_UARTE
+ bool "UART E"
+
+endchoice
+
config DEBUG_LL_INCLUDE
string
default "debug/icedcc.S" if DEBUG_ICEDCC
@@ -443,8 +498,7 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX31_IMX35_UART || \
DEBUG_IMX51_UART || \
DEBUG_IMX50_IMX53_UART ||\
- DEBUG_IMX6Q_UART2 || \
- DEBUG_IMX6Q_UART4
+ DEBUG_IMX6Q_UART
default "debug/highbank.S" if DEBUG_HIGHBANK_UART
default "debug/mvebu.S" if DEBUG_MVEBU_UART
default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
@@ -452,6 +506,8 @@ config DEBUG_LL_INCLUDE
default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1
+ default "debug/tegra.S" if DEBUG_TEGRA_UART
+ default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
default "mach/debug-macro.S"
config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 9c60f474a559..30c443c406f3 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -202,7 +202,6 @@ machine-$(CONFIG_ARCH_SUNXI) += sunxi
plat-$(CONFIG_ARCH_OMAP) += omap
plat-$(CONFIG_ARCH_S3C64XX) += samsung
plat-$(CONFIG_PLAT_IOP) += iop
-plat-$(CONFIG_PLAT_NOMADIK) += nomadik
plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
plat-$(CONFIG_PLAT_S3C24XX) += s3c24xx samsung
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f3f2f80cdf3b..2af359cfe985 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -34,6 +34,8 @@ dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
dtb-$(CONFIG_ARCH_BCM) += bcm11351-brt.dtb
+dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
+ da850-evm.dtb
dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
dove-cubox.dtb \
dove-dove-db.dtb
@@ -41,7 +43,10 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos4210-smdkv310.dtb \
exynos4210-trats.dtb \
exynos5250-smdk5250.dtb \
- exynos5440-ssdk5440.dtb
+ exynos5440-ssdk5440.dtb \
+ exynos4412-smdk4412.dtb \
+ exynos5250-smdk5250.dtb \
+ exynos5250-snow.dtb
dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
ecx-2000.dtb
dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
@@ -79,16 +84,20 @@ dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \
imx53-qsb.dtb \
imx53-smd.dtb \
imx6q-arm2.dtb \
+ imx6q-sabreauto.dtb \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb
dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
imx23-olinuxino.dtb \
imx23-stmp378x_devb.dtb \
+ imx28-apf28.dtb \
+ imx28-apf28dev.dtb \
imx28-apx4devkit.dtb \
imx28-cfa10036.dtb \
imx28-cfa10049.dtb \
imx28-evk.dtb \
imx28-m28evk.dtb \
+ imx28-sps1.dtb \
imx28-tx28.dtb
dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
omap3-beagle.dtb \
@@ -105,7 +114,10 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
am335x-bone.dtb
dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
-dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
+dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
+ hrefprev60.dtb \
+ hrefv60plus.dtb \
+ ccu9540.dtb
dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
r8a7740-armadillo800eva.dtb \
sh73a0-kzm9g.dtb \
@@ -137,6 +149,7 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
wm8505-ref.dtb \
wm8650-mid.dtb
+dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
targets += dtbs
endif
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index 2c338889df1b..11b240c5d323 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -128,3 +128,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <1>;
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 9f65f17ebdf8..d6496440fcea 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -236,3 +236,11 @@
};
};
};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <1>;
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 20a3f29a6bfe..c2f14e875eb6 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -338,5 +338,52 @@
power = <250>;
ti,hwmods = "usb_otg_hs";
};
+
+ mac: ethernet@4a100000 {
+ compatible = "ti,cpsw";
+ ti,hwmods = "cpgmac0";
+ cpdma_channels = <8>;
+ ale_entries = <1024>;
+ bd_ram_size = <0x2000>;
+ no_bd_ram = <0>;
+ rx_descs = <64>;
+ mac_control = <0x20>;
+ slaves = <2>;
+ cpts_active_slave = <0>;
+ cpts_clock_mult = <0x80000000>;
+ cpts_clock_shift = <29>;
+ reg = <0x4a100000 0x800
+ 0x4a101200 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+ /*
+ * c0_rx_thresh_pend
+ * c0_rx_pend
+ * c0_tx_pend
+ * c0_misc_pend
+ */
+ interrupts = <40 41 42 43>;
+ ranges;
+
+ davinci_mdio: mdio@4a101000 {
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "davinci_mdio";
+ bus_freq = <1000000>;
+ reg = <0x4a101000 0x100>;
+ };
+
+ cpsw_emac0: slave@4a100200 {
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ cpsw_emac1: slave@4a100300 {
+ /* Filled in by U-Boot */
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index b1d3fab60e0a..68bccf41a2c6 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -29,6 +29,7 @@
tcb0 = &tcb0;
tcb1 = &tcb1;
i2c0 = &i2c0;
+ ssc0 = &ssc0;
};
cpus {
cpu@0 {
@@ -445,6 +446,13 @@
status = "disabled";
};
+ ssc0: ssc@fffbc000 {
+ compatible = "atmel,at91rm9200-ssc";
+ reg = <0xfffbc000 0x4000>;
+ interrupts = <14 4 5>;
+ status = "disabled";
+ };
+
adc0: adc@fffe0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffe0000 0x100>;
@@ -479,6 +487,12 @@
trigger-external;
};
};
+
+ watchdog@fffffd40 {
+ compatible = "atmel,at91sam9260-wdt";
+ reg = <0xfffffd40 0x10>;
+ status = "disabled";
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 66106eecf1ed..8e6251f1f7a3 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -25,6 +25,8 @@
gpio4 = &pioE;
tcb0 = &tcb0;
i2c0 = &i2c0;
+ ssc0 = &ssc0;
+ ssc1 = &ssc1;
};
cpus {
cpu@0 {
@@ -362,6 +364,20 @@
status = "disabled";
};
+ ssc0: ssc@fff98000 {
+ compatible = "atmel,at91rm9200-ssc";
+ reg = <0xfff98000 0x4000>;
+ interrupts = <16 4 5>;
+ status = "disable";
+ };
+
+ ssc1: ssc@fff9c000 {
+ compatible = "atmel,at91rm9200-ssc";
+ reg = <0xfff9c000 0x4000>;
+ interrupts = <17 4 5>;
+ status = "disable";
+ };
+
macb0: ethernet@fffbc000 {
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xfffbc000 0x100>;
@@ -404,6 +420,12 @@
#size-cells = <0>;
status = "disabled";
};
+
+ watchdog@fffffd40 {
+ compatible = "atmel,at91sam9260-wdt";
+ reg = <0xfffffd40 0x10>;
+ status = "disabled";
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index 32a500a0e481..da15e83e7f17 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -30,6 +30,16 @@
ahb {
apb {
+ pinctrl@fffff400 {
+ board {
+ pinctrl_pck0_as_mck: pck0_as_mck {
+ atmel,pins =
+ <2 1 0x2 0x0>; /* PC1 periph B */
+ };
+
+ };
+ };
+
dbgu: serial@fffff200 {
status = "okay";
};
@@ -81,6 +91,11 @@
};
};
};
+
+ ssc0: ssc@fffbc000 {
+ status = "okay";
+ pinctrl-0 = <&pinctrl_ssc0_tx>;
+ };
};
nand0: nand@40000000 {
@@ -144,7 +159,7 @@
reg = <0x50>;
};
- wm8731@1b {
+ wm8731: wm8731@1b {
compatible = "wm8731";
reg = <0x1b>;
};
@@ -169,4 +184,19 @@
gpio-key,wakeup;
};
};
+
+ sound {
+ compatible = "atmel,at91sam9g20ek-wm8731-audio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+ atmel,model = "wm8731 @ AT91SAMG20EK";
+
+ atmel,audio-routing =
+ "Ext Spk", "LHPOUT",
+ "Int Mic", "MICIN";
+
+ atmel,ssc-controller = <&ssc0>;
+ atmel,audio-codec = <&wm8731>;
+ };
};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 0741caeeced1..fa1ae0c5479c 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -31,6 +31,8 @@
tcb1 = &tcb1;
i2c0 = &i2c0;
i2c1 = &i2c1;
+ ssc0 = &ssc0;
+ ssc1 = &ssc1;
};
cpus {
cpu@0 {
@@ -419,6 +421,20 @@
status = "disabled";
};
+ ssc0: ssc@fff9c000 {
+ compatible = "atmel,at91sam9g45-ssc";
+ reg = <0xfff9c000 0x4000>;
+ interrupts = <16 4 5>;
+ status = "disable";
+ };
+
+ ssc1: ssc@fffa0000 {
+ compatible = "atmel,at91sam9g45-ssc";
+ reg = <0xfffa0000 0x4000>;
+ interrupts = <17 4 5>;
+ status = "disable";
+ };
+
adc0: adc@fffb0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffb0000 0x100>;
@@ -473,6 +489,12 @@
#size-cells = <0>;
status = "disabled";
};
+
+ watchdog@fffffd40 {
+ compatible = "atmel,at91sam9260-wdt";
+ reg = <0xfffffd40 0x10>;
+ status = "disabled";
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 7ee49e8daf98..617ede541ca2 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -30,6 +30,7 @@
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
+ ssc0 = &ssc0;
};
cpus {
cpu@0 {
@@ -87,6 +88,13 @@
interrupts = <1 4 7>;
};
+ ssc0: ssc@f0010000 {
+ compatible = "atmel,at91sam9g45-ssc";
+ reg = <0xf0010000 0x4000>;
+ interrupts = <28 4 5>;
+ status = "disable";
+ };
+
tcb0: timer@f8008000 {
compatible = "atmel,at91sam9x5-tcb";
reg = <0xf8008000 0x100>;
diff --git a/arch/arm/boot/dts/ccu9540.dts b/arch/arm/boot/dts/ccu9540.dts
new file mode 100644
index 000000000000..04305463f00d
--- /dev/null
+++ b/arch/arm/boot/dts/ccu9540.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * 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/ "dbx5x0.dtsi"
+
+/ {
+ model = "ST-Ericsson CCU9540 platform with Device Tree";
+ compatible = "st-ericsson,ccu9540", "st-ericsson,u9540";
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+
+ soc-u9500 {
+ uart@80120000 {
+ status = "okay";
+ };
+
+ uart@80121000 {
+ status = "okay";
+ };
+
+ uart@80007000 {
+ status = "okay";
+ };
+
+ // External Micro SD slot
+ sdi0_per1@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ mmc-cap-sd-highspeed;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+ cd-gpios = <&gpio7 6 0x4>; // 230
+ cd-inverted;
+
+ status = "okay";
+ };
+
+
+ // WLAN SDIO channel
+ sdi1_per2@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+
+ status = "okay";
+ };
+
+ // On-board eMMC
+ sdi4_per2@80114000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi
new file mode 100644
index 000000000000..fddd17417433
--- /dev/null
+++ b/arch/arm/boot/dts/cros5250-common.dtsi
@@ -0,0 +1,184 @@
+/*
+ * Common device tree include for all Exynos 5250 boards based off of Daisy.
+ *
+ * Copyright (c) 2012 Google, 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.
+*/
+
+/ {
+ aliases {
+ };
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ };
+
+ i2c@12C60000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <378000>;
+ gpios = <&gpb3 0 2 3 0>,
+ <&gpb3 1 2 3 0>;
+ };
+
+ i2c@12C70000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <378000>;
+ gpios = <&gpb3 2 2 3 0>,
+ <&gpb3 3 2 3 0>;
+ };
+
+ i2c@12C80000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+
+ /*
+ * Disabled pullups since external part has its own pullups and
+ * double-pulling gets us out of spec in some cases.
+ */
+ gpios = <&gpa0 6 3 0 0>,
+ <&gpa0 7 3 0 0>;
+
+ hdmiddc@50 {
+ compatible = "samsung,exynos5-hdmiddc";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@12C90000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ gpios = <&gpa1 2 3 3 0>,
+ <&gpa1 3 3 3 0>;
+ };
+
+ i2c@12CA0000 {
+ status = "disabled";
+ };
+
+ i2c@12CB0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ gpios = <&gpa2 2 3 3 0>,
+ <&gpa2 3 3 3 0>;
+ };
+
+ i2c@12CC0000 {
+ status = "disabled";
+ };
+
+ i2c@12CD0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ gpios = <&gpb2 2 3 3 0>,
+ <&gpb2 3 3 3 0>;
+ };
+
+ i2c@12CE0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <378000>;
+
+ hdmiphy@38 {
+ compatible = "samsung,exynos5-hdmiphy";
+ reg = <0x38>;
+ };
+ };
+
+ dwmmc0@12200000 {
+ 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 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <8>;
+ gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+ <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+ <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+ <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+ <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+ };
+ };
+
+ dwmmc1@12210000 {
+ status = "disabled";
+ };
+
+ dwmmc2@12220000 {
+ 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 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
+ wp-gpios = <&gpc2 1 0 0 3>;
+ gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
+ <&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
+ <&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>;
+ };
+ };
+
+ dwmmc3@12230000 {
+ 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 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ /* See board-specific dts files for GPIOs */
+ };
+ };
+
+ spi_0: spi@12d20000 {
+ status = "disabled";
+ };
+
+ spi_1: spi@12d30000 {
+ gpios = <&gpa2 4 2 3 0>,
+ <&gpa2 6 2 3 0>,
+ <&gpa2 7 2 3 0>;
+ samsung,spi-src-clk = <0>;
+ num-cs = <1>;
+ };
+
+ spi_2: spi@12d40000 {
+ status = "disabled";
+ };
+
+ hdmi {
+ hpd-gpio = <&gpx3 7 0xf 1 3>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power";
+ gpios = <&gpx1 3 0 0x10000 0>;
+ linux,code = <116>; /* KEY_POWER */
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 731086b2fca2..0d69322f689f 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -217,123 +217,103 @@
// DB8500_REGULATOR_VAPE
db8500_vape_reg: db8500_vape {
regulator-compatible = "db8500_vape";
- regulator-name = "db8500-vape";
regulator-always-on;
};
// DB8500_REGULATOR_VARM
db8500_varm_reg: db8500_varm {
regulator-compatible = "db8500_varm";
- regulator-name = "db8500-varm";
};
// DB8500_REGULATOR_VMODEM
db8500_vmodem_reg: db8500_vmodem {
regulator-compatible = "db8500_vmodem";
- regulator-name = "db8500-vmodem";
};
// DB8500_REGULATOR_VPLL
db8500_vpll_reg: db8500_vpll {
regulator-compatible = "db8500_vpll";
- regulator-name = "db8500-vpll";
};
// DB8500_REGULATOR_VSMPS1
db8500_vsmps1_reg: db8500_vsmps1 {
regulator-compatible = "db8500_vsmps1";
- regulator-name = "db8500-vsmps1";
};
// DB8500_REGULATOR_VSMPS2
db8500_vsmps2_reg: db8500_vsmps2 {
regulator-compatible = "db8500_vsmps2";
- regulator-name = "db8500-vsmps2";
};
// DB8500_REGULATOR_VSMPS3
db8500_vsmps3_reg: db8500_vsmps3 {
regulator-compatible = "db8500_vsmps3";
- regulator-name = "db8500-vsmps3";
};
// DB8500_REGULATOR_VRF1
db8500_vrf1_reg: db8500_vrf1 {
regulator-compatible = "db8500_vrf1";
- regulator-name = "db8500-vrf1";
};
// DB8500_REGULATOR_SWITCH_SVAMMDSP
db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
regulator-compatible = "db8500_sva_mmdsp";
- regulator-name = "db8500-sva-mmdsp";
};
// DB8500_REGULATOR_SWITCH_SVAMMDSPRET
db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
regulator-compatible = "db8500_sva_mmdsp_ret";
- regulator-name = "db8500-sva-mmdsp-ret";
};
// DB8500_REGULATOR_SWITCH_SVAPIPE
db8500_sva_pipe_reg: db8500_sva_pipe {
regulator-compatible = "db8500_sva_pipe";
- regulator-name = "db8500_sva_pipe";
};
// DB8500_REGULATOR_SWITCH_SIAMMDSP
db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
regulator-compatible = "db8500_sia_mmdsp";
- regulator-name = "db8500_sia_mmdsp";
};
// DB8500_REGULATOR_SWITCH_SIAMMDSPRET
db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
- regulator-name = "db8500-sia-mmdsp-ret";
};
// DB8500_REGULATOR_SWITCH_SIAPIPE
db8500_sia_pipe_reg: db8500_sia_pipe {
regulator-compatible = "db8500_sia_pipe";
- regulator-name = "db8500-sia-pipe";
};
// DB8500_REGULATOR_SWITCH_SGA
db8500_sga_reg: db8500_sga {
regulator-compatible = "db8500_sga";
- regulator-name = "db8500-sga";
vin-supply = <&db8500_vape_reg>;
};
// DB8500_REGULATOR_SWITCH_B2R2_MCDE
db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
regulator-compatible = "db8500_b2r2_mcde";
- regulator-name = "db8500-b2r2-mcde";
vin-supply = <&db8500_vape_reg>;
};
// DB8500_REGULATOR_SWITCH_ESRAM12
db8500_esram12_reg: db8500_esram12 {
regulator-compatible = "db8500_esram12";
- regulator-name = "db8500-esram12";
};
// DB8500_REGULATOR_SWITCH_ESRAM12RET
db8500_esram12_ret_reg: db8500_esram12_ret {
regulator-compatible = "db8500_esram12_ret";
- regulator-name = "db8500-esram12-ret";
};
// DB8500_REGULATOR_SWITCH_ESRAM34
db8500_esram34_reg: db8500_esram34 {
regulator-compatible = "db8500_esram34";
- regulator-name = "db8500-esram34";
};
// DB8500_REGULATOR_SWITCH_ESRAM34RET
db8500_esram34_ret_reg: db8500_esram34_ret {
regulator-compatible = "db8500_esram34_ret";
- regulator-name = "db8500-esram34-ret";
};
};
@@ -412,7 +392,6 @@
// supplies to the display/camera
ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
regulator-compatible = "ab8500_ldo_aux1";
- regulator-name = "V-DISPLAY";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2900000>;
regulator-boot-on;
@@ -423,7 +402,6 @@
// supplies to the on-board eMMC
ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
regulator-compatible = "ab8500_ldo_aux2";
- regulator-name = "V-eMMC1";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <3300000>;
};
@@ -431,7 +409,6 @@
// supply for VAUX3; SDcard slots
ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
regulator-compatible = "ab8500_ldo_aux3";
- regulator-name = "V-MMC-SD";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <3300000>;
};
@@ -439,49 +416,41 @@
// supply for v-intcore12; VINTCORE12 LDO
ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
regulator-compatible = "ab8500_ldo_initcore";
- regulator-name = "V-INTCORE";
};
// supply for tvout; gpadc; TVOUT LDO
ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
regulator-compatible = "ab8500_ldo_tvout";
- regulator-name = "V-TVOUT";
};
// supply for ab8500-usb; USB LDO
ab8500_ldo_usb_reg: ab8500_ldo_usb {
regulator-compatible = "ab8500_ldo_usb";
- regulator-name = "dummy";
};
// supply for ab8500-vaudio; VAUDIO LDO
ab8500_ldo_audio_reg: ab8500_ldo_audio {
regulator-compatible = "ab8500_ldo_audio";
- regulator-name = "V-AUD";
};
// supply for v-anamic1 VAMic1-LDO
ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
regulator-compatible = "ab8500_ldo_anamic1";
- regulator-name = "V-AMIC1";
};
// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
regulator-compatible = "ab8500_ldo_amamic2";
- regulator-name = "V-AMIC2";
};
// supply for v-dmic; VDMIC LDO
ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
regulator-compatible = "ab8500_ldo_dmic";
- regulator-name = "V-DMIC";
};
// supply for U8500 CSI/DSI; VANA LDO
ab8500_ldo_ana_reg: ab8500_ldo_ana {
regulator-compatible = "ab8500_ldo_ana";
- regulator-name = "V-CSI/DSI";
};
};
};
@@ -585,42 +554,42 @@
status = "disabled";
};
- sdi@80126000 {
+ sdi0_per1@80126000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80126000 0x1000>;
interrupts = <0 60 0x4>;
status = "disabled";
};
- sdi@80118000 {
+ sdi1_per2@80118000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80118000 0x1000>;
interrupts = <0 50 0x4>;
status = "disabled";
};
- sdi@80005000 {
+ sdi2_per3@80005000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80005000 0x1000>;
interrupts = <0 41 0x4>;
status = "disabled";
};
- sdi@80119000 {
+ sdi3_per2@80119000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80119000 0x1000>;
interrupts = <0 59 0x4>;
status = "disabled";
};
- sdi@80114000 {
+ sdi4_per2@80114000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80114000 0x1000>;
interrupts = <0 99 0x4>;
status = "disabled";
};
- sdi@80008000 {
+ sdi5_per3@80008000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80008000 0x1000>;
interrupts = <0 100 0x4>;
@@ -674,5 +643,18 @@
status = "disabled";
};
+ vmmci: regulator-gpio {
+ compatible = "regulator-gpio";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2600000>;
+ regulator-name = "mmci-reg";
+ regulator-type = "voltage";
+
+ states = <1800000 0x1
+ 2900000 0x0>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 0adbd5a38095..fed7d3f9f431 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -40,3 +40,13 @@
reg = <0>;
};
};
+
+&pinctrl {
+ pinctrl-0 = <&pmx_gpio_18>;
+ pinctrl-names = "default";
+
+ pmx_gpio_18: pmx-gpio-18 {
+ marvell,pins = "mpp18";
+ marvell,function = "gpio";
+ };
+};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 5a00022383e7..61f391412a5a 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -4,6 +4,12 @@
compatible = "marvell,dove";
model = "Marvell Armada 88AP510 SoC";
+ aliases {
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ gpio2 = &gpio2;
+ };
+
soc@f1000000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -72,7 +78,8 @@
#gpio-cells = <2>;
gpio-controller;
reg = <0xd0400 0x20>;
- ngpio = <32>;
+ ngpios = <32>;
+ interrupt-controller;
interrupts = <12>, <13>, <14>, <60>;
};
@@ -81,7 +88,8 @@
#gpio-cells = <2>;
gpio-controller;
reg = <0xd0420 0x20>;
- ngpio = <32>;
+ ngpios = <32>;
+ interrupt-controller;
interrupts = <61>;
};
@@ -90,7 +98,12 @@
#gpio-cells = <2>;
gpio-controller;
reg = <0xe8400 0x0c>;
- ngpio = <8>;
+ ngpios = <8>;
+ };
+
+ pinctrl: pinctrl@d0200 {
+ compatible = "marvell,dove-pinctrl";
+ reg = <0xd0200 0x10>;
};
spi0: spi@10600 {
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index b7354e6506de..96e50f569433 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -22,10 +22,22 @@
status = "okay";
};
+ usart0: serial@fffb0000 {
+ status = "okay";
+ };
+
+ usart2: serial@fffb8000 {
+ status = "okay";
+ };
+
usb1: gadget@fffa4000 {
atmel,vbus-gpio = <&pioC 5 0>;
status = "okay";
};
+
+ watchdog@fffffd40 {
+ status = "okay";
+ };
};
usb0: ohci@00500000 {
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 96d4462730fb..e1347fceb5bc 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -28,6 +28,44 @@
spi0 = &spi_0;
spi1 = &spi_1;
spi2 = &spi_2;
+ i2c0 = &i2c_0;
+ i2c1 = &i2c_1;
+ i2c2 = &i2c_2;
+ i2c3 = &i2c_3;
+ i2c4 = &i2c_4;
+ i2c5 = &i2c_5;
+ i2c6 = &i2c_6;
+ i2c7 = &i2c_7;
+ };
+
+ pd_mfc: mfc-power-domain@10023C40 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C40 0x20>;
+ };
+
+ pd_g3d: g3d-power-domain@10023C60 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C60 0x20>;
+ };
+
+ pd_lcd0: lcd0-power-domain@10023C80 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C80 0x20>;
+ };
+
+ pd_tv: tv-power-domain@10023C20 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C20 0x20>;
+ };
+
+ pd_cam: cam-power-domain@10023C00 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C00 0x20>;
+ };
+
+ pd_gps: gps-power-domain@10023CE0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023CE0 0x20>;
};
gic:interrupt-controller@10490000 {
@@ -121,7 +159,7 @@
status = "disabled";
};
- i2c@13860000 {
+ i2c_0: i2c@13860000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -130,7 +168,7 @@
status = "disabled";
};
- i2c@13870000 {
+ i2c_1: i2c@13870000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -139,7 +177,7 @@
status = "disabled";
};
- i2c@13880000 {
+ i2c_2: i2c@13880000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -148,7 +186,7 @@
status = "disabled";
};
- i2c@13890000 {
+ i2c_3: i2c@13890000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -157,7 +195,7 @@
status = "disabled";
};
- i2c@138A0000 {
+ i2c_4: i2c@138A0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -166,7 +204,7 @@
status = "disabled";
};
- i2c@138B0000 {
+ i2c_5: i2c@138B0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -175,7 +213,7 @@
status = "disabled";
};
- i2c@138C0000 {
+ i2c_6: i2c@138C0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
@@ -184,7 +222,7 @@
status = "disabled";
};
- i2c@138D0000 {
+ i2c_7: i2c@138D0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "samsung,s3c2440-i2c";
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 3e68f52e8454..f2710018e84e 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -22,38 +22,54 @@
compatible = "insignal,origen", "samsung,exynos4210";
memory {
- reg = <0x40000000 0x40000000>;
+ reg = <0x40000000 0x10000000
+ 0x50000000 0x10000000
+ 0x60000000 0x10000000
+ 0x70000000 0x10000000>;
};
chosen {
bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
};
+ mmc_reg: voltage-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "VMEM_VDD_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpx1 1 0>;
+ enable-active-high;
+ };
+
sdhci@12530000 {
- samsung,sdhci-bus-width = <4>;
- linux,mmc_cap_4_bit_data;
- samsung,sdhci-cd-internal;
- gpio-cd = <&gpk2 2 2 3 3>;
- gpios = <&gpk2 0 2 0 3>,
- <&gpk2 1 2 0 3>,
- <&gpk2 3 2 3 3>,
- <&gpk2 4 2 3 3>,
- <&gpk2 5 2 3 3>,
- <&gpk2 6 2 3 3>;
+ bus-width = <4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+ pinctrl-names = "default";
+ vmmc-supply = <&mmc_reg>;
status = "okay";
};
sdhci@12510000 {
- samsung,sdhci-bus-width = <4>;
- linux,mmc_cap_4_bit_data;
- samsung,sdhci-cd-internal;
- gpio-cd = <&gpk0 2 2 3 3>;
- gpios = <&gpk0 0 2 0 3>,
- <&gpk0 1 2 0 3>,
- <&gpk0 3 2 3 3>,
- <&gpk0 4 2 3 3>,
- <&gpk0 5 2 3 3>,
- <&gpk0 6 2 3 3>;
+ bus-width = <4>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>;
+ pinctrl-names = "default";
+ vmmc-supply = <&mmc_reg>;
+ status = "okay";
+ };
+
+ serial@13800000 {
+ status = "okay";
+ };
+
+ serial@13810000 {
+ status = "okay";
+ };
+
+ serial@13820000 {
+ status = "okay";
+ };
+
+ serial@13830000 {
status = "okay";
};
@@ -64,35 +80,35 @@
up {
label = "Up";
- gpios = <&gpx2 0 0 0x10000 2>;
+ gpios = <&gpx2 0 1>;
linux,code = <103>;
gpio-key,wakeup;
};
down {
label = "Down";
- gpios = <&gpx2 1 0 0x10000 2>;
+ gpios = <&gpx2 1 1>;
linux,code = <108>;
gpio-key,wakeup;
};
back {
label = "Back";
- gpios = <&gpx1 7 0 0x10000 2>;
+ gpios = <&gpx1 7 1>;
linux,code = <158>;
gpio-key,wakeup;
};
home {
label = "Home";
- gpios = <&gpx1 6 0 0x10000 2>;
+ gpios = <&gpx1 6 1>;
linux,code = <102>;
gpio-key,wakeup;
};
menu {
label = "Menu";
- gpios = <&gpx1 5 0 0x10000 2>;
+ gpios = <&gpx1 5 1>;
linux,code = <139>;
gpio-key,wakeup;
};
@@ -101,7 +117,7 @@
leds {
compatible = "gpio-leds";
status {
- gpios = <&gpx1 3 0 0x10000 2>;
+ gpios = <&gpx1 3 1>;
linux,default-trigger = "heartbeat";
};
};
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index 6a4a1a04221c..55a2efb763d1 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -482,196 +482,196 @@
samsung,pins = "gpk0-0";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd0_cmd: sd0-cmd {
samsung,pins = "gpk0-1";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd0_cd: sd0-cd {
samsung,pins = "gpk0-2";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd0_bus1: sd0-bus-width1 {
samsung,pins = "gpk0-3";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd0_bus4: sd0-bus-width4 {
samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd0_bus8: sd0-bus-width8 {
samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_clk: sd4-clk {
samsung,pins = "gpk0-0";
samsung,pin-function = <3>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_cmd: sd4-cmd {
samsung,pins = "gpk0-1";
samsung,pin-function = <3>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_cd: sd4-cd {
samsung,pins = "gpk0-2";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_bus1: sd4-bus-width1 {
samsung,pins = "gpk0-3";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_bus4: sd4-bus-width4 {
samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd4_bus8: sd4-bus-width8 {
samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
samsung,pin-function = <3>;
samsung,pin-pud = <4>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd1_clk: sd1-clk {
samsung,pins = "gpk1-0";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd1_cmd: sd1-cmd {
samsung,pins = "gpk1-1";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd1_cd: sd1-cd {
samsung,pins = "gpk1-2";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd1_bus1: sd1-bus-width1 {
samsung,pins = "gpk1-3";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd1_bus4: sd1-bus-width4 {
samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_clk: sd2-clk {
samsung,pins = "gpk2-0";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_cmd: sd2-cmd {
samsung,pins = "gpk2-1";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_cd: sd2-cd {
samsung,pins = "gpk2-2";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_bus1: sd2-bus-width1 {
samsung,pins = "gpk2-3";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_bus4: sd2-bus-width4 {
samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd2_bus8: sd2-bus-width8 {
samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd3_clk: sd3-clk {
samsung,pins = "gpk3-0";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd3_cmd: sd3-cmd {
samsung,pins = "gpk3-1";
samsung,pin-function = <2>;
samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd3_cd: sd3-cd {
samsung,pins = "gpk3-2";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd3_bus1: sd3-bus-width1 {
samsung,pins = "gpk3-3";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
sd3_bus4: sd3-bus-width4 {
samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
samsung,pin-function = <2>;
samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
+ samsung,pin-drv = <3>;
};
eint0: ext-int0 {
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
index 63610c3ba3af..9b23a8255e39 100644
--- a/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -43,6 +43,22 @@
status = "okay";
};
+ serial@13800000 {
+ status = "okay";
+ };
+
+ serial@13810000 {
+ status = "okay";
+ };
+
+ serial@13820000 {
+ status = "okay";
+ };
+
+ serial@13830000 {
+ status = "okay";
+ };
+
keypad@100A0000 {
samsung,keypad-num-rows = <2>;
samsung,keypad-num-columns = <8>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index a21511c14071..c346b64dff55 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -35,24 +35,15 @@
regulator-name = "VMEM_VDD_2.8V";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
- gpio = <&gpk0 2 1 0 0>;
+ gpio = <&gpk0 2 0>;
enable-active-high;
};
sdhci_emmc: sdhci@12510000 {
bus-width = <8>;
non-removable;
- broken-voltage;
- gpios = <&gpk0 0 2 0 3>,
- <&gpk0 1 2 0 3>,
- <&gpk0 3 2 2 3>,
- <&gpk0 4 2 2 3>,
- <&gpk0 5 2 2 3>,
- <&gpk0 6 2 2 3>,
- <&gpk1 3 3 3 3>,
- <&gpk1 4 3 3 3>,
- <&gpk1 5 3 3 3>,
- <&gpk1 6 3 3 3>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>;
+ pinctrl-names = "default";
vmmc-supply = <&vemmc_reg>;
status = "okay";
};
@@ -73,12 +64,74 @@
status = "okay";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ vol-down-key {
+ gpios = <&gpx2 1 1>;
+ linux,code = <114>;
+ label = "volume down";
+ debounce-interval = <10>;
+ };
+
+ vol-up-key {
+ gpios = <&gpx2 0 1>;
+ linux,code = <115>;
+ label = "volume up";
+ debounce-interval = <10>;
+ };
+
+ power-key {
+ gpios = <&gpx2 7 1>;
+ linux,code = <116>;
+ label = "power";
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+
+ ok-key {
+ gpios = <&gpx3 5 1>;
+ linux,code = <352>;
+ label = "ok";
+ debounce-interval = <10>;
+ };
+ };
+
+ tsp_reg: voltage-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "TSP_FIXED_VOLTAGES";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpl0 3 0>;
+ enable-active-high;
+ };
+
+ i2c@13890000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-slave-addr = <0x10>;
+ samsung,i2c-max-bus-freq = <400000>;
+ pinctrl-0 = <&i2c3_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mms114-touchscreen@48 {
+ compatible = "melfas,mms114";
+ reg = <0x48>;
+ interrupt-parent = <&gpx0>;
+ interrupts = <4 2>;
+ x-size = <720>;
+ y-size = <1280>;
+ avdd-supply = <&tsp_reg>;
+ vdd-supply = <&tsp_reg>;
+ };
+ };
+
i2c@138B0000 {
samsung,i2c-sda-delay = <100>;
samsung,i2c-slave-addr = <0x10>;
samsung,i2c-max-bus-freq = <100000>;
- gpios = <&gpb 6 3 3 0>,
- <&gpb 7 3 3 0>;
+ pinctrl-0 = <&i2c5_bus>;
+ pinctrl-names = "default";
status = "okay";
max8997_pmic@66 {
@@ -93,9 +146,9 @@
max8997,pmic-ignore-gpiodvs-side-effect;
max8997,pmic-buck125-default-dvs-idx = <0>;
- max8997,pmic-buck125-dvs-gpios = <&gpx0 5 1 0 0>,
- <&gpx0 6 1 0 0>,
- <&gpl0 0 1 0 0>;
+ max8997,pmic-buck125-dvs-gpios = <&gpx0 5 0>,
+ <&gpx0 6 0>,
+ <&gpl0 0 0>;
max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
<1250000>, <1200000>,
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index d877dbe7ac0e..e31bfc4a6f09 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -31,6 +31,11 @@
pinctrl2 = &pinctrl_2;
};
+ pd_lcd1: lcd1-power-domain@10023CA0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023CA0 0x20>;
+ };
+
gic:interrupt-controller@10490000 {
cpu-offset = <0x8000>;
};
@@ -64,4 +69,11 @@
compatible = "samsung,pinctrl-exynos4210";
reg = <0x03860000 0x1000>;
};
+
+ tmu@100C0000 {
+ compatible = "samsung,exynos4210-tmu";
+ interrupt-parent = <&combiner>;
+ reg = <0x100C0000 0x100>;
+ interrupts = <2 4>;
+ };
};
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
new file mode 100644
index 000000000000..c6ae2005961f
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -0,0 +1,28 @@
+/*
+ * Samsung's Exynos4212 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung's Exynos4212 SoC device nodes are listed in this file. Exynos4212
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4212 SoC. As device tree coverage for Exynos4212 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/include/ "exynos4x12.dtsi"
+
+/ {
+ compatible = "samsung,exynos4212";
+
+ gic:interrupt-controller@10490000 {
+ cpu-offset = <0x8000>;
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts
new file mode 100644
index 000000000000..f05bf575cc45
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts
@@ -0,0 +1,45 @@
+/*
+ * Samsung's Exynos4412 based SMDK board device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Device tree source file for Samsung's SMDK4412 board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos4412.dtsi"
+
+/ {
+ model = "Samsung SMDK evaluation board based on Exynos4412";
+ compatible = "samsung,smdk4412", "samsung,exynos4412";
+
+ memory {
+ reg = <0x40000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
+ };
+
+ serial@13800000 {
+ status = "okay";
+ };
+
+ serial@13810000 {
+ status = "okay";
+ };
+
+ serial@13820000 {
+ status = "okay";
+ };
+
+ serial@13830000 {
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
new file mode 100644
index 000000000000..d7dfe312772a
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -0,0 +1,28 @@
+/*
+ * Samsung's Exynos4412 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/include/ "exynos4x12.dtsi"
+
+/ {
+ compatible = "samsung,exynos4412";
+
+ gic:interrupt-controller@10490000 {
+ cpu-offset = <0x4000>;
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
new file mode 100644
index 000000000000..8e6115adcd97
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
@@ -0,0 +1,965 @@
+/*
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/ {
+ pinctrl@11400000 {
+ gpa0: gpa0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpa1: gpa1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc0: gpc0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc1: gpc1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd0: gpd0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd1: gpd1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf0: gpf0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf1: gpf1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf2: gpf2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf3: gpf3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj0: gpj0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj1: gpj1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ uart0_data: uart0-data {
+ samsung,pins = "gpa0-0", "gpa0-1";
+ samsung,pin-function = <0x2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart0_fctl: uart0-fctl {
+ samsung,pins = "gpa0-2", "gpa0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_data: uart1-data {
+ samsung,pins = "gpa0-4", "gpa0-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_fctl: uart1-fctl {
+ samsung,pins = "gpa0-6", "gpa0-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c2_bus: i2c2-bus {
+ samsung,pins = "gpa0-6", "gpa0-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart2_data: uart2-data {
+ samsung,pins = "gpa1-0", "gpa1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart2_fctl: uart2-fctl {
+ samsung,pins = "gpa1-2", "gpa1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart_audio_a: uart-audio-a {
+ samsung,pins = "gpa1-0", "gpa1-1";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c3_bus: i2c3-bus {
+ samsung,pins = "gpa1-2", "gpa1-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart3_data: uart3-data {
+ samsung,pins = "gpa1-4", "gpa1-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart_audio_b: uart-audio-b {
+ samsung,pins = "gpa1-4", "gpa1-5";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi0_bus: spi0-bus {
+ samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c4_bus: i2c4-bus {
+ samsung,pins = "gpb-0", "gpb-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi1_bus: spi1-bus {
+ samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c5_bus: i2c5-bus {
+ samsung,pins = "gpb-2", "gpb-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s1_bus: i2s1-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pcm1_bus: pcm1-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ ac97_bus: ac97-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s2_bus: i2s2-bus {
+ samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+ "gpc1-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pcm2_bus: pcm2-bus {
+ samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+ "gpc1-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ spdif_bus: spdif-bus {
+ samsung,pins = "gpc1-0", "gpc1-1";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c6_bus: i2c6-bus {
+ samsung,pins = "gpc1-3", "gpc1-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi2_bus: spi2-bus {
+ samsung,pins = "gpc1-1", "gpc1-3", "gpc1-4";
+ samsung,pin-function = <5>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm0_out: pwm0-out {
+ samsung,pins = "gpd0-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm1_out: pwm1-out {
+ samsung,pins = "gpd0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_ctrl: lcd-ctrl {
+ samsung,pins = "gpd0-0", "gpd0-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c7_bus: i2c7-bus {
+ samsung,pins = "gpd0-2", "gpd0-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm2_out: pwm2-out {
+ samsung,pins = "gpd0-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm3_out: pwm3-out {
+ samsung,pins = "gpd0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c0_bus: i2c0-bus {
+ samsung,pins = "gpd1-0", "gpd1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ mipi0_clk: mipi0-clk {
+ samsung,pins = "gpd1-0", "gpd1-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c1_bus: i2c1-bus {
+ samsung,pins = "gpd1-2", "gpd1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ mipi1_clk: mipi1-clk {
+ samsung,pins = "gpd1-2", "gpd1-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_clk: lcd-clk {
+ samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_data16: lcd-data-width16 {
+ samsung,pins = "gpf0-7", "gpf1-0", "gpf1-1", "gpf1-2",
+ "gpf1-3", "gpf1-6", "gpf1-7", "gpf2-0",
+ "gpf2-1", "gpf2-2", "gpf2-3", "gpf2-7",
+ "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_data18: lcd-data-width18 {
+ samsung,pins = "gpf0-6", "gpf0-7", "gpf1-0", "gpf1-1",
+ "gpf1-2", "gpf1-3", "gpf1-6", "gpf1-7",
+ "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+ "gpf2-6", "gpf2-7", "gpf3-0", "gpf3-1",
+ "gpf3-2", "gpf3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_data24: lcd-data-width24 {
+ samsung,pins = "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7",
+ "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3",
+ "gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7",
+ "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+ "gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7",
+ "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_ldi: lcd-ldi {
+ samsung,pins = "gpf3-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_a: cam-port-a {
+ samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
+ "gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
+ "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3",
+ "gpj1-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+ };
+
+ pinctrl@11000000 {
+ gpk0: gpk0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk1: gpk1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk2: gpk2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk3: gpk3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl0: gpl0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl1: gpl1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl2: gpl2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm0: gpm0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm1: gpm1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm2: gpm2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm3: gpm3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm4: gpm4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpy0: gpy0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy1: gpy1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy2: gpy2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy3: gpy3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy4: gpy4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy5: gpy5 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy6: gpy6 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpx0: gpx0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+ #interrupt-cells = <2>;
+ };
+
+ gpx1: gpx1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+ #interrupt-cells = <2>;
+ };
+
+ gpx2: gpx2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpx3: gpx3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ sd0_clk: sd0-clk {
+ samsung,pins = "gpk0-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_cmd: sd0-cmd {
+ samsung,pins = "gpk0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_cd: sd0-cd {
+ samsung,pins = "gpk0-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus1: sd0-bus-width1 {
+ samsung,pins = "gpk0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus4: sd0-bus-width4 {
+ samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus8: sd0-bus-width8 {
+ samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_clk: sd4-clk {
+ samsung,pins = "gpk0-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_cmd: sd4-cmd {
+ samsung,pins = "gpk0-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_cd: sd4-cd {
+ samsung,pins = "gpk0-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_bus1: sd4-bus-width1 {
+ samsung,pins = "gpk0-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_bus4: sd4-bus-width4 {
+ samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd4_bus8: sd4-bus-width8 {
+ samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <4>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_clk: sd1-clk {
+ samsung,pins = "gpk1-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_cmd: sd1-cmd {
+ samsung,pins = "gpk1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_cd: sd1-cd {
+ samsung,pins = "gpk1-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_bus1: sd1-bus-width1 {
+ samsung,pins = "gpk1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_bus4: sd1-bus-width4 {
+ samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_clk: sd2-clk {
+ samsung,pins = "gpk2-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_cmd: sd2-cmd {
+ samsung,pins = "gpk2-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_cd: sd2-cd {
+ samsung,pins = "gpk2-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus1: sd2-bus-width1 {
+ samsung,pins = "gpk2-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus4: sd2-bus-width4 {
+ samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus8: sd2-bus-width8 {
+ samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_clk: sd3-clk {
+ samsung,pins = "gpk3-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_cmd: sd3-cmd {
+ samsung,pins = "gpk3-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_cd: sd3-cd {
+ samsung,pins = "gpk3-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_bus1: sd3-bus-width1 {
+ samsung,pins = "gpk3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_bus4: sd3-bus-width4 {
+ samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+
+ keypad_col0: keypad-col0 {
+ samsung,pins = "gpl2-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col1: keypad-col1 {
+ samsung,pins = "gpl2-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col2: keypad-col2 {
+ samsung,pins = "gpl2-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col3: keypad-col3 {
+ samsung,pins = "gpl2-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col4: keypad-col4 {
+ samsung,pins = "gpl2-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col5: keypad-col5 {
+ samsung,pins = "gpl2-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col6: keypad-col6 {
+ samsung,pins = "gpl2-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col7: keypad-col7 {
+ samsung,pins = "gpl2-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_b: cam-port-b {
+ samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
+ "gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
+ "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1",
+ "gpm2-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint0: ext-int0 {
+ samsung,pins = "gpx0-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint8: ext-int8 {
+ samsung,pins = "gpx1-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint15: ext-int15 {
+ samsung,pins = "gpx1-7";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint16: ext-int16 {
+ samsung,pins = "gpx2-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint31: ext-int31 {
+ samsung,pins = "gpx3-7";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+ };
+
+ pinctrl@03860000 {
+ gpz: gpz {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ i2s0_bus: i2s0-bus {
+ samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+ "gpz-4", "gpz-5", "gpz-6";
+ samsung,pin-function = <0x2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pcm0_bus: pcm0-bus {
+ samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+ "gpz-4";
+ samsung,pin-function = <0x3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+ };
+
+ pinctrl@106E0000 {
+ gpv0: gpv0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpv1: gpv1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpv2: gpv2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpv3: gpv3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpv4: gpv4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ c2c_bus: c2c-bus {
+ samsung,pins = "gpv0-0", "gpv0-1", "gpv0-2", "gpv0-3",
+ "gpv0-4", "gpv0-5", "gpv0-6", "gpv0-7",
+ "gpv1-0", "gpv1-1", "gpv1-2", "gpv1-3",
+ "gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7",
+ "gpv2-0", "gpv2-1", "gpv2-2", "gpv2-3",
+ "gpv2-4", "gpv2-5", "gpv2-6", "gpv2-7",
+ "gpv3-0", "gpv3-1", "gpv3-2", "gpv3-3",
+ "gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7",
+ "gpv4-0", "gpv4-1";
+ samsung,pin-function = <0x2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
new file mode 100644
index 000000000000..179a62e46c9d
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -0,0 +1,69 @@
+/*
+ * Samsung's Exynos4x12 SoCs device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs device nodes are listed in this file. Exynos4x12
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4x12 SoC. As device tree coverage for Exynos4x12 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/include/ "exynos4.dtsi"
+/include/ "exynos4x12-pinctrl.dtsi"
+
+/ {
+ aliases {
+ pinctrl0 = &pinctrl_0;
+ pinctrl1 = &pinctrl_1;
+ pinctrl2 = &pinctrl_2;
+ pinctrl3 = &pinctrl_3;
+ };
+
+ combiner:interrupt-controller@10440000 {
+ interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+ <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+ <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+ <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+ <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>;
+ };
+
+ pinctrl_0: pinctrl@11400000 {
+ compatible = "samsung,pinctrl-exynos4x12";
+ reg = <0x11400000 0x1000>;
+ interrupts = <0 47 0>;
+ };
+
+ pinctrl_1: pinctrl@11000000 {
+ compatible = "samsung,pinctrl-exynos4x12";
+ reg = <0x11000000 0x1000>;
+ interrupts = <0 46 0>;
+
+ wakup_eint: wakeup-interrupt-controller {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ interrupt-parent = <&gic>;
+ interrupts = <0 32 0>;
+ };
+ };
+
+ pinctrl_2: pinctrl@03860000 {
+ compatible = "samsung,pinctrl-exynos4x12";
+ reg = <0x03860000 0x1000>;
+ interrupt-parent = <&combiner>;
+ interrupts = <10 0>;
+ };
+
+ pinctrl_3: pinctrl@106E0000 {
+ compatible = "samsung,pinctrl-exynos4x12";
+ reg = <0x106E0000 0x1000>;
+ interrupts = <0 72 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a352df403b7a..942d5761ca97 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -17,10 +17,6 @@
compatible = "samsung,smdk5250", "samsung,exynos5250";
aliases {
- mshc0 = &dwmmc_0;
- mshc1 = &dwmmc_1;
- mshc2 = &dwmmc_2;
- mshc3 = &dwmmc_3;
};
memory {
@@ -55,8 +51,31 @@
};
};
+ i2c@121D0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <40000>;
+ samsung,i2c-slave-addr = <0x38>;
+
+ sata-phy {
+ compatible = "samsung,sata-phy";
+ reg = <0x38>;
+ };
+ };
+
+ sata@122F0000 {
+ samsung,sata-freq = <66>;
+ };
+
i2c@12C80000 {
- status = "disabled";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ gpios = <&gpa0 6 3 3 0>,
+ <&gpa0 7 3 3 0>;
+
+ hdmiddc@50 {
+ compatible = "samsung,exynos5-hdmiddc";
+ reg = <0x50>;
+ };
};
i2c@12C90000 {
@@ -79,7 +98,17 @@
status = "disabled";
};
- dwmmc_0: dwmmc0@12200000 {
+ i2c@12CE0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+
+ hdmiphy@38 {
+ compatible = "samsung,exynos5-hdmiphy";
+ reg = <0x38>;
+ };
+ };
+
+ dwmmc0@12200000 {
num-slots = <1>;
supports-highspeed;
broken-cd;
@@ -100,11 +129,11 @@
};
};
- dwmmc_1: dwmmc1@12210000 {
+ dwmmc1@12210000 {
status = "disabled";
};
- dwmmc_2: dwmmc2@12220000 {
+ dwmmc2@12220000 {
num-slots = <1>;
supports-highspeed;
fifo-depth = <0x80>;
@@ -125,7 +154,7 @@
};
};
- dwmmc_3: dwmmc3@12230000 {
+ dwmmc3@12230000 {
status = "disabled";
};
@@ -166,4 +195,13 @@
spi_2: spi@12d40000 {
status = "disabled";
};
+
+ hdmi {
+ hpd-gpio = <&gpx3 7 0xf 1 3>;
+ };
+
+ codec@11000000 {
+ samsung,mfc-r = <0x43000000 0x800000>;
+ samsung,mfc-l = <0x51000000 0x800000>;
+ };
};
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
new file mode 100644
index 000000000000..17dd951c1cd2
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -0,0 +1,43 @@
+/*
+ * Google Snow board device tree source
+ *
+ * Copyright (c) 2012 Google, 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.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+/include/ "cros5250-common.dtsi"
+
+/ {
+ model = "Google Snow";
+ compatible = "google,snow", "samsung,exynos5250";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ lid-switch {
+ label = "Lid";
+ gpios = <&gpx3 5 0 0x10000 0>;
+ linux,input-type = <5>; /* EV_SW */
+ linux,code = <0>; /* SW_LID */
+ debounce-interval = <1>;
+ gpio-key,wakeup;
+ };
+ };
+
+ /*
+ * On Snow we've got SIP WiFi and so can keep drive strengths low to
+ * reduce EMI.
+ */
+ dwmmc3@12230000 {
+ slot@0 {
+ gpios = <&gpc4 0 2 0 0>, <&gpc4 1 2 3 0>,
+ <&gpc4 3 2 3 0>, <&gpc4 4 2 3 0>,
+ <&gpc4 5 2 3 0>, <&gpc4 6 2 3 0>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index dddfd6e444dc..36d8246ea50e 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -31,6 +31,10 @@
gsc1 = &gsc_1;
gsc2 = &gsc_2;
gsc3 = &gsc_3;
+ mshc0 = &dwmmc_0;
+ mshc1 = &dwmmc_1;
+ mshc2 = &dwmmc_2;
+ mshc3 = &dwmmc_3;
};
gic:interrupt-controller@10481000 {
@@ -62,12 +66,24 @@
interrupts = <0 42 0>;
};
+ codec@11000000 {
+ compatible = "samsung,mfc-v6";
+ reg = <0x11000000 0x10000>;
+ interrupts = <0 96 0>;
+ };
+
rtc {
compatible = "samsung,s3c6410-rtc";
reg = <0x101E0000 0x100>;
interrupts = <0 43 0>, <0 44 0>;
};
+ tmu@10060000 {
+ compatible = "samsung,exynos5250-tmu";
+ reg = <0x10060000 0x100>;
+ interrupts = <0 65 0>;
+ };
+
serial@12C00000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C00000 0x100>;
@@ -92,6 +108,17 @@
interrupts = <0 54 0>;
};
+ sata@122F0000 {
+ compatible = "samsung,exynos5-sata-ahci";
+ reg = <0x122F0000 0x1ff>;
+ interrupts = <0 115 0>;
+ };
+
+ sata-phy@12170000 {
+ compatible = "samsung,exynos5-sata-phy";
+ reg = <0x12170000 0x1ff>;
+ };
+
i2c@12C60000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12C60000 0x100>;
@@ -156,6 +183,21 @@
#size-cells = <0>;
};
+ i2c@12CE0000 {
+ compatible = "samsung,s3c2440-hdmiphy-i2c";
+ reg = <0x12CE0000 0x1000>;
+ interrupts = <0 64 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c@121D0000 {
+ compatible = "samsung,exynos5-sata-phy-i2c";
+ reg = <0x121D0000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
spi_0: spi@12d20000 {
compatible = "samsung,exynos4210-spi";
reg = <0x12d20000 0x100>;
@@ -186,7 +228,7 @@
#size-cells = <0>;
};
- dwmmc0@12200000 {
+ dwmmc_0: dwmmc0@12200000 {
compatible = "samsung,exynos5250-dw-mshc";
reg = <0x12200000 0x1000>;
interrupts = <0 75 0>;
@@ -194,7 +236,7 @@
#size-cells = <0>;
};
- dwmmc1@12210000 {
+ dwmmc_1: dwmmc1@12210000 {
compatible = "samsung,exynos5250-dw-mshc";
reg = <0x12210000 0x1000>;
interrupts = <0 76 0>;
@@ -202,7 +244,7 @@
#size-cells = <0>;
};
- dwmmc2@12220000 {
+ dwmmc_2: dwmmc2@12220000 {
compatible = "samsung,exynos5250-dw-mshc";
reg = <0x12220000 0x1000>;
interrupts = <0 77 0>;
@@ -210,7 +252,7 @@
#size-cells = <0>;
};
- dwmmc3@12230000 {
+ dwmmc_3: dwmmc3@12230000 {
compatible = "samsung,exynos5250-dw-mshc";
reg = <0x12230000 0x1000>;
interrupts = <0 78 0>;
@@ -520,4 +562,16 @@
reg = <0x13e30000 0x1000>;
interrupts = <0 88 0>;
};
+
+ hdmi {
+ compatible = "samsung,exynos5-hdmi";
+ reg = <0x14530000 0x100000>;
+ interrupts = <0 95 0>;
+ };
+
+ mixer {
+ compatible = "samsung,exynos5-mixer";
+ reg = <0x14450000 0x10000>;
+ interrupts = <0 94 0>;
+ };
};
diff --git a/arch/arm/boot/dts/href.dtsi b/arch/arm/boot/dts/href.dtsi
new file mode 100644
index 000000000000..592fb9dc35bd
--- /dev/null
+++ b/arch/arm/boot/dts/href.dtsi
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * 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/ "dbx5x0.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-u9500 {
+ uart@80120000 {
+ status = "okay";
+ };
+
+ uart@80121000 {
+ status = "okay";
+ };
+
+ uart@80007000 {
+ status = "okay";
+ };
+
+ i2c@80004000 {
+ tc3589x@42 {
+ compatible = "tc3589x";
+ reg = <0x42>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <25 0x1>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ tc3589x_gpio: tc3589x_gpio {
+ compatible = "tc3589x-gpio";
+ interrupts = <0 0x1>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+ };
+
+ i2c@80128000 {
+ lp5521@0x33 {
+ compatible = "lp5521";
+ reg = <0x33>;
+ };
+
+ lp5521@0x34 {
+ compatible = "lp5521";
+ reg = <0x34>;
+ };
+
+ bh1780@0x29 {
+ compatible = "rohm,bh1780gli";
+ reg = <0x33>;
+ };
+ };
+
+ // External Micro SD slot
+ sdi0_per1@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ mmc-cap-sd-highspeed;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+ cd-gpios = <&tc3589x_gpio 3 0x4>;
+
+ status = "okay";
+ };
+
+ // WLAN SDIO channel
+ sdi1_per2@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+
+ status = "okay";
+ };
+
+ // PoP:ed eMMC
+ sdi2_per3@80005000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+
+ status = "okay";
+ };
+
+ // On-board eMMC
+ sdi4_per2@80114000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+ status = "okay";
+ };
+
+ sound {
+ compatible = "stericsson,snd-soc-mop500";
+
+ stericsson,cpu-dai = <&msp1 &msp3>;
+ stericsson,audio-codec = <&codec>;
+ };
+
+ msp1: msp@80124000 {
+ status = "okay";
+ };
+
+ msp3: msp@80125000 {
+ status = "okay";
+ };
+
+ prcmu@80157000 {
+ db8500-prcmu-regulators {
+ db8500_vape_reg: db8500_vape {
+ regulator-name = "db8500-vape";
+ };
+
+ db8500_varm_reg: db8500_varm {
+ regulator-name = "db8500-varm";
+ };
+
+ db8500_vmodem_reg: db8500_vmodem {
+ regulator-name = "db8500-vmodem";
+ };
+
+ db8500_vpll_reg: db8500_vpll {
+ regulator-name = "db8500-vpll";
+ };
+
+ db8500_vsmps1_reg: db8500_vsmps1 {
+ regulator-name = "db8500-vsmps1";
+ };
+
+ db8500_vsmps2_reg: db8500_vsmps2 {
+ regulator-name = "db8500-vsmps2";
+ };
+
+ db8500_vsmps3_reg: db8500_vsmps3 {
+ regulator-name = "db8500-vsmps3";
+ };
+
+ db8500_vrf1_reg: db8500_vrf1 {
+ regulator-name = "db8500-vrf1";
+ };
+
+ db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+ regulator-name = "db8500-sva-mmdsp";
+ };
+
+ db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+ regulator-name = "db8500-sva-mmdsp-ret";
+ };
+
+ db8500_sva_pipe_reg: db8500_sva_pipe {
+ regulator-name = "db8500_sva_pipe";
+ };
+
+ db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+ regulator-name = "db8500_sia_mmdsp";
+ };
+
+ db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
+ regulator-name = "db8500-sia-mmdsp-ret";
+ };
+
+ db8500_sia_pipe_reg: db8500_sia_pipe {
+ regulator-name = "db8500-sia-pipe";
+ };
+
+ db8500_sga_reg: db8500_sga {
+ regulator-name = "db8500-sga";
+ };
+
+ db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+ regulator-name = "db8500-b2r2-mcde";
+ };
+
+ db8500_esram12_reg: db8500_esram12 {
+ regulator-name = "db8500-esram12";
+ };
+
+ db8500_esram12_ret_reg: db8500_esram12_ret {
+ regulator-name = "db8500-esram12-ret";
+ };
+
+ db8500_esram34_reg: db8500_esram34 {
+ regulator-name = "db8500-esram34";
+ };
+
+ db8500_esram34_ret_reg: db8500_esram34_ret {
+ regulator-name = "db8500-esram34-ret";
+ };
+ };
+
+ ab8500@5 {
+ ab8500-regulators {
+ ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+ regulator-name = "V-DISPLAY";
+ };
+
+ ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+ regulator-name = "V-eMMC1";
+ };
+
+ ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+ regulator-name = "V-MMC-SD";
+ };
+
+ ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+ regulator-name = "V-INTCORE";
+ };
+
+ ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+ regulator-name = "V-TVOUT";
+ };
+
+ ab8500_ldo_usb_reg: ab8500_ldo_usb {
+ regulator-name = "dummy";
+ };
+
+ ab8500_ldo_audio_reg: ab8500_ldo_audio {
+ regulator-name = "V-AUD";
+ };
+
+ ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+ regulator-name = "V-AMIC1";
+ };
+
+ ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+ regulator-name = "V-AMIC2";
+ };
+
+ ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+ regulator-name = "V-DMIC";
+ };
+
+ ab8500_ldo_ana_reg: ab8500_ldo_ana {
+ regulator-name = "V-CSI/DSI";
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/hrefprev60.dts b/arch/arm/boot/dts/hrefprev60.dts
new file mode 100644
index 000000000000..eec29c4a86dc
--- /dev/null
+++ b/arch/arm/boot/dts/hrefprev60.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * 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/ "dbx5x0.dtsi"
+/include/ "href.dtsi"
+/include/ "stuib.dtsi"
+
+/ {
+ model = "ST-Ericsson HREF (pre-v60) platform with Device Tree";
+ compatible = "st-ericsson,mop500", "st-ericsson,u8500";
+
+ gpio_keys {
+ button@1 {
+ gpios = <&tc3589x_gpio 7 0x4>;
+ };
+ };
+
+ soc-u9500 {
+ i2c@80004000 {
+ tps61052@33 {
+ compatible = "tps61052";
+ reg = <0x33>;
+ };
+ };
+
+ i2c@80110000 {
+ bu21013_tp@0x5c {
+ reset-gpio = <&tc3589x_gpio 13 0x4>;
+ };
+ };
+
+ vmmci: regulator-gpio {
+ gpios = <&tc3589x_gpio 18 0x4>;
+ gpio-enable = <&tc3589x_gpio 17 0x4>;
+
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/hrefv60plus.dts b/arch/arm/boot/dts/hrefv60plus.dts
index 2131d77dc9c9..55f4191a626e 100644
--- a/arch/arm/boot/dts/hrefv60plus.dts
+++ b/arch/arm/boot/dts/hrefv60plus.dts
@@ -11,85 +11,200 @@
/dts-v1/;
/include/ "dbx5x0.dtsi"
+/include/ "href.dtsi"
+/include/ "stuib.dtsi"
/ {
- model = "ST-Ericsson HREF platform with Device Tree";
- compatible = "st-ericsson,hrefv60+";
+ model = "ST-Ericsson HREF (v60+) platform with Device Tree";
+ compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
- memory {
- reg = <0x00000000 0x20000000>;
+ gpio_keys {
+ button@1 {
+ gpios = <&gpio6 25 0x4>;
+ };
};
soc-u9500 {
- uart@80120000 {
+ i2c@80110000 {
+ bu21013_tp@0x5c {
+ reset-gpio = <&gpio4 15 0x4>;
+ };
+ };
+
+ // External Micro SD slot
+ sdi0_per1@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ mmc-cap-sd-highspeed;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+ cd-gpios = <&tc3589x_gpio 3 0x4>;
+
status = "okay";
};
- uart@80121000 {
+ // WLAN SDIO channel
+ sdi1_per2@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+
status = "okay";
};
- uart@80007000 {
+ // PoP:ed eMMC
+ sdi2_per3@80005000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+
status = "okay";
};
- i2c@80004000 {
- tc3589x@42 {
- compatible = "tc3589x";
- reg = <0x42>;
- interrupt-parent = <&gpio6>;
- interrupts = <25 0x1>;
+ // On-board eMMC
+ sdi4_per2@80114000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux2_reg>;
- interrupt-controller;
- #interrupt-cells = <2>;
+ status = "okay";
+ };
- tc3589x_gpio: tc3589x_gpio {
- compatible = "tc3589x-gpio";
- interrupts = <0 0x1>;
+ prcmu@80157000 {
+ db8500-prcmu-regulators {
+ db8500_vape_reg: db8500_vape {
+ regulator-name = "db8500-vape";
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-controller;
- #gpio-cells = <2>;
+ db8500_varm_reg: db8500_varm {
+ regulator-name = "db8500-varm";
};
- };
- tps61052@33 {
- compatible = "tps61052";
- reg = <0x33>;
- };
- };
+ db8500_vmodem_reg: db8500_vmodem {
+ regulator-name = "db8500-vmodem";
+ };
- i2c@80128000 {
- lp5521@0x33 {
- compatible = "lp5521";
- reg = <0x33>;
- };
+ db8500_vpll_reg: db8500_vpll {
+ regulator-name = "db8500-vpll";
+ };
- lp5521@0x34 {
- compatible = "lp5521";
- reg = <0x34>;
- };
+ db8500_vsmps1_reg: db8500_vsmps1 {
+ regulator-name = "db8500-vsmps1";
+ };
+
+ db8500_vsmps2_reg: db8500_vsmps2 {
+ regulator-name = "db8500-vsmps2";
+ };
+
+ db8500_vsmps3_reg: db8500_vsmps3 {
+ regulator-name = "db8500-vsmps3";
+ };
+
+ db8500_vrf1_reg: db8500_vrf1 {
+ regulator-name = "db8500-vrf1";
+ };
+
+ db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+ regulator-name = "db8500-sva-mmdsp";
+ };
+
+ db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+ regulator-name = "db8500-sva-mmdsp-ret";
+ };
+
+ db8500_sva_pipe_reg: db8500_sva_pipe {
+ regulator-name = "db8500_sva_pipe";
+ };
- bh1780@0x29 {
- compatible = "rohm,bh1780gli";
- reg = <0x33>;
+ db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+ regulator-name = "db8500_sia_mmdsp";
+ };
+
+ db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
+ regulator-name = "db8500-sia-mmdsp-ret";
+ };
+
+ db8500_sia_pipe_reg: db8500_sia_pipe {
+ regulator-name = "db8500-sia-pipe";
+ };
+
+ db8500_sga_reg: db8500_sga {
+ regulator-name = "db8500-sga";
+ };
+
+ db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+ regulator-name = "db8500-b2r2-mcde";
+ };
+
+ db8500_esram12_reg: db8500_esram12 {
+ regulator-name = "db8500-esram12";
+ };
+
+ db8500_esram12_ret_reg: db8500_esram12_ret {
+ regulator-name = "db8500-esram12-ret";
+ };
+
+ db8500_esram34_reg: db8500_esram34 {
+ regulator-name = "db8500-esram34";
+ };
+
+ db8500_esram34_ret_reg: db8500_esram34_ret {
+ regulator-name = "db8500-esram34-ret";
+ };
};
- };
- sound {
- compatible = "stericsson,snd-soc-mop500";
+ ab8500@5 {
+ ab8500-regulators {
+ ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+ regulator-name = "V-DISPLAY";
+ };
- stericsson,cpu-dai = <&msp1 &msp3>;
- stericsson,audio-codec = <&codec>;
- };
+ ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+ regulator-name = "V-eMMC1";
+ };
- msp1: msp@80124000 {
- status = "okay";
- };
+ ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+ regulator-name = "V-MMC-SD";
+ };
- msp3: msp@80125000 {
- status = "okay";
+ ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+ regulator-name = "V-INTCORE";
+ };
+
+ ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+ regulator-name = "V-TVOUT";
+ };
+
+ ab8500_ldo_usb_reg: ab8500_ldo_usb {
+ regulator-name = "dummy";
+ };
+
+ ab8500_ldo_audio_reg: ab8500_ldo_audio {
+ regulator-name = "V-AUD";
+ };
+
+ ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+ regulator-name = "V-AMIC1";
+ };
+
+ ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+ regulator-name = "V-AMIC2";
+ };
+
+ ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+ regulator-name = "V-DMIC";
+ };
+
+ ab8500_ldo_ana_reg: ab8500_ldo_ana {
+ regulator-name = "V-CSI/DSI";
+ };
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index 384d8b66f337..7c43b8e70b9f 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -40,6 +40,15 @@
reg = <0>;
fsl,pinmux-ids = <
0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
+ led_pin_gpio0_17: led_gpio0_17@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
>;
fsl,drive-strength = <0>;
@@ -47,6 +56,15 @@
fsl,pull-up = <0>;
};
};
+
+ ssp1: ssp@80034000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx23-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
+ };
};
apbx@80040000 {
@@ -91,11 +109,12 @@
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pin_gpio0_17>;
user {
label = "green";
- gpios = <&gpio2 1 0>;
- linux,default-trigger = "default-on";
+ gpios = <&gpio2 1 1>;
};
};
};
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 6d31aa383460..65415c598a5e 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -279,6 +279,19 @@
fsl,voltage = <1>;
fsl,pull-up = <0>;
};
+
+ spi2_pins_a: spi2@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x0182 /* MX23_PAD_GPMI_WRN__SSP2_SCK */
+ 0x0142 /* MX23_PAD_GPMI_RDY1__SSP2_CMD */
+ 0x0002 /* MX23_PAD_GPMI_D00__SSP2_DATA0 */
+ 0x0032 /* MX23_PAD_GPMI_D03__SSP2_DATA3 */
+ >;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
};
digctl@8001c000 {
diff --git a/arch/arm/boot/dts/imx25-karo-tx25.dts b/arch/arm/boot/dts/imx25-karo-tx25.dts
new file mode 100644
index 000000000000..d81f8a0b9794
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-karo-tx25.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Sascha Hauer, 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
+ */
+
+/dts-v1/;
+/include/ "imx25.dtsi"
+
+/ {
+ model = "Ka-Ro TX25";
+ compatible = "karo,imx25-tx25", "fsl,imx25";
+
+ memory {
+ reg = <0x80000000 0x02000000 0x90000000 0x02000000>;
+ };
+
+ soc {
+ aips@43f00000 {
+ uart1: serial@43f90000 {
+ status = "okay";
+ };
+ };
+
+ spba@50000000 {
+ fec: ethernet@50038000 {
+ status = "okay";
+ phy-mode = "rmii";
+ };
+ };
+
+ emi@80000000 {
+ nand@bb000000 {
+ nand-on-flash-bbt;
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
new file mode 100644
index 000000000000..e1b13ebc96d6
--- /dev/null
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -0,0 +1,515 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.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
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ usb0 = &usbotg;
+ usb1 = &usbhost1;
+ };
+
+ asic: asic-interrupt-controller@68000000 {
+ compatible = "fsl,imx25-asic", "fsl,avic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x68000000 0x8000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&asic>;
+ ranges;
+
+ aips@43f00000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x43f00000 0x100000>;
+ ranges;
+
+ i2c1: i2c@43f80000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+ reg = <0x43f80000 0x4000>;
+ clocks = <&clks 48>;
+ clock-names = "";
+ interrupts = <3>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@43f84000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+ reg = <0x43f84000 0x4000>;
+ clocks = <&clks 48>;
+ clock-names = "";
+ interrupts = <10>;
+ status = "disabled";
+ };
+
+ can1: can@43f88000 {
+ compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+ reg = <0x43f88000 0x4000>;
+ interrupts = <43>;
+ clocks = <&clks 75>, <&clks 75>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ can2: can@43f8c000 {
+ compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+ reg = <0x43f8c000 0x4000>;
+ interrupts = <44>;
+ clocks = <&clks 76>, <&clks 76>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart1: serial@43f90000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x43f90000 0x4000>;
+ interrupts = <45>;
+ clocks = <&clks 120>, <&clks 57>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart2: serial@43f94000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x43f94000 0x4000>;
+ interrupts = <32>;
+ clocks = <&clks 121>, <&clks 57>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ i2c2: i2c@43f98000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+ reg = <0x43f98000 0x4000>;
+ clocks = <&clks 48>;
+ clock-names = "";
+ interrupts = <4>;
+ status = "disabled";
+ };
+
+ owire@43f9c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x43f9c000 0x4000>;
+ clocks = <&clks 51>;
+ clock-names = "";
+ interrupts = <2>;
+ status = "disabled";
+ };
+
+ spi1: cspi@43fa4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+ reg = <0x43fa4000 0x4000>;
+ clocks = <&clks 62>;
+ clock-names = "ipg";
+ interrupts = <14>;
+ status = "disabled";
+ };
+
+ kpp@43fa8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x43fa8000 0x4000>;
+ clocks = <&clks 102>;
+ clock-names = "";
+ interrupts = <24>;
+ status = "disabled";
+ };
+
+ iomuxc@43fac000{
+ compatible = "fsl,imx25-iomuxc";
+ reg = <0x43fac000 0x4000>;
+ };
+
+ audmux@43fb0000 {
+ compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
+ reg = <0x43fb0000 0x4000>;
+ status = "disabled";
+ };
+ };
+
+ spba@50000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x50000000 0x40000>;
+ ranges;
+
+ spi3: cspi@50004000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+ reg = <0x50004000 0x4000>;
+ interrupts = <0>;
+ clocks = <&clks 80>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ uart4: serial@50008000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x50008000 0x4000>;
+ interrupts = <5>;
+ clocks = <&clks 123>, <&clks 57>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart3: serial@5000c000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x5000c000 0x4000>;
+ interrupts = <18>;
+ clocks = <&clks 122>, <&clks 57>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ spi2: cspi@50010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+ reg = <0x50010000 0x4000>;
+ clocks = <&clks 79>;
+ clock-names = "ipg";
+ interrupts = <13>;
+ status = "disabled";
+ };
+
+ ssi2: ssi@50014000 {
+ compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+ reg = <0x50014000 0x4000>;
+ interrupts = <11>;
+ status = "disabled";
+ };
+
+ esai@50018000 {
+ reg = <0x50018000 0x4000>;
+ interrupts = <7>;
+ };
+
+ uart5: serial@5002c000 {
+ compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+ reg = <0x5002c000 0x4000>;
+ interrupts = <40>;
+ clocks = <&clks 124>, <&clks 57>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ tsc: tsc@50030000 {
+ compatible = "fsl,imx25-adc", "fsl,imx21-tsc";
+ reg = <0x50030000 0x4000>;
+ interrupts = <46>;
+ clocks = <&clks 119>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ ssi1: ssi@50034000 {
+ compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+ reg = <0x50034000 0x4000>;
+ interrupts = <12>;
+ status = "disabled";
+ };
+
+ fec: ethernet@50038000 {
+ compatible = "fsl,imx25-fec";
+ reg = <0x50038000 0x4000>;
+ interrupts = <57>;
+ clocks = <&clks 88>, <&clks 65>;
+ clock-names = "ipg", "ahb";
+ status = "disabled";
+ };
+ };
+
+ aips@53f00000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x53f00000 0x100000>;
+ ranges;
+
+ clks: ccm@53f80000 {
+ compatible = "fsl,imx25-ccm";
+ reg = <0x53f80000 0x4000>;
+ interrupts = <31>;
+ #clock-cells = <1>;
+ };
+
+ gpt4: timer@53f84000 {
+ compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+ reg = <0x53f84000 0x4000>;
+ clocks = <&clks 9>, <&clks 45>;
+ clock-names = "ipg", "per";
+ interrupts = <1>;
+ };
+
+ gpt3: timer@53f88000 {
+ compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+ reg = <0x53f88000 0x4000>;
+ clocks = <&clks 9>, <&clks 47>;
+ clock-names = "ipg", "per";
+ interrupts = <29>;
+ };
+
+ gpt2: timer@53f8c000 {
+ compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+ reg = <0x53f8c000 0x4000>;
+ clocks = <&clks 9>, <&clks 47>;
+ clock-names = "ipg", "per";
+ interrupts = <53>;
+ };
+
+ gpt1: timer@53f90000 {
+ compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+ reg = <0x53f90000 0x4000>;
+ clocks = <&clks 9>, <&clks 47>;
+ clock-names = "ipg", "per";
+ interrupts = <54>;
+ };
+
+ epit1: timer@53f94000 {
+ compatible = "fsl,imx25-epit";
+ reg = <0x53f94000 0x4000>;
+ interrupts = <28>;
+ };
+
+ epit2: timer@53f98000 {
+ compatible = "fsl,imx25-epit";
+ reg = <0x53f98000 0x4000>;
+ interrupts = <27>;
+ };
+
+ gpio4: gpio@53f9c000 {
+ compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+ reg = <0x53f9c000 0x4000>;
+ interrupts = <23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pwm2: pwm@53fa0000 {
+ compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ #pwm-cells = <2>;
+ reg = <0x53fa0000 0x4000>;
+ clocks = <&clks 106>, <&clks 36>;
+ clock-names = "ipg", "per";
+ interrupts = <36>;
+ };
+
+ gpio3: gpio@53fa4000 {
+ compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+ reg = <0x53fa4000 0x4000>;
+ interrupts = <16>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pwm3: pwm@53fa8000 {
+ compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ #pwm-cells = <2>;
+ reg = <0x53fa8000 0x4000>;
+ clocks = <&clks 107>, <&clks 36>;
+ clock-names = "ipg", "per";
+ interrupts = <41>;
+ };
+
+ esdhc1: esdhc@53fb4000 {
+ compatible = "fsl,imx25-esdhc";
+ reg = <0x53fb4000 0x4000>;
+ interrupts = <9>;
+ clocks = <&clks 86>, <&clks 63>, <&clks 45>;
+ clock-names = "ipg", "ahb", "per";
+ status = "disabled";
+ };
+
+ esdhc2: esdhc@53fb8000 {
+ compatible = "fsl,imx25-esdhc";
+ reg = <0x53fb8000 0x4000>;
+ interrupts = <8>;
+ clocks = <&clks 87>, <&clks 64>, <&clks 46>;
+ clock-names = "ipg", "ahb", "per";
+ status = "disabled";
+ };
+
+ lcdc@53fbc000 {
+ reg = <0x53fbc000 0x4000>;
+ interrupts = <39>;
+ clocks = <&clks 103>, <&clks 66>, <&clks 49>;
+ clock-names = "ipg", "ahb", "per";
+ status = "disabled";
+ };
+
+ slcdc@53fc0000 {
+ reg = <0x53fc0000 0x4000>;
+ interrupts = <38>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@53fc8000 {
+ compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ reg = <0x53fc8000 0x4000>;
+ clocks = <&clks 108>, <&clks 36>;
+ clock-names = "ipg", "per";
+ interrupts = <42>;
+ };
+
+ gpio1: gpio@53fcc000 {
+ compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+ reg = <0x53fcc000 0x4000>;
+ interrupts = <52>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@53fd0000 {
+ compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+ reg = <0x53fd0000 0x4000>;
+ interrupts = <51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ sdma@53fd4000 {
+ compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
+ reg = <0x53fd4000 0x4000>;
+ clocks = <&clks 112>, <&clks 68>;
+ clock-names = "ipg", "ahb";
+ interrupts = <34>;
+ };
+
+ wdog@53fdc000 {
+ compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
+ reg = <0x53fdc000 0x4000>;
+ clocks = <&clks 126>;
+ clock-names = "";
+ interrupts = <55>;
+ };
+
+ pwm1: pwm@53fe0000 {
+ compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ #pwm-cells = <2>;
+ reg = <0x53fe0000 0x4000>;
+ clocks = <&clks 105>, <&clks 36>;
+ clock-names = "ipg", "per";
+ interrupts = <26>;
+ };
+
+ usbphy1: usbphy@1 {
+ compatible = "nop-usbphy";
+ status = "disabled";
+ };
+
+ usbphy2: usbphy@2 {
+ compatible = "nop-usbphy";
+ status = "disabled";
+ };
+
+ usbotg: usb@53ff4000 {
+ compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+ reg = <0x53ff4000 0x0200>;
+ interrupts = <37>;
+ clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+ clock-names = "ipg", "ahb", "per";
+ fsl,usbmisc = <&usbmisc 0>;
+ status = "disabled";
+ };
+
+ usbhost1: usb@53ff4400 {
+ compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+ reg = <0x53ff4400 0x0200>;
+ interrupts = <35>;
+ clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+ clock-names = "ipg", "ahb", "per";
+ fsl,usbmisc = <&usbmisc 1>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@53ff4600 {
+ #index-cells = <1>;
+ compatible = "fsl,imx25-usbmisc";
+ clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+ clock-names = "ipg", "ahb", "per";
+ reg = <0x53ff4600 0x00f>;
+ status = "disabled";
+ };
+
+ dryice@53ffc000 {
+ compatible = "fsl,imx25-dryice", "fsl,imx25-rtc";
+ reg = <0x53ffc000 0x4000>;
+ clocks = <&clks 81>;
+ clock-names = "ipg";
+ interrupts = <25>;
+ };
+ };
+
+ emi@80000000 {
+ compatible = "fsl,emi-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x80000000 0x3b002000>;
+ ranges;
+
+ nand@bb000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ compatible = "fsl,imx25-nand";
+ reg = <0xbb000000 0x2000>;
+ clocks = <&clks 50>;
+ clock-names = "";
+ interrupts = <33>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
new file mode 100644
index 000000000000..c0327c054de2
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 Philippe Reynes <tremyfr@yahoo.fr>
+ * Copyright 2012 Armadeus Systems <support@armadeus.com>
+ *
+ * Based on code which is: Copyright 2012 Sascha Hauer, 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
+ */
+
+/dts-v1/;
+/include/ "imx27.dtsi"
+
+/ {
+ model = "Armadeus Systems APF27 module";
+ compatible = "armadeus,imx27-apf27", "fsl,imx27";
+
+ memory {
+ reg = <0xa0000000 0x04000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ osc26m {
+ compatible = "fsl,imx-osc26m", "fixed-clock";
+ clock-frequency = <0>;
+ };
+ };
+
+ soc {
+ aipi@10000000 {
+ serial@1000a000 {
+ status = "okay";
+ };
+
+ ethernet@1002b000 {
+ status = "okay";
+ };
+ };
+
+ nand@d8000000 {
+ status = "okay";
+ nand-bus-width = <16>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0 0x100000>;
+ };
+
+ partition@100000 {
+ label = "env";
+ reg = <0x100000 0x80000>;
+ };
+
+ partition@180000 {
+ label = "env2";
+ reg = <0x180000 0x80000>;
+ };
+
+ partition@200000 {
+ label = "firmware";
+ reg = <0x200000 0x80000>;
+ };
+
+ partition@280000 {
+ label = "dtb";
+ reg = <0x280000 0x80000>;
+ };
+
+ partition@300000 {
+ label = "kernel";
+ reg = <0x300000 0x500000>;
+ };
+
+ partition@800000 {
+ label = "rootfs";
+ reg = <0x800000 0xf800000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 67d672792b0d..b8d3905915ac 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -58,7 +58,7 @@
reg = <0x10000000 0x10000000>;
ranges;
- wdog@10002000 {
+ wdog: wdog@10002000 {
compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
reg = <0x10002000 0x4000>;
interrupts = <27>;
@@ -218,7 +218,8 @@
status = "disabled";
};
};
- nand@d8000000 {
+
+ nfc: nand@d8000000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/imx28-apf28.dts
new file mode 100644
index 000000000000..7eb075876c4c
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-apf28.dts
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ *
+ * 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 = "Armadeus Systems APF28 module";
+ compatible = "armadeus,imx28-apf28", "fsl,imx28";
+
+ memory {
+ reg = <0x40000000 0x08000000>;
+ };
+
+ apb@80000000 {
+ apbh@80000000 {
+ gpmi-nand@8000c000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+ status = "okay";
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0 0x300000>;
+ };
+
+ partition@300000 {
+ label = "env";
+ reg = <0x300000 0x80000>;
+ };
+
+ partition@380000 {
+ label = "env2";
+ reg = <0x380000 0x80000>;
+ };
+
+ partition@400000 {
+ label = "dtb";
+ reg = <0x400000 0x80000>;
+ };
+
+ partition@480000 {
+ label = "splash";
+ reg = <0x480000 0x80000>;
+ };
+
+ partition@500000 {
+ label = "kernel";
+ reg = <0x500000 0x800000>;
+ };
+
+ partition@d00000 {
+ label = "rootfs";
+ reg = <0xd00000 0xf300000>;
+ };
+ };
+ };
+
+ apbx@80040000 {
+ duart: serial@80074000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&duart_pins_a>;
+ status = "okay";
+ };
+ };
+ };
+
+ ahb@80080000 {
+ mac0: ethernet@800f0000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac0_pins_a>;
+ phy-reset-gpios = <&gpio4 13 0>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
new file mode 100644
index 000000000000..6d8865bfb4b7
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ *
+ * 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
+ */
+
+/* APF28Dev is a docking board for the APF28 SOM */
+/include/ "imx28-apf28.dts"
+
+/ {
+ model = "Armadeus Systems APF28Dev docking/development board";
+ compatible = "armadeus,imx28-apf28dev", "armadeus,imx28-apf28", "fsl,imx28";
+
+ apb@80000000 {
+ apbh@80000000 {
+ ssp0: ssp@80010000 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_4bit_pins_a
+ &mmc0_cd_cfg &mmc0_sck_cfg>;
+ bus-width = <4>;
+ status = "okay";
+ };
+
+ ssp2: ssp@80014000 {
+ compatible = "fsl,imx28-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
+ };
+
+ pinctrl@80018000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hog_pins_apf28dev>;
+
+ hog_pins_apf28dev: hog@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x1103 /* MX28_PAD_LCD_D16__GPIO_1_16 */
+ 0x1113 /* MX28_PAD_LCD_D17__GPIO_1_17 */
+ 0x1123 /* MX28_PAD_LCD_D18__GPIO_1_18 */
+ 0x1133 /* MX28_PAD_LCD_D19__GPIO_1_19 */
+ 0x1143 /* MX28_PAD_LCD_D20__GPIO_1_20 */
+ 0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
+ 0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
+ lcdif_pins_apf28dev: lcdif-apf28dev@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+ 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+ 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+ 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+ };
+
+ lcdif@80030000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcdif_16bit_pins_a
+ &lcdif_pins_apf28dev>;
+ status = "okay";
+ };
+ };
+
+ apbx@80040000 {
+ lradc@80050000 {
+ status = "okay";
+ };
+
+ i2c0: i2c@80058000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+ };
+
+ pwm: pwm@80064000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_pins_a &pwm4_pins_a>;
+ status = "okay";
+ };
+
+ usbphy0: usbphy@8007c000 {
+ status = "okay";
+ };
+
+ usbphy1: usbphy@8007e000 {
+ status = "okay";
+ };
+ };
+ };
+
+ ahb@80080000 {
+ usb0: usb@80080000 {
+ vbus-supply = <&reg_usb0_vbus>;
+ status = "okay";
+ };
+
+ usb1: usb@80090000 {
+ status = "okay";
+ };
+
+ mac1: ethernet@800f4000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac1_pins_a>;
+ phy-reset-gpios = <&gpio0 23 0>;
+ status = "okay";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_usb0_vbus: usb0_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 23 1>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user {
+ label = "Heartbeat";
+ gpios = <&gpio0 21 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+
+ pwms = <&pwm 3 191000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index c03a577beca3..1594694532b9 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -22,6 +22,31 @@
apb@80000000 {
apbh@80000000 {
+ pinctrl@80018000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hog_pins_cfa10036>;
+
+ hog_pins_cfa10036: hog-10036@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x2073 /* MX28_PAD_SSP0_D7__GPIO_2_7 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
+ led_pins_cfa10036: leds-10036@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x3043 /* MX28_PAD_AUART1_RX__GPIO_3_4 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+ };
+
ssp0: ssp@80010000 {
compatible = "fsl,imx28-mmc";
pinctrl-names = "default";
@@ -33,16 +58,37 @@
};
apbx@80040000 {
+ pwm: pwm@80064000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm4_pins_a>;
+ status = "okay";
+ };
+
duart: serial@80074000 {
pinctrl-names = "default";
pinctrl-0 = <&duart_pins_b>;
status = "okay";
};
+
+ i2c0: i2c@80058000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_b>;
+ status = "okay";
+
+ ssd1307: oled@3c {
+ compatible = "solomon,ssd1307fb-i2c";
+ reg = <0x3c>;
+ pwms = <&pwm 4 3000>;
+ reset-gpios = <&gpio2 7 0>;
+ };
+ };
};
};
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins_cfa10036>;
power {
gpios = <&gpio3 4 1>;
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 05c892e931e3..b222614ac9e0 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -22,6 +22,22 @@
apb@80000000 {
apbh@80000000 {
pinctrl@80018000 {
+ pinctrl-names = "default", "default";
+ pinctrl-1 = <&hog_pins_cfa10049>;
+
+ hog_pins_cfa10049: hog-10049@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+ 0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
+ 0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
+ 0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
spi3_pins_cfa10049: spi3-cfa10049@0 {
reg = <0>;
fsl,pinmux-ids = <
@@ -29,6 +45,7 @@
0x01c1 /* MX28_PAD_GPMI_RESETN__SSP3_CMD */
0x0111 /* MX28_PAD_GPMI_CE1N__SSP3_D3 */
0x01a2 /* MX28_PAD_GPMI_ALE__SSP3_D4 */
+ 0x01b2 /* MX28_PAD_GPMI_CLE__SSP3_D5 */
>;
fsl,drive-strength = <1>;
fsl,voltage = <1>;
@@ -60,6 +77,11 @@
spi-max-frequency = <100000>;
};
+ dac0: dh2228@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <2>;
+ spi-max-frequency = <100000>;
+ };
};
};
@@ -96,4 +118,15 @@
gpio = <&gpio0 7 1>;
};
};
+
+ ahb@80080000 {
+ mac0: ethernet@800f0000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac0_pins_a>;
+ phy-reset-gpios = <&gpio2 21 0>;
+ phy-reset-duration = <100>;
+ status = "okay";
+ };
+ };
};
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index a0ad71ca3a44..2da316e04409 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -76,7 +76,6 @@
0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
- 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
>;
@@ -85,6 +84,16 @@
fsl,pull-up = <0>;
};
+ led_pin_gpio3_5: led_gpio3_5@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
gpmi_pins_evk: gpmi-nand-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
@@ -288,6 +297,8 @@
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pin_gpio3_5>;
user {
label = "Heartbeat";
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
new file mode 100644
index 000000000000..e6cde8aa7fff
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@denx.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 = "SchulerControl GmbH, SC SPS 1";
+ compatible = "schulercontrol,imx28-sps1", "fsl,imx28";
+
+ memory {
+ reg = <0x40000000 0x08000000>;
+ };
+
+ apb@80000000 {
+ apbh@80000000 {
+ pinctrl@80018000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hog_pins_a>;
+
+ hog_pins_a: hog-gpios@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x0003 /* MX28_PAD_GPMI_D00__GPIO_0_0 */
+ 0x0033 /* MX28_PAD_GPMI_D03__GPIO_0_3 */
+ 0x0063 /* MX28_PAD_GPMI_D06__GPIO_0_6 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
+ };
+
+ ssp0: ssp@80010000 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_4bit_pins_a>;
+ bus-width = <4>;
+ status = "okay";
+ };
+
+ ssp2: ssp@80014000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx28-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "everspin,mr25h256", "mr25h256";
+ spi-max-frequency = <40000000>;
+ reg = <0>;
+ };
+ };
+ };
+
+ apbx@80040000 {
+ i2c0: i2c@80058000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ rtc: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+
+ eeprom: eeprom@52 {
+ compatible = "atmel,24c64";
+ reg = <0x52>;
+ pagesize = <32>;
+ };
+ };
+
+ duart: serial@80074000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&duart_pins_a>;
+ status = "okay";
+ };
+
+ usbphy0: usbphy@8007c000 {
+ status = "okay";
+ };
+
+ auart0: serial@8006a000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&auart0_pins_a>;
+ status = "okay";
+ };
+ };
+ };
+
+ ahb@80080000 {
+ usb0: usb@80080000 {
+ vbus-supply = <&reg_usb0_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbphy0_pins_b>;
+ status = "okay";
+ };
+
+ mac0: ethernet@800f0000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac0_pins_a>;
+ status = "okay";
+ };
+
+ mac1: ethernet@800f4000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac1_pins_a>;
+ status = "okay";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_usb0_vbus: usb0_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 9 0>;
+ };
+ };
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "gpio-leds";
+ status = "okay";
+
+ led@1 {
+ label = "sps1-1:yellow:user";
+ gpios = <&gpio0 6 0>;
+ linux,default-trigger = "heartbeat";
+ reg = <0>;
+ };
+
+ led@2 {
+ label = "sps1-2:red:user";
+ gpios = <&gpio0 3 0>;
+ linux,default-trigger = "heartbeat";
+ reg = <1>;
+ };
+
+ led@3 {
+ label = "sps1-3:red:user";
+ gpios = <&gpio0 0 0>;
+ default-trigger = "heartbeat";
+ reg = <2>;
+ };
+
+ };
+};
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index b4587b27ae42..13b7053d799e 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -492,6 +492,16 @@
fsl,pull-up = <0>;
};
+ pwm3_pins_a: pwm3@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x31c0 /* MX28_PAD_PWM3__PWM_3 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
pwm4_pins_a: pwm4@0 {
reg = <0>;
fsl,pinmux-ids = <
@@ -535,6 +545,31 @@
fsl,pull-up = <0>;
};
+ lcdif_16bit_pins_a: lcdif-16bit@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
+ 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
+ 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
+ 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
+ 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
+ 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
+ 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
+ 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
+ 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
+ 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
+ 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
+ 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
+ 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
+ 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
+ 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
+ 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
can0_pins_a: can0@0 {
reg = <0>;
fsl,pinmux-ids = <
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 2781e47cff0d..1f5d45eff45e 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -83,7 +83,7 @@
reg = <0x70000000 0x40000>;
ranges;
- esdhc@70004000 { /* ESDHC1 */
+ esdhc1: esdhc@70004000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70004000 0x4000>;
interrupts = <1>;
@@ -92,12 +92,13 @@
status = "disabled";
};
- esdhc@70008000 { /* ESDHC2 */
+ esdhc2: esdhc@70008000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70008000 0x4000>;
interrupts = <2>;
clocks = <&clks 45>, <&clks 0>, <&clks 72>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
@@ -110,7 +111,7 @@
status = "disabled";
};
- ecspi@70010000 { /* ECSPI1 */
+ ecspi1: ecspi@70010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-ecspi";
@@ -131,47 +132,49 @@
status = "disabled";
};
- esdhc@70020000 { /* ESDHC3 */
+ esdhc3: esdhc@70020000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70020000 0x4000>;
interrupts = <3>;
clocks = <&clks 46>, <&clks 0>, <&clks 73>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- esdhc@70024000 { /* ESDHC4 */
+ esdhc4: esdhc@70024000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70024000 0x4000>;
interrupts = <4>;
clocks = <&clks 47>, <&clks 0>, <&clks 74>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
};
- usb@73f80000 {
+ usbotg: usb@73f80000 {
compatible = "fsl,imx51-usb", "fsl,imx27-usb";
reg = <0x73f80000 0x0200>;
interrupts = <18>;
status = "disabled";
};
- usb@73f80200 {
+ usbh1: usb@73f80200 {
compatible = "fsl,imx51-usb", "fsl,imx27-usb";
reg = <0x73f80200 0x0200>;
interrupts = <14>;
status = "disabled";
};
- usb@73f80400 {
+ usbh2: usb@73f80400 {
compatible = "fsl,imx51-usb", "fsl,imx27-usb";
reg = <0x73f80400 0x0200>;
interrupts = <16>;
status = "disabled";
};
- usb@73f80600 {
+ usbh3: usb@73f80600 {
compatible = "fsl,imx51-usb", "fsl,imx27-usb";
reg = <0x73f80600 0x0200>;
interrupts = <17>;
@@ -218,14 +221,14 @@
#interrupt-cells = <2>;
};
- wdog@73f98000 { /* WDOG1 */
+ wdog1: wdog@73f98000 {
compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
reg = <0x73f98000 0x4000>;
interrupts = <58>;
clocks = <&clks 0>;
};
- wdog@73f9c000 { /* WDOG2 */
+ wdog2: wdog@73f9c000 {
compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
reg = <0x73f9c000 0x4000>;
interrupts = <59>;
@@ -233,7 +236,7 @@
status = "disabled";
};
- iomuxc@73fa8000 {
+ iomuxc: iomuxc@73fa8000 {
compatible = "fsl,imx51-iomuxc";
reg = <0x73fa8000 0x4000>;
@@ -460,7 +463,7 @@
reg = <0x80000000 0x10000000>;
ranges;
- ecspi@83fac000 { /* ECSPI2 */
+ ecspi2: ecspi@83fac000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-ecspi";
@@ -471,7 +474,7 @@
status = "disabled";
};
- sdma@83fb0000 {
+ sdma: sdma@83fb0000 {
compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
reg = <0x83fb0000 0x4000>;
interrupts = <6>;
@@ -480,7 +483,7 @@
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
};
- cspi@83fc0000 {
+ cspi: cspi@83fc0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
@@ -491,7 +494,7 @@
status = "disabled";
};
- i2c@83fc4000 { /* I2C2 */
+ i2c2: i2c@83fc4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
@@ -501,7 +504,7 @@
status = "disabled";
};
- i2c@83fc8000 { /* I2C1 */
+ i2c1: i2c@83fc8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
@@ -521,13 +524,13 @@
status = "disabled";
};
- audmux@83fd0000 {
+ audmux: audmux@83fd0000 {
compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
reg = <0x83fd0000 0x4000>;
status = "disabled";
};
- nand@83fdb000 {
+ nfc: nand@83fdb000 {
compatible = "fsl,imx51-nand";
reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
interrupts = <8>;
@@ -545,7 +548,7 @@
status = "disabled";
};
- ethernet@83fec000 {
+ fec: ethernet@83fec000 {
compatible = "fsl,imx51-fec", "fsl,imx27-fec";
reg = <0x83fec000 0x4000>;
interrupts = <87>;
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 08948af86d1a..b0075537195b 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -60,10 +60,17 @@
697 0x80000000 /* MX53_PAD_EIM_DA12__GPIO3_12 */
701 0x80000000 /* MX53_PAD_EIM_DA13__GPIO3_13 */
868 0x80000000 /* MX53_PAD_PATA_DA_0__GPIO7_6 */
+ 1149 0x80000000 /* MX53_PAD_GPIO_16__GPIO7_11 */
+ >;
+ };
+
+ led_pin_gpio7_7: led_gpio7_7@0 {
+ fsl,pins = <
873 0x80000000 /* MX53_PAD_PATA_DA_1__GPIO7_7 */
>;
};
};
+
};
uart1: serial@53fbc000 {
@@ -100,76 +107,93 @@
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 {
- buck0 {
+ buck1_reg: buck1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
+ regulator-always-on;
};
- buck1 {
+ buck2_reg: buck2 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
+ regulator-always-on;
};
- buck2 {
+ buck3_reg: buck3 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
+ regulator-always-on;
};
- buck3 {
+ buck4_reg: buck4 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
+ regulator-always-on;
};
- ldo4 {
+ ldo1_reg: ldo1 {
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
};
- ldo5 {
+ ldo2_reg: ldo2 {
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: ldo3 {
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1800000>;
+ regulator-always-on;
};
- ldo6 {
+ ldo4_reg: ldo4 {
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
- ldo7 {
+ ldo5_reg: ldo5 {
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
- ldo8 {
+ ldo6_reg: ldo6 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
+ regulator-always-on;
};
- ldo9 {
+ ldo7_reg: ldo7 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
+ regulator-always-on;
};
- ldo10 {
+ ldo8_reg: ldo8 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
+ regulator-always-on;
};
- ldo11 {
+ ldo9_reg: ldo9 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
+ regulator-always-on;
};
- ldo12 {
+ ldo10_reg: ldo10 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3650000>;
- };
-
- ldo13 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <3600000>;
+ regulator-always-on;
};
};
};
@@ -216,6 +240,8 @@
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pin_gpio7_7>;
user {
label = "Heartbeat";
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index da9a047ce4cf..552aed4ff982 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -88,21 +88,23 @@
reg = <0x50000000 0x40000>;
ranges;
- esdhc@50004000 { /* ESDHC1 */
+ esdhc1: esdhc@50004000 {
compatible = "fsl,imx53-esdhc";
reg = <0x50004000 0x4000>;
interrupts = <1>;
clocks = <&clks 44>, <&clks 0>, <&clks 71>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- esdhc@50008000 { /* ESDHC2 */
+ esdhc2: esdhc@50008000 {
compatible = "fsl,imx53-esdhc";
reg = <0x50008000 0x4000>;
interrupts = <2>;
clocks = <&clks 45>, <&clks 0>, <&clks 72>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
@@ -115,7 +117,7 @@
status = "disabled";
};
- ecspi@50010000 { /* ECSPI1 */
+ ecspi1: ecspi@50010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
@@ -136,47 +138,49 @@
status = "disabled";
};
- esdhc@50020000 { /* ESDHC3 */
+ esdhc3: esdhc@50020000 {
compatible = "fsl,imx53-esdhc";
reg = <0x50020000 0x4000>;
interrupts = <3>;
clocks = <&clks 46>, <&clks 0>, <&clks 73>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- esdhc@50024000 { /* ESDHC4 */
+ esdhc4: esdhc@50024000 {
compatible = "fsl,imx53-esdhc";
reg = <0x50024000 0x4000>;
interrupts = <4>;
clocks = <&clks 47>, <&clks 0>, <&clks 74>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
};
- usb@53f80000 {
+ usbotg: usb@53f80000 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80000 0x0200>;
interrupts = <18>;
status = "disabled";
};
- usb@53f80200 {
+ usbh1: usb@53f80200 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80200 0x0200>;
interrupts = <14>;
status = "disabled";
};
- usb@53f80400 {
+ usbh2: usb@53f80400 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80400 0x0200>;
interrupts = <16>;
status = "disabled";
};
- usb@53f80600 {
+ usbh3: usb@53f80600 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80600 0x0200>;
interrupts = <17>;
@@ -223,14 +227,14 @@
#interrupt-cells = <2>;
};
- wdog@53f98000 { /* WDOG1 */
+ wdog1: wdog@53f98000 {
compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
reg = <0x53f98000 0x4000>;
interrupts = <58>;
clocks = <&clks 0>;
};
- wdog@53f9c000 { /* WDOG2 */
+ wdog2: wdog@53f9c000 {
compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
reg = <0x53f9c000 0x4000>;
interrupts = <59>;
@@ -238,7 +242,7 @@
status = "disabled";
};
- iomuxc@53fa8000 {
+ iomuxc: iomuxc@53fa8000 {
compatible = "fsl,imx53-iomuxc";
reg = <0x53fa8000 0x4000>;
@@ -338,6 +342,24 @@
};
};
+ can1 {
+ pinctrl_can1_1: can1grp-1 {
+ fsl,pins = <
+ 847 0x80000000 /* MX53_PAD_PATA_INTRQ__CAN1_TXCAN */
+ 853 0x80000000 /* MX53_PAD_PATA_DIOR__CAN1_RXCAN */
+ >;
+ };
+ };
+
+ can2 {
+ pinctrl_can2_1: can2grp-1 {
+ fsl,pins = <
+ 67 0x80000000 /* MX53_PAD_KEY_COL4__CAN2_TXCAN */
+ 74 0x80000000 /* MX53_PAD_KEY_ROW4__CAN2_RXCAN */
+ >;
+ };
+ };
+
i2c1 {
pinctrl_i2c1_1: i2c1grp-1 {
fsl,pins = <
@@ -356,6 +378,15 @@
};
};
+ i2c3 {
+ pinctrl_i2c3_1: i2c3grp-1 {
+ fsl,pins = <
+ 1102 0xc0000000 /* MX53_PAD_GPIO_6__I2C3_SDA */
+ 1130 0xc0000000 /* MX53_PAD_GPIO_5__I2C3_SCL */
+ >;
+ };
+ };
+
uart1 {
pinctrl_uart1_1: uart1grp-1 {
fsl,pins = <
@@ -391,6 +422,25 @@
>;
};
};
+
+ uart4 {
+ pinctrl_uart4_1: uart4grp-1 {
+ fsl,pins = <
+ 11 0x1c5 /* MX53_PAD_KEY_COL0__UART4_TXD_MUX */
+ 18 0x1c5 /* MX53_PAD_KEY_ROW0__UART4_RXD_MUX */
+ >;
+ };
+ };
+
+ uart5 {
+ pinctrl_uart5_1: uart5grp-1 {
+ fsl,pins = <
+ 24 0x1c5 /* MX53_PAD_KEY_COL1__UART5_TXD_MUX */
+ 31 0x1c5 /* MX53_PAD_KEY_ROW1__UART5_RXD_MUX */
+ >;
+ };
+ };
+
};
pwm1: pwm@53fb4000 {
@@ -484,7 +534,7 @@
#interrupt-cells = <2>;
};
- i2c@53fec000 { /* I2C3 */
+ i2c3: i2c@53fec000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
@@ -520,7 +570,7 @@
status = "disabled";
};
- ecspi@63fac000 { /* ECSPI2 */
+ ecspi2: ecspi@63fac000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
@@ -531,7 +581,7 @@
status = "disabled";
};
- sdma@63fb0000 {
+ sdma: sdma@63fb0000 {
compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
reg = <0x63fb0000 0x4000>;
interrupts = <6>;
@@ -540,7 +590,7 @@
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
};
- cspi@63fc0000 {
+ cspi: cspi@63fc0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
@@ -551,7 +601,7 @@
status = "disabled";
};
- i2c@63fc4000 { /* I2C2 */
+ i2c2: i2c@63fc4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
@@ -561,7 +611,7 @@
status = "disabled";
};
- i2c@63fc8000 { /* I2C1 */
+ i2c1: i2c@63fc8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
@@ -581,13 +631,13 @@
status = "disabled";
};
- audmux@63fd0000 {
+ audmux: audmux@63fd0000 {
compatible = "fsl,imx53-audmux", "fsl,imx31-audmux";
reg = <0x63fd0000 0x4000>;
status = "disabled";
};
- nand@63fdb000 {
+ nfc: nand@63fdb000 {
compatible = "fsl,imx53-nand";
reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
interrupts = <8>;
@@ -605,7 +655,7 @@
status = "disabled";
};
- ethernet@63fec000 {
+ fec: ethernet@63fec000 {
compatible = "fsl,imx53-fec", "fsl,imx25-fec";
reg = <0x63fec000 0x4000>;
interrupts = <87>;
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
new file mode 100644
index 000000000000..826e4ad1477e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 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/ "imx6q.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Quad SABRE Automotive Board";
+ compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+
+ soc {
+ aips-bus@02000000 { /* AIPS1 */
+ iomuxc@020e0000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ hog {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ 1376 0x80000000 /* MX6Q_PAD_NANDF_CS2__GPIO_6_15 */
+ 13 0x80000000 /* MX6Q_PAD_SD2_DAT2__GPIO_1_13 */
+ >;
+ };
+ };
+ };
+ };
+
+ aips-bus@02100000 { /* AIPS2 */
+ uart4: serial@021f0000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4_1>;
+ status = "okay";
+ };
+
+ ethernet@02188000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_2>;
+ phy-mode = "rgmii";
+ status = "okay";
+ };
+
+ usdhc@02198000 { /* uSDHC3 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ cd-gpios = <&gpio6 15 0>;
+ wp-gpios = <&gpio1 13 0>;
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index e596c28c214d..a42402562b7b 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -38,6 +38,8 @@
hog {
pinctrl_hog: hoggrp {
fsl,pins = <
+ 1004 0x80000000 /* MX6Q_PAD_GPIO_4__GPIO_1_4 */
+ 1012 0x80000000 /* MX6Q_PAD_GPIO_5__GPIO_1_5 */
1402 0x80000000 /* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
1410 0x80000000 /* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
1418 0x80000000 /* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
@@ -73,4 +75,20 @@
};
};
};
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 4 0>;
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 5 0>;
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index d907d062e5dd..d6265ca97119 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -36,6 +36,14 @@
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 792000 1100000
+ 396000 950000
+ 198000 850000
+ >;
+ clock-latency = <61036>; /* two CLK32 periods */
+ cpu0-supply = <&reg_cpu>;
};
cpu@1 {
@@ -100,7 +108,7 @@
clocks = <&clks 106>;
};
- gpmi-nand@00112000 {
+ nfc: gpmi-nand@00112000 {
compatible = "fsl,imx6q-gpmi-nand";
#address-cells = <1>;
#size-cells = <1>;
@@ -144,12 +152,12 @@
reg = <0x02000000 0x40000>;
ranges;
- spdif@02004000 {
+ spdif: spdif@02004000 {
reg = <0x02004000 0x4000>;
interrupts = <0 52 0x04>;
};
- ecspi@02008000 { /* eCSPI1 */
+ ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -160,7 +168,7 @@
status = "disabled";
};
- ecspi@0200c000 { /* eCSPI2 */
+ ecspi2: ecspi@0200c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -171,7 +179,7 @@
status = "disabled";
};
- ecspi@02010000 { /* eCSPI3 */
+ ecspi3: ecspi@02010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -182,7 +190,7 @@
status = "disabled";
};
- ecspi@02014000 { /* eCSPI4 */
+ ecspi4: ecspi@02014000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -193,7 +201,7 @@
status = "disabled";
};
- ecspi@02018000 { /* eCSPI5 */
+ ecspi5: ecspi@02018000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -213,7 +221,7 @@
status = "disabled";
};
- esai@02024000 {
+ esai: esai@02024000 {
reg = <0x02024000 0x4000>;
interrupts = <0 51 0x04>;
};
@@ -248,7 +256,7 @@
status = "disabled";
};
- asrc@02034000 {
+ asrc: asrc@02034000 {
reg = <0x02034000 0x4000>;
interrupts = <0 50 0x04>;
};
@@ -258,7 +266,7 @@
};
};
- vpu@02040000 {
+ vpu: vpu@02040000 {
reg = <0x02040000 0x3c000>;
interrupts = <0 3 0x04 0 12 0x04>;
};
@@ -267,7 +275,7 @@
reg = <0x0207c000 0x4000>;
};
- pwm@02080000 { /* PWM1 */
+ pwm1: pwm@02080000 {
#pwm-cells = <2>;
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02080000 0x4000>;
@@ -276,7 +284,7 @@
clock-names = "ipg", "per";
};
- pwm@02084000 { /* PWM2 */
+ pwm2: pwm@02084000 {
#pwm-cells = <2>;
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02084000 0x4000>;
@@ -285,7 +293,7 @@
clock-names = "ipg", "per";
};
- pwm@02088000 { /* PWM3 */
+ pwm3: pwm@02088000 {
#pwm-cells = <2>;
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02088000 0x4000>;
@@ -294,7 +302,7 @@
clock-names = "ipg", "per";
};
- pwm@0208c000 { /* PWM4 */
+ pwm4: pwm@0208c000 {
#pwm-cells = <2>;
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x0208c000 0x4000>;
@@ -303,17 +311,17 @@
clock-names = "ipg", "per";
};
- flexcan@02090000 { /* CAN1 */
+ can1: flexcan@02090000 {
reg = <0x02090000 0x4000>;
interrupts = <0 110 0x04>;
};
- flexcan@02094000 { /* CAN2 */
+ can2: flexcan@02094000 {
reg = <0x02094000 0x4000>;
interrupts = <0 111 0x04>;
};
- gpt@02098000 {
+ gpt: gpt@02098000 {
compatible = "fsl,imx6q-gpt";
reg = <0x02098000 0x4000>;
interrupts = <0 55 0x04>;
@@ -389,19 +397,19 @@
#interrupt-cells = <2>;
};
- kpp@020b8000 {
+ kpp: kpp@020b8000 {
reg = <0x020b8000 0x4000>;
interrupts = <0 82 0x04>;
};
- wdog@020bc000 { /* WDOG1 */
+ wdog1: wdog@020bc000 {
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020bc000 0x4000>;
interrupts = <0 80 0x04>;
clocks = <&clks 0>;
};
- wdog@020c0000 { /* WDOG2 */
+ wdog2: wdog@020c0000 {
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020c0000 0x4000>;
interrupts = <0 81 0x04>;
@@ -463,7 +471,7 @@
anatop-max-voltage = <2750000>;
};
- regulator-vddcore@140 {
+ reg_cpu: regulator-vddcore@140 {
compatible = "fsl,anatop-regulator";
regulator-name = "cpu";
regulator-min-microvolt = <725000>;
@@ -521,27 +529,35 @@
};
snvs@020cc000 {
- reg = <0x020cc000 0x4000>;
- interrupts = <0 19 0x04 0 20 0x04>;
+ compatible = "fsl,sec-v4.0-mon", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x020cc000 0x4000>;
+
+ snvs-rtc-lp@34 {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ reg = <0x34 0x58>;
+ interrupts = <0 19 0x04 0 20 0x04>;
+ };
};
- epit@020d0000 { /* EPIT1 */
+ epit1: epit@020d0000 { /* EPIT1 */
reg = <0x020d0000 0x4000>;
interrupts = <0 56 0x04>;
};
- epit@020d4000 { /* EPIT2 */
+ epit2: epit@020d4000 { /* EPIT2 */
reg = <0x020d4000 0x4000>;
interrupts = <0 57 0x04>;
};
- src@020d8000 {
+ src: src@020d8000 {
compatible = "fsl,imx6q-src";
reg = <0x020d8000 0x4000>;
interrupts = <0 91 0x04 0 96 0x04>;
};
- gpc@020dc000 {
+ gpc: gpc@020dc000 {
compatible = "fsl,imx6q-gpc";
reg = <0x020dc000 0x4000>;
interrupts = <0 89 0x04 0 90 0x04>;
@@ -552,7 +568,7 @@
reg = <0x020e0000 0x38>;
};
- iomuxc@020e0000 {
+ iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6q-iomuxc";
reg = <0x020e0000 0x4000>;
@@ -596,6 +612,7 @@
66 0x1b0b0 /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
70 0x1b0b0 /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
48 0x1b0b0 /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+ 1033 0x4001b0a8 /* MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT*/
>;
};
@@ -764,17 +781,17 @@
};
};
- dcic@020e4000 { /* DCIC1 */
+ dcic1: dcic@020e4000 {
reg = <0x020e4000 0x4000>;
interrupts = <0 124 0x04>;
};
- dcic@020e8000 { /* DCIC2 */
+ dcic2: dcic@020e8000 {
reg = <0x020e8000 0x4000>;
interrupts = <0 125 0x04>;
};
- sdma@020ec000 {
+ sdma: sdma@020ec000 {
compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <0 2 0x04>;
@@ -800,7 +817,7 @@
reg = <0x0217c000 0x4000>;
};
- usb@02184000 { /* USB OTG */
+ usbotg: usb@02184000 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184000 0x200>;
interrupts = <0 43 0x04>;
@@ -810,7 +827,7 @@
status = "disabled";
};
- usb@02184200 { /* USB1 */
+ usbh1: usb@02184200 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184200 0x200>;
interrupts = <0 40 0x04>;
@@ -820,7 +837,7 @@
status = "disabled";
};
- usb@02184400 { /* USB2 */
+ usbh2: usb@02184400 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184400 0x200>;
interrupts = <0 41 0x04>;
@@ -829,7 +846,7 @@
status = "disabled";
};
- usb@02184600 { /* USB3 */
+ usbh3: usb@02184600 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184600 0x200>;
interrupts = <0 42 0x04>;
@@ -838,19 +855,19 @@
status = "disabled";
};
- usbmisc: usbmisc@02184800 {
+ usbmisc: usbmisc: usbmisc@02184800 {
#index-cells = <1>;
compatible = "fsl,imx6q-usbmisc";
reg = <0x02184800 0x200>;
clocks = <&clks 162>;
};
- ethernet@02188000 {
+ fec: ethernet@02188000 {
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupts = <0 118 0x04 0 119 0x04>;
- clocks = <&clks 117>, <&clks 117>;
- clock-names = "ipg", "ahb";
+ clocks = <&clks 117>, <&clks 117>, <&clks 177>;
+ clock-names = "ipg", "ahb", "ptp";
status = "disabled";
};
@@ -859,43 +876,47 @@
interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
};
- usdhc@02190000 { /* uSDHC1 */
+ usdhc1: usdhc@02190000 {
compatible = "fsl,imx6q-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <0 22 0x04>;
clocks = <&clks 163>, <&clks 163>, <&clks 163>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- usdhc@02194000 { /* uSDHC2 */
+ usdhc2: usdhc@02194000 {
compatible = "fsl,imx6q-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <0 23 0x04>;
clocks = <&clks 164>, <&clks 164>, <&clks 164>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- usdhc@02198000 { /* uSDHC3 */
+ usdhc3: usdhc@02198000 {
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
clocks = <&clks 165>, <&clks 165>, <&clks 165>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- usdhc@0219c000 { /* uSDHC4 */
+ usdhc4: usdhc@0219c000 {
compatible = "fsl,imx6q-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <0 25 0x04>;
clocks = <&clks 166>, <&clks 166>, <&clks 166>;
clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
status = "disabled";
};
- i2c@021a0000 { /* I2C1 */
+ i2c1: i2c@021a0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
@@ -905,7 +926,7 @@
status = "disabled";
};
- i2c@021a4000 { /* I2C2 */
+ i2c2: i2c@021a4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
@@ -915,7 +936,7 @@
status = "disabled";
};
- i2c@021a8000 { /* I2C3 */
+ i2c3: i2c@021a8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
@@ -929,12 +950,12 @@
reg = <0x021ac000 0x4000>;
};
- mmdc@021b0000 { /* MMDC0 */
+ mmdc0: mmdc@021b0000 { /* MMDC0 */
compatible = "fsl,imx6q-mmdc";
reg = <0x021b0000 0x4000>;
};
- mmdc@021b4000 { /* MMDC1 */
+ mmdc1: mmdc@021b4000 { /* MMDC1 */
reg = <0x021b4000 0x4000>;
};
@@ -962,7 +983,7 @@
interrupts = <0 109 0x04>;
};
- audmux@021d8000 {
+ audmux: audmux@021d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
status = "disabled";
diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/kirkwood-6281.dtsi
new file mode 100644
index 000000000000..d6c9d65cbaeb
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-6281.dtsi
@@ -0,0 +1,44 @@
+/ {
+ ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+ compatible = "marvell,88f6281-pinctrl";
+ reg = <0x10000 0x20>;
+
+ pmx_nand: pmx-nand {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+ "mpp4", "mpp5", "mpp18",
+ "mpp19";
+ marvell,function = "nand";
+ };
+ pmx_sata0: pmx-sata0 {
+ marvell,pins = "mpp5", "mpp21", "mpp23";
+ marvell,function = "sata0";
+ };
+ pmx_sata1: pmx-sata1 {
+ marvell,pins = "mpp4", "mpp20", "mpp22";
+ marvell,function = "sata1";
+ };
+ pmx_spi: pmx-spi {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+ marvell,function = "spi";
+ };
+ pmx_twsi0: pmx-twsi0 {
+ marvell,pins = "mpp8", "mpp9";
+ marvell,function = "twsi0";
+ };
+ pmx_uart0: pmx-uart0 {
+ marvell,pins = "mpp10", "mpp11";
+ marvell,function = "uart0";
+ };
+ pmx_uart1: pmx-uart1 {
+ marvell,pins = "mpp13", "mpp14";
+ marvell,function = "uart1";
+ };
+ pmx_sdio: pmx-sdio {
+ marvell,pins = "mpp12", "mpp13", "mpp14",
+ "mpp15", "mpp16", "mpp17";
+ marvell,function = "sdio";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi
new file mode 100644
index 000000000000..9ae2004d5675
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-6282.dtsi
@@ -0,0 +1,45 @@
+/ {
+ ocp@f1000000 {
+
+ pinctrl: pinctrl@10000 {
+ compatible = "marvell,88f6282-pinctrl";
+ reg = <0x10000 0x20>;
+
+ pmx_sata0: pmx-sata0 {
+ marvell,pins = "mpp5", "mpp21", "mpp23";
+ marvell,function = "sata0";
+ };
+ pmx_sata1: pmx-sata1 {
+ marvell,pins = "mpp4", "mpp20", "mpp22";
+ marvell,function = "sata1";
+ };
+ pmx_spi: pmx-spi {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+ marvell,function = "spi";
+ };
+ pmx_twsi0: pmx-twsi0 {
+ marvell,pins = "mpp8", "mpp9";
+ marvell,function = "twsi0";
+ };
+ pmx_uart0: pmx-uart0 {
+ marvell,pins = "mpp10", "mpp11";
+ marvell,function = "uart0";
+ };
+
+ pmx_uart1: pmx-uart1 {
+ marvell,pins = "mpp13", "mpp14";
+ marvell,function = "uart1";
+ };
+ };
+
+ i2c@11100 {
+ compatible = "marvell,mv64xxx-i2c";
+ reg = <0x11100 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <32>;
+ clock-frequency = <100000>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi
new file mode 100644
index 000000000000..3271e4c8ea07
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi
@@ -0,0 +1,31 @@
+/ {
+ ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+ compatible = "marvell,98dx4122-pinctrl";
+ reg = <0x10000 0x20>;
+
+ pmx_nand: pmx-nand {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+ "mpp4", "mpp5", "mpp18",
+ "mpp19";
+ marvell,function = "nand";
+ };
+ pmx_spi: pmx-spi {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+ marvell,function = "spi";
+ };
+ pmx_twsi0: pmx-twsi0 {
+ marvell,pins = "mpp8", "mpp9";
+ marvell,function = "twsi0";
+ };
+ pmx_uart0: pmx-uart0 {
+ marvell,pins = "mpp10", "mpp11";
+ marvell,function = "uart0";
+ };
+ pmx_uart1: pmx-uart1 {
+ marvell,pins = "mpp13", "mpp14";
+ marvell,function = "uart1";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index 9b32d0272825..6875ac00c174 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -1,4 +1,5 @@
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "D-Link DNS NASes (kirkwood-based)";
@@ -35,7 +36,116 @@
6000 2>;
};
+ gpio_poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio1 4 0>;
+ };
+
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_nand &pmx_uart1
+ &pmx_sata0 &pmx_sata1
+ &pmx_led_power
+ &pmx_led_red_right_hdd
+ &pmx_led_red_left_hdd
+ &pmx_led_red_usb_325
+ &pmx_button_power
+ &pmx_led_red_usb_320
+ &pmx_power_off &pmx_power_back_on
+ &pmx_power_sata0 &pmx_power_sata1
+ &pmx_present_sata0 &pmx_present_sata1
+ &pmx_led_white_usb &pmx_fan_tacho
+ &pmx_fan_high_speed &pmx_fan_low_speed
+ &pmx_button_unmount &pmx_button_reset
+ &pmx_temp_alarm >;
+ pinctrl-names = "default";
+
+ pmx_sata0: pmx-sata0 {
+ marvell,pins = "mpp20";
+ marvell,function = "sata1";
+ };
+ pmx_sata1: pmx-sata1 {
+ marvell,pins = "mpp21";
+ marvell,function = "sata0";
+ };
+ pmx_led_power: pmx-led-power {
+ marvell,pins = "mpp26";
+ marvell,function = "gpio";
+ };
+ pmx_led_red_right_hdd: pmx-led-red-right-hdd {
+ marvell,pins = "mpp27";
+ marvell,function = "gpio";
+ };
+ pmx_led_red_left_hdd: pmx-led-red-left-hdd {
+ marvell,pins = "mpp28";
+ marvell,function = "gpio";
+ };
+ pmx_led_red_usb_325: pmx-led-red-usb-325 {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+ pmx_button_power: pmx-button-power {
+ marvell,pins = "mpp34";
+ marvell,function = "gpio";
+ };
+ pmx_led_red_usb_320: pmx-led-red-usb-320 {
+ marvell,pins = "mpp35";
+ marvell,function = "gpio";
+ };
+ pmx_power_off: pmx-power-off {
+ marvell,pins = "mpp36";
+ marvell,function = "gpio";
+ };
+ pmx_power_back_on: pmx-power-back-on {
+ marvell,pins = "mpp37";
+ marvell,function = "gpio";
+ };
+ pmx_power_sata0: pmx-power-sata0 {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+ pmx_power_sata1: pmx-power-sata1 {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+ pmx_present_sata0: pmx-present-sata0 {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ pmx_present_sata1: pmx-present-sata1 {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+ pmx_led_white_usb: pmx-led-white-usb {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_fan_tacho: pmx-fan-tacho {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ pmx_fan_high_speed: pmx-fan-high-speed {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+ pmx_fan_low_speed: pmx-fan-low-speed {
+ marvell,pins = "mpp46";
+ marvell,function = "gpio";
+ };
+ pmx_button_unmount: pmx-button-unmount {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ pmx_button_reset: pmx-button-reset {
+ marvell,pins = "mpp48";
+ marvell,function = "gpio";
+ };
+ pmx_temp_alarm: pmx-temp-alarm {
+ marvell,pins = "mpp49";
+ marvell,function = "gpio";
+ };
+ };
sata@80000 {
status = "okay";
nr-ports = <2>;
@@ -43,6 +153,7 @@
nand@3000000 {
status = "okay";
+ chip-delay = <35>;
partition@0 {
label = "u-boot";
@@ -76,4 +187,33 @@
};
};
};
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sata0_power: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "SATA0 Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 7 0>;
+ };
+ sata1_power: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "SATA1 Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 8 0>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
index 08a582414b88..2e3dd34e21a5 100644
--- a/arch/arm/boot/dts/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "Seagate FreeAgent Dockstar";
@@ -16,6 +17,25 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_usb_power_enable
+ &pmx_led_green &pmx_led_orange >;
+ pinctrl-names = "default";
+
+ pmx_usb_power_enable: pmx-usb-power-enable {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+ pmx_led_green: pmx-led-green {
+ marvell,pins = "mpp46";
+ marvell,function = "gpio";
+ };
+ pmx_led_orange: pmx-led-orange {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ };
serial@12000 {
clock-frequency = <200000000>;
status = "ok";
@@ -54,4 +74,21 @@
gpios = <&gpio1 15 1>;
};
};
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_power: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "USB Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 29 0>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts
index 26e281fbf6bc..f2d386c95b07 100644
--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "Globalscale Technologies Dreamplug";
@@ -16,6 +17,26 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_spi
+ &pmx_led_bluetooth &pmx_led_wifi
+ &pmx_led_wifi_ap >;
+ pinctrl-names = "default";
+
+ pmx_led_bluetooth: pmx-led-bluetooth {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ pmx_led_wifi: pmx-led-wifi {
+ marvell,pins = "mpp48";
+ marvell,function = "gpio";
+ };
+ pmx_led_wifi_ap: pmx-led-wifi-ap {
+ marvell,pins = "mpp49";
+ marvell,function = "gpio";
+ };
+ };
serial@12000 {
clock-frequency = <200000000>;
status = "ok";
diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/kirkwood-goflexnet.dts
index 7c8238fbb6f9..1b133e0c566e 100644
--- a/arch/arm/boot/dts/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/kirkwood-goflexnet.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "Seagate GoFlex Net";
@@ -16,6 +17,61 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_usb_power_enable &pmx_led_orange
+ &pmx_led_left_cap_0 &pmx_led_left_cap_1
+ &pmx_led_left_cap_2 &pmx_led_left_cap_3
+ &pmx_led_right_cap_0 &pmx_led_right_cap_1
+ &pmx_led_right_cap_2 &pmx_led_right_cap_3
+ >;
+ pinctrl-names = "default";
+
+ pmx_usb_power_enable: pmx-usb-power-enable {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+ pmx_led_right_cap_0: pmx-led_right_cap_0 {
+ marvell,pins = "mpp38";
+ marvell,function = "gpio";
+ };
+ pmx_led_right_cap_1: pmx-led_right_cap_1 {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+ pmx_led_right_cap_2: pmx-led_right_cap_2 {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+ pmx_led_right_cap_3: pmx-led_right_cap_3 {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ pmx_led_left_cap_0: pmx-led_left_cap_0 {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+ pmx_led_left_cap_1: pmx-led_left_cap_1 {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_led_left_cap_2: pmx-led_left_cap_2 {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ pmx_led_left_cap_3: pmx-led_left_cap_3 {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+ pmx_led_green: pmx-led_green {
+ marvell,pins = "mpp46";
+ marvell,function = "gpio";
+ };
+ pmx_led_orange: pmx-led_orange {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ };
serial@12000 {
clock-frequency = <200000000>;
status = "ok";
@@ -96,4 +152,21 @@
gpios = <&gpio1 9 0>;
};
};
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_power: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "USB Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 29 0>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
index 66794ed75ff1..71902da33d63 100644
--- a/arch/arm/boot/dts/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
@@ -16,6 +17,39 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_nand
+ &pmx_led_os_red &pmx_power_off
+ &pmx_led_os_green &pmx_led_usb_transfer
+ &pmx_button_reset &pmx_button_usb_copy >;
+ pinctrl-names = "default";
+
+ pmx_led_os_red: pmx-led-os-red {
+ marvell,pins = "mpp22";
+ marvell,function = "gpio";
+ };
+ pmx_power_off: pmx-power-off {
+ marvell,pins = "mpp24";
+ marvell,function = "gpio";
+ };
+ pmx_led_os_green: pmx-led-os-green {
+ marvell,pins = "mpp25";
+ marvell,function = "gpio";
+ };
+ pmx_led_usb_transfer: pmx-led-usb-transfer {
+ marvell,pins = "mpp27";
+ marvell,function = "gpio";
+ };
+ pmx_button_reset: pmx-button-reset {
+ marvell,pins = "mpp28";
+ marvell,function = "gpio";
+ };
+ pmx_button_usb_copy: pmx-button-usb-copy {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+ };
serial@12000 {
clock-frequency = <200000000>;
status = "okay";
@@ -79,4 +113,10 @@
gpios = <&gpio0 27 0>;
};
};
+ gpio_poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio0 24 0>;
+ };
+
+
};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index d97cd9d4753e..504f16be8b54 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "Iomega Iconnect";
@@ -18,6 +19,56 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_gpio_12 &pmx_gpio_35
+ &pmx_gpio_41 &pmx_gpio_42
+ &pmx_gpio_43 &pmx_gpio_44
+ &pmx_gpio_45 &pmx_gpio_46
+ &pmx_gpio_47 &pmx_gpio_48 >;
+ pinctrl-names = "default";
+
+ pmx_gpio_12: pmx-gpio-12 {
+ marvell,pins = "mpp12";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_35: pmx-gpio-35 {
+ marvell,pins = "mpp35";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_41: pmx-gpio-41 {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_42: pmx-gpio-42 {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_43: pmx-gpio-43 {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_44: pmx-gpio-44 {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_45: pmx-gpio-45 {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_46: pmx-gpio-46 {
+ marvell,pins = "mpp46";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_47: pmx-gpio-47 {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ pmx_gpio_48: pmx-gpio-48 {
+ marvell,pins = "mpp48";
+ marvell,function = "gpio";
+ };
+ };
i2c@11000 {
status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
index 865aeec40a26..6cae4599c4b3 100644
--- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "Iomega StorCenter ix2-200";
@@ -16,6 +17,94 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_button_reset &pmx_button_power
+ &pmx_led_backup &pmx_led_power
+ &pmx_button_otb &pmx_led_rebuild
+ &pmx_led_health
+ &pmx_led_sata_brt_ctrl_1
+ &pmx_led_sata_brt_ctrl_2
+ &pmx_led_backup_brt_ctrl_1
+ &pmx_led_backup_brt_ctrl_2
+ &pmx_led_power_brt_ctrl_1
+ &pmx_led_power_brt_ctrl_2
+ &pmx_led_health_brt_ctrl_1
+ &pmx_led_health_brt_ctrl_2
+ &pmx_led_rebuild_brt_ctrl_1
+ &pmx_led_rebuild_brt_ctrl_2 >;
+ pinctrl-names = "default";
+
+ pmx_button_reset: pmx-button-reset {
+ marvell,pins = "mpp12";
+ marvell,function = "gpio";
+ };
+ pmx_button_power: pmx-button-power {
+ marvell,pins = "mpp14";
+ marvell,function = "gpio";
+ };
+ pmx_led_backup: pmx-led-backup {
+ marvell,pins = "mpp15";
+ marvell,function = "gpio";
+ };
+ pmx_led_power: pmx-led-power {
+ marvell,pins = "mpp16";
+ marvell,function = "gpio";
+ };
+ pmx_button_otb: pmx-button-otb {
+ marvell,pins = "mpp35";
+ marvell,function = "gpio";
+ };
+ pmx_led_rebuild: pmx-led-rebuild {
+ marvell,pins = "mpp36";
+ marvell,function = "gpio";
+ };
+ pmx_led_health: pmx-led_health {
+ marvell,pins = "mpp37";
+ marvell,function = "gpio";
+ };
+ pmx_led_sata_brt_ctrl_1: pmx-led-sata-brt-ctrl-1 {
+ marvell,pins = "mpp38";
+ marvell,function = "gpio";
+ };
+ pmx_led_sata_brt_ctrl_2: pmx-led-sata-brt-ctrl-2 {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+ pmx_led_backup_brt_ctrl_1: pmx-led-backup-brt-ctrl-1 {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+ pmx_led_backup_brt_ctrl_2: pmx-led-backup-brt-ctrl-2 {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ pmx_led_power_brt_ctrl_1: pmx-led-power-brt-ctrl-1 {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+ pmx_led_power_brt_ctrl_2: pmx-led-power-brt-ctrl-2 {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_led_health_brt_ctrl_1: pmx-led-health-brt-ctrl-1 {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ pmx_led_health_brt_ctrl_2: pmx-led-health-brt-ctrl-2 {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+ pmx_led_rebuild_brt_ctrl_1: pmx-led-rebuild-brt-ctrl-1 {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ pmx_led_rebuild_brt_ctrl_2: pmx-led-rebuild-brt-ctrl-2 {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+
+ };
i2c@11000 {
status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
index 75bdb93fed26..8db3123ac80f 100644
--- a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
+++ b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-98dx4122.dtsi"
/ {
model = "Keymile Kirkwood Reference Design";
@@ -16,6 +17,22 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_nand &pmx_i2c_gpio_sda
+ &pmx_i2c_gpio_scl >;
+ pinctrl-names = "default";
+
+ pmx_i2c_gpio_sda: pmx-gpio-sda {
+ marvell,pins = "mpp8";
+ marvell,function = "gpio";
+ };
+ pmx_i2c_gpio_scl: pmx-gpio-scl {
+ marvell,pins = "mpp9";
+ marvell,function = "gpio";
+ };
+ };
+
serial@12000 {
clock-frequency = <200000000>;
status = "ok";
diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
index 798e60eeedf3..37d45c4f88fb 100644
--- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi
+++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
@@ -1,4 +1,5 @@
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
chosen {
@@ -6,6 +7,71 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_power_hdd &pmx_usb_vbus
+ &pmx_fan_low &pmx_fan_high
+ &pmx_led_function_red &pmx_led_alarm
+ &pmx_led_info &pmx_led_power
+ &pmx_fan_lock &pmx_button_function
+ &pmx_power_switch &pmx_power_auto_switch
+ &pmx_led_function_blue >;
+ pinctrl-names = "default";
+
+ pmx_power_hdd: pmx-power-hdd {
+ marvell,pins = "mpp10";
+ marvell,function = "gpo";
+ };
+ pmx_usb_vbus: pmx-usb-vbus {
+ marvell,pins = "mpp11";
+ marvell,function = "gpio";
+ };
+ pmx_fan_high: pmx-fan-high {
+ marvell,pins = "mpp18";
+ marvell,function = "gpo";
+ };
+ pmx_fan_low: pmx-fan-low {
+ marvell,pins = "mpp19";
+ marvell,function = "gpo";
+ };
+ pmx_led_function_blue: pmx-led-function-blue {
+ marvell,pins = "mpp36";
+ marvell,function = "gpio";
+ };
+ pmx_led_alarm: pmx-led-alarm {
+ marvell,pins = "mpp37";
+ marvell,function = "gpio";
+ };
+ pmx_led_info: pmx-led-info {
+ marvell,pins = "mpp38";
+ marvell,function = "gpio";
+ };
+ pmx_led_power: pmx-led-power {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+ pmx_fan_lock: pmx-fan-lock {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+ pmx_button_function: pmx-button-function {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ pmx_power_switch: pmx-power-switch {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+ pmx_power_auto_switch: pmx-power-auto-switch {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_led_function_red: pmx-led-function_red {
+ marvell,pins = "mpp48";
+ marvell,function = "gpio";
+ };
+
+ };
sata@80000 {
status = "okay";
nr-ports = <1>;
@@ -105,4 +171,33 @@
5000 0>;
alarm-gpios = <&gpio1 8 0>;
};
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_power: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "USB Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 11 0>;
+ };
+ hdd_power: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "HDD Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 10 0>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts
index ac3c080bed21..262c65403760 100644
--- a/arch/arm/boot/dts/kirkwood-mplcec4.dts
+++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
model = "MPL CEC4";
@@ -16,6 +17,64 @@
};
ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_nand &pmx_uart0
+ &pmx_led_health &pmx_sdio
+ &pmx_sata0 &pmx_sata1
+ &pmx_led_user1o
+ &pmx_led_user1g &pmx_led_user0o
+ &pmx_led_user0g &pmx_led_misc
+ &pmx_sdio_cd
+ >;
+ pinctrl-names = "default";
+
+ pmx_led_health: pmx-led-health {
+ marvell,pins = "mpp7";
+ marvell,function = "gpo";
+ };
+
+ pmx_sata1: pmx-sata1 {
+ marvell,pins = "mpp34";
+ marvell,function = "sata1";
+ };
+
+ pmx_sata0: pmx-sata0 {
+ marvell,pins = "mpp35";
+ marvell,function = "sata0";
+ };
+
+ pmx_led_user1o: pmx-led-user1o {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+
+ pmx_led_user1g: pmx-led-user1g {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+
+ pmx_led_user0o: pmx-led-user0o {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+
+ pmx_led_user0g: pmx-led-user0g {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+
+ pmx_led_misc: pmx-led-misc {
+ marvell,pins = "mpp46";
+ marvell,function = "gpio";
+ };
+
+ pmx_sdio_cd: pmx-sdio-cd {
+ marvell,pins = "mpp47";
+ marvell,function = "gpio";
+ };
+ };
+
i2c@11000 {
status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
index 9a2606c8b78f..49d3d74d4d38 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -1,6 +1,7 @@
/dts-v1/;
/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6282.dtsi"
/ {
model = "Plat'Home OpenBlocksA6";
@@ -29,11 +30,69 @@
nand@3000000 {
chip-delay = <25>;
status = "okay";
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x0 0x90000>;
+ };
+
+ partition@90000 {
+ label = "env";
+ reg = <0x90000 0x44000>;
+ };
+
+ partition@d4000 {
+ label = "test";
+ reg = <0xd4000 0x24000>;
+ };
+
+ partition@f4000 {
+ label = "conf";
+ reg = <0xf4000 0x400000>;
+ };
+
+ partition@4f4000 {
+ label = "linux";
+ reg = <0x4f4000 0x1d20000>;
+ };
+
+ partition@2214000 {
+ label = "user";
+ reg = <0x2214000 0x1dec000>;
+ };
};
sata@80000 {
nr-ports = <1>;
status = "okay";
};
+
+ i2c@11100 {
+ status = "okay";
+
+ s35390a: s35390a@30 {
+ compatible = "s35390a";
+ reg = <0x30>;
+ };
+ };
};
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ led-red {
+ label = "obsa6:red:stat";
+ gpios = <&gpio1 9 1>;
+ };
+
+ led-green {
+ label = "obsa6:green:stat";
+ gpios = <&gpio1 10 1>;
+ };
+
+ led-yellow {
+ label = "obsa6:yellow:stat";
+ gpios = <&gpio1 11 1>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
index ccbf32757800..8295c833887f 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6281.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
@@ -1,8 +1,39 @@
/dts-v1/;
/include/ "kirkwood-ts219.dtsi"
+/include/ "kirkwood-6281.dtsi"
/ {
+ ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_uart0 &pmx_uart1 &pmx_spi
+ &pmx_twsi0 &pmx_sata0 &pmx_sata1
+ &pmx_ram_size &pmx_reset_button
+ &pmx_USB_copy_button &pmx_board_id>;
+ pinctrl-names = "default";
+
+ pmx_ram_size: pmx-ram-size {
+ /* RAM: 0: 256 MB, 1: 512 MB */
+ marvell,pins = "mpp36";
+ marvell,function = "gpio";
+ };
+ pmx_USB_copy_button: pmx-USB-copy-button {
+ marvell,pins = "mpp15";
+ marvell,function = "gpio";
+ };
+ pmx_reset_button: pmx-reset-button {
+ marvell,pins = "mpp16";
+ marvell,function = "gpio";
+ };
+ pmx_board_id: pmx-board-id {
+ /* 0: TS-11x, 1: TS-21x */
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ };
+ };
+
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
index fbe9932161a1..df3f95dfba33 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
@@ -1,8 +1,39 @@
/dts-v1/;
/include/ "kirkwood-ts219.dtsi"
+/include/ "kirkwood-6282.dtsi"
/ {
+ ocp@f1000000 {
+ pinctrl: pinctrl@10000 {
+
+ pinctrl-0 = < &pmx_uart0 &pmx_uart1 &pmx_spi
+ &pmx_twsi0 &pmx_sata0 &pmx_sata1
+ &pmx_ram_size &pmx_reset_button
+ &pmx_USB_copy_button &pmx_board_id>;
+ pinctrl-names = "default";
+
+ pmx_ram_size: pmx-ram-size {
+ /* RAM: 0: 256 MB, 1: 512 MB */
+ marvell,pins = "mpp36";
+ marvell,function = "gpio";
+ };
+ pmx_reset_button: pmx-reset-button {
+ marvell,pins = "mpp37";
+ marvell,function = "gpio";
+ };
+ pmx_USB_copy_button: pmx-USB-copy-button {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ pmx_board_id: pmx-board-id {
+ /* 0: TS-11x, 1: TS-21x */
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+ };
+ };
+
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 4e5b8154a5be..a990c30f0a26 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -4,6 +4,10 @@
compatible = "marvell,kirkwood";
interrupt-parent = <&intc>;
+ aliases {
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ };
intc: interrupt-controller {
compatible = "marvell,orion-intc", "marvell,intc";
interrupt-controller;
@@ -24,7 +28,8 @@
#gpio-cells = <2>;
gpio-controller;
reg = <0x10100 0x40>;
- ngpio = <32>;
+ ngpios = <32>;
+ interrupt-controller;
interrupts = <35>, <36>, <37>, <38>;
};
@@ -33,7 +38,8 @@
#gpio-cells = <2>;
gpio-controller;
reg = <0x10140 0x40>;
- ngpio = <18>;
+ ngpios = <18>;
+ interrupt-controller;
interrupts = <39>, <40>, <41>;
};
@@ -77,6 +83,13 @@
status = "okay";
};
+ ehci@50000 {
+ compatible = "marvell,orion-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <19>;
+ status = "okay";
+ };
+
sata@80000 {
compatible = "marvell,orion-sata";
reg = <0x80000 0x5000>;
diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi
index e5ffe960dbf3..1582f484a867 100644
--- a/arch/arm/boot/dts/lpc32xx.dtsi
+++ b/arch/arm/boot/dts/lpc32xx.dtsi
@@ -182,6 +182,13 @@
pnx,timeout = <0x64>;
};
+ mpwm: mpwm@400E8000 {
+ compatible = "nxp,lpc3220-motor-pwm";
+ reg = <0x400E8000 0x78>;
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
i2cusb: i2c@31020300 {
compatible = "nxp,pnx-i2c";
reg = <0x31020300 0x100>;
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index c6f85f0bc531..27f31a5fa494 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -14,7 +14,7 @@
/ {
model = "Calao Systems Snowball platform with device tree";
- compatible = "calaosystems,snowball-a9500";
+ compatible = "calaosystems,snowball-a9500", "st-ericsson,u9500";
memory {
reg = <0x00000000 0x20000000>;
@@ -147,10 +147,10 @@
};
// External Micro SD slot
- sdi@80126000 {
+ sdi0_per1@80126000 {
arm,primecell-periphid = <0x10480180>;
max-frequency = <50000000>;
- bus-width = <8>;
+ bus-width = <4>;
mmc-cap-mmc-highspeed;
vmmc-supply = <&ab8500_ldo_aux3_reg>;
@@ -161,7 +161,7 @@
};
// On-board eMMC
- sdi@80114000 {
+ sdi4_per2@80114000 {
arm,primecell-periphid = <0x10480180>;
max-frequency = <50000000>;
bus-width = <8>;
@@ -214,5 +214,137 @@
cpufreq-cooling {
status = "okay";
};
+
+ prcmu@80157000 {
+ db8500-prcmu-regulators {
+ db8500_vape_reg: db8500_vape {
+ regulator-name = "db8500-vape";
+ };
+
+ db8500_varm_reg: db8500_varm {
+ regulator-name = "db8500-varm";
+ };
+
+ db8500_vmodem_reg: db8500_vmodem {
+ regulator-name = "db8500-vmodem";
+ };
+
+ db8500_vpll_reg: db8500_vpll {
+ regulator-name = "db8500-vpll";
+ };
+
+ db8500_vsmps1_reg: db8500_vsmps1 {
+ regulator-name = "db8500-vsmps1";
+ };
+
+ db8500_vsmps2_reg: db8500_vsmps2 {
+ regulator-name = "db8500-vsmps2";
+ };
+
+ db8500_vsmps3_reg: db8500_vsmps3 {
+ regulator-name = "db8500-vsmps3";
+ };
+
+ db8500_vrf1_reg: db8500_vrf1 {
+ regulator-name = "db8500-vrf1";
+ };
+
+ db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+ regulator-name = "db8500-sva-mmdsp";
+ };
+
+ db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+ regulator-name = "db8500-sva-mmdsp-ret";
+ };
+
+ db8500_sva_pipe_reg: db8500_sva_pipe {
+ regulator-name = "db8500_sva_pipe";
+ };
+
+ db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+ regulator-name = "db8500_sia_mmdsp";
+ };
+
+ db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
+ regulator-name = "db8500-sia-mmdsp-ret";
+ };
+
+ db8500_sia_pipe_reg: db8500_sia_pipe {
+ regulator-name = "db8500-sia-pipe";
+ };
+
+ db8500_sga_reg: db8500_sga {
+ regulator-name = "db8500-sga";
+ };
+
+ db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+ regulator-name = "db8500-b2r2-mcde";
+ };
+
+ db8500_esram12_reg: db8500_esram12 {
+ regulator-name = "db8500-esram12";
+ };
+
+ db8500_esram12_ret_reg: db8500_esram12_ret {
+ regulator-name = "db8500-esram12-ret";
+ };
+
+ db8500_esram34_reg: db8500_esram34 {
+ regulator-name = "db8500-esram34";
+ };
+
+ db8500_esram34_ret_reg: db8500_esram34_ret {
+ regulator-name = "db8500-esram34-ret";
+ };
+ };
+
+ ab8500@5 {
+ ab8500-regulators {
+ ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+ regulator-name = "V-DISPLAY";
+ };
+
+ ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+ regulator-name = "V-eMMC1";
+ };
+
+ ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+ regulator-name = "V-MMC-SD";
+ };
+
+ ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+ regulator-name = "V-INTCORE";
+ };
+
+ ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+ regulator-name = "V-TVOUT";
+ };
+
+ ab8500_ldo_usb_reg: ab8500_ldo_usb {
+ regulator-name = "dummy";
+ };
+
+ ab8500_ldo_audio_reg: ab8500_ldo_audio {
+ regulator-name = "V-AUD";
+ };
+
+ ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+ regulator-name = "V-AMIC1";
+ };
+
+ ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+ regulator-name = "V-AMIC2";
+ };
+
+ ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+ regulator-name = "V-DMIC";
+ };
+
+ ab8500_ldo_ana_reg: ab8500_ldo_ana {
+ regulator-name = "V-CSI/DSI";
+ };
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/stuib.dtsi b/arch/arm/boot/dts/stuib.dtsi
new file mode 100644
index 000000000000..39446a247e79
--- /dev/null
+++ b/arch/arm/boot/dts/stuib.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * 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
+ */
+
+/ {
+ soc-u9500 {
+ i2c@80004000 {
+ stmpe1601: stmpe1601@40 {
+ compatible = "st,stmpe1601";
+ reg = <0x40>;
+ interrupts = <26 0x1>;
+ interrupt-parent = <&gpio6>;
+ interrupt-controller;
+
+ wakeup-source;
+ st,autosleep-timeout = <1024>;
+
+ stmpe_keypad {
+ compatible = "st,stmpe-keypad";
+
+ debounce-interval = <64>;
+ st,scan-count = <8>;
+ st,no-autorepeat;
+
+ linux,keymap = <0x205006b
+ 0x4010074
+ 0x3050072
+ 0x1030004
+ 0x502006a
+ 0x500000a
+ 0x5008b
+ 0x706001c
+ 0x405000b
+ 0x6070003
+ 0x3040067
+ 0x303006c
+ 0x60400e7
+ 0x602009e
+ 0x4020073
+ 0x5050002
+ 0x4030069
+ 0x3020008>;
+ };
+ };
+ };
+
+ i2c@80110000 {
+ bu21013_tp@0x5c {
+ compatible = "rhom,bu21013_tp";
+ reg = <0x5c>;
+ touch-gpio = <&gpio2 20 0x4>;
+ avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+ rhom,touch-max-x = <384>;
+ rhom,touch-max-y = <704>;
+ rhom,flip-y;
+ };
+
+ bu21013_tp@0x5d {
+ compatible = "rhom,bu21013_tp";
+ reg = <0x5d>;
+ touch-gpio = <&gpio2 20 0x4>;
+ avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+ rhom,touch-max-x = <384>;
+ rhom,touch-max-y = <704>;
+ rhom,flip-y;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index 74b8a47adf91..43eb72af8948 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -10,6 +10,18 @@
reg = <0x00000000 0x40000000>;
};
+ host1x {
+ hdmi {
+ status = "okay";
+
+ vdd-supply = <&hdmi_vdd_reg>;
+ pll-supply = <&hdmi_pll_reg>;
+
+ nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+ nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+ };
+ };
+
pinmux {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
@@ -262,9 +274,9 @@
};
};
- i2c@7000c400 {
+ hdmi_ddc: i2c@7000c400 {
status = "okay";
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
};
i2c@7000c500 {
@@ -369,13 +381,13 @@
regulator-max-microvolt = <1800000>;
};
- ldo7 {
+ hdmi_vdd_reg: ldo7 {
regulator-name = "vdd_ldo7,avdd_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
- ldo8 {
+ hdmi_pll_reg: ldo8 {
regulator-name = "vdd_ldo8,avdd_hdmi_pll";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -396,6 +408,11 @@
};
};
};
+
+ temperature-sensor@4c {
+ compatible = "adi,adt7461";
+ reg = <0x4c>;
+ };
};
pmc {
diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
index 331a3ef24d59..289480026fbf 100644
--- a/arch/arm/boot/dts/tegra20-plutux.dts
+++ b/arch/arm/boot/dts/tegra20-plutux.dts
@@ -6,6 +6,12 @@
model = "Avionic Design Plutux board";
compatible = "ad,plutux", "ad,tamonten", "nvidia,tegra20";
+ host1x {
+ hdmi {
+ status = "okay";
+ };
+ };
+
i2c@7000c000 {
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index e58a0e60f711..420459825b46 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -561,6 +561,12 @@
status = "okay";
};
+ sdhci@c8000000 {
+ status = "okay";
+ power-gpios = <&gpio 86 0>; /* gpio PK6 */
+ bus-width = <4>;
+ };
+
sdhci@c8000400 {
status = "okay";
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 5b3d8b157b33..a239ccdfaa52 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -8,6 +8,16 @@
reg = <0x00000000 0x20000000>;
};
+ host1x {
+ hdmi {
+ vdd-supply = <&hdmi_vdd_reg>;
+ pll-supply = <&hdmi_pll_reg>;
+
+ nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+ nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+ };
+ };
+
pinmux {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
@@ -62,10 +72,6 @@
nvidia,pins = "dap4";
nvidia,function = "dap4";
};
- ddc {
- nvidia,pins = "ddc";
- nvidia,function = "i2c2";
- };
dta {
nvidia,pins = "dta", "dtd";
nvidia,function = "sdio2";
@@ -91,7 +97,7 @@
nvidia,function = "pcie";
};
hdint {
- nvidia,pins = "hdint", "pta";
+ nvidia,pins = "hdint";
nvidia,function = "hdmi";
};
i2cp {
@@ -230,6 +236,39 @@
nvidia,pull = <1>;
};
};
+
+ state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "i2c2";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "rsvd4";
+ };
+ };
+
+ state_i2cmux_pta: pinmux_i2cmux_pta {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "rsvd4";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "i2c2";
+ };
+ };
+
+ state_i2cmux_idle: pinmux_i2cmux_idle {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "rsvd4";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "rsvd4";
+ };
+ };
};
i2s@70002800 {
@@ -246,6 +285,36 @@
status = "okay";
};
+ i2c@7000c400 {
+ clock-frequency = <100000>;
+ status = "okay";
+ };
+
+ i2cmux {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c-parent = <&{/i2c@7000c400}>;
+
+ pinctrl-names = "ddc", "pta", "idle";
+ pinctrl-0 = <&state_i2cmux_ddc>;
+ pinctrl-1 = <&state_i2cmux_pta>;
+ pinctrl-2 = <&state_i2cmux_idle>;
+
+ hdmi_ddc: i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
i2c@7000d000 {
clock-frequency = <400000>;
status = "okay";
@@ -348,13 +417,13 @@
regulator-max-microvolt = <2850000>;
};
- ldo7 {
+ hdmi_vdd_reg: ldo7 {
regulator-name = "vdd_ldo7,avdd_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
- ldo8 {
+ hdmi_pll_reg: ldo8 {
regulator-name = "vdd_ldo8,avdd_hdmi_pll";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -381,6 +450,11 @@
};
};
};
+
+ temperature-sensor@4c {
+ compatible = "onnn,nct1008";
+ reg = <0x4c>;
+ };
};
pmc {
diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
index 9aff31b0fe4a..402b21004bef 100644
--- a/arch/arm/boot/dts/tegra20-tec.dts
+++ b/arch/arm/boot/dts/tegra20-tec.dts
@@ -6,10 +6,13 @@
model = "Avionic Design Tamonten Evaluation Carrier";
compatible = "ad,tec", "ad,tamonten", "nvidia,tegra20";
- i2c@7000c000 {
- clock-frequency = <400000>;
- status = "okay";
+ host1x {
+ hdmi {
+ status = "okay";
+ };
+ };
+ i2c@7000c000 {
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 27fb8a67ea42..b70b4cb754c8 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -10,6 +10,18 @@
reg = <0x00000000 0x40000000>;
};
+ host1x {
+ hdmi {
+ status = "okay";
+
+ vdd-supply = <&hdmi_vdd_reg>;
+ pll-supply = <&hdmi_pll_reg>;
+
+ nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+ nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+ };
+ };
+
pinmux {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
@@ -249,14 +261,24 @@
clock-frequency = <216000000>;
};
- i2c@7000c000 {
+ dvi_ddc: i2c@7000c000 {
status = "okay";
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
};
- i2c@7000c400 {
+ spi@7000c380 {
status = "okay";
- clock-frequency = <400000>;
+ spi-max-frequency = <48000000>;
+ spi-flash@0 {
+ compatible = "winbond,w25q80bl";
+ reg = <0>;
+ spi-max-frequency = <48000000>;
+ };
+ };
+
+ hdmi_ddc: i2c@7000c400 {
+ status = "okay";
+ clock-frequency = <100000>;
};
i2c@7000c500 {
@@ -300,6 +322,30 @@
bus-width = <4>;
};
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_vdd_reg: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "avdd_hdmi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ hdmi_pll_reg: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "avdd_hdmi_pll";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
+
sound {
compatible = "nvidia,tegra-audio-trimslice";
nvidia,i2s-controller = <&tegra_i2s1>;
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index 86854f1abd58..adc47547eaae 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -64,11 +64,6 @@
nvidia,pins = "dap4";
nvidia,function = "dap4";
};
- ddc {
- nvidia,pins = "ddc", "owc", "spdi", "spdo",
- "uac";
- nvidia,function = "rsvd2";
- };
dta {
nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
nvidia,function = "vi";
@@ -98,7 +93,7 @@
nvidia,function = "pcie";
};
hdint {
- nvidia,pins = "hdint", "pta";
+ nvidia,pins = "hdint";
nvidia,function = "hdmi";
};
i2cp {
@@ -129,6 +124,10 @@
"lspi", "lvp1", "lvs";
nvidia,function = "displaya";
};
+ owc {
+ nvidia,pins = "owc", "spdi", "spdo", "uac";
+ nvidia,function = "rsvd2";
+ };
pmc {
nvidia,pins = "pmc";
nvidia,function = "pwr_on";
@@ -237,6 +236,49 @@
"ld23_22";
nvidia,pull = <1>;
};
+ drive_sdio1 {
+ nvidia,pins = "drive_sdio1";
+ nvidia,high-speed-mode = <0>;
+ nvidia,schmitt = <1>;
+ nvidia,low-power-mode = <3>;
+ nvidia,pull-down-strength = <31>;
+ nvidia,pull-up-strength = <31>;
+ nvidia,slew-rate-rising = <3>;
+ nvidia,slew-rate-falling = <3>;
+ };
+ };
+
+ state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "i2c2";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "rsvd4";
+ };
+ };
+
+ state_i2cmux_pta: pinmux_i2cmux_pta {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "rsvd4";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "i2c2";
+ };
+ };
+
+ state_i2cmux_idle: pinmux_i2cmux_idle {
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "rsvd4";
+ };
+ pta {
+ nvidia,pins = "pta";
+ nvidia,function = "rsvd4";
+ };
};
};
@@ -281,6 +323,31 @@
clock-frequency = <400000>;
};
+ i2cmux {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c-parent = <&{/i2c@7000c400}>;
+
+ pinctrl-names = "ddc", "pta", "idle";
+ pinctrl-0 = <&state_i2cmux_ddc>;
+ pinctrl-1 = <&state_i2cmux_pta>;
+ pinctrl-2 = <&state_i2cmux_idle>;
+
+ i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
i2c@7000c500 {
status = "okay";
clock-frequency = <400000>;
@@ -406,6 +473,11 @@
};
};
};
+
+ temperature-sensor@4c {
+ compatible = "onnn,nct1008";
+ reg = <0x4c>;
+ };
};
pmc {
@@ -425,6 +497,12 @@
status = "okay";
};
+ sdhci@c8000000 {
+ status = "okay";
+ power-gpios = <&gpio 86 0>; /* gpio PK6 */
+ bus-width = <4>;
+ };
+
sdhci@c8000400 {
status = "okay";
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index 94a71c91beb5..20d576ecd555 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -10,6 +10,18 @@
reg = <0x00000000 0x20000000>;
};
+ host1x {
+ hdmi {
+ status = "okay";
+
+ vdd-supply = <&hdmi_vdd_reg>;
+ pll-supply = <&hdmi_pll_reg>;
+
+ nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+ nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+ };
+ };
+
pinmux {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
@@ -246,6 +258,11 @@
clock-frequency = <216000000>;
};
+ hdmi_ddc: i2c@7000c400 {
+ status = "okay";
+ clock-frequency = <100000>;
+ };
+
i2c@7000d000 {
status = "okay";
clock-frequency = <100000>;
@@ -356,7 +373,7 @@
regulator-always-on;
};
- ldo6 {
+ hdmi_pll_reg: ldo6 {
regulator-name = "nvvdd_ldo6,avdd_hdmi_pll";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -388,7 +405,7 @@
regulator-always-on;
};
- ldo11 {
+ hdmi_vdd_reg: ldo11 {
regulator-name = "nvvdd_ldo11,vddio_pex_clk,vcom_33,avdd_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index f40cfbaa7c7e..b8effa1cbda7 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -4,6 +4,99 @@
compatible = "nvidia,tegra20";
interrupt-parent = <&intc>;
+ host1x {
+ compatible = "nvidia,tegra20-host1x", "simple-bus";
+ reg = <0x50000000 0x00024000>;
+ interrupts = <0 65 0x04 /* mpcore syncpt */
+ 0 67 0x04>; /* mpcore general */
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0x54000000 0x54000000 0x04000000>;
+
+ mpe {
+ compatible = "nvidia,tegra20-mpe";
+ reg = <0x54040000 0x00040000>;
+ interrupts = <0 68 0x04>;
+ };
+
+ vi {
+ compatible = "nvidia,tegra20-vi";
+ reg = <0x54080000 0x00040000>;
+ interrupts = <0 69 0x04>;
+ };
+
+ epp {
+ compatible = "nvidia,tegra20-epp";
+ reg = <0x540c0000 0x00040000>;
+ interrupts = <0 70 0x04>;
+ };
+
+ isp {
+ compatible = "nvidia,tegra20-isp";
+ reg = <0x54100000 0x00040000>;
+ interrupts = <0 71 0x04>;
+ };
+
+ gr2d {
+ compatible = "nvidia,tegra20-gr2d";
+ reg = <0x54140000 0x00040000>;
+ interrupts = <0 72 0x04>;
+ };
+
+ gr3d {
+ compatible = "nvidia,tegra20-gr3d";
+ reg = <0x54180000 0x00040000>;
+ };
+
+ dc@54200000 {
+ compatible = "nvidia,tegra20-dc";
+ reg = <0x54200000 0x00040000>;
+ interrupts = <0 73 0x04>;
+
+ rgb {
+ status = "disabled";
+ };
+ };
+
+ dc@54240000 {
+ compatible = "nvidia,tegra20-dc";
+ reg = <0x54240000 0x00040000>;
+ interrupts = <0 74 0x04>;
+
+ rgb {
+ status = "disabled";
+ };
+ };
+
+ hdmi {
+ compatible = "nvidia,tegra20-hdmi";
+ reg = <0x54280000 0x00040000>;
+ interrupts = <0 75 0x04>;
+ status = "disabled";
+ };
+
+ tvo {
+ compatible = "nvidia,tegra20-tvo";
+ reg = <0x542c0000 0x00040000>;
+ interrupts = <0 76 0x04>;
+ status = "disabled";
+ };
+
+ dsi {
+ compatible = "nvidia,tegra20-dsi";
+ reg = <0x54300000 0x00040000>;
+ status = "disabled";
+ };
+ };
+
+ timer@50004600 {
+ compatible = "arm,cortex-a9-twd-timer";
+ reg = <0x50040600 0x20>;
+ interrupts = <1 13 0x304>;
+ };
+
cache-controller@50043000 {
compatible = "arm,pl310-cache";
reg = <0x50043000 0x1000>;
@@ -21,6 +114,15 @@
#interrupt-cells = <3>;
};
+ timer@60005000 {
+ compatible = "nvidia,tegra20-timer";
+ reg = <0x60005000 0x60>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04>;
+ };
+
apbdma: dma {
compatible = "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1200>;
@@ -138,6 +240,12 @@
#pwm-cells = <2>;
};
+ rtc {
+ compatible = "nvidia,tegra20-rtc";
+ reg = <0x7000e000 0x100>;
+ interrupts = <0 2 0x04>;
+ };
+
i2c@7000c000 {
compatible = "nvidia,tegra20-i2c";
reg = <0x7000c000 0x100>;
@@ -147,6 +255,16 @@
status = "disabled";
};
+ spi@7000c380 {
+ compatible = "nvidia,tegra20-sflash";
+ reg = <0x7000c380 0x80>;
+ interrupts = <0 39 0x04>;
+ nvidia,dma-request-selector = <&apbdma 11>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c@7000c400 {
compatible = "nvidia,tegra20-i2c";
reg = <0x7000c400 0x100>;
@@ -174,6 +292,46 @@
status = "disabled";
};
+ spi@7000d400 {
+ compatible = "nvidia,tegra20-slink";
+ reg = <0x7000d400 0x200>;
+ interrupts = <0 59 0x04>;
+ nvidia,dma-request-selector = <&apbdma 15>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000d600 {
+ compatible = "nvidia,tegra20-slink";
+ reg = <0x7000d600 0x200>;
+ interrupts = <0 82 0x04>;
+ nvidia,dma-request-selector = <&apbdma 16>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000d800 {
+ compatible = "nvidia,tegra20-slink";
+ reg = <0x7000d480 0x200>;
+ interrupts = <0 83 0x04>;
+ nvidia,dma-request-selector = <&apbdma 17>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000da00 {
+ compatible = "nvidia,tegra20-slink";
+ reg = <0x7000da00 0x200>;
+ interrupts = <0 93 0x04>;
+ nvidia,dma-request-selector = <&apbdma 18>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
pmc {
compatible = "nvidia,tegra20-pmc";
reg = <0x7000e400 0x400>;
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
index dd4222f00eca..adc88aa50eb6 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a02.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
@@ -83,5 +83,11 @@
gpio = <&gpio 83 0>; /* GPIO PK3 */
};
};
+
+ sdhci@78000400 {
+ status = "okay";
+ power-gpios = <&gpio 28 0>; /* gpio PD4 */
+ bus-width = <4>;
+ };
};
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
index 0828f097ca86..08163e145d57 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a04.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
@@ -95,4 +95,10 @@
gpio = <&gpio 232 0>; /* GPIO PDD0 */
};
};
+
+ sdhci@78000400 {
+ status = "okay";
+ power-gpios = <&gpio 27 0>; /* gpio PD3 */
+ bus-width = <4>;
+ };
};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index b1271a894327..bdb2a660f376 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -52,6 +52,22 @@
nvidia,pull = <2>;
nvidia,tristate = <0>;
};
+ sdmmc3_clk_pa6 {
+ nvidia,pins = "sdmmc3_clk_pa6";
+ nvidia,function = "sdmmc3";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ sdmmc3_cmd_pa7 {
+ nvidia,pins = "sdmmc3_cmd_pa7",
+ "sdmmc3_dat0_pb7",
+ "sdmmc3_dat1_pb6",
+ "sdmmc3_dat2_pb5",
+ "sdmmc3_dat3_pb4";
+ nvidia,function = "sdmmc3";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
sdmmc4_clk_pcc4 {
nvidia,pins = "sdmmc4_clk_pcc4",
"sdmmc4_rst_n_pcc3";
@@ -81,6 +97,15 @@
nvidia,pull = <0>;
nvidia,tristate = <0>;
};
+ sdio3 {
+ nvidia,pins = "drive_sdio3";
+ nvidia,high-speed-mode = <0>;
+ nvidia,schmitt = <0>;
+ nvidia,pull-down-strength = <46>;
+ nvidia,pull-up-strength = <42>;
+ nvidia,slew-rate-rising = <1>;
+ nvidia,slew-rate-falling = <1>;
+ };
};
};
@@ -250,6 +275,16 @@
};
};
+ spi@7000da00 {
+ status = "okay";
+ spi-max-frequency = <25000000>;
+ spi-flash@1 {
+ compatible = "winbond,w25q32";
+ reg = <1>;
+ spi-max-frequency = <20000000>;
+ };
+ };
+
ahub {
i2s@70080400 {
status = "okay";
@@ -384,6 +419,8 @@
regulator-name = "vdd_com";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
enable-active-high;
gpio = <&gpio 24 0>; /* gpio PD0 */
vin-supply = <&sys_3v3_reg>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index fed8dca1692d..529fdb82dfdb 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -4,6 +4,99 @@
compatible = "nvidia,tegra30";
interrupt-parent = <&intc>;
+ host1x {
+ compatible = "nvidia,tegra30-host1x", "simple-bus";
+ reg = <0x50000000 0x00024000>;
+ interrupts = <0 65 0x04 /* mpcore syncpt */
+ 0 67 0x04>; /* mpcore general */
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0x54000000 0x54000000 0x04000000>;
+
+ mpe {
+ compatible = "nvidia,tegra30-mpe";
+ reg = <0x54040000 0x00040000>;
+ interrupts = <0 68 0x04>;
+ };
+
+ vi {
+ compatible = "nvidia,tegra30-vi";
+ reg = <0x54080000 0x00040000>;
+ interrupts = <0 69 0x04>;
+ };
+
+ epp {
+ compatible = "nvidia,tegra30-epp";
+ reg = <0x540c0000 0x00040000>;
+ interrupts = <0 70 0x04>;
+ };
+
+ isp {
+ compatible = "nvidia,tegra30-isp";
+ reg = <0x54100000 0x00040000>;
+ interrupts = <0 71 0x04>;
+ };
+
+ gr2d {
+ compatible = "nvidia,tegra30-gr2d";
+ reg = <0x54140000 0x00040000>;
+ interrupts = <0 72 0x04>;
+ };
+
+ gr3d {
+ compatible = "nvidia,tegra30-gr3d";
+ reg = <0x54180000 0x00040000>;
+ };
+
+ dc@54200000 {
+ compatible = "nvidia,tegra30-dc";
+ reg = <0x54200000 0x00040000>;
+ interrupts = <0 73 0x04>;
+
+ rgb {
+ status = "disabled";
+ };
+ };
+
+ dc@54240000 {
+ compatible = "nvidia,tegra30-dc";
+ reg = <0x54240000 0x00040000>;
+ interrupts = <0 74 0x04>;
+
+ rgb {
+ status = "disabled";
+ };
+ };
+
+ hdmi {
+ compatible = "nvidia,tegra30-hdmi";
+ reg = <0x54280000 0x00040000>;
+ interrupts = <0 75 0x04>;
+ status = "disabled";
+ };
+
+ tvo {
+ compatible = "nvidia,tegra30-tvo";
+ reg = <0x542c0000 0x00040000>;
+ interrupts = <0 76 0x04>;
+ status = "disabled";
+ };
+
+ dsi {
+ compatible = "nvidia,tegra30-dsi";
+ reg = <0x54300000 0x00040000>;
+ status = "disabled";
+ };
+ };
+
+ timer@50004600 {
+ compatible = "arm,cortex-a9-twd-timer";
+ reg = <0x50040600 0x20>;
+ interrupts = <1 13 0xf04>;
+ };
+
cache-controller@50043000 {
compatible = "arm,pl310-cache";
reg = <0x50043000 0x1000>;
@@ -21,6 +114,17 @@
#interrupt-cells = <3>;
};
+ timer@60005000 {
+ compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+ reg = <0x60005000 0x400>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04
+ 0 121 0x04
+ 0 122 0x04>;
+ };
+
apbdma: dma {
compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1400>;
@@ -132,6 +236,12 @@
#pwm-cells = <2>;
};
+ rtc {
+ compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
+ reg = <0x7000e000 0x100>;
+ interrupts = <0 2 0x04>;
+ };
+
i2c@7000c000 {
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000c000 0x100>;
@@ -177,6 +287,66 @@
status = "disabled";
};
+ spi@7000d400 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000d400 0x200>;
+ interrupts = <0 59 0x04>;
+ nvidia,dma-request-selector = <&apbdma 15>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000d600 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000d600 0x200>;
+ interrupts = <0 82 0x04>;
+ nvidia,dma-request-selector = <&apbdma 16>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000d800 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000d480 0x200>;
+ interrupts = <0 83 0x04>;
+ nvidia,dma-request-selector = <&apbdma 17>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000da00 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000da00 0x200>;
+ interrupts = <0 93 0x04>;
+ nvidia,dma-request-selector = <&apbdma 18>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000dc00 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000dc00 0x200>;
+ interrupts = <0 94 0x04>;
+ nvidia,dma-request-selector = <&apbdma 27>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi@7000de00 {
+ compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+ reg = <0x7000de00 0x200>;
+ interrupts = <0 79 0x04>;
+ nvidia,dma-request-selector = <&apbdma 28>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
pmc {
compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
reg = <0x7000e400 0x400>;
diff --git a/arch/arm/boot/dts/u9540.dts b/arch/arm/boot/dts/u9540.dts
new file mode 100644
index 000000000000..95892ec6c342
--- /dev/null
+++ b/arch/arm/boot/dts/u9540.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * 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/ "dbx5x0.dtsi"
+
+/ {
+ model = "ST-Ericsson U9540 platform with Device Tree";
+ compatible = "st-ericsson,u9540";
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+
+ soc-u9500 {
+ uart@80120000 {
+ status = "okay";
+ };
+
+ uart@80121000 {
+ status = "okay";
+ };
+
+ uart@80007000 {
+ status = "okay";
+ };
+
+ // External Micro SD slot
+ sdi0_per1@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ mmc-cap-sd-highspeed;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+ cd-gpios = <&gpio7 6 0x4>; // 230
+ cd-inverted;
+
+ status = "okay";
+ };
+
+
+ // WLAN SDIO channel
+ sdi1_per2@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+
+ status = "okay";
+ };
+
+ // On-board eMMC
+ sdi4_per2@80114000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <8>;
+ mmc-cap-mmc-highspeed;
+ vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
new file mode 100644
index 000000000000..401c1262d4ed
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "xlnx,zynq-7000";
+
+ amba {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+ ranges;
+
+ intc: interrupt-controller@f8f01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ interrupt-controller;
+ reg = <0xF8F01000 0x1000>,
+ <0xF8F00100 0x100>;
+ };
+
+ L2: cache-controller {
+ compatible = "arm,pl310-cache";
+ reg = <0xF8F02000 0x1000>;
+ arm,data-latency = <2 3 2>;
+ arm,tag-latency = <2 3 2>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ uart0: uart@e0000000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <0 27 4>;
+ clock = <50000000>;
+ };
+
+ uart1: uart@e0001000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0001000 0x1000>;
+ interrupts = <0 50 4>;
+ clock = <50000000>;
+ };
+
+ slcr: slcr@f8000000 {
+ compatible = "xlnx,zynq-slcr";
+ reg = <0xF8000000 0x1000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ps_clk: ps_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* clock-frequency set in board-specific file */
+ clock-output-names = "ps_clk";
+ };
+ armpll: armpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x100 0x110>;
+ clock-output-names = "armpll";
+ };
+ ddrpll: ddrpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x104 0x114>;
+ clock-output-names = "ddrpll";
+ };
+ iopll: iopll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x108 0x118>;
+ clock-output-names = "iopll";
+ };
+ uart_clk: uart_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-periph-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x154>;
+ clock-output-names = "uart0_ref_clk",
+ "uart1_ref_clk";
+ };
+ cpu_clk: cpu_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-cpu-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x120 0x1C4>;
+ clock-output-names = "cpu_6x4x",
+ "cpu_3x2x",
+ "cpu_2x",
+ "cpu_1x";
+ };
+ };
+ };
+
+ ttc0: ttc0@f8001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8001000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc0_0: ttc0.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 10 4>;
+ };
+ ttc0_1: ttc0.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 11 4>;
+ };
+ ttc0_2: ttc0.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 12 4>;
+ };
+ };
+
+ ttc1: ttc1@f8002000 {
+ #interrupt-parent = <&intc>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "xlnx,ttc";
+ reg = <0xF8002000 0x1000>;
+ clocks = <&cpu_clk 3>;
+ clock-names = "cpu_1x";
+ clock-ranges;
+
+ ttc1_0: ttc1.0 {
+ status = "disabled";
+ reg = <0>;
+ interrupts = <0 37 4>;
+ };
+ ttc1_1: ttc1.1 {
+ status = "disabled";
+ reg = <1>;
+ interrupts = <0 38 4>;
+ };
+ ttc1_2: ttc1.2 {
+ status = "disabled";
+ reg = <2>;
+ interrupts = <0 39 4>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
deleted file mode 100644
index 574bc044f572..000000000000
--- a/arch/arm/boot/dts/zynq-ep107.dts
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-/ {
- model = "Xilinx Zynq EP107";
- compatible = "xlnx,zynq-ep107";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
-
- memory {
- device_type = "memory";
- reg = <0x0 0x10000000>;
- };
-
- chosen {
- bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
- linux,stdout-path = &uart0;
- };
-
- amba {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- intc: interrupt-controller@f8f01000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- #address-cells = <1>;
- interrupt-controller;
- reg = <0xF8F01000 0x1000>,
- <0xF8F00100 0x100>;
- };
-
- L2: cache-controller {
- compatible = "arm,pl310-cache";
- reg = <0xF8F02000 0x1000>;
- arm,data-latency = <2 3 2>;
- arm,tag-latency = <2 3 2>;
- cache-unified;
- cache-level = <2>;
- };
-
- uart0: uart@e0000000 {
- compatible = "xlnx,xuartps";
- reg = <0xE0000000 0x1000>;
- interrupts = <0 27 4>;
- clock = <50000000>;
- };
- };
-};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
new file mode 100644
index 000000000000..c772942a399a
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ * Copyright (C) 2012 National Instruments Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+ model = "Zynq ZC702 Development Board";
+ compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS1,115200 earlyprintk";
+ };
+
+};
+
+&ps_clk {
+ clock-frequency = <33333330>;
+};
+
+&ttc0_0 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clocksource";
+};
+
+&ttc0_1 {
+ status = "ok";
+ compatible = "xlnx,ttc-counter-clockevent";
+};
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 5b8215f424c5..728a43c446f8 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -47,6 +47,8 @@ CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_FARADAY is not set
@@ -59,9 +61,8 @@ CONFIG_SMSC911X=y
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
@@ -78,9 +79,16 @@ CONFIG_GPIO_SYSFS=y
CONFIG_THERMAL=y
CONFIG_RCAR_THERMAL=y
CONFIG_SSB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_RCAR_PHY=y
CONFIG_MMC=y
CONFIG_MMC_SDHI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
CONFIG_UIO=y
CONFIG_UIO_PDRV_GENIRQ=y
# CONFIG_IOMMU_SUPPORT is not set
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 048aaca60814..7bf535104e26 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -61,6 +61,8 @@ CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_ENC28J60=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
@@ -158,6 +160,10 @@ CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
CONFIG_PRINTK_TIME=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 62303043db9c..a1dc5c071e71 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -240,3 +240,6 @@ CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_LIBCRC32C=y
CONFIG_SOC_OMAP5=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_TI_CPSW=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 250625d5223f..231dca604737 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -78,6 +78,7 @@ CONFIG_AB8500_CORE=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_AB8500=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB_GADGET=y
CONFIG_AB8500_USB=y
diff --git a/arch/arm/include/debug/imx.S b/arch/arm/include/debug/imx.S
index 0b65d792f664..0c4e17d4d359 100644
--- a/arch/arm/include/debug/imx.S
+++ b/arch/arm/include/debug/imx.S
@@ -10,6 +10,20 @@
* published by the Free Software Foundation.
*
*/
+#define IMX6Q_UART1_BASE_ADDR 0x02020000
+#define IMX6Q_UART2_BASE_ADDR 0x021e8000
+#define IMX6Q_UART3_BASE_ADDR 0x021ec000
+#define IMX6Q_UART4_BASE_ADDR 0x021f0000
+#define IMX6Q_UART5_BASE_ADDR 0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n) IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n) IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
+
#ifdef CONFIG_DEBUG_IMX1_UART
#define UART_PADDR 0x00206000
#elif defined (CONFIG_DEBUG_IMX25_UART)
@@ -22,10 +36,8 @@
#define UART_PADDR 0x73fbc000
#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
#define UART_PADDR 0x53fbc000
-#elif defined (CONFIG_DEBUG_IMX6Q_UART2)
-#define UART_PADDR 0x021e8000
-#elif defined (CONFIG_DEBUG_IMX6Q_UART4)
-#define UART_PADDR 0x021f0000
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR IMX6Q_DEBUG_UART_BASE
#endif
/*
diff --git a/arch/arm/include/debug/tegra.S b/arch/arm/include/debug/tegra.S
new file mode 100644
index 000000000000..883d7c22fd9d
--- /dev/null
+++ b/arch/arm/include/debug/tegra.S
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
+ *
+ * Author:
+ * Colin Cross <ccross@google.com>
+ * Erik Gilling <konkers@google.com>
+ * Doug Anderson <dianders@chromium.org>
+ * Stephen Warren <swarren@nvidia.com>
+ *
+ * Portions based on mach-omap2's debug-macro.S
+ * Copyright (C) 1994-1999 Russell King
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/serial_reg.h>
+
+#define UART_SHIFT 2
+
+/* Physical addresses */
+#define TEGRA_CLK_RESET_BASE 0x60006000
+#define TEGRA_APB_MISC_BASE 0x70000000
+#define TEGRA_UARTA_BASE 0x70006000
+#define TEGRA_UARTB_BASE 0x70006040
+#define TEGRA_UARTC_BASE 0x70006200
+#define TEGRA_UARTD_BASE 0x70006300
+#define TEGRA_UARTE_BASE 0x70006400
+#define TEGRA_PMC_BASE 0x7000e400
+
+#define TEGRA_CLK_RST_DEVICES_L (TEGRA_CLK_RESET_BASE + 0x04)
+#define TEGRA_CLK_RST_DEVICES_H (TEGRA_CLK_RESET_BASE + 0x08)
+#define TEGRA_CLK_RST_DEVICES_U (TEGRA_CLK_RESET_BASE + 0x0c)
+#define TEGRA_CLK_OUT_ENB_L (TEGRA_CLK_RESET_BASE + 0x10)
+#define TEGRA_CLK_OUT_ENB_H (TEGRA_CLK_RESET_BASE + 0x14)
+#define TEGRA_CLK_OUT_ENB_U (TEGRA_CLK_RESET_BASE + 0x18)
+#define TEGRA_PMC_SCRATCH20 (TEGRA_PMC_BASE + 0xa0)
+#define TEGRA_APB_MISC_GP_HIDREV (TEGRA_APB_MISC_BASE + 0x804)
+
+/*
+ * Must be 1MB-aligned since a 1MB mapping is used early on.
+ * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[].
+ */
+#define UART_VIRTUAL_BASE 0xfe100000
+
+#define checkuart(rp, rv, lhu, bit, uart) \
+ /* Load address of CLK_RST register */ \
+ movw rp, #TEGRA_CLK_RST_DEVICES_##lhu & 0xffff ; \
+ movt rp, #TEGRA_CLK_RST_DEVICES_##lhu >> 16 ; \
+ /* Load value from CLK_RST register */ \
+ ldr rp, [rp, #0] ; \
+ /* Test UART's reset bit */ \
+ tst rp, #(1 << bit) ; \
+ /* If set, can't use UART; jump to save no UART */ \
+ bne 90f ; \
+ /* Load address of CLK_OUT_ENB register */ \
+ movw rp, #TEGRA_CLK_OUT_ENB_##lhu & 0xffff ; \
+ movt rp, #TEGRA_CLK_OUT_ENB_##lhu >> 16 ; \
+ /* Load value from CLK_OUT_ENB register */ \
+ ldr rp, [rp, #0] ; \
+ /* Test UART's clock enable bit */ \
+ tst rp, #(1 << bit) ; \
+ /* If clear, can't use UART; jump to save no UART */ \
+ beq 90f ; \
+ /* Passed all tests, load address of UART registers */ \
+ movw rp, #TEGRA_UART##uart##_BASE & 0xffff ; \
+ movt rp, #TEGRA_UART##uart##_BASE >> 16 ; \
+ /* Jump to save UART address */ \
+ b 91f
+
+ .macro addruart, rp, rv, tmp
+ adr \rp, 99f @ actual addr of 99f
+ ldr \rv, [\rp] @ linked addr is stored there
+ sub \rv, \rv, \rp @ offset between the two
+ ldr \rp, [\rp, #4] @ linked tegra_uart_config
+ sub \tmp, \rp, \rv @ actual tegra_uart_config
+ ldr \rp, [\tmp] @ Load tegra_uart_config
+ cmp \rp, #1 @ needs initialization?
+ bne 100f @ no; go load the addresses
+ mov \rv, #0 @ yes; record init is done
+ str \rv, [\tmp]
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
+ /* Check ODMDATA */
+10: movw \rp, #TEGRA_PMC_SCRATCH20 & 0xffff
+ movt \rp, #TEGRA_PMC_SCRATCH20 >> 16
+ ldr \rp, [\rp, #0] @ Load PMC_SCRATCH20
+ ubfx \rv, \rp, #18, #2 @ 19:18 are console type
+ cmp \rv, #2 @ 2 and 3 mean DCC, UART
+ beq 11f @ some boards swap the meaning
+ cmp \rv, #3 @ so accept either
+ bne 90f
+11: ubfx \rv, \rp, #15, #3 @ 17:15 are UART ID
+ cmp \rv, #0 @ UART 0?
+ beq 20f
+ cmp \rv, #1 @ UART 1?
+ beq 21f
+ cmp \rv, #2 @ UART 2?
+ beq 22f
+ cmp \rv, #3 @ UART 3?
+ beq 23f
+ cmp \rv, #4 @ UART 4?
+ beq 24f
+ b 90f @ invalid
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA) || \
+ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ /* Check UART A validity */
+20: checkuart(\rp, \rv, L, 6, A)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTB) || \
+ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ /* Check UART B validity */
+21: checkuart(\rp, \rv, L, 7, B)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTC) || \
+ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ /* Check UART C validity */
+22: checkuart(\rp, \rv, H, 23, C)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTD) || \
+ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ /* Check UART D validity */
+23: checkuart(\rp, \rv, U, 1, D)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTE) || \
+ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ /* Check UART E validity */
+24:
+ checkuart(\rp, \rv, U, 2, E)
+#endif
+
+ /* No valid UART found */
+90: mov \rp, #0
+ /* fall through */
+
+ /* Record whichever UART we chose */
+91: str \rp, [\tmp, #4] @ Store in tegra_uart_phys
+ cmp \rp, #0 @ Valid UART address?
+ bne 92f @ Yes, go process it
+ str \rp, [\tmp, #8] @ Store 0 in tegra_uart_virt
+ b 100f @ Done
+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
+99: .word .
+ .word tegra_uart_config
+ .ltorg
+
+ /* Load previously selected UART address */
+100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
+ ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
+ .endm
+
+/*
+ * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
+ * check to make sure that the UART address is actually valid.
+ */
+
+ .macro senduart, rd, rx
+ cmp \rx, #0
+ strneb \rd, [\rx, #UART_TX << UART_SHIFT]
+1001:
+ .endm
+
+ .macro busyuart, rd, rx
+ 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
+ bne 1001b
+1002:
+ .endm
+
+ .macro waituart, rd, rx
+#ifdef FLOW_CONTROL
+ cmp \rx, #0
+ beq 1002f
+1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
+ tst \rd, #UART_MSR_CTS
+ beq 1001b
+1002:
+#endif
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/include/debug/zynq.S
index 3ab0be1f6191..f9aa9740a73f 100644
--- a/arch/arm/mach-zynq/include/mach/debug-macro.S
+++ b/arch/arm/include/debug/zynq.S
@@ -1,5 +1,4 @@
-/* arch/arm/mach-zynq/include/mach/debug-macro.S
- *
+/*
* Debugging macro include header
*
* Copyright (C) 2011 Xilinx
@@ -13,9 +12,25 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
+#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
+
+#define UART0_PHYS 0xE0000000
+#define UART1_PHYS 0xE0001000
+#define UART_SIZE SZ_4K
+#define UART_VIRT 0xF0001000
+
+#if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1)
+# define LL_UART_PADDR UART1_PHYS
+#else
+# define LL_UART_PADDR UART0_PHYS
+#endif
-#include <mach/zynq_soc.h>
-#include <mach/uart.h>
+#define LL_UART_VADDR UART_VIRT
.macro addruart, rp, rv, tmp
ldr \rp, =LL_UART_PADDR @ physical
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index 1862d8f2fd44..0cd63d080c7b 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -1598,7 +1598,7 @@ static int __init run_all_tests(void)
{
int ret = 0;
- pr_info("Begining kprobe tests...\n");
+ pr_info("Beginning kprobe tests...\n");
#ifndef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index e34c1bdb804d..958358c91afd 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -39,7 +39,6 @@ config SOC_AT91RM9200
config SOC_AT91SAM9260
bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
select HAVE_AT91_DBGU0
- select HAVE_NET_MACB
select SOC_AT91SAM9
help
Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -57,7 +56,6 @@ config SOC_AT91SAM9263
bool "AT91SAM9263"
select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
- select HAVE_NET_MACB
select SOC_AT91SAM9
config SOC_AT91SAM9RL
@@ -70,7 +68,6 @@ config SOC_AT91SAM9G45
bool "AT91SAM9G45 or AT91SAM9M10 families"
select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
- select HAVE_NET_MACB
select SOC_AT91SAM9
help
Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
@@ -80,7 +77,6 @@ config SOC_AT91SAM9X5
bool "AT91SAM9x5 family"
select HAVE_AT91_DBGU0
select HAVE_FB_ATMEL
- select HAVE_NET_MACB
select SOC_AT91SAM9
help
Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 8ce068240c69..7aeb473ee539 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -184,9 +184,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 2a1f8e67683d..3ebc9792560c 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -752,7 +752,7 @@ static struct resource ssc0_resources[] = {
};
static struct platform_device at91rm9200_ssc0_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc0_dmamask,
@@ -794,7 +794,7 @@ static struct resource ssc1_resources[] = {
};
static struct platform_device at91rm9200_ssc1_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 1,
.dev = {
.dma_mask = &ssc1_dmamask,
@@ -836,7 +836,7 @@ static struct resource ssc2_resources[] = {
};
static struct platform_device at91rm9200_ssc2_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 2,
.dev = {
.dma_mask = &ssc2_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index c65e7b8d7a81..b67cd5374117 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -210,7 +210,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
/* more usart lookup table for DT entries */
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 1f6fac21b2c8..eda8d1679d40 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -742,7 +742,7 @@ static struct resource ssc_resources[] = {
};
static struct platform_device at91sam9260_ssc_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 9d3e9b8b9926..2998a08afc2d 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -174,9 +174,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 6ce6d27e2442..92e0f861084a 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -706,7 +706,7 @@ static struct resource ssc0_resources[] = {
};
static struct platform_device at91sam9261_ssc0_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc0_dmamask,
@@ -748,7 +748,7 @@ static struct resource ssc1_resources[] = {
};
static struct platform_device at91sam9261_ssc1_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 1,
.dev = {
.dma_mask = &ssc1_dmamask,
@@ -790,7 +790,7 @@ static struct resource ssc2_resources[] = {
};
static struct platform_device at91sam9261_ssc2_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 2,
.dev = {
.dma_mask = &ssc2_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 82deb4d748b2..b9fc60d1b33a 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -186,8 +186,10 @@ static struct clk *periph_clocks[] __initdata = {
static struct clk_lookup periph_clocks_lookups[] = {
/* One additional fake clock for macb_hclk */
CLKDEV_CON_ID("hclk", &macb_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index fb98163b9b3a..ed666f5cb01d 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1199,7 +1199,7 @@ static struct resource ssc0_resources[] = {
};
static struct platform_device at91sam9263_ssc0_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc0_dmamask,
@@ -1241,7 +1241,7 @@ static struct resource ssc1_resources[] = {
};
static struct platform_device at91sam9263_ssc1_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 1,
.dev = {
.dma_mask = &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 45d753d473f6..d3addee43d8d 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -239,8 +239,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index e35964201a10..827c9f2a70fb 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1459,7 +1459,7 @@ static struct resource ssc0_resources[] = {
};
static struct platform_device at91sam9g45_ssc0_device = {
- .name = "ssc",
+ .name = "at91sam9g45_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc0_dmamask,
@@ -1501,7 +1501,7 @@ static struct resource ssc1_resources[] = {
};
static struct platform_device at91sam9g45_ssc1_device = {
- .name = "ssc",
+ .name = "at91sam9g45_ssc",
.id = 1,
.dev = {
.dma_mask = &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 44e3a633fda7..eb98704db2d9 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -184,8 +184,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
+ CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 160384d93db2..ddf223ff35c4 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -832,7 +832,7 @@ static struct resource ssc0_resources[] = {
};
static struct platform_device at91sam9rl_ssc0_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 0,
.dev = {
.dma_mask = &ssc0_dmamask,
@@ -874,7 +874,7 @@ static struct resource ssc1_resources[] = {
};
static struct platform_device at91sam9rl_ssc1_device = {
- .name = "ssc",
+ .name = "at91rm9200_ssc",
.id = 1,
.dev = {
.dma_mask = &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index dfb2c0c13fb5..44a9a62dcc13 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -233,6 +233,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+ CLKDEV_CON_DEV_ID("pclk", "f0010000.ssc", &ssc_clk),
CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 78e025074423..48a531e05be3 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -53,6 +53,8 @@ static void __init csb337_init_early(void)
static struct macb_platform_data __initdata csb337_eth_data = {
.phy_irq_pin = AT91_PIN_PC2,
.is_rmii = 0,
+ /* The CSB337 bootloader stores the MAC the wrong-way around */
+ .rev_eth_addr = 1,
};
static struct at91_usbh_data __initdata csb337_usbh_data = {
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 7b5123802368..1b7dd9f688d3 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -353,6 +353,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
},
};
+static struct platform_device sam9g20ek_audio_device = {
+ .name = "at91sam9g20ek-audio",
+ .id = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+ platform_device_register(&sam9g20ek_audio_device);
+}
+
static void __init ek_board_init(void)
{
@@ -394,6 +404,7 @@ static void __init ek_board_init(void)
at91_set_B_periph(AT91_PIN_PC1, 0);
/* SSC (for WM8731) */
at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+ ek_add_device_audio();
}
MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h b/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
deleted file mode 100644
index b8260cd8041c..000000000000
--- a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200_emac.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Ethernet MAC registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * 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 AT91RM9200_EMAC_H
-#define AT91RM9200_EMAC_H
-
-#define AT91_EMAC_CTL 0x00 /* Control Register */
-#define AT91_EMAC_LB (1 << 0) /* Loopback */
-#define AT91_EMAC_LBL (1 << 1) /* Loopback Local */
-#define AT91_EMAC_RE (1 << 2) /* Receive Enable */
-#define AT91_EMAC_TE (1 << 3) /* Transmit Enable */
-#define AT91_EMAC_MPE (1 << 4) /* Management Port Enable */
-#define AT91_EMAC_CSR (1 << 5) /* Clear Statistics Registers */
-#define AT91_EMAC_INCSTAT (1 << 6) /* Increment Statistics Registers */
-#define AT91_EMAC_WES (1 << 7) /* Write Enable for Statistics Registers */
-#define AT91_EMAC_BP (1 << 8) /* Back Pressure */
-
-#define AT91_EMAC_CFG 0x04 /* Configuration Register */
-#define AT91_EMAC_SPD (1 << 0) /* Speed */
-#define AT91_EMAC_FD (1 << 1) /* Full Duplex */
-#define AT91_EMAC_BR (1 << 2) /* Bit Rate */
-#define AT91_EMAC_CAF (1 << 4) /* Copy All Frames */
-#define AT91_EMAC_NBC (1 << 5) /* No Broadcast */
-#define AT91_EMAC_MTI (1 << 6) /* Multicast Hash Enable */
-#define AT91_EMAC_UNI (1 << 7) /* Unicast Hash Enable */
-#define AT91_EMAC_BIG (1 << 8) /* Receive 1522 Bytes */
-#define AT91_EMAC_EAE (1 << 9) /* External Address Match Enable */
-#define AT91_EMAC_CLK (3 << 10) /* MDC Clock Divisor */
-#define AT91_EMAC_CLK_DIV8 (0 << 10)
-#define AT91_EMAC_CLK_DIV16 (1 << 10)
-#define AT91_EMAC_CLK_DIV32 (2 << 10)
-#define AT91_EMAC_CLK_DIV64 (3 << 10)
-#define AT91_EMAC_RTY (1 << 12) /* Retry Test */
-#define AT91_EMAC_RMII (1 << 13) /* Reduce MII (RMII) */
-
-#define AT91_EMAC_SR 0x08 /* Status Register */
-#define AT91_EMAC_SR_LINK (1 << 0) /* Link */
-#define AT91_EMAC_SR_MDIO (1 << 1) /* MDIO pin */
-#define AT91_EMAC_SR_IDLE (1 << 2) /* PHY idle */
-
-#define AT91_EMAC_TAR 0x0c /* Transmit Address Register */
-
-#define AT91_EMAC_TCR 0x10 /* Transmit Control Register */
-#define AT91_EMAC_LEN (0x7ff << 0) /* Transmit Frame Length */
-#define AT91_EMAC_NCRC (1 << 15) /* No CRC */
-
-#define AT91_EMAC_TSR 0x14 /* Transmit Status Register */
-#define AT91_EMAC_TSR_OVR (1 << 0) /* Transmit Buffer Overrun */
-#define AT91_EMAC_TSR_COL (1 << 1) /* Collision Occurred */
-#define AT91_EMAC_TSR_RLE (1 << 2) /* Retry Limit Exceeded */
-#define AT91_EMAC_TSR_IDLE (1 << 3) /* Transmitter Idle */
-#define AT91_EMAC_TSR_BNQ (1 << 4) /* Transmit Buffer not Queued */
-#define AT91_EMAC_TSR_COMP (1 << 5) /* Transmit Complete */
-#define AT91_EMAC_TSR_UND (1 << 6) /* Transmit Underrun */
-
-#define AT91_EMAC_RBQP 0x18 /* Receive Buffer Queue Pointer */
-
-#define AT91_EMAC_RSR 0x20 /* Receive Status Register */
-#define AT91_EMAC_RSR_BNA (1 << 0) /* Buffer Not Available */
-#define AT91_EMAC_RSR_REC (1 << 1) /* Frame Received */
-#define AT91_EMAC_RSR_OVR (1 << 2) /* RX Overrun */
-
-#define AT91_EMAC_ISR 0x24 /* Interrupt Status Register */
-#define AT91_EMAC_DONE (1 << 0) /* Management Done */
-#define AT91_EMAC_RCOM (1 << 1) /* Receive Complete */
-#define AT91_EMAC_RBNA (1 << 2) /* Receive Buffer Not Available */
-#define AT91_EMAC_TOVR (1 << 3) /* Transmit Buffer Overrun */
-#define AT91_EMAC_TUND (1 << 4) /* Transmit Buffer Underrun */
-#define AT91_EMAC_RTRY (1 << 5) /* Retry Limit */
-#define AT91_EMAC_TBRE (1 << 6) /* Transmit Buffer Register Empty */
-#define AT91_EMAC_TCOM (1 << 7) /* Transmit Complete */
-#define AT91_EMAC_TIDLE (1 << 8) /* Transmit Idle */
-#define AT91_EMAC_LINK (1 << 9) /* Link */
-#define AT91_EMAC_ROVR (1 << 10) /* RX Overrun */
-#define AT91_EMAC_ABT (1 << 11) /* Abort */
-
-#define AT91_EMAC_IER 0x28 /* Interrupt Enable Register */
-#define AT91_EMAC_IDR 0x2c /* Interrupt Disable Register */
-#define AT91_EMAC_IMR 0x30 /* Interrupt Mask Register */
-
-#define AT91_EMAC_MAN 0x34 /* PHY Maintenance Register */
-#define AT91_EMAC_DATA (0xffff << 0) /* MDIO Data */
-#define AT91_EMAC_REGA (0x1f << 18) /* MDIO Register */
-#define AT91_EMAC_PHYA (0x1f << 23) /* MDIO PHY Address */
-#define AT91_EMAC_RW (3 << 28) /* Read/Write operation */
-#define AT91_EMAC_RW_W (1 << 28)
-#define AT91_EMAC_RW_R (2 << 28)
-#define AT91_EMAC_MAN_802_3 0x40020000 /* IEEE 802.3 value */
-
-/*
- * Statistics Registers.
- */
-#define AT91_EMAC_FRA 0x40 /* Frames Transmitted OK */
-#define AT91_EMAC_SCOL 0x44 /* Single Collision Frame */
-#define AT91_EMAC_MCOL 0x48 /* Multiple Collision Frame */
-#define AT91_EMAC_OK 0x4c /* Frames Received OK */
-#define AT91_EMAC_SEQE 0x50 /* Frame Check Sequence Error */
-#define AT91_EMAC_ALE 0x54 /* Alignmemt Error */
-#define AT91_EMAC_DTE 0x58 /* Deffered Transmission Frame */
-#define AT91_EMAC_LCOL 0x5c /* Late Collision */
-#define AT91_EMAC_ECOL 0x60 /* Excessive Collision */
-#define AT91_EMAC_TUE 0x64 /* Transmit Underrun Error */
-#define AT91_EMAC_CSE 0x68 /* Carrier Sense Error */
-#define AT91_EMAC_DRFC 0x6c /* Discard RX Frame */
-#define AT91_EMAC_ROV 0x70 /* Receive Overrun */
-#define AT91_EMAC_CDE 0x74 /* Code Error */
-#define AT91_EMAC_ELR 0x78 /* Excessive Length Error */
-#define AT91_EMAC_RJB 0x7c /* Receive Jabber */
-#define AT91_EMAC_USF 0x80 /* Undersize Frame */
-#define AT91_EMAC_SQEE 0x84 /* SQE Test Error */
-
-/*
- * Address Registers.
- */
-#define AT91_EMAC_HSL 0x90 /* Hash Address Low [31:0] */
-#define AT91_EMAC_HSH 0x94 /* Hash Address High [63:32] */
-#define AT91_EMAC_SA1L 0x98 /* Specific Address 1 Low, bytes 0-3 */
-#define AT91_EMAC_SA1H 0x9c /* Specific Address 1 High, bytes 4-5 */
-#define AT91_EMAC_SA2L 0xa0 /* Specific Address 2 Low, bytes 0-3 */
-#define AT91_EMAC_SA2H 0xa4 /* Specific Address 2 High, bytes 4-5 */
-#define AT91_EMAC_SA3L 0xa8 /* Specific Address 3 Low, bytes 0-3 */
-#define AT91_EMAC_SA3H 0xac /* Specific Address 3 High, bytes 4-5 */
-#define AT91_EMAC_SA4L 0xb0 /* Specific Address 4 Low, bytes 0-3 */
-#define AT91_EMAC_SA4H 0xb4 /* Specific Address 4 High, bytes 4-5 */
-
-#endif
diff --git a/arch/arm/mach-davinci/Makefile.boot b/arch/arm/mach-davinci/Makefile.boot
index 5c5a95a9d7d2..04a6c4e67b14 100644
--- a/arch/arm/mach-davinci/Makefile.boot
+++ b/arch/arm/mach-davinci/Makefile.boot
@@ -11,5 +11,3 @@ else
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000
endif
-
-dtb-$(CONFIG_MACH_DA8XX_DT) += da850-enbw-cmc.dtb da850-evm.dtb
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index d4f4dbfc0e59..7211772edd9d 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -763,16 +763,19 @@ static u8 da850_iis_serializer_direction[] = {
};
static struct snd_platform_data da850_evm_snd_data = {
- .tx_dma_offset = 0x2000,
- .rx_dma_offset = 0x2000,
- .op_mode = DAVINCI_MCASP_IIS_MODE,
- .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
- .tdm_slots = 2,
- .serial_dir = da850_iis_serializer_direction,
- .asp_chan_q = EVENTQ_0,
- .version = MCASP_VERSION_2,
- .txnumevt = 1,
- .rxnumevt = 1,
+ .tx_dma_offset = 0x2000,
+ .rx_dma_offset = 0x2000,
+ .op_mode = DAVINCI_MCASP_IIS_MODE,
+ .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
+ .tdm_slots = 2,
+ .serial_dir = da850_iis_serializer_direction,
+ .asp_chan_q = EVENTQ_0,
+ .ram_chan_q = EVENTQ_1,
+ .version = MCASP_VERSION_2,
+ .txnumevt = 1,
+ .rxnumevt = 1,
+ .sram_size_playback = SZ_8K,
+ .sram_size_capture = SZ_8K,
};
static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1510,6 +1513,7 @@ static __init void da850_evm_init(void)
pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
ret);
+ da850_evm_snd_data.sram_pool = sram_get_gen_pool();
da8xx_register_mcasp(0, &da850_evm_snd_data);
ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 070c7b6d3d86..91d5b6f1d5af 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -63,6 +63,7 @@ config SOC_EXYNOS5250
depends on ARCH_EXYNOS5
select S5P_PM if PM
select S5P_SLEEP if PM
+ select S5P_DEV_MFC
select SAMSUNG_DMADEV
help
Enable EXYNOS5250 SoC support
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 66135eedf491..b189881657ec 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -52,7 +52,6 @@ obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o
obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o
obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o
-obj-$(CONFIG_EXYNOS_DEV_DRM) += dev-drm.o
obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index fa8a13405c94..efead60b9436 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -576,6 +576,10 @@ static struct clk exynos4_init_clocks_off[] = {
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 15),
}, {
+ .name = "tmu_apbif",
+ .enable = exynos4_clk_ip_perir_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
.name = "keypad",
.enable = exynos4_clk_ip_perir_ctrl,
.ctrlbit = (1 << 16),
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index 4478757b9301..7652f5d78a56 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -196,6 +196,11 @@ static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
}
+static int exynos5_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
/* Core list of CMU_CPU side */
static struct clksrc_clk exynos5_clk_mout_apll = {
@@ -616,6 +621,11 @@ static struct clk exynos5_init_clocks_off[] = {
.enable = exynos5_clk_ip_peric_ctrl,
.ctrlbit = (1 << 24),
}, {
+ .name = "tmu_apbif",
+ .parent = &exynos5_clk_aclk_66.clk,
+ .enable = exynos5_clk_ip_peris_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
.name = "rtc",
.parent = &exynos5_clk_aclk_66.clk,
.enable = exynos5_clk_ip_peris_ctrl,
@@ -664,17 +674,22 @@ static struct clk exynos5_init_clocks_off[] = {
.ctrlbit = (1 << 25),
}, {
.name = "mfc",
- .devname = "s5p-mfc",
+ .devname = "s5p-mfc-v6",
.enable = exynos5_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "hdmi",
- .devname = "exynos4-hdmi",
+ .devname = "exynos5-hdmi",
.enable = exynos5_clk_ip_disp1_ctrl,
.ctrlbit = (1 << 6),
}, {
+ .name = "hdmiphy",
+ .devname = "exynos5-hdmi",
+ .enable = exynos5_clk_hdmiphy_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
.name = "mixer",
- .devname = "s5p-mixer",
+ .devname = "exynos5-mixer",
.enable = exynos5_clk_ip_disp1_ctrl,
.ctrlbit = (1 << 5),
}, {
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index e05f6cca2c9b..ddd4b72c6f9a 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -680,6 +680,8 @@ void __init exynos5_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
+
+ gic_arch_extn.irq_set_wake = s3c_irq_wake;
}
struct bus_type exynos_subsys = {
@@ -1020,11 +1022,14 @@ static int __init exynos_init_irq_eint(void)
* platforms switch over to using the pinctrl driver, the wakeup
* interrupt support code here can be completely removed.
*/
+ static const struct of_device_id exynos_pinctrl_ids[] = {
+ { .compatible = "samsung,pinctrl-exynos4210", },
+ { .compatible = "samsung,pinctrl-exynos4x12", },
+ };
struct device_node *pctrl_np, *wkup_np;
- const char *pctrl_compat = "samsung,pinctrl-exynos4210";
const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
- for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
+ for_each_matching_node(pctrl_np, exynos_pinctrl_ids) {
if (of_device_is_available(pctrl_np)) {
wkup_np = of_find_compatible_node(pctrl_np, NULL,
wkup_compat);
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index cff0595d0d35..8e4ec21ef2cf 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -116,7 +116,8 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
cpu_suspend(0, idle_finisher);
#ifdef CONFIG_SMP
- scu_enable(S5P_VA_SCU);
+ if (!soc_is_exynos5250())
+ scu_enable(S5P_VA_SCU);
#endif
cpu_pm_exit();
diff --git a/arch/arm/mach-exynos/dev-drm.c b/arch/arm/mach-exynos/dev-drm.c
deleted file mode 100644
index 17c9c6ecc2e0..000000000000
--- a/arch/arm/mach-exynos/dev-drm.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos/dev-drm.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS - core DRM device
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-
-#include <plat/devs.h>
-
-static u64 exynos_drm_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device exynos_device_drm = {
- .name = "exynos-drm",
- .dev = {
- .dma_mask = &exynos_drm_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- }
-};
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index f4d7dd20cdac..c3f825b27947 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -20,10 +20,11 @@
#include <asm/smp_plat.h>
#include <mach/regs-pmu.h>
+#include <plat/cpu.h>
#include "common.h"
-static inline void cpu_enter_lowpower(void)
+static inline void cpu_enter_lowpower_a9(void)
{
unsigned int v;
@@ -45,6 +46,35 @@ static inline void cpu_enter_lowpower(void)
: "cc");
}
+static inline void cpu_enter_lowpower_a15(void)
+{
+ unsigned int v;
+
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "Ir" (CR_C)
+ : "cc");
+
+ flush_cache_louis();
+
+ asm volatile(
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (0x40)
+ : "cc");
+
+ isb();
+ dsb();
+}
+
static inline void cpu_leave_lowpower(void)
{
unsigned int v;
@@ -103,11 +133,20 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
void __ref exynos_cpu_die(unsigned int cpu)
{
int spurious = 0;
+ int primary_part = 0;
/*
- * we're ready for shutdown now, so do it
+ * we're ready for shutdown now, so do it.
+ * Exynos4 is A9 based while Exynos5 is A15; check the CPU part
+ * number by reading the Main ID register and then perform the
+ * appropriate sequence for entering low power.
*/
- cpu_enter_lowpower();
+ asm("mrc p15, 0, %0, c0, c0, 0" : "=r"(primary_part) : : "cc");
+ if ((primary_part & 0xfff0) == 0xc0f0)
+ cpu_enter_lowpower_a15();
+ else
+ cpu_enter_lowpower_a9();
+
platform_do_lowpower(cpu, &spurious);
/*
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index e0f0ae3e0cf9..1f4dc35cd4b9 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -136,6 +136,9 @@
#define EXYNOS4_IRQ_TSI IRQ_SPI(115)
#define EXYNOS4_IRQ_SATA IRQ_SPI(116)
+#define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4)
+#define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4)
+
#define EXYNOS4_IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
#define EXYNOS4_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1)
#define EXYNOS4_IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 61b74e12d12b..1df6abbf53b8 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -89,6 +89,8 @@
#define EXYNOS4_PA_TWD 0x10500600
#define EXYNOS4_PA_L2CC 0x10502000
+#define EXYNOS4_PA_TMU 0x100C0000
+
#define EXYNOS4_PA_MDMA0 0x10810000
#define EXYNOS4_PA_MDMA1 0x12850000
#define EXYNOS4_PA_S_MDMA1 0x12840000
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 3f37a5e8a1f4..b938f9fc1dd1 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -147,7 +147,6 @@ static struct platform_device *armlex4210_devices[] __initdata = {
&s3c_device_hsmmc3,
&s3c_device_rtc,
&s3c_device_wdt,
- &samsung_asoc_dma,
&armlex4210_smsc911x,
&exynos4_device_ahci,
};
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 6df99c06419d..92757ff817ae 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -78,6 +78,8 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU,
+ "exynos-tmu", NULL),
{},
};
@@ -95,6 +97,8 @@ static void __init exynos4_dt_machine_init(void)
static char const *exynos4_dt_compat[] __initdata = {
"samsung,exynos4210",
+ "samsung,exynos4212",
+ "samsung,exynos4412",
NULL
};
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f1326be80b91..929de766d490 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -12,6 +12,8 @@
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
#include <linux/serial_core.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -19,6 +21,7 @@
#include <plat/cpu.h>
#include <plat/regs-serial.h>
+#include <plat/mfc.h>
#include "common.h"
@@ -48,6 +51,20 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
"s3c2440-i2c.0", NULL),
OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
"s3c2440-i2c.1", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(2),
+ "s3c2440-i2c.2", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(3),
+ "s3c2440-i2c.3", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(4),
+ "s3c2440-i2c.4", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(5),
+ "s3c2440-i2c.5", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(6),
+ "s3c2440-i2c.6", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(7),
+ "s3c2440-i2c.7", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS5_PA_IIC(8),
+ "s3c2440-hdmiphy-i2c", NULL),
OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI0,
"dw_mmc.0", NULL),
OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI1,
@@ -62,6 +79,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
"exynos4210-spi.1", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
"exynos4210-spi.2", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000,
+ "exynos5-sata", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000,
+ "exynos5-sata-phy", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000,
+ "exynos5-sata-phy-i2c", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
@@ -73,6 +96,13 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
"exynos-gsc.2", NULL),
OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
"exynos-gsc.3", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5-hdmi", 0x14530000,
+ "exynos5-hdmi", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5-mixer", 0x14450000,
+ "exynos5-mixer", NULL),
+ OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000,
+ "exynos-tmu", NULL),
{},
};
@@ -108,6 +138,17 @@ static char const *exynos5_dt_compat[] __initdata = {
NULL
};
+static void __init exynos5_reserve(void)
+{
+ struct s5p_mfc_dt_meminfo mfc_mem;
+
+ /* Reserve memory for MFC only if it's available */
+ mfc_mem.compatible = "samsung,mfc-v6";
+ if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
+ s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
+ mfc_mem.lsize);
+}
+
DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.init_irq = exynos5_init_irq,
@@ -119,4 +160,5 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
.timer = &exynos4_timer,
.dt_compat = exynos5_dt_compat,
.restart = exynos5_restart,
+ .reserve = exynos5_reserve,
MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 69359a0c8a1c..27d4ed8b116e 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1326,9 +1326,6 @@ static struct platform_device *nuri_devices[] __initdata = {
&cam_vdda_fixed_rdev,
&cam_8m_12v_fixed_rdev,
&exynos4_bus_devfreq,
-#ifdef CONFIG_DRM_EXYNOS
- &exynos_device_drm,
-#endif
};
static void __init nuri_map_io(void)
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index c606080b5dfa..e6f4191cd14c 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -711,9 +711,6 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&s5p_device_mixer,
-#ifdef CONFIG_DRM_EXYNOS
- &exynos_device_drm,
-#endif
&exynos4_device_ohci,
&origen_device_gpiokeys,
&origen_lcd_hv070wsa,
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index ddb92631252d..a1555a73c7af 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -317,9 +317,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
&s5p_device_mfc,
&s5p_device_mfc_l,
&s5p_device_mfc_r,
-#ifdef CONFIG_DRM_EXYNOS
- &exynos_device_drm,
-#endif
&samsung_device_keypad,
};
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 8dd6a1e8030d..b7384241fb03 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -300,9 +300,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&s5p_device_fimc_md,
&s5p_device_g2d,
&s5p_device_jpeg,
-#ifdef CONFIG_DRM_EXYNOS
- &exynos_device_drm,
-#endif
&exynos4_device_ac97,
&exynos4_device_i2s0,
&exynos4_device_ohci,
@@ -311,7 +308,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&exynos4_device_spdif,
- &samsung_asoc_dma,
&samsung_asoc_idma,
&s5p_device_fimd0,
&smdkv310_device_audio,
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 2d6bc83d5c99..9e3340f18950 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -1080,9 +1080,6 @@ static struct platform_device *universal_devices[] __initdata = {
&s5p_device_onenand,
&s5p_device_fimd0,
&s5p_device_jpeg,
-#ifdef CONFIG_DRM_EXYNOS
- &exynos_device_drm,
-#endif
&s3c_device_usb_hsotg,
&s5p_device_mfc,
&s5p_device_mfc_l,
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index c06c992943a1..8df6ec547f78 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -81,6 +81,9 @@ static int exynos_cpu_suspend(unsigned long arg)
outer_flush_all();
#endif
+ if (soc_is_exynos5250())
+ flush_cache_all();
+
/* issue the standby signal into the pm unit. */
cpu_do_idle();
@@ -312,6 +315,10 @@ static void exynos_pm_resume(void)
}
early_wakeup:
+
+ /* Clear SLEEP mode set in INFORM1 */
+ __raw_writel(0x0, S5P_INFORM1);
+
return;
}
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index c0bc83a7663e..9f1351de52f7 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -19,6 +19,8 @@
#include <linux/pm_domain.h>
#include <linux/delay.h>
#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sched.h>
#include <mach/regs-pmu.h>
#include <plat/devs.h>
@@ -83,12 +85,88 @@ static struct exynos_pm_domain PD = { \
}
#ifdef CONFIG_OF
+static void exynos_add_device_to_domain(struct exynos_pm_domain *pd,
+ struct device *dev)
+{
+ int ret;
+
+ dev_dbg(dev, "adding to power domain %s\n", pd->pd.name);
+
+ while (1) {
+ ret = pm_genpd_add_device(&pd->pd, dev);
+ if (ret != -EAGAIN)
+ break;
+ cond_resched();
+ }
+
+ pm_genpd_dev_need_restore(dev, true);
+}
+
+static void exynos_remove_device_from_domain(struct device *dev)
+{
+ struct generic_pm_domain *genpd = dev_to_genpd(dev);
+ int ret;
+
+ dev_dbg(dev, "removing from power domain %s\n", genpd->name);
+
+ while (1) {
+ ret = pm_genpd_remove_device(genpd, dev);
+ if (ret != -EAGAIN)
+ break;
+ cond_resched();
+ }
+}
+
+static void exynos_read_domain_from_dt(struct device *dev)
+{
+ struct platform_device *pd_pdev;
+ struct exynos_pm_domain *pd;
+ struct device_node *node;
+
+ node = of_parse_phandle(dev->of_node, "samsung,power-domain", 0);
+ if (!node)
+ return;
+ pd_pdev = of_find_device_by_node(node);
+ if (!pd_pdev)
+ return;
+ pd = platform_get_drvdata(pd_pdev);
+ exynos_add_device_to_domain(pd, dev);
+}
+
+static int exynos_pm_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct device *dev = data;
+
+ switch (event) {
+ case BUS_NOTIFY_BIND_DRIVER:
+ if (dev->of_node)
+ exynos_read_domain_from_dt(dev);
+
+ break;
+
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ exynos_remove_device_from_domain(dev);
+
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block platform_nb = {
+ .notifier_call = exynos_pm_notifier_call,
+};
+
static __init int exynos_pm_dt_parse_domains(void)
{
+ struct platform_device *pdev;
struct device_node *np;
for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
struct exynos_pm_domain *pd;
+ int on;
+
+ pdev = of_find_device_by_node(np);
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
if (!pd) {
@@ -97,15 +175,22 @@ static __init int exynos_pm_dt_parse_domains(void)
return -ENOMEM;
}
- if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
- pd->is_off = true;
- pd->name = np->name;
+ pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+ pd->name = pd->pd.name;
pd->base = of_iomap(np, 0);
pd->pd.power_off = exynos_pd_power_off;
pd->pd.power_on = exynos_pd_power_on;
pd->pd.of_node = np;
- pm_genpd_init(&pd->pd, NULL, false);
+
+ platform_set_drvdata(pdev, pd);
+
+ on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+
+ pm_genpd_init(&pd->pd, NULL, !on);
}
+
+ bus_register_notifier(&platform_bus_type, &platform_nb);
+
return 0;
}
#else
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4e24b8c77eb4..1ad0d76de8c7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -272,6 +272,13 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
endchoice
+config MACH_IMX25_DT
+ bool "Support i.MX25 platforms from device tree"
+ select SOC_IMX25
+ help
+ Include support for Freescale i.MX25 based platforms
+ using the device tree for discovery
+
comment "MX27 platforms:"
config MACH_MX27ADS
@@ -831,7 +838,14 @@ config SOC_IMX53
config SOC_IMX6Q
bool "i.MX6 Quad support"
+ select ARCH_HAS_CPUFREQ
+ select ARCH_HAS_OPP
select ARM_CPU_SUSPEND if PM
+ select ARM_ERRATA_743622
+ select ARM_ERRATA_751472
+ select ARM_ERRATA_754322
+ select ARM_ERRATA_764369 if SMP
+ select ARM_ERRATA_775420
select ARM_GIC
select COMMON_CLK
select CPU_V7
@@ -843,6 +857,10 @@ config SOC_IMX6Q
select MFD_SYSCON
select PINCTRL
select PINCTRL_IMX6Q
+ select PL310_ERRATA_588369 if CACHE_PL310
+ select PL310_ERRATA_727915 if CACHE_PL310
+ select PL310_ERRATA_769419 if CACHE_PL310
+ select PM_OPP if PM
help
This enables support for Freescale i.MX6 Quad processor.
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index fe47b71469c9..0634b3152c24 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o
obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
+obj-$(CONFIG_MACH_IMX25_DT) += imx25-dt.o
# i.MX27 based machines
obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index bc885801cd68..b197aa73dc4b 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -23,6 +23,9 @@
#include <linux/io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include "clk.h"
#include "common.h"
@@ -55,6 +58,8 @@
#define ccm(x) (CRM_BASE + (x))
+static struct clk_onecell_data clk_data;
+
static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", };
static const char *per_sel_clks[] = { "ahb", "upll", };
@@ -64,24 +69,30 @@ enum mx25_clks {
per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel,
per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5,
per6, per7, per8, per9, per10, per11, per12, per13, per14, per15,
- csi_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per, gpt_ipg_per, i2c_ipg_per,
- lcdc_ipg_per, nfc_ipg_per, ssi1_ipg_per, ssi2_ipg_per, uart_ipg_per,
- csi_ahb, esdhc1_ahb, esdhc2_ahb, fec_ahb, lcdc_ahb, sdma_ahb,
- usbotg_ahb, can1_ipg, can2_ipg, csi_ipg, cspi1_ipg, cspi2_ipg,
- cspi3_ipg, dryice_ipg, esdhc1_ipg, esdhc2_ipg, fec_ipg, iim_ipg,
- kpp_ipg, lcdc_ipg, pwm1_ipg, pwm2_ipg, pwm3_ipg, pwm4_ipg, sdma_ipg,
- ssi1_ipg, ssi2_ipg, tsc_ipg, uart1_ipg, uart2_ipg, uart3_ipg,
- uart4_ipg, uart5_ipg, wdt_ipg, clk_max
+ csi_ipg_per, epit_ipg_per, esai_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per,
+ gpt_ipg_per, i2c_ipg_per, lcdc_ipg_per, nfc_ipg_per, owire_ipg_per,
+ pwm_ipg_per, sim1_ipg_per, sim2_ipg_per, ssi1_ipg_per, ssi2_ipg_per,
+ uart_ipg_per, ata_ahb, reserved1, csi_ahb, emi_ahb, esai_ahb, esdhc1_ahb,
+ esdhc2_ahb, fec_ahb, lcdc_ahb, rtic_ahb, sdma_ahb, slcdc_ahb, usbotg_ahb,
+ reserved2, reserved3, reserved4, reserved5, can1_ipg, can2_ipg, csi_ipg,
+ cspi1_ipg, cspi2_ipg, cspi3_ipg, dryice_ipg, ect_ipg, epit1_ipg, epit2_ipg,
+ reserved6, esdhc1_ipg, esdhc2_ipg, fec_ipg, reserved7, reserved8, reserved9,
+ gpt1_ipg, gpt2_ipg, gpt3_ipg, gpt4_ipg, reserved10, reserved11, reserved12,
+ iim_ipg, reserved13, reserved14, kpp_ipg, lcdc_ipg, reserved15, pwm1_ipg,
+ pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg,
+ sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg,
+ uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17,
+ wdt_ipg, clk_max
};
static struct clk *clk[clk_max];
-int __init mx25_clocks_init(void)
+static int __init __mx25_clocks_init(unsigned long osc_rate)
{
int i;
clk[dummy] = imx_clk_fixed("dummy", 0);
- clk[osc] = imx_clk_fixed("osc", 24000000);
+ clk[osc] = imx_clk_fixed("osc", osc_rate);
clk[mpll] = imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL));
clk[upll] = imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL));
clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
@@ -123,22 +134,36 @@ int __init mx25_clocks_init(void)
clk[per14] = imx_clk_divider("per14", "per14_sel", ccm(CCM_PCDR3), 16, 6);
clk[per15] = imx_clk_divider("per15", "per15_sel", ccm(CCM_PCDR3), 24, 6);
clk[csi_ipg_per] = imx_clk_gate("csi_ipg_per", "per0", ccm(CCM_CGCR0), 0);
+ clk[epit_ipg_per] = imx_clk_gate("epit_ipg_per", "per1", ccm(CCM_CGCR0), 1);
+ clk[esai_ipg_per] = imx_clk_gate("esai_ipg_per", "per2", ccm(CCM_CGCR0), 2);
clk[esdhc1_ipg_per] = imx_clk_gate("esdhc1_ipg_per", "per3", ccm(CCM_CGCR0), 3);
clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0), 4);
clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0), 5);
clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0), 6);
clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0), 7);
clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0), 8);
+ clk[owire_ipg_per] = imx_clk_gate("owire_ipg_per", "per9", ccm(CCM_CGCR0), 9);
+ clk[pwm_ipg_per] = imx_clk_gate("pwm_ipg_per", "per10", ccm(CCM_CGCR0), 10);
+ clk[sim1_ipg_per] = imx_clk_gate("sim1_ipg_per", "per11", ccm(CCM_CGCR0), 11);
+ clk[sim2_ipg_per] = imx_clk_gate("sim2_ipg_per", "per12", ccm(CCM_CGCR0), 12);
clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
+ clk[ata_ahb] = imx_clk_gate("ata_ahb", "ahb", ccm(CCM_CGCR0), 16);
+ /* CCM_CGCR0(17): reserved */
clk[csi_ahb] = imx_clk_gate("csi_ahb", "ahb", ccm(CCM_CGCR0), 18);
+ clk[emi_ahb] = imx_clk_gate("emi_ahb", "ahb", ccm(CCM_CGCR0), 19);
+ clk[esai_ahb] = imx_clk_gate("esai_ahb", "ahb", ccm(CCM_CGCR0), 20);
clk[esdhc1_ahb] = imx_clk_gate("esdhc1_ahb", "ahb", ccm(CCM_CGCR0), 21);
clk[esdhc2_ahb] = imx_clk_gate("esdhc2_ahb", "ahb", ccm(CCM_CGCR0), 22);
clk[fec_ahb] = imx_clk_gate("fec_ahb", "ahb", ccm(CCM_CGCR0), 23);
clk[lcdc_ahb] = imx_clk_gate("lcdc_ahb", "ahb", ccm(CCM_CGCR0), 24);
+ clk[rtic_ahb] = imx_clk_gate("rtic_ahb", "ahb", ccm(CCM_CGCR0), 25);
clk[sdma_ahb] = imx_clk_gate("sdma_ahb", "ahb", ccm(CCM_CGCR0), 26);
+ clk[slcdc_ahb] = imx_clk_gate("slcdc_ahb", "ahb", ccm(CCM_CGCR0), 27);
clk[usbotg_ahb] = imx_clk_gate("usbotg_ahb", "ahb", ccm(CCM_CGCR0), 28);
+ /* CCM_CGCR0(29-31): reserved */
+ /* CCM_CGCR1(0): reserved in datasheet, used as audmux in FSL kernel */
clk[can1_ipg] = imx_clk_gate("can1_ipg", "ipg", ccm(CCM_CGCR1), 2);
clk[can2_ipg] = imx_clk_gate("can2_ipg", "ipg", ccm(CCM_CGCR1), 3);
clk[csi_ipg] = imx_clk_gate("csi_ipg", "ipg", ccm(CCM_CGCR1), 4);
@@ -146,17 +171,41 @@ int __init mx25_clocks_init(void)
clk[cspi2_ipg] = imx_clk_gate("cspi2_ipg", "ipg", ccm(CCM_CGCR1), 6);
clk[cspi3_ipg] = imx_clk_gate("cspi3_ipg", "ipg", ccm(CCM_CGCR1), 7);
clk[dryice_ipg] = imx_clk_gate("dryice_ipg", "ipg", ccm(CCM_CGCR1), 8);
+ clk[ect_ipg] = imx_clk_gate("ect_ipg", "ipg", ccm(CCM_CGCR1), 9);
+ clk[epit1_ipg] = imx_clk_gate("epit1_ipg", "ipg", ccm(CCM_CGCR1), 10);
+ clk[epit2_ipg] = imx_clk_gate("epit2_ipg", "ipg", ccm(CCM_CGCR1), 11);
+ /* CCM_CGCR1(12): reserved in datasheet, used as esai in FSL kernel */
clk[esdhc1_ipg] = imx_clk_gate("esdhc1_ipg", "ipg", ccm(CCM_CGCR1), 13);
clk[esdhc2_ipg] = imx_clk_gate("esdhc2_ipg", "ipg", ccm(CCM_CGCR1), 14);
clk[fec_ipg] = imx_clk_gate("fec_ipg", "ipg", ccm(CCM_CGCR1), 15);
+ /* CCM_CGCR1(16): reserved in datasheet, used as gpio1 in FSL kernel */
+ /* CCM_CGCR1(17): reserved in datasheet, used as gpio2 in FSL kernel */
+ /* CCM_CGCR1(18): reserved in datasheet, used as gpio3 in FSL kernel */
+ clk[gpt1_ipg] = imx_clk_gate("gpt1_ipg", "ipg", ccm(CCM_CGCR1), 19);
+ clk[gpt2_ipg] = imx_clk_gate("gpt2_ipg", "ipg", ccm(CCM_CGCR1), 20);
+ clk[gpt3_ipg] = imx_clk_gate("gpt3_ipg", "ipg", ccm(CCM_CGCR1), 21);
+ clk[gpt4_ipg] = imx_clk_gate("gpt4_ipg", "ipg", ccm(CCM_CGCR1), 22);
+ /* CCM_CGCR1(23): reserved in datasheet, used as i2c1 in FSL kernel */
+ /* CCM_CGCR1(24): reserved in datasheet, used as i2c2 in FSL kernel */
+ /* CCM_CGCR1(25): reserved in datasheet, used as i2c3 in FSL kernel */
clk[iim_ipg] = imx_clk_gate("iim_ipg", "ipg", ccm(CCM_CGCR1), 26);
+ /* CCM_CGCR1(27): reserved in datasheet, used as iomuxc in FSL kernel */
+ /* CCM_CGCR1(28): reserved in datasheet, used as kpp in FSL kernel */
clk[kpp_ipg] = imx_clk_gate("kpp_ipg", "ipg", ccm(CCM_CGCR1), 28);
clk[lcdc_ipg] = imx_clk_gate("lcdc_ipg", "ipg", ccm(CCM_CGCR1), 29);
+ /* CCM_CGCR1(30): reserved in datasheet, used as owire in FSL kernel */
clk[pwm1_ipg] = imx_clk_gate("pwm1_ipg", "ipg", ccm(CCM_CGCR1), 31);
clk[pwm2_ipg] = imx_clk_gate("pwm2_ipg", "ipg", ccm(CCM_CGCR2), 0);
clk[pwm3_ipg] = imx_clk_gate("pwm3_ipg", "ipg", ccm(CCM_CGCR2), 1);
clk[pwm4_ipg] = imx_clk_gate("pwm4_ipg", "ipg", ccm(CCM_CGCR2), 2);
+ clk[rngb_ipg] = imx_clk_gate("rngb_ipg", "ipg", ccm(CCM_CGCR2), 3);
+ /* CCM_CGCR2(4): reserved in datasheet, used as rtic in FSL kernel */
+ clk[scc_ipg] = imx_clk_gate("scc_ipg", "ipg", ccm(CCM_CGCR2), 5);
clk[sdma_ipg] = imx_clk_gate("sdma_ipg", "ipg", ccm(CCM_CGCR2), 6);
+ clk[sim1_ipg] = imx_clk_gate("sim1_ipg", "ipg", ccm(CCM_CGCR2), 7);
+ clk[sim2_ipg] = imx_clk_gate("sim2_ipg", "ipg", ccm(CCM_CGCR2), 8);
+ clk[slcdc_ipg] = imx_clk_gate("slcdc_ipg", "ipg", ccm(CCM_CGCR2), 9);
+ clk[spba_ipg] = imx_clk_gate("spba_ipg", "ipg", ccm(CCM_CGCR2), 10);
clk[ssi1_ipg] = imx_clk_gate("ssi1_ipg", "ipg", ccm(CCM_CGCR2), 11);
clk[ssi2_ipg] = imx_clk_gate("ssi2_ipg", "ipg", ccm(CCM_CGCR2), 12);
clk[tsc_ipg] = imx_clk_gate("tsc_ipg", "ipg", ccm(CCM_CGCR2), 13);
@@ -165,6 +214,7 @@ int __init mx25_clocks_init(void)
clk[uart3_ipg] = imx_clk_gate("uart3_ipg", "ipg", ccm(CCM_CGCR2), 16);
clk[uart4_ipg] = imx_clk_gate("uart4_ipg", "ipg", ccm(CCM_CGCR2), 17);
clk[uart5_ipg] = imx_clk_gate("uart5_ipg", "ipg", ccm(CCM_CGCR2), 18);
+ /* CCM_CGCR2(19): reserved in datasheet, but used as wdt in FSL kernel */
clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
for (i = 0; i < ARRAY_SIZE(clk); i++)
@@ -172,6 +222,18 @@ int __init mx25_clocks_init(void)
pr_err("i.MX25 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
+ clk_prepare_enable(clk[emi_ahb]);
+
+ clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
+
+ return 0;
+}
+
+int __init mx25_clocks_init(void)
+{
+ __mx25_clocks_init(24000000);
+
/* i.mx25 has the i.mx21 type uart */
clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
@@ -183,8 +245,6 @@ int __init mx25_clocks_init(void)
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.3");
clk_register_clkdev(clk[uart5_ipg], "ipg", "imx21-uart.4");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.4");
- clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
@@ -242,5 +302,40 @@ int __init mx25_clocks_init(void)
clk_register_clkdev(clk[iim_ipg], "iim", NULL);
mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1);
+
+ return 0;
+}
+
+int __init mx25_clocks_init_dt(void)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int irq;
+ unsigned long osc_rate = 24000000;
+
+ /* retrieve the freqency of fixed clocks from device tree */
+ for_each_compatible_node(np, NULL, "fixed-clock") {
+ u32 rate;
+ if (of_property_read_u32(np, "clock-frequency", &rate))
+ continue;
+
+ if (of_device_is_compatible(np, "fsl,imx-osc"))
+ osc_rate = rate;
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
+ clk_data.clks = clk;
+ clk_data.clk_num = ARRAY_SIZE(clk);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+ __mx25_clocks_init(osc_rate);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+ irq = irq_of_parse_and_map(np, 0);
+
+ mxc_timer_init(base, irq);
+
return 0;
}
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 448476958e7f..7f2c10c7413a 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -424,6 +424,7 @@ int __init mx6q_clocks_init(void)
clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
clk_register_clkdev(clk[ahb], "ahb", NULL);
clk_register_clkdev(clk[cko1], "cko1", NULL);
+ clk_register_clkdev(clk[arm], NULL, "cpu0");
/*
* The gpmi needs 100MHz frequency in the EDO/Sync mode,
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index ef8db6b34841..7191ab4434e5 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -66,6 +66,7 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2);
extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2);
+extern int mx25_clocks_init_dt(void);
extern int mx27_clocks_init_dt(void);
extern int mx31_clocks_init_dt(void);
extern int mx51_clocks_init_dt(void);
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
new file mode 100644
index 000000000000..e17dfbc42192
--- /dev/null
+++ b/arch/arm/mach-imx/imx25-dt.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 Sascha Hauer, 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
+ */
+
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include "common.h"
+#include "mx25.h"
+
+static void __init imx25_dt_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static void __init imx25_timer_init(void)
+{
+ mx25_clocks_init_dt();
+}
+
+static struct sys_timer imx25_timer = {
+ .init = imx25_timer_init,
+};
+
+static const char * const imx25_dt_board_compat[] __initconst = {
+ "fsl,imx25",
+ NULL
+};
+
+DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
+ .map_io = mx25_map_io,
+ .init_early = imx25_init_early,
+ .init_irq = mx25_init_irq,
+ .handle_irq = imx25_handle_irq,
+ .timer = &imx25_timer,
+ .init_machine = imx25_dt_init,
+ .dt_compat = imx25_dt_board_compat,
+ .restart = mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
index 5f1510363ee7..2fdc9bf2fb5e 100644
--- a/arch/arm/mach-imx/lluart.c
+++ b/arch/arm/mach-imx/lluart.c
@@ -17,17 +17,25 @@
#include "hardware.h"
+#define IMX6Q_UART1_BASE_ADDR 0x02020000
+#define IMX6Q_UART2_BASE_ADDR 0x021e8000
+#define IMX6Q_UART3_BASE_ADDR 0x021ec000
+#define IMX6Q_UART4_BASE_ADDR 0x021f0000
+#define IMX6Q_UART5_BASE_ADDR 0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n) IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n) IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
+
static struct map_desc imx_lluart_desc = {
-#ifdef CONFIG_DEBUG_IMX6Q_UART2
- .virtual = MX6Q_IO_P2V(MX6Q_UART2_BASE_ADDR),
- .pfn = __phys_to_pfn(MX6Q_UART2_BASE_ADDR),
- .length = MX6Q_UART2_SIZE,
- .type = MT_DEVICE,
-#endif
-#ifdef CONFIG_DEBUG_IMX6Q_UART4
- .virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
- .pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
- .length = MX6Q_UART4_SIZE,
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+ .virtual = IMX_IO_P2V(IMX6Q_DEBUG_UART_BASE),
+ .pfn = __phys_to_pfn(IMX6Q_DEBUG_UART_BASE),
+ .length = 0x4000,
.type = MT_DEVICE,
#endif
};
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 978b6dd00de4..4eb1b3ac794c 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -38,6 +38,40 @@
#include "cpuidle.h"
#include "hardware.h"
+#define IMX6Q_ANALOG_DIGPROG 0x260
+
+static int imx6q_revision(void)
+{
+ struct device_node *np;
+ void __iomem *base;
+ static u32 rev;
+
+ if (!rev) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+ if (!np)
+ return IMX_CHIP_REVISION_UNKNOWN;
+ base = of_iomap(np, 0);
+ if (!base) {
+ of_node_put(np);
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+ rev = readl_relaxed(base + IMX6Q_ANALOG_DIGPROG);
+ iounmap(base);
+ of_node_put(np);
+ }
+
+ switch (rev & 0xff) {
+ case 0:
+ return IMX_CHIP_REVISION_1_0;
+ case 1:
+ return IMX_CHIP_REVISION_1_1;
+ case 2:
+ return IMX_CHIP_REVISION_1_2;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+}
+
void imx6q_restart(char mode, const char *cmd)
{
struct device_node *np;
@@ -117,6 +151,17 @@ static void __init imx6q_sabrelite_init(void)
imx6q_sabrelite_cko1_setup();
}
+static void __init imx6q_1588_init(void)
+{
+ struct regmap *gpr;
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr))
+ regmap_update_bits(gpr, 0x4, 1 << 21, 1 << 21);
+ else
+ pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+
+}
static void __init imx6q_usb_init(void)
{
struct regmap *anatop;
@@ -153,6 +198,7 @@ static void __init imx6q_init_machine(void)
imx6q_pm_init();
imx6q_usb_init();
+ imx6q_1588_init();
}
static struct cpuidle_driver imx6q_cpuidle_driver = {
@@ -192,6 +238,7 @@ static void __init imx6q_timer_init(void)
{
mx6q_clocks_init();
twd_local_timer_of_register();
+ imx_print_silicon_rev("i.MX6Q", imx6q_revision());
}
static struct sys_timer imx6q_timer = {
diff --git a/arch/arm/mach-imx/mx6q.h b/arch/arm/mach-imx/mx6q.h
index f7e7dbac8f4b..19d3f54db5af 100644
--- a/arch/arm/mach-imx/mx6q.h
+++ b/arch/arm/mach-imx/mx6q.h
@@ -27,9 +27,5 @@
#define MX6Q_CCM_SIZE 0x4000
#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
#define MX6Q_ANATOP_SIZE 0x1000
-#define MX6Q_UART2_BASE_ADDR 0x021e8000
-#define MX6Q_UART2_SIZE 0x4000
-#define MX6Q_UART4_BASE_ADDR 0x021f0000
-#define MX6Q_UART4_SIZE 0x4000
#endif /* __MACH_MX6Q_H__ */
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index d018ad4bcc3c..503d7dd944ff 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -46,6 +46,11 @@ config MACH_GURUPLUG
config ARCH_KIRKWOOD_DT
bool "Marvell Kirkwood Flattened Device Tree"
+ select POWER_SUPPLY
+ select POWER_RESET
+ select POWER_RESET_GPIO
+ select REGULATOR
+ select REGULATOR_FIXED_VOLTAGE
select USE_OF
help
Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-kirkwood/board-dnskw.c b/arch/arm/mach-kirkwood/board-dnskw.c
index 43d16d6714b8..a1aa87f09180 100644
--- a/arch/arm/mach-kirkwood/board-dnskw.c
+++ b/arch/arm/mach-kirkwood/board-dnskw.c
@@ -17,51 +17,11 @@
#include <linux/mv643xx_eth.h>
#include <linux/gpio.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data dnskw_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8),
};
-static unsigned int dnskw_mpp_config[] __initdata = {
- MPP13_UART1_TXD, /* Custom ... */
- MPP14_UART1_RXD, /* ... Controller (DNS-320 only) */
- MPP20_SATA1_ACTn, /* LED: White Right HDD */
- MPP21_SATA0_ACTn, /* LED: White Left HDD */
- MPP24_GPIO,
- MPP25_GPIO,
- MPP26_GPIO, /* LED: Power */
- MPP27_GPIO, /* LED: Red Right HDD */
- MPP28_GPIO, /* LED: Red Left HDD */
- MPP29_GPIO, /* LED: Red USB (DNS-325 only) */
- MPP30_GPIO,
- MPP31_GPIO,
- MPP32_GPIO,
- MPP33_GPO,
- MPP34_GPIO, /* Button: Front power */
- MPP35_GPIO, /* LED: Red USB (DNS-320 only) */
- MPP36_GPIO, /* Power: Turn off board */
- MPP37_GPIO, /* Power: Turn back on after power failure */
- MPP38_GPIO,
- MPP39_GPIO, /* Power: SATA0 */
- MPP40_GPIO, /* Power: SATA1 */
- MPP41_GPIO, /* SATA0 present */
- MPP42_GPIO, /* SATA1 present */
- MPP43_GPIO, /* LED: White USB */
- MPP44_GPIO, /* Fan: Tachometer Pin */
- MPP45_GPIO, /* Fan: high speed */
- MPP46_GPIO, /* Fan: low speed */
- MPP47_GPIO, /* Button: Back unmount */
- MPP48_GPIO, /* Button: Back reset */
- MPP49_GPIO, /* Temp Alarm (DNS-325) Pin of U5 (DNS-320) */
- 0
-};
-
-static void dnskw_power_off(void)
-{
- gpio_set_value(36, 1);
-}
-
/* Register any GPIO for output and set the value */
static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
{
@@ -76,22 +36,8 @@ static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
void __init dnskw_init(void)
{
- kirkwood_mpp_conf(dnskw_mpp_config);
-
- kirkwood_ehci_init();
kirkwood_ge00_init(&dnskw_ge00_data);
- /* Register power-off GPIO. */
- if (gpio_request(36, "dnskw:power:off") == 0
- && gpio_direction_output(36, 0) == 0)
- pm_power_off = dnskw_power_off;
- else
- pr_err("dnskw: failed to configure power-off GPIO\n");
-
- /* Ensure power is supplied to both HDDs */
- dnskw_gpio_register(39, "dnskw:power:sata0", 1);
- dnskw_gpio_register(40, "dnskw:power:sata1", 1);
-
/* Set NAS to turn back on after a power failure */
dnskw_gpio_register(37, "dnskw:power:recover", 1);
}
diff --git a/arch/arm/mach-kirkwood/board-dockstar.c b/arch/arm/mach-kirkwood/board-dockstar.c
index 6912882b0aa9..d7196db33984 100644
--- a/arch/arm/mach-kirkwood/board-dockstar.c
+++ b/arch/arm/mach-kirkwood/board-dockstar.c
@@ -17,32 +17,16 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data dockstar_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
};
-static unsigned int dockstar_mpp_config[] __initdata = {
- MPP29_GPIO, /* USB Power Enable */
- MPP46_GPIO, /* LED green */
- MPP47_GPIO, /* LED orange */
- 0
-};
-
void __init dockstar_dt_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(dockstar_mpp_config);
-
- if (gpio_request(29, "USB Power Enable") != 0 ||
- gpio_direction_output(29, 1) != 0)
- pr_err("can't setup GPIO 29 (USB Power Enable)\n");
- kirkwood_ehci_init();
-
kirkwood_ge00_init(&dockstar_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c
index 8a8ebe09e512..08248e24ffcd 100644
--- a/arch/arm/mach-kirkwood/board-dreamplug.c
+++ b/arch/arm/mach-kirkwood/board-dreamplug.c
@@ -17,7 +17,6 @@
#include <linux/gpio.h>
#include <linux/platform_data/mmc-mvsdio.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data dreamplug_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
@@ -31,25 +30,11 @@ static struct mvsdio_platform_data dreamplug_mvsdio_data = {
/* unfortunately the CD signal has not been connected */
};
-static unsigned int dreamplug_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP47_GPIO, /* Bluetooth LED */
- MPP48_GPIO, /* Wifi LED */
- MPP49_GPIO, /* Wifi AP LED */
- 0
-};
-
void __init dreamplug_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(dreamplug_mpp_config);
-
- kirkwood_ehci_init();
kirkwood_ge00_init(&dreamplug_ge00_data);
kirkwood_ge01_init(&dreamplug_ge01_data);
kirkwood_sdio_init(&dreamplug_mvsdio_data);
diff --git a/arch/arm/mach-kirkwood/board-goflexnet.c b/arch/arm/mach-kirkwood/board-goflexnet.c
index 5dcd0d62aa42..9db979aec82e 100644
--- a/arch/arm/mach-kirkwood/board-goflexnet.c
+++ b/arch/arm/mach-kirkwood/board-goflexnet.c
@@ -19,40 +19,16 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data goflexnet_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
};
-static unsigned int goflexnet_mpp_config[] __initdata = {
- MPP29_GPIO, /* USB Power Enable */
- MPP47_GPIO, /* LED Orange */
- MPP46_GPIO, /* LED Green */
- MPP45_GPIO, /* LED Left Capacity 3 */
- MPP44_GPIO, /* LED Left Capacity 2 */
- MPP43_GPIO, /* LED Left Capacity 1 */
- MPP42_GPIO, /* LED Left Capacity 0 */
- MPP41_GPIO, /* LED Right Capacity 3 */
- MPP40_GPIO, /* LED Right Capacity 2 */
- MPP39_GPIO, /* LED Right Capacity 1 */
- MPP38_GPIO, /* LED Right Capacity 0 */
- 0
-};
-
void __init goflexnet_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(goflexnet_mpp_config);
-
- if (gpio_request(29, "USB Power Enable") != 0 ||
- gpio_direction_output(29, 1) != 0)
- pr_err("can't setup GPIO 29 (USB Power Enable)\n");
- kirkwood_ehci_init();
-
kirkwood_ge00_init(&goflexnet_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-ib62x0.c b/arch/arm/mach-kirkwood/board-ib62x0.c
index 6d3a56421142..9f6f496380d8 100644
--- a/arch/arm/mach-kirkwood/board-ib62x0.c
+++ b/arch/arm/mach-kirkwood/board-ib62x0.c
@@ -14,52 +14,17 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
#include <linux/input.h>
#include "common.h"
-#include "mpp.h"
-
-#define IB62X0_GPIO_POWER_OFF 24
static struct mv643xx_eth_platform_data ib62x0_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8),
};
-static unsigned int ib62x0_mpp_config[] __initdata = {
- MPP0_NF_IO2,
- MPP1_NF_IO3,
- MPP2_NF_IO4,
- MPP3_NF_IO5,
- MPP4_NF_IO6,
- MPP5_NF_IO7,
- MPP18_NF_IO0,
- MPP19_NF_IO1,
- MPP22_GPIO, /* OS LED red */
- MPP24_GPIO, /* Power off device */
- MPP25_GPIO, /* OS LED green */
- MPP27_GPIO, /* USB transfer LED */
- MPP28_GPIO, /* Reset button */
- MPP29_GPIO, /* USB Copy button */
- 0
-};
-
-static void ib62x0_power_off(void)
-{
- gpio_set_value(IB62X0_GPIO_POWER_OFF, 1);
-}
-
void __init ib62x0_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(ib62x0_mpp_config);
-
- kirkwood_ehci_init();
kirkwood_ge00_init(&ib62x0_ge00_data);
- if (gpio_request(IB62X0_GPIO_POWER_OFF, "ib62x0:power:off") == 0 &&
- gpio_direction_output(IB62X0_GPIO_POWER_OFF, 0) == 0)
- pm_power_off = ib62x0_power_off;
- else
- pr_err("board-ib62x0: failed to configure power-off GPIO\n");
}
diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c
index 24f5aa7f698b..c8ebde4919e2 100644
--- a/arch/arm/mach-kirkwood/board-iconnect.c
+++ b/arch/arm/mach-kirkwood/board-iconnect.c
@@ -13,31 +13,13 @@
#include <linux/of.h>
#include <linux/mv643xx_eth.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data iconnect_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(11),
};
-static unsigned int iconnect_mpp_config[] __initdata = {
- MPP12_GPIO,
- MPP35_GPIO,
- MPP41_GPIO,
- MPP42_GPIO,
- MPP43_GPIO,
- MPP44_GPIO,
- MPP45_GPIO,
- MPP46_GPIO,
- MPP47_GPIO,
- MPP48_GPIO,
- 0
-};
-
void __init iconnect_init(void)
{
- kirkwood_mpp_conf(iconnect_mpp_config);
-
- kirkwood_ehci_init();
kirkwood_ge00_init(&iconnect_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
index e4ed62c28f54..f655b2637b0e 100644
--- a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+++ b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
@@ -13,7 +13,6 @@
#include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_NONE,
@@ -21,35 +20,10 @@ static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
.duplex = DUPLEX_FULL,
};
-static unsigned int iomega_ix2_200_mpp_config[] __initdata = {
- MPP12_GPIO, /* Reset Button */
- MPP14_GPIO, /* Power Button */
- MPP15_GPIO, /* Backup LED (blue) */
- MPP16_GPIO, /* Power LED (white) */
- MPP35_GPIO, /* OTB Button */
- MPP36_GPIO, /* Rebuild LED (white) */
- MPP37_GPIO, /* Health LED (red) */
- MPP38_GPIO, /* SATA LED brightness control 1 */
- MPP39_GPIO, /* SATA LED brightness control 2 */
- MPP40_GPIO, /* Backup LED brightness control 1 */
- MPP41_GPIO, /* Backup LED brightness control 2 */
- MPP42_GPIO, /* Power LED brightness control 1 */
- MPP43_GPIO, /* Power LED brightness control 2 */
- MPP44_GPIO, /* Health LED brightness control 1 */
- MPP45_GPIO, /* Health LED brightness control 2 */
- MPP46_GPIO, /* Rebuild LED brightness control 1 */
- MPP47_GPIO, /* Rebuild LED brightness control 2 */
- 0
-};
-
void __init iomega_ix2_200_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(iomega_ix2_200_mpp_config);
-
- kirkwood_ehci_init();
-
kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-km_kirkwood.c b/arch/arm/mach-kirkwood/board-km_kirkwood.c
index f7d32834b757..44e4605ba0bf 100644
--- a/arch/arm/mach-kirkwood/board-km_kirkwood.c
+++ b/arch/arm/mach-kirkwood/board-km_kirkwood.c
@@ -18,27 +18,15 @@
#include <linux/clk.h>
#include <linux/clk-private.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data km_kirkwood_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
};
-static unsigned int km_kirkwood_mpp_config[] __initdata = {
- MPP8_GPIO, /* I2C SDA */
- MPP9_GPIO, /* I2C SCL */
- 0
-};
-
void __init km_kirkwood_init(void)
{
struct clk *sata_clk;
/*
- * Basic setup. Needs to be called early.
- */
- kirkwood_mpp_conf(km_kirkwood_mpp_config);
-
- /*
* Our variant of kirkwood (integrated in the Bobcat) hangs on accessing
* SATA bits (14-15) of the Clock Gating Control Register. Since these
* devices are also not present in this variant, their clocks get
@@ -52,6 +40,5 @@ void __init km_kirkwood_init(void)
if (!IS_ERR(sata_clk))
sata_clk->flags |= CLK_IGNORE_UNUSED;
- kirkwood_ehci_init();
kirkwood_ge00_init(&km_kirkwood_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-lsxl.c b/arch/arm/mach-kirkwood/board-lsxl.c
index 7e18cad9b796..4ec8b7ae784a 100644
--- a/arch/arm/mach-kirkwood/board-lsxl.c
+++ b/arch/arm/mach-kirkwood/board-lsxl.c
@@ -15,9 +15,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
#include "common.h"
-#include "mpp.h"
static struct mv643xx_eth_platform_data lsxl_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
@@ -27,23 +25,6 @@ static struct mv643xx_eth_platform_data lsxl_ge01_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8),
};
-static unsigned int lsxl_mpp_config[] __initdata = {
- MPP10_GPO, /* HDD Power Enable */
- MPP11_GPIO, /* USB Vbus Enable */
- MPP18_GPO, /* FAN High Enable# */
- MPP19_GPO, /* FAN Low Enable# */
- MPP36_GPIO, /* Function Blue LED */
- MPP37_GPIO, /* Alarm LED */
- MPP38_GPIO, /* Info LED */
- MPP39_GPIO, /* Power LED */
- MPP40_GPIO, /* Fan Lock */
- MPP41_GPIO, /* Function Button */
- MPP42_GPIO, /* Power Switch */
- MPP43_GPIO, /* Power Auto Switch */
- MPP48_GPIO, /* Function Red LED */
- 0
-};
-
/*
* On the LS-XHL/LS-CHLv2, the shutdown process is following:
* - Userland monitors key events until the power switch goes to off position
@@ -57,21 +38,12 @@ static void lsxl_power_off(void)
kirkwood_restart('h', NULL);
}
-#define LSXL_GPIO_HDD_POWER 10
-#define LSXL_GPIO_USB_POWER 11
-
void __init lsxl_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(lsxl_mpp_config);
-
- /* usb and sata power on */
- gpio_set_value(LSXL_GPIO_USB_POWER, 1);
- gpio_set_value(LSXL_GPIO_HDD_POWER, 1);
- kirkwood_ehci_init();
kirkwood_ge00_init(&lsxl_ge00_data);
kirkwood_ge01_init(&lsxl_ge01_data);
diff --git a/arch/arm/mach-kirkwood/board-mplcec4.c b/arch/arm/mach-kirkwood/board-mplcec4.c
index e78a227468e6..56bfe5a1605a 100644
--- a/arch/arm/mach-kirkwood/board-mplcec4.c
+++ b/arch/arm/mach-kirkwood/board-mplcec4.c
@@ -24,52 +24,16 @@ static struct mv643xx_eth_platform_data mplcec4_ge01_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(2),
};
-static unsigned int mplcec4_mpp_config[] __initdata = {
- MPP0_NF_IO2,
- MPP1_NF_IO3,
- MPP2_NF_IO4,
- MPP3_NF_IO5,
- MPP4_NF_IO6,
- MPP5_NF_IO7,
- MPP6_SYSRST_OUTn,
- MPP7_GPO, /* Status LED Green High Active */
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP12_SD_CLK,
- MPP13_SD_CMD, /* Alt UART1_TXD */
- MPP14_SD_D0, /* Alt UART1_RXD */
- MPP15_SD_D1,
- MPP16_SD_D2,
- MPP17_SD_D3,
- MPP18_NF_IO0,
- MPP19_NF_IO1,
- MPP28_GPIO, /* Input SYS_POR_DET (active High) */
- MPP29_GPIO, /* Input SYS_RTC_INT (active High) */
- MPP34_SATA1_ACTn,
- MPP35_SATA0_ACTn,
- MPP40_GPIO, /* LED User1 orange */
- MPP41_GPIO, /* LED User1 green */
- MPP44_GPIO, /* LED User0 orange */
- MPP45_GPIO, /* LED User0 green */
- MPP46_GPIO, /* Status LED Yellow High Active */
- MPP47_GPIO, /* SD_CD# (in/IRQ)*/
- 0
-};
-
-
static struct mvsdio_platform_data mplcec4_mvsdio_data = {
.gpio_card_detect = 47, /* MPP47 used as SD card detect */
};
-
void __init mplcec4_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_mpp_conf(mplcec4_mpp_config);
- kirkwood_ehci_init();
kirkwood_ge00_init(&mplcec4_ge00_data);
kirkwood_ge01_init(&mplcec4_ge01_data);
kirkwood_sdio_init(&mplcec4_mvsdio_data);
diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
index 78596c4f76d2..8821720ab5a4 100644
--- a/arch/arm/mach-kirkwood/board-ns2.c
+++ b/arch/arm/mach-kirkwood/board-ns2.c
@@ -73,7 +73,6 @@ void __init ns2_init(void)
*/
kirkwood_mpp_conf(ns2_mpp_config);
- kirkwood_ehci_init();
if (of_machine_is_compatible("lacie,netspace_lite_v2") ||
of_machine_is_compatible("lacie,netspace_mini_v2"))
ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c
index 027ce83f3fe5..f58d2e1a4042 100644
--- a/arch/arm/mach-kirkwood/board-nsa310.c
+++ b/arch/arm/mach-kirkwood/board-nsa310.c
@@ -85,10 +85,6 @@ void __init nsa310_init(void)
nsa310_gpio_init();
- /* this can be removed once the mainline kirkwood.dtsi gets
- * the ehci configuration by default */
- kirkwood_ehci_init();
-
kirkwood_pcie_id(&dev, &rev);
i2c_register_board_info(0, ARRAY_AND_SIZE(nsa310_i2c_info));
diff --git a/arch/arm/mach-kirkwood/board-openblocks_a6.c b/arch/arm/mach-kirkwood/board-openblocks_a6.c
index e807e8cfdd44..815fc6451d52 100644
--- a/arch/arm/mach-kirkwood/board-openblocks_a6.c
+++ b/arch/arm/mach-kirkwood/board-openblocks_a6.c
@@ -55,8 +55,8 @@ static unsigned int openblocks_a6_mpp_config[] __initdata = {
MPP38_GPIO, /* INIT */
MPP39_GPIO, /* USB OC */
MPP41_GPIO, /* LED: Red */
- MPP42_GPIO, /* LED: Yellow */
- MPP43_GPIO, /* LED: Green */
+ MPP42_GPIO, /* LED: Green */
+ MPP43_GPIO, /* LED: Yellow */
0,
};
@@ -66,6 +66,5 @@ void __init openblocks_a6_init(void)
* Basic setup. Needs to be called early.
*/
kirkwood_mpp_conf(openblocks_a6_mpp_config);
- kirkwood_ehci_init();
kirkwood_ge00_init(&openblocks_ge00_data);
}
diff --git a/arch/arm/mach-kirkwood/board-ts219.c b/arch/arm/mach-kirkwood/board-ts219.c
index f3bfedae3a20..acb0187c7ee1 100644
--- a/arch/arm/mach-kirkwood/board-ts219.c
+++ b/arch/arm/mach-kirkwood/board-ts219.c
@@ -23,47 +23,21 @@
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
#include "common.h"
-#include "mpp.h"
#include "tsx1x-common.h"
static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8),
};
-static unsigned int qnap_ts219_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP4_SATA1_ACTn,
- MPP5_SATA0_ACTn,
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP13_UART1_TXD, /* PIC controller */
- MPP14_UART1_RXD, /* PIC controller */
- MPP15_GPIO, /* USB Copy button (on devices with 88F6281) */
- MPP16_GPIO, /* Reset button (on devices with 88F6281) */
- MPP36_GPIO, /* RAM: 0: 256 MB, 1: 512 MB */
- MPP37_GPIO, /* Reset button (on devices with 88F6282) */
- MPP43_GPIO, /* USB Copy button (on devices with 88F6282) */
- MPP44_GPIO, /* Board ID: 0: TS-11x, 1: TS-21x */
- 0
-};
-
void __init qnap_dt_ts219_init(void)
{
u32 dev, rev;
- kirkwood_mpp_conf(qnap_ts219_mpp_config);
-
kirkwood_pcie_id(&dev, &rev);
if (dev == MV88F6282_DEV_ID)
qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
kirkwood_ge00_init(&qnap_ts219_ge00_data);
- kirkwood_ehci_init();
pm_power_off = qnap_tsx1x_power_off;
}
diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c
index e2ec9d891fe3..15e69fcde9f4 100644
--- a/arch/arm/mach-kirkwood/board-usi_topkick.c
+++ b/arch/arm/mach-kirkwood/board-usi_topkick.c
@@ -76,7 +76,6 @@ void __init usi_topkick_init(void)
/* SATA0 power enable */
gpio_set_value(TOPKICK_SATA0_PWR_ENABLE, 1);
- kirkwood_ehci_init();
kirkwood_ge00_init(&topkick_ge00_data);
kirkwood_sdio_init(&topkick_mvsdio_data);
}
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 4748ec551a68..98070370d602 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -100,6 +100,25 @@ static struct fb_videomode apx4devkit_video_modes[] = {
},
};
+static struct fb_videomode apf28dev_video_modes[] = {
+ {
+ .name = "LW700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 30303, /* picosecond */
+ .left_margin = 96,
+ .right_margin = 96, /* at least 3 & 1 */
+ .upper_margin = 0x14,
+ .lower_margin = 0x15,
+ .hsync_len = 64,
+ .vsync_len = 4,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
+ FB_SYNC_DATA_ENABLE_HIGH_ACT |
+ FB_SYNC_DOTCLK_FAILING_ACT,
+ },
+};
+
static struct mxsfb_platform_data mxsfb_pdata __initdata;
/*
@@ -160,6 +179,7 @@ static struct sys_timer imx28_timer = {
enum mac_oui {
OUI_FSL,
OUI_DENX,
+ OUI_CRYSTALFONTZ,
};
static void __init update_fec_mac_prop(enum mac_oui oui)
@@ -175,8 +195,12 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
if (!np)
return;
+
from = np;
+ if (of_get_property(np, "local-mac-address", NULL))
+ continue;
+
newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
if (!newmac)
return;
@@ -205,6 +229,11 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
macaddr[1] = 0xe5;
macaddr[2] = 0x4e;
break;
+ case OUI_CRYSTALFONTZ:
+ macaddr[0] = 0x58;
+ macaddr[1] = 0xb9;
+ macaddr[2] = 0xe1;
+ break;
}
val = ocotp[i];
macaddr[3] = (val >> 16) & 0xff;
@@ -261,6 +290,11 @@ static void __init m28evk_init(void)
mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
}
+static void __init sc_sps1_init(void)
+{
+ enable_clk_enet_out();
+}
+
static int apx4devkit_phy_fixup(struct phy_device *phy)
{
phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -355,6 +389,22 @@ static void __init tx28_post_init(void)
pinctrl_put(pctl);
}
+static void __init cfa10049_init(void)
+{
+ enable_clk_enet_out();
+ update_fec_mac_prop(OUI_CRYSTALFONTZ);
+}
+
+static void __init apf28_init(void)
+{
+ enable_clk_enet_out();
+
+ mxsfb_pdata.mode_list = apf28dev_video_modes;
+ mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes);
+ mxsfb_pdata.default_bpp = 16;
+ mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT;
+}
+
static void __init mxs_machine_init(void)
{
if (of_machine_is_compatible("fsl,imx28-evk"))
@@ -365,6 +415,12 @@ static void __init mxs_machine_init(void)
m28evk_init();
else if (of_machine_is_compatible("bluegiga,apx4devkit"))
apx4devkit_init();
+ else if (of_machine_is_compatible("crystalfontz,cfa10049"))
+ cfa10049_init();
+ else if (of_machine_is_compatible("armadeus,imx28-apf28"))
+ apf28_init();
+ else if (of_machine_is_compatible("schulercontrol,imx28-sps1"))
+ sc_sps1_init();
of_platform_populate(NULL, of_default_bus_match_table,
mxs_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
index 7c3792613392..856f4c796061 100644
--- a/arch/arm/mach-mxs/timer.c
+++ b/arch/arm/mach-mxs/timer.c
@@ -29,6 +29,7 @@
#include <linux/of_irq.h>
#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
#include <mach/mxs.h>
#include <mach/common.h>
@@ -233,15 +234,22 @@ static struct clocksource clocksource_mxs = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+static u32 notrace mxs_read_sched_clock_v2(void)
+{
+ return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
+}
+
static int __init mxs_clocksource_init(struct clk *timer_clk)
{
unsigned int c = clk_get_rate(timer_clk);
if (timrot_is_v1())
clocksource_register_hz(&clocksource_mxs, c);
- else
+ else {
clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
+ setup_sched_clock(mxs_read_sched_clock_v2, 32, c);
+ }
return 0;
}
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
index e4cfb7e5361d..f1c972d87bac 100644
--- a/arch/arm/mach-netx/xc.c
+++ b/arch/arm/mach-netx/xc.c
@@ -136,7 +136,7 @@ int xc_request_firmware(struct xc *x)
if (head->magic != 0x4e657458) {
if (head->magic == 0x5874654e) {
dev_err(x->dev,
- "firmware magic is 'XteN'. Endianess problems?\n");
+ "firmware magic is 'XteN'. Endianness problems?\n");
ret = -ENODEV;
goto exit_release_firmware;
}
diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
index c744946ef022..706dc5727bbe 100644
--- a/arch/arm/mach-nomadik/Kconfig
+++ b/arch/arm/mach-nomadik/Kconfig
@@ -4,7 +4,7 @@ menu "Nomadik boards"
config MACH_NOMADIK_8815NHK
bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
- select HAS_MTU
+ select CLKSRC_NOMADIK_MTU
select NOMADIK_8815
endmenu
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 22ef8a1abe08..5ccdf53c5a9d 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -25,18 +25,16 @@
#include <linux/io.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/pinctrl-nomadik.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
+#include <linux/platform_data/mtd-nomadik-nand.h>
#include <asm/hardware/vic.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
-
-#include <plat/mtu.h>
-
-#include <linux/platform_data/mtd-nomadik-nand.h>
#include <mach/fsmc.h>
+#include <mach/irqs.h>
#include "cpu-8815.h"
@@ -260,7 +258,7 @@ static void __init nomadik_timer_init(void)
src_cr |= SRC_CR_INIT_VAL;
writel(src_cr, io_p2v(NOMADIK_SRC_BASE));
- nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE));
+ nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0);
}
static struct sys_timer nomadik_timer = {
diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h
index a118e615f865..b549d0571548 100644
--- a/arch/arm/mach-nomadik/include/mach/irqs.h
+++ b/arch/arm/mach-nomadik/include/mach/irqs.h
@@ -72,7 +72,7 @@
#define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */
#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_GPIO_OFFSET)
#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_GPIO_OFFSET)
-#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
+#define NOMADIK_NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
/* Following two are used by entry_macro.S, to access our dual-vic */
#define VIC_REG_IRQSR0 0
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 4953cf7a5123..2274bd677efc 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -39,7 +39,7 @@
#include <asm/mach/map.h>
#include <mach/mux.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/tc.h>
#include <mach/irda.h>
#include <linux/platform_data/keypad-omap.h>
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 563ba167bb16..1051935f0aac 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -43,7 +43,7 @@
#include <mach/mux.h>
#include <mach/tc.h>
#include <linux/platform_data/keypad-omap.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/flash.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 584b6fab894b..c33dceb46607 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -37,7 +37,7 @@
#include <mach/flash.h>
#include <mach/mux.h>
#include <mach/tc.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/irda.h>
#include <linux/platform_data/keypad-omap.h>
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index fbc986bfe69e..2948b0ee4be8 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -36,7 +36,7 @@
#include <mach/flash.h>
#include <mach/mux.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/tc.h>
#include <mach/irda.h>
#include <linux/platform_data/keypad-omap.h>
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 60d917a93763..7a05895c0be3 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -38,7 +38,7 @@
#include <mach/flash.h>
#include <mach/mux.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/tc.h>
#include <mach/irda.h>
#include <linux/platform_data/keypad-omap.h>
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 1ebc7e08d6e5..20ed52ae1714 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -36,7 +36,7 @@
#include <mach/flash.h>
#include <mach/mux.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/irda.h>
#include <mach/tc.h>
#include <mach/board-sx1.h>
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 978aed85d328..e190611e4b46 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -25,7 +25,7 @@
#include <linux/device.h>
#include <linux/io.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/tc.h>
#include <mach/irqs.h>
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 5a3b80617a11..499b8accb83d 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,7 +18,7 @@
#include <mach/mux.h>
#include <mach/tc.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "iomap.h"
#include "common.h"
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
index 7ed8c1857d56..77924be37d41 100644
--- a/arch/arm/mach-omap1/lcd_dma.c
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -27,7 +27,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/hardware.h>
#include <mach/lcdc.h>
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index c6d8fdf92e9c..b0d4723c9a90 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/mux.h>
#include "soc.h"
#include <linux/platform_data/asoc-ti-mcbsp.h>
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 66d663a6ef3a..7a7690ab6cb8 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -52,7 +52,7 @@
#include <mach/tc.h>
#include <mach/mux.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <plat/dmtimer.h>
#include <mach/irqs.h>
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 2265e5826883..be0f62bf9037 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -34,6 +34,7 @@ config ARCH_OMAP2
select CPU_V6
select MULTI_IRQ_HANDLER
select SOC_HAS_OMAP2_SDRC
+ select COMMON_CLK
config ARCH_OMAP3
bool "TI OMAP3"
@@ -47,6 +48,7 @@ config ARCH_OMAP3
select PM_OPP if PM
select PM_RUNTIME if CPU_IDLE
select SOC_HAS_OMAP2_SDRC
+ select COMMON_CLK
select USB_ARCH_HAS_EHCI if USB_SUPPORT
config ARCH_OMAP4
@@ -68,6 +70,7 @@ config ARCH_OMAP4
select PM_OPP if PM
select PM_RUNTIME if CPU_IDLE
select USB_ARCH_HAS_EHCI if USB_SUPPORT
+ select COMMON_CLK
config SOC_OMAP5
bool "TI OMAP5"
@@ -77,6 +80,7 @@ config SOC_OMAP5
select CPU_V7
select HAVE_SMP
select SOC_HAS_REALTIME_COUNTER
+ select COMMON_CLK
comment "OMAP Core Type"
depends on ARCH_OMAP2
@@ -111,6 +115,7 @@ config SOC_AM33XX
select ARM_CPU_SUSPEND if PM
select CPU_V7
select MULTI_IRQ_HANDLER
+ select COMMON_CLK
config OMAP_PACKAGE_ZAF
bool
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b455ffc12ebe..a8004f33b7e2 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -160,17 +160,17 @@ obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o clkt2xxx_osc.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o
-obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o
+obj-$(CONFIG_SOC_OMAP2420) += cclock2420_data.o
+obj-$(CONFIG_SOC_OMAP2430) += clock2430.o cclock2430_data.o
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
-obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o clock3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o cclock3xxx_data.o
obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
-obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o
+obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) cclock44xx_data.o
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o
-obj-$(CONFIG_SOC_AM33XX) += clock33xx_data.o
+obj-$(CONFIG_SOC_AM33XX) += cclock33xx_data.o
obj-$(CONFIG_SOC_OMAP5) += $(clock-common)
obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 6601754f9512..7b201546834d 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -31,7 +31,7 @@
#include <asm/mach/map.h>
#include "common.h"
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <video/omapdss.h>
#include <video/omap-panel-tfp410.h>
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index b626dbe6f7bc..9a3878ec2256 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -32,7 +32,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <plat/debug-devices.h>
#include <video/omapdss.h>
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 07005fe40a2a..60529e0b3d67 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -31,7 +31,7 @@
#include <asm/system_info.h>
#include "common.h"
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "gpmc-smc91x.h"
#include "board-rx51.h"
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index b67fe11d0d94..f1d6efe079ca 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -24,7 +24,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "common.h"
#include "mux.h"
diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c
new file mode 100644
index 000000000000..7e5febe456d9
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock2420_data.c
@@ -0,0 +1,1950 @@
+/*
+ * OMAP2420 clock data
+ *
+ * Copyright (C) 2005-2012 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ * Updated to COMMON clk format by Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock2xxx.h"
+#include "opp2xxx.h"
+#include "cm2xxx.h"
+#include "prm2xxx.h"
+#include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "control.h"
+
+#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR
+
+/*
+ * 2420 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ * many cases the parent is selectable. The set parent calls will
+ * also switch sources.
+ *
+ * Several sources are given initial rates which may be wrong, this will
+ * be fixed up in the init func.
+ *
+ * Things are broadly separated below by clock domains. It is
+ * noteworthy that most peripherals have dependencies on multiple clock
+ * domains. Many get their interface clocks from the L4 domain, but get
+ * functional clocks from fixed sources or other core domain derived
+ * clocks.
+ */
+
+DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+static struct clk osc_ck;
+
+static const struct clk_ops osc_ck_ops = {
+ .recalc_rate = &omap2_osc_clk_recalc,
+};
+
+static struct clk_hw_omap osc_ck_hw = {
+ .hw = {
+ .clk = &osc_ck,
+ },
+};
+
+static struct clk osc_ck = {
+ .name = "osc_ck",
+ .ops = &osc_ck_ops,
+ .hw = &osc_ck_hw.hw,
+ .flags = CLK_IS_ROOT,
+};
+
+DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+static struct clk sys_ck;
+
+static const char *sys_ck_parent_names[] = {
+ "osc_ck",
+};
+
+static const struct clk_ops sys_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .recalc_rate = &omap2xxx_sys_clk_recalc,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
+
+static struct dpll_data dpll_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .mult_mask = OMAP24XX_DPLL_MULT_MASK,
+ .div1_mask = OMAP24XX_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_mask = OMAP24XX_EN_DPLL_MASK,
+ .max_multiplier = 1023,
+ .min_divider = 1,
+ .max_divider = 16,
+};
+
+static struct clk dpll_ck;
+
+static const char *dpll_ck_parent_names[] = {
+ "sys_ck",
+};
+
+static const struct clk_ops dpll_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap2_dpllcore_recalc,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap2_reprogram_dpllcore,
+};
+
+static struct clk_hw_omap dpll_ck_hw = {
+ .hw = {
+ .clk = &dpll_ck,
+ },
+ .ops = &clkhwops_omap2xxx_dpll,
+ .dpll_data = &dpll_dd,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+ "dpll_ck",
+};
+
+static const struct clk_ops core_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk aes_ick;
+
+static const char *aes_ick_parent_names[] = {
+ "l4_ck",
+};
+
+static const struct clk_ops aes_ick_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes_ick_hw = {
+ .hw = {
+ .clk = &aes_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_AES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk apll54_ck;
+
+static const struct clk_ops apll54_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_clk_apll54_enable,
+ .disable = &omap2_clk_apll54_disable,
+ .recalc_rate = &omap2_clk_apll54_recalc,
+};
+
+static struct clk_hw_omap apll54_ck_hw = {
+ .hw = {
+ .clk = &apll54_ck,
+ },
+ .ops = &clkhwops_apll54,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
+
+static struct clk apll96_ck;
+
+static const struct clk_ops apll96_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_clk_apll96_enable,
+ .disable = &omap2_clk_apll96_disable,
+ .recalc_rate = &omap2_clk_apll96_recalc,
+};
+
+static struct clk_hw_omap apll96_ck_hw = {
+ .hw = {
+ .clk = &apll96_ck,
+ },
+ .ops = &clkhwops_apll96,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
+
+static struct clk func_96m_ck;
+
+static const char *func_96m_ck_parent_names[] = {
+ "apll96_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(func_96m_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(func_96m_ck, func_96m_ck_parent_names, core_ck_ops);
+
+static struct clk cam_fck;
+
+static const char *cam_fck_parent_names[] = {
+ "func_96m_ck",
+};
+
+static struct clk_hw_omap cam_fck_hw = {
+ .hw = {
+ .clk = &cam_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+ .hw = {
+ .clk = &cam_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk des_ick;
+
+static struct clk_hw_omap des_ick_hw = {
+ .hw = {
+ .clk = &des_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_DES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate dsp_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 6, .val = 6, .flags = RATE_IN_242X },
+ { .div = 8, .val = 8, .flags = RATE_IN_242X },
+ { .div = 12, .val = 12, .flags = RATE_IN_242X },
+ { .div = 0 }
+};
+
+static const struct clksel dsp_fck_clksel[] = {
+ { .parent = &core_ck, .rates = dsp_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *dsp_fck_parent_names[] = {
+ "core_ck",
+};
+
+static const struct clk_ops dsp_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_DSP_MASK,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+ OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+ dsp_fck_parent_names, dsp_fck_ops);
+
+static const struct clksel dsp_ick_clksel[] = {
+ { .parent = &dsp_fck, .rates = dsp_ick_rates },
+ { .parent = NULL },
+};
+
+static const char *dsp_ick_parent_names[] = {
+ "dsp_fck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_ick, "dsp_clkdm", dsp_ick_clksel,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_DSP_IF_MASK,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
+ OMAP2420_EN_DSP_IPI_SHIFT, &clkhwops_iclk_wait,
+ dsp_ick_parent_names, dsp_fck_ops);
+
+static const struct clksel_rate dss1_fck_sys_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate dss1_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 5, .val = 5, .flags = RATE_IN_24XX },
+ { .div = 6, .val = 6, .flags = RATE_IN_24XX },
+ { .div = 8, .val = 8, .flags = RATE_IN_24XX },
+ { .div = 9, .val = 9, .flags = RATE_IN_24XX },
+ { .div = 12, .val = 12, .flags = RATE_IN_24XX },
+ { .div = 16, .val = 16, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel dss1_fck_clksel[] = {
+ { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
+ { .parent = &core_ck, .rates = dss1_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *dss1_fck_parent_names[] = {
+ "sys_ck", "core_ck",
+};
+
+static struct clk dss1_fck;
+
+static const struct clk_ops dss1_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_DSS1_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_DSS1_SHIFT, NULL,
+ dss1_fck_parent_names, dss1_fck_ops);
+
+static const struct clksel_rate dss2_fck_sys_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate dss2_fck_48m_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate func_48m_apll96_rates[] = {
+ { .div = 2, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate func_48m_alt_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel func_48m_clksel[] = {
+ { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
+ { .parent = &alt_ck, .rates = func_48m_alt_rates },
+ { .parent = NULL },
+};
+
+static const char *func_48m_ck_parent_names[] = {
+ "apll96_ck", "alt_ck",
+};
+
+static struct clk func_48m_ck;
+
+static const struct clk_ops func_48m_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap func_48m_ck_hw = {
+ .hw = {
+ .clk = &func_48m_ck,
+ },
+ .clksel = func_48m_clksel,
+ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
+
+static const struct clksel dss2_fck_clksel[] = {
+ { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
+ { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
+ { .parent = NULL },
+};
+
+static const char *dss2_fck_parent_names[] = {
+ "sys_ck", "func_48m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_DSS2_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_DSS2_SHIFT, NULL,
+ dss2_fck_parent_names, dss1_fck_ops);
+
+static const char *func_54m_ck_parent_names[] = {
+ "apll54_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH,
+ 0x0, NULL);
+
+static struct clk dss_54m_fck;
+
+static const char *dss_54m_fck_parent_names[] = {
+ "func_54m_ck",
+};
+
+static struct clk_hw_omap dss_54m_fck_hw = {
+ .hw = {
+ .clk = &dss_54m_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_TV_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
+
+static struct clk dss_ick;
+
+static struct clk_hw_omap dss_ick_hw = {
+ .hw = {
+ .clk = &dss_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk eac_fck;
+
+static struct clk_hw_omap eac_fck_hw = {
+ .hw = {
+ .clk = &eac_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP2420_EN_EAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(eac_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk eac_ick;
+
+static struct clk_hw_omap eac_ick_hw = {
+ .hw = {
+ .clk = &eac_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_EAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(eac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk emul_ck;
+
+static struct clk_hw_omap emul_ck_hw = {
+ .hw = {
+ .clk = &emul_ck,
+ },
+ .enable_reg = OMAP2420_PRCM_CLKEMUL_CTRL,
+ .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
+
+static struct clk fac_fck;
+
+static const char *fac_fck_parent_names[] = {
+ "func_12m_ck",
+};
+
+static struct clk_hw_omap fac_fck_hw = {
+ .hw = {
+ .clk = &fac_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+ .hw = {
+ .clk = &fac_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel gfx_fck_clksel[] = {
+ { .parent = &core_l3_ck, .rates = gfx_l3_rates },
+ { .parent = NULL },
+};
+
+static const char *gfx_2d_fck_parent_names[] = {
+ "core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
+ OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+ OMAP_CLKSEL_GFX_MASK,
+ OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
+ gfx_2d_fck_parent_names, dsp_fck_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
+ OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+ OMAP_CLKSEL_GFX_MASK,
+ OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
+ gfx_2d_fck_parent_names, dsp_fck_ops);
+
+static struct clk gfx_ick;
+
+static const char *gfx_ick_parent_names[] = {
+ "core_l3_ck",
+};
+
+static struct clk_hw_omap gfx_ick_hw = {
+ .hw = {
+ .clk = &gfx_ick,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+ .enable_bit = OMAP_EN_GFX_SHIFT,
+ .clkdm_name = "gfx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk gpios_fck;
+
+static const char *gpios_fck_parent_names[] = {
+ "func_32k_ck",
+};
+
+static struct clk_hw_omap gpios_fck_hw = {
+ .hw = {
+ .clk = &gpios_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wu_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
+
+static struct clk gpios_ick;
+
+static const char *gpios_ick_parent_names[] = {
+ "wu_l4_ick",
+};
+
+static struct clk_hw_omap gpios_ick_hw = {
+ .hw = {
+ .clk = &gpios_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+ .hw = {
+ .clk = &gpmc_fck,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
+
+static const struct clksel_rate gpt_alt_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel omap24xx_gpt_clksel[] = {
+ { .parent = &func_32k_ck, .rates = gpt_32k_rates },
+ { .parent = &sys_ck, .rates = gpt_sys_rates },
+ { .parent = &alt_ck, .rates = gpt_alt_rates },
+ { .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+ "func_32k_ck", "sys_ck", "alt_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT10_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+ .hw = {
+ .clk = &gpt10_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT11_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+ .hw = {
+ .clk = &gpt11_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT12_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+ .hw = {
+ .clk = &gpt12_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clk_ops gpt1_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_GPT1_MASK,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, gpt1_fck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+ .hw = {
+ .clk = &gpt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT2_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+ .hw = {
+ .clk = &gpt2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT3_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+ .hw = {
+ .clk = &gpt3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT4_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+ .hw = {
+ .clk = &gpt4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT5_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+ .hw = {
+ .clk = &gpt5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT6_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+ .hw = {
+ .clk = &gpt6_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT7_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+ .hw = {
+ .clk = &gpt7_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT8_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+ .hw = {
+ .clk = &gpt8_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT9_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+ .hw = {
+ .clk = &gpt9_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk hdq_fck;
+
+static struct clk_hw_omap hdq_fck_hw = {
+ .hw = {
+ .clk = &hdq_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+ .hw = {
+ .clk = &hdq_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c1_fck;
+
+static struct clk_hw_omap i2c1_fck_hw = {
+ .hw = {
+ .clk = &i2c1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP2420_EN_I2C1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+ .hw = {
+ .clk = &i2c1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_I2C1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c2_fck;
+
+static struct clk_hw_omap i2c2_fck_hw = {
+ .hw = {
+ .clk = &i2c2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP2420_EN_I2C2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+ .hw = {
+ .clk = &i2c2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_I2C2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(iva1_ifck, "iva1_clkdm", dsp_fck_clksel,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+ OMAP2420_CLKSEL_IVA_MASK,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+ OMAP2420_EN_IVA_COP_SHIFT, &clkhwops_wait,
+ dsp_fck_parent_names, dsp_fck_ops);
+
+static struct clk iva1_mpu_int_ifck;
+
+static const char *iva1_mpu_int_ifck_parent_names[] = {
+ "iva1_ifck",
+};
+
+static const struct clk_ops iva1_mpu_int_ifck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap_fixed_divisor_recalc,
+};
+
+static struct clk_hw_omap iva1_mpu_int_ifck_hw = {
+ .hw = {
+ .clk = &iva1_mpu_int_ifck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT,
+ .clkdm_name = "iva1_clkdm",
+ .fixed_div = 2,
+};
+
+DEFINE_STRUCT_CLK(iva1_mpu_int_ifck, iva1_mpu_int_ifck_parent_names,
+ iva1_mpu_int_ifck_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+ .hw = {
+ .clk = &mailboxes_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+ { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
+ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+ "func_96m_ck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP1_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+ .hw = {
+ .clk = &mcbsp1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP2_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+ .hw = {
+ .clk = &mcbsp2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static const char *mcspi1_fck_parent_names[] = {
+ "func_48m_ck",
+};
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+ .hw = {
+ .clk = &mcspi1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+ .hw = {
+ .clk = &mcspi1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+ .hw = {
+ .clk = &mcspi2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+ .hw = {
+ .clk = &mcspi2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmc_fck;
+
+static struct clk_hw_omap mmc_fck_hw = {
+ .hw = {
+ .clk = &mmc_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP2420_EN_MMC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmc_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmc_ick;
+
+static struct clk_hw_omap mmc_ick_hw = {
+ .hw = {
+ .clk = &mmc_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_MMC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmc_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_wdt_fck;
+
+static struct clk_hw_omap mpu_wdt_fck_hw = {
+ .hw = {
+ .clk = &mpu_wdt_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk mpu_wdt_ick;
+
+static struct clk_hw_omap mpu_wdt_ick_hw = {
+ .hw = {
+ .clk = &mpu_wdt_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+ .hw = {
+ .clk = &mspro_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+ .hw = {
+ .clk = &mspro_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+ .hw = {
+ .clk = &omapctrl_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk pka_ick;
+
+static struct clk_hw_omap pka_ick_hw = {
+ .hw = {
+ .clk = &pka_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_PKA_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+ .hw = {
+ .clk = &rng_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_RNG_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk sdma_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdma_ick;
+
+static struct clk_hw_omap sdma_ick_hw = {
+ .hw = {
+ .clk = &sdma_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+ .hw = {
+ .clk = &sdrc_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP24XX_AUTO_SDRC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sha_ick;
+
+static struct clk_hw_omap sha_ick_hw = {
+ .hw = {
+ .clk = &sha_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_SHA_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+static struct clk_hw_omap ssi_l4_ick_hw = {
+ .hw = {
+ .clk = &ssi_l4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP24XX_EN_SSI_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 6, .val = 6, .flags = RATE_IN_242X },
+ { .div = 8, .val = 8, .flags = RATE_IN_242X },
+ { .div = 0 }
+};
+
+static const struct clksel ssi_ssr_sst_fck_clksel[] = {
+ { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *ssi_ssr_sst_fck_parent_names[] = {
+ "core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
+ ssi_ssr_sst_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_SSI_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
+ ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
+
+static struct clk sync_32k_ick;
+
+static struct clk_hw_omap sync_32k_ick_hw = {
+ .hw = {
+ .clk = &sync_32k_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_clkout_src_core_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_sys_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_96m_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_54m_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel common_clkout_src_clksel[] = {
+ { .parent = &core_ck, .rates = common_clkout_src_core_rates },
+ { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
+ { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
+ { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
+ { .parent = NULL },
+};
+
+static const char *sys_clkout_src_parent_names[] = {
+ "core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
+ OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
+ OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
+ NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
+ OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
+ OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout2_src, "wkup_clkdm",
+ common_clkout_src_clksel, OMAP2420_PRCM_CLKOUT_CTRL,
+ OMAP2420_CLKOUT2_SOURCE_MASK,
+ OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_EN_SHIFT,
+ NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout2, "sys_clkout2_src", &sys_clkout2_src, 0x0,
+ OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_DIV_SHIFT,
+ OMAP2420_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+ .hw = {
+ .clk = &uart1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+ .hw = {
+ .clk = &uart1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+ .hw = {
+ .clk = &uart2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+ .hw = {
+ .clk = &uart2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart3_fck;
+
+static struct clk_hw_omap uart3_fck_hw = {
+ .hw = {
+ .clk = &uart3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+ .hw = {
+ .clk = &uart3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk usb_fck;
+
+static struct clk_hw_omap usb_fck_hw = {
+ .hw = {
+ .clk = &usb_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP24XX_EN_USB_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel usb_l4_ick_clksel[] = {
+ { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
+ { .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+ "core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_USB_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
+ usb_l4_ick_parent_names, dsp_fck_ops);
+
+static struct clk virt_prcm_set;
+
+static const char *virt_prcm_set_parent_names[] = {
+ "mpu_ck",
+};
+
+static const struct clk_ops virt_prcm_set_ops = {
+ .recalc_rate = &omap2_table_mpu_recalc,
+ .set_rate = &omap2_select_table_rate,
+ .round_rate = &omap2_round_to_table_rate,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
+DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
+
+static const struct clksel_rate vlynq_fck_96m_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_242X },
+ { .div = 0 }
+};
+
+static const struct clksel_rate vlynq_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_242X },
+ { .div = 2, .val = 2, .flags = RATE_IN_242X },
+ { .div = 3, .val = 3, .flags = RATE_IN_242X },
+ { .div = 4, .val = 4, .flags = RATE_IN_242X },
+ { .div = 6, .val = 6, .flags = RATE_IN_242X },
+ { .div = 8, .val = 8, .flags = RATE_IN_242X },
+ { .div = 9, .val = 9, .flags = RATE_IN_242X },
+ { .div = 12, .val = 12, .flags = RATE_IN_242X },
+ { .div = 16, .val = 16, .flags = RATE_IN_242X },
+ { .div = 18, .val = 18, .flags = RATE_IN_242X },
+ { .div = 0 }
+};
+
+static const struct clksel vlynq_fck_clksel[] = {
+ { .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
+ { .parent = &core_ck, .rates = vlynq_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *vlynq_fck_parent_names[] = {
+ "func_96m_ck", "core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(vlynq_fck, "core_l3_clkdm", vlynq_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP2420_CLKSEL_VLYNQ_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP2420_EN_VLYNQ_SHIFT, &clkhwops_wait,
+ vlynq_fck_parent_names, dss1_fck_ops);
+
+static struct clk vlynq_ick;
+
+static struct clk_hw_omap vlynq_ick_hw = {
+ .hw = {
+ .clk = &vlynq_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(vlynq_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+ .hw = {
+ .clk = &wdt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_osc_ck;
+
+static const struct clk_ops wdt1_osc_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
+DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
+
+static struct clk wdt3_fck;
+
+static struct clk_hw_omap wdt3_fck_hw = {
+ .hw = {
+ .clk = &wdt3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP2420_EN_WDT3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt3_ick;
+
+static struct clk_hw_omap wdt3_ick_hw = {
+ .hw = {
+ .clk = &wdt3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_WDT3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt4_fck;
+
+static struct clk_hw_omap wdt4_fck_hw = {
+ .hw = {
+ .clk = &wdt4_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt4_ick;
+
+static struct clk_hw_omap wdt4_ick_hw = {
+ .hw = {
+ .clk = &wdt4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+/*
+ * clkdev integration
+ */
+
+static struct omap_clk omap2420_clks[] = {
+ /* external root sources */
+ CLK(NULL, "func_32k_ck", &func_32k_ck, CK_242X),
+ CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_242X),
+ CLK(NULL, "osc_ck", &osc_ck, CK_242X),
+ CLK(NULL, "sys_ck", &sys_ck, CK_242X),
+ CLK(NULL, "alt_ck", &alt_ck, CK_242X),
+ CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_242X),
+ /* internal analog sources */
+ CLK(NULL, "dpll_ck", &dpll_ck, CK_242X),
+ CLK(NULL, "apll96_ck", &apll96_ck, CK_242X),
+ CLK(NULL, "apll54_ck", &apll54_ck, CK_242X),
+ /* internal prcm root sources */
+ CLK(NULL, "func_54m_ck", &func_54m_ck, CK_242X),
+ CLK(NULL, "core_ck", &core_ck, CK_242X),
+ CLK(NULL, "func_96m_ck", &func_96m_ck, CK_242X),
+ CLK(NULL, "func_48m_ck", &func_48m_ck, CK_242X),
+ CLK(NULL, "func_12m_ck", &func_12m_ck, CK_242X),
+ CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_242X),
+ CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_242X),
+ CLK(NULL, "sys_clkout", &sys_clkout, CK_242X),
+ CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X),
+ CLK(NULL, "sys_clkout2", &sys_clkout2, CK_242X),
+ CLK(NULL, "emul_ck", &emul_ck, CK_242X),
+ /* mpu domain clocks */
+ CLK(NULL, "mpu_ck", &mpu_ck, CK_242X),
+ /* dsp domain clocks */
+ CLK(NULL, "dsp_fck", &dsp_fck, CK_242X),
+ CLK(NULL, "dsp_ick", &dsp_ick, CK_242X),
+ CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X),
+ CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
+ /* GFX domain clocks */
+ CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_242X),
+ CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X),
+ CLK(NULL, "gfx_ick", &gfx_ick, CK_242X),
+ /* DSS domain clocks */
+ CLK("omapdss_dss", "ick", &dss_ick, CK_242X),
+ CLK(NULL, "dss_ick", &dss_ick, CK_242X),
+ CLK(NULL, "dss1_fck", &dss1_fck, CK_242X),
+ CLK(NULL, "dss2_fck", &dss2_fck, CK_242X),
+ CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_242X),
+ /* L3 domain clocks */
+ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X),
+ CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X),
+ CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_242X),
+ /* L4 domain clocks */
+ CLK(NULL, "l4_ck", &l4_ck, CK_242X),
+ CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X),
+ CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_242X),
+ /* virtual meta-group clock */
+ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X),
+ /* general l4 interface ck, multi-parent functional clk */
+ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X),
+ CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X),
+ CLK(NULL, "gpt2_ick", &gpt2_ick, CK_242X),
+ CLK(NULL, "gpt2_fck", &gpt2_fck, CK_242X),
+ CLK(NULL, "gpt3_ick", &gpt3_ick, CK_242X),
+ CLK(NULL, "gpt3_fck", &gpt3_fck, CK_242X),
+ CLK(NULL, "gpt4_ick", &gpt4_ick, CK_242X),
+ CLK(NULL, "gpt4_fck", &gpt4_fck, CK_242X),
+ CLK(NULL, "gpt5_ick", &gpt5_ick, CK_242X),
+ CLK(NULL, "gpt5_fck", &gpt5_fck, CK_242X),
+ CLK(NULL, "gpt6_ick", &gpt6_ick, CK_242X),
+ CLK(NULL, "gpt6_fck", &gpt6_fck, CK_242X),
+ CLK(NULL, "gpt7_ick", &gpt7_ick, CK_242X),
+ CLK(NULL, "gpt7_fck", &gpt7_fck, CK_242X),
+ CLK(NULL, "gpt8_ick", &gpt8_ick, CK_242X),
+ CLK(NULL, "gpt8_fck", &gpt8_fck, CK_242X),
+ CLK(NULL, "gpt9_ick", &gpt9_ick, CK_242X),
+ CLK(NULL, "gpt9_fck", &gpt9_fck, CK_242X),
+ CLK(NULL, "gpt10_ick", &gpt10_ick, CK_242X),
+ CLK(NULL, "gpt10_fck", &gpt10_fck, CK_242X),
+ CLK(NULL, "gpt11_ick", &gpt11_ick, CK_242X),
+ CLK(NULL, "gpt11_fck", &gpt11_fck, CK_242X),
+ CLK(NULL, "gpt12_ick", &gpt12_ick, CK_242X),
+ CLK(NULL, "gpt12_fck", &gpt12_fck, CK_242X),
+ CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_242X),
+ CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_242X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_242X),
+ CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_242X),
+ CLK(NULL, "mcbsp2_ick", &mcbsp2_ick, CK_242X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_242X),
+ CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_242X),
+ CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_242X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_242X),
+ CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_242X),
+ CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_242X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_242X),
+ CLK(NULL, "uart1_ick", &uart1_ick, CK_242X),
+ CLK(NULL, "uart1_fck", &uart1_fck, CK_242X),
+ CLK(NULL, "uart2_ick", &uart2_ick, CK_242X),
+ CLK(NULL, "uart2_fck", &uart2_fck, CK_242X),
+ CLK(NULL, "uart3_ick", &uart3_ick, CK_242X),
+ CLK(NULL, "uart3_fck", &uart3_fck, CK_242X),
+ CLK(NULL, "gpios_ick", &gpios_ick, CK_242X),
+ CLK(NULL, "gpios_fck", &gpios_fck, CK_242X),
+ CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_242X),
+ CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_242X),
+ CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_242X),
+ CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_242X),
+ CLK(NULL, "wdt1_ick", &wdt1_ick, CK_242X),
+ CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_242X),
+ CLK("omap24xxcam", "fck", &cam_fck, CK_242X),
+ CLK(NULL, "cam_fck", &cam_fck, CK_242X),
+ CLK("omap24xxcam", "ick", &cam_ick, CK_242X),
+ CLK(NULL, "cam_ick", &cam_ick, CK_242X),
+ CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_242X),
+ CLK(NULL, "wdt4_ick", &wdt4_ick, CK_242X),
+ CLK(NULL, "wdt4_fck", &wdt4_fck, CK_242X),
+ CLK(NULL, "wdt3_ick", &wdt3_ick, CK_242X),
+ CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X),
+ CLK(NULL, "mspro_ick", &mspro_ick, CK_242X),
+ CLK(NULL, "mspro_fck", &mspro_fck, CK_242X),
+ CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X),
+ CLK(NULL, "mmc_ick", &mmc_ick, CK_242X),
+ CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X),
+ CLK(NULL, "mmc_fck", &mmc_fck, CK_242X),
+ CLK(NULL, "fac_ick", &fac_ick, CK_242X),
+ CLK(NULL, "fac_fck", &fac_fck, CK_242X),
+ CLK(NULL, "eac_ick", &eac_ick, CK_242X),
+ CLK(NULL, "eac_fck", &eac_fck, CK_242X),
+ CLK("omap_hdq.0", "ick", &hdq_ick, CK_242X),
+ CLK(NULL, "hdq_ick", &hdq_ick, CK_242X),
+ CLK("omap_hdq.0", "fck", &hdq_fck, CK_242X),
+ CLK(NULL, "hdq_fck", &hdq_fck, CK_242X),
+ CLK("omap_i2c.1", "ick", &i2c1_ick, CK_242X),
+ CLK(NULL, "i2c1_ick", &i2c1_ick, CK_242X),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_242X),
+ CLK("omap_i2c.2", "ick", &i2c2_ick, CK_242X),
+ CLK(NULL, "i2c2_ick", &i2c2_ick, CK_242X),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_242X),
+ CLK(NULL, "gpmc_fck", &gpmc_fck, CK_242X),
+ CLK(NULL, "sdma_fck", &sdma_fck, CK_242X),
+ CLK(NULL, "sdma_ick", &sdma_ick, CK_242X),
+ CLK(NULL, "sdrc_ick", &sdrc_ick, CK_242X),
+ CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X),
+ CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X),
+ CLK(NULL, "des_ick", &des_ick, CK_242X),
+ CLK("omap-sham", "ick", &sha_ick, CK_242X),
+ CLK(NULL, "sha_ick", &sha_ick, CK_242X),
+ CLK("omap_rng", "ick", &rng_ick, CK_242X),
+ CLK(NULL, "rng_ick", &rng_ick, CK_242X),
+ CLK("omap-aes", "ick", &aes_ick, CK_242X),
+ CLK(NULL, "aes_ick", &aes_ick, CK_242X),
+ CLK(NULL, "pka_ick", &pka_ick, CK_242X),
+ CLK(NULL, "usb_fck", &usb_fck, CK_242X),
+ CLK("musb-hdrc", "fck", &osc_ck, CK_242X),
+ CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_242X),
+ CLK(NULL, "timer_sys_ck", &sys_ck, CK_242X),
+ CLK(NULL, "timer_ext_ck", &alt_ck, CK_242X),
+ CLK(NULL, "cpufreq_ck", &virt_prcm_set, CK_242X),
+};
+
+
+static const char *enable_init_clks[] = {
+ "apll96_ck",
+ "apll54_ck",
+ "sync_32k_ick",
+ "omapctrl_ick",
+ "gpmc_fck",
+ "sdrc_ick",
+};
+
+/*
+ * init code
+ */
+
+int __init omap2420_clk_init(void)
+{
+ struct omap_clk *c;
+
+ prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
+ cpu_mask = RATE_IN_242X;
+ rate_table = omap2420_rate_table;
+
+ omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
+
+ omap2xxx_clkt_vps_check_bootloader_rates();
+
+ for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
+ c++) {
+ clkdev_add(&c->lk);
+ if (!__clk_init(NULL, c->lk.clk))
+ omap2_init_clk_hw_omap_clocks(c->lk.clk);
+ }
+
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
+ (clk_get_rate(&sys_ck) / 1000000),
+ (clk_get_rate(&sys_ck) / 100000) % 10,
+ (clk_get_rate(&dpll_ck) / 1000000),
+ (clk_get_rate(&mpu_ck) / 1000000));
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
new file mode 100644
index 000000000000..eda079b96c6a
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock2430_data.c
@@ -0,0 +1,2065 @@
+/*
+ * OMAP2430 clock data
+ *
+ * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ *
+ * 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/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock2xxx.h"
+#include "opp2xxx.h"
+#include "cm2xxx.h"
+#include "prm2xxx.h"
+#include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "control.h"
+
+#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR
+
+/*
+ * 2430 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ * many cases the parent is selectable. The set parent calls will
+ * also switch sources.
+ *
+ * Several sources are given initial rates which may be wrong, this will
+ * be fixed up in the init func.
+ *
+ * Things are broadly separated below by clock domains. It is
+ * noteworthy that most peripherals have dependencies on multiple clock
+ * domains. Many get their interface clocks from the L4 domain, but get
+ * functional clocks from fixed sources or other core domain derived
+ * clocks.
+ */
+
+DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+static struct clk osc_ck;
+
+static const struct clk_ops osc_ck_ops = {
+ .enable = &omap2_enable_osc_ck,
+ .disable = omap2_disable_osc_ck,
+ .recalc_rate = &omap2_osc_clk_recalc,
+};
+
+static struct clk_hw_omap osc_ck_hw = {
+ .hw = {
+ .clk = &osc_ck,
+ },
+};
+
+static struct clk osc_ck = {
+ .name = "osc_ck",
+ .ops = &osc_ck_ops,
+ .hw = &osc_ck_hw.hw,
+ .flags = CLK_IS_ROOT,
+};
+
+DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+static struct clk sys_ck;
+
+static const char *sys_ck_parent_names[] = {
+ "osc_ck",
+};
+
+static const struct clk_ops sys_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .recalc_rate = &omap2xxx_sys_clk_recalc,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
+
+static struct dpll_data dpll_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .mult_mask = OMAP24XX_DPLL_MULT_MASK,
+ .div1_mask = OMAP24XX_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_mask = OMAP24XX_EN_DPLL_MASK,
+ .max_multiplier = 1023,
+ .min_divider = 1,
+ .max_divider = 16,
+};
+
+static struct clk dpll_ck;
+
+static const char *dpll_ck_parent_names[] = {
+ "sys_ck",
+};
+
+static const struct clk_ops dpll_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap2_dpllcore_recalc,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap2_reprogram_dpllcore,
+};
+
+static struct clk_hw_omap dpll_ck_hw = {
+ .hw = {
+ .clk = &dpll_ck,
+ },
+ .ops = &clkhwops_omap2xxx_dpll,
+ .dpll_data = &dpll_dd,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+ "dpll_ck",
+};
+
+static const struct clk_ops core_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk aes_ick;
+
+static const char *aes_ick_parent_names[] = {
+ "l4_ck",
+};
+
+static const struct clk_ops aes_ick_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes_ick_hw = {
+ .hw = {
+ .clk = &aes_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_AES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk apll54_ck;
+
+static const struct clk_ops apll54_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_clk_apll54_enable,
+ .disable = &omap2_clk_apll54_disable,
+ .recalc_rate = &omap2_clk_apll54_recalc,
+};
+
+static struct clk_hw_omap apll54_ck_hw = {
+ .hw = {
+ .clk = &apll54_ck,
+ },
+ .ops = &clkhwops_apll54,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
+
+static struct clk apll96_ck;
+
+static const struct clk_ops apll96_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_clk_apll96_enable,
+ .disable = &omap2_clk_apll96_disable,
+ .recalc_rate = &omap2_clk_apll96_recalc,
+};
+
+static struct clk_hw_omap apll96_ck_hw = {
+ .hw = {
+ .clk = &apll96_ck,
+ },
+ .ops = &clkhwops_apll96,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
+
+static const char *func_96m_ck_parent_names[] = {
+ "apll96_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_96m_ck, func_96m_ck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP2430_96M_SOURCE_SHIFT,
+ OMAP2430_96M_SOURCE_WIDTH, 0x0, NULL);
+
+static struct clk cam_fck;
+
+static const char *cam_fck_parent_names[] = {
+ "func_96m_ck",
+};
+
+static struct clk_hw_omap cam_fck_hw = {
+ .hw = {
+ .clk = &cam_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+ .hw = {
+ .clk = &cam_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk des_ick;
+
+static struct clk_hw_omap des_ick_hw = {
+ .hw = {
+ .clk = &des_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_DES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate dsp_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel dsp_fck_clksel[] = {
+ { .parent = &core_ck, .rates = dsp_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *dsp_fck_parent_names[] = {
+ "core_ck",
+};
+
+static struct clk dsp_fck;
+
+static const struct clk_ops dsp_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_DSP_MASK,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+ OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+ dsp_fck_parent_names, dsp_fck_ops);
+
+static const struct clksel_rate dss1_fck_sys_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate dss1_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 5, .val = 5, .flags = RATE_IN_24XX },
+ { .div = 6, .val = 6, .flags = RATE_IN_24XX },
+ { .div = 8, .val = 8, .flags = RATE_IN_24XX },
+ { .div = 9, .val = 9, .flags = RATE_IN_24XX },
+ { .div = 12, .val = 12, .flags = RATE_IN_24XX },
+ { .div = 16, .val = 16, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel dss1_fck_clksel[] = {
+ { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
+ { .parent = &core_ck, .rates = dss1_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *dss1_fck_parent_names[] = {
+ "sys_ck", "core_ck",
+};
+
+static const struct clk_ops dss1_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_DSS1_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_DSS1_SHIFT, NULL,
+ dss1_fck_parent_names, dss1_fck_ops);
+
+static const struct clksel_rate dss2_fck_sys_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate dss2_fck_48m_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate func_48m_apll96_rates[] = {
+ { .div = 2, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate func_48m_alt_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel func_48m_clksel[] = {
+ { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
+ { .parent = &alt_ck, .rates = func_48m_alt_rates },
+ { .parent = NULL },
+};
+
+static const char *func_48m_ck_parent_names[] = {
+ "apll96_ck", "alt_ck",
+};
+
+static struct clk func_48m_ck;
+
+static const struct clk_ops func_48m_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap func_48m_ck_hw = {
+ .hw = {
+ .clk = &func_48m_ck,
+ },
+ .clksel = func_48m_clksel,
+ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
+
+static const struct clksel dss2_fck_clksel[] = {
+ { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
+ { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
+ { .parent = NULL },
+};
+
+static const char *dss2_fck_parent_names[] = {
+ "sys_ck", "func_48m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_DSS2_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_DSS2_SHIFT, NULL,
+ dss2_fck_parent_names, dss1_fck_ops);
+
+static const char *func_54m_ck_parent_names[] = {
+ "apll54_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH, 0x0, NULL);
+
+static struct clk dss_54m_fck;
+
+static const char *dss_54m_fck_parent_names[] = {
+ "func_54m_ck",
+};
+
+static struct clk_hw_omap dss_54m_fck_hw = {
+ .hw = {
+ .clk = &dss_54m_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_TV_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
+
+static struct clk dss_ick;
+
+static struct clk_hw_omap dss_ick_hw = {
+ .hw = {
+ .clk = &dss_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk emul_ck;
+
+static struct clk_hw_omap emul_ck_hw = {
+ .hw = {
+ .clk = &emul_ck,
+ },
+ .enable_reg = OMAP2430_PRCM_CLKEMUL_CTRL,
+ .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
+
+static struct clk fac_fck;
+
+static const char *fac_fck_parent_names[] = {
+ "func_12m_ck",
+};
+
+static struct clk_hw_omap fac_fck_hw = {
+ .hw = {
+ .clk = &fac_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+ .hw = {
+ .clk = &fac_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel gfx_fck_clksel[] = {
+ { .parent = &core_l3_ck, .rates = gfx_l3_rates },
+ { .parent = NULL },
+};
+
+static const char *gfx_2d_fck_parent_names[] = {
+ "core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
+ OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+ OMAP_CLKSEL_GFX_MASK,
+ OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
+ gfx_2d_fck_parent_names, dsp_fck_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
+ OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+ OMAP_CLKSEL_GFX_MASK,
+ OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
+ gfx_2d_fck_parent_names, dsp_fck_ops);
+
+static struct clk gfx_ick;
+
+static const char *gfx_ick_parent_names[] = {
+ "core_l3_ck",
+};
+
+static struct clk_hw_omap gfx_ick_hw = {
+ .hw = {
+ .clk = &gfx_ick,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+ .enable_bit = OMAP_EN_GFX_SHIFT,
+ .clkdm_name = "gfx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk gpio5_fck;
+
+static const char *gpio5_fck_parent_names[] = {
+ "func_32k_ck",
+};
+
+static struct clk_hw_omap gpio5_fck_hw = {
+ .hw = {
+ .clk = &gpio5_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk gpio5_ick;
+
+static struct clk_hw_omap gpio5_ick_hw = {
+ .hw = {
+ .clk = &gpio5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk gpios_fck;
+
+static struct clk_hw_omap gpios_fck_hw = {
+ .hw = {
+ .clk = &gpios_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk wu_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
+
+static struct clk gpios_ick;
+
+static const char *gpios_ick_parent_names[] = {
+ "wu_l4_ick",
+};
+
+static struct clk_hw_omap gpios_ick_hw = {
+ .hw = {
+ .clk = &gpios_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+ .hw = {
+ .clk = &gpmc_fck,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
+
+static const struct clksel_rate gpt_alt_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel omap24xx_gpt_clksel[] = {
+ { .parent = &func_32k_ck, .rates = gpt_32k_rates },
+ { .parent = &sys_ck, .rates = gpt_sys_rates },
+ { .parent = &alt_ck, .rates = gpt_alt_rates },
+ { .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+ "func_32k_ck", "sys_ck", "alt_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT10_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+ .hw = {
+ .clk = &gpt10_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT11_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+ .hw = {
+ .clk = &gpt11_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT12_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+ .hw = {
+ .clk = &gpt12_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clk_ops gpt1_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_GPT1_MASK,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, gpt1_fck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+ .hw = {
+ .clk = &gpt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT2_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+ .hw = {
+ .clk = &gpt2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT3_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+ .hw = {
+ .clk = &gpt3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT4_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+ .hw = {
+ .clk = &gpt4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT5_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+ .hw = {
+ .clk = &gpt5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT6_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+ .hw = {
+ .clk = &gpt6_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT7_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+ .hw = {
+ .clk = &gpt7_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk gpt8_fck;
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT8_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+ .hw = {
+ .clk = &gpt8_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+ OMAP24XX_CLKSEL_GPT9_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+ .hw = {
+ .clk = &gpt9_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk hdq_fck;
+
+static struct clk_hw_omap hdq_fck_hw = {
+ .hw = {
+ .clk = &hdq_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+ .hw = {
+ .clk = &hdq_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+ .hw = {
+ .clk = &i2c1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_I2C1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+ .hw = {
+ .clk = &i2c2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP2420_EN_I2C2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2chs1_fck;
+
+static struct clk_hw_omap i2chs1_fck_hw = {
+ .hw = {
+ .clk = &i2chs1_fck,
+ },
+ .ops = &clkhwops_omap2430_i2chs_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_I2CHS1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2chs1_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk i2chs2_fck;
+
+static struct clk_hw_omap i2chs2_fck_hw = {
+ .hw = {
+ .clk = &i2chs2_fck,
+ },
+ .ops = &clkhwops_omap2430_i2chs_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_I2CHS2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2chs2_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk icr_ick;
+
+static struct clk_hw_omap icr_ick_hw = {
+ .hw = {
+ .clk = &icr_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP2430_EN_ICR_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(icr_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel dsp_ick_clksel[] = {
+ { .parent = &dsp_fck, .rates = dsp_ick_rates },
+ { .parent = NULL },
+};
+
+static const char *iva2_1_ick_parent_names[] = {
+ "dsp_fck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(iva2_1_ick, "dsp_clkdm", dsp_ick_clksel,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_DSP_IF_MASK,
+ OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+ OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+ iva2_1_ick_parent_names, dsp_fck_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+ .hw = {
+ .clk = &mailboxes_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+ { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
+ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+ "func_96m_ck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP1_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+ .hw = {
+ .clk = &mcbsp1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP2_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+ .hw = {
+ .clk = &mcbsp2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP3_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ OMAP2430_EN_MCBSP3_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp3_ick;
+
+static struct clk_hw_omap mcbsp3_ick_hw = {
+ .hw = {
+ .clk = &mcbsp3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP4_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ OMAP2430_EN_MCBSP4_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp4_ick;
+
+static struct clk_hw_omap mcbsp4_ick_hw = {
+ .hw = {
+ .clk = &mcbsp4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+ OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP5_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ OMAP2430_EN_MCBSP5_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp5_ick;
+
+static struct clk_hw_omap mcbsp5_ick_hw = {
+ .hw = {
+ .clk = &mcbsp5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp5_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static const char *mcspi1_fck_parent_names[] = {
+ "func_48m_ck",
+};
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+ .hw = {
+ .clk = &mcspi1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+ .hw = {
+ .clk = &mcspi1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+ .hw = {
+ .clk = &mcspi2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+ .hw = {
+ .clk = &mcspi2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi3_fck;
+
+static struct clk_hw_omap mcspi3_fck_hw = {
+ .hw = {
+ .clk = &mcspi3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi3_ick;
+
+static struct clk_hw_omap mcspi3_ick_hw = {
+ .hw = {
+ .clk = &mcspi3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate mdm_ick_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_243X },
+ { .div = 4, .val = 4, .flags = RATE_IN_243X },
+ { .div = 6, .val = 6, .flags = RATE_IN_243X },
+ { .div = 9, .val = 9, .flags = RATE_IN_243X },
+ { .div = 0 }
+};
+
+static const struct clksel mdm_ick_clksel[] = {
+ { .parent = &core_ck, .rates = mdm_ick_core_rates },
+ { .parent = NULL },
+};
+
+static const char *mdm_ick_parent_names[] = {
+ "core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mdm_ick, "mdm_clkdm", mdm_ick_clksel,
+ OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
+ OMAP2430_CLKSEL_MDM_MASK,
+ OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
+ OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
+ &clkhwops_iclk_wait, mdm_ick_parent_names,
+ dsp_fck_ops);
+
+static struct clk mdm_intc_ick;
+
+static struct clk_hw_omap mdm_intc_ick_hw = {
+ .hw = {
+ .clk = &mdm_intc_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mdm_intc_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mdm_osc_ck;
+
+static struct clk_hw_omap mdm_osc_ck_hw = {
+ .hw = {
+ .clk = &mdm_osc_ck,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
+ .enable_bit = OMAP2430_EN_OSC_SHIFT,
+ .clkdm_name = "mdm_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mdm_osc_ck, sys_ck_parent_names, aes_ick_ops);
+
+static struct clk mmchs1_fck;
+
+static struct clk_hw_omap mmchs1_fck_hw = {
+ .hw = {
+ .clk = &mmchs1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchs1_ick;
+
+static struct clk_hw_omap mmchs1_ick_hw = {
+ .hw = {
+ .clk = &mmchs1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmchs2_fck;
+
+static struct clk_hw_omap mmchs2_fck_hw = {
+ .hw = {
+ .clk = &mmchs2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchs2_ick;
+
+static struct clk_hw_omap mmchs2_ick_hw = {
+ .hw = {
+ .clk = &mmchs2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmchsdb1_fck;
+
+static struct clk_hw_omap mmchsdb1_fck_hw = {
+ .hw = {
+ .clk = &mmchsdb1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchsdb1_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchsdb2_fck;
+
+static struct clk_hw_omap mmchsdb2_fck_hw = {
+ .hw = {
+ .clk = &mmchsdb2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchsdb2_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
+ OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_wdt_fck;
+
+static struct clk_hw_omap mpu_wdt_fck_hw = {
+ .hw = {
+ .clk = &mpu_wdt_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk mpu_wdt_ick;
+
+static struct clk_hw_omap mpu_wdt_ick_hw = {
+ .hw = {
+ .clk = &mpu_wdt_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+ .hw = {
+ .clk = &mspro_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+ .hw = {
+ .clk = &mspro_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+ .hw = {
+ .clk = &omapctrl_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk pka_ick;
+
+static struct clk_hw_omap pka_ick_hw = {
+ .hw = {
+ .clk = &pka_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_PKA_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+ .hw = {
+ .clk = &rng_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_RNG_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk sdma_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdma_ick;
+
+static struct clk_hw_omap sdma_ick_hw = {
+ .hw = {
+ .clk = &sdma_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+ .hw = {
+ .clk = &sdrc_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP2430_EN_SDRC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sha_ick;
+
+static struct clk_hw_omap sha_ick_hw = {
+ .hw = {
+ .clk = &sha_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+ .enable_bit = OMAP24XX_EN_SHA_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+static struct clk_hw_omap ssi_l4_ick_hw = {
+ .hw = {
+ .clk = &ssi_l4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP24XX_EN_SSI_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 5, .val = 5, .flags = RATE_IN_243X },
+ { .div = 0 }
+};
+
+static const struct clksel ssi_ssr_sst_fck_clksel[] = {
+ { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
+ { .parent = NULL },
+};
+
+static const char *ssi_ssr_sst_fck_parent_names[] = {
+ "core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
+ ssi_ssr_sst_fck_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_SSI_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
+ ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
+
+static struct clk sync_32k_ick;
+
+static struct clk_hw_omap sync_32k_ick_hw = {
+ .hw = {
+ .clk = &sync_32k_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_clkout_src_core_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_sys_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_96m_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_54m_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel common_clkout_src_clksel[] = {
+ { .parent = &core_ck, .rates = common_clkout_src_core_rates },
+ { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
+ { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
+ { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
+ { .parent = NULL },
+};
+
+static const char *sys_clkout_src_parent_names[] = {
+ "core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
+ OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
+ OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
+ NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
+ OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
+ OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+ .hw = {
+ .clk = &uart1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+ .hw = {
+ .clk = &uart1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+ .hw = {
+ .clk = &uart2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+ .hw = {
+ .clk = &uart2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart3_fck;
+
+static struct clk_hw_omap uart3_fck_hw = {
+ .hw = {
+ .clk = &uart3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+ .hw = {
+ .clk = &uart3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk usb_fck;
+
+static struct clk_hw_omap usb_fck_hw = {
+ .hw = {
+ .clk = &usb_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+ .enable_bit = OMAP24XX_EN_USB_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
+ { .div = 0 }
+};
+
+static const struct clksel usb_l4_ick_clksel[] = {
+ { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
+ { .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+ "core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+ OMAP24XX_CLKSEL_USB_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
+ usb_l4_ick_parent_names, dsp_fck_ops);
+
+static struct clk usbhs_ick;
+
+static struct clk_hw_omap usbhs_ick_hw = {
+ .hw = {
+ .clk = &usbhs_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP2430_EN_USBHS_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhs_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk virt_prcm_set;
+
+static const char *virt_prcm_set_parent_names[] = {
+ "mpu_ck",
+};
+
+static const struct clk_ops virt_prcm_set_ops = {
+ .recalc_rate = &omap2_table_mpu_recalc,
+ .set_rate = &omap2_select_table_rate,
+ .round_rate = &omap2_round_to_table_rate,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
+DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+ .hw = {
+ .clk = &wdt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_osc_ck;
+
+static const struct clk_ops wdt1_osc_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
+DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
+
+static struct clk wdt4_fck;
+
+static struct clk_hw_omap wdt4_fck_hw = {
+ .hw = {
+ .clk = &wdt4_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt4_ick;
+
+static struct clk_hw_omap wdt4_ick_hw = {
+ .hw = {
+ .clk = &wdt4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+/*
+ * clkdev integration
+ */
+
+static struct omap_clk omap2430_clks[] = {
+ /* external root sources */
+ CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X),
+ CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X),
+ CLK(NULL, "osc_ck", &osc_ck, CK_243X),
+ CLK("twl", "fck", &osc_ck, CK_243X),
+ CLK(NULL, "sys_ck", &sys_ck, CK_243X),
+ CLK(NULL, "alt_ck", &alt_ck, CK_243X),
+ CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_243X),
+ /* internal analog sources */
+ CLK(NULL, "dpll_ck", &dpll_ck, CK_243X),
+ CLK(NULL, "apll96_ck", &apll96_ck, CK_243X),
+ CLK(NULL, "apll54_ck", &apll54_ck, CK_243X),
+ /* internal prcm root sources */
+ CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X),
+ CLK(NULL, "core_ck", &core_ck, CK_243X),
+ CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X),
+ CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X),
+ CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X),
+ CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X),
+ CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X),
+ CLK(NULL, "sys_clkout", &sys_clkout, CK_243X),
+ CLK(NULL, "emul_ck", &emul_ck, CK_243X),
+ /* mpu domain clocks */
+ CLK(NULL, "mpu_ck", &mpu_ck, CK_243X),
+ /* dsp domain clocks */
+ CLK(NULL, "dsp_fck", &dsp_fck, CK_243X),
+ CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X),
+ /* GFX domain clocks */
+ CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X),
+ CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_243X),
+ CLK(NULL, "gfx_ick", &gfx_ick, CK_243X),
+ /* Modem domain clocks */
+ CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
+ CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
+ /* DSS domain clocks */
+ CLK("omapdss_dss", "ick", &dss_ick, CK_243X),
+ CLK(NULL, "dss_ick", &dss_ick, CK_243X),
+ CLK(NULL, "dss1_fck", &dss1_fck, CK_243X),
+ CLK(NULL, "dss2_fck", &dss2_fck, CK_243X),
+ CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_243X),
+ /* L3 domain clocks */
+ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X),
+ CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X),
+ CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X),
+ /* L4 domain clocks */
+ CLK(NULL, "l4_ck", &l4_ck, CK_243X),
+ CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X),
+ CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_243X),
+ /* virtual meta-group clock */
+ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X),
+ /* general l4 interface ck, multi-parent functional clk */
+ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X),
+ CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X),
+ CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X),
+ CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X),
+ CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X),
+ CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X),
+ CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X),
+ CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X),
+ CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X),
+ CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X),
+ CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X),
+ CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X),
+ CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X),
+ CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X),
+ CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X),
+ CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X),
+ CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X),
+ CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X),
+ CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X),
+ CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X),
+ CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X),
+ CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X),
+ CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X),
+ CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X),
+ CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X),
+ CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_243X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_243X),
+ CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X),
+ CLK(NULL, "mcbsp2_ick", &mcbsp2_ick, CK_243X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_243X),
+ CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X),
+ CLK(NULL, "mcbsp3_ick", &mcbsp3_ick, CK_243X),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_243X),
+ CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X),
+ CLK(NULL, "mcbsp4_ick", &mcbsp4_ick, CK_243X),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_243X),
+ CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X),
+ CLK(NULL, "mcbsp5_ick", &mcbsp5_ick, CK_243X),
+ CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_243X),
+ CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X),
+ CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_243X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_243X),
+ CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X),
+ CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_243X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_243X),
+ CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X),
+ CLK(NULL, "mcspi3_ick", &mcspi3_ick, CK_243X),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_243X),
+ CLK(NULL, "uart1_ick", &uart1_ick, CK_243X),
+ CLK(NULL, "uart1_fck", &uart1_fck, CK_243X),
+ CLK(NULL, "uart2_ick", &uart2_ick, CK_243X),
+ CLK(NULL, "uart2_fck", &uart2_fck, CK_243X),
+ CLK(NULL, "uart3_ick", &uart3_ick, CK_243X),
+ CLK(NULL, "uart3_fck", &uart3_fck, CK_243X),
+ CLK(NULL, "gpios_ick", &gpios_ick, CK_243X),
+ CLK(NULL, "gpios_fck", &gpios_fck, CK_243X),
+ CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X),
+ CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_243X),
+ CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_243X),
+ CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X),
+ CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X),
+ CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X),
+ CLK(NULL, "icr_ick", &icr_ick, CK_243X),
+ CLK("omap24xxcam", "fck", &cam_fck, CK_243X),
+ CLK(NULL, "cam_fck", &cam_fck, CK_243X),
+ CLK("omap24xxcam", "ick", &cam_ick, CK_243X),
+ CLK(NULL, "cam_ick", &cam_ick, CK_243X),
+ CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X),
+ CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X),
+ CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X),
+ CLK(NULL, "mspro_ick", &mspro_ick, CK_243X),
+ CLK(NULL, "mspro_fck", &mspro_fck, CK_243X),
+ CLK(NULL, "fac_ick", &fac_ick, CK_243X),
+ CLK(NULL, "fac_fck", &fac_fck, CK_243X),
+ CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X),
+ CLK(NULL, "hdq_ick", &hdq_ick, CK_243X),
+ CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X),
+ CLK(NULL, "hdq_fck", &hdq_fck, CK_243X),
+ CLK("omap_i2c.1", "ick", &i2c1_ick, CK_243X),
+ CLK(NULL, "i2c1_ick", &i2c1_ick, CK_243X),
+ CLK(NULL, "i2chs1_fck", &i2chs1_fck, CK_243X),
+ CLK("omap_i2c.2", "ick", &i2c2_ick, CK_243X),
+ CLK(NULL, "i2c2_ick", &i2c2_ick, CK_243X),
+ CLK(NULL, "i2chs2_fck", &i2chs2_fck, CK_243X),
+ CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X),
+ CLK(NULL, "sdma_fck", &sdma_fck, CK_243X),
+ CLK(NULL, "sdma_ick", &sdma_ick, CK_243X),
+ CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X),
+ CLK(NULL, "des_ick", &des_ick, CK_243X),
+ CLK("omap-sham", "ick", &sha_ick, CK_243X),
+ CLK("omap_rng", "ick", &rng_ick, CK_243X),
+ CLK(NULL, "rng_ick", &rng_ick, CK_243X),
+ CLK("omap-aes", "ick", &aes_ick, CK_243X),
+ CLK(NULL, "pka_ick", &pka_ick, CK_243X),
+ CLK(NULL, "usb_fck", &usb_fck, CK_243X),
+ CLK("musb-omap2430", "ick", &usbhs_ick, CK_243X),
+ CLK(NULL, "usbhs_ick", &usbhs_ick, CK_243X),
+ CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_243X),
+ CLK(NULL, "mmchs1_ick", &mmchs1_ick, CK_243X),
+ CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_243X),
+ CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_243X),
+ CLK(NULL, "mmchs2_ick", &mmchs2_ick, CK_243X),
+ CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_243X),
+ CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X),
+ CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X),
+ CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
+ CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
+ CLK(NULL, "mmchsdb1_fck", &mmchsdb1_fck, CK_243X),
+ CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
+ CLK(NULL, "mmchsdb2_fck", &mmchsdb2_fck, CK_243X),
+ CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_243X),
+ CLK(NULL, "timer_sys_ck", &sys_ck, CK_243X),
+ CLK(NULL, "timer_ext_ck", &alt_ck, CK_243X),
+ CLK(NULL, "cpufreq_ck", &virt_prcm_set, CK_243X),
+};
+
+static const char *enable_init_clks[] = {
+ "apll96_ck",
+ "apll54_ck",
+ "sync_32k_ick",
+ "omapctrl_ick",
+ "gpmc_fck",
+ "sdrc_ick",
+};
+
+/*
+ * init code
+ */
+
+int __init omap2430_clk_init(void)
+{
+ struct omap_clk *c;
+
+ prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
+ cpu_mask = RATE_IN_243X;
+ rate_table = omap2430_rate_table;
+
+ omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
+
+ omap2xxx_clkt_vps_check_bootloader_rates();
+
+ for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
+ c++) {
+ clkdev_add(&c->lk);
+ if (!__clk_init(NULL, c->lk.clk))
+ omap2_init_clk_hw_omap_clocks(c->lk.clk);
+ }
+
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
+ (clk_get_rate(&sys_ck) / 1000000),
+ (clk_get_rate(&sys_ck) / 100000) % 10,
+ (clk_get_rate(&dpll_ck) / 1000000),
+ (clk_get_rate(&mpu_ck) / 1000000));
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
new file mode 100644
index 000000000000..ea64ad606759
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock33xx_data.c
@@ -0,0 +1,961 @@
+/*
+ * AM33XX Clock data
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+
+#include "am33xx.h"
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "control.h"
+#include "cm.h"
+#include "cm33xx.h"
+#include "cm-regbits-33xx.h"
+#include "prm.h"
+
+/* Modulemode control */
+#define AM33XX_MODULEMODE_HWCTRL_SHIFT 0
+#define AM33XX_MODULEMODE_SWCTRL_SHIFT 1
+
+/*LIST_HEAD(clocks);*/
+
+/* Root clocks */
+
+/* RTC 32k */
+DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0);
+
+/* On-Chip 32KHz RC OSC */
+DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0);
+
+/* Crystal input clks */
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+/* Oscillator clock */
+/* 19.2, 24, 25 or 26 MHz */
+static const char *sys_clkin_ck_parents[] = {
+ "virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck",
+ "virt_26000000_ck",
+};
+
+/*
+ * sys_clk in: input to the dpll and also used as funtional clock for,
+ * adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
+ *
+ */
+DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
+ AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
+ AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT,
+ AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH,
+ 0, NULL);
+
+/* External clock - 12 MHz */
+DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+/* Module clocks and DPLL outputs */
+
+/* DPLL_CORE */
+static struct dpll_data dpll_core_dd = {
+ .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE,
+ .clk_bypass = &sys_clkin_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = AM33XX_CM_CLKMODE_DPLL_CORE,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE,
+ .mult_mask = AM33XX_DPLL_MULT_MASK,
+ .div1_mask = AM33XX_DPLL_DIV_MASK,
+ .enable_mask = AM33XX_DPLL_EN_MASK,
+ .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+/* CLKDCOLDO output */
+static const char *dpll_core_ck_parents[] = {
+ "sys_clkin_ck",
+};
+
+static struct clk dpll_core_ck;
+
+static const struct clk_ops dpll_core_ck_ops = {
+ .recalc_rate = &omap3_dpll_recalc,
+ .get_parent = &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_core_ck_hw = {
+ .hw = {
+ .clk = &dpll_core_ck,
+ },
+ .dpll_data = &dpll_core_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
+
+static const char *dpll_core_x2_ck_parents[] = {
+ "dpll_core_ck",
+};
+
+static struct clk dpll_core_x2_ck;
+
+static const struct clk_ops dpll_x2_ck_ops = {
+ .recalc_rate = &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll_core_x2_ck_hw = {
+ .hw = {
+ .clk = &dpll_core_x2_ck,
+ },
+ .flags = CLOCK_CLKOUTX2,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+ 0x0, AM33XX_CM_DIV_M4_DPLL_CORE,
+ AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT,
+ AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
+ NULL);
+
+DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+ 0x0, AM33XX_CM_DIV_M5_DPLL_CORE,
+ AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT,
+ AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+ 0x0, AM33XX_CM_DIV_M6_DPLL_CORE,
+ AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT,
+ AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+
+/* DPLL_MPU */
+static struct dpll_data dpll_mpu_dd = {
+ .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU,
+ .clk_bypass = &sys_clkin_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = AM33XX_CM_CLKMODE_DPLL_MPU,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU,
+ .mult_mask = AM33XX_DPLL_MULT_MASK,
+ .div1_mask = AM33XX_DPLL_DIV_MASK,
+ .enable_mask = AM33XX_DPLL_EN_MASK,
+ .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_mpu_ck;
+
+static const struct clk_ops dpll_mpu_ck_ops = {
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+ .recalc_rate = &omap3_dpll_recalc,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .get_parent = &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_mpu_ck_hw = {
+ .hw = {
+ .clk = &dpll_mpu_ck,
+ },
+ .dpll_data = &dpll_mpu_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_mpu_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck,
+ 0x0, AM33XX_CM_DIV_M2_DPLL_MPU, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+ AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+/* DPLL_DDR */
+static struct dpll_data dpll_ddr_dd = {
+ .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DDR,
+ .clk_bypass = &sys_clkin_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = AM33XX_CM_CLKMODE_DPLL_DDR,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .idlest_reg = AM33XX_CM_IDLEST_DPLL_DDR,
+ .mult_mask = AM33XX_DPLL_MULT_MASK,
+ .div1_mask = AM33XX_DPLL_DIV_MASK,
+ .enable_mask = AM33XX_DPLL_EN_MASK,
+ .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_ddr_ck;
+
+static const struct clk_ops dpll_ddr_ck_ops = {
+ .recalc_rate = &omap3_dpll_recalc,
+ .get_parent = &omap2_init_dpll_parent,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+};
+
+static struct clk_hw_omap dpll_ddr_ck_hw = {
+ .hw = {
+ .clk = &dpll_ddr_ck,
+ },
+ .dpll_data = &dpll_ddr_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_ddr_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_ddr_m2_ck, "dpll_ddr_ck", &dpll_ddr_ck,
+ 0x0, AM33XX_CM_DIV_M2_DPLL_DDR,
+ AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+/* emif_fck functional clock */
+DEFINE_CLK_FIXED_FACTOR(dpll_ddr_m2_div2_ck, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck,
+ 0x0, 1, 2);
+
+/* DPLL_DISP */
+static struct dpll_data dpll_disp_dd = {
+ .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DISP,
+ .clk_bypass = &sys_clkin_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = AM33XX_CM_CLKMODE_DPLL_DISP,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .idlest_reg = AM33XX_CM_IDLEST_DPLL_DISP,
+ .mult_mask = AM33XX_DPLL_MULT_MASK,
+ .div1_mask = AM33XX_DPLL_DIV_MASK,
+ .enable_mask = AM33XX_DPLL_EN_MASK,
+ .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_disp_ck;
+
+static struct clk_hw_omap dpll_disp_ck_hw = {
+ .hw = {
+ .clk = &dpll_disp_ck,
+ },
+ .dpll_data = &dpll_disp_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck, 0x0,
+ AM33XX_CM_DIV_M2_DPLL_DISP, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+ AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+/* DPLL_PER */
+static struct dpll_data dpll_per_dd = {
+ .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_PERIPH,
+ .clk_bypass = &sys_clkin_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = AM33XX_CM_CLKMODE_DPLL_PER,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .idlest_reg = AM33XX_CM_IDLEST_DPLL_PER,
+ .mult_mask = AM33XX_DPLL_MULT_PERIPH_MASK,
+ .div1_mask = AM33XX_DPLL_PER_DIV_MASK,
+ .enable_mask = AM33XX_DPLL_EN_MASK,
+ .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+ .flags = DPLL_J_TYPE,
+};
+
+/* CLKDCOLDO */
+static struct clk dpll_per_ck;
+
+static struct clk_hw_omap dpll_per_ck_hw = {
+ .hw = {
+ .clk = &dpll_per_ck,
+ },
+ .dpll_data = &dpll_per_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/* CLKOUT: fdpll/M2 */
+DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
+ AM33XX_CM_DIV_M2_DPLL_PER, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+ AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
+ NULL);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_wkupdm_ck, "dpll_per_m2_ck",
+ &dpll_per_m2_ck, 0x0, 1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_ck, "dpll_per_m2_ck",
+ &dpll_per_m2_ck, 0x0, 1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_core_m4_div2_ck, "dpll_core_m4_ck",
+ &dpll_core_m4_ck, 0x0, 1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(l4_rtc_gclk, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+ 1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(clk_24mhz, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1,
+ 8);
+
+/*
+ * Below clock nodes describes clockdomains derived out
+ * of core clock.
+ */
+static const struct clk_ops clk_ops_null = {
+};
+
+static const char *l3_gclk_parents[] = {
+ "dpll_core_m4_ck"
+};
+
+static struct clk l3_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l3_gclk, NULL);
+DEFINE_STRUCT_CLK(l3_gclk, l3_gclk_parents, clk_ops_null);
+
+static struct clk l4hs_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4hs_gclk, NULL);
+DEFINE_STRUCT_CLK(l4hs_gclk, l3_gclk_parents, clk_ops_null);
+
+static const char *l3s_gclk_parents[] = {
+ "dpll_core_m4_div2_ck"
+};
+
+static struct clk l3s_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l3s_gclk, NULL);
+DEFINE_STRUCT_CLK(l3s_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk l4fw_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4fw_gclk, NULL);
+DEFINE_STRUCT_CLK(l4fw_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk l4ls_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4ls_gclk, NULL);
+DEFINE_STRUCT_CLK(l4ls_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk sysclk_div_ck;
+DEFINE_STRUCT_CLK_HW_OMAP(sysclk_div_ck, NULL);
+DEFINE_STRUCT_CLK(sysclk_div_ck, l3_gclk_parents, clk_ops_null);
+
+/*
+ * In order to match the clock domain with hwmod clockdomain entry,
+ * separate clock nodes is required for the modules which are
+ * directly getting their funtioncal clock from sys_clkin.
+ */
+static struct clk adc_tsc_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(adc_tsc_fck, NULL);
+DEFINE_STRUCT_CLK(adc_tsc_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk dcan0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(dcan0_fck, NULL);
+DEFINE_STRUCT_CLK(dcan0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk dcan1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(dcan1_fck, NULL);
+DEFINE_STRUCT_CLK(dcan1_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk mcasp0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(mcasp0_fck, NULL);
+DEFINE_STRUCT_CLK(mcasp0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk mcasp1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(mcasp1_fck, NULL);
+DEFINE_STRUCT_CLK(mcasp1_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk smartreflex0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(smartreflex0_fck, NULL);
+DEFINE_STRUCT_CLK(smartreflex0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk smartreflex1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL);
+DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
+
+/*
+ * Modules clock nodes
+ *
+ * The following clock leaf nodes are added for the moment because:
+ *
+ * - hwmod data is not present for these modules, either hwmod
+ * control is not required or its not populated.
+ * - Driver code is not yet migrated to use hwmod/runtime pm
+ * - Modules outside kernel access (to disable them by default)
+ *
+ * - debugss
+ * - mmu (gfx domain)
+ * - cefuse
+ * - usbotg_fck (its additional clock and not really a modulemode)
+ * - ieee5000
+ */
+DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+ AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(mmu_fck, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+ AM33XX_CM_GFX_MMUDATA_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+ AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+/*
+ * clkdiv32 is generated from fixed division of 732.4219
+ */
+DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732);
+
+DEFINE_CLK_GATE(clkdiv32k_ick, "clkdiv32k_ck", &clkdiv32k_ck, 0x0,
+ AM33XX_CM_PER_CLKDIV32K_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+/* "usbotg_fck" is an additional clock and not really a modulemode */
+DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0,
+ AM33XX_CM_CLKDCOLDO_DPLL_PER, AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(ieee5000_fck, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck,
+ 0x0, AM33XX_CM_PER_IEEE5000_CLKCTRL,
+ AM33XX_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+/* Timers */
+static const struct clksel timer1_clkmux_sel[] = {
+ { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+ { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+ { .parent = &tclkin_ck, .rates = div_1_2_rates },
+ { .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
+ { .parent = &clk_32768_ck, .rates = div_1_4_rates },
+ { .parent = NULL },
+};
+
+static const char *timer1_ck_parents[] = {
+ "sys_clkin_ck", "clkdiv32k_ick", "tclkin_ck", "clk_rc32k_ck",
+ "clk_32768_ck",
+};
+
+static struct clk timer1_fck;
+
+static const struct clk_ops timer1_fck_ops = {
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+ .init = &omap2_init_clk_clkdm,
+};
+
+static struct clk_hw_omap timer1_fck_hw = {
+ .hw = {
+ .clk = &timer1_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer1_clkmux_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER1MS_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_2_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer1_fck, timer1_ck_parents, timer1_fck_ops);
+
+static const struct clksel timer2_to_7_clk_sel[] = {
+ { .parent = &tclkin_ck, .rates = div_1_0_rates },
+ { .parent = &sys_clkin_ck, .rates = div_1_1_rates },
+ { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *timer2_to_7_ck_parents[] = {
+ "tclkin_ck", "sys_clkin_ck", "clkdiv32k_ick",
+};
+
+static struct clk timer2_fck;
+
+static struct clk_hw_omap timer2_fck_hw = {
+ .hw = {
+ .clk = &timer2_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER2_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer2_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer3_fck;
+
+static struct clk_hw_omap timer3_fck_hw = {
+ .hw = {
+ .clk = &timer3_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER3_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer3_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer4_fck;
+
+static struct clk_hw_omap timer4_fck_hw = {
+ .hw = {
+ .clk = &timer4_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER4_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer4_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer5_fck;
+
+static struct clk_hw_omap timer5_fck_hw = {
+ .hw = {
+ .clk = &timer5_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER5_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer5_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer6_fck;
+
+static struct clk_hw_omap timer6_fck_hw = {
+ .hw = {
+ .clk = &timer6_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER6_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer6_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer7_fck;
+
+static struct clk_hw_omap timer7_fck_hw = {
+ .hw = {
+ .clk = &timer7_fck,
+ },
+ .clkdm_name = "l4ls_clkdm",
+ .clksel = timer2_to_7_clk_sel,
+ .clksel_reg = AM33XX_CLKSEL_TIMER7_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer7_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(cpsw_125mhz_gclk,
+ "dpll_core_m5_ck",
+ &dpll_core_m5_ck,
+ 0x0,
+ 1, 2);
+
+static const struct clk_ops cpsw_fck_ops = {
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
+ { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
+ { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *cpsw_cpts_rft_ck_parents[] = {
+ "dpll_core_m5_ck", "dpll_core_m4_ck",
+};
+
+static struct clk cpsw_cpts_rft_clk;
+
+static struct clk_hw_omap cpsw_cpts_rft_clk_hw = {
+ .hw = {
+ .clk = &cpsw_cpts_rft_clk,
+ },
+ .clkdm_name = "cpsw_125mhz_clkdm",
+ .clksel = cpsw_cpts_rft_clkmux_sel,
+ .clksel_reg = AM33XX_CM_CPTS_RFT_CLKSEL,
+ .clksel_mask = AM33XX_CLKSEL_0_0_MASK,
+};
+
+DEFINE_STRUCT_CLK(cpsw_cpts_rft_clk, cpsw_cpts_rft_ck_parents, cpsw_fck_ops);
+
+
+/* gpio */
+static const char *gpio0_ck_parents[] = {
+ "clk_rc32k_ck", "clk_32768_ck", "clkdiv32k_ick",
+};
+
+static const struct clksel gpio0_dbclk_mux_sel[] = {
+ { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+ { .parent = &clk_32768_ck, .rates = div_1_1_rates },
+ { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const struct clk_ops gpio_fck_ops = {
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+ .init = &omap2_init_clk_clkdm,
+};
+
+static struct clk gpio0_dbclk_mux_ck;
+
+static struct clk_hw_omap gpio0_dbclk_mux_ck_hw = {
+ .hw = {
+ .clk = &gpio0_dbclk_mux_ck,
+ },
+ .clkdm_name = "l4_wkup_clkdm",
+ .clksel = gpio0_dbclk_mux_sel,
+ .clksel_reg = AM33XX_CLKSEL_GPIO0_DBCLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(gpio0_dbclk_mux_ck, gpio0_ck_parents, gpio_fck_ops);
+
+DEFINE_CLK_GATE(gpio0_dbclk, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, 0x0,
+ AM33XX_CM_WKUP_GPIO0_CLKCTRL,
+ AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+ AM33XX_CM_PER_GPIO1_CLKCTRL,
+ AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+ AM33XX_CM_PER_GPIO2_CLKCTRL,
+ AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+ AM33XX_CM_PER_GPIO3_CLKCTRL,
+ AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, 0x0, NULL);
+
+
+static const char *pruss_ck_parents[] = {
+ "l3_gclk", "dpll_disp_m2_ck",
+};
+
+static const struct clksel pruss_ocp_clk_mux_sel[] = {
+ { .parent = &l3_gclk, .rates = div_1_0_rates },
+ { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static struct clk pruss_ocp_gclk;
+
+static struct clk_hw_omap pruss_ocp_gclk_hw = {
+ .hw = {
+ .clk = &pruss_ocp_gclk,
+ },
+ .clkdm_name = "pruss_ocp_clkdm",
+ .clksel = pruss_ocp_clk_mux_sel,
+ .clksel_reg = AM33XX_CLKSEL_PRUSS_OCP_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_0_MASK,
+};
+
+DEFINE_STRUCT_CLK(pruss_ocp_gclk, pruss_ck_parents, gpio_fck_ops);
+
+static const char *lcd_ck_parents[] = {
+ "dpll_disp_m2_ck", "dpll_core_m5_ck", "dpll_per_m2_ck",
+};
+
+static const struct clksel lcd_clk_mux_sel[] = {
+ { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
+ { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
+ { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static struct clk lcd_gclk;
+
+static struct clk_hw_omap lcd_gclk_hw = {
+ .hw = {
+ .clk = &lcd_gclk,
+ },
+ .clkdm_name = "lcdc_clkdm",
+ .clksel = lcd_clk_mux_sel,
+ .clksel_reg = AM33XX_CLKSEL_LCDC_PIXEL_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(lcd_gclk, lcd_ck_parents, gpio_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
+
+static const char *gfx_ck_parents[] = {
+ "dpll_core_m4_ck", "dpll_per_m2_ck",
+};
+
+static const struct clksel gfx_clksel_sel[] = {
+ { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
+ { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static struct clk gfx_fclk_clksel_ck;
+
+static struct clk_hw_omap gfx_fclk_clksel_ck_hw = {
+ .hw = {
+ .clk = &gfx_fclk_clksel_ck,
+ },
+ .clksel = gfx_clksel_sel,
+ .clksel_reg = AM33XX_CLKSEL_GFX_FCLK,
+ .clksel_mask = AM33XX_CLKSEL_GFX_FCLK_MASK,
+};
+
+DEFINE_STRUCT_CLK(gfx_fclk_clksel_ck, gfx_ck_parents, gpio_fck_ops);
+
+static const struct clk_div_table div_1_0_2_1_rates[] = {
+ { .div = 1, .val = 0, },
+ { .div = 2, .val = 1, },
+ { .div = 0 },
+};
+
+DEFINE_CLK_DIVIDER_TABLE(gfx_fck_div_ck, "gfx_fclk_clksel_ck",
+ &gfx_fclk_clksel_ck, 0x0, AM33XX_CLKSEL_GFX_FCLK,
+ AM33XX_CLKSEL_0_0_SHIFT, AM33XX_CLKSEL_0_0_WIDTH,
+ 0x0, div_1_0_2_1_rates, NULL);
+
+static const char *sysclkout_ck_parents[] = {
+ "clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
+ "lcd_gclk",
+};
+
+static const struct clksel sysclkout_pre_sel[] = {
+ { .parent = &clk_32768_ck, .rates = div_1_0_rates },
+ { .parent = &l3_gclk, .rates = div_1_1_rates },
+ { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
+ { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
+ { .parent = &lcd_gclk, .rates = div_1_4_rates },
+ { .parent = NULL },
+};
+
+static struct clk sysclkout_pre_ck;
+
+static struct clk_hw_omap sysclkout_pre_ck_hw = {
+ .hw = {
+ .clk = &sysclkout_pre_ck,
+ },
+ .clksel = sysclkout_pre_sel,
+ .clksel_reg = AM33XX_CM_CLKOUT_CTRL,
+ .clksel_mask = AM33XX_CLKOUT2SOURCE_MASK,
+};
+
+DEFINE_STRUCT_CLK(sysclkout_pre_ck, sysclkout_ck_parents, gpio_fck_ops);
+
+/* Divide by 8 clock rates with default clock is 1/1*/
+static const struct clk_div_table div8_rates[] = {
+ { .div = 1, .val = 0, },
+ { .div = 2, .val = 1, },
+ { .div = 3, .val = 2, },
+ { .div = 4, .val = 3, },
+ { .div = 5, .val = 4, },
+ { .div = 6, .val = 5, },
+ { .div = 7, .val = 6, },
+ { .div = 8, .val = 7, },
+ { .div = 0 },
+};
+
+DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
+ 0x0, AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2DIV_SHIFT,
+ AM33XX_CLKOUT2DIV_WIDTH, 0x0, div8_rates, NULL);
+
+DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
+ AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
+
+static const char *wdt_ck_parents[] = {
+ "clk_rc32k_ck", "clkdiv32k_ick",
+};
+
+static const struct clksel wdt_clkmux_sel[] = {
+ { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+ { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static struct clk wdt1_fck;
+
+static struct clk_hw_omap wdt1_fck_hw = {
+ .hw = {
+ .clk = &wdt1_fck,
+ },
+ .clkdm_name = "l4_wkup_clkdm",
+ .clksel = wdt_clkmux_sel,
+ .clksel_reg = AM33XX_CLKSEL_WDT1_CLK,
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
+
+/*
+ * clkdev
+ */
+static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "clk_32768_ck", &clk_32768_ck, CK_AM33XX),
+ CLK(NULL, "clk_rc32k_ck", &clk_rc32k_ck, CK_AM33XX),
+ CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_AM33XX),
+ CLK(NULL, "virt_24000000_ck", &virt_24000000_ck, CK_AM33XX),
+ CLK(NULL, "virt_25000000_ck", &virt_25000000_ck, CK_AM33XX),
+ CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_AM33XX),
+ CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_AM33XX),
+ CLK(NULL, "tclkin_ck", &tclkin_ck, CK_AM33XX),
+ CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_AM33XX),
+ CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck, CK_AM33XX),
+ CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck, CK_AM33XX),
+ CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck, CK_AM33XX),
+ CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_AM33XX),
+ CLK("cpu0", NULL, &dpll_mpu_ck, CK_AM33XX),
+ CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_ddr_ck", &dpll_ddr_ck, CK_AM33XX),
+ CLK(NULL, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_ddr_m2_div2_ck", &dpll_ddr_m2_div2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_disp_ck", &dpll_disp_ck, CK_AM33XX),
+ CLK(NULL, "dpll_disp_m2_ck", &dpll_disp_m2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_AM33XX),
+ CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_AM33XX),
+ CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", &dpll_per_m2_div4_wkupdm_ck, CK_AM33XX),
+ CLK(NULL, "dpll_per_m2_div4_ck", &dpll_per_m2_div4_ck, CK_AM33XX),
+ CLK(NULL, "adc_tsc_fck", &adc_tsc_fck, CK_AM33XX),
+ CLK(NULL, "cefuse_fck", &cefuse_fck, CK_AM33XX),
+ CLK(NULL, "clkdiv32k_ck", &clkdiv32k_ck, CK_AM33XX),
+ CLK(NULL, "clkdiv32k_ick", &clkdiv32k_ick, CK_AM33XX),
+ CLK(NULL, "dcan0_fck", &dcan0_fck, CK_AM33XX),
+ CLK("481cc000.d_can", NULL, &dcan0_fck, CK_AM33XX),
+ CLK(NULL, "dcan1_fck", &dcan1_fck, CK_AM33XX),
+ CLK("481d0000.d_can", NULL, &dcan1_fck, CK_AM33XX),
+ CLK(NULL, "debugss_ick", &debugss_ick, CK_AM33XX),
+ CLK(NULL, "pruss_ocp_gclk", &pruss_ocp_gclk, CK_AM33XX),
+ CLK(NULL, "mcasp0_fck", &mcasp0_fck, CK_AM33XX),
+ CLK(NULL, "mcasp1_fck", &mcasp1_fck, CK_AM33XX),
+ CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX),
+ CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX),
+ CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX),
+ CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX),
+ CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX),
+ CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX),
+ CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX),
+ CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX),
+ CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX),
+ CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX),
+ CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX),
+ CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX),
+ CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX),
+ CLK(NULL, "l4_rtc_gclk", &l4_rtc_gclk, CK_AM33XX),
+ CLK(NULL, "l3_gclk", &l3_gclk, CK_AM33XX),
+ CLK(NULL, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck, CK_AM33XX),
+ CLK(NULL, "l4hs_gclk", &l4hs_gclk, CK_AM33XX),
+ CLK(NULL, "l3s_gclk", &l3s_gclk, CK_AM33XX),
+ CLK(NULL, "l4fw_gclk", &l4fw_gclk, CK_AM33XX),
+ CLK(NULL, "l4ls_gclk", &l4ls_gclk, CK_AM33XX),
+ CLK(NULL, "clk_24mhz", &clk_24mhz, CK_AM33XX),
+ CLK(NULL, "sysclk_div_ck", &sysclk_div_ck, CK_AM33XX),
+ CLK(NULL, "cpsw_125mhz_gclk", &cpsw_125mhz_gclk, CK_AM33XX),
+ CLK(NULL, "cpsw_cpts_rft_clk", &cpsw_cpts_rft_clk, CK_AM33XX),
+ CLK(NULL, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, CK_AM33XX),
+ CLK(NULL, "gpio0_dbclk", &gpio0_dbclk, CK_AM33XX),
+ CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_AM33XX),
+ CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_AM33XX),
+ CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_AM33XX),
+ CLK(NULL, "lcd_gclk", &lcd_gclk, CK_AM33XX),
+ CLK(NULL, "mmc_clk", &mmc_clk, CK_AM33XX),
+ CLK(NULL, "gfx_fclk_clksel_ck", &gfx_fclk_clksel_ck, CK_AM33XX),
+ CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX),
+ CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX),
+ CLK(NULL, "clkout2_div_ck", &clkout2_div_ck, CK_AM33XX),
+ CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
+ CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
+};
+
+
+static const char *enable_init_clks[] = {
+ "dpll_ddr_m2_ck",
+ "dpll_mpu_m2_ck",
+ "l3_gclk",
+ "l4hs_gclk",
+ "l4fw_gclk",
+ "l4ls_gclk",
+};
+
+int __init am33xx_clk_init(void)
+{
+ struct omap_clk *c;
+ u32 cpu_clkflg;
+
+ if (soc_is_am33xx()) {
+ cpu_mask = RATE_IN_AM33XX;
+ cpu_clkflg = CK_AM33XX;
+ }
+
+ for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
+ if (c->cpu & cpu_clkflg) {
+ clkdev_add(&c->lk);
+ if (!__clk_init(NULL, c->lk.clk))
+ omap2_init_clk_hw_omap_clocks(c->lk.clk);
+ }
+ }
+
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ /* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
+ * physically present, in such a case HWMOD enabling of
+ * clock would be failure with default parent. And timer
+ * probe thinks clock is already enabled, this leads to
+ * crash upon accessing timer 3 & 6 registers in probe.
+ * Fix by setting parent of both these timers to master
+ * oscillator clock.
+ */
+
+ clk_set_parent(&timer3_fck, &sys_clkin_ck);
+ clk_set_parent(&timer6_fck, &sys_clkin_ck);
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
new file mode 100644
index 000000000000..bdf39481fbd6
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -0,0 +1,3595 @@
+/*
+ * OMAP3 clock data
+ *
+ * Copyright (C) 2007-2012 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Updated to COMMON clk data format by Rajendra Nayak <rnayak@ti.com>
+ * With many device clock fixes by Kevin Hilman and Jouni Högander
+ * DPLL bypass clock support added by Roman Tereshonkov
+ *
+ */
+
+/*
+ * Virtual clocks are introduced as convenient tools.
+ * They are sources for other clocks and not supposed
+ * to be requested from drivers directly.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock3xxx.h"
+#include "clock34xx.h"
+#include "clock36xx.h"
+#include "clock3517.h"
+#include "cm3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm3xxx.h"
+#include "prm-regbits-34xx.h"
+#include "control.h"
+
+/*
+ * clocks
+ */
+
+#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR
+
+/* Maximum DPLL multiplier, divider values for OMAP3 */
+#define OMAP3_MAX_DPLL_MULT 2047
+#define OMAP3630_MAX_JTYPE_DPLL_MULT 4095
+#define OMAP3_MAX_DPLL_DIV 128
+
+DEFINE_CLK_FIXED_RATE(dummy_apb_pclk, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(omap_32k_fck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(pclk_ck, CLK_IS_ROOT, 27000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(rmii_ck, CLK_IS_ROOT, 50000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(secure_32k_fck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(sys_altclk, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_12m_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_13m_ck, CLK_IS_ROOT, 13000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_16_8m_ck, CLK_IS_ROOT, 16800000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_38_4m_ck, CLK_IS_ROOT, 38400000, 0x0);
+
+static const char *osc_sys_ck_parent_names[] = {
+ "virt_12m_ck", "virt_13m_ck", "virt_19200000_ck", "virt_26000000_ck",
+ "virt_38_4m_ck", "virt_16_8m_ck",
+};
+
+DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
+ OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
+ OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
+ OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
+ OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct dpll_data dpll3_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_mask = OMAP3430_EN_CORE_DPLL_MASK,
+ .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+ .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+ .idlest_mask = OMAP3430_ST_CORE_CLK_MASK,
+ .max_multiplier = OMAP3_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll3_ck;
+
+static const char *dpll3_ck_parent_names[] = {
+ "sys_ck",
+};
+
+static const struct clk_ops dpll3_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap3_dpll_recalc,
+ .round_rate = &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll3_ck_hw = {
+ .hw = {
+ .clk = &dpll3_ck,
+ },
+ .ops = &clkhwops_omap3_dpll,
+ .dpll_data = &dpll3_dd,
+ .clkdm_name = "dpll3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
+ OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+ "dpll3_m2_ck",
+};
+
+static const struct clk_ops core_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk security_l4_ick2;
+
+static const char *security_l4_ick2_parent_names[] = {
+ "l4_ick",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(security_l4_ick2, NULL);
+DEFINE_STRUCT_CLK(security_l4_ick2, security_l4_ick2_parent_names, core_ck_ops);
+
+static struct clk aes1_ick;
+
+static const char *aes1_ick_parent_names[] = {
+ "security_l4_ick2",
+};
+
+static const struct clk_ops aes1_ick_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes1_ick_hw = {
+ .hw = {
+ .clk = &aes1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP3430_EN_AES1_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(aes1_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk core_l4_ick;
+
+static const struct clk_ops core_l4_ick_ops = {
+ .init = &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk aes2_ick;
+
+static const char *aes2_ick_parent_names[] = {
+ "core_l4_ick",
+};
+
+static const struct clk_ops aes2_ick_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes2_ick_hw = {
+ .hw = {
+ .clk = &aes2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_AES2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk dpll1_fck;
+
+static struct dpll_data dpll1_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
+ .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK,
+ .clk_bypass = &dpll1_fck,
+ .clk_ref = &sys_ck,
+ .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK,
+ .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
+ .enable_mask = OMAP3430_EN_MPU_DPLL_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+ .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
+ .idlest_mask = OMAP3430_ST_MPU_CLK_MASK,
+ .max_multiplier = OMAP3_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll1_ck;
+
+static const struct clk_ops dpll1_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap3_dpll_recalc,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .round_rate = &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll1_ck_hw = {
+ .hw = {
+ .clk = &dpll1_ck,
+ },
+ .ops = &clkhwops_omap3_dpll,
+ .dpll_data = &dpll1_dd,
+ .clkdm_name = "dpll1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
+
+DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
+ OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
+ OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
+ OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_ck;
+
+static const char *mpu_ck_parent_names[] = {
+ "dpll1_x2m2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
+DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
+
+DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
+ OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
+ OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
+ 0x0, NULL);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+ .hw = {
+ .clk = &cam_ick,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_CAM_SHIFT,
+ .clkdm_name = "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, security_l4_ick2_parent_names, aes2_ick_ops);
+
+/* DPLL4 */
+/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
+/* Type: DPLL */
+static struct dpll_data dpll4_dd;
+
+static struct dpll_data dpll4_dd_34xx __initdata = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
+ .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
+ .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+ .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+ .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+ .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
+ .max_multiplier = OMAP3_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+};
+
+static struct dpll_data dpll4_dd_3630 __initdata = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
+ .mult_mask = OMAP3630_PERIPH_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
+ .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+ .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+ .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+ .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
+ .dco_mask = OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
+ .sddiv_mask = OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
+ .max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+ .flags = DPLL_J_TYPE
+};
+
+static struct clk dpll4_ck;
+
+static const struct clk_ops dpll4_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+ .get_parent = &omap2_init_dpll_parent,
+ .recalc_rate = &omap3_dpll_recalc,
+ .set_rate = &omap3_dpll4_set_rate,
+ .round_rate = &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll4_ck_hw = {
+ .hw = {
+ .clk = &dpll4_ck,
+ },
+ .dpll_data = &dpll4_dd,
+ .ops = &clkhwops_omap3_dpll,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_ck, dpll3_ck_parent_names, dpll4_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m5x2_ck;
+
+static const char *dpll4_m5x2_ck_parent_names[] = {
+ "dpll4_m5_ck",
+};
+
+static const struct clk_ops dpll4_m5x2_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap3_clkoutx2_recalc,
+};
+
+static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
+ .disable = &omap2_dflt_clk_disable,
+ .recalc_rate = &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll4_m5x2_ck_hw = {
+ .hw = {
+ .clk = &dpll4_m5x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_CAM_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m5x2_ck_3630 = {
+ .name = "dpll4_m5x2_ck",
+ .hw = &dpll4_m5x2_ck_hw.hw,
+ .parent_names = dpll4_m5x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll4_m5x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+static struct clk cam_mclk;
+
+static const char *cam_mclk_parent_names[] = {
+ "dpll4_m5x2_ck",
+};
+
+static struct clk_hw_omap cam_mclk_hw = {
+ .hw = {
+ .clk = &cam_mclk,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_CAM_SHIFT,
+ .clkdm_name = "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_mclk, cam_mclk_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate clkout2_src_core_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate clkout2_src_sys_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate clkout2_src_96m_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
+ OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m2x2_ck;
+
+static const char *dpll4_m2x2_ck_parent_names[] = {
+ "dpll4_m2_ck",
+};
+
+static struct clk_hw_omap dpll4_m2x2_ck_hw = {
+ .hw = {
+ .clk = &dpll4_m2x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_96M_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m2x2_ck_3630 = {
+ .name = "dpll4_m2x2_ck",
+ .hw = &dpll4_m2x2_ck_hw.hw,
+ .parent_names = dpll4_m2x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll4_m2x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+static struct clk omap_96m_alwon_fck;
+
+static const char *omap_96m_alwon_fck_parent_names[] = {
+ "dpll4_m2x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(omap_96m_alwon_fck, NULL);
+DEFINE_STRUCT_CLK(omap_96m_alwon_fck, omap_96m_alwon_fck_parent_names,
+ core_ck_ops);
+
+static struct clk cm_96m_fck;
+
+static const char *cm_96m_fck_parent_names[] = {
+ "omap_96m_alwon_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(cm_96m_fck, NULL);
+DEFINE_STRUCT_CLK(cm_96m_fck, cm_96m_fck_parent_names, core_ck_ops);
+
+static const struct clksel_rate clkout2_src_54m_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m3x2_ck;
+
+static const char *dpll4_m3x2_ck_parent_names[] = {
+ "dpll4_m3_ck",
+};
+
+static struct clk_hw_omap dpll4_m3x2_ck_hw = {
+ .hw = {
+ .clk = &dpll4_m3x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_TV_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m3x2_ck_3630 = {
+ .name = "dpll4_m3x2_ck",
+ .hw = &dpll4_m3x2_ck_hw.hw,
+ .parent_names = dpll4_m3x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll4_m3x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+static const char *omap_54m_fck_parent_names[] = {
+ "dpll4_m3x2_ck", "sys_altclk",
+};
+
+DEFINE_CLK_MUX(omap_54m_fck, omap_54m_fck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_SOURCE_54M_SHIFT,
+ OMAP3430_SOURCE_54M_WIDTH, 0x0, NULL);
+
+static const struct clksel clkout2_src_clksel[] = {
+ { .parent = &core_ck, .rates = clkout2_src_core_rates },
+ { .parent = &sys_ck, .rates = clkout2_src_sys_rates },
+ { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates },
+ { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates },
+ { .parent = NULL },
+};
+
+static const char *clkout2_src_ck_parent_names[] = {
+ "core_ck", "sys_ck", "cm_96m_fck", "omap_54m_fck",
+};
+
+static const struct clk_ops clkout2_src_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(clkout2_src_ck, "core_clkdm",
+ clkout2_src_clksel, OMAP3430_CM_CLKOUT_CTRL,
+ OMAP3430_CLKOUT2SOURCE_MASK,
+ OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_EN_SHIFT,
+ NULL, clkout2_src_ck_parent_names, clkout2_src_ck_ops);
+
+static const struct clksel_rate omap_48m_cm96m_rates[] = {
+ { .div = 2, .val = 0, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate omap_48m_alt_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel omap_48m_clksel[] = {
+ { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
+ { .parent = &sys_altclk, .rates = omap_48m_alt_rates },
+ { .parent = NULL },
+};
+
+static const char *omap_48m_fck_parent_names[] = {
+ "cm_96m_fck", "sys_altclk",
+};
+
+static struct clk omap_48m_fck;
+
+static const struct clk_ops omap_48m_fck_ops = {
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap omap_48m_fck_hw = {
+ .hw = {
+ .clk = &omap_48m_fck,
+ },
+ .clksel = omap_48m_clksel,
+ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ .clksel_mask = OMAP3430_SOURCE_48M_MASK,
+};
+
+DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
+
+static struct clk core_12m_fck;
+
+static const char *core_12m_fck_parent_names[] = {
+ "omap_12m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_12m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_12m_fck, core_12m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk core_48m_fck;
+
+static const char *core_48m_fck_parent_names[] = {
+ "omap_48m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_48m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
+
+static const char *omap_96m_fck_parent_names[] = {
+ "cm_96m_fck", "sys_ck",
+};
+
+DEFINE_CLK_MUX(omap_96m_fck, omap_96m_fck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+ OMAP3430_SOURCE_96M_SHIFT, OMAP3430_SOURCE_96M_WIDTH, 0x0, NULL);
+
+static struct clk core_96m_fck;
+
+static const char *core_96m_fck_parent_names[] = {
+ "omap_96m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_96m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_96m_fck, core_96m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk core_l3_ick;
+
+static const char *core_l3_ick_parent_names[] = {
+ "l3_ick",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
+
+static struct clk corex2_fck;
+
+static const char *corex2_fck_parent_names[] = {
+ "dpll3_m2x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(corex2_fck, NULL);
+DEFINE_STRUCT_CLK(corex2_fck, corex2_fck_parent_names, core_ck_ops);
+
+static struct clk cpefuse_fck;
+
+static struct clk_hw_omap cpefuse_fck_hw = {
+ .hw = {
+ .clk = &cpefuse_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+ .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cpefuse_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk csi2_96m_fck;
+
+static const char *csi2_96m_fck_parent_names[] = {
+ "core_96m_fck",
+};
+
+static struct clk_hw_omap csi2_96m_fck_hw = {
+ .hw = {
+ .clk = &csi2_96m_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_CSI2_SHIFT,
+ .clkdm_name = "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(csi2_96m_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk d2d_26m_fck;
+
+static struct clk_hw_omap d2d_26m_fck_hw = {
+ .hw = {
+ .clk = &d2d_26m_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430ES1_EN_D2D_SHIFT,
+ .clkdm_name = "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(d2d_26m_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk des1_ick;
+
+static struct clk_hw_omap des1_ick_hw = {
+ .hw = {
+ .clk = &des1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP3430_EN_DES1_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(des1_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk des2_ick;
+
+static struct clk_hw_omap des2_ick_hw = {
+ .hw = {
+ .clk = &des2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_DES2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
+ OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll2_fck;
+
+static struct dpll_data dpll2_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
+ .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK,
+ .clk_bypass = &dpll2_fck,
+ .clk_ref = &sys_ck,
+ .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK,
+ .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
+ .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK,
+ .modes = ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
+ (1 << DPLL_LOW_POWER_BYPASS)),
+ .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+ .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
+ .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK,
+ .max_multiplier = OMAP3_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll2_ck;
+
+static struct clk_hw_omap dpll2_ck_hw = {
+ .hw = {
+ .clk = &dpll2_ck,
+ },
+ .ops = &clkhwops_omap3_dpll,
+ .dpll_data = &dpll2_dd,
+ .clkdm_name = "dpll2_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
+ OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
+ OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
+ OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll3_m3x2_ck;
+
+static const char *dpll3_m3x2_ck_parent_names[] = {
+ "dpll3_m3_ck",
+};
+
+static struct clk_hw_omap dpll3_m3x2_ck_hw = {
+ .hw = {
+ .clk = &dpll3_m3x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll3_m3x2_ck_3630 = {
+ .name = "dpll3_m3x2_ck",
+ .hw = &dpll3_m3x2_ck_hw.hw,
+ .parent_names = dpll3_m3x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll3_m3x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
+
+DEFINE_CLK_DIVIDER(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m4x2_ck;
+
+static const char *dpll4_m4x2_ck_parent_names[] = {
+ "dpll4_m4_ck",
+};
+
+static struct clk_hw_omap dpll4_m4x2_ck_hw = {
+ .hw = {
+ .clk = &dpll4_m4x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_DSS1_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m4x2_ck_3630 = {
+ .name = "dpll4_m4x2_ck",
+ .hw = &dpll4_m4x2_ck_hw.hw,
+ .parent_names = dpll4_m4x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll4_m4x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m6x2_ck;
+
+static const char *dpll4_m6x2_ck_parent_names[] = {
+ "dpll4_m6_ck",
+};
+
+static struct clk_hw_omap dpll4_m6x2_ck_hw = {
+ .hw = {
+ .clk = &dpll4_m6x2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+ .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
+ .flags = INVERT_ENABLE,
+ .clkdm_name = "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m6x2_ck_3630 = {
+ .name = "dpll4_m6x2_ck",
+ .hw = &dpll4_m6x2_ck_hw.hw,
+ .parent_names = dpll4_m6x2_ck_parent_names,
+ .num_parents = ARRAY_SIZE(dpll4_m6x2_ck_parent_names),
+ .ops = &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
+
+static struct dpll_data dpll5_dd = {
+ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
+ .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
+ .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &sys_ck,
+ .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
+ .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
+ .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
+ .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+ .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
+ .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
+ .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
+ .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
+ .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
+ .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
+ .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
+ .max_multiplier = OMAP3_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll5_ck;
+
+static struct clk_hw_omap dpll5_ck_hw = {
+ .hw = {
+ .clk = &dpll5_ck,
+ },
+ .ops = &clkhwops_omap3_dpll,
+ .dpll_data = &dpll5_dd,
+ .clkdm_name = "dpll5_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
+ OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
+ OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dss1_alwon_fck_3430es1;
+
+static const char *dss1_alwon_fck_3430es1_parent_names[] = {
+ "dpll4_m4x2_ck",
+};
+
+static struct clk_hw_omap dss1_alwon_fck_3430es1_hw = {
+ .hw = {
+ .clk = &dss1_alwon_fck_3430es1,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_DSS1_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es1, dss1_alwon_fck_3430es1_parent_names,
+ aes2_ick_ops);
+
+static struct clk dss1_alwon_fck_3430es2;
+
+static struct clk_hw_omap dss1_alwon_fck_3430es2_hw = {
+ .hw = {
+ .clk = &dss1_alwon_fck_3430es2,
+ },
+ .ops = &clkhwops_omap3430es2_dss_usbhost_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_DSS1_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es2, dss1_alwon_fck_3430es1_parent_names,
+ aes2_ick_ops);
+
+static struct clk dss2_alwon_fck;
+
+static struct clk_hw_omap dss2_alwon_fck_hw = {
+ .hw = {
+ .clk = &dss2_alwon_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_DSS2_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss2_alwon_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk dss_96m_fck;
+
+static struct clk_hw_omap dss_96m_fck_hw = {
+ .hw = {
+ .clk = &dss_96m_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_TV_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_96m_fck, core_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk dss_ick_3430es1;
+
+static struct clk_hw_omap dss_ick_3430es1_hw = {
+ .hw = {
+ .clk = &dss_ick_3430es1,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick_3430es1, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk dss_ick_3430es2;
+
+static struct clk_hw_omap dss_ick_3430es2_hw = {
+ .hw = {
+ .clk = &dss_ick_3430es2,
+ },
+ .ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick_3430es2, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk dss_tv_fck;
+
+static const char *dss_tv_fck_parent_names[] = {
+ "omap_54m_fck",
+};
+
+static struct clk_hw_omap dss_tv_fck_hw = {
+ .hw = {
+ .clk = &dss_tv_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_TV_SHIFT,
+ .clkdm_name = "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_tv_fck, dss_tv_fck_parent_names, aes2_ick_ops);
+
+static struct clk emac_fck;
+
+static const char *emac_fck_parent_names[] = {
+ "rmii_ck",
+};
+
+static struct clk_hw_omap emac_fck_hw = {
+ .hw = {
+ .clk = &emac_fck,
+ },
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_CPGMAC_FCLK_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(emac_fck, emac_fck_parent_names, aes1_ick_ops);
+
+static struct clk ipss_ick;
+
+static const char *ipss_ick_parent_names[] = {
+ "core_l3_ick",
+};
+
+static struct clk_hw_omap ipss_ick_hw = {
+ .hw = {
+ .clk = &ipss_ick,
+ },
+ .ops = &clkhwops_am35xx_ipss_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = AM35XX_EN_IPSS_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ipss_ick, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk emac_ick;
+
+static const char *emac_ick_parent_names[] = {
+ "ipss_ick",
+};
+
+static struct clk_hw_omap emac_ick_hw = {
+ .hw = {
+ .clk = &emac_ick,
+ },
+ .ops = &clkhwops_am35xx_ipss_module_wait,
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emac_ick, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk emu_core_alwon_ck;
+
+static const char *emu_core_alwon_ck_parent_names[] = {
+ "dpll3_m3x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_core_alwon_ck, "dpll3_clkdm");
+DEFINE_STRUCT_CLK(emu_core_alwon_ck, emu_core_alwon_ck_parent_names,
+ core_l4_ick_ops);
+
+static struct clk emu_mpu_alwon_ck;
+
+static const char *emu_mpu_alwon_ck_parent_names[] = {
+ "mpu_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_mpu_alwon_ck, NULL);
+DEFINE_STRUCT_CLK(emu_mpu_alwon_ck, emu_mpu_alwon_ck_parent_names, core_ck_ops);
+
+static struct clk emu_per_alwon_ck;
+
+static const char *emu_per_alwon_ck_parent_names[] = {
+ "dpll4_m6x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_per_alwon_ck, "dpll4_clkdm");
+DEFINE_STRUCT_CLK(emu_per_alwon_ck, emu_per_alwon_ck_parent_names,
+ core_l4_ick_ops);
+
+static const char *emu_src_ck_parent_names[] = {
+ "sys_ck", "emu_core_alwon_ck", "emu_per_alwon_ck", "emu_mpu_alwon_ck",
+};
+
+static const struct clksel_rate emu_src_sys_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+ { .div = 0 },
+};
+
+static const struct clksel_rate emu_src_core_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 0 },
+};
+
+static const struct clksel_rate emu_src_per_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
+ { .div = 0 },
+};
+
+static const struct clksel_rate emu_src_mpu_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+ { .div = 0 },
+};
+
+static const struct clksel emu_src_clksel[] = {
+ { .parent = &sys_ck, .rates = emu_src_sys_rates },
+ { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
+ { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates },
+ { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates },
+ { .parent = NULL },
+};
+
+static const struct clk_ops emu_src_ck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+static struct clk emu_src_ck;
+
+static struct clk_hw_omap emu_src_ck_hw = {
+ .hw = {
+ .clk = &emu_src_ck,
+ },
+ .clksel = emu_src_clksel,
+ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ .clksel_mask = OMAP3430_MUX_CTRL_MASK,
+ .clkdm_name = "emu_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+ .hw = {
+ .clk = &fac_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430ES1_EN_FAC_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk fshostusb_fck;
+
+static const char *fshostusb_fck_parent_names[] = {
+ "core_48m_fck",
+};
+
+static struct clk_hw_omap fshostusb_fck_hw = {
+ .hw = {
+ .clk = &fshostusb_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fshostusb_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_l3_ck;
+
+static struct clk_hw_omap gfx_l3_ck_hw = {
+ .hw = {
+ .clk = &gfx_l3_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+ .enable_bit = OMAP_EN_GFX_SHIFT,
+ .clkdm_name = "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
+ OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+ OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk gfx_cg1_ck;
+
+static const char *gfx_cg1_ck_parent_names[] = {
+ "gfx_l3_fck",
+};
+
+static struct clk_hw_omap gfx_cg1_ck_hw = {
+ .hw = {
+ .clk = &gfx_cg1_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430ES1_EN_2D_SHIFT,
+ .clkdm_name = "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_cg1_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_cg2_ck;
+
+static struct clk_hw_omap gfx_cg2_ck_hw = {
+ .hw = {
+ .clk = &gfx_cg2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430ES1_EN_3D_SHIFT,
+ .clkdm_name = "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_cg2_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_l3_ick;
+
+static const char *gfx_l3_ick_parent_names[] = {
+ "gfx_l3_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(gfx_l3_ick, "gfx_3430es1_clkdm");
+DEFINE_STRUCT_CLK(gfx_l3_ick, gfx_l3_ick_parent_names, core_l4_ick_ops);
+
+static struct clk wkup_32k_fck;
+
+static const char *wkup_32k_fck_parent_names[] = {
+ "omap_32k_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wkup_32k_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wkup_32k_fck, wkup_32k_fck_parent_names, core_l4_ick_ops);
+
+static struct clk gpio1_dbck;
+
+static const char *gpio1_dbck_parent_names[] = {
+ "wkup_32k_fck",
+};
+
+static struct clk_hw_omap gpio1_dbck_hw = {
+ .hw = {
+ .clk = &gpio1_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio1_dbck, gpio1_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wkup_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wkup_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wkup_l4_ick, dpll3_ck_parent_names, core_l4_ick_ops);
+
+static struct clk gpio1_ick;
+
+static const char *gpio1_ick_parent_names[] = {
+ "wkup_l4_ick",
+};
+
+static struct clk_hw_omap gpio1_ick_hw = {
+ .hw = {
+ .clk = &gpio1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk per_32k_alwon_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_32k_alwon_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_32k_alwon_fck, wkup_32k_fck_parent_names,
+ core_l4_ick_ops);
+
+static struct clk gpio2_dbck;
+
+static const char *gpio2_dbck_parent_names[] = {
+ "per_32k_alwon_fck",
+};
+
+static struct clk_hw_omap gpio2_dbck_hw = {
+ .hw = {
+ .clk = &gpio2_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio2_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk per_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_l4_ick, "per_clkdm");
+DEFINE_STRUCT_CLK(per_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk gpio2_ick;
+
+static const char *gpio2_ick_parent_names[] = {
+ "per_l4_ick",
+};
+
+static struct clk_hw_omap gpio2_ick_hw = {
+ .hw = {
+ .clk = &gpio2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio3_dbck;
+
+static struct clk_hw_omap gpio3_dbck_hw = {
+ .hw = {
+ .clk = &gpio3_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio3_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio3_ick;
+
+static struct clk_hw_omap gpio3_ick_hw = {
+ .hw = {
+ .clk = &gpio3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio4_dbck;
+
+static struct clk_hw_omap gpio4_dbck_hw = {
+ .hw = {
+ .clk = &gpio4_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio4_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio4_ick;
+
+static struct clk_hw_omap gpio4_ick_hw = {
+ .hw = {
+ .clk = &gpio4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio5_dbck;
+
+static struct clk_hw_omap gpio5_dbck_hw = {
+ .hw = {
+ .clk = &gpio5_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio5_ick;
+
+static struct clk_hw_omap gpio5_ick_hw = {
+ .hw = {
+ .clk = &gpio5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio6_dbck;
+
+static struct clk_hw_omap gpio6_dbck_hw = {
+ .hw = {
+ .clk = &gpio6_dbck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio6_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio6_ick;
+
+static struct clk_hw_omap gpio6_ick_hw = {
+ .hw = {
+ .clk = &gpio6_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio6_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+ .hw = {
+ .clk = &gpmc_fck,
+ },
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, ipss_ick_parent_names, core_l4_ick_ops);
+
+static const struct clksel omap343x_gpt_clksel[] = {
+ { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
+ { .parent = &sys_ck, .rates = gpt_sys_rates },
+ { .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+ "omap_32k_fck", "sys_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT10_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_GPT10_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+ .hw = {
+ .clk = &gpt10_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_GPT10_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT11_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_GPT11_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+ .hw = {
+ .clk = &gpt11_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_GPT11_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpt12_fck;
+
+static const char *gpt12_fck_parent_names[] = {
+ "secure_32k_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(gpt12_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(gpt12_fck, gpt12_fck_parent_names, core_l4_ick_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+ .hw = {
+ .clk = &gpt12_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT12_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "wkup_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT1_MASK,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT1_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+ .hw = {
+ .clk = &gpt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT2_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT2_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+ .hw = {
+ .clk = &gpt2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT2_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT3_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT3_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+ .hw = {
+ .clk = &gpt3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT4_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT4_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+ .hw = {
+ .clk = &gpt4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT5_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT5_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+ .hw = {
+ .clk = &gpt5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT5_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT6_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT6_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+ .hw = {
+ .clk = &gpt6_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT6_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT7_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT7_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+ .hw = {
+ .clk = &gpt7_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT7_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT8_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT8_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+ .hw = {
+ .clk = &gpt8_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT8_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "per_clkdm", omap343x_gpt_clksel,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_GPT9_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_GPT9_SHIFT, &clkhwops_wait,
+ gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+ .hw = {
+ .clk = &gpt9_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_GPT9_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk hdq_fck;
+
+static const char *hdq_fck_parent_names[] = {
+ "core_12m_fck",
+};
+
+static struct clk_hw_omap hdq_fck_hw = {
+ .hw = {
+ .clk = &hdq_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, hdq_fck_parent_names, aes2_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+ .hw = {
+ .clk = &hdq_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_HDQ_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk hecc_ck;
+
+static struct clk_hw_omap hecc_ck_hw = {
+ .hw = {
+ .clk = &hecc_ck,
+ },
+ .ops = &clkhwops_am35xx_ipss_module_wait,
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_HECC_VBUSP_CLK_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hecc_ck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_fck_am35xx;
+
+static struct clk_hw_omap hsotgusb_fck_am35xx_hw = {
+ .hw = {
+ .clk = &hsotgusb_fck_am35xx,
+ },
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_USBOTG_FCLK_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_fck_am35xx, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_3430es1;
+
+static struct clk_hw_omap hsotgusb_ick_3430es1_hw = {
+ .hw = {
+ .clk = &hsotgusb_ick_3430es1,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_3430es1, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_3430es2;
+
+static struct clk_hw_omap hsotgusb_ick_3430es2_hw = {
+ .hw = {
+ .clk = &hsotgusb_ick_3430es2,
+ },
+ .ops = &clkhwops_omap3430es2_iclk_hsotgusb_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_3430es2, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_am35xx;
+
+static struct clk_hw_omap hsotgusb_ick_am35xx_hw = {
+ .hw = {
+ .clk = &hsotgusb_ick_am35xx,
+ },
+ .ops = &clkhwops_am35xx_ipss_module_wait,
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_USBOTG_VBUSP_CLK_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_am35xx, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c1_fck;
+
+static struct clk_hw_omap i2c1_fck_hw = {
+ .hw = {
+ .clk = &i2c1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_I2C1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+ .hw = {
+ .clk = &i2c1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_I2C1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c2_fck;
+
+static struct clk_hw_omap i2c2_fck_hw = {
+ .hw = {
+ .clk = &i2c2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_I2C2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+ .hw = {
+ .clk = &i2c2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_I2C2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c3_fck;
+
+static struct clk_hw_omap i2c3_fck_hw = {
+ .hw = {
+ .clk = &i2c3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_I2C3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c3_ick;
+
+static struct clk_hw_omap i2c3_ick_hw = {
+ .hw = {
+ .clk = &i2c3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_I2C3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk icr_ick;
+
+static struct clk_hw_omap icr_ick_hw = {
+ .hw = {
+ .clk = &icr_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_ICR_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(icr_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk iva2_ck;
+
+static const char *iva2_ck_parent_names[] = {
+ "dpll2_m2_ck",
+};
+
+static struct clk_hw_omap iva2_ck_hw = {
+ .hw = {
+ .clk = &iva2_ck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
+ .clkdm_name = "iva2_clkdm",
+};
+
+DEFINE_STRUCT_CLK(iva2_ck, iva2_ck_parent_names, aes2_ick_ops);
+
+static struct clk mad2d_ick;
+
+static struct clk_hw_omap mad2d_ick_hw = {
+ .hw = {
+ .clk = &mad2d_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP3430_EN_MAD2D_SHIFT,
+ .clkdm_name = "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+ .hw = {
+ .clk = &mailboxes_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel mcbsp_15_clksel[] = {
+ { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
+ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+ "core_96m_fck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_15_clksel,
+ OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP1_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_MCBSP1_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+ .hw = {
+ .clk = &mcbsp1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk per_96m_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_96m_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_96m_fck, cm_96m_fck_parent_names, core_l4_ick_ops);
+
+static const struct clksel mcbsp_234_clksel[] = {
+ { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
+ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp2_fck_parent_names[] = {
+ "per_96m_fck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "per_clkdm", mcbsp_234_clksel,
+ OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+ OMAP2_MCBSP2_CLKS_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_MCBSP2_SHIFT, &clkhwops_wait,
+ mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+ .hw = {
+ .clk = &mcbsp2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "per_clkdm", mcbsp_234_clksel,
+ OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP3_CLKS_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_MCBSP3_SHIFT, &clkhwops_wait,
+ mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp3_ick;
+
+static struct clk_hw_omap mcbsp3_ick_hw = {
+ .hw = {
+ .clk = &mcbsp3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "per_clkdm", mcbsp_234_clksel,
+ OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP4_CLKS_MASK,
+ OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ OMAP3430_EN_MCBSP4_SHIFT, &clkhwops_wait,
+ mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp4_ick;
+
+static struct clk_hw_omap mcbsp4_ick_hw = {
+ .hw = {
+ .clk = &mcbsp4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_15_clksel,
+ OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+ OMAP2_MCBSP5_CLKS_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_MCBSP5_SHIFT, &clkhwops_wait,
+ mcbsp1_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp5_ick;
+
+static struct clk_hw_omap mcbsp5_ick_hw = {
+ .hw = {
+ .clk = &mcbsp5_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp5_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+ .hw = {
+ .clk = &mcspi1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+ .hw = {
+ .clk = &mcspi1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+ .hw = {
+ .clk = &mcspi2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+ .hw = {
+ .clk = &mcspi2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi3_fck;
+
+static struct clk_hw_omap mcspi3_fck_hw = {
+ .hw = {
+ .clk = &mcspi3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi3_ick;
+
+static struct clk_hw_omap mcspi3_ick_hw = {
+ .hw = {
+ .clk = &mcspi3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi4_fck;
+
+static struct clk_hw_omap mcspi4_fck_hw = {
+ .hw = {
+ .clk = &mcspi4_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi4_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi4_ick;
+
+static struct clk_hw_omap mcspi4_ick_hw = {
+ .hw = {
+ .clk = &mcspi4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi4_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs1_fck;
+
+static struct clk_hw_omap mmchs1_fck_hw = {
+ .hw = {
+ .clk = &mmchs1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MMC1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs1_ick;
+
+static struct clk_hw_omap mmchs1_ick_hw = {
+ .hw = {
+ .clk = &mmchs1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MMC1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs2_fck;
+
+static struct clk_hw_omap mmchs2_fck_hw = {
+ .hw = {
+ .clk = &mmchs2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MMC2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs2_ick;
+
+static struct clk_hw_omap mmchs2_ick_hw = {
+ .hw = {
+ .clk = &mmchs2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MMC2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs3_fck;
+
+static struct clk_hw_omap mmchs3_fck_hw = {
+ .hw = {
+ .clk = &mmchs3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs3_ick;
+
+static struct clk_hw_omap mmchs3_ick_hw = {
+ .hw = {
+ .clk = &mmchs3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk modem_fck;
+
+static struct clk_hw_omap modem_fck_hw = {
+ .hw = {
+ .clk = &modem_fck,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MODEM_SHIFT,
+ .clkdm_name = "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(modem_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+ .hw = {
+ .clk = &mspro_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+ .hw = {
+ .clk = &mspro_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk omap_192m_alwon_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(omap_192m_alwon_fck, NULL);
+DEFINE_STRUCT_CLK(omap_192m_alwon_fck, omap_96m_alwon_fck_parent_names,
+ core_ck_ops);
+
+static struct clk omap_32ksync_ick;
+
+static struct clk_hw_omap omap_32ksync_ick_hw = {
+ .hw = {
+ .clk = &omap_32ksync_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_32KSYNC_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omap_32ksync_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate omap_96m_alwon_fck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_36XX },
+ { .div = 2, .val = 2, .flags = RATE_IN_36XX },
+ { .div = 0 }
+};
+
+static const struct clksel omap_96m_alwon_fck_clksel[] = {
+ { .parent = &omap_192m_alwon_fck, .rates = omap_96m_alwon_fck_rates },
+ { .parent = NULL }
+};
+
+static struct clk omap_96m_alwon_fck_3630;
+
+static const char *omap_96m_alwon_fck_3630_parent_names[] = {
+ "omap_192m_alwon_fck",
+};
+
+static const struct clk_ops omap_96m_alwon_fck_3630_ops = {
+ .set_rate = &omap2_clksel_set_rate,
+ .recalc_rate = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+};
+
+static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
+ .hw = {
+ .clk = &omap_96m_alwon_fck_3630,
+ },
+ .clksel = omap_96m_alwon_fck_clksel,
+ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ .clksel_mask = OMAP3630_CLKSEL_96M_MASK,
+};
+
+static struct clk omap_96m_alwon_fck_3630 = {
+ .name = "omap_96m_alwon_fck",
+ .hw = &omap_96m_alwon_fck_3630_hw.hw,
+ .parent_names = omap_96m_alwon_fck_3630_parent_names,
+ .num_parents = ARRAY_SIZE(omap_96m_alwon_fck_3630_parent_names),
+ .ops = &omap_96m_alwon_fck_3630_ops,
+};
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+ .hw = {
+ .clk = &omapctrl_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk per_48m_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_48m_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk security_l3_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(security_l3_ick, NULL);
+DEFINE_STRUCT_CLK(security_l3_ick, core_l3_ick_parent_names, core_ck_ops);
+
+static struct clk pka_ick;
+
+static const char *pka_ick_parent_names[] = {
+ "security_l3_ick",
+};
+
+static struct clk_hw_omap pka_ick_hw = {
+ .hw = {
+ .clk = &pka_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP3430_EN_PKA_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
+ CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+ .hw = {
+ .clk = &rng_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP3430_EN_RNG_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk sad2d_ick;
+
+static struct clk_hw_omap sad2d_ick_hw = {
+ .hw = {
+ .clk = &sad2d_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_SAD2D_SHIFT,
+ .clkdm_name = "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+ .hw = {
+ .clk = &sdrc_ick,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_SDRC_SHIFT,
+ .flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, ipss_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate sgx_core_rates[] = {
+ { .div = 2, .val = 5, .flags = RATE_IN_36XX },
+ { .div = 3, .val = 0, .flags = RATE_IN_3XXX },
+ { .div = 4, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 6, .val = 2, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sgx_96m_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sgx_192m_rates[] = {
+ { .div = 1, .val = 4, .flags = RATE_IN_36XX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sgx_corex2_rates[] = {
+ { .div = 3, .val = 6, .flags = RATE_IN_36XX },
+ { .div = 5, .val = 7, .flags = RATE_IN_36XX },
+ { .div = 0 }
+};
+
+static const struct clksel sgx_clksel[] = {
+ { .parent = &core_ck, .rates = sgx_core_rates },
+ { .parent = &cm_96m_fck, .rates = sgx_96m_rates },
+ { .parent = &omap_192m_alwon_fck, .rates = sgx_192m_rates },
+ { .parent = &corex2_fck, .rates = sgx_corex2_rates },
+ { .parent = NULL },
+};
+
+static const char *sgx_fck_parent_names[] = {
+ "core_ck", "cm_96m_fck", "omap_192m_alwon_fck", "corex2_fck",
+};
+
+static struct clk sgx_fck;
+
+static const struct clk_ops sgx_fck_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sgx_fck, "sgx_clkdm", sgx_clksel,
+ OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
+ OMAP3430ES2_CLKSEL_SGX_MASK,
+ OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
+ OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
+ &clkhwops_wait, sgx_fck_parent_names, sgx_fck_ops);
+
+static struct clk sgx_ick;
+
+static struct clk_hw_omap sgx_ick_hw = {
+ .hw = {
+ .clk = &sgx_ick,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
+ .clkdm_name = "sgx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sgx_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk sha11_ick;
+
+static struct clk_hw_omap sha11_ick_hw = {
+ .hw = {
+ .clk = &sha11_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+ .enable_bit = OMAP3430_EN_SHA11_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(sha11_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk sha12_ick;
+
+static struct clk_hw_omap sha12_ick_hw = {
+ .hw = {
+ .clk = &sha12_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_SHA12_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha12_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk sr1_fck;
+
+static struct clk_hw_omap sr1_fck_hw = {
+ .hw = {
+ .clk = &sr1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_SR1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sr1_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk sr2_fck;
+
+static struct clk_hw_omap sr2_fck_hw = {
+ .hw = {
+ .clk = &sr2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_SR2_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sr2_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk sr_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sr_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(sr_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(ssi_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(ssi_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk ssi_ick_3430es1;
+
+static const char *ssi_ick_3430es1_parent_names[] = {
+ "ssi_l4_ick",
+};
+
+static struct clk_hw_omap ssi_ick_3430es1_hw = {
+ .hw = {
+ .clk = &ssi_ick_3430es1,
+ },
+ .ops = &clkhwops_iclk,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_SSI_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_ick_3430es1, ssi_ick_3430es1_parent_names, aes2_ick_ops);
+
+static struct clk ssi_ick_3430es2;
+
+static struct clk_hw_omap ssi_ick_3430es2_hw = {
+ .hw = {
+ .clk = &ssi_ick_3430es2,
+ },
+ .ops = &clkhwops_omap3430es2_iclk_ssi_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_SSI_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_ick_3430es2, ssi_ick_3430es1_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate ssi_ssr_corex2_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
+ { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
+ { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
+ { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
+ { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel ssi_ssr_clksel[] = {
+ { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
+ { .parent = NULL },
+};
+
+static const char *ssi_ssr_fck_3430es1_parent_names[] = {
+ "corex2_fck",
+};
+
+static const struct clk_ops ssi_ssr_fck_3430es1_ops = {
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es1, "core_l4_clkdm",
+ ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_SSI_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_SSI_SHIFT,
+ NULL, ssi_ssr_fck_3430es1_parent_names,
+ ssi_ssr_fck_3430es1_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
+ ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430_CLKSEL_SSI_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ OMAP3430_EN_SSI_SHIFT,
+ NULL, ssi_ssr_fck_3430es1_parent_names,
+ ssi_ssr_fck_3430es1_ops);
+
+DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
+ &ssi_ssr_fck_3430es1, 0x0, 1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
+ &ssi_ssr_fck_3430es2, 0x0, 1, 2);
+
+static struct clk sys_clkout1;
+
+static const char *sys_clkout1_parent_names[] = {
+ "osc_sys_ck",
+};
+
+static struct clk_hw_omap sys_clkout1_hw = {
+ .hw = {
+ .clk = &sys_clkout1,
+ },
+ .enable_reg = OMAP3430_PRM_CLKOUT_CTRL,
+ .enable_bit = OMAP3430_CLKOUT_EN_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
+ OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
+ OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
+ OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+ OMAP3430_CLKSEL_TRACECLK_SHIFT,
+ OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk ts_fck;
+
+static struct clk_hw_omap ts_fck_hw = {
+ .hw = {
+ .clk = &ts_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+ .enable_bit = OMAP3430ES2_EN_TS_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ts_fck, wkup_32k_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+ .hw = {
+ .clk = &uart1_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+ .hw = {
+ .clk = &uart1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_UART1_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+ .hw = {
+ .clk = &uart2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = OMAP3430_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+ .hw = {
+ .clk = &uart2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = OMAP3430_EN_UART2_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart3_fck;
+
+static const char *uart3_fck_parent_names[] = {
+ "per_48m_fck",
+};
+
+static struct clk_hw_omap uart3_fck_hw = {
+ .hw = {
+ .clk = &uart3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_UART3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, uart3_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+ .hw = {
+ .clk = &uart3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_UART3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart4_fck;
+
+static struct clk_hw_omap uart4_fck_hw = {
+ .hw = {
+ .clk = &uart4_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3630_EN_UART4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_fck, uart3_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart4_fck_am35xx;
+
+static struct clk_hw_omap uart4_fck_am35xx_hw = {
+ .hw = {
+ .clk = &uart4_fck_am35xx,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+ .enable_bit = AM35XX_EN_UART4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_fck_am35xx, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart4_ick;
+
+static struct clk_hw_omap uart4_ick_hw = {
+ .hw = {
+ .clk = &uart4_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3630_EN_UART4_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart4_ick_am35xx;
+
+static struct clk_hw_omap uart4_ick_am35xx_hw = {
+ .hw = {
+ .clk = &uart4_ick_am35xx,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ .enable_bit = AM35XX_EN_UART4_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_ick_am35xx, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate div2_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+ { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel usb_l4_clksel[] = {
+ { .parent = &l4_ick, .rates = div2_rates },
+ { .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+ "l4_ick",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_clksel,
+ OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+ OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
+ OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+ OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
+ &clkhwops_iclk_wait, usb_l4_ick_parent_names,
+ ssi_ssr_fck_3430es1_ops);
+
+static struct clk usbhost_120m_fck;
+
+static const char *usbhost_120m_fck_parent_names[] = {
+ "dpll5_m2_ck",
+};
+
+static struct clk_hw_omap usbhost_120m_fck_hw = {
+ .hw = {
+ .clk = &usbhost_120m_fck,
+ },
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT,
+ .clkdm_name = "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_120m_fck, usbhost_120m_fck_parent_names,
+ aes2_ick_ops);
+
+static struct clk usbhost_48m_fck;
+
+static struct clk_hw_omap usbhost_48m_fck_hw = {
+ .hw = {
+ .clk = &usbhost_48m_fck,
+ },
+ .ops = &clkhwops_omap3430es2_dss_usbhost_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT,
+ .clkdm_name = "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_48m_fck, core_48m_fck_parent_names, aes2_ick_ops);
+
+static struct clk usbhost_ick;
+
+static struct clk_hw_omap usbhost_ick_hw = {
+ .hw = {
+ .clk = &usbhost_ick,
+ },
+ .ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT,
+ .clkdm_name = "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_ick, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk usbtll_fck;
+
+static struct clk_hw_omap usbtll_fck_hw = {
+ .hw = {
+ .clk = &usbtll_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+ .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbtll_fck, usbhost_120m_fck_parent_names, aes2_ick_ops);
+
+static struct clk usbtll_ick;
+
+static struct clk_hw_omap usbtll_ick_hw = {
+ .hw = {
+ .clk = &usbtll_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+ .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
+ .clkdm_name = "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbtll_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate usim_96m_rates[] = {
+ { .div = 2, .val = 3, .flags = RATE_IN_3XXX },
+ { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
+ { .div = 8, .val = 5, .flags = RATE_IN_3XXX },
+ { .div = 10, .val = 6, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel_rate usim_120m_rates[] = {
+ { .div = 4, .val = 7, .flags = RATE_IN_3XXX },
+ { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
+ { .div = 16, .val = 9, .flags = RATE_IN_3XXX },
+ { .div = 20, .val = 10, .flags = RATE_IN_3XXX },
+ { .div = 0 }
+};
+
+static const struct clksel usim_clksel[] = {
+ { .parent = &omap_96m_fck, .rates = usim_96m_rates },
+ { .parent = &dpll5_m2_ck, .rates = usim_120m_rates },
+ { .parent = &sys_ck, .rates = div2_rates },
+ { .parent = NULL },
+};
+
+static const char *usim_fck_parent_names[] = {
+ "omap_96m_fck", "dpll5_m2_ck", "sys_ck",
+};
+
+static struct clk usim_fck;
+
+static const struct clk_ops usim_fck_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usim_fck, NULL, usim_clksel,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+ OMAP3430ES2_CLKSEL_USIMOCP_MASK,
+ OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ OMAP3430ES2_EN_USIMOCP_SHIFT, &clkhwops_wait,
+ usim_fck_parent_names, usim_fck_ops);
+
+static struct clk usim_ick;
+
+static struct clk_hw_omap usim_ick_hw = {
+ .hw = {
+ .clk = &usim_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usim_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk vpfe_fck;
+
+static const char *vpfe_fck_parent_names[] = {
+ "pclk_ck",
+};
+
+static struct clk_hw_omap vpfe_fck_hw = {
+ .hw = {
+ .clk = &vpfe_fck,
+ },
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_VPFE_FCLK_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(vpfe_fck, vpfe_fck_parent_names, aes1_ick_ops);
+
+static struct clk vpfe_ick;
+
+static struct clk_hw_omap vpfe_ick_hw = {
+ .hw = {
+ .clk = &vpfe_ick,
+ },
+ .ops = &clkhwops_am35xx_ipss_module_wait,
+ .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+ .enable_bit = AM35XX_VPFE_VBUSP_CLK_SHIFT,
+ .clkdm_name = "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(vpfe_ick, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt1_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wdt1_fck, gpt12_fck_parent_names, core_l4_ick_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+ .hw = {
+ .clk = &wdt1_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_WDT1_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt2_fck;
+
+static struct clk_hw_omap wdt2_fck_hw = {
+ .hw = {
+ .clk = &wdt2_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_WDT2_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt2_fck, gpio1_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wdt2_ick;
+
+static struct clk_hw_omap wdt2_ick_hw = {
+ .hw = {
+ .clk = &wdt2_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_WDT2_SHIFT,
+ .clkdm_name = "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt2_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt3_fck;
+
+static struct clk_hw_omap wdt3_fck_hw = {
+ .hw = {
+ .clk = &wdt3_fck,
+ },
+ .ops = &clkhwops_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+ .enable_bit = OMAP3430_EN_WDT3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_fck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wdt3_ick;
+
+static struct clk_hw_omap wdt3_ick_hw = {
+ .hw = {
+ .clk = &wdt3_ick,
+ },
+ .ops = &clkhwops_iclk_wait,
+ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+ .enable_bit = OMAP3430_EN_WDT3_SHIFT,
+ .clkdm_name = "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+/*
+ * clkdev
+ */
+static struct omap_clk omap3xxx_clks[] = {
+ CLK(NULL, "apb_pclk", &dummy_apb_pclk, CK_3XXX),
+ CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_3XXX),
+ CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_3XXX),
+ CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_3XXX),
+ CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_3XXX),
+ CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_3XXX),
+ CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
+ CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_3XXX),
+ CLK("twl", "fck", &osc_sys_ck, CK_3XXX),
+ CLK(NULL, "sys_ck", &sys_ck, CK_3XXX),
+ CLK(NULL, "sys_altclk", &sys_altclk, CK_3XXX),
+ CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX),
+ CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX),
+ CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX),
+ CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_3XXX),
+ CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
+ CLK(NULL, "dpll2_ck", &dpll2_ck, CK_34XX | CK_36XX),
+ CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_34XX | CK_36XX),
+ CLK(NULL, "dpll3_ck", &dpll3_ck, CK_3XXX),
+ CLK(NULL, "core_ck", &core_ck, CK_3XXX),
+ CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_3XXX),
+ CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_3XXX),
+ CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
+ CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_3XXX),
+ CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
+ CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
+ CLK(NULL, "dpll4_ck", &dpll4_ck, CK_3XXX),
+ CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_3XXX),
+ CLK(NULL, "omap_192m_alwon_fck", &omap_192m_alwon_fck, CK_36XX),
+ CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
+ CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_3XXX),
+ CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_3XXX),
+ CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_3XXX),
+ CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_3XXX),
+ CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_3XXX),
+ CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_3XXX),
+ CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
+ CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
+ CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
+ CLK(NULL, "sys_clkout2", &sys_clkout2, CK_3XXX),
+ CLK(NULL, "corex2_fck", &corex2_fck, CK_3XXX),
+ CLK(NULL, "dpll1_fck", &dpll1_fck, CK_3XXX),
+ CLK(NULL, "mpu_ck", &mpu_ck, CK_3XXX),
+ CLK(NULL, "arm_fck", &arm_fck, CK_3XXX),
+ CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
+ CLK(NULL, "dpll2_fck", &dpll2_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "iva2_ck", &iva2_ck, CK_34XX | CK_36XX),
+ CLK(NULL, "l3_ick", &l3_ick, CK_3XXX),
+ CLK(NULL, "l4_ick", &l4_ick, CK_3XXX),
+ CLK(NULL, "rm_ick", &rm_ick, CK_3XXX),
+ CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1),
+ CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1),
+ CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1),
+ CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1),
+ CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1),
+ CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
+ CLK(NULL, "modem_fck", &modem_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "sad2d_ick", &sad2d_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "mad2d_ick", &mad2d_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "gpt10_fck", &gpt10_fck, CK_3XXX),
+ CLK(NULL, "gpt11_fck", &gpt11_fck, CK_3XXX),
+ CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_tll", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
+ CLK(NULL, "mmchs3_fck", &mmchs3_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_3XXX),
+ CLK(NULL, "mspro_fck", &mspro_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_3XXX),
+ CLK(NULL, "i2c3_fck", &i2c3_fck, CK_3XXX),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_3XXX),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_3XXX),
+ CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_3XXX),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_3XXX),
+ CLK(NULL, "core_48m_fck", &core_48m_fck, CK_3XXX),
+ CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_3XXX),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_3XXX),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_3XXX),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_3XXX),
+ CLK(NULL, "uart2_fck", &uart2_fck, CK_3XXX),
+ CLK(NULL, "uart1_fck", &uart1_fck, CK_3XXX),
+ CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
+ CLK(NULL, "core_12m_fck", &core_12m_fck, CK_3XXX),
+ CLK("omap_hdq.0", "fck", &hdq_fck, CK_3XXX),
+ CLK(NULL, "hdq_fck", &hdq_fck, CK_3XXX),
+ CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1),
+ CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1),
+ CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "core_l3_ick", &core_l3_ick, CK_3XXX),
+ CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es1, CK_3430ES1),
+ CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es1, CK_3430ES1),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "sdrc_ick", &sdrc_ick, CK_3XXX),
+ CLK(NULL, "gpmc_fck", &gpmc_fck, CK_3XXX),
+ CLK(NULL, "security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
+ CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_tll", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "mmchs3_ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
+ CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
+ CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "des2_ick", &des2_ick, CK_34XX | CK_36XX),
+ CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_3XXX),
+ CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_3XXX),
+ CLK(NULL, "mmchs2_ick", &mmchs2_ick, CK_3XXX),
+ CLK(NULL, "mmchs1_ick", &mmchs1_ick, CK_3XXX),
+ CLK(NULL, "mspro_ick", &mspro_ick, CK_34XX | CK_36XX),
+ CLK("omap_hdq.0", "ick", &hdq_ick, CK_3XXX),
+ CLK(NULL, "hdq_ick", &hdq_ick, CK_3XXX),
+ CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_3XXX),
+ CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_3XXX),
+ CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_3XXX),
+ CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_3XXX),
+ CLK(NULL, "mcspi4_ick", &mcspi4_ick, CK_3XXX),
+ CLK(NULL, "mcspi3_ick", &mcspi3_ick, CK_3XXX),
+ CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_3XXX),
+ CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_3XXX),
+ CLK("omap_i2c.3", "ick", &i2c3_ick, CK_3XXX),
+ CLK("omap_i2c.2", "ick", &i2c2_ick, CK_3XXX),
+ CLK("omap_i2c.1", "ick", &i2c1_ick, CK_3XXX),
+ CLK(NULL, "i2c3_ick", &i2c3_ick, CK_3XXX),
+ CLK(NULL, "i2c2_ick", &i2c2_ick, CK_3XXX),
+ CLK(NULL, "i2c1_ick", &i2c1_ick, CK_3XXX),
+ CLK(NULL, "uart2_ick", &uart2_ick, CK_3XXX),
+ CLK(NULL, "uart1_ick", &uart1_ick, CK_3XXX),
+ CLK(NULL, "gpt11_ick", &gpt11_ick, CK_3XXX),
+ CLK(NULL, "gpt10_ick", &gpt10_ick, CK_3XXX),
+ CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_3XXX),
+ CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_3XXX),
+ CLK(NULL, "mcbsp5_ick", &mcbsp5_ick, CK_3XXX),
+ CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_3XXX),
+ CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1),
+ CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_3XXX),
+ CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "ssi_ick", &ssi_ick_3430es1, CK_3430ES1),
+ CLK(NULL, "ssi_ick", &ssi_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1),
+ CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_34XX | CK_36XX),
+ CLK(NULL, "aes1_ick", &aes1_ick, CK_34XX | CK_36XX),
+ CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "dss_tv_fck", &dss_tv_fck, CK_3XXX),
+ CLK(NULL, "dss_96m_fck", &dss_96m_fck, CK_3XXX),
+ CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck, CK_3XXX),
+ CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1),
+ CLK(NULL, "dss_ick", &dss_ick_3430es1, CK_3430ES1),
+ CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "dss_ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX),
+ CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
+ CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
+ CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
+ CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
+ CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
+ CLK(NULL, "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_tll", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
+ CLK("usbhs_tll", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
+ CLK(NULL, "init_60m_fclk", &dummy_ck, CK_3XXX),
+ CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
+ CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
+ CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
+ CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
+ CLK(NULL, "wdt2_fck", &wdt2_fck, CK_3XXX),
+ CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2PLUS | CK_36XX),
+ CLK("omap_wdt", "ick", &wdt2_ick, CK_3XXX),
+ CLK(NULL, "wdt2_ick", &wdt2_ick, CK_3XXX),
+ CLK(NULL, "wdt1_ick", &wdt1_ick, CK_3XXX),
+ CLK(NULL, "gpio1_ick", &gpio1_ick, CK_3XXX),
+ CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
+ CLK(NULL, "gpt12_ick", &gpt12_ick, CK_3XXX),
+ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_3XXX),
+ CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX),
+ CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX),
+ CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX),
+ CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX),
+ CLK(NULL, "uart4_fck", &uart4_fck_am35xx, CK_AM35XX),
+ CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX),
+ CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX),
+ CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX),
+ CLK(NULL, "gpt5_fck", &gpt5_fck, CK_3XXX),
+ CLK(NULL, "gpt6_fck", &gpt6_fck, CK_3XXX),
+ CLK(NULL, "gpt7_fck", &gpt7_fck, CK_3XXX),
+ CLK(NULL, "gpt8_fck", &gpt8_fck, CK_3XXX),
+ CLK(NULL, "gpt9_fck", &gpt9_fck, CK_3XXX),
+ CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
+ CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_3XXX),
+ CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_3XXX),
+ CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_3XXX),
+ CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_3XXX),
+ CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_3XXX),
+ CLK(NULL, "wdt3_fck", &wdt3_fck, CK_3XXX),
+ CLK(NULL, "per_l4_ick", &per_l4_ick, CK_3XXX),
+ CLK(NULL, "gpio6_ick", &gpio6_ick, CK_3XXX),
+ CLK(NULL, "gpio5_ick", &gpio5_ick, CK_3XXX),
+ CLK(NULL, "gpio4_ick", &gpio4_ick, CK_3XXX),
+ CLK(NULL, "gpio3_ick", &gpio3_ick, CK_3XXX),
+ CLK(NULL, "gpio2_ick", &gpio2_ick, CK_3XXX),
+ CLK(NULL, "wdt3_ick", &wdt3_ick, CK_3XXX),
+ CLK(NULL, "uart3_ick", &uart3_ick, CK_3XXX),
+ CLK(NULL, "uart4_ick", &uart4_ick, CK_36XX),
+ CLK(NULL, "gpt9_ick", &gpt9_ick, CK_3XXX),
+ CLK(NULL, "gpt8_ick", &gpt8_ick, CK_3XXX),
+ CLK(NULL, "gpt7_ick", &gpt7_ick, CK_3XXX),
+ CLK(NULL, "gpt6_ick", &gpt6_ick, CK_3XXX),
+ CLK(NULL, "gpt5_ick", &gpt5_ick, CK_3XXX),
+ CLK(NULL, "gpt4_ick", &gpt4_ick, CK_3XXX),
+ CLK(NULL, "gpt3_ick", &gpt3_ick, CK_3XXX),
+ CLK(NULL, "gpt2_ick", &gpt2_ick, CK_3XXX),
+ CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_3XXX),
+ CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_3XXX),
+ CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_3XXX),
+ CLK(NULL, "mcbsp4_ick", &mcbsp2_ick, CK_3XXX),
+ CLK(NULL, "mcbsp3_ick", &mcbsp3_ick, CK_3XXX),
+ CLK(NULL, "mcbsp2_ick", &mcbsp4_ick, CK_3XXX),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_3XXX),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_3XXX),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_3XXX),
+ CLK("etb", "emu_src_ck", &emu_src_ck, CK_3XXX),
+ CLK(NULL, "emu_src_ck", &emu_src_ck, CK_3XXX),
+ CLK(NULL, "pclk_fck", &pclk_fck, CK_3XXX),
+ CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_3XXX),
+ CLK(NULL, "atclk_fck", &atclk_fck, CK_3XXX),
+ CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
+ CLK(NULL, "traceclk_fck", &traceclk_fck, CK_3XXX),
+ CLK(NULL, "sr1_fck", &sr1_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "sr2_fck", &sr2_fck, CK_34XX | CK_36XX),
+ CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_3XXX),
+ CLK(NULL, "gpt12_fck", &gpt12_fck, CK_3XXX),
+ CLK(NULL, "wdt1_fck", &wdt1_fck, CK_3XXX),
+ CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX),
+ CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX),
+ CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX),
+ CLK(NULL, "emac_ick", &emac_ick, CK_AM35XX),
+ CLK(NULL, "emac_fck", &emac_fck, CK_AM35XX),
+ CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX),
+ CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX),
+ CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX),
+ CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx, CK_AM35XX),
+ CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx, CK_AM35XX),
+ CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
+ CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
+ CLK(NULL, "timer_32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK(NULL, "timer_sys_ck", &sys_ck, CK_3XXX),
+ CLK(NULL, "cpufreq_ck", &dpll1_ck, CK_3XXX),
+};
+
+static const char *enable_init_clks[] = {
+ "sdrc_ick",
+ "gpmc_fck",
+ "omapctrl_ick",
+};
+
+int __init omap3xxx_clk_init(void)
+{
+ struct omap_clk *c;
+ u32 cpu_clkflg = 0;
+
+ /*
+ * 3505 must be tested before 3517, since 3517 returns true
+ * for both AM3517 chips and AM3517 family chips, which
+ * includes 3505. Unfortunately there's no obvious family
+ * test for 3517/3505 :-(
+ */
+ if (soc_is_am35xx()) {
+ cpu_mask = RATE_IN_34XX;
+ cpu_clkflg = CK_AM35XX;
+ } else if (cpu_is_omap3630()) {
+ cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
+ cpu_clkflg = CK_36XX;
+ } else if (cpu_is_ti816x()) {
+ cpu_mask = RATE_IN_TI816X;
+ cpu_clkflg = CK_TI816X;
+ } else if (soc_is_am33xx()) {
+ cpu_mask = RATE_IN_AM33XX;
+ } else if (cpu_is_ti814x()) {
+ cpu_mask = RATE_IN_TI814X;
+ } else if (cpu_is_omap34xx()) {
+ if (omap_rev() == OMAP3430_REV_ES1_0) {
+ cpu_mask = RATE_IN_3430ES1;
+ cpu_clkflg = CK_3430ES1;
+ } else {
+ /*
+ * Assume that anything that we haven't matched yet
+ * has 3430ES2-type clocks.
+ */
+ cpu_mask = RATE_IN_3430ES2PLUS;
+ cpu_clkflg = CK_3430ES2PLUS;
+ }
+ } else {
+ WARN(1, "clock: could not identify OMAP3 variant\n");
+ }
+
+ if (omap3_has_192mhz_clk())
+ omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
+
+ if (cpu_is_omap3630()) {
+ dpll3_m3x2_ck = dpll3_m3x2_ck_3630;
+ dpll4_m2x2_ck = dpll4_m2x2_ck_3630;
+ dpll4_m3x2_ck = dpll4_m3x2_ck_3630;
+ dpll4_m4x2_ck = dpll4_m4x2_ck_3630;
+ dpll4_m5x2_ck = dpll4_m5x2_ck_3630;
+ dpll4_m6x2_ck = dpll4_m6x2_ck_3630;
+ }
+
+ /*
+ * XXX This type of dynamic rewriting of the clock tree is
+ * deprecated and should be revised soon.
+ */
+ if (cpu_is_omap3630())
+ dpll4_dd = dpll4_dd_3630;
+ else
+ dpll4_dd = dpll4_dd_34xx;
+
+ for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
+ c++)
+ if (c->cpu & cpu_clkflg) {
+ clkdev_add(&c->lk);
+ if (!__clk_init(NULL, c->lk.clk))
+ omap2_init_clk_hw_omap_clocks(c->lk.clk);
+ }
+
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+ (clk_get_rate(&osc_sys_ck) / 1000000),
+ (clk_get_rate(&osc_sys_ck) / 100000) % 10,
+ (clk_get_rate(&core_ck) / 1000000),
+ (clk_get_rate(&arm_fck) / 1000000));
+
+ /*
+ * Lock DPLL5 -- here only until other device init code can
+ * handle this
+ */
+ if (!cpu_is_ti81xx() && (omap_rev() >= OMAP3430_REV_ES2_0))
+ omap3_clk_lock_dpll5();
+
+ /* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
+ sdrc_ick_p = clk_get(NULL, "sdrc_ick");
+ arm_fck_p = clk_get(NULL, "arm_fck");
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
new file mode 100644
index 000000000000..aa56c3e5bb34
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -0,0 +1,1987 @@
+/*
+ * OMAP4 Clock data
+ *
+ * Copyright (C) 2009-2012 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ * Mike Turquette (mturquette@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.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock44xx.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "control.h"
+#include "scrm44xx.h"
+
+/* OMAP4 modulemode control */
+#define OMAP4430_MODULEMODE_HWCTRL_SHIFT 0
+#define OMAP4430_MODULEMODE_SWCTRL_SHIFT 1
+
+/* Root clocks */
+
+DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(pad_clks_src_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_GATE(pad_clks_ck, "pad_clks_src_ck", &pad_clks_src_ck, 0x0,
+ OMAP4430_CM_CLKSEL_ABE, OMAP4430_PAD_CLKS_GATE_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_FIXED_RATE(pad_slimbus_core_clks_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(secure_32k_clk_src_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(slimbus_src_clk, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_GATE(slimbus_clk, "slimbus_src_clk", &slimbus_src_clk, 0x0,
+ OMAP4430_CM_CLKSEL_ABE, OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_FIXED_RATE(sys_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_12000000_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_13000000_ck, CLK_IS_ROOT, 13000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_16800000_ck, CLK_IS_ROOT, 16800000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_27000000_ck, CLK_IS_ROOT, 27000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_38400000_ck, CLK_IS_ROOT, 38400000, 0x0);
+
+static const char *sys_clkin_ck_parents[] = {
+ "virt_12000000_ck", "virt_13000000_ck", "virt_16800000_ck",
+ "virt_19200000_ck", "virt_26000000_ck", "virt_27000000_ck",
+ "virt_38400000_ck",
+};
+
+DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
+ OMAP4430_CM_SYS_CLKSEL, OMAP4430_SYS_CLKSEL_SHIFT,
+ OMAP4430_SYS_CLKSEL_WIDTH, CLK_MUX_INDEX_ONE, NULL);
+
+DEFINE_CLK_FIXED_RATE(tie_low_clock_ck, CLK_IS_ROOT, 0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(utmi_phy_clkout_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60mhsp1_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60mhsp2_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60motg_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+/* Module clocks and DPLL outputs */
+
+static const char *abe_dpll_bypass_clk_mux_ck_parents[] = {
+ "sys_clkin_ck", "sys_32k_ck",
+};
+
+DEFINE_CLK_MUX(abe_dpll_bypass_clk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents,
+ NULL, 0x0, OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_SHIFT,
+ OMAP4430_CLKSEL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_MUX(abe_dpll_refclk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents, NULL,
+ 0x0, OMAP4430_CM_ABE_PLL_REF_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+ OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+/* DPLL_ABE */
+static struct dpll_data dpll_abe_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_ABE,
+ .clk_bypass = &abe_dpll_bypass_clk_mux_ck,
+ .clk_ref = &abe_dpll_refclk_mux_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_ABE,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_ABE,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_ABE,
+ .mult_mask = OMAP4430_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+
+static const char *dpll_abe_ck_parents[] = {
+ "abe_dpll_refclk_mux_ck",
+};
+
+static struct clk dpll_abe_ck;
+
+static const struct clk_ops dpll_abe_ck_ops = {
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+ .recalc_rate = &omap4_dpll_regm4xen_recalc,
+ .round_rate = &omap4_dpll_regm4xen_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .get_parent = &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_abe_ck_hw = {
+ .hw = {
+ .clk = &dpll_abe_ck,
+ },
+ .dpll_data = &dpll_abe_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_abe_ck, dpll_abe_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_abe_x2_ck_parents[] = {
+ "dpll_abe_ck",
+};
+
+static struct clk dpll_abe_x2_ck;
+
+static const struct clk_ops dpll_abe_x2_ck_ops = {
+ .recalc_rate = &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll_abe_x2_ck_hw = {
+ .hw = {
+ .clk = &dpll_abe_x2_ck,
+ },
+ .flags = CLOCK_CLKOUTX2,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
+ .ops = &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_abe_x2_ck, dpll_abe_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+static const struct clk_ops omap_hsdivider_ops = {
+ .set_rate = &omap2_clksel_set_rate,
+ .recalc_rate = &omap2_clksel_recalc,
+ .round_rate = &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m2x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M2_DPLL_ABE,
+ OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(abe_24m_fclk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
+ 0x0, 1, 8);
+
+DEFINE_CLK_DIVIDER(abe_clk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, 0x0,
+ OMAP4430_CM_CLKSEL_ABE, OMAP4430_CLKSEL_OPP_SHIFT,
+ OMAP4430_CLKSEL_OPP_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_DIVIDER(aess_fclk, "abe_clk", &abe_clk, 0x0,
+ OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
+ OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m3x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M3_DPLL_ABE,
+ OMAP4430_DPLL_CLKOUTHIF_DIV_MASK);
+
+static const char *core_hsd_byp_clk_mux_ck_parents[] = {
+ "sys_clkin_ck", "dpll_abe_m3x2_ck",
+};
+
+DEFINE_CLK_MUX(core_hsd_byp_clk_mux_ck, core_hsd_byp_clk_mux_ck_parents, NULL,
+ 0x0, OMAP4430_CM_CLKSEL_DPLL_CORE,
+ OMAP4430_DPLL_BYP_CLKSEL_SHIFT, OMAP4430_DPLL_BYP_CLKSEL_WIDTH,
+ 0x0, NULL);
+
+/* DPLL_CORE */
+static struct dpll_data dpll_core_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_CORE,
+ .clk_bypass = &core_hsd_byp_clk_mux_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_CORE,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_CORE,
+ .mult_mask = OMAP4430_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+
+static const char *dpll_core_ck_parents[] = {
+ "sys_clkin_ck",
+};
+
+static struct clk dpll_core_ck;
+
+static const struct clk_ops dpll_core_ck_ops = {
+ .recalc_rate = &omap3_dpll_recalc,
+ .get_parent = &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_core_ck_hw = {
+ .hw = {
+ .clk = &dpll_core_ck,
+ },
+ .dpll_data = &dpll_core_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
+
+static const char *dpll_core_x2_ck_parents[] = {
+ "dpll_core_ck",
+};
+
+static struct clk dpll_core_x2_ck;
+
+static struct clk_hw_omap dpll_core_x2_ck_hw = {
+ .hw = {
+ .clk = &dpll_core_x2_ck,
+ },
+};
+
+DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m6x2_ck, "dpll_core_x2_ck",
+ &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M6_DPLL_CORE,
+ OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m2_ck, "dpll_core_ck", &dpll_core_ck, 0x0,
+ OMAP4430_CM_DIV_M2_DPLL_CORE,
+ OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(ddrphy_ck, "dpll_core_m2_ck", &dpll_core_m2_ck, 0x0, 1,
+ 2);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m5x2_ck, "dpll_core_x2_ck",
+ &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M5_DPLL_CORE,
+ OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0,
+ OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT,
+ OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck",
+ &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA,
+ OMAP4430_CLKSEL_0_1_MASK);
+
+DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
+ 0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT,
+ OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m4x2_ck, "dpll_core_x2_ck",
+ &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M4_DPLL_CORE,
+ OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(dll_clk_div_ck, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck,
+ 0x0, 1, 2);
+
+DEFINE_CLK_DIVIDER(dpll_abe_m2_ck, "dpll_abe_ck", &dpll_abe_ck, 0x0,
+ OMAP4430_CM_DIV_M2_DPLL_ABE, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
+ OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static const struct clk_ops dmic_fck_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+ .set_parent = &omap2_clksel_set_parent,
+ .init = &omap2_init_clk_clkdm,
+};
+
+static const char *dpll_core_m3x2_ck_parents[] = {
+ "dpll_core_x2_ck",
+};
+
+static const struct clksel dpll_core_m3x2_div[] = {
+ { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
+ { .parent = NULL },
+};
+
+/* XXX Missing round_rate, set_rate in ops */
+DEFINE_CLK_OMAP_MUX_GATE(dpll_core_m3x2_ck, NULL, dpll_core_m3x2_div,
+ OMAP4430_CM_DIV_M3_DPLL_CORE,
+ OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ OMAP4430_CM_DIV_M3_DPLL_CORE,
+ OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
+ dpll_core_m3x2_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m7x2_ck, "dpll_core_x2_ck",
+ &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M7_DPLL_CORE,
+ OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
+
+static const char *iva_hsd_byp_clk_mux_ck_parents[] = {
+ "sys_clkin_ck", "div_iva_hs_clk",
+};
+
+DEFINE_CLK_MUX(iva_hsd_byp_clk_mux_ck, iva_hsd_byp_clk_mux_ck_parents, NULL,
+ 0x0, OMAP4430_CM_CLKSEL_DPLL_IVA, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
+ OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
+
+/* DPLL_IVA */
+static struct dpll_data dpll_iva_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_IVA,
+ .clk_bypass = &iva_hsd_byp_clk_mux_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_IVA,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_IVA,
+ .mult_mask = OMAP4430_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+static struct clk dpll_iva_ck;
+
+static struct clk_hw_omap dpll_iva_ck_hw = {
+ .hw = {
+ .clk = &dpll_iva_ck,
+ },
+ .dpll_data = &dpll_iva_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_iva_x2_ck_parents[] = {
+ "dpll_iva_ck",
+};
+
+static struct clk dpll_iva_x2_ck;
+
+static struct clk_hw_omap dpll_iva_x2_ck_hw = {
+ .hw = {
+ .clk = &dpll_iva_x2_ck,
+ },
+};
+
+DEFINE_STRUCT_CLK(dpll_iva_x2_ck, dpll_iva_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m4x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M4_DPLL_IVA,
+ OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m5x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M5_DPLL_IVA,
+ OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+/* DPLL_MPU */
+static struct dpll_data dpll_mpu_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_MPU,
+ .clk_bypass = &div_mpu_hs_clk,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_MPU,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_MPU,
+ .mult_mask = OMAP4430_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+static struct clk dpll_mpu_ck;
+
+static struct clk_hw_omap dpll_mpu_ck_hw = {
+ .hw = {
+ .clk = &dpll_mpu_ck,
+ },
+ .dpll_data = &dpll_mpu_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck, 0x0,
+ OMAP4430_CM_DIV_M2_DPLL_MPU,
+ OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(per_hs_clk_div_ck, "dpll_abe_m3x2_ck",
+ &dpll_abe_m3x2_ck, 0x0, 1, 2);
+
+static const char *per_hsd_byp_clk_mux_ck_parents[] = {
+ "sys_clkin_ck", "per_hs_clk_div_ck",
+};
+
+DEFINE_CLK_MUX(per_hsd_byp_clk_mux_ck, per_hsd_byp_clk_mux_ck_parents, NULL,
+ 0x0, OMAP4430_CM_CLKSEL_DPLL_PER, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
+ OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
+
+/* DPLL_PER */
+static struct dpll_data dpll_per_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_PER,
+ .clk_bypass = &per_hsd_byp_clk_mux_ck,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_PER,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_PER,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_PER,
+ .mult_mask = OMAP4430_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = 2047,
+ .max_divider = 128,
+ .min_divider = 1,
+};
+
+
+static struct clk dpll_per_ck;
+
+static struct clk_hw_omap dpll_per_ck_hw = {
+ .hw = {
+ .clk = &dpll_per_ck,
+ },
+ .dpll_data = &dpll_per_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
+ OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
+ OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static const char *dpll_per_x2_ck_parents[] = {
+ "dpll_per_ck",
+};
+
+static struct clk dpll_per_x2_ck;
+
+static struct clk_hw_omap dpll_per_x2_ck_hw = {
+ .hw = {
+ .clk = &dpll_per_x2_ck,
+ },
+ .flags = CLOCK_CLKOUTX2,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
+ .ops = &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_x2_ck, dpll_per_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m2x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M2_DPLL_PER,
+ OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+static const char *dpll_per_m3x2_ck_parents[] = {
+ "dpll_per_x2_ck",
+};
+
+static const struct clksel dpll_per_m3x2_div[] = {
+ { .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
+ { .parent = NULL },
+};
+
+/* XXX Missing round_rate, set_rate in ops */
+DEFINE_CLK_OMAP_MUX_GATE(dpll_per_m3x2_ck, NULL, dpll_per_m3x2_div,
+ OMAP4430_CM_DIV_M3_DPLL_PER,
+ OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ OMAP4430_CM_DIV_M3_DPLL_PER,
+ OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
+ dpll_per_m3x2_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m4x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M4_DPLL_PER,
+ OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m5x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M5_DPLL_PER,
+ OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m6x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M6_DPLL_PER,
+ OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m7x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+ 0x0, OMAP4430_CM_DIV_M7_DPLL_PER,
+ OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(usb_hs_clk_div_ck, "dpll_abe_m3x2_ck",
+ &dpll_abe_m3x2_ck, 0x0, 1, 3);
+
+/* DPLL_USB */
+static struct dpll_data dpll_usb_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_USB,
+ .clk_bypass = &usb_hs_clk_div_ck,
+ .flags = DPLL_J_TYPE,
+ .clk_ref = &sys_clkin_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_USB,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB,
+ .mult_mask = OMAP4430_DPLL_MULT_USB_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_0_7_MASK,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .sddiv_mask = OMAP4430_DPLL_SD_DIV_MASK,
+ .max_multiplier = 4095,
+ .max_divider = 256,
+ .min_divider = 1,
+};
+
+static struct clk dpll_usb_ck;
+
+static struct clk_hw_omap dpll_usb_ck_hw = {
+ .hw = {
+ .clk = &dpll_usb_ck,
+ },
+ .dpll_data = &dpll_usb_dd,
+ .ops = &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_usb_clkdcoldo_ck_parents[] = {
+ "dpll_usb_ck",
+};
+
+static struct clk dpll_usb_clkdcoldo_ck;
+
+static const struct clk_ops dpll_usb_clkdcoldo_ck_ops = {
+};
+
+static struct clk_hw_omap dpll_usb_clkdcoldo_ck_hw = {
+ .hw = {
+ .clk = &dpll_usb_clkdcoldo_ck,
+ },
+ .clksel_reg = OMAP4430_CM_CLKDCOLDO_DPLL_USB,
+ .ops = &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_usb_clkdcoldo_ck, dpll_usb_clkdcoldo_ck_parents,
+ dpll_usb_clkdcoldo_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_usb_m2_ck, "dpll_usb_ck", &dpll_usb_ck, 0x0,
+ OMAP4430_CM_DIV_M2_DPLL_USB,
+ OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK);
+
+static const char *ducati_clk_mux_ck_parents[] = {
+ "div_core_ck", "dpll_per_m6x2_ck",
+};
+
+DEFINE_CLK_MUX(ducati_clk_mux_ck, ducati_clk_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT, OMAP4430_CLKSEL_0_0_SHIFT,
+ OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+ 0x0, 1, 16);
+
+DEFINE_CLK_FIXED_FACTOR(func_24m_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0,
+ 1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(func_24mc_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+ 0x0, 1, 8);
+
+static const struct clk_div_table func_48m_fclk_rates[] = {
+ { .div = 4, .val = 0 },
+ { .div = 8, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_48m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+ 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+ OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_48m_fclk_rates,
+ NULL);
+
+DEFINE_CLK_FIXED_FACTOR(func_48mc_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+ 0x0, 1, 4);
+
+static const struct clk_div_table func_64m_fclk_rates[] = {
+ { .div = 2, .val = 0 },
+ { .div = 4, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_64m_fclk, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck,
+ 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+ OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_64m_fclk_rates,
+ NULL);
+
+static const struct clk_div_table func_96m_fclk_rates[] = {
+ { .div = 2, .val = 0 },
+ { .div = 4, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_96m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+ 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+ OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_96m_fclk_rates,
+ NULL);
+
+static const struct clk_div_table init_60m_fclk_rates[] = {
+ { .div = 1, .val = 0 },
+ { .div = 8, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(init_60m_fclk, "dpll_usb_m2_ck", &dpll_usb_m2_ck,
+ 0x0, OMAP4430_CM_CLKSEL_USB_60MHZ,
+ OMAP4430_CLKSEL_0_0_SHIFT, OMAP4430_CLKSEL_0_0_WIDTH,
+ 0x0, init_60m_fclk_rates, NULL);
+
+DEFINE_CLK_DIVIDER(l3_div_ck, "div_core_ck", &div_core_ck, 0x0,
+ OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L3_SHIFT,
+ OMAP4430_CLKSEL_L3_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(l4_div_ck, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L4_SHIFT,
+ OMAP4430_CLKSEL_L4_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(lp_clk_div_ck, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
+ 0x0, 1, 16);
+
+static const char *l4_wkup_clk_mux_ck_parents[] = {
+ "sys_clkin_ck", "lp_clk_div_ck",
+};
+
+DEFINE_CLK_MUX(l4_wkup_clk_mux_ck, l4_wkup_clk_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+ OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+static const struct clk_div_table ocp_abe_iclk_rates[] = {
+ { .div = 2, .val = 0 },
+ { .div = 1, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(ocp_abe_iclk, "aess_fclk", &aess_fclk, 0x0,
+ OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
+ OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
+ 0x0, ocp_abe_iclk_rates, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(per_abe_24m_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck,
+ 0x0, 1, 4);
+
+DEFINE_CLK_DIVIDER(per_abe_nc_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck, 0x0,
+ OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+ OMAP4430_SCALE_FCLK_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+ OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+ OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+static struct clk dbgclk_mux_ck;
+DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL);
+DEFINE_STRUCT_CLK(dbgclk_mux_ck, dpll_core_ck_parents,
+ dpll_usb_clkdcoldo_ck_ops);
+
+/* Leaf clocks controlled by modules */
+
+DEFINE_CLK_GATE(aes1_fck, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_AES1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(aes2_fck, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_AES2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(aess_fck, "aess_fclk", &aess_fclk, 0x0,
+ OMAP4430_CM1_ABE_AESS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(bandgap_fclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, 0x0, NULL);
+
+static const struct clk_div_table div_ts_ck_rates[] = {
+ { .div = 8, .val = 0 },
+ { .div = 16, .val = 1 },
+ { .div = 32, .val = 2 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(div_ts_ck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+ 0x0, OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ OMAP4430_CLKSEL_24_25_SHIFT,
+ OMAP4430_CLKSEL_24_25_WIDTH, 0x0, div_ts_ck_rates,
+ NULL);
+
+DEFINE_CLK_GATE(bandgap_ts_fclk, "div_ts_ck", &div_ts_ck, 0x0,
+ OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+ OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(des3des_fck, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+static const char *dmic_sync_mux_ck_parents[] = {
+ "abe_24m_fclk", "syc_clk_div_ck", "func_24m_clk",
+};
+
+DEFINE_CLK_MUX(dmic_sync_mux_ck, dmic_sync_mux_ck_parents, NULL,
+ 0x0, OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_dmic_abe_gfclk_sel[] = {
+ { .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = &slimbus_clk, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *dmic_fck_parents[] = {
+ "dmic_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_dmic_abe_gfclk into dmic */
+static struct clk dmic_fck;
+
+DEFINE_CLK_OMAP_MUX_GATE(dmic_fck, "abe_clkdm", func_dmic_abe_gfclk_sel,
+ OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_MASK,
+ OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ dmic_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(dsp_fck, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, 0x0,
+ OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_sys_clk, "syc_clk_div_ck", &syc_clk_div_ck, 0x0,
+ OMAP4430_CM_DSS_DSS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_tv_clk, "extalt_clkin_ck", &extalt_clkin_ck, 0x0,
+ OMAP4430_CM_DSS_DSS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_TV_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_dss_clk, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, 0x0,
+ OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_48mhz_clk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
+ OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_fck, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(efuse_ctrl_cust_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+ OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(emif1_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
+ OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(emif2_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
+ OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(fdif_fck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
+ OMAP4430_CM_CAM_FDIF_CLKCTRL, OMAP4430_CLKSEL_FCLK_SHIFT,
+ OMAP4430_CLKSEL_FCLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_GATE(fpka_fck, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_ick, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, 0x0,
+ OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO2_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio4_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO4_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio4_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio5_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO5_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio5_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio6_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO6_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio6_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpmc_ick, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_L3_2_GPMC_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ 0x0, NULL);
+
+static const struct clksel sgx_clk_mux_sel[] = {
+ { .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
+ { .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *gpu_fck_parents[] = {
+ "dpll_core_m7x2_ck", "dpll_per_m7x2_ck",
+};
+
+/* Merged sgx_clk_mux into gpu */
+DEFINE_CLK_OMAP_MUX_GATE(gpu_fck, "l3_gfx_clkdm", sgx_clk_mux_sel,
+ OMAP4430_CM_GFX_GFX_CLKCTRL,
+ OMAP4430_CLKSEL_SGX_FCLK_MASK,
+ OMAP4430_CM_GFX_GFX_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ gpu_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(hdq1w_fck, "func_12m_fclk", &func_12m_fclk, 0x0,
+ OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(hsi_fck, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0,
+ OMAP4430_CM_L3INIT_HSI_CLKCTRL, OMAP4430_CLKSEL_24_25_SHIFT,
+ OMAP4430_CLKSEL_24_25_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
+ NULL);
+
+DEFINE_CLK_GATE(i2c1_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+ OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c2_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+ OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c3_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+ OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c4_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+ OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ipu_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
+ OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(iss_ctrlclk, "func_96m_fclk", &func_96m_fclk, 0x0,
+ OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(iss_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
+ OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(iva_fck, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
+ OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(kbd_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk l3_instr_ick;
+
+static const char *l3_instr_ick_parent_names[] = {
+ "l3_div_ck",
+};
+
+static const struct clk_ops l3_instr_ick_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .init = &omap2_init_clk_clkdm,
+};
+
+static struct clk_hw_omap l3_instr_ick_hw = {
+ .hw = {
+ .clk = &l3_instr_ick,
+ },
+ .enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
+ .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ .clkdm_name = "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(l3_instr_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+static struct clk l3_main_3_ick;
+static struct clk_hw_omap l3_main_3_ick_hw = {
+ .hw = {
+ .clk = &l3_main_3_ick,
+ },
+ .enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
+ .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ .clkdm_name = "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(l3_main_3_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+DEFINE_CLK_MUX(mcasp_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcasp_abe_gfclk_sel[] = {
+ { .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = &slimbus_clk, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *mcasp_fck_parents[] = {
+ "mcasp_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcasp_abe_gfclk into mcasp */
+DEFINE_CLK_OMAP_MUX_GATE(mcasp_fck, "abe_clkdm", func_mcasp_abe_gfclk_sel,
+ OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_MASK,
+ OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mcasp_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp1_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp1_gfclk_sel[] = {
+ { .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = &slimbus_clk, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parents[] = {
+ "mcbsp1_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp1_gfclk into mcbsp1 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "abe_clkdm", func_mcbsp1_gfclk_sel,
+ OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_MASK,
+ OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mcbsp1_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp2_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp2_gfclk_sel[] = {
+ { .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = &slimbus_clk, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp2_fck_parents[] = {
+ "mcbsp2_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp2_gfclk into mcbsp2 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "abe_clkdm", func_mcbsp2_gfclk_sel,
+ OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_MASK,
+ OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mcbsp2_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp3_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp3_gfclk_sel[] = {
+ { .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = &slimbus_clk, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp3_fck_parents[] = {
+ "mcbsp3_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp3_gfclk into mcbsp3 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "abe_clkdm", func_mcbsp3_gfclk_sel,
+ OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_MASK,
+ OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mcbsp3_fck_parents, dmic_fck_ops);
+
+static const char *mcbsp4_sync_mux_ck_parents[] = {
+ "func_96m_fclk", "per_abe_nc_fclk",
+};
+
+DEFINE_CLK_MUX(mcbsp4_sync_mux_ck, mcbsp4_sync_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+ OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel per_mcbsp4_gfclk_sel[] = {
+ { .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates },
+ { .parent = &pad_clks_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *mcbsp4_fck_parents[] = {
+ "mcbsp4_sync_mux_ck", "pad_clks_ck",
+};
+
+/* Merged per_mcbsp4_gfclk into mcbsp4 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "l4_per_clkdm", per_mcbsp4_gfclk_sel,
+ OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+ OMAP4430_CLKSEL_SOURCE_24_24_MASK,
+ OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mcbsp4_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(mcpdm_fck, "pad_clks_ck", &pad_clks_ck, 0x0,
+ OMAP4430_CM1_ABE_PDM_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clksel hsmmc1_fclk_sel[] = {
+ { .parent = &func_64m_fclk, .rates = div_1_0_rates },
+ { .parent = &func_96m_fclk, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *mmc1_fck_parents[] = {
+ "func_64m_fclk", "func_96m_fclk",
+};
+
+/* Merged hsmmc1_fclk into mmc1 */
+DEFINE_CLK_OMAP_MUX_GATE(mmc1_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
+ OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mmc1_fck_parents, dmic_fck_ops);
+
+/* Merged hsmmc2_fclk into mmc2 */
+DEFINE_CLK_OMAP_MUX_GATE(mmc2_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
+ OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ mmc1_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(mmc3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mmc4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mmc5_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+ OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ocp2scp_usb_phy_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk ocp_wp_noc_ick;
+
+static struct clk_hw_omap ocp_wp_noc_ick_hw = {
+ .hw = {
+ .clk = &ocp_wp_noc_ick,
+ },
+ .enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
+ .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ .clkdm_name = "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ocp_wp_noc_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+DEFINE_CLK_GATE(rng_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_RNG_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(sl2if_ick, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
+ OMAP4430_CM_IVAHD_SL2_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_1, "func_24m_clk", &func_24m_clk, 0x0,
+ OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_FCLK1_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_0, "abe_24m_fclk", &abe_24m_fclk, 0x0,
+ OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_FCLK0_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_2, "pad_clks_ck", &pad_clks_ck, 0x0,
+ OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_FCLK2_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_slimbus_clk, "slimbus_clk", &slimbus_clk, 0x0,
+ OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fck, "ocp_abe_iclk", &ocp_abe_iclk, 0x0,
+ OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fclk_1, "per_abe_24m_fclk", &per_abe_24m_fclk, 0x0,
+ OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+ OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fclk_0, "func_24mc_fclk", &func_24mc_fclk, 0x0,
+ OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+ OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_slimbus_clk, "pad_slimbus_core_clks_ck",
+ &pad_slimbus_core_clks_ck, 0x0,
+ OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+ OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fck, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_core_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+ 0x0, OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_iva_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+ 0x0, OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_mpu_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+ 0x0, OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clksel dmt1_clk_mux_sel[] = {
+ { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+ { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+/* Merged dmt1_clk_mux into timer1 */
+DEFINE_CLK_OMAP_MUX_GATE(timer1_fck, "l4_wkup_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm10_mux into timer10 */
+DEFINE_CLK_OMAP_MUX_GATE(timer10_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm11_mux into timer11 */
+DEFINE_CLK_OMAP_MUX_GATE(timer11_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm2_mux into timer2 */
+DEFINE_CLK_OMAP_MUX_GATE(timer2_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm3_mux into timer3 */
+DEFINE_CLK_OMAP_MUX_GATE(timer3_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm4_mux into timer4 */
+DEFINE_CLK_OMAP_MUX_GATE(timer4_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+static const struct clksel timer5_sync_mux_sel[] = {
+ { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
+ { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *timer5_fck_parents[] = {
+ "syc_clk_div_ck", "sys_32k_ck",
+};
+
+/* Merged timer5_sync_mux into timer5 */
+DEFINE_CLK_OMAP_MUX_GATE(timer5_fck, "abe_clkdm", timer5_sync_mux_sel,
+ OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer6_sync_mux into timer6 */
+DEFINE_CLK_OMAP_MUX_GATE(timer6_fck, "abe_clkdm", timer5_sync_mux_sel,
+ OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer7_sync_mux into timer7 */
+DEFINE_CLK_OMAP_MUX_GATE(timer7_fck, "abe_clkdm", timer5_sync_mux_sel,
+ OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer8_sync_mux into timer8 */
+DEFINE_CLK_OMAP_MUX_GATE(timer8_fck, "abe_clkdm", timer5_sync_mux_sel,
+ OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ timer5_fck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm9_mux into timer9 */
+DEFINE_CLK_OMAP_MUX_GATE(timer9_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+ OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+ OMAP4430_CLKSEL_MASK,
+ OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+ abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(uart1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_UART1_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_UART2_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_UART3_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+ OMAP4430_CM_L4PER_UART4_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk usb_host_fs_fck;
+
+static const char *usb_host_fs_fck_parent_names[] = {
+ "func_48mc_fclk",
+};
+
+static const struct clk_ops usb_host_fs_fck_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap usb_host_fs_fck_hw = {
+ .hw = {
+ .clk = &usb_host_fs_fck,
+ },
+ .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ .enable_bit = OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ .clkdm_name = "l3_init_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_host_fs_fck, usb_host_fs_fck_parent_names,
+ usb_host_fs_fck_ops);
+
+static const char *utmi_p1_gfclk_parents[] = {
+ "init_60m_fclk", "xclk60mhsp1_ck",
+};
+
+DEFINE_CLK_MUX(utmi_p1_gfclk, utmi_p1_gfclk_parents, NULL, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_CLKSEL_UTMI_P1_SHIFT, OMAP4430_CLKSEL_UTMI_P1_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p1_clk, "utmi_p1_gfclk", &utmi_p1_gfclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT, 0x0, NULL);
+
+static const char *utmi_p2_gfclk_parents[] = {
+ "init_60m_fclk", "xclk60mhsp2_ck",
+};
+
+DEFINE_CLK_MUX(utmi_p2_gfclk, utmi_p2_gfclk_parents, NULL, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_CLKSEL_UTMI_P2_SHIFT, OMAP4430_CLKSEL_UTMI_P2_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p2_clk, "utmi_p2_gfclk", &utmi_p2_gfclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p3_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic480m_p1_clk, "dpll_usb_m2_ck",
+ &dpll_usb_m2_ck, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic60m_p1_clk, "init_60m_fclk",
+ &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic60m_p2_clk, "init_60m_fclk",
+ &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic480m_p2_clk, "dpll_usb_m2_ck",
+ &dpll_usb_m2_ck, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_func48mclk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_fck, "init_60m_fclk", &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const char *otg_60m_gfclk_parents[] = {
+ "utmi_phy_clkout_ck", "xclk60motg_ck",
+};
+
+DEFINE_CLK_MUX(otg_60m_gfclk, otg_60m_gfclk_parents, NULL, 0x0,
+ OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, OMAP4430_CLKSEL_60M_SHIFT,
+ OMAP4430_CLKSEL_60M_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_otg_hs_xclk, "otg_60m_gfclk", &otg_60m_gfclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+ OMAP4430_OPTFCLKEN_XCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_otg_hs_ick, "l3_div_ck", &l3_div_ck, 0x0,
+ OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_phy_cm_clk32k, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
+ OMAP4430_OPTFCLKEN_CLK32K_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch2_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch0_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch1_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+ OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_ick, "l4_div_ck", &l4_div_ck, 0x0,
+ OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+ OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clk_div_table usim_ck_rates[] = {
+ { .div = 14, .val = 0 },
+ { .div = 18, .val = 1 },
+ { .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(usim_ck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
+ OMAP4430_CM_WKUP_USIM_CLKCTRL,
+ OMAP4430_CLKSEL_DIV_SHIFT, OMAP4430_CLKSEL_DIV_WIDTH,
+ 0x0, usim_ck_rates, NULL);
+
+DEFINE_CLK_GATE(usim_fclk, "usim_ck", &usim_ck, 0x0,
+ OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(usim_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(wd_timer2_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM_WKUP_WDT2_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+DEFINE_CLK_GATE(wd_timer3_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+ OMAP4430_CM1_ABE_WDT3_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
+/* Remaining optional clocks */
+static const char *pmd_stm_clock_mux_ck_parents[] = {
+ "sys_clkin_ck", "dpll_core_m6x2_ck", "tie_low_clock_ck",
+};
+
+DEFINE_CLK_MUX(pmd_stm_clock_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, OMAP4430_PMD_STM_MUX_CTRL_SHIFT,
+ OMAP4430_PMD_STM_MUX_CTRL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_MUX(pmd_trace_clk_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
+ OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+ OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT,
+ OMAP4430_PMD_TRACE_MUX_CTRL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(stm_clk_div_ck, "pmd_stm_clock_mux_ck",
+ &pmd_stm_clock_mux_ck, 0x0, OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+ OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT,
+ OMAP4430_CLKSEL_PMD_STM_CLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
+ NULL);
+
+static const char *trace_clk_div_ck_parents[] = {
+ "pmd_trace_clk_mux_ck",
+};
+
+static const struct clksel trace_clk_div_div[] = {
+ { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
+ { .parent = NULL },
+};
+
+static struct clk trace_clk_div_ck;
+
+static const struct clk_ops trace_clk_div_ck_ops = {
+ .recalc_rate = &omap2_clksel_recalc,
+ .set_rate = &omap2_clksel_set_rate,
+ .round_rate = &omap2_clksel_round_rate,
+ .init = &omap2_init_clk_clkdm,
+ .enable = &omap2_clkops_enable_clkdm,
+ .disable = &omap2_clkops_disable_clkdm,
+};
+
+static struct clk_hw_omap trace_clk_div_ck_hw = {
+ .hw = {
+ .clk = &trace_clk_div_ck,
+ },
+ .clkdm_name = "emu_sys_clkdm",
+ .clksel = trace_clk_div_div,
+ .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
+};
+
+DEFINE_STRUCT_CLK(trace_clk_div_ck, trace_clk_div_ck_parents,
+ trace_clk_div_ck_ops);
+
+/* SCRM aux clk nodes */
+
+static const struct clksel auxclk_src_sel[] = {
+ { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+ { .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
+ { .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
+ { .parent = NULL },
+};
+
+static const char *auxclk_src_ck_parents[] = {
+ "sys_clkin_ck", "dpll_core_m3x2_ck", "dpll_per_m3x2_ck",
+};
+
+static const struct clk_ops auxclk_src_ck_ops = {
+ .enable = &omap2_dflt_clk_enable,
+ .disable = &omap2_dflt_clk_disable,
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ .recalc_rate = &omap2_clksel_recalc,
+ .get_parent = &omap2_clksel_find_parent_index,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk0_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK0, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK0, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk0_ck, "auxclk0_src_ck", &auxclk0_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK0, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk1_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK1, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK1, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk1_ck, "auxclk1_src_ck", &auxclk1_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK1, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk2_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK2, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK2, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk2_ck, "auxclk2_src_ck", &auxclk2_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK2, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk3_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK3, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK3, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk3_ck, "auxclk3_src_ck", &auxclk3_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK3, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk4_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK4, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK4, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk4_ck, "auxclk4_src_ck", &auxclk4_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK4, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk5_src_ck, NULL, auxclk_src_sel,
+ OMAP4_SCRM_AUXCLK5, OMAP4_SRCSELECT_MASK,
+ OMAP4_SCRM_AUXCLK5, OMAP4_ENABLE_SHIFT, NULL,
+ auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk5_ck, "auxclk5_src_ck", &auxclk5_src_ck, 0x0,
+ OMAP4_SCRM_AUXCLK5, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+ 0x0, NULL);
+
+static const char *auxclkreq_ck_parents[] = {
+ "auxclk0_ck", "auxclk1_ck", "auxclk2_ck", "auxclk3_ck", "auxclk4_ck",
+ "auxclk5_ck",
+};
+
+DEFINE_CLK_MUX(auxclkreq0_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ0, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq1_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ1, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq2_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ2, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq3_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ3, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq4_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ4, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq5_ck, auxclkreq_ck_parents, NULL, 0x0,
+ OMAP4_SCRM_AUXCLKREQ5, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+ 0x0, NULL);
+
+/*
+ * clkdev
+ */
+
+static struct omap_clk omap44xx_clks[] = {
+ CLK(NULL, "extalt_clkin_ck", &extalt_clkin_ck, CK_443X),
+ CLK(NULL, "pad_clks_src_ck", &pad_clks_src_ck, CK_443X),
+ CLK(NULL, "pad_clks_ck", &pad_clks_ck, CK_443X),
+ CLK(NULL, "pad_slimbus_core_clks_ck", &pad_slimbus_core_clks_ck, CK_443X),
+ CLK(NULL, "secure_32k_clk_src_ck", &secure_32k_clk_src_ck, CK_443X),
+ CLK(NULL, "slimbus_src_clk", &slimbus_src_clk, CK_443X),
+ CLK(NULL, "slimbus_clk", &slimbus_clk, CK_443X),
+ CLK(NULL, "sys_32k_ck", &sys_32k_ck, CK_443X),
+ CLK(NULL, "virt_12000000_ck", &virt_12000000_ck, CK_443X),
+ CLK(NULL, "virt_13000000_ck", &virt_13000000_ck, CK_443X),
+ CLK(NULL, "virt_16800000_ck", &virt_16800000_ck, CK_443X),
+ CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_443X),
+ CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_443X),
+ CLK(NULL, "virt_27000000_ck", &virt_27000000_ck, CK_443X),
+ CLK(NULL, "virt_38400000_ck", &virt_38400000_ck, CK_443X),
+ CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_443X),
+ CLK(NULL, "tie_low_clock_ck", &tie_low_clock_ck, CK_443X),
+ CLK(NULL, "utmi_phy_clkout_ck", &utmi_phy_clkout_ck, CK_443X),
+ CLK(NULL, "xclk60mhsp1_ck", &xclk60mhsp1_ck, CK_443X),
+ CLK(NULL, "xclk60mhsp2_ck", &xclk60mhsp2_ck, CK_443X),
+ CLK(NULL, "xclk60motg_ck", &xclk60motg_ck, CK_443X),
+ CLK(NULL, "abe_dpll_bypass_clk_mux_ck", &abe_dpll_bypass_clk_mux_ck, CK_443X),
+ CLK(NULL, "abe_dpll_refclk_mux_ck", &abe_dpll_refclk_mux_ck, CK_443X),
+ CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_443X),
+ CLK(NULL, "dpll_abe_x2_ck", &dpll_abe_x2_ck, CK_443X),
+ CLK(NULL, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, CK_443X),
+ CLK(NULL, "abe_24m_fclk", &abe_24m_fclk, CK_443X),
+ CLK(NULL, "abe_clk", &abe_clk, CK_443X),
+ CLK(NULL, "aess_fclk", &aess_fclk, CK_443X),
+ CLK(NULL, "dpll_abe_m3x2_ck", &dpll_abe_m3x2_ck, CK_443X),
+ CLK(NULL, "core_hsd_byp_clk_mux_ck", &core_hsd_byp_clk_mux_ck, CK_443X),
+ CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_443X),
+ CLK(NULL, "dpll_core_m6x2_ck", &dpll_core_m6x2_ck, CK_443X),
+ CLK(NULL, "dbgclk_mux_ck", &dbgclk_mux_ck, CK_443X),
+ CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_443X),
+ CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_443X),
+ CLK(NULL, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, CK_443X),
+ CLK(NULL, "div_core_ck", &div_core_ck, CK_443X),
+ CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_443X),
+ CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_443X),
+ CLK(NULL, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck, CK_443X),
+ CLK(NULL, "dll_clk_div_ck", &dll_clk_div_ck, CK_443X),
+ CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_443X),
+ CLK(NULL, "dpll_core_m3x2_ck", &dpll_core_m3x2_ck, CK_443X),
+ CLK(NULL, "dpll_core_m7x2_ck", &dpll_core_m7x2_ck, CK_443X),
+ CLK(NULL, "iva_hsd_byp_clk_mux_ck", &iva_hsd_byp_clk_mux_ck, CK_443X),
+ CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_443X),
+ CLK(NULL, "dpll_iva_x2_ck", &dpll_iva_x2_ck, CK_443X),
+ CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_443X),
+ CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_443X),
+ CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X),
+ CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X),
+ CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X),
+ CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X),
+ CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_443X),
+ CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2_ck", &dpll_per_x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m3x2_ck", &dpll_per_m3x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m6x2_ck", &dpll_per_m6x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m7x2_ck", &dpll_per_m7x2_ck, CK_443X),
+ CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_443X),
+ CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X),
+ CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_443X),
+ CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_443X),
+ CLK(NULL, "ducati_clk_mux_ck", &ducati_clk_mux_ck, CK_443X),
+ CLK(NULL, "func_12m_fclk", &func_12m_fclk, CK_443X),
+ CLK(NULL, "func_24m_clk", &func_24m_clk, CK_443X),
+ CLK(NULL, "func_24mc_fclk", &func_24mc_fclk, CK_443X),
+ CLK(NULL, "func_48m_fclk", &func_48m_fclk, CK_443X),
+ CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_443X),
+ CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_443X),
+ CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_443X),
+ CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_443X),
+ CLK(NULL, "l3_div_ck", &l3_div_ck, CK_443X),
+ CLK(NULL, "l4_div_ck", &l4_div_ck, CK_443X),
+ CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_443X),
+ CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_443X),
+ CLK("smp_twd", NULL, &mpu_periphclk, CK_443X),
+ CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_443X),
+ CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_443X),
+ CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X),
+ CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X),
+ CLK(NULL, "aes1_fck", &aes1_fck, CK_443X),
+ CLK(NULL, "aes2_fck", &aes2_fck, CK_443X),
+ CLK(NULL, "aess_fck", &aess_fck, CK_443X),
+ CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X),
+ CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X),
+ CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X),
+ CLK(NULL, "des3des_fck", &des3des_fck, CK_443X),
+ CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X),
+ CLK(NULL, "dmic_fck", &dmic_fck, CK_443X),
+ CLK(NULL, "dsp_fck", &dsp_fck, CK_443X),
+ CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X),
+ CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X),
+ CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X),
+ CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X),
+ CLK(NULL, "dss_fck", &dss_fck, CK_443X),
+ CLK("omapdss_dss", "ick", &dss_fck, CK_443X),
+ CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X),
+ CLK(NULL, "emif1_fck", &emif1_fck, CK_443X),
+ CLK(NULL, "emif2_fck", &emif2_fck, CK_443X),
+ CLK(NULL, "fdif_fck", &fdif_fck, CK_443X),
+ CLK(NULL, "fpka_fck", &fpka_fck, CK_443X),
+ CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_443X),
+ CLK(NULL, "gpio1_ick", &gpio1_ick, CK_443X),
+ CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_443X),
+ CLK(NULL, "gpio2_ick", &gpio2_ick, CK_443X),
+ CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_443X),
+ CLK(NULL, "gpio3_ick", &gpio3_ick, CK_443X),
+ CLK(NULL, "gpio4_dbclk", &gpio4_dbclk, CK_443X),
+ CLK(NULL, "gpio4_ick", &gpio4_ick, CK_443X),
+ CLK(NULL, "gpio5_dbclk", &gpio5_dbclk, CK_443X),
+ CLK(NULL, "gpio5_ick", &gpio5_ick, CK_443X),
+ CLK(NULL, "gpio6_dbclk", &gpio6_dbclk, CK_443X),
+ CLK(NULL, "gpio6_ick", &gpio6_ick, CK_443X),
+ CLK(NULL, "gpmc_ick", &gpmc_ick, CK_443X),
+ CLK(NULL, "gpu_fck", &gpu_fck, CK_443X),
+ CLK(NULL, "hdq1w_fck", &hdq1w_fck, CK_443X),
+ CLK(NULL, "hsi_fck", &hsi_fck, CK_443X),
+ CLK(NULL, "i2c1_fck", &i2c1_fck, CK_443X),
+ CLK(NULL, "i2c2_fck", &i2c2_fck, CK_443X),
+ CLK(NULL, "i2c3_fck", &i2c3_fck, CK_443X),
+ CLK(NULL, "i2c4_fck", &i2c4_fck, CK_443X),
+ CLK(NULL, "ipu_fck", &ipu_fck, CK_443X),
+ CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_443X),
+ CLK(NULL, "iss_fck", &iss_fck, CK_443X),
+ CLK(NULL, "iva_fck", &iva_fck, CK_443X),
+ CLK(NULL, "kbd_fck", &kbd_fck, CK_443X),
+ CLK(NULL, "l3_instr_ick", &l3_instr_ick, CK_443X),
+ CLK(NULL, "l3_main_3_ick", &l3_main_3_ick, CK_443X),
+ CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X),
+ CLK(NULL, "mcasp_fck", &mcasp_fck, CK_443X),
+ CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_443X),
+ CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_443X),
+ CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_443X),
+ CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_443X),
+ CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_443X),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_443X),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_443X),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_443X),
+ CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_443X),
+ CLK(NULL, "mmc1_fck", &mmc1_fck, CK_443X),
+ CLK(NULL, "mmc2_fck", &mmc2_fck, CK_443X),
+ CLK(NULL, "mmc3_fck", &mmc3_fck, CK_443X),
+ CLK(NULL, "mmc4_fck", &mmc4_fck, CK_443X),
+ CLK(NULL, "mmc5_fck", &mmc5_fck, CK_443X),
+ CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X),
+ CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_443X),
+ CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_443X),
+ CLK(NULL, "rng_ick", &rng_ick, CK_443X),
+ CLK("omap_rng", "ick", &rng_ick, CK_443X),
+ CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X),
+ CLK(NULL, "sl2if_ick", &sl2if_ick, CK_443X),
+ CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X),
+ CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X),
+ CLK(NULL, "slimbus1_fclk_2", &slimbus1_fclk_2, CK_443X),
+ CLK(NULL, "slimbus1_slimbus_clk", &slimbus1_slimbus_clk, CK_443X),
+ CLK(NULL, "slimbus1_fck", &slimbus1_fck, CK_443X),
+ CLK(NULL, "slimbus2_fclk_1", &slimbus2_fclk_1, CK_443X),
+ CLK(NULL, "slimbus2_fclk_0", &slimbus2_fclk_0, CK_443X),
+ CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_443X),
+ CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_443X),
+ CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X),
+ CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X),
+ CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X),
+ CLK(NULL, "timer1_fck", &timer1_fck, CK_443X),
+ CLK(NULL, "timer10_fck", &timer10_fck, CK_443X),
+ CLK(NULL, "timer11_fck", &timer11_fck, CK_443X),
+ CLK(NULL, "timer2_fck", &timer2_fck, CK_443X),
+ CLK(NULL, "timer3_fck", &timer3_fck, CK_443X),
+ CLK(NULL, "timer4_fck", &timer4_fck, CK_443X),
+ CLK(NULL, "timer5_fck", &timer5_fck, CK_443X),
+ CLK(NULL, "timer6_fck", &timer6_fck, CK_443X),
+ CLK(NULL, "timer7_fck", &timer7_fck, CK_443X),
+ CLK(NULL, "timer8_fck", &timer8_fck, CK_443X),
+ CLK(NULL, "timer9_fck", &timer9_fck, CK_443X),
+ CLK(NULL, "uart1_fck", &uart1_fck, CK_443X),
+ CLK(NULL, "uart2_fck", &uart2_fck, CK_443X),
+ CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
+ CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
+ CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
+ CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X),
+ CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
+ CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
+ CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X),
+ CLK(NULL, "usb_host_hs_utmi_p2_clk", &usb_host_hs_utmi_p2_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_hsic480m_p1_clk", &usb_host_hs_hsic480m_p1_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
+ CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
+ CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
+ CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X),
+ CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
+ CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
+ CLK(NULL, "usb_otg_hs_ick", &usb_otg_hs_ick, CK_443X),
+ CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X),
+ CLK(NULL, "usb_phy_cm_clk32k", &usb_phy_cm_clk32k, CK_443X),
+ CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X),
+ CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
+ CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
+ CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
+ CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
+ CLK("usbhs_tll", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
+ CLK(NULL, "usim_ck", &usim_ck, CK_443X),
+ CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
+ CLK(NULL, "usim_fck", &usim_fck, CK_443X),
+ CLK(NULL, "wd_timer2_fck", &wd_timer2_fck, CK_443X),
+ CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_443X),
+ CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X),
+ CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X),
+ CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X),
+ CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_443X),
+ CLK(NULL, "auxclk0_src_ck", &auxclk0_src_ck, CK_443X),
+ CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
+ CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X),
+ CLK(NULL, "auxclk1_src_ck", &auxclk1_src_ck, CK_443X),
+ CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
+ CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X),
+ CLK(NULL, "auxclk2_src_ck", &auxclk2_src_ck, CK_443X),
+ CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
+ CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X),
+ CLK(NULL, "auxclk3_src_ck", &auxclk3_src_ck, CK_443X),
+ CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
+ CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_443X),
+ CLK(NULL, "auxclk4_src_ck", &auxclk4_src_ck, CK_443X),
+ CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
+ CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_443X),
+ CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_443X),
+ CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
+ CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X),
+ CLK("omap-gpmc", "fck", &dummy_ck, CK_443X),
+ CLK("omap_i2c.1", "ick", &dummy_ck, CK_443X),
+ CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X),
+ CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X),
+ CLK("omap_i2c.4", "ick", &dummy_ck, CK_443X),
+ CLK(NULL, "mailboxes_ick", &dummy_ck, CK_443X),
+ CLK("omap_hsmmc.0", "ick", &dummy_ck, CK_443X),
+ CLK("omap_hsmmc.1", "ick", &dummy_ck, CK_443X),
+ CLK("omap_hsmmc.2", "ick", &dummy_ck, CK_443X),
+ CLK("omap_hsmmc.3", "ick", &dummy_ck, CK_443X),
+ CLK("omap_hsmmc.4", "ick", &dummy_ck, CK_443X),
+ CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_443X),
+ CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_443X),
+ CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_443X),
+ CLK("omap-mcbsp.4", "ick", &dummy_ck, CK_443X),
+ CLK("omap2_mcspi.1", "ick", &dummy_ck, CK_443X),
+ CLK("omap2_mcspi.2", "ick", &dummy_ck, CK_443X),
+ CLK("omap2_mcspi.3", "ick", &dummy_ck, CK_443X),
+ CLK("omap2_mcspi.4", "ick", &dummy_ck, CK_443X),
+ CLK(NULL, "uart1_ick", &dummy_ck, CK_443X),
+ CLK(NULL, "uart2_ick", &dummy_ck, CK_443X),
+ CLK(NULL, "uart3_ick", &dummy_ck, CK_443X),
+ CLK(NULL, "uart4_ick", &dummy_ck, CK_443X),
+ CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X),
+ CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X),
+ CLK("usbhs_tll", "usbtll_fck", &dummy_ck, CK_443X),
+ CLK("omap_wdt", "ick", &dummy_ck, CK_443X),
+ CLK(NULL, "timer_32k_ck", &sys_32k_ck, CK_443X),
+ /* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
+ CLK("omap_timer.1", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.2", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.3", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.4", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.9", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.10", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.11", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.5", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.6", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.7", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.8", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("4a318000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("48032000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("48034000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("48036000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("49038000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("4903a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("4903c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("4903e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X),
+};
+
+static const char *enable_init_clks[] = {
+ "emif1_fck",
+ "emif2_fck",
+ "gpmc_ick",
+ "l3_instr_ick",
+ "l3_main_3_ick",
+ "ocp_wp_noc_ick",
+};
+
+int __init omap4xxx_clk_init(void)
+{
+ u32 cpu_clkflg;
+ struct omap_clk *c;
+
+ if (cpu_is_omap443x()) {
+ cpu_mask = RATE_IN_4430;
+ cpu_clkflg = CK_443X;
+ } else if (cpu_is_omap446x() || cpu_is_omap447x()) {
+ cpu_mask = RATE_IN_4460 | RATE_IN_4430;
+ cpu_clkflg = CK_446X | CK_443X;
+
+ if (cpu_is_omap447x())
+ pr_warn("WARNING: OMAP4470 clock data incomplete!\n");
+ } else {
+ return 0;
+ }
+
+ for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
+ c++) {
+ if (c->cpu & cpu_clkflg) {
+ clkdev_add(&c->lk);
+ if (!__clk_init(NULL, c->lk.clk))
+ omap2_init_clk_hw_omap_clocks(c->lk.clk);
+ }
+ }
+
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index 8c5b13e7ee61..25b1feed480d 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -38,62 +38,88 @@
/* Private functions */
-static int _apll96_enable(struct clk *clk)
+/**
+ * omap2xxx_clk_apll_locked - is the APLL locked?
+ * @hw: struct clk_hw * of the APLL to check
+ *
+ * If the APLL IP block referred to by @hw indicates that it's locked,
+ * return true; otherwise, return false.
+ */
+static bool omap2xxx_clk_apll_locked(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ u32 r, apll_mask;
+
+ apll_mask = EN_APLL_LOCKED << clk->enable_bit;
+
+ r = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+
+ return ((r & apll_mask) == apll_mask) ? true : false;
+}
+
+int omap2_clk_apll96_enable(struct clk_hw *hw)
{
return omap2xxx_cm_apll96_enable();
}
-static int _apll54_enable(struct clk *clk)
+int omap2_clk_apll54_enable(struct clk_hw *hw)
{
return omap2xxx_cm_apll54_enable();
}
-static void _apll96_allow_idle(struct clk *clk)
+static void _apll96_allow_idle(struct clk_hw_omap *clk)
{
omap2xxx_cm_set_apll96_auto_low_power_stop();
}
-static void _apll96_deny_idle(struct clk *clk)
+static void _apll96_deny_idle(struct clk_hw_omap *clk)
{
omap2xxx_cm_set_apll96_disable_autoidle();
}
-static void _apll54_allow_idle(struct clk *clk)
+static void _apll54_allow_idle(struct clk_hw_omap *clk)
{
omap2xxx_cm_set_apll54_auto_low_power_stop();
}
-static void _apll54_deny_idle(struct clk *clk)
+static void _apll54_deny_idle(struct clk_hw_omap *clk)
{
omap2xxx_cm_set_apll54_disable_autoidle();
}
-static void _apll96_disable(struct clk *clk)
+void omap2_clk_apll96_disable(struct clk_hw *hw)
{
omap2xxx_cm_apll96_disable();
}
-static void _apll54_disable(struct clk *clk)
+void omap2_clk_apll54_disable(struct clk_hw *hw)
{
omap2xxx_cm_apll54_disable();
}
-/* Public data */
+unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return (omap2xxx_clk_apll_locked(hw)) ? 54000000 : 0;
+}
-const struct clkops clkops_apll96 = {
- .enable = _apll96_enable,
- .disable = _apll96_disable,
- .allow_idle = _apll96_allow_idle,
- .deny_idle = _apll96_deny_idle,
-};
+unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return (omap2xxx_clk_apll_locked(hw)) ? 96000000 : 0;
+}
-const struct clkops clkops_apll54 = {
- .enable = _apll54_enable,
- .disable = _apll54_disable,
+/* Public data */
+const struct clk_hw_omap_ops clkhwops_apll54 = {
.allow_idle = _apll54_allow_idle,
.deny_idle = _apll54_deny_idle,
};
+const struct clk_hw_omap_ops clkhwops_apll96 = {
+ .allow_idle = _apll96_allow_idle,
+ .deny_idle = _apll96_deny_idle,
+};
+
/* Public functions */
u32 omap2xxx_get_apll_clkin(void)
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c
index 399534c7843b..82572e277b97 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c
@@ -29,7 +29,7 @@
* REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
* instead. Add some mechanism to optionally enter this mode.
*/
-static void _allow_idle(struct clk *clk)
+static void _allow_idle(struct clk_hw_omap *clk)
{
if (!clk || !clk->dpll_data)
return;
@@ -43,7 +43,7 @@ static void _allow_idle(struct clk *clk)
*
* Disable DPLL automatic idle control. No return value.
*/
-static void _deny_idle(struct clk *clk)
+static void _deny_idle(struct clk_hw_omap *clk)
{
if (!clk || !clk->dpll_data)
return;
@@ -53,9 +53,7 @@ static void _deny_idle(struct clk *clk)
/* Public data */
-
-const struct clkops clkops_omap2xxx_dpll_ops = {
+const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll = {
.allow_idle = _allow_idle,
.deny_idle = _deny_idle,
};
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
index 825e44cdf1cf..d8620105c42a 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
@@ -40,7 +40,7 @@
* (currently defined as "dpll_ck" in the OMAP2xxx clock tree). Set
* during dpll_ck init and used later by omap2xxx_clk_get_core_rate().
*/
-static struct clk *dpll_core_ck;
+static struct clk_hw_omap *dpll_core_ck;
/**
* omap2xxx_clk_get_core_rate - return the CORE_CLK rate
@@ -104,13 +104,16 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
}
-unsigned long omap2_dpllcore_recalc(struct clk *clk)
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
{
return omap2xxx_clk_get_core_rate();
}
-int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
+int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 cur_rate, low, mult, div, valid_rate, done_rate;
u32 bypass = 0;
struct prcm_config tmpset;
@@ -188,8 +191,8 @@ int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
* statically defined, this code may need to change to increment some
* kind of use count on dpll_ck.
*/
-void omap2xxx_clkt_dpllcore_init(struct clk *clk)
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw)
{
WARN(dpll_core_ck, "dpll_core_ck already set - should never happen");
- dpll_core_ck = clk;
+ dpll_core_ck = to_clk_hw_omap(hw);
}
diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
index e1777371bb5e..19f54d433490 100644
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ b/arch/arm/mach-omap2/clkt2xxx_osc.c
@@ -35,7 +35,7 @@
* clk_enable/clk_disable()-based usecounting for osc_ck should be
* replaced with autoidle-based usecounting.
*/
-static int omap2_enable_osc_ck(struct clk *clk)
+int omap2_enable_osc_ck(struct clk_hw *clk)
{
u32 pcc;
@@ -53,7 +53,7 @@ static int omap2_enable_osc_ck(struct clk *clk)
* clk_enable/clk_disable()-based usecounting for osc_ck should be
* replaced with autoidle-based usecounting.
*/
-static void omap2_disable_osc_ck(struct clk *clk)
+void omap2_disable_osc_ck(struct clk_hw *clk)
{
u32 pcc;
@@ -62,13 +62,8 @@ static void omap2_disable_osc_ck(struct clk *clk)
__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
}
-const struct clkops clkops_oscck = {
- .enable = omap2_enable_osc_ck,
- .disable = omap2_disable_osc_ck,
-};
-
-unsigned long omap2_osc_clk_recalc(struct clk *clk)
+unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
+ unsigned long parent_rate)
{
return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
}
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c
index 46683b3c2461..f467d072cd02 100644
--- a/arch/arm/mach-omap2/clkt2xxx_sys.c
+++ b/arch/arm/mach-omap2/clkt2xxx_sys.c
@@ -40,9 +40,8 @@ u32 omap2xxx_get_sysclkdiv(void)
return div;
}
-unsigned long omap2xxx_sys_clk_recalc(struct clk *clk)
+unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
+ unsigned long parent_rate)
{
- return clk->parent->rate / omap2xxx_get_sysclkdiv();
+ return parent_rate / omap2xxx_get_sysclkdiv();
}
-
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 1c2041fbd718..ae2b35e76dc8 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -58,7 +58,8 @@ static unsigned long sys_ck_rate;
*
* Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
*/
-unsigned long omap2_table_mpu_recalc(struct clk *clk)
+unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
+ unsigned long parent_rate)
{
return curr_prcm_set->mpu_speed;
}
@@ -70,7 +71,8 @@ unsigned long omap2_table_mpu_recalc(struct clk *clk)
* Some might argue L3-DDR, others ARM, others IVA. This code is simple and
* just uses the ARM rates.
*/
-long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
+long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
const struct prcm_config *ptr;
long highest_rate;
@@ -93,7 +95,8 @@ long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
}
/* Sets basic clocks based on the specified rate */
-int omap2_select_table_rate(struct clk *clk, unsigned long rate)
+int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
u32 cur_rate, done_rate, bypass = 0, tmp;
const struct prcm_config *prcm;
diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index 6cf298e262f6..eb69acf21014 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -44,8 +44,10 @@
* Program the DPLL M2 divider with the rounded target rate. Returns
* -EINVAL upon error, or 0 upon success.
*/
-int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
+int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 new_div = 0;
u32 unlock_dll = 0;
u32 c;
@@ -63,7 +65,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
return -EINVAL;
sdrcrate = __clk_get_rate(sdrc_ick_p);
- clkrate = __clk_get_rate(clk);
+ clkrate = __clk_get_rate(hw->clk);
if (rate > clkrate)
sdrcrate <<= ((rate / clkrate) >> 1);
else
@@ -112,8 +114,6 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
0, 0, 0, 0);
- clk->rate = rate;
-
return 0;
}
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 53646facda45..0ec9f6fdf046 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -41,7 +41,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/bug.h>
@@ -58,11 +58,14 @@
* the element associated with the supplied parent clock address.
* Returns a pointer to the struct clksel on success or NULL on error.
*/
-static const struct clksel *_get_clksel_by_parent(struct clk *clk,
+static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
struct clk *src_clk)
{
const struct clksel *clks;
+ if (!src_clk)
+ return NULL;
+
for (clks = clk->clksel; clks->parent; clks++)
if (clks->parent == src_clk)
break; /* Found the requested parent */
@@ -70,7 +73,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
if (!clks->parent) {
/* This indicates a data problem */
WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
- __clk_get_name(clk), __clk_get_name(src_clk));
+ __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
return NULL;
}
@@ -78,64 +81,6 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
}
/**
- * _get_div_and_fieldval() - find the new clksel divisor and field value to use
- * @src_clk: planned new parent struct clk *
- * @clk: struct clk * that is being reparented
- * @field_val: pointer to a u32 to contain the register data for the divisor
- *
- * Given an intended new parent struct clk * @src_clk, and the struct
- * clk * @clk to the clock that is being reparented, find the
- * appropriate rate divisor for the new clock (returned as the return
- * value), and the corresponding register bitfield data to program to
- * reach that divisor (returned in the u32 pointed to by @field_val).
- * Returns 0 on error, or returns the newly-selected divisor upon
- * success (in this latter case, the corresponding register bitfield
- * value is passed back in the variable pointed to by @field_val)
- */
-static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
- u32 *field_val)
-{
- const struct clksel *clks;
- const struct clksel_rate *clkr, *max_clkr = NULL;
- u8 max_div = 0;
-
- clks = _get_clksel_by_parent(clk, src_clk);
- if (!clks)
- return 0;
-
- /*
- * Find the highest divisor (e.g., the one resulting in the
- * lowest rate) to use as the default. This should avoid
- * clock rates that are too high for the device. XXX A better
- * solution here would be to try to determine if there is a
- * divisor matching the original clock rate before the parent
- * switch, and if it cannot be found, to fall back to the
- * highest divisor.
- */
- for (clkr = clks->rates; clkr->div; clkr++) {
- if (!(clkr->flags & cpu_mask))
- continue;
-
- if (clkr->div > max_div) {
- max_div = clkr->div;
- max_clkr = clkr;
- }
- }
-
- if (max_div == 0) {
- /* This indicates an error in the clksel data */
- WARN(1, "clock: %s: could not find divisor for parent %s\n",
- __clk_get_name(clk),
- __clk_get_name(__clk_get_parent(src_clk)));
- return 0;
- }
-
- *field_val = max_clkr->val;
-
- return max_div;
-}
-
-/**
* _write_clksel_reg() - program a clock's clksel register in hardware
* @clk: struct clk * to program
* @v: clksel bitfield value to program (with LSB at bit 0)
@@ -148,7 +93,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
* take into account any time the hardware might take to switch the
* clock source.
*/
-static void _write_clksel_reg(struct clk *clk, u32 field_val)
+static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
{
u32 v;
@@ -171,13 +116,14 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
* before calling. Returns 0 on error or returns the actual integer divisor
* upon success.
*/
-static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
+static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
struct clk *parent;
- parent = __clk_get_parent(clk);
+ parent = __clk_get_parent(clk->hw.clk);
+
clks = _get_clksel_by_parent(clk, parent);
if (!clks)
return 0;
@@ -193,7 +139,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
if (!clkr->div) {
/* This indicates a data error */
WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
- __clk_get_name(clk), field_val, __clk_get_name(parent));
+ __clk_get_name(clk->hw.clk), field_val,
+ __clk_get_name(parent));
return 0;
}
@@ -210,7 +157,7 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
* register field value _before_ left-shifting (i.e., LSB is at bit
* 0); or returns 0xFFFFFFFF (~0) upon error.
*/
-static u32 _divisor_to_clksel(struct clk *clk, u32 div)
+static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
@@ -219,7 +166,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
/* should never happen */
WARN_ON(div == 0);
- parent = __clk_get_parent(clk);
+ parent = __clk_get_parent(clk->hw.clk);
clks = _get_clksel_by_parent(clk, parent);
if (!clks)
return ~0;
@@ -234,7 +181,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
if (!clkr->div) {
pr_err("clock: %s: could not find divisor %d for parent %s\n",
- __clk_get_name(clk), div, __clk_get_name(parent));
+ __clk_get_name(clk->hw.clk), div,
+ __clk_get_name(parent));
return ~0;
}
@@ -249,7 +197,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
* into the hardware, convert it into the actual divisor value, and
* return it; or return 0 on error.
*/
-static u32 _read_divisor(struct clk *clk)
+static u32 _read_divisor(struct clk_hw_omap *clk)
{
u32 v;
@@ -277,7 +225,8 @@ static u32 _read_divisor(struct clk *clk)
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
-u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
+ unsigned long target_rate,
u32 *new_div)
{
unsigned long test_rate;
@@ -288,9 +237,9 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
unsigned long parent_rate;
const char *clk_name;
- parent = __clk_get_parent(clk);
+ parent = __clk_get_parent(clk->hw.clk);
+ clk_name = __clk_get_name(clk->hw.clk);
parent_rate = __clk_get_rate(parent);
- clk_name = __clk_get_name(clk);
if (!clk->clksel || !clk->clksel_mask)
return ~0;
@@ -341,27 +290,35 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
*/
/**
- * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
- * @clk: OMAP clock struct ptr to use
+ * omap2_clksel_find_parent_index() - return the array index of the current
+ * hardware parent of @hw
+ * @hw: struct clk_hw * to find the current hardware parent of
*
- * Given a pointer @clk to a source-selectable struct clk, read the
- * hardware register and determine what its parent is currently set
- * to. Update @clk's .parent field with the appropriate clk ptr. No
- * return value.
+ * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
+ * clk_hw_omap record representing a source-selectable hardware clock,
+ * read the hardware register and determine what its parent is
+ * currently set to. Intended to be called only by the common clock
+ * framework struct clk_hw_ops.get_parent function pointer. Return
+ * the array index of this parent clock upon success -- there is no
+ * way to return an error, so if we encounter an error, just WARN()
+ * and pretend that we know that we're doing.
*/
-void omap2_init_clksel_parent(struct clk *clk)
+u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 r, found = 0;
struct clk *parent;
const char *clk_name;
+ int ret = 0, f = 0;
- if (!clk->clksel || !clk->clksel_mask)
- return;
+ parent = __clk_get_parent(hw->clk);
+ clk_name = __clk_get_name(hw->clk);
- parent = __clk_get_parent(clk);
- clk_name = __clk_get_name(clk);
+ /* XXX should be able to return an error */
+ WARN((!clk->clksel || !clk->clksel_mask),
+ "clock: %s: attempt to call on a non-clksel clock", clk_name);
r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
r >>= __ffs(clk->clksel_mask);
@@ -372,27 +329,21 @@ void omap2_init_clksel_parent(struct clk *clk)
continue;
if (clkr->val == r) {
- if (parent != clks->parent) {
- pr_debug("clock: %s: inited parent to %s (was %s)\n",
- clk_name,
- __clk_get_name(clks->parent),
- ((parent) ?
- __clk_get_name(parent) :
- "NULL"));
- clk_reparent(clk, clks->parent);
- }
found = 1;
+ ret = f;
}
}
+ f++;
}
/* This indicates a data error */
WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
clk_name, r);
- return;
+ return ret;
}
+
/**
* omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
* @clk: struct clk *
@@ -402,21 +353,23 @@ void omap2_init_clksel_parent(struct clk *clk)
* function. Returns the clock's current rate, based on its parent's rate
* and its current divisor setting in the hardware.
*/
-unsigned long omap2_clksel_recalc(struct clk *clk)
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
{
unsigned long rate;
u32 div = 0;
- struct clk *parent;
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
- div = _read_divisor(clk);
- if (div == 0)
- return __clk_get_rate(clk);
+ if (!parent_rate)
+ return 0;
- parent = __clk_get_parent(clk);
- rate = __clk_get_rate(parent) / div;
+ div = _read_divisor(clk);
+ if (!div)
+ rate = parent_rate;
+ else
+ rate = parent_rate / div;
- pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
- __clk_get_name(clk), rate, div);
+ pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
+ __clk_get_name(hw->clk), rate, div);
return rate;
}
@@ -432,8 +385,10 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
-long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+ unsigned long *parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 new_div;
return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
@@ -454,8 +409,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
* is changed, they will all be affected without any notification.
* Returns -EINVAL upon error, or 0 upon success.
*/
-int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 field_val, validrate, new_div = 0;
if (!clk->clksel || !clk->clksel_mask)
@@ -471,10 +428,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
_write_clksel_reg(clk, field_val);
- clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
-
- pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
- __clk_get_rate(clk));
+ pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
+ __clk_get_rate(hw->clk));
return 0;
}
@@ -499,32 +454,13 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
* affected without any notification. Returns -EINVAL upon error, or
* 0 upon success.
*/
-int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
{
- u32 field_val = 0;
- u32 parent_div;
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
if (!clk->clksel || !clk->clksel_mask)
return -EINVAL;
- parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
- if (!parent_div)
- return -EINVAL;
-
_write_clksel_reg(clk, field_val);
-
- clk_reparent(clk, new_parent);
-
- /* CLKSEL clocks follow their parents' rates, divided by a divisor */
- clk->rate = __clk_get_rate(new_parent);
-
- if (parent_div > 0)
- __clk_get_rate(clk) /= parent_div;
-
- pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
- __clk_get_name(clk),
- __clk_get_name(__clk_get_parent(clk)),
- __clk_get_rate(clk));
-
return 0;
}
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 8463cc356245..924c230f8948 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -16,7 +16,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/io.h>
#include <asm/div64.h>
@@ -76,7 +76,7 @@
* (assuming that it is counting N upwards), or -2 if the enclosing loop
* should skip to the next iteration (again assuming N is increasing).
*/
-static int _dpll_test_fint(struct clk *clk, u8 n)
+static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
{
struct dpll_data *dd;
long fint, fint_min, fint_max;
@@ -85,7 +85,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
dd = clk->dpll_data;
/* DPLL divider must result in a valid jitter correction val */
- fint = __clk_get_rate(__clk_get_parent(clk)) / n;
+ fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
if (cpu_is_omap24xx()) {
/* Should not be called for OMAP2, so warn if it is called */
@@ -186,15 +186,15 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
}
/* Public functions */
-
-void omap2_init_dpll_parent(struct clk *clk)
+u8 omap2_init_dpll_parent(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 v;
struct dpll_data *dd;
dd = clk->dpll_data;
if (!dd)
- return;
+ return -EINVAL;
v = __raw_readl(dd->control_reg);
v &= dd->enable_mask;
@@ -204,18 +204,18 @@ void omap2_init_dpll_parent(struct clk *clk)
if (cpu_is_omap24xx()) {
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
- clk_reparent(clk, dd->clk_bypass);
+ return 1;
} else if (cpu_is_omap34xx()) {
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
- clk_reparent(clk, dd->clk_bypass);
+ return 1;
} else if (soc_is_am33xx() || cpu_is_omap44xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
- clk_reparent(clk, dd->clk_bypass);
+ return 1;
}
- return;
+ return 0;
}
/**
@@ -232,7 +232,7 @@ void omap2_init_dpll_parent(struct clk *clk)
* locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
* if the clock @clk is not a DPLL.
*/
-u32 omap2_get_dpll_rate(struct clk *clk)
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
{
long long dpll_clk;
u32 dpll_mult, dpll_div, v;
@@ -288,8 +288,10 @@ u32 omap2_get_dpll_rate(struct clk *clk)
* (expensive) function again. Returns ~0 if the target rate cannot
* be rounded, or the rounded rate upon success.
*/
-long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+ unsigned long *parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int m, n, r, scaled_max_m;
unsigned long scaled_rt_rp;
unsigned long new_rate = 0;
@@ -303,7 +305,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
dd = clk->dpll_data;
ref_rate = __clk_get_rate(dd->clk_ref);
- clk_name = __clk_get_name(clk);
+ clk_name = __clk_get_name(hw->clk);
pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
clk_name, target_rate);
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index fe774a09dd0c..f10eb03ce3e2 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -11,7 +11,7 @@
#undef DEBUG
#include <linux/kernel.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/io.h>
@@ -23,7 +23,7 @@
/* Private functions */
/* XXX */
-void omap2_clkt_iclk_allow_idle(struct clk *clk)
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
{
u32 v, r;
@@ -35,7 +35,7 @@ void omap2_clkt_iclk_allow_idle(struct clk *clk)
}
/* XXX */
-void omap2_clkt_iclk_deny_idle(struct clk *clk)
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
{
u32 v, r;
@@ -48,33 +48,17 @@ void omap2_clkt_iclk_deny_idle(struct clk *clk)
/* Public data */
-const struct clkops clkops_omap2_iclk_dflt_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_companion = omap2_clk_dflt_find_companion,
- .find_idlest = omap2_clk_dflt_find_idlest,
+const struct clk_hw_omap_ops clkhwops_iclk = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
};
-const struct clkops clkops_omap2_iclk_dflt = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_iclk_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
+ .find_idlest = omap2_clk_dflt_find_idlest,
+ .find_companion = omap2_clk_dflt_find_companion,
};
-const struct clkops clkops_omap2_iclk_idle_only = {
- .allow_idle = omap2_clkt_iclk_allow_idle,
- .deny_idle = omap2_clkt_iclk_deny_idle,
-};
-const struct clkops clkops_omap2_mdmclk_dflt_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_companion = omap2_clk_dflt_find_companion,
- .find_idlest = omap2_clk_dflt_find_idlest,
- .allow_idle = omap2_clkt_iclk_allow_idle,
- .deny_idle = omap2_clkt_iclk_deny_idle,
-};
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index e381d991092c..e4ec3a69ee2e 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -20,7 +20,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/delay.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/bitops.h>
@@ -55,9 +55,28 @@ u16 cpu_mask;
*/
static bool clkdm_control = true;
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clockfw_lock);
+static LIST_HEAD(clk_hw_omap_clocks);
+
+/*
+ * Used for clocks that have the same value as the parent clock,
+ * divided by some factor
+ */
+unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_hw_omap *oclk;
+
+ if (!hw) {
+ pr_warn("%s: hw is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ oclk = to_clk_hw_omap(hw);
+
+ WARN_ON(!oclk->fixed_div);
+
+ return parent_rate / oclk->fixed_div;
+}
/*
* OMAP2+ specific clock functions
@@ -109,7 +128,7 @@ static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
* belong in the clock code and will be moved in the medium term to
* module-dependent code. No return value.
*/
-static void _omap2_module_wait_ready(struct clk *clk)
+static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
{
void __iomem *companion_reg, *idlest_reg;
u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
@@ -124,12 +143,11 @@ static void _omap2_module_wait_ready(struct clk *clk)
}
clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-
r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
if (r) {
/* IDLEST register not in the CM module */
_wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
- clk->name);
+ __clk_get_name(clk->hw.clk));
} else {
cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
};
@@ -145,15 +163,16 @@ static void _omap2_module_wait_ready(struct clk *clk)
* clockdomain pointer, and save it into the struct clk. Intended to be
* called during clk_register(). No return value.
*/
-void omap2_init_clk_clkdm(struct clk *clk)
+void omap2_init_clk_clkdm(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct clockdomain *clkdm;
const char *clk_name;
if (!clk->clkdm_name)
return;
- clk_name = __clk_get_name(clk);
+ clk_name = __clk_get_name(hw->clk);
clkdm = clkdm_lookup(clk->clkdm_name);
if (clkdm) {
@@ -200,8 +219,8 @@ void __init omap2_clk_disable_clkdm_control(void)
* associate this type of code with per-module data structures to
* avoid this issue, and remove the casts. No return value.
*/
-void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
- u8 *other_bit)
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+ void __iomem **other_reg, u8 *other_bit)
{
u32 r;
@@ -229,8 +248,8 @@ void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
* register address ID (e.g., that CM_FCLKEN2 corresponds to
* CM_IDLEST2). This is not true for all modules. No return value.
*/
-void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
- u8 *idlest_bit, u8 *idlest_val)
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+ void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
{
u32 r;
@@ -252,16 +271,44 @@ void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
}
-int omap2_dflt_clk_enable(struct clk *clk)
+/**
+ * omap2_dflt_clk_enable - enable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to enable
+ *
+ * Enable the clock @hw in the hardware. We first call into the OMAP
+ * clockdomain code to "enable" the corresponding clockdomain if this
+ * is the first enabled user of the clockdomain. Then program the
+ * hardware to enable the clock. Then wait for the IP block that uses
+ * this clock to leave idle (if applicable). Returns the error value
+ * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
+ * if @hw has a null clock enable_reg, or zero upon success.
+ */
+int omap2_dflt_clk_enable(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk;
u32 v;
+ int ret = 0;
+
+ clk = to_clk_hw_omap(hw);
+
+ if (clkdm_control && clk->clkdm) {
+ ret = clkdm_clk_enable(clk->clkdm, hw->clk);
+ if (ret) {
+ WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
+ __func__, __clk_get_name(hw->clk),
+ clk->clkdm->name, ret);
+ return ret;
+ }
+ }
if (unlikely(clk->enable_reg == NULL)) {
- pr_err("clock.c: Enable for %s without enable code\n",
- clk->name);
- return 0; /* REVISIT: -EINVAL */
+ pr_err("%s: %s missing enable_reg\n", __func__,
+ __clk_get_name(hw->clk));
+ ret = -EINVAL;
+ goto err;
}
+ /* FIXME should not have INVERT_ENABLE bit here */
v = __raw_readl(clk->enable_reg);
if (clk->flags & INVERT_ENABLE)
v &= ~(1 << clk->enable_bit);
@@ -270,22 +317,39 @@ int omap2_dflt_clk_enable(struct clk *clk)
__raw_writel(v, clk->enable_reg);
v = __raw_readl(clk->enable_reg); /* OCP barrier */
- if (clk->ops->find_idlest)
+ if (clk->ops && clk->ops->find_idlest)
_omap2_module_wait_ready(clk);
return 0;
+
+err:
+ if (clkdm_control && clk->clkdm)
+ clkdm_clk_disable(clk->clkdm, hw->clk);
+ return ret;
}
-void omap2_dflt_clk_disable(struct clk *clk)
+/**
+ * omap2_dflt_clk_disable - disable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to disable
+ *
+ * Disable the clock @hw in the hardware, and call into the OMAP
+ * clockdomain code to "disable" the corresponding clockdomain if all
+ * clocks/hwmods in that clockdomain are now disabled. No return
+ * value.
+ */
+void omap2_dflt_clk_disable(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk;
u32 v;
+ clk = to_clk_hw_omap(hw);
if (!clk->enable_reg) {
/*
- * 'Independent' here refers to a clock which is not
+ * 'independent' here refers to a clock which is not
* controlled by its parent.
*/
- pr_err("clock: clk_disable called on independent clock %s which has no enable_reg\n", clk->name);
+ pr_err("%s: independent clock %s has no enable_reg\n",
+ __func__, __clk_get_name(hw->clk));
return;
}
@@ -296,191 +360,213 @@ void omap2_dflt_clk_disable(struct clk *clk)
v &= ~(1 << clk->enable_bit);
__raw_writel(v, clk->enable_reg);
/* No OCP barrier needed here since it is a disable operation */
-}
-
-const struct clkops clkops_omap2_dflt_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_companion = omap2_clk_dflt_find_companion,
- .find_idlest = omap2_clk_dflt_find_idlest,
-};
-const struct clkops clkops_omap2_dflt = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
-};
+ if (clkdm_control && clk->clkdm)
+ clkdm_clk_disable(clk->clkdm, hw->clk);
+}
/**
- * omap2_clk_disable - disable a clock, if the system is not using it
- * @clk: struct clk * to disable
+ * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being enabled
*
- * Decrements the usecount on struct clk @clk. If there are no users
- * left, call the clkops-specific clock disable function to disable it
- * in hardware. If the clock is part of a clockdomain (which they all
- * should be), request that the clockdomain be disabled. (It too has
- * a usecount, and so will not be disabled in the hardware until it no
- * longer has any users.) If the clock has a parent clock (most of
- * them do), then call ourselves, recursing on the parent clock. This
- * can cause an entire branch of the clock tree to be powered off by
- * simply disabling one clock. Intended to be called with the clockfw_lock
- * spinlock held. No return value.
+ * Increment the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 1, the clockdomain will be "enabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_enable() as
+ * their enable function pointer. Passes along the return value of
+ * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
+ * clockdomain, or 0 if clock framework-based clockdomain control is
+ * not implemented.
*/
-void omap2_clk_disable(struct clk *clk)
+int omap2_clkops_enable_clkdm(struct clk_hw *hw)
{
- if (clk->usecount == 0) {
- WARN(1, "clock: %s: omap2_clk_disable() called, but usecount already 0?", clk->name);
- return;
- }
-
- pr_debug("clock: %s: decrementing usecount\n", clk->name);
+ struct clk_hw_omap *clk;
+ int ret = 0;
- clk->usecount--;
+ clk = to_clk_hw_omap(hw);
- if (clk->usecount > 0)
- return;
+ if (unlikely(!clk->clkdm)) {
+ pr_err("%s: %s: no clkdm set ?!\n", __func__,
+ __clk_get_name(hw->clk));
+ return -EINVAL;
+ }
- pr_debug("clock: %s: disabling in hardware\n", clk->name);
+ if (unlikely(clk->enable_reg))
+ pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
+ __clk_get_name(hw->clk));
- if (clk->ops && clk->ops->disable) {
- trace_clock_disable(clk->name, 0, smp_processor_id());
- clk->ops->disable(clk);
+ if (!clkdm_control) {
+ pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+ __func__, __clk_get_name(hw->clk));
+ return 0;
}
- if (clkdm_control && clk->clkdm)
- clkdm_clk_disable(clk->clkdm, clk);
+ ret = clkdm_clk_enable(clk->clkdm, hw->clk);
+ WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
+ __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
- if (clk->parent)
- omap2_clk_disable(clk->parent);
+ return ret;
}
/**
- * omap2_clk_enable - request that the system enable a clock
- * @clk: struct clk * to enable
+ * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being disabled
*
- * Increments the usecount on struct clk @clk. If there were no users
- * previously, then recurse up the clock tree, enabling all of the
- * clock's parents and all of the parent clockdomains, and finally,
- * enabling @clk's clockdomain, and @clk itself. Intended to be
- * called with the clockfw_lock spinlock held. Returns 0 upon success
- * or a negative error code upon failure.
+ * Decrement the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 0, the clockdomain will be "disabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
+ * disable function pointer. No return value.
*/
-int omap2_clk_enable(struct clk *clk)
+void omap2_clkops_disable_clkdm(struct clk_hw *hw)
{
- int ret;
+ struct clk_hw_omap *clk;
- pr_debug("clock: %s: incrementing usecount\n", clk->name);
+ clk = to_clk_hw_omap(hw);
- clk->usecount++;
-
- if (clk->usecount > 1)
- return 0;
-
- pr_debug("clock: %s: enabling in hardware\n", clk->name);
-
- if (clk->parent) {
- ret = omap2_clk_enable(clk->parent);
- if (ret) {
- WARN(1, "clock: %s: could not enable parent %s: %d\n",
- clk->name, clk->parent->name, ret);
- goto oce_err1;
- }
+ if (unlikely(!clk->clkdm)) {
+ pr_err("%s: %s: no clkdm set ?!\n", __func__,
+ __clk_get_name(hw->clk));
+ return;
}
- if (clkdm_control && clk->clkdm) {
- ret = clkdm_clk_enable(clk->clkdm, clk);
- if (ret) {
- WARN(1, "clock: %s: could not enable clockdomain %s: %d\n",
- clk->name, clk->clkdm->name, ret);
- goto oce_err2;
- }
- }
+ if (unlikely(clk->enable_reg))
+ pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
+ __clk_get_name(hw->clk));
- if (clk->ops && clk->ops->enable) {
- trace_clock_enable(clk->name, 1, smp_processor_id());
- ret = clk->ops->enable(clk);
- if (ret) {
- WARN(1, "clock: %s: could not enable: %d\n",
- clk->name, ret);
- goto oce_err3;
- }
+ if (!clkdm_control) {
+ pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+ __func__, __clk_get_name(hw->clk));
+ return;
}
- return 0;
-
-oce_err3:
- if (clkdm_control && clk->clkdm)
- clkdm_clk_disable(clk->clkdm, clk);
-oce_err2:
- if (clk->parent)
- omap2_clk_disable(clk->parent);
-oce_err1:
- clk->usecount--;
-
- return ret;
+ clkdm_clk_disable(clk->clkdm, hw->clk);
}
-/* Given a clock and a rate apply a clock specific rounding function */
-long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
+/**
+ * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
+ * @hw: struct clk_hw * to check
+ *
+ * Return 1 if the clock represented by @hw is enabled in the
+ * hardware, or 0 otherwise. Intended for use in the struct
+ * clk_ops.is_enabled function pointer.
+ */
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
{
- if (clk->round_rate)
- return clk->round_rate(clk, rate);
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ u32 v;
- return clk->rate;
+ v = __raw_readl(clk->enable_reg);
+
+ if (clk->flags & INVERT_ENABLE)
+ v ^= BIT(clk->enable_bit);
+
+ v &= BIT(clk->enable_bit);
+
+ return v ? 1 : 0;
}
-/* Set the clock rate for a clock source */
-int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+static int __initdata mpurate;
+
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init omap_clk_setup(char *str)
{
- int ret = -EINVAL;
+ get_option(&str, &mpurate);
- pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
+ if (!mpurate)
+ return 1;
- /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
- if (clk->set_rate) {
- trace_clock_set_rate(clk->name, rate, smp_processor_id());
- ret = clk->set_rate(clk, rate);
- }
+ if (mpurate < 1000)
+ mpurate *= 1000000;
- return ret;
+ return 1;
}
+__setup("mpurate=", omap_clk_setup);
-int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+/**
+ * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
+ * @clk: struct clk * to initialize
+ *
+ * Add an OMAP clock @clk to the internal list of OMAP clocks. Used
+ * temporarily for autoidle handling, until this support can be
+ * integrated into the common clock framework code in some way. No
+ * return value.
+ */
+void omap2_init_clk_hw_omap_clocks(struct clk *clk)
{
- if (!clk->clksel)
- return -EINVAL;
+ struct clk_hw_omap *c;
- if (clk->parent == new_parent)
- return 0;
+ if (__clk_get_flags(clk) & CLK_IS_BASIC)
+ return;
- return omap2_clksel_set_parent(clk, new_parent);
+ c = to_clk_hw_omap(__clk_get_hw(clk));
+ list_add(&c->node, &clk_hw_omap_clocks);
}
-/*
- * OMAP2+ clock reset and init functions
+/**
+ * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Enable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them. This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code. Returns 0.
*/
+int omap2_clk_enable_autoidle_all(void)
+{
+ struct clk_hw_omap *c;
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-void omap2_clk_disable_unused(struct clk *clk)
+ list_for_each_entry(c, &clk_hw_omap_clocks, node)
+ if (c->ops && c->ops->allow_idle)
+ c->ops->allow_idle(c);
+ return 0;
+}
+
+/**
+ * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Disable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them. This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code. Returns 0.
+ */
+int omap2_clk_disable_autoidle_all(void)
{
- u32 regval32, v;
+ struct clk_hw_omap *c;
- v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
+ list_for_each_entry(c, &clk_hw_omap_clocks, node)
+ if (c->ops && c->ops->deny_idle)
+ c->ops->deny_idle(c);
+ return 0;
+}
- regval32 = __raw_readl(clk->enable_reg);
- if ((regval32 & (1 << clk->enable_bit)) == v)
- return;
+/**
+ * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
+ * @clk_names: ptr to an array of strings of clock names to enable
+ * @num_clocks: number of clock names in @clk_names
+ *
+ * Prepare and enable a list of clocks, named by @clk_names. No
+ * return value. XXX Deprecated; only needed until these clocks are
+ * properly claimed and enabled by the drivers or core code that uses
+ * them. XXX What code disables & calls clk_put on these clocks?
+ */
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+{
+ struct clk *init_clk;
+ int i;
- pr_debug("Disabling unused clock \"%s\"\n", clk->name);
- if (cpu_is_omap34xx()) {
- omap2_clk_enable(clk);
- omap2_clk_disable(clk);
- } else {
- clk->ops->disable(clk);
+ for (i = 0; i < num_clocks; i++) {
+ init_clk = clk_get(NULL, clk_names[i]);
+ clk_prepare_enable(init_clk);
}
- if (clk->clkdm != NULL)
- pwrdm_state_switch(clk->clkdm->pwrdm.ptr);
}
-#endif
+
+const struct clk_hw_omap_ops clkhwops_wait = {
+ .find_idlest = omap2_clk_dflt_find_idlest,
+ .find_companion = omap2_clk_dflt_find_companion,
+};
/**
* omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
@@ -512,14 +598,12 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
r = clk_set_rate(mpurate_ck, mpurate);
if (IS_ERR_VALUE(r)) {
WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
- mpurate_ck->name, mpurate, r);
+ mpurate_ck_name, mpurate, r);
clk_put(mpurate_ck);
return -EINVAL;
}
calibrate_delay();
- recalculate_root_clocks();
-
clk_put(mpurate_ck);
return 0;
@@ -563,513 +647,3 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
(clk_get_rate(core_ck) / 1000000),
(clk_get_rate(mpu_ck) / 1000000));
}
-
-/* Common data */
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
- int ret;
-
- if (clk == NULL || IS_ERR(clk))
- return -EINVAL;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap2_clk_enable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- if (clk == NULL || IS_ERR(clk))
- return;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->usecount == 0) {
- pr_err("Trying disable clock %s with 0 usecount\n",
- clk->name);
- WARN_ON(1);
- goto out;
- }
-
- omap2_clk_disable(clk);
-
-out:
- spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- unsigned long flags;
- unsigned long ret;
-
- if (clk == NULL || IS_ERR(clk))
- return 0;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = clk->rate;
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/*
- * Optional clock functions defined in include/linux/clk.h
- */
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long flags;
- long ret;
-
- if (clk == NULL || IS_ERR(clk))
- return 0;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap2_clk_round_rate(clk, rate);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long flags;
- int ret = -EINVAL;
-
- if (clk == NULL || IS_ERR(clk))
- return ret;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap2_clk_set_rate(clk, rate);
- if (ret == 0)
- propagate_rate(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- unsigned long flags;
- int ret = -EINVAL;
-
- if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
- return ret;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->usecount == 0) {
- ret = omap2_clk_set_parent(clk, parent);
- if (ret == 0)
- propagate_rate(clk);
- } else {
- ret = -EBUSY;
- }
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
- return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-/*
- * OMAP specific clock functions shared between omap1 and omap2
- */
-
-int __initdata mpurate;
-
-/*
- * By default we use the rate set by the bootloader.
- * You can override this with mpurate= cmdline option.
- */
-static int __init omap_clk_setup(char *str)
-{
- get_option(&str, &mpurate);
-
- if (!mpurate)
- return 1;
-
- if (mpurate < 1000)
- mpurate *= 1000000;
-
- return 1;
-}
-__setup("mpurate=", omap_clk_setup);
-
-/* Used for clocks that always have same value as the parent clock */
-unsigned long followparent_recalc(struct clk *clk)
-{
- return clk->parent->rate;
-}
-
-/*
- * Used for clocks that have the same value as the parent clock,
- * divided by some factor
- */
-unsigned long omap_fixed_divisor_recalc(struct clk *clk)
-{
- WARN_ON(!clk->fixed_div);
-
- return clk->parent->rate / clk->fixed_div;
-}
-
-void clk_reparent(struct clk *child, struct clk *parent)
-{
- list_del_init(&child->sibling);
- if (parent)
- list_add(&child->sibling, &parent->children);
- child->parent = parent;
-
- /* now do the debugfs renaming to reattach the child
- to the proper parent */
-}
-
-/* Propagate rate to children */
-void propagate_rate(struct clk *tclk)
-{
- struct clk *clkp;
-
- list_for_each_entry(clkp, &tclk->children, sibling) {
- if (clkp->recalc)
- clkp->rate = clkp->recalc(clkp);
- propagate_rate(clkp);
- }
-}
-
-static LIST_HEAD(root_clks);
-
-/**
- * recalculate_root_clocks - recalculate and propagate all root clocks
- *
- * Recalculates all root clocks (clocks with no parent), which if the
- * clock's .recalc is set correctly, should also propagate their rates.
- * Called at init.
- */
-void recalculate_root_clocks(void)
-{
- struct clk *clkp;
-
- list_for_each_entry(clkp, &root_clks, sibling) {
- if (clkp->recalc)
- clkp->rate = clkp->recalc(clkp);
- propagate_rate(clkp);
- }
-}
-
-/**
- * clk_preinit - initialize any fields in the struct clk before clk init
- * @clk: struct clk * to initialize
- *
- * Initialize any struct clk fields needed before normal clk initialization
- * can run. No return value.
- */
-void clk_preinit(struct clk *clk)
-{
- INIT_LIST_HEAD(&clk->children);
-}
-
-int clk_register(struct clk *clk)
-{
- if (clk == NULL || IS_ERR(clk))
- return -EINVAL;
-
- /*
- * trap out already registered clocks
- */
- if (clk->node.next || clk->node.prev)
- return 0;
-
- mutex_lock(&clocks_mutex);
- if (clk->parent)
- list_add(&clk->sibling, &clk->parent->children);
- else
- list_add(&clk->sibling, &root_clks);
-
- list_add(&clk->node, &clocks);
- if (clk->init)
- clk->init(clk);
- mutex_unlock(&clocks_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
- if (clk == NULL || IS_ERR(clk))
- return;
-
- mutex_lock(&clocks_mutex);
- list_del(&clk->sibling);
- list_del(&clk->node);
- mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
-void clk_enable_init_clocks(void)
-{
- struct clk *clkp;
-
- list_for_each_entry(clkp, &clocks, node)
- if (clkp->flags & ENABLE_ON_INIT)
- clk_enable(clkp);
-}
-
-/**
- * omap_clk_get_by_name - locate OMAP struct clk by its name
- * @name: name of the struct clk to locate
- *
- * Locate an OMAP struct clk by its name. Assumes that struct clk
- * names are unique. Returns NULL if not found or a pointer to the
- * struct clk if found.
- */
-struct clk *omap_clk_get_by_name(const char *name)
-{
- struct clk *c;
- struct clk *ret = NULL;
-
- mutex_lock(&clocks_mutex);
-
- list_for_each_entry(c, &clocks, node) {
- if (!strcmp(c->name, name)) {
- ret = c;
- break;
- }
- }
-
- mutex_unlock(&clocks_mutex);
-
- return ret;
-}
-
-int omap_clk_enable_autoidle_all(void)
-{
- struct clk *c;
- unsigned long flags;
-
- spin_lock_irqsave(&clockfw_lock, flags);
-
- list_for_each_entry(c, &clocks, node)
- if (c->ops->allow_idle)
- c->ops->allow_idle(c);
-
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return 0;
-}
-
-int omap_clk_disable_autoidle_all(void)
-{
- struct clk *c;
- unsigned long flags;
-
- spin_lock_irqsave(&clockfw_lock, flags);
-
- list_for_each_entry(c, &clocks, node)
- if (c->ops->deny_idle)
- c->ops->deny_idle(c);
-
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return 0;
-}
-
-/*
- * Low level helpers
- */
-static int clkll_enable_null(struct clk *clk)
-{
- return 0;
-}
-
-static void clkll_disable_null(struct clk *clk)
-{
-}
-
-const struct clkops clkops_null = {
- .enable = clkll_enable_null,
- .disable = clkll_disable_null,
-};
-
-/*
- * Dummy clock
- *
- * Used for clock aliases that are needed on some OMAPs, but not others
- */
-struct clk dummy_ck = {
- .name = "dummy",
- .ops = &clkops_null,
-};
-
-/*
- *
- */
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Disable any unused clocks left on by the bootloader
- */
-static int __init clk_disable_unused(void)
-{
- struct clk *ck;
- unsigned long flags;
-
- pr_info("clock: disabling unused clocks to save power\n");
-
- spin_lock_irqsave(&clockfw_lock, flags);
- list_for_each_entry(ck, &clocks, node) {
- if (ck->ops == &clkops_null)
- continue;
-
- if (ck->usecount > 0 || !ck->enable_reg)
- continue;
-
- omap2_clk_disable_unused(ck);
- }
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return 0;
-}
-late_initcall(clk_disable_unused);
-late_initcall(omap_clk_enable_autoidle_all);
-#endif
-
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-/*
- * debugfs support to trace clock tree hierarchy and attributes
- */
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static struct dentry *clk_debugfs_root;
-
-static int clk_dbg_show_summary(struct seq_file *s, void *unused)
-{
- struct clk *c;
- struct clk *pa;
-
- mutex_lock(&clocks_mutex);
- seq_printf(s, "%-30s %-30s %-10s %s\n",
- "clock-name", "parent-name", "rate", "use-count");
-
- list_for_each_entry(c, &clocks, node) {
- pa = c->parent;
- seq_printf(s, "%-30s %-30s %-10lu %d\n",
- c->name, pa ? pa->name : "none", c->rate,
- c->usecount);
- }
- mutex_unlock(&clocks_mutex);
-
- return 0;
-}
-
-static int clk_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_dbg_show_summary, inode->i_private);
-}
-
-static const struct file_operations debug_clock_fops = {
- .open = clk_dbg_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int clk_debugfs_register_one(struct clk *c)
-{
- int err;
- struct dentry *d;
- struct clk *pa = c->parent;
-
- d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
- if (!d)
- return -ENOMEM;
- c->dent = d;
-
- d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- return 0;
-
-err_out:
- debugfs_remove_recursive(c->dent);
- return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
- int err;
- struct clk *pa = c->parent;
-
- if (pa && !pa->dent) {
- err = clk_debugfs_register(pa);
- if (err)
- return err;
- }
-
- if (!c->dent) {
- err = clk_debugfs_register_one(c);
- if (err)
- return err;
- }
- return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
- struct clk *c;
- struct dentry *d;
- int err;
-
- d = debugfs_create_dir("clock", NULL);
- if (!d)
- return -ENOMEM;
- clk_debugfs_root = d;
-
- list_for_each_entry(c, &clocks, node) {
- err = clk_debugfs_register(c);
- if (err)
- goto err_out;
- }
-
- d = debugfs_create_file("summary", S_IRUGO,
- d, NULL, &debug_clock_fops);
- if (!d)
- return -ENOMEM;
-
- return 0;
-err_out:
- debugfs_remove_recursive(clk_debugfs_root);
- return err;
-}
-late_initcall(clk_debugfs_init);
-
-#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
-
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index ff9789bc0fd1..9917f793c3b6 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -20,6 +20,7 @@
#include <linux/list.h>
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
struct omap_clk {
u16 cpu;
@@ -52,43 +53,84 @@ struct omap_clk {
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
#define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX)
-struct module;
-struct clk;
struct clockdomain;
-
-/* Temporary, needed during the common clock framework conversion */
-#define __clk_get_name(clk) (clk->name)
-#define __clk_get_parent(clk) (clk->parent)
-#define __clk_get_rate(clk) (clk->rate)
-
-/**
- * struct clkops - some clock function pointers
- * @enable: fn ptr that enables the current clock in hardware
- * @disable: fn ptr that enables the current clock in hardware
- * @find_idlest: function returning the IDLEST register for the clock's IP blk
- * @find_companion: function returning the "companion" clk reg for the clock
- * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
- * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
- *
- * A "companion" clk is an accompanying clock to the one being queried
- * that must be enabled for the IP module connected to the clock to
- * become accessible by the hardware. Neither @find_idlest nor
- * @find_companion should be needed; that information is IP
- * block-specific; the hwmod code has been created to handle this, but
- * until hwmod data is ready and drivers have been converted to use PM
- * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and
- * @find_companion must, unfortunately, remain.
- */
-struct clkops {
- int (*enable)(struct clk *);
- void (*disable)(struct clk *);
- void (*find_idlest)(struct clk *, void __iomem **,
- u8 *, u8 *);
- void (*find_companion)(struct clk *, void __iomem **,
- u8 *);
- void (*allow_idle)(struct clk *);
- void (*deny_idle)(struct clk *);
-};
+#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
+
+#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
+ static struct clk _name = { \
+ .name = #_name, \
+ .hw = &_name##_hw.hw, \
+ .parent_names = _parent_array_name, \
+ .num_parents = ARRAY_SIZE(_parent_array_name), \
+ .ops = &_clkops_name, \
+ };
+
+#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
+ static struct clk_hw_omap _name##_hw = { \
+ .hw = { \
+ .clk = &_name, \
+ }, \
+ .clkdm_name = _clkdm_name, \
+ };
+
+#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel, \
+ _clksel_reg, _clksel_mask, \
+ _parent_names, _ops) \
+ static struct clk _name; \
+ static struct clk_hw_omap _name##_hw = { \
+ .hw = { \
+ .clk = &_name, \
+ }, \
+ .clksel = _clksel, \
+ .clksel_reg = _clksel_reg, \
+ .clksel_mask = _clksel_mask, \
+ .clkdm_name = _clkdm_name, \
+ }; \
+ DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
+
+#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel, \
+ _clksel_reg, _clksel_mask, \
+ _enable_reg, _enable_bit, \
+ _hwops, _parent_names, _ops) \
+ static struct clk _name; \
+ static struct clk_hw_omap _name##_hw = { \
+ .hw = { \
+ .clk = &_name, \
+ }, \
+ .ops = _hwops, \
+ .enable_reg = _enable_reg, \
+ .enable_bit = _enable_bit, \
+ .clksel = _clksel, \
+ .clksel_reg = _clksel_reg, \
+ .clksel_mask = _clksel_mask, \
+ .clkdm_name = _clkdm_name, \
+ }; \
+ DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
+
+#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name, \
+ _parent_ptr, _flags, \
+ _clksel_reg, _clksel_mask) \
+ static const struct clksel _name##_div[] = { \
+ { \
+ .parent = _parent_ptr, \
+ .rates = div31_1to31_rates \
+ }, \
+ { .parent = NULL }, \
+ }; \
+ static struct clk _name; \
+ static const char *_name##_parent_names[] = { \
+ _parent_name, \
+ }; \
+ static struct clk_hw_omap _name##_hw = { \
+ .hw = { \
+ .clk = &_name, \
+ }, \
+ .clksel = _name##_div, \
+ .clksel_reg = _clksel_reg, \
+ .clksel_mask = _clksel_mask, \
+ .ops = &clkhwops_omap4_dpllmx, \
+ }; \
+ DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
/* struct clksel_rate.flags possibilities */
#define RATE_IN_242X (1 << 0)
@@ -229,22 +271,10 @@ struct dpll_data {
#define CLOCK_CLKOUTX2 (1 << 5)
/**
- * struct clk - OMAP struct clk
+ * struct clk_hw_omap - OMAP struct clk
* @node: list_head connecting this clock into the full clock list
- * @ops: struct clkops * for this clock
- * @name: the name of the clock in the hardware (used in hwmod data and debug)
- * @parent: pointer to this clock's parent struct clk
- * @children: list_head connecting to the child clks' @sibling list_heads
- * @sibling: list_head connecting this clk to its parent clk's @children
- * @rate: current clock rate
* @enable_reg: register to write to enable the clock (see @enable_bit)
- * @recalc: fn ptr that returns the clock's current rate
- * @set_rate: fn ptr that can change the clock's current rate
- * @round_rate: fn ptr that can round the clock's current rate
- * @init: fn ptr to do clock-specific initialization
* @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
- * @usecount: number of users that have requested this clock to be enabled
- * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
* @flags: see "struct clk.flags possibilities" above
* @clksel_reg: for clksel clks, register va containing src/divisor select
* @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
@@ -258,39 +288,17 @@ struct dpll_data {
* XXX @rate_offset, @src_offset should probably be removed and OMAP1
* clock code converted to use clksel.
*
- * XXX @usecount is poorly named. It should be "enable_count" or
- * something similar. "users" in the description refers to kernel
- * code (core code or drivers) that have called clk_enable() and not
- * yet called clk_disable(); the usecount of parent clocks is also
- * incremented by the clock code when clk_enable() is called on child
- * clocks and decremented by the clock code when clk_disable() is
- * called on child clocks.
- *
- * XXX @clkdm, @usecount, @children, @sibling should be marked for
- * internal use only.
- *
- * @children and @sibling are used to optimize parent-to-child clock
- * tree traversals. (child-to-parent traversals use @parent.)
- *
- * XXX The notion of the clock's current rate probably needs to be
- * separated from the clock's target rate.
*/
-struct clk {
+
+struct clk_hw_omap_ops;
+
+struct clk_hw_omap {
+ struct clk_hw hw;
struct list_head node;
- const struct clkops *ops;
- const char *name;
- struct clk *parent;
- struct list_head children;
- struct list_head sibling; /* node for children */
- unsigned long rate;
+ unsigned long fixed_rate;
+ u8 fixed_div;
void __iomem *enable_reg;
- unsigned long (*recalc)(struct clk *);
- int (*set_rate)(struct clk *, unsigned long);
- long (*round_rate)(struct clk *, unsigned long);
- void (*init)(struct clk *);
u8 enable_bit;
- s8 usecount;
- u8 fixed_div;
u8 flags;
void __iomem *clksel_reg;
u32 clksel_mask;
@@ -298,42 +306,22 @@ struct clk {
struct dpll_data *dpll_data;
const char *clkdm_name;
struct clockdomain *clkdm;
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
- struct dentry *dent; /* For visible tree hierarchy */
-#endif
+ const struct clk_hw_omap_ops *ops;
};
-struct clk_functions {
- int (*clk_enable)(struct clk *clk);
- void (*clk_disable)(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);
- void (*clk_allow_idle)(struct clk *clk);
- void (*clk_deny_idle)(struct clk *clk);
- void (*clk_disable_unused)(struct clk *clk);
+struct clk_hw_omap_ops {
+ void (*find_idlest)(struct clk_hw_omap *oclk,
+ void __iomem **idlest_reg,
+ u8 *idlest_bit, u8 *idlest_val);
+ void (*find_companion)(struct clk_hw_omap *oclk,
+ void __iomem **other_reg,
+ u8 *other_bit);
+ void (*allow_idle)(struct clk_hw_omap *oclk);
+ void (*deny_idle)(struct clk_hw_omap *oclk);
};
-extern int mpurate;
-
-extern int clk_init(struct clk_functions *custom_clocks);
-extern void clk_preinit(struct clk *clk);
-extern int clk_register(struct clk *clk);
-extern void clk_reparent(struct clk *child, struct clk *parent);
-extern void clk_unregister(struct clk *clk);
-extern void propagate_rate(struct clk *clk);
-extern void recalculate_root_clocks(void);
-extern unsigned long followparent_recalc(struct clk *clk);
-extern void clk_enable_init_clocks(void);
-unsigned long omap_fixed_divisor_recalc(struct clk *clk);
-extern struct clk *omap_clk_get_by_name(const char *name);
-extern int omap_clk_enable_autoidle_all(void);
-extern int omap_clk_disable_autoidle_all(void);
-
-extern const struct clkops clkops_null;
-
-extern struct clk dummy_ck;
-
+unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
#define CORE_CLK_SRC_32K 0x0
@@ -364,57 +352,62 @@ extern struct clk dummy_ck;
/* DPLL Type and DCO Selection Flags */
#define DPLL_J_TYPE 0x1
-int omap2_clk_enable(struct clk *clk);
-void omap2_clk_disable(struct clk *clk);
-long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
-int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
-int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
-unsigned long omap3_dpll_recalc(struct clk *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk *clk);
-void omap3_dpll_allow_idle(struct clk *clk);
-void omap3_dpll_deny_idle(struct clk *clk);
-u32 omap3_dpll_autoidle_read(struct clk *clk);
-int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
-int omap3_noncore_dpll_enable(struct clk *clk);
-void omap3_noncore_dpll_disable(struct clk *clk);
-int omap4_dpllmx_gatectrl_read(struct clk *clk);
-void omap4_dpllmx_allow_gatectrl(struct clk *clk);
-void omap4_dpllmx_deny_gatectrl(struct clk *clk);
-long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-void omap2_clk_disable_unused(struct clk *clk);
-#else
-#define omap2_clk_disable_unused NULL
-#endif
-
-void omap2_init_clk_clkdm(struct clk *clk);
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+ unsigned long *parent_rate);
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+ unsigned long target_rate,
+ unsigned long *parent_rate);
+
+void omap2_init_clk_clkdm(struct clk_hw *clk);
void __init omap2_clk_disable_clkdm_control(void);
/* clkt_clksel.c public functions */
-u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
+ unsigned long target_rate,
u32 *new_div);
-void omap2_init_clksel_parent(struct clk *clk);
-unsigned long omap2_clksel_recalc(struct clk *clk);
-long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
-int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
-int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
+u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+ unsigned long *parent_rate);
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
/* clkt_iclk.c public functions */
-extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
-extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
+extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
+extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
-u32 omap2_get_dpll_rate(struct clk *clk);
-void omap2_init_dpll_parent(struct clk *clk);
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
-int omap2_dflt_clk_enable(struct clk *clk);
-void omap2_dflt_clk_disable(struct clk *clk);
-void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+ void __iomem **other_reg,
u8 *other_bit);
-void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+ void __iomem **idlest_reg,
u8 *idlest_bit, u8 *idlest_val);
+void omap2_init_clk_hw_omap_clocks(struct clk *clk);
+int omap2_clk_enable_autoidle_all(void);
+int omap2_clk_disable_autoidle_all(void);
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
const char *core_ck_name,
@@ -432,28 +425,38 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
+extern struct clk dummy_ck;
-extern const struct clkops clkops_omap2_iclk_dflt_wait;
-extern const struct clkops clkops_omap2_iclk_dflt;
-extern const struct clkops clkops_omap2_iclk_idle_only;
-extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
-extern const struct clkops clkops_omap2xxx_dpll_ops;
-extern const struct clkops clkops_omap3_noncore_dpll_ops;
-extern const struct clkops clkops_omap3_core_dpll_ops;
-extern const struct clkops clkops_omap4_dpllmx_ops;
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+extern const struct clk_hw_omap_ops clkhwops_apll54;
+extern const struct clk_hw_omap_ops clkhwops_apll96;
+extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
/* clksel_rate blocks shared between OMAP44xx and AM33xx */
extern const struct clksel_rate div_1_0_rates[];
+extern const struct clksel_rate div3_1to4_rates[];
extern const struct clksel_rate div_1_1_rates[];
extern const struct clksel_rate div_1_2_rates[];
extern const struct clksel_rate div_1_3_rates[];
extern const struct clksel_rate div_1_4_rates[];
extern const struct clksel_rate div31_1to31_rates[];
-/* clocks shared between various OMAP SoCs */
-extern struct clk virt_19200000_ck;
-extern struct clk virt_26000000_ck;
-
extern int am33xx_clk_init(void);
+extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+
#endif
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
deleted file mode 100644
index 608874b651e8..000000000000
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ /dev/null
@@ -1,1972 +0,0 @@
-/*
- * OMAP2420 clock data
- *
- * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * 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/io.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR
-
-/*
- * 2420 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- * many cases the parent is selectable. The set parent calls will
- * also switch sources.
- *
- * Several sources are given initial rates which may be wrong, this will
- * be fixed up in the init func.
- *
- * Things are broadly separated below by clock domains. It is
- * noteworthy that most peripherals have dependencies on multiple clock
- * domains. Many get their interface clocks from the L4 domain, but get
- * functional clocks from fixed sources or other core domain derived
- * clocks.
- */
-
-/* Base external input clocks */
-static struct clk func_32k_ck = {
- .name = "func_32k_ck",
- .ops = &clkops_null,
- .rate = 32768,
- .clkdm_name = "wkup_clkdm",
-};
-
-static struct clk secure_32k_ck = {
- .name = "secure_32k_ck",
- .ops = &clkops_null,
- .rate = 32768,
- .clkdm_name = "wkup_clkdm",
-};
-
-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
-static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
- .name = "osc_ck",
- .ops = &clkops_oscck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2_osc_clk_recalc,
-};
-
-/* Without modem likely 12MHz, with modem likely 13MHz */
-static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
- .name = "sys_ck", /* ~ ref_clk also */
- .ops = &clkops_null,
- .parent = &osc_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2xxx_sys_clk_recalc,
-};
-
-static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
- .name = "alt_ck",
- .ops = &clkops_null,
- .rate = 54000000,
- .clkdm_name = "wkup_clkdm",
-};
-
-/* Optional external clock input for McBSP CLKS */
-static struct clk mcbsp_clks = {
- .name = "mcbsp_clks",
- .ops = &clkops_null,
-};
-
-/*
- * Analog domain root source clocks
- */
-
-/* dpll_ck, is broken out in to special cases through clksel */
-/* REVISIT: Rate changes on dpll_ck trigger a full set change. ...
- * deal with this
- */
-
-static struct dpll_data dpll_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP24XX_DPLL_MULT_MASK,
- .div1_mask = OMAP24XX_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP24XX_EN_DPLL_MASK,
- .max_multiplier = 1023,
- .min_divider = 1,
- .max_divider = 16,
-};
-
-/*
- * XXX Cannot add round_rate here yet, as this is still a composite clock,
- * not just a DPLL
- */
-static struct clk dpll_ck = {
- .name = "dpll_ck",
- .ops = &clkops_omap2xxx_dpll_ops,
- .parent = &sys_ck, /* Can be func_32k also */
- .init = &omap2xxx_clkt_dpllcore_init,
- .dpll_data = &dpll_dd,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2_dpllcore_recalc,
- .set_rate = &omap2_reprogram_dpllcore,
-};
-
-static struct clk apll96_ck = {
- .name = "apll96_ck",
- .ops = &clkops_apll96,
- .parent = &sys_ck,
- .rate = 96000000,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
-};
-
-static struct clk apll54_ck = {
- .name = "apll54_ck",
- .ops = &clkops_apll54,
- .parent = &sys_ck,
- .rate = 54000000,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
-};
-
-/*
- * PRCM digital base sources
- */
-
-/* func_54m_ck */
-
-static const struct clksel_rate func_54m_apll54_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate func_54m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel func_54m_clksel[] = {
- { .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
- { .parent = &alt_ck, .rates = func_54m_alt_rates, },
- { .parent = NULL },
-};
-
-static struct clk func_54m_ck = {
- .name = "func_54m_ck",
- .ops = &clkops_null,
- .parent = &apll54_ck, /* can also be alt_clk */
- .clkdm_name = "wkup_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_54M_SOURCE_MASK,
- .clksel = func_54m_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
- .name = "core_ck",
- .ops = &clkops_null,
- .parent = &dpll_ck, /* can also be 32k */
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk func_96m_ck = {
- .name = "func_96m_ck",
- .ops = &clkops_null,
- .parent = &apll96_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* func_48m_ck */
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel func_48m_clksel[] = {
- { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
- { .parent = &alt_ck, .rates = func_48m_alt_rates },
- { .parent = NULL }
-};
-
-static struct clk func_48m_ck = {
- .name = "func_48m_ck",
- .ops = &clkops_null,
- .parent = &apll96_ck, /* 96M or Alt */
- .clkdm_name = "wkup_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
- .clksel = func_48m_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk func_12m_ck = {
- .name = "func_12m_ck",
- .ops = &clkops_null,
- .parent = &func_48m_ck,
- .fixed_div = 4,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/* Secure timer, only available in secure mode */
-static struct clk wdt1_osc_ck = {
- .name = "ck_wdt1_osc",
- .ops = &clkops_null, /* RMK: missing? */
- .parent = &osc_ck,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The common_clkout* clksel_rate structs are common to
- * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
- * sys_clkout2_* are 2420-only, so the
- * clksel_rate flags fields are inaccurate for those clocks. This is
- * harmless since access to those clocks are gated by the struct clk
- * flags fields, which mark them as 2420-only.
- */
-static const struct clksel_rate common_clkout_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
- { .parent = &core_ck, .rates = common_clkout_src_core_rates },
- { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
- { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
- { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
- { .parent = NULL }
-};
-
-static struct clk sys_clkout_src = {
- .name = "sys_clkout_src",
- .ops = &clkops_omap2_dflt,
- .parent = &func_54m_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP24XX_CLKOUT_SOURCE_MASK,
- .clksel = common_clkout_src_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static const struct clksel_rate common_clkout_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 2, .val = 1, .flags = RATE_IN_24XX },
- { .div = 4, .val = 2, .flags = RATE_IN_24XX },
- { .div = 8, .val = 3, .flags = RATE_IN_24XX },
- { .div = 16, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel sys_clkout_clksel[] = {
- { .parent = &sys_clkout_src, .rates = common_clkout_rates },
- { .parent = NULL }
-};
-
-static struct clk sys_clkout = {
- .name = "sys_clkout",
- .ops = &clkops_null,
- .parent = &sys_clkout_src,
- .clkdm_name = "wkup_clkdm",
- .clksel_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK,
- .clksel = sys_clkout_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-/* In 2430, new in 2420 ES2 */
-static struct clk sys_clkout2_src = {
- .name = "sys_clkout2_src",
- .ops = &clkops_omap2_dflt,
- .parent = &func_54m_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .enable_bit = OMAP2420_CLKOUT2_EN_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP2420_CLKOUT2_SOURCE_MASK,
- .clksel = common_clkout_src_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static const struct clksel sys_clkout2_clksel[] = {
- { .parent = &sys_clkout2_src, .rates = common_clkout_rates },
- { .parent = NULL }
-};
-
-/* In 2430, new in 2420 ES2 */
-static struct clk sys_clkout2 = {
- .name = "sys_clkout2",
- .ops = &clkops_null,
- .parent = &sys_clkout2_src,
- .clkdm_name = "wkup_clkdm",
- .clksel_reg = OMAP2420_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP2420_CLKOUT2_DIV_MASK,
- .clksel = sys_clkout2_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk emul_ck = {
- .name = "emul_ck",
- .ops = &clkops_omap2_dflt,
- .parent = &func_54m_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP2420_PRCM_CLKEMUL_CTRL,
- .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
- .recalc = &followparent_recalc,
-
-};
-
-/*
- * MPU clock domain
- * Clocks:
- * MPU_FCLK, MPU_ICLK
- * INT_M_FCLK, INT_M_I_CLK
- *
- * - Individual clocks are hardware managed.
- * - Base divider comes from: CM_CLKSEL_MPU
- *
- */
-static const struct clksel_rate mpu_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_242X },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 0 },
-};
-
-static const struct clksel mpu_clksel[] = {
- { .parent = &core_ck, .rates = mpu_core_rates },
- { .parent = NULL }
-};
-
-static struct clk mpu_ck = { /* Control cpu */
- .name = "mpu_ck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .clkdm_name = "mpu_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_MPU_MASK,
- .clksel = mpu_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * DSP (2420-UMA+IVA1) clock domain
- * Clocks:
- * 2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
- *
- * Won't be too specific here. The core clock comes into this block
- * it is divided then tee'ed. One branch goes directly to xyz enable
- * controls. The other branch gets further divided by 2 then possibly
- * routed into a synchronizer and out of clocks abc.
- */
-static const struct clksel_rate dsp_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 12, .val = 12, .flags = RATE_IN_242X },
- { .div = 0 },
-};
-
-static const struct clksel dsp_fck_clksel[] = {
- { .parent = &core_ck, .rates = dsp_fck_core_rates },
- { .parent = NULL }
-};
-
-static struct clk dsp_fck = {
- .name = "dsp_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "dsp_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_DSP_MASK,
- .clksel = dsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel dsp_ick_clksel[] = {
- { .parent = &dsp_fck, .rates = dsp_ick_rates },
- { .parent = NULL }
-};
-
-static struct clk dsp_ick = {
- .name = "dsp_ick", /* apparently ipi and isp */
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &dsp_fck,
- .clkdm_name = "dsp_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
- .enable_bit = OMAP2420_EN_DSP_IPI_SHIFT, /* for ipi */
- .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK,
- .clksel = dsp_ick_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * The IVA1 is an ARM7 core on the 2420 that has nothing to do with
- * the C54x, but which is contained in the DSP powerdomain. Does not
- * exist on later OMAPs.
- */
-static struct clk iva1_ifck = {
- .name = "iva1_ifck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "iva1_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP2420_EN_IVA_COP_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP2420_CLKSEL_IVA_MASK,
- .clksel = dsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* IVA1 mpu/int/i/f clocks are /2 of parent */
-static struct clk iva1_mpu_int_ifck = {
- .name = "iva1_mpu_int_ifck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &iva1_ifck,
- .clkdm_name = "iva1_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/*
- * L3 clock domain
- * L3 clocks are used for both interface and functional clocks to
- * multiple entities. Some of these clocks are completely managed
- * by hardware, and some others allow software control. Hardware
- * managed ones general are based on directly CLK_REQ signals and
- * various auto idle settings. The functional spec sets many of these
- * as 'tie-high' for their enables.
- *
- * I-CLOCKS:
- * L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
- * CAM, HS-USB.
- * F-CLOCK
- * SSI.
- *
- * GPMC memories and SDRC have timing and clock sensitive registers which
- * may very well need notification when the clock changes. Currently for low
- * operating points, these are taken care of in sleep.S.
- */
-static const struct clksel_rate core_l3_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_242X },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 12, .val = 12, .flags = RATE_IN_242X },
- { .div = 16, .val = 16, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel core_l3_clksel[] = {
- { .parent = &core_ck, .rates = core_l3_core_rates },
- { .parent = NULL }
-};
-
-static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
- .name = "core_l3_ck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .clkdm_name = "core_l3_clkdm",
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_L3_MASK,
- .clksel = core_l3_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* usb_l4_ick */
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
- { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
- { .parent = NULL },
-};
-
-/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
-static struct clk usb_l4_ick = { /* FS-USB interface clock */
- .name = "usb_l4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_USB_MASK,
- .clksel = usb_l4_ick_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * L4 clock management domain
- *
- * This domain contains lots of interface clocks from the L4 interface, some
- * functional clocks. Fixed APLL functional source clocks are managed in
- * this domain.
- */
-static const struct clksel_rate l4_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel l4_clksel[] = {
- { .parent = &core_l3_ck, .rates = l4_core_l3_rates },
- { .parent = NULL }
-};
-
-static struct clk l4_ck = { /* used both as an ick and fck */
- .name = "l4_ck",
- .ops = &clkops_null,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l4_clkdm",
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_L4_MASK,
- .clksel = l4_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * SSI is in L3 management domain, its direct parent is core not l3,
- * many core power domain entities are grouped into the L3 clock
- * domain.
- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK
- *
- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
- */
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
- { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
- { .parent = NULL }
-};
-
-static struct clk ssi_ssr_sst_fck = {
- .name = "ssi_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_SSI_MASK,
- .clksel = ssi_ssr_sst_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * Presumably this is the same as SSI_ICLK.
- * TRM contradicts itself on what clockdomain SSI_ICLK is in
- */
-static struct clk ssi_l4_ick = {
- .name = "ssi_l4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-
-/*
- * GFX clock domain
- * Clocks:
- * GFX_FCLK, GFX_ICLK
- * GFX_CG1(2d), GFX_CG2(3d)
- *
- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
- * The 2d and 3d clocks run at a hardware determined
- * divided value of fclk.
- *
- */
-
-/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
-static const struct clksel gfx_fck_clksel[] = {
- { .parent = &core_l3_ck, .rates = gfx_l3_rates },
- { .parent = NULL },
-};
-
-static struct clk gfx_3d_fck = {
- .name = "gfx_3d_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_3D_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP_CLKSEL_GFX_MASK,
- .clksel = gfx_fck_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk gfx_2d_fck = {
- .name = "gfx_2d_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_2D_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP_CLKSEL_GFX_MASK,
- .clksel = gfx_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk gfx_ick = {
- .name = "gfx_ick", /* From l3 */
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * DSS clock domain
- * CLOCKs:
- * DSS_L4_ICLK, DSS_L3_ICLK,
- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
- *
- * DSS is both initiator and target.
- */
-/* XXX Add RATE_NOT_VALIDATED */
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 8, .val = 8, .flags = RATE_IN_24XX },
- { .div = 9, .val = 9, .flags = RATE_IN_24XX },
- { .div = 12, .val = 12, .flags = RATE_IN_24XX },
- { .div = 16, .val = 16, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
- { .parent = &core_ck, .rates = dss1_fck_core_rates },
- { .parent = NULL },
-};
-
-static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */
- .name = "dss_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ck, /* really both l3 and l4 */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss1_fck = {
- .name = "dss1_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &core_ck, /* Core or sys */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_DSS1_MASK,
- .clksel = dss1_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss2_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
- { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
- { .parent = NULL }
-};
-
-static struct clk dss2_fck = { /* Alt clk used in power management */
- .name = "dss2_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &sys_ck, /* fixed at sys_ck or 48MHz */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_DSS2_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_DSS2_MASK,
- .clksel = dss2_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk dss_54m_fck = { /* Alt clk used in power management */
- .name = "dss_54m_fck", /* 54m tv clk */
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_54m_ck,
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_TV_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wu_l4_ick = {
- .name = "wu_l4_ick",
- .ops = &clkops_null,
- .parent = &sys_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/*
- * CORE power domain ICLK & FCLK defines.
- * Many of the these can have more than one possible parent. Entries
- * here will likely have an L4 interface parent, and may have multiple
- * functional clock parents.
- */
-static const struct clksel_rate gpt_alt_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
- { .parent = &func_32k_ck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = &alt_ck, .rates = gpt_alt_rates },
- { .parent = NULL },
-};
-
-static struct clk gpt1_ick = {
- .name = "gpt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt1_fck = {
- .name = "gpt1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_GPT1_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk gpt2_ick = {
- .name = "gpt2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
- .name = "gpt2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT2_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_ick = {
- .name = "gpt3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt3_fck = {
- .name = "gpt3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT3_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_ick = {
- .name = "gpt4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt4_fck = {
- .name = "gpt4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT4_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_ick = {
- .name = "gpt5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt5_fck = {
- .name = "gpt5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT5_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_ick = {
- .name = "gpt6_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt6_fck = {
- .name = "gpt6_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT6_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_ick = {
- .name = "gpt7_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt7_fck = {
- .name = "gpt7_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT7_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_ick = {
- .name = "gpt8_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt8_fck = {
- .name = "gpt8_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT8_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_ick = {
- .name = "gpt9_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt9_fck = {
- .name = "gpt9_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT9_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt10_ick = {
- .name = "gpt10_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt10_fck = {
- .name = "gpt10_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT10_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_ick = {
- .name = "gpt11_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt11_fck = {
- .name = "gpt11_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT11_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt12_ick = {
- .name = "gpt12_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt12_fck = {
- .name = "gpt12_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &secure_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT12_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_ick = {
- .name = "mcbsp1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL }
-};
-
-static struct clk mcbsp1_fck = {
- .name = "mcbsp1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .clksel_reg = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP1_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp2_ick = {
- .name = "mcbsp2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp2_fck = {
- .name = "mcbsp2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .clksel_reg = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP2_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcspi1_ick = {
- .name = "mcspi1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
- .name = "mcspi1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
- .name = "mcspi2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
- .name = "mcspi2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
- .name = "uart1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
- .name = "uart1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
- .name = "uart2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
- .name = "uart2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
- .name = "uart3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
- .name = "uart3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpios_ick = {
- .name = "gpios_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpios_fck = {
- .name = "gpios_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mpu_wdt_ick = {
- .name = "mpu_wdt_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mpu_wdt_fck = {
- .name = "mpu_wdt_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sync_32k_ick = {
- .name = "sync_32k_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .flags = ENABLE_ON_INIT,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
- .name = "wdt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
- .name = "omapctrl_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .flags = ENABLE_ON_INIT,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk cam_ick = {
- .name = "cam_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * cam_fck controls both CAM_MCLK and CAM_FCLK. It should probably be
- * split into two separate clocks, since the parent clocks are different
- * and the clockdomains are also different.
- */
-static struct clk cam_fck = {
- .name = "cam_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
- .name = "mailboxes_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt4_ick = {
- .name = "wdt4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt4_fck = {
- .name = "wdt4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt3_ick = {
- .name = "wdt3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_WDT3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt3_fck = {
- .name = "wdt3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_WDT3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
- .name = "mspro_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
- .name = "mspro_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmc_ick = {
- .name = "mmc_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_MMC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmc_fck = {
- .name = "mmc_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_MMC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk fac_ick = {
- .name = "fac_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk fac_fck = {
- .name = "fac_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk eac_ick = {
- .name = "eac_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_EAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk eac_fck = {
- .name = "eac_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_EAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
- .name = "hdq_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
- .name = "hdq_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c2_ick = {
- .name = "i2c2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
- .name = "i2c2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c1_ick = {
- .name = "i2c1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c1_fck = {
- .name = "i2c1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk gpmc_fck = {
- .name = "gpmc_fck",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sdma_fck = {
- .name = "sdma_fck",
- .ops = &clkops_null, /* RMK: missing? */
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdma_ick = {
- .name = "sdma_ick",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdrc_ick = {
- .name = "sdrc_ick",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDRC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk vlynq_ick = {
- .name = "vlynq_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate vlynq_fck_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel_rate vlynq_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_242X },
- { .div = 2, .val = 2, .flags = RATE_IN_242X },
- { .div = 3, .val = 3, .flags = RATE_IN_242X },
- { .div = 4, .val = 4, .flags = RATE_IN_242X },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 9, .val = 9, .flags = RATE_IN_242X },
- { .div = 12, .val = 12, .flags = RATE_IN_242X },
- { .div = 16, .val = 16, .flags = RATE_IN_242X },
- { .div = 18, .val = 18, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel vlynq_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
- { .parent = &core_ck, .rates = vlynq_fck_core_rates },
- { .parent = NULL }
-};
-
-static struct clk vlynq_fck = {
- .name = "vlynq_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP2420_CLKSEL_VLYNQ_MASK,
- .clksel = vlynq_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk des_ick = {
- .name = "des_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_DES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sha_ick = {
- .name = "sha_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_SHA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk rng_ick = {
- .name = "rng_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_RNG_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk aes_ick = {
- .name = "aes_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_AES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk pka_ick = {
- .name = "pka_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_PKA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_fck = {
- .name = "usb_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * This clock is a composite clock which does entire set changes then
- * forces a rebalance. It keys on the MPU speed, but it really could
- * be any key speed part of a set in the rate table.
- *
- * to really change a set, you need memory table sets which get changed
- * in sram, pre-notifiers & post notifiers, changing the top set, without
- * having low level display recalc's won't work... this is why dpm notifiers
- * work, isr's off, walk a list of clocks already _off_ and not messing with
- * the bus.
- *
- * This clock should have no parent. It embodies the entire upper level
- * active set. A parent will mess up some of the init also.
- */
-static struct clk virt_prcm_set = {
- .name = "virt_prcm_set",
- .ops = &clkops_null,
- .parent = &mpu_ck, /* Indexed by mpu speed, no parent */
- .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */
- .set_rate = &omap2_select_table_rate,
- .round_rate = &omap2_round_to_table_rate,
-};
-
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2420_clks[] = {
- /* external root sources */
- CLK(NULL, "func_32k_ck", &func_32k_ck, CK_242X),
- CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_242X),
- CLK(NULL, "osc_ck", &osc_ck, CK_242X),
- CLK(NULL, "sys_ck", &sys_ck, CK_242X),
- CLK(NULL, "alt_ck", &alt_ck, CK_242X),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_242X),
- /* internal analog sources */
- CLK(NULL, "dpll_ck", &dpll_ck, CK_242X),
- CLK(NULL, "apll96_ck", &apll96_ck, CK_242X),
- CLK(NULL, "apll54_ck", &apll54_ck, CK_242X),
- /* internal prcm root sources */
- CLK(NULL, "func_54m_ck", &func_54m_ck, CK_242X),
- CLK(NULL, "core_ck", &core_ck, CK_242X),
- CLK(NULL, "func_96m_ck", &func_96m_ck, CK_242X),
- CLK(NULL, "func_48m_ck", &func_48m_ck, CK_242X),
- CLK(NULL, "func_12m_ck", &func_12m_ck, CK_242X),
- CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_242X),
- CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_242X),
- CLK(NULL, "sys_clkout", &sys_clkout, CK_242X),
- CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X),
- CLK(NULL, "sys_clkout2", &sys_clkout2, CK_242X),
- CLK(NULL, "emul_ck", &emul_ck, CK_242X),
- /* mpu domain clocks */
- CLK(NULL, "mpu_ck", &mpu_ck, CK_242X),
- /* dsp domain clocks */
- CLK(NULL, "dsp_fck", &dsp_fck, CK_242X),
- CLK(NULL, "dsp_ick", &dsp_ick, CK_242X),
- CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X),
- CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
- /* GFX domain clocks */
- CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_242X),
- CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X),
- CLK(NULL, "gfx_ick", &gfx_ick, CK_242X),
- /* DSS domain clocks */
- CLK("omapdss_dss", "ick", &dss_ick, CK_242X),
- CLK(NULL, "dss_ick", &dss_ick, CK_242X),
- CLK(NULL, "dss1_fck", &dss1_fck, CK_242X),
- CLK(NULL, "dss2_fck", &dss2_fck, CK_242X),
- CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_242X),
- /* L3 domain clocks */
- CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X),
- CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_242X),
- /* L4 domain clocks */
- CLK(NULL, "l4_ck", &l4_ck, CK_242X),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X),
- CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_242X),
- /* virtual meta-group clock */
- CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X),
- /* general l4 interface ck, multi-parent functional clk */
- CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X),
- CLK(NULL, "gpt2_ick", &gpt2_ick, CK_242X),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_242X),
- CLK(NULL, "gpt3_ick", &gpt3_ick, CK_242X),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_242X),
- CLK(NULL, "gpt4_ick", &gpt4_ick, CK_242X),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_242X),
- CLK(NULL, "gpt5_ick", &gpt5_ick, CK_242X),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_242X),
- CLK(NULL, "gpt6_ick", &gpt6_ick, CK_242X),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_242X),
- CLK(NULL, "gpt7_ick", &gpt7_ick, CK_242X),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_242X),
- CLK(NULL, "gpt8_ick", &gpt8_ick, CK_242X),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_242X),
- CLK(NULL, "gpt9_ick", &gpt9_ick, CK_242X),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_242X),
- CLK(NULL, "gpt10_ick", &gpt10_ick, CK_242X),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_242X),
- CLK(NULL, "gpt11_ick", &gpt11_ick, CK_242X),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_242X),
- CLK(NULL, "gpt12_ick", &gpt12_ick, CK_242X),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_242X),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_242X),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_242X),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_242X),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_242X),
- CLK(NULL, "mcbsp2_ick", &mcbsp2_ick, CK_242X),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_242X),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_242X),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_242X),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_242X),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_242X),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_242X),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_242X),
- CLK(NULL, "uart1_ick", &uart1_ick, CK_242X),
- CLK(NULL, "uart1_fck", &uart1_fck, CK_242X),
- CLK(NULL, "uart2_ick", &uart2_ick, CK_242X),
- CLK(NULL, "uart2_fck", &uart2_fck, CK_242X),
- CLK(NULL, "uart3_ick", &uart3_ick, CK_242X),
- CLK(NULL, "uart3_fck", &uart3_fck, CK_242X),
- CLK(NULL, "gpios_ick", &gpios_ick, CK_242X),
- CLK(NULL, "gpios_fck", &gpios_fck, CK_242X),
- CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_242X),
- CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_242X),
- CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_242X),
- CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_242X),
- CLK(NULL, "wdt1_ick", &wdt1_ick, CK_242X),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_242X),
- CLK("omap24xxcam", "fck", &cam_fck, CK_242X),
- CLK(NULL, "cam_fck", &cam_fck, CK_242X),
- CLK("omap24xxcam", "ick", &cam_ick, CK_242X),
- CLK(NULL, "cam_ick", &cam_ick, CK_242X),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_242X),
- CLK(NULL, "wdt4_ick", &wdt4_ick, CK_242X),
- CLK(NULL, "wdt4_fck", &wdt4_fck, CK_242X),
- CLK(NULL, "wdt3_ick", &wdt3_ick, CK_242X),
- CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X),
- CLK(NULL, "mspro_ick", &mspro_ick, CK_242X),
- CLK(NULL, "mspro_fck", &mspro_fck, CK_242X),
- CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X),
- CLK(NULL, "mmc_ick", &mmc_ick, CK_242X),
- CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X),
- CLK(NULL, "mmc_fck", &mmc_fck, CK_242X),
- CLK(NULL, "fac_ick", &fac_ick, CK_242X),
- CLK(NULL, "fac_fck", &fac_fck, CK_242X),
- CLK(NULL, "eac_ick", &eac_ick, CK_242X),
- CLK(NULL, "eac_fck", &eac_fck, CK_242X),
- CLK("omap_hdq.0", "ick", &hdq_ick, CK_242X),
- CLK(NULL, "hdq_ick", &hdq_ick, CK_242X),
- CLK("omap_hdq.0", "fck", &hdq_fck, CK_242X),
- CLK(NULL, "hdq_fck", &hdq_fck, CK_242X),
- CLK("omap_i2c.1", "ick", &i2c1_ick, CK_242X),
- CLK(NULL, "i2c1_ick", &i2c1_ick, CK_242X),
- CLK(NULL, "i2c1_fck", &i2c1_fck, CK_242X),
- CLK("omap_i2c.2", "ick", &i2c2_ick, CK_242X),
- CLK(NULL, "i2c2_ick", &i2c2_ick, CK_242X),
- CLK(NULL, "i2c2_fck", &i2c2_fck, CK_242X),
- CLK(NULL, "gpmc_fck", &gpmc_fck, CK_242X),
- CLK(NULL, "sdma_fck", &sdma_fck, CK_242X),
- CLK(NULL, "sdma_ick", &sdma_ick, CK_242X),
- CLK(NULL, "sdrc_ick", &sdrc_ick, CK_242X),
- CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X),
- CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X),
- CLK(NULL, "des_ick", &des_ick, CK_242X),
- CLK("omap-sham", "ick", &sha_ick, CK_242X),
- CLK(NULL, "sha_ick", &sha_ick, CK_242X),
- CLK("omap_rng", "ick", &rng_ick, CK_242X),
- CLK(NULL, "rng_ick", &rng_ick, CK_242X),
- CLK("omap-aes", "ick", &aes_ick, CK_242X),
- CLK(NULL, "aes_ick", &aes_ick, CK_242X),
- CLK(NULL, "pka_ick", &pka_ick, CK_242X),
- CLK(NULL, "usb_fck", &usb_fck, CK_242X),
- CLK("musb-hdrc", "fck", &osc_ck, CK_242X),
- CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_242X),
- CLK(NULL, "timer_sys_ck", &sys_ck, CK_242X),
- CLK(NULL, "timer_ext_ck", &alt_ck, CK_242X),
- CLK(NULL, "cpufreq_ck", &virt_prcm_set, CK_242X),
-};
-
-/*
- * init code
- */
-
-int __init omap2420_clk_init(void)
-{
- struct omap_clk *c;
-
- prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
- cpu_mask = RATE_IN_242X;
- rate_table = omap2420_rate_table;
-
- for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
- c++)
- clk_preinit(c->lk.clk);
-
- osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
- propagate_rate(&osc_ck);
- sys_ck.rate = omap2xxx_sys_clk_recalc(&sys_ck);
- propagate_rate(&sys_ck);
-
- for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
- c++) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- omap2_init_clk_clkdm(c->lk.clk);
- }
-
- omap2xxx_clkt_vps_late_init();
-
- /* Disable autoidle on all clocks; let the PM code enable it later */
- omap_clk_disable_autoidle_all();
-
- /* XXX Can this be done from the virt_prcm_set clk init function? */
- omap2xxx_clkt_vps_check_bootloader_rates();
-
- recalculate_root_clocks();
-
- pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
- (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
-
- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable_init_clocks();
-
- return 0;
-}
-
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
index e37df538bcd3..cef0c8d1de52 100644
--- a/arch/arm/mach-omap2/clock2430.c
+++ b/arch/arm/mach-omap2/clock2430.c
@@ -40,7 +40,7 @@
* passes back the correct CM_IDLEST register address for I2CHS
* modules. No return value.
*/
-static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -51,9 +51,7 @@ static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
}
/* 2430 I2CHS has non-standard IDLEST register */
-const struct clkops clkops_omap2430_i2chs_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
.find_idlest = omap2430_clk_i2chs_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+ .find_companion = omap2_clk_dflt_find_companion,
};
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
deleted file mode 100644
index b179b6ef4329..000000000000
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ /dev/null
@@ -1,2071 +0,0 @@
-/*
- * OMAP2430 clock data
- *
- * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * 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/clk.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR
-
-/*
- * 2430 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- * many cases the parent is selectable. The set parent calls will
- * also switch sources.
- *
- * Several sources are given initial rates which may be wrong, this will
- * be fixed up in the init func.
- *
- * Things are broadly separated below by clock domains. It is
- * noteworthy that most peripherals have dependencies on multiple clock
- * domains. Many get their interface clocks from the L4 domain, but get
- * functional clocks from fixed sources or other core domain derived
- * clocks.
- */
-
-/* Base external input clocks */
-static struct clk func_32k_ck = {
- .name = "func_32k_ck",
- .ops = &clkops_null,
- .rate = 32768,
- .clkdm_name = "wkup_clkdm",
-};
-
-static struct clk secure_32k_ck = {
- .name = "secure_32k_ck",
- .ops = &clkops_null,
- .rate = 32768,
- .clkdm_name = "wkup_clkdm",
-};
-
-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
-static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
- .name = "osc_ck",
- .ops = &clkops_oscck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2_osc_clk_recalc,
-};
-
-/* Without modem likely 12MHz, with modem likely 13MHz */
-static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
- .name = "sys_ck", /* ~ ref_clk also */
- .ops = &clkops_null,
- .parent = &osc_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2xxx_sys_clk_recalc,
-};
-
-static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
- .name = "alt_ck",
- .ops = &clkops_null,
- .rate = 54000000,
- .clkdm_name = "wkup_clkdm",
-};
-
-/* Optional external clock input for McBSP CLKS */
-static struct clk mcbsp_clks = {
- .name = "mcbsp_clks",
- .ops = &clkops_null,
-};
-
-/*
- * Analog domain root source clocks
- */
-
-/* dpll_ck, is broken out in to special cases through clksel */
-/* REVISIT: Rate changes on dpll_ck trigger a full set change. ...
- * deal with this
- */
-
-static struct dpll_data dpll_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP24XX_DPLL_MULT_MASK,
- .div1_mask = OMAP24XX_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP24XX_EN_DPLL_MASK,
- .max_multiplier = 1023,
- .min_divider = 1,
- .max_divider = 16,
-};
-
-/*
- * XXX Cannot add round_rate here yet, as this is still a composite clock,
- * not just a DPLL
- */
-static struct clk dpll_ck = {
- .name = "dpll_ck",
- .ops = &clkops_omap2xxx_dpll_ops,
- .parent = &sys_ck, /* Can be func_32k also */
- .init = &omap2xxx_clkt_dpllcore_init,
- .dpll_data = &dpll_dd,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2_dpllcore_recalc,
- .set_rate = &omap2_reprogram_dpllcore,
-};
-
-static struct clk apll96_ck = {
- .name = "apll96_ck",
- .ops = &clkops_apll96,
- .parent = &sys_ck,
- .rate = 96000000,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
-};
-
-static struct clk apll54_ck = {
- .name = "apll54_ck",
- .ops = &clkops_apll54,
- .parent = &sys_ck,
- .rate = 54000000,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
-};
-
-/*
- * PRCM digital base sources
- */
-
-/* func_54m_ck */
-
-static const struct clksel_rate func_54m_apll54_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate func_54m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel func_54m_clksel[] = {
- { .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
- { .parent = &alt_ck, .rates = func_54m_alt_rates, },
- { .parent = NULL },
-};
-
-static struct clk func_54m_ck = {
- .name = "func_54m_ck",
- .ops = &clkops_null,
- .parent = &apll54_ck, /* can also be alt_clk */
- .clkdm_name = "wkup_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_54M_SOURCE_MASK,
- .clksel = func_54m_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
- .name = "core_ck",
- .ops = &clkops_null,
- .parent = &dpll_ck, /* can also be 32k */
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* func_96m_ck */
-static const struct clksel_rate func_96m_apll96_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate func_96m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_243X },
- { .div = 0 },
-};
-
-static const struct clksel func_96m_clksel[] = {
- { .parent = &apll96_ck, .rates = func_96m_apll96_rates },
- { .parent = &alt_ck, .rates = func_96m_alt_rates },
- { .parent = NULL }
-};
-
-static struct clk func_96m_ck = {
- .name = "func_96m_ck",
- .ops = &clkops_null,
- .parent = &apll96_ck,
- .clkdm_name = "wkup_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP2430_96M_SOURCE_MASK,
- .clksel = func_96m_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* func_48m_ck */
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel func_48m_clksel[] = {
- { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
- { .parent = &alt_ck, .rates = func_48m_alt_rates },
- { .parent = NULL }
-};
-
-static struct clk func_48m_ck = {
- .name = "func_48m_ck",
- .ops = &clkops_null,
- .parent = &apll96_ck, /* 96M or Alt */
- .clkdm_name = "wkup_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
- .clksel = func_48m_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk func_12m_ck = {
- .name = "func_12m_ck",
- .ops = &clkops_null,
- .parent = &func_48m_ck,
- .fixed_div = 4,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/* Secure timer, only available in secure mode */
-static struct clk wdt1_osc_ck = {
- .name = "ck_wdt1_osc",
- .ops = &clkops_null, /* RMK: missing? */
- .parent = &osc_ck,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The common_clkout* clksel_rate structs are common to
- * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
- * sys_clkout2_* are 2420-only, so the
- * clksel_rate flags fields are inaccurate for those clocks. This is
- * harmless since access to those clocks are gated by the struct clk
- * flags fields, which mark them as 2420-only.
- */
-static const struct clksel_rate common_clkout_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
- { .parent = &core_ck, .rates = common_clkout_src_core_rates },
- { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
- { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
- { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
- { .parent = NULL }
-};
-
-static struct clk sys_clkout_src = {
- .name = "sys_clkout_src",
- .ops = &clkops_omap2_dflt,
- .parent = &func_54m_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP2430_PRCM_CLKOUT_CTRL,
- .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP2430_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP24XX_CLKOUT_SOURCE_MASK,
- .clksel = common_clkout_src_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static const struct clksel_rate common_clkout_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 2, .val = 1, .flags = RATE_IN_24XX },
- { .div = 4, .val = 2, .flags = RATE_IN_24XX },
- { .div = 8, .val = 3, .flags = RATE_IN_24XX },
- { .div = 16, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel sys_clkout_clksel[] = {
- { .parent = &sys_clkout_src, .rates = common_clkout_rates },
- { .parent = NULL }
-};
-
-static struct clk sys_clkout = {
- .name = "sys_clkout",
- .ops = &clkops_null,
- .parent = &sys_clkout_src,
- .clkdm_name = "wkup_clkdm",
- .clksel_reg = OMAP2430_PRCM_CLKOUT_CTRL,
- .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK,
- .clksel = sys_clkout_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk emul_ck = {
- .name = "emul_ck",
- .ops = &clkops_omap2_dflt,
- .parent = &func_54m_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP2430_PRCM_CLKEMUL_CTRL,
- .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
- .recalc = &followparent_recalc,
-
-};
-
-/*
- * MPU clock domain
- * Clocks:
- * MPU_FCLK, MPU_ICLK
- * INT_M_FCLK, INT_M_I_CLK
- *
- * - Individual clocks are hardware managed.
- * - Base divider comes from: CM_CLKSEL_MPU
- *
- */
-static const struct clksel_rate mpu_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel mpu_clksel[] = {
- { .parent = &core_ck, .rates = mpu_core_rates },
- { .parent = NULL }
-};
-
-static struct clk mpu_ck = { /* Control cpu */
- .name = "mpu_ck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .clkdm_name = "mpu_clkdm",
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_MPU_MASK,
- .clksel = mpu_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * DSP (2430-IVA2.1) clock domain
- * Clocks:
- * 2430: IVA2.1_FCLK (really just DSP_FCLK), IVA2.1_ICLK
- *
- * Won't be too specific here. The core clock comes into this block
- * it is divided then tee'ed. One branch goes directly to xyz enable
- * controls. The other branch gets further divided by 2 then possibly
- * routed into a synchronizer and out of clocks abc.
- */
-static const struct clksel_rate dsp_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 },
-};
-
-static const struct clksel dsp_fck_clksel[] = {
- { .parent = &core_ck, .rates = dsp_fck_core_rates },
- { .parent = NULL }
-};
-
-static struct clk dsp_fck = {
- .name = "dsp_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "dsp_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_DSP_MASK,
- .clksel = dsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel dsp_ick_clksel[] = {
- { .parent = &dsp_fck, .rates = dsp_ick_rates },
- { .parent = NULL }
-};
-
-/* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
-static struct clk iva2_1_ick = {
- .name = "iva2_1_ick",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dsp_fck,
- .clkdm_name = "dsp_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK,
- .clksel = dsp_ick_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * L3 clock domain
- * L3 clocks are used for both interface and functional clocks to
- * multiple entities. Some of these clocks are completely managed
- * by hardware, and some others allow software control. Hardware
- * managed ones general are based on directly CLK_REQ signals and
- * various auto idle settings. The functional spec sets many of these
- * as 'tie-high' for their enables.
- *
- * I-CLOCKS:
- * L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
- * CAM, HS-USB.
- * F-CLOCK
- * SSI.
- *
- * GPMC memories and SDRC have timing and clock sensitive registers which
- * may very well need notification when the clock changes. Currently for low
- * operating points, these are taken care of in sleep.S.
- */
-static const struct clksel_rate core_l3_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel core_l3_clksel[] = {
- { .parent = &core_ck, .rates = core_l3_core_rates },
- { .parent = NULL }
-};
-
-static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
- .name = "core_l3_ck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .clkdm_name = "core_l3_clkdm",
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_L3_MASK,
- .clksel = core_l3_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* usb_l4_ick */
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
- { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
- { .parent = NULL },
-};
-
-/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
-static struct clk usb_l4_ick = { /* FS-USB interface clock */
- .name = "usb_l4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_USB_MASK,
- .clksel = usb_l4_ick_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * L4 clock management domain
- *
- * This domain contains lots of interface clocks from the L4 interface, some
- * functional clocks. Fixed APLL functional source clocks are managed in
- * this domain.
- */
-static const struct clksel_rate l4_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel l4_clksel[] = {
- { .parent = &core_l3_ck, .rates = l4_core_l3_rates },
- { .parent = NULL }
-};
-
-static struct clk l4_ck = { /* used both as an ick and fck */
- .name = "l4_ck",
- .ops = &clkops_null,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l4_clkdm",
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_L4_MASK,
- .clksel = l4_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * SSI is in L3 management domain, its direct parent is core not l3,
- * many core power domain entities are grouped into the L3 clock
- * domain.
- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK
- *
- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
- */
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_243X },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
- { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
- { .parent = NULL }
-};
-
-static struct clk ssi_ssr_sst_fck = {
- .name = "ssi_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_SSI_MASK,
- .clksel = ssi_ssr_sst_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * Presumably this is the same as SSI_ICLK.
- * TRM contradicts itself on what clockdomain SSI_ICLK is in
- */
-static struct clk ssi_l4_ick = {
- .name = "ssi_l4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-
-/*
- * GFX clock domain
- * Clocks:
- * GFX_FCLK, GFX_ICLK
- * GFX_CG1(2d), GFX_CG2(3d)
- *
- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
- * The 2d and 3d clocks run at a hardware determined
- * divided value of fclk.
- *
- */
-
-/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
-static const struct clksel gfx_fck_clksel[] = {
- { .parent = &core_l3_ck, .rates = gfx_l3_rates },
- { .parent = NULL },
-};
-
-static struct clk gfx_3d_fck = {
- .name = "gfx_3d_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_3D_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP_CLKSEL_GFX_MASK,
- .clksel = gfx_fck_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk gfx_2d_fck = {
- .name = "gfx_2d_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_2D_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP_CLKSEL_GFX_MASK,
- .clksel = gfx_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk gfx_ick = {
- .name = "gfx_ick", /* From l3 */
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "gfx_clkdm",
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * Modem clock domain (2430)
- * CLOCKS:
- * MDM_OSC_CLK
- * MDM_ICLK
- * These clocks are usable in chassis mode only.
- */
-static const struct clksel_rate mdm_ick_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_243X },
- { .div = 4, .val = 4, .flags = RATE_IN_243X },
- { .div = 6, .val = 6, .flags = RATE_IN_243X },
- { .div = 9, .val = 9, .flags = RATE_IN_243X },
- { .div = 0 }
-};
-
-static const struct clksel mdm_ick_clksel[] = {
- { .parent = &core_ck, .rates = mdm_ick_core_rates },
- { .parent = NULL }
-};
-
-static struct clk mdm_ick = { /* used both as a ick and fck */
- .name = "mdm_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_ck,
- .clkdm_name = "mdm_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
- .enable_bit = OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
- .clksel_mask = OMAP2430_CLKSEL_MDM_MASK,
- .clksel = mdm_ick_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mdm_osc_ck = {
- .name = "mdm_osc_ck",
- .ops = &clkops_omap2_mdmclk_dflt_wait,
- .parent = &osc_ck,
- .clkdm_name = "mdm_clkdm",
- .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
- .enable_bit = OMAP2430_EN_OSC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * DSS clock domain
- * CLOCKs:
- * DSS_L4_ICLK, DSS_L3_ICLK,
- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
- *
- * DSS is both initiator and target.
- */
-/* XXX Add RATE_NOT_VALIDATED */
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 8, .val = 8, .flags = RATE_IN_24XX },
- { .div = 9, .val = 9, .flags = RATE_IN_24XX },
- { .div = 12, .val = 12, .flags = RATE_IN_24XX },
- { .div = 16, .val = 16, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
- { .parent = &core_ck, .rates = dss1_fck_core_rates },
- { .parent = NULL },
-};
-
-static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */
- .name = "dss_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ck, /* really both l3 and l4 */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss1_fck = {
- .name = "dss1_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &core_ck, /* Core or sys */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_DSS1_MASK,
- .clksel = dss1_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss2_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
- { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
- { .parent = NULL }
-};
-
-static struct clk dss2_fck = { /* Alt clk used in power management */
- .name = "dss2_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &sys_ck, /* fixed at sys_ck or 48MHz */
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_DSS2_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_DSS2_MASK,
- .clksel = dss2_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk dss_54m_fck = { /* Alt clk used in power management */
- .name = "dss_54m_fck", /* 54m tv clk */
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_54m_ck,
- .clkdm_name = "dss_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_TV_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wu_l4_ick = {
- .name = "wu_l4_ick",
- .ops = &clkops_null,
- .parent = &sys_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/*
- * CORE power domain ICLK & FCLK defines.
- * Many of the these can have more than one possible parent. Entries
- * here will likely have an L4 interface parent, and may have multiple
- * functional clock parents.
- */
-static const struct clksel_rate gpt_alt_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
- { .parent = &func_32k_ck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = &alt_ck, .rates = gpt_alt_rates },
- { .parent = NULL },
-};
-
-static struct clk gpt1_ick = {
- .name = "gpt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt1_fck = {
- .name = "gpt1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_CLKSEL_GPT1_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-static struct clk gpt2_ick = {
- .name = "gpt2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
- .name = "gpt2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT2_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_ick = {
- .name = "gpt3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt3_fck = {
- .name = "gpt3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT3_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_ick = {
- .name = "gpt4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt4_fck = {
- .name = "gpt4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT4_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_ick = {
- .name = "gpt5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt5_fck = {
- .name = "gpt5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT5_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_ick = {
- .name = "gpt6_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt6_fck = {
- .name = "gpt6_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT6_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_ick = {
- .name = "gpt7_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt7_fck = {
- .name = "gpt7_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT7_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_ick = {
- .name = "gpt8_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt8_fck = {
- .name = "gpt8_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT8_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_ick = {
- .name = "gpt9_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt9_fck = {
- .name = "gpt9_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT9_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt10_ick = {
- .name = "gpt10_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt10_fck = {
- .name = "gpt10_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT10_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_ick = {
- .name = "gpt11_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt11_fck = {
- .name = "gpt11_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT11_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt12_ick = {
- .name = "gpt12_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt12_fck = {
- .name = "gpt12_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &secure_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- .clksel_mask = OMAP24XX_CLKSEL_GPT12_MASK,
- .clksel = omap24xx_gpt_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_ick = {
- .name = "mcbsp1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL }
-};
-
-static struct clk mcbsp1_fck = {
- .name = "mcbsp1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .clksel_reg = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP1_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp2_ick = {
- .name = "mcbsp2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp2_fck = {
- .name = "mcbsp2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .clksel_reg = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP2_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp3_ick = {
- .name = "mcbsp3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp3_fck = {
- .name = "mcbsp3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
- .clksel_reg = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP3_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp4_ick = {
- .name = "mcbsp4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp4_fck = {
- .name = "mcbsp4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
- .clksel_reg = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP4_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp5_ick = {
- .name = "mcbsp5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp5_fck = {
- .name = "mcbsp5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .init = &omap2_init_clksel_parent,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
- .clksel_reg = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP5_CLKS_MASK,
- .clksel = mcbsp_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcspi1_ick = {
- .name = "mcspi1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
- .name = "mcspi1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
- .name = "mcspi2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
- .name = "mcspi2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi3_ick = {
- .name = "mcspi3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi3_fck = {
- .name = "mcspi3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
- .name = "uart1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
- .name = "uart1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
- .name = "uart2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
- .name = "uart2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
- .name = "uart3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
- .name = "uart3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpios_ick = {
- .name = "gpios_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpios_fck = {
- .name = "gpios_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mpu_wdt_ick = {
- .name = "mpu_wdt_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mpu_wdt_fck = {
- .name = "mpu_wdt_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sync_32k_ick = {
- .name = "sync_32k_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .flags = ENABLE_ON_INIT,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
- .name = "wdt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
- .name = "omapctrl_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .flags = ENABLE_ON_INIT,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk icr_ick = {
- .name = "icr_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wu_l4_ick,
- .clkdm_name = "wkup_clkdm",
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP2430_EN_ICR_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk cam_ick = {
- .name = "cam_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * cam_fck controls both CAM_MCLK and CAM_FCLK. It should probably be
- * split into two separate clocks, since the parent clocks are different
- * and the clockdomains are also different.
- */
-static struct clk cam_fck = {
- .name = "cam_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
- .name = "mailboxes_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt4_ick = {
- .name = "wdt4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt4_fck = {
- .name = "wdt4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
- .name = "mspro_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
- .name = "mspro_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk fac_ick = {
- .name = "fac_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk fac_fck = {
- .name = "fac_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
- .name = "hdq_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
- .name = "hdq_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_12m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * XXX This is marked as a 2420-only define, but it claims to be present
- * on 2430 also. Double-check.
- */
-static struct clk i2c2_ick = {
- .name = "i2c2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2chs2_fck = {
- .name = "i2chs2_fck",
- .ops = &clkops_omap2430_i2chs_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_I2CHS2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * XXX This is marked as a 2420-only define, but it claims to be present
- * on 2430 also. Double-check.
- */
-static struct clk i2c1_ick = {
- .name = "i2c1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2chs1_fck = {
- .name = "i2chs1_fck",
- .ops = &clkops_omap2430_i2chs_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_I2CHS1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk gpmc_fck = {
- .name = "gpmc_fck",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sdma_fck = {
- .name = "sdma_fck",
- .ops = &clkops_null, /* RMK: missing? */
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdma_ick = {
- .name = "sdma_ick",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sdrc_ick = {
- .name = "sdrc_ick",
- .ops = &clkops_omap2_iclk_idle_only,
- .parent = &core_l3_ck,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP2430_EN_SDRC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk des_ick = {
- .name = "des_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_DES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sha_ick = {
- .name = "sha_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_SHA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk rng_ick = {
- .name = "rng_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_RNG_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk aes_ick = {
- .name = "aes_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_AES_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk pka_ick = {
- .name = "pka_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_PKA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_fck = {
- .name = "usb_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_48m_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usbhs_ick = {
- .name = "usbhs_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l3_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_USBHS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs1_ick = {
- .name = "mmchs1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs1_fck = {
- .name = "mmchs1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs2_ick = {
- .name = "mmchs2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs2_fck = {
- .name = "mmchs2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_96m_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
- .name = "gpio5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_fck = {
- .name = "gpio5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mdm_intc_ick = {
- .name = "mdm_intc_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchsdb1_fck = {
- .name = "mmchsdb1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchsdb2_fck = {
- .name = "mmchsdb2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * This clock is a composite clock which does entire set changes then
- * forces a rebalance. It keys on the MPU speed, but it really could
- * be any key speed part of a set in the rate table.
- *
- * to really change a set, you need memory table sets which get changed
- * in sram, pre-notifiers & post notifiers, changing the top set, without
- * having low level display recalc's won't work... this is why dpm notifiers
- * work, isr's off, walk a list of clocks already _off_ and not messing with
- * the bus.
- *
- * This clock should have no parent. It embodies the entire upper level
- * active set. A parent will mess up some of the init also.
- */
-static struct clk virt_prcm_set = {
- .name = "virt_prcm_set",
- .ops = &clkops_null,
- .parent = &mpu_ck, /* Indexed by mpu speed, no parent */
- .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */
- .set_rate = &omap2_select_table_rate,
- .round_rate = &omap2_round_to_table_rate,
-};
-
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2430_clks[] = {
- /* external root sources */
- CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X),
- CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X),
- CLK(NULL, "osc_ck", &osc_ck, CK_243X),
- CLK("twl", "fck", &osc_ck, CK_243X),
- CLK(NULL, "sys_ck", &sys_ck, CK_243X),
- CLK(NULL, "alt_ck", &alt_ck, CK_243X),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_243X),
- /* internal analog sources */
- CLK(NULL, "dpll_ck", &dpll_ck, CK_243X),
- CLK(NULL, "apll96_ck", &apll96_ck, CK_243X),
- CLK(NULL, "apll54_ck", &apll54_ck, CK_243X),
- /* internal prcm root sources */
- CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X),
- CLK(NULL, "core_ck", &core_ck, CK_243X),
- CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X),
- CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X),
- CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X),
- CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X),
- CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X),
- CLK(NULL, "sys_clkout", &sys_clkout, CK_243X),
- CLK(NULL, "emul_ck", &emul_ck, CK_243X),
- /* mpu domain clocks */
- CLK(NULL, "mpu_ck", &mpu_ck, CK_243X),
- /* dsp domain clocks */
- CLK(NULL, "dsp_fck", &dsp_fck, CK_243X),
- CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X),
- /* GFX domain clocks */
- CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X),
- CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_243X),
- CLK(NULL, "gfx_ick", &gfx_ick, CK_243X),
- /* Modem domain clocks */
- CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
- CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
- /* DSS domain clocks */
- CLK("omapdss_dss", "ick", &dss_ick, CK_243X),
- CLK(NULL, "dss_ick", &dss_ick, CK_243X),
- CLK(NULL, "dss1_fck", &dss1_fck, CK_243X),
- CLK(NULL, "dss2_fck", &dss2_fck, CK_243X),
- CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_243X),
- /* L3 domain clocks */
- CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X),
- CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X),
- /* L4 domain clocks */
- CLK(NULL, "l4_ck", &l4_ck, CK_243X),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X),
- CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_243X),
- /* virtual meta-group clock */
- CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X),
- /* general l4 interface ck, multi-parent functional clk */
- CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X),
- CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X),
- CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X),
- CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X),
- CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X),
- CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X),
- CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X),
- CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X),
- CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X),
- CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X),
- CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X),
- CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_243X),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_243X),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X),
- CLK(NULL, "mcbsp2_ick", &mcbsp2_ick, CK_243X),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_243X),
- CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X),
- CLK(NULL, "mcbsp3_ick", &mcbsp3_ick, CK_243X),
- CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_243X),
- CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X),
- CLK(NULL, "mcbsp4_ick", &mcbsp4_ick, CK_243X),
- CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_243X),
- CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X),
- CLK(NULL, "mcbsp5_ick", &mcbsp5_ick, CK_243X),
- CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_243X),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_243X),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_243X),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_243X),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_243X),
- CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X),
- CLK(NULL, "mcspi3_ick", &mcspi3_ick, CK_243X),
- CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_243X),
- CLK(NULL, "uart1_ick", &uart1_ick, CK_243X),
- CLK(NULL, "uart1_fck", &uart1_fck, CK_243X),
- CLK(NULL, "uart2_ick", &uart2_ick, CK_243X),
- CLK(NULL, "uart2_fck", &uart2_fck, CK_243X),
- CLK(NULL, "uart3_ick", &uart3_ick, CK_243X),
- CLK(NULL, "uart3_fck", &uart3_fck, CK_243X),
- CLK(NULL, "gpios_ick", &gpios_ick, CK_243X),
- CLK(NULL, "gpios_fck", &gpios_fck, CK_243X),
- CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X),
- CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_243X),
- CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_243X),
- CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X),
- CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X),
- CLK(NULL, "icr_ick", &icr_ick, CK_243X),
- CLK("omap24xxcam", "fck", &cam_fck, CK_243X),
- CLK(NULL, "cam_fck", &cam_fck, CK_243X),
- CLK("omap24xxcam", "ick", &cam_ick, CK_243X),
- CLK(NULL, "cam_ick", &cam_ick, CK_243X),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X),
- CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X),
- CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X),
- CLK(NULL, "mspro_ick", &mspro_ick, CK_243X),
- CLK(NULL, "mspro_fck", &mspro_fck, CK_243X),
- CLK(NULL, "fac_ick", &fac_ick, CK_243X),
- CLK(NULL, "fac_fck", &fac_fck, CK_243X),
- CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X),
- CLK(NULL, "hdq_ick", &hdq_ick, CK_243X),
- CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X),
- CLK(NULL, "hdq_fck", &hdq_fck, CK_243X),
- CLK("omap_i2c.1", "ick", &i2c1_ick, CK_243X),
- CLK(NULL, "i2c1_ick", &i2c1_ick, CK_243X),
- CLK(NULL, "i2chs1_fck", &i2chs1_fck, CK_243X),
- CLK("omap_i2c.2", "ick", &i2c2_ick, CK_243X),
- CLK(NULL, "i2c2_ick", &i2c2_ick, CK_243X),
- CLK(NULL, "i2chs2_fck", &i2chs2_fck, CK_243X),
- CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X),
- CLK(NULL, "sdma_fck", &sdma_fck, CK_243X),
- CLK(NULL, "sdma_ick", &sdma_ick, CK_243X),
- CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X),
- CLK(NULL, "des_ick", &des_ick, CK_243X),
- CLK("omap-sham", "ick", &sha_ick, CK_243X),
- CLK("omap_rng", "ick", &rng_ick, CK_243X),
- CLK(NULL, "rng_ick", &rng_ick, CK_243X),
- CLK("omap-aes", "ick", &aes_ick, CK_243X),
- CLK(NULL, "pka_ick", &pka_ick, CK_243X),
- CLK(NULL, "usb_fck", &usb_fck, CK_243X),
- CLK("musb-omap2430", "ick", &usbhs_ick, CK_243X),
- CLK(NULL, "usbhs_ick", &usbhs_ick, CK_243X),
- CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_243X),
- CLK(NULL, "mmchs1_ick", &mmchs1_ick, CK_243X),
- CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_243X),
- CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_243X),
- CLK(NULL, "mmchs2_ick", &mmchs2_ick, CK_243X),
- CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_243X),
- CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X),
- CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X),
- CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
- CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
- CLK(NULL, "mmchsdb1_fck", &mmchsdb1_fck, CK_243X),
- CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
- CLK(NULL, "mmchsdb2_fck", &mmchsdb2_fck, CK_243X),
- CLK(NULL, "timer_32k_ck", &func_32k_ck, CK_243X),
- CLK(NULL, "timer_sys_ck", &sys_ck, CK_243X),
- CLK(NULL, "timer_ext_ck", &alt_ck, CK_243X),
- CLK(NULL, "cpufreq_ck", &virt_prcm_set, CK_243X),
-};
-
-/*
- * init code
- */
-
-int __init omap2430_clk_init(void)
-{
- struct omap_clk *c;
-
- prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
- cpu_mask = RATE_IN_243X;
- rate_table = omap2430_rate_table;
-
- for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
- c++)
- clk_preinit(c->lk.clk);
-
- osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
- propagate_rate(&osc_ck);
- sys_ck.rate = omap2xxx_sys_clk_recalc(&sys_ck);
- propagate_rate(&sys_ck);
-
- for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
- c++) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- omap2_init_clk_clkdm(c->lk.clk);
- }
-
- omap2xxx_clkt_vps_late_init();
-
- /* Disable autoidle on all clocks; let the PM code enable it later */
- omap_clk_disable_autoidle_all();
-
- /* XXX Can this be done from the virt_prcm_set clk init function? */
- omap2xxx_clkt_vps_check_bootloader_rates();
-
- recalculate_root_clocks();
-
- pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
- (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
-
- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable_init_clocks();
-
- return 0;
-}
-
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
index 5f7faeb4c19b..1ff646908627 100644
--- a/arch/arm/mach-omap2/clock2xxx.c
+++ b/arch/arm/mach-omap2/clock2xxx.c
@@ -28,6 +28,7 @@
#include "cm.h"
#include "cm-regbits-24xx.h"
+struct clk_hw *dclk_hw;
/*
* Omap24xx specific clock functions
*/
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h
index ce809c913b6f..539dc08afbba 100644
--- a/arch/arm/mach-omap2/clock2xxx.h
+++ b/arch/arm/mach-omap2/clock2xxx.h
@@ -8,18 +8,32 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
-unsigned long omap2_table_mpu_recalc(struct clk *clk);
-int omap2_select_table_rate(struct clk *clk, unsigned long rate);
-long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
-unsigned long omap2xxx_sys_clk_recalc(struct clk *clk);
-unsigned long omap2_osc_clk_recalc(struct clk *clk);
-unsigned long omap2_dpllcore_recalc(struct clk *clk);
-int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
+#include <linux/clk-provider.h>
+#include "clock.h"
+
+unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
+ unsigned long parent_rate);
+int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate);
+unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
+ unsigned long parent_rate);
+unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
+ unsigned long parent_rate);
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
+int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
+ unsigned long parent_rate);
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
+unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
+unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
+ unsigned long parent_rate);
unsigned long omap2xxx_clk_get_core_rate(void);
u32 omap2xxx_get_apll_clkin(void);
u32 omap2xxx_get_sysclkdiv(void);
void omap2xxx_clk_prepare_for_reboot(void);
-void omap2xxx_clkt_dpllcore_init(struct clk *clk);
void omap2xxx_clkt_vps_check_bootloader_rates(void);
void omap2xxx_clkt_vps_late_init(void);
@@ -37,9 +51,12 @@ int omap2430_clk_init(void);
extern void __iomem *prcm_clksrc_ctrl;
-extern const struct clkops clkops_omap2430_i2chs_wait;
-extern const struct clkops clkops_oscck;
-extern const struct clkops clkops_apll96;
-extern const struct clkops clkops_apll54;
+extern struct clk_hw *dclk_hw;
+int omap2_enable_osc_ck(struct clk_hw *hw);
+void omap2_disable_osc_ck(struct clk_hw *hw);
+int omap2_clk_apll96_enable(struct clk_hw *hw);
+int omap2_clk_apll54_enable(struct clk_hw *hw);
+void omap2_clk_apll96_disable(struct clk_hw *hw);
+void omap2_clk_apll54_disable(struct clk_hw *hw);
#endif
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
deleted file mode 100644
index 17e3de51bcba..000000000000
--- a/arch/arm/mach-omap2/clock33xx_data.c
+++ /dev/null
@@ -1,1109 +0,0 @@
-/*
- * AM33XX Clock data
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Vaibhav Hiremath <hvaibhav@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.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "control.h"
-#include "clock.h"
-#include "cm.h"
-#include "cm33xx.h"
-#include "cm-regbits-33xx.h"
-#include "prm.h"
-
-/* Maximum DPLL multiplier, divider values for AM33XX */
-#define AM33XX_MAX_DPLL_MULT 2047
-#define AM33XX_MAX_DPLL_DIV 128
-
-/* Modulemode control */
-#define AM33XX_MODULEMODE_HWCTRL 0
-#define AM33XX_MODULEMODE_SWCTRL 1
-
-/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
- * physically present, in such a case HWMOD enabling of
- * clock would be failure with default parent. And timer
- * probe thinks clock is already enabled, this leads to
- * crash upon accessing timer 3 & 6 registers in probe.
- * Fix by setting parent of both these timers to master
- * oscillator clock.
- */
-static inline void am33xx_init_timer_parent(struct clk *clk)
-{
- omap2_clksel_set_parent(clk, clk->parent);
-}
-
-/* Root clocks */
-
-/* RTC 32k */
-static struct clk clk_32768_ck = {
- .name = "clk_32768_ck",
- .clkdm_name = "l4_rtc_clkdm",
- .rate = 32768,
- .ops = &clkops_null,
-};
-
-/* On-Chip 32KHz RC OSC */
-static struct clk clk_rc32k_ck = {
- .name = "clk_rc32k_ck",
- .rate = 32000,
- .ops = &clkops_null,
-};
-
-/* Crystal input clks */
-static struct clk virt_24000000_ck = {
- .name = "virt_24000000_ck",
- .rate = 24000000,
- .ops = &clkops_null,
-};
-
-static struct clk virt_25000000_ck = {
- .name = "virt_25000000_ck",
- .rate = 25000000,
- .ops = &clkops_null,
-};
-
-/* Oscillator clock */
-/* 19.2, 24, 25 or 26 MHz */
-static const struct clksel sys_clkin_sel[] = {
- { .parent = &virt_19200000_ck, .rates = div_1_0_rates },
- { .parent = &virt_24000000_ck, .rates = div_1_1_rates },
- { .parent = &virt_25000000_ck, .rates = div_1_2_rates },
- { .parent = &virt_26000000_ck, .rates = div_1_3_rates },
- { .parent = NULL },
-};
-
-/* External clock - 12 MHz */
-static struct clk tclkin_ck = {
- .name = "tclkin_ck",
- .rate = 12000000,
- .ops = &clkops_null,
-};
-
-/*
- * sys_clk in: input to the dpll and also used as funtional clock for,
- * adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
- *
- */
-static struct clk sys_clkin_ck = {
- .name = "sys_clkin_ck",
- .parent = &virt_24000000_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
- .clksel_mask = AM33XX_CONTROL_STATUS_SYSBOOT1_MASK,
- .clksel = sys_clkin_sel,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = AM33XX_CM_CLKMODE_DPLL_CORE,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE,
- .mult_mask = AM33XX_DPLL_MULT_MASK,
- .div1_mask = AM33XX_DPLL_DIV_MASK,
- .enable_mask = AM33XX_DPLL_EN_MASK,
- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
- .max_multiplier = AM33XX_MAX_DPLL_MULT,
- .max_divider = AM33XX_MAX_DPLL_DIV,
- .min_divider = 1,
-};
-
-/* CLKDCOLDO output */
-static struct clk dpll_core_ck = {
- .name = "dpll_core_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_core_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_core_dpll_ops,
- .recalc = &omap3_dpll_recalc,
-};
-
-static struct clk dpll_core_x2_ck = {
- .name = "dpll_core_x2_ck",
- .parent = &dpll_core_ck,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_null,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-
-static const struct clksel dpll_core_m4_div[] = {
- { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_core_m4_ck = {
- .name = "dpll_core_m4_ck",
- .parent = &dpll_core_x2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = dpll_core_m4_div,
- .clksel_reg = AM33XX_CM_DIV_M4_DPLL_CORE,
- .clksel_mask = AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel dpll_core_m5_div[] = {
- { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_core_m5_ck = {
- .name = "dpll_core_m5_ck",
- .parent = &dpll_core_x2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = dpll_core_m5_div,
- .clksel_reg = AM33XX_CM_DIV_M5_DPLL_CORE,
- .clksel_mask = AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel dpll_core_m6_div[] = {
- { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_core_m6_ck = {
- .name = "dpll_core_m6_ck",
- .parent = &dpll_core_x2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = dpll_core_m6_div,
- .clksel_reg = AM33XX_CM_DIV_M6_DPLL_CORE,
- .clksel_mask = AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = AM33XX_CM_CLKMODE_DPLL_MPU,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU,
- .mult_mask = AM33XX_DPLL_MULT_MASK,
- .div1_mask = AM33XX_DPLL_DIV_MASK,
- .enable_mask = AM33XX_DPLL_EN_MASK,
- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
- .max_multiplier = AM33XX_MAX_DPLL_MULT,
- .max_divider = AM33XX_MAX_DPLL_DIV,
- .min_divider = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_mpu_ck = {
- .name = "dpll_mpu_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_mpu_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_mpu_m2_div[] = {
- { .parent = &dpll_mpu_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_mpu_m2_ck = {
- .name = "dpll_mpu_m2_ck",
- .clkdm_name = "mpu_clkdm",
- .parent = &dpll_mpu_ck,
- .clksel = dpll_mpu_m2_div,
- .clksel_reg = AM33XX_CM_DIV_M2_DPLL_MPU,
- .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* DPLL_DDR */
-static struct dpll_data dpll_ddr_dd = {
- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DDR,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = AM33XX_CM_CLKMODE_DPLL_DDR,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .idlest_reg = AM33XX_CM_IDLEST_DPLL_DDR,
- .mult_mask = AM33XX_DPLL_MULT_MASK,
- .div1_mask = AM33XX_DPLL_DIV_MASK,
- .enable_mask = AM33XX_DPLL_EN_MASK,
- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
- .max_multiplier = AM33XX_MAX_DPLL_MULT,
- .max_divider = AM33XX_MAX_DPLL_DIV,
- .min_divider = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_ddr_ck = {
- .name = "dpll_ddr_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_ddr_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_null,
- .recalc = &omap3_dpll_recalc,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_ddr_m2_div[] = {
- { .parent = &dpll_ddr_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_ddr_m2_ck = {
- .name = "dpll_ddr_m2_ck",
- .parent = &dpll_ddr_ck,
- .clksel = dpll_ddr_m2_div,
- .clksel_reg = AM33XX_CM_DIV_M2_DPLL_DDR,
- .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* emif_fck functional clock */
-static struct clk dpll_ddr_m2_div2_ck = {
- .name = "dpll_ddr_m2_div2_ck",
- .clkdm_name = "l3_clkdm",
- .parent = &dpll_ddr_m2_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/* DPLL_DISP */
-static struct dpll_data dpll_disp_dd = {
- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DISP,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = AM33XX_CM_CLKMODE_DPLL_DISP,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .idlest_reg = AM33XX_CM_IDLEST_DPLL_DISP,
- .mult_mask = AM33XX_DPLL_MULT_MASK,
- .div1_mask = AM33XX_DPLL_DIV_MASK,
- .enable_mask = AM33XX_DPLL_EN_MASK,
- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
- .max_multiplier = AM33XX_MAX_DPLL_MULT,
- .max_divider = AM33XX_MAX_DPLL_DIV,
- .min_divider = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_disp_ck = {
- .name = "dpll_disp_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_disp_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_null,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_disp_m2_div[] = {
- { .parent = &dpll_disp_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_disp_m2_ck = {
- .name = "dpll_disp_m2_ck",
- .parent = &dpll_disp_ck,
- .clksel = dpll_disp_m2_div,
- .clksel_reg = AM33XX_CM_DIV_M2_DPLL_DISP,
- .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_PERIPH,
- .clk_bypass = &sys_clkin_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = AM33XX_CM_CLKMODE_DPLL_PER,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .idlest_reg = AM33XX_CM_IDLEST_DPLL_PER,
- .mult_mask = AM33XX_DPLL_MULT_PERIPH_MASK,
- .div1_mask = AM33XX_DPLL_PER_DIV_MASK,
- .enable_mask = AM33XX_DPLL_EN_MASK,
- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
- .max_multiplier = AM33XX_MAX_DPLL_MULT,
- .max_divider = AM33XX_MAX_DPLL_DIV,
- .min_divider = 1,
- .flags = DPLL_J_TYPE,
-};
-
-/* CLKDCOLDO */
-static struct clk dpll_per_ck = {
- .name = "dpll_per_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_per_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_null,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-/* CLKOUT: fdpll/M2 */
-static const struct clksel dpll_per_m2_div[] = {
- { .parent = &dpll_per_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_per_m2_ck = {
- .name = "dpll_per_m2_ck",
- .parent = &dpll_per_ck,
- .clksel = dpll_per_m2_div,
- .clksel_reg = AM33XX_CM_DIV_M2_DPLL_PER,
- .clksel_mask = AM33XX_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m2_div4_wkupdm_ck = {
- .name = "dpll_per_m2_div4_wkupdm_ck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &dpll_per_m2_ck,
- .fixed_div = 4,
- .ops = &clkops_null,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk dpll_per_m2_div4_ck = {
- .name = "dpll_per_m2_div4_ck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &dpll_per_m2_ck,
- .fixed_div = 4,
- .ops = &clkops_null,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk l3_gclk = {
- .name = "l3_gclk",
- .clkdm_name = "l3_clkdm",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dpll_core_m4_div2_ck = {
- .name = "dpll_core_m4_div2_ck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk l4_rtc_gclk = {
- .name = "l4_rtc_gclk",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk clk_24mhz = {
- .name = "clk_24mhz",
- .parent = &dpll_per_m2_ck,
- .fixed_div = 8,
- .ops = &clkops_null,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/*
- * Below clock nodes describes clockdomains derived out
- * of core clock.
- */
-static struct clk l4hs_gclk = {
- .name = "l4hs_gclk",
- .clkdm_name = "l4hs_clkdm",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk l3s_gclk = {
- .name = "l3s_gclk",
- .clkdm_name = "l3s_clkdm",
- .parent = &dpll_core_m4_div2_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk l4fw_gclk = {
- .name = "l4fw_gclk",
- .clkdm_name = "l4fw_clkdm",
- .parent = &dpll_core_m4_div2_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk l4ls_gclk = {
- .name = "l4ls_gclk",
- .clkdm_name = "l4ls_clkdm",
- .parent = &dpll_core_m4_div2_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sysclk_div_ck = {
- .name = "sysclk_div_ck",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-/*
- * In order to match the clock domain with hwmod clockdomain entry,
- * separate clock nodes is required for the modules which are
- * directly getting their funtioncal clock from sys_clkin.
- */
-static struct clk adc_tsc_fck = {
- .name = "adc_tsc_fck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dcan0_fck = {
- .name = "dcan0_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dcan1_fck = {
- .name = "dcan1_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcasp0_fck = {
- .name = "mcasp0_fck",
- .clkdm_name = "l3s_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcasp1_fck = {
- .name = "mcasp1_fck",
- .clkdm_name = "l3s_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk smartreflex0_fck = {
- .name = "smartreflex0_fck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk smartreflex1_fck = {
- .name = "smartreflex1_fck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-/*
- * Modules clock nodes
- *
- * The following clock leaf nodes are added for the moment because:
- *
- * - hwmod data is not present for these modules, either hwmod
- * control is not required or its not populated.
- * - Driver code is not yet migrated to use hwmod/runtime pm
- * - Modules outside kernel access (to disable them by default)
- *
- * - debugss
- * - mmu (gfx domain)
- * - cefuse
- * - usbotg_fck (its additional clock and not really a modulemode)
- * - ieee5000
- */
-static struct clk debugss_ick = {
- .name = "debugss_ick",
- .clkdm_name = "l3_aon_clkdm",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_omap2_dflt,
- .enable_reg = AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
- .enable_bit = AM33XX_MODULEMODE_SWCTRL,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmu_fck = {
- .name = "mmu_fck",
- .clkdm_name = "gfx_l3_clkdm",
- .parent = &dpll_core_m4_ck,
- .ops = &clkops_omap2_dflt,
- .enable_reg = AM33XX_CM_GFX_MMUDATA_CLKCTRL,
- .enable_bit = AM33XX_MODULEMODE_SWCTRL,
- .recalc = &followparent_recalc,
-};
-
-static struct clk cefuse_fck = {
- .name = "cefuse_fck",
- .clkdm_name = "l4_cefuse_clkdm",
- .parent = &sys_clkin_ck,
- .enable_reg = AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL,
- .enable_bit = AM33XX_MODULEMODE_SWCTRL,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-/*
- * clkdiv32 is generated from fixed division of 732.4219
- */
-static struct clk clkdiv32k_ick = {
- .name = "clkdiv32k_ick",
- .clkdm_name = "clk_24mhz_clkdm",
- .rate = 32768,
- .parent = &clk_24mhz,
- .enable_reg = AM33XX_CM_PER_CLKDIV32K_CLKCTRL,
- .enable_bit = AM33XX_MODULEMODE_SWCTRL,
- .ops = &clkops_omap2_dflt,
-};
-
-static struct clk usbotg_fck = {
- .name = "usbotg_fck",
- .clkdm_name = "l3s_clkdm",
- .parent = &dpll_per_ck,
- .enable_reg = AM33XX_CM_CLKDCOLDO_DPLL_PER,
- .enable_bit = AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ieee5000_fck = {
- .name = "ieee5000_fck",
- .clkdm_name = "l3s_clkdm",
- .parent = &dpll_core_m4_div2_ck,
- .enable_reg = AM33XX_CM_PER_IEEE5000_CLKCTRL,
- .enable_bit = AM33XX_MODULEMODE_SWCTRL,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-/* Timers */
-static const struct clksel timer1_clkmux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
- { .parent = &tclkin_ck, .rates = div_1_2_rates },
- { .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
- { .parent = &clk_32768_ck, .rates = div_1_4_rates },
- { .parent = NULL },
-};
-
-static struct clk timer1_fck = {
- .name = "timer1_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = timer1_clkmux_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER1MS_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_2_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel timer2_to_7_clk_sel[] = {
- { .parent = &tclkin_ck, .rates = div_1_0_rates },
- { .parent = &sys_clkin_ck, .rates = div_1_1_rates },
- { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static struct clk timer2_fck = {
- .name = "timer2_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER2_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk timer3_fck = {
- .name = "timer3_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &am33xx_init_timer_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER3_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk timer4_fck = {
- .name = "timer4_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER4_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk timer5_fck = {
- .name = "timer5_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER5_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk timer6_fck = {
- .name = "timer6_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &am33xx_init_timer_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER6_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk timer7_fck = {
- .name = "timer7_fck",
- .clkdm_name = "l4ls_clkdm",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = timer2_to_7_clk_sel,
- .clksel_reg = AM33XX_CLKSEL_TIMER7_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk cpsw_125mhz_gclk = {
- .name = "cpsw_125mhz_gclk",
- .clkdm_name = "cpsw_125mhz_clkdm",
- .parent = &dpll_core_m5_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
- { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
- { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk cpsw_cpts_rft_clk = {
- .name = "cpsw_cpts_rft_clk",
- .clkdm_name = "cpsw_125mhz_clkdm",
- .parent = &dpll_core_m5_ck,
- .clksel = cpsw_cpts_rft_clkmux_sel,
- .clksel_reg = AM33XX_CM_CPTS_RFT_CLKSEL,
- .clksel_mask = AM33XX_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-/* gpio */
-static const struct clksel gpio0_dbclk_mux_sel[] = {
- { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
- { .parent = &clk_32768_ck, .rates = div_1_1_rates },
- { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static struct clk gpio0_dbclk_mux_ck = {
- .name = "gpio0_dbclk_mux_ck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &clk_rc32k_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = gpio0_dbclk_mux_sel,
- .clksel_reg = AM33XX_CLKSEL_GPIO0_DBCLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpio0_dbclk = {
- .name = "gpio0_dbclk",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &gpio0_dbclk_mux_ck,
- .enable_reg = AM33XX_CM_WKUP_GPIO0_CLKCTRL,
- .enable_bit = AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio1_dbclk = {
- .name = "gpio1_dbclk",
- .clkdm_name = "l4ls_clkdm",
- .parent = &clkdiv32k_ick,
- .enable_reg = AM33XX_CM_PER_GPIO1_CLKCTRL,
- .enable_bit = AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio2_dbclk = {
- .name = "gpio2_dbclk",
- .clkdm_name = "l4ls_clkdm",
- .parent = &clkdiv32k_ick,
- .enable_reg = AM33XX_CM_PER_GPIO2_CLKCTRL,
- .enable_bit = AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio3_dbclk = {
- .name = "gpio3_dbclk",
- .clkdm_name = "l4ls_clkdm",
- .parent = &clkdiv32k_ick,
- .enable_reg = AM33XX_CM_PER_GPIO3_CLKCTRL,
- .enable_bit = AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT,
- .ops = &clkops_omap2_dflt,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel pruss_ocp_clk_mux_sel[] = {
- { .parent = &l3_gclk, .rates = div_1_0_rates },
- { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk pruss_ocp_gclk = {
- .name = "pruss_ocp_gclk",
- .clkdm_name = "pruss_ocp_clkdm",
- .parent = &l3_gclk,
- .init = &omap2_init_clksel_parent,
- .clksel = pruss_ocp_clk_mux_sel,
- .clksel_reg = AM33XX_CLKSEL_PRUSS_OCP_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel lcd_clk_mux_sel[] = {
- { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
- { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
- { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static struct clk lcd_gclk = {
- .name = "lcd_gclk",
- .clkdm_name = "lcdc_clkdm",
- .parent = &dpll_disp_m2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = lcd_clk_mux_sel,
- .clksel_reg = AM33XX_CLKSEL_LCDC_PIXEL_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmc_clk = {
- .name = "mmc_clk",
- .clkdm_name = "l4ls_clkdm",
- .parent = &dpll_per_m2_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk mmc2_fck = {
- .name = "mmc2_fck",
- .clkdm_name = "l3s_clkdm",
- .parent = &mmc_clk,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel gfx_clksel_sel[] = {
- { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
- { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk gfx_fclk_clksel_ck = {
- .name = "gfx_fclk_clksel_ck",
- .parent = &dpll_core_m4_ck,
- .clksel = gfx_clksel_sel,
- .ops = &clkops_null,
- .clksel_reg = AM33XX_CLKSEL_GFX_FCLK,
- .clksel_mask = AM33XX_CLKSEL_GFX_FCLK_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div_1_0_2_1_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
- { .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
- { .div = 0 },
-};
-
-static const struct clksel gfx_div_sel[] = {
- { .parent = &gfx_fclk_clksel_ck, .rates = div_1_0_2_1_rates },
- { .parent = NULL },
-};
-
-static struct clk gfx_fck_div_ck = {
- .name = "gfx_fck_div_ck",
- .clkdm_name = "gfx_l3_clkdm",
- .parent = &gfx_fclk_clksel_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = gfx_div_sel,
- .clksel_reg = AM33XX_CLKSEL_GFX_FCLK,
- .clksel_mask = AM33XX_CLKSEL_0_0_MASK,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
- .ops = &clkops_null,
-};
-
-static const struct clksel sysclkout_pre_sel[] = {
- { .parent = &clk_32768_ck, .rates = div_1_0_rates },
- { .parent = &l3_gclk, .rates = div_1_1_rates },
- { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
- { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
- { .parent = &lcd_gclk, .rates = div_1_4_rates },
- { .parent = NULL },
-};
-
-static struct clk sysclkout_pre_ck = {
- .name = "sysclkout_pre_ck",
- .parent = &clk_32768_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = sysclkout_pre_sel,
- .clksel_reg = AM33XX_CM_CLKOUT_CTRL,
- .clksel_mask = AM33XX_CLKOUT2SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* Divide by 8 clock rates with default clock is 1/1*/
-static const struct clksel_rate div8_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
- { .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
- { .div = 3, .val = 2, .flags = RATE_IN_AM33XX },
- { .div = 4, .val = 3, .flags = RATE_IN_AM33XX },
- { .div = 5, .val = 4, .flags = RATE_IN_AM33XX },
- { .div = 6, .val = 5, .flags = RATE_IN_AM33XX },
- { .div = 7, .val = 6, .flags = RATE_IN_AM33XX },
- { .div = 8, .val = 7, .flags = RATE_IN_AM33XX },
- { .div = 0 },
-};
-
-static const struct clksel clkout2_div[] = {
- { .parent = &sysclkout_pre_ck, .rates = div8_rates },
- { .parent = NULL },
-};
-
-static struct clk clkout2_ck = {
- .name = "clkout2_ck",
- .parent = &sysclkout_pre_ck,
- .ops = &clkops_omap2_dflt,
- .clksel = clkout2_div,
- .clksel_reg = AM33XX_CM_CLKOUT_CTRL,
- .clksel_mask = AM33XX_CLKOUT2DIV_MASK,
- .enable_reg = AM33XX_CM_CLKOUT_CTRL,
- .enable_bit = AM33XX_CLKOUT2EN_SHIFT,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel wdt_clkmux_sel[] = {
- { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
- { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk wdt1_fck = {
- .name = "wdt1_fck",
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &clk_rc32k_ck,
- .init = &omap2_init_clksel_parent,
- .clksel = wdt_clkmux_sel,
- .clksel_reg = AM33XX_CLKSEL_WDT1_CLK,
- .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * clkdev
- */
-static struct omap_clk am33xx_clks[] = {
- CLK(NULL, "clk_32768_ck", &clk_32768_ck, CK_AM33XX),
- CLK(NULL, "clk_rc32k_ck", &clk_rc32k_ck, CK_AM33XX),
- CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_AM33XX),
- CLK(NULL, "virt_24000000_ck", &virt_24000000_ck, CK_AM33XX),
- CLK(NULL, "virt_25000000_ck", &virt_25000000_ck, CK_AM33XX),
- CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_AM33XX),
- CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_AM33XX),
- CLK(NULL, "tclkin_ck", &tclkin_ck, CK_AM33XX),
- CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_AM33XX),
- CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_AM33XX),
- CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck, CK_AM33XX),
- CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck, CK_AM33XX),
- CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck, CK_AM33XX),
- CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_AM33XX),
- CLK("cpu0", NULL, &dpll_mpu_ck, CK_AM33XX),
- CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_AM33XX),
- CLK(NULL, "dpll_ddr_ck", &dpll_ddr_ck, CK_AM33XX),
- CLK(NULL, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck, CK_AM33XX),
- CLK(NULL, "dpll_ddr_m2_div2_ck", &dpll_ddr_m2_div2_ck, CK_AM33XX),
- CLK(NULL, "dpll_disp_ck", &dpll_disp_ck, CK_AM33XX),
- CLK(NULL, "dpll_disp_m2_ck", &dpll_disp_m2_ck, CK_AM33XX),
- CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_AM33XX),
- CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_AM33XX),
- CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", &dpll_per_m2_div4_wkupdm_ck, CK_AM33XX),
- CLK(NULL, "dpll_per_m2_div4_ck", &dpll_per_m2_div4_ck, CK_AM33XX),
- CLK(NULL, "adc_tsc_fck", &adc_tsc_fck, CK_AM33XX),
- CLK(NULL, "cefuse_fck", &cefuse_fck, CK_AM33XX),
- CLK(NULL, "clkdiv32k_ick", &clkdiv32k_ick, CK_AM33XX),
- CLK(NULL, "dcan0_fck", &dcan0_fck, CK_AM33XX),
- CLK("481cc000.d_can", NULL, &dcan0_fck, CK_AM33XX),
- CLK(NULL, "dcan1_fck", &dcan1_fck, CK_AM33XX),
- CLK("481d0000.d_can", NULL, &dcan1_fck, CK_AM33XX),
- CLK(NULL, "debugss_ick", &debugss_ick, CK_AM33XX),
- CLK(NULL, "pruss_ocp_gclk", &pruss_ocp_gclk, CK_AM33XX),
- CLK("davinci-mcasp.0", NULL, &mcasp0_fck, CK_AM33XX),
- CLK("davinci-mcasp.1", NULL, &mcasp1_fck, CK_AM33XX),
- CLK(NULL, "mcasp0_fck", &mcasp0_fck, CK_AM33XX),
- CLK(NULL, "mcasp1_fck", &mcasp1_fck, CK_AM33XX),
- CLK("NULL", "mmc2_fck", &mmc2_fck, CK_AM33XX),
- CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX),
- CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX),
- CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX),
- CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX),
- CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX),
- CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX),
- CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX),
- CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX),
- CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX),
- CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX),
- CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX),
- CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX),
- CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX),
- CLK(NULL, "l4_rtc_gclk", &l4_rtc_gclk, CK_AM33XX),
- CLK(NULL, "l3_gclk", &l3_gclk, CK_AM33XX),
- CLK(NULL, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck, CK_AM33XX),
- CLK(NULL, "l4hs_gclk", &l4hs_gclk, CK_AM33XX),
- CLK(NULL, "l3s_gclk", &l3s_gclk, CK_AM33XX),
- CLK(NULL, "l4fw_gclk", &l4fw_gclk, CK_AM33XX),
- CLK(NULL, "l4ls_gclk", &l4ls_gclk, CK_AM33XX),
- CLK(NULL, "clk_24mhz", &clk_24mhz, CK_AM33XX),
- CLK(NULL, "sysclk_div_ck", &sysclk_div_ck, CK_AM33XX),
- CLK(NULL, "cpsw_125mhz_gclk", &cpsw_125mhz_gclk, CK_AM33XX),
- CLK(NULL, "cpsw_cpts_rft_clk", &cpsw_cpts_rft_clk, CK_AM33XX),
- CLK(NULL, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, CK_AM33XX),
- CLK(NULL, "gpio0_dbclk", &gpio0_dbclk, CK_AM33XX),
- CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_AM33XX),
- CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_AM33XX),
- CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_AM33XX),
- CLK(NULL, "lcd_gclk", &lcd_gclk, CK_AM33XX),
- CLK(NULL, "mmc_clk", &mmc_clk, CK_AM33XX),
- CLK(NULL, "gfx_fclk_clksel_ck", &gfx_fclk_clksel_ck, CK_AM33XX),
- CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX),
- CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX),
- CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX),
- CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
- CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
-};
-
-int __init am33xx_clk_init(void)
-{
- struct omap_clk *c;
- u32 cpu_clkflg;
-
- if (soc_is_am33xx()) {
- cpu_mask = RATE_IN_AM33XX;
- cpu_clkflg = CK_AM33XX;
- }
-
- for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)
- clk_preinit(c->lk.clk);
-
- for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
- if (c->cpu & cpu_clkflg) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- omap2_init_clk_clkdm(c->lk.clk);
- }
- }
-
- recalculate_root_clocks();
-
- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable_init_clocks();
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index e41819ba7482..4596468e50ab 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -37,7 +37,7 @@
* from the CM_{I,F}CLKEN bit. Pass back the correct info via
* @idlest_reg and @idlest_bit. No return value.
*/
-static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -49,21 +49,16 @@ static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
-
-const struct clkops clkops_omap3430es2_ssi_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
.find_idlest = omap3430es2_clk_ssi_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+ .find_companion = omap2_clk_dflt_find_companion,
};
-const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_idlest = omap3430es2_clk_ssi_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
+ .find_idlest = omap3430es2_clk_ssi_find_idlest,
+ .find_companion = omap2_clk_dflt_find_companion,
};
/**
@@ -80,7 +75,7 @@ const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
* default find_idlest code assumes that they are at the same
* position.) No return value.
*/
-static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -94,20 +89,16 @@ static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
-const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
.find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+ .find_companion = omap2_clk_dflt_find_companion,
};
-const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
+ .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
+ .find_companion = omap2_clk_dflt_find_companion,
};
/**
@@ -121,7 +112,7 @@ const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
* shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
* @idlest_reg and @idlest_bit. No return value.
*/
-static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -134,18 +125,14 @@ static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
-const struct clkops clkops_omap3430es2_hsotgusb_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
+ .allow_idle = omap2_clkt_iclk_allow_idle,
+ .deny_idle = omap2_clkt_iclk_deny_idle,
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+ .find_companion = omap2_clk_dflt_find_companion,
};
-const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
.find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
- .allow_idle = omap2_clkt_iclk_allow_idle,
- .deny_idle = omap2_clkt_iclk_deny_idle,
+ .find_companion = omap2_clk_dflt_find_companion,
};
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
index 622ea0502610..4d79ae2c0241 100644
--- a/arch/arm/mach-omap2/clock3517.c
+++ b/arch/arm/mach-omap2/clock3517.c
@@ -47,7 +47,7 @@
* in the enable register itsel at a bit offset of 4 from the enable
* bit. A value of 1 indicates that clock is enabled.
*/
-static void am35xx_clk_find_idlest(struct clk *clk,
+static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -71,8 +71,9 @@ static void am35xx_clk_find_idlest(struct clk *clk,
* associate this type of code with per-module data structures to
* avoid this issue, and remove the casts. No return value.
*/
-static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
- u8 *other_bit)
+static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
+ void __iomem **other_reg,
+ u8 *other_bit)
{
*other_reg = (__force void __iomem *)(clk->enable_reg);
if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
@@ -80,10 +81,7 @@ static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
else
*other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
}
-
-const struct clkops clkops_am35xx_ipss_module_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
.find_idlest = am35xx_clk_find_idlest,
.find_companion = am35xx_clk_find_companion,
};
@@ -99,7 +97,7 @@ const struct clkops clkops_am35xx_ipss_module_wait = {
* CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
* and @idlest_bit. No return value.
*/
-static void am35xx_clk_ipss_find_idlest(struct clk *clk,
+static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
void __iomem **idlest_reg,
u8 *idlest_bit,
u8 *idlest_val)
@@ -112,13 +110,9 @@ static void am35xx_clk_ipss_find_idlest(struct clk *clk,
*idlest_val = OMAP34XX_CM_IDLEST_VAL;
}
-const struct clkops clkops_am35xx_ipss_wait = {
- .enable = omap2_dflt_clk_enable,
- .disable = omap2_dflt_clk_disable,
- .find_idlest = am35xx_clk_ipss_find_idlest,
- .find_companion = omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
.allow_idle = omap2_clkt_iclk_allow_idle,
.deny_idle = omap2_clkt_iclk_deny_idle,
+ .find_idlest = am35xx_clk_ipss_find_idlest,
+ .find_companion = omap2_clk_dflt_find_companion,
};
-
-
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c
index 0e1e9e4e2fa4..8f3bf4e50908 100644
--- a/arch/arm/mach-omap2/clock36xx.c
+++ b/arch/arm/mach-omap2/clock36xx.c
@@ -37,34 +37,32 @@
* (Any other value different from the Read value) to the
* corresponding CM_CLKSEL register will refresh the dividers.
*/
-static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk)
+int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
{
+ struct clk_hw_omap *parent;
+ struct clk_hw *parent_hw;
u32 dummy_v, orig_v, clksel_shift;
int ret;
/* Clear PWRDN bit of HSDIVIDER */
ret = omap2_dflt_clk_enable(clk);
+ parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
+ parent = to_clk_hw_omap(parent_hw);
+
/* Restore the dividers */
if (!ret) {
- clksel_shift = __ffs(clk->parent->clksel_mask);
- orig_v = __raw_readl(clk->parent->clksel_reg);
+ clksel_shift = __ffs(parent->clksel_mask);
+ orig_v = __raw_readl(parent->clksel_reg);
dummy_v = orig_v;
/* Write any other value different from the Read value */
dummy_v ^= (1 << clksel_shift);
- __raw_writel(dummy_v, clk->parent->clksel_reg);
+ __raw_writel(dummy_v, parent->clksel_reg);
/* Write the original divider */
- __raw_writel(orig_v, clk->parent->clksel_reg);
+ __raw_writel(orig_v, parent->clksel_reg);
}
return ret;
}
-
-const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = {
- .enable = omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
- .disable = omap2_dflt_clk_disable,
- .find_companion = omap2_clk_dflt_find_companion,
- .find_idlest = omap2_clk_dflt_find_idlest,
-};
diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h
index a7dee5bc6364..945bb7f083e9 100644
--- a/arch/arm/mach-omap2/clock36xx.h
+++ b/arch/arm/mach-omap2/clock36xx.h
@@ -8,6 +8,6 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
-extern const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
+extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
#endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index 3e8aca2b1b61..4eacab8f1176 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -38,8 +38,8 @@
/* needed by omap3_core_dpll_m2_set_rate() */
struct clk *sdrc_ick_p, *arm_fck_p;
-
-int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
+int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
/*
* According to the 12-5 CDP code from TI, "Limitation 2.5"
@@ -51,7 +51,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
return -EINVAL;
}
- return omap3_noncore_dpll_set_rate(clk, rate);
+ return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
}
void __init omap3_clk_lock_dpll5(void)
diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
index 8bbeeaf399e2..8cd4b0a882ae 100644
--- a/arch/arm/mach-omap2/clock3xxx.h
+++ b/arch/arm/mach-omap2/clock3xxx.h
@@ -9,8 +9,10 @@
#define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
int omap3xxx_clk_init(void);
-int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
-int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
+int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
+ unsigned long parent_rate);
+int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
+ unsigned long parent_rate);
void omap3_clk_lock_dpll5(void);
extern struct clk *sdrc_ick_p;
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
deleted file mode 100644
index 6cca19953950..000000000000
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ /dev/null
@@ -1,3613 +0,0 @@
-/*
- * OMAP3 clock data
- *
- * Copyright (C) 2007-2010, 2012 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- *
- * Written by Paul Walmsley
- * With many device clock fixes by Kevin Hilman and Jouni Högander
- * DPLL bypass clock support added by Roman Tereshonkov
- *
- */
-
-/*
- * Virtual clocks are introduced as convenient tools.
- * They are sources for other clocks and not supposed
- * to be requested from drivers directly.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock3xxx.h"
-#include "clock34xx.h"
-#include "clock36xx.h"
-#include "clock3517.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "control.h"
-
-/*
- * clocks
- */
-
-#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR
-
-/* Maximum DPLL multiplier, divider values for OMAP3 */
-#define OMAP3_MAX_DPLL_MULT 2047
-#define OMAP3630_MAX_JTYPE_DPLL_MULT 4095
-#define OMAP3_MAX_DPLL_DIV 128
-
-/*
- * DPLL1 supplies clock to the MPU.
- * DPLL2 supplies clock to the IVA2.
- * DPLL3 supplies CORE domain clocks.
- * DPLL4 supplies peripheral clocks.
- * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
- */
-
-/* Forward declarations for DPLL bypass clocks */
-static struct clk dpll1_fck;
-static struct clk dpll2_fck;
-
-/* PRM CLOCKS */
-
-/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
-static struct clk omap_32k_fck = {
- .name = "omap_32k_fck",
- .ops = &clkops_null,
- .rate = 32768,
-};
-
-static struct clk secure_32k_fck = {
- .name = "secure_32k_fck",
- .ops = &clkops_null,
- .rate = 32768,
-};
-
-/* Virtual source clocks for osc_sys_ck */
-static struct clk virt_12m_ck = {
- .name = "virt_12m_ck",
- .ops = &clkops_null,
- .rate = 12000000,
-};
-
-static struct clk virt_13m_ck = {
- .name = "virt_13m_ck",
- .ops = &clkops_null,
- .rate = 13000000,
-};
-
-static struct clk virt_16_8m_ck = {
- .name = "virt_16_8m_ck",
- .ops = &clkops_null,
- .rate = 16800000,
-};
-
-static struct clk virt_38_4m_ck = {
- .name = "virt_38_4m_ck",
- .ops = &clkops_null,
- .rate = 38400000,
-};
-
-static const struct clksel_rate osc_sys_12m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_13m_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_16_8m_rates[] = {
- { .div = 1, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_19_2m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_26m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_38_4m_rates[] = {
- { .div = 1, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel osc_sys_clksel[] = {
- { .parent = &virt_12m_ck, .rates = osc_sys_12m_rates },
- { .parent = &virt_13m_ck, .rates = osc_sys_13m_rates },
- { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates },
- { .parent = &virt_19200000_ck, .rates = osc_sys_19_2m_rates },
- { .parent = &virt_26000000_ck, .rates = osc_sys_26m_rates },
- { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates },
- { .parent = NULL },
-};
-
-/* Oscillator clock */
-/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */
-static struct clk osc_sys_ck = {
- .name = "osc_sys_ck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP3430_PRM_CLKSEL,
- .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK,
- .clksel = osc_sys_clksel,
- /* REVISIT: deal with autoextclkmode? */
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div2_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel sys_clksel[] = {
- { .parent = &osc_sys_ck, .rates = div2_rates },
- { .parent = NULL }
-};
-
-/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */
-/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */
-static struct clk sys_ck = {
- .name = "sys_ck",
- .ops = &clkops_null,
- .parent = &osc_sys_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL,
- .clksel_mask = OMAP_SYSCLKDIV_MASK,
- .clksel = sys_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk sys_altclk = {
- .name = "sys_altclk",
- .ops = &clkops_null,
-};
-
-/* Optional external clock input for some McBSPs */
-static struct clk mcbsp_clks = {
- .name = "mcbsp_clks",
- .ops = &clkops_null,
-};
-
-/* PRM EXTERNAL CLOCK OUTPUT */
-
-static struct clk sys_clkout1 = {
- .name = "sys_clkout1",
- .ops = &clkops_omap2_dflt,
- .parent = &osc_sys_ck,
- .enable_reg = OMAP3430_PRM_CLKOUT_CTRL,
- .enable_bit = OMAP3430_CLKOUT_EN_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* DPLLS */
-
-/* CM CLOCKS */
-
-static const struct clksel_rate div16_dpll_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 5, .val = 5, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 7, .val = 7, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 9, .val = 9, .flags = RATE_IN_3XXX },
- { .div = 10, .val = 10, .flags = RATE_IN_3XXX },
- { .div = 11, .val = 11, .flags = RATE_IN_3XXX },
- { .div = 12, .val = 12, .flags = RATE_IN_3XXX },
- { .div = 13, .val = 13, .flags = RATE_IN_3XXX },
- { .div = 14, .val = 14, .flags = RATE_IN_3XXX },
- { .div = 15, .val = 15, .flags = RATE_IN_3XXX },
- { .div = 16, .val = 16, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dpll4_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 5, .val = 5, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 7, .val = 7, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 9, .val = 9, .flags = RATE_IN_3XXX },
- { .div = 10, .val = 10, .flags = RATE_IN_3XXX },
- { .div = 11, .val = 11, .flags = RATE_IN_3XXX },
- { .div = 12, .val = 12, .flags = RATE_IN_3XXX },
- { .div = 13, .val = 13, .flags = RATE_IN_3XXX },
- { .div = 14, .val = 14, .flags = RATE_IN_3XXX },
- { .div = 15, .val = 15, .flags = RATE_IN_3XXX },
- { .div = 16, .val = 16, .flags = RATE_IN_3XXX },
- { .div = 17, .val = 17, .flags = RATE_IN_36XX },
- { .div = 18, .val = 18, .flags = RATE_IN_36XX },
- { .div = 19, .val = 19, .flags = RATE_IN_36XX },
- { .div = 20, .val = 20, .flags = RATE_IN_36XX },
- { .div = 21, .val = 21, .flags = RATE_IN_36XX },
- { .div = 22, .val = 22, .flags = RATE_IN_36XX },
- { .div = 23, .val = 23, .flags = RATE_IN_36XX },
- { .div = 24, .val = 24, .flags = RATE_IN_36XX },
- { .div = 25, .val = 25, .flags = RATE_IN_36XX },
- { .div = 26, .val = 26, .flags = RATE_IN_36XX },
- { .div = 27, .val = 27, .flags = RATE_IN_36XX },
- { .div = 28, .val = 28, .flags = RATE_IN_36XX },
- { .div = 29, .val = 29, .flags = RATE_IN_36XX },
- { .div = 30, .val = 30, .flags = RATE_IN_36XX },
- { .div = 31, .val = 31, .flags = RATE_IN_36XX },
- { .div = 32, .val = 32, .flags = RATE_IN_36XX },
- { .div = 0 }
-};
-
-/* DPLL1 */
-/* MPU clock source */
-/* Type: DPLL */
-static struct dpll_data dpll1_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK,
- .clk_bypass = &dpll1_fck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
- .enable_mask = OMAP3430_EN_MPU_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
- .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
- .idlest_mask = OMAP3430_ST_MPU_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll1_ck = {
- .name = "dpll1_ck",
- .ops = &clkops_omap3_noncore_dpll_ops,
- .parent = &sys_ck,
- .dpll_data = &dpll1_dd,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
- .clkdm_name = "dpll1_clkdm",
- .recalc = &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed.
- */
-static struct clk dpll1_x2_ck = {
- .name = "dpll1_x2_ck",
- .ops = &clkops_null,
- .parent = &dpll1_ck,
- .clkdm_name = "dpll1_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */
-static const struct clksel div16_dpll1_x2m2_clksel[] = {
- { .parent = &dpll1_x2_ck, .rates = div16_dpll_rates },
- { .parent = NULL }
-};
-
-/*
- * Does not exist in the TRM - needed to separate the M2 divider from
- * bypass selection in mpu_ck
- */
-static struct clk dpll1_x2m2_ck = {
- .name = "dpll1_x2m2_ck",
- .ops = &clkops_null,
- .parent = &dpll1_x2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
- .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
- .clksel = div16_dpll1_x2m2_clksel,
- .clkdm_name = "dpll1_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL2 */
-/* IVA2 clock source */
-/* Type: DPLL */
-
-static struct dpll_data dpll2_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK,
- .clk_bypass = &dpll2_fck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
- .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
- (1 << DPLL_LOW_POWER_BYPASS),
- .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
- .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
- .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll2_ck = {
- .name = "dpll2_ck",
- .ops = &clkops_omap3_noncore_dpll_ops,
- .parent = &sys_ck,
- .dpll_data = &dpll2_dd,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
- .clkdm_name = "dpll2_clkdm",
- .recalc = &omap3_dpll_recalc,
-};
-
-static const struct clksel div16_dpll2_m2x2_clksel[] = {
- { .parent = &dpll2_ck, .rates = div16_dpll_rates },
- { .parent = NULL }
-};
-
-/*
- * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT
- * or CLKOUTX2. CLKOUT seems most plausible.
- */
-static struct clk dpll2_m2_ck = {
- .name = "dpll2_m2_ck",
- .ops = &clkops_null,
- .parent = &dpll2_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
- OMAP3430_CM_CLKSEL2_PLL),
- .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
- .clksel = div16_dpll2_m2x2_clksel,
- .clkdm_name = "dpll2_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * DPLL3
- * Source clock for all interfaces and for some device fclks
- * REVISIT: Also supports fast relock bypass - not included below
- */
-static struct dpll_data dpll3_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_CORE_DPLL_MASK,
- .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_CORE_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll3_ck = {
- .name = "dpll3_ck",
- .ops = &clkops_omap3_core_dpll_ops,
- .parent = &sys_ck,
- .dpll_data = &dpll3_dd,
- .round_rate = &omap2_dpll_round_rate,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed
- */
-static struct clk dpll3_x2_ck = {
- .name = "dpll3_x2_ck",
- .ops = &clkops_null,
- .parent = &dpll3_ck,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel_rate div31_dpll3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 4, .val = 4, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 5, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 6, .val = 6, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 7, .val = 7, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 8, .val = 8, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 9, .val = 9, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 10, .val = 10, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 11, .val = 11, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 12, .val = 12, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 13, .val = 13, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 14, .val = 14, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 15, .val = 15, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 16, .val = 16, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 17, .val = 17, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 18, .val = 18, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 19, .val = 19, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 20, .val = 20, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 21, .val = 21, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 22, .val = 22, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 23, .val = 23, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 24, .val = 24, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 25, .val = 25, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 26, .val = 26, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 27, .val = 27, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 28, .val = 28, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 29, .val = 29, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 30, .val = 30, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 31, .val = 31, .flags = RATE_IN_3430ES2PLUS_36XX },
- { .div = 0 },
-};
-
-static const struct clksel div31_dpll3m2_clksel[] = {
- { .parent = &dpll3_ck, .rates = div31_dpll3_rates },
- { .parent = NULL }
-};
-
-/* DPLL3 output M2 - primary control point for CORE speed */
-static struct clk dpll3_m2_ck = {
- .name = "dpll3_m2_ck",
- .ops = &clkops_null,
- .parent = &dpll3_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
- .clksel = div31_dpll3m2_clksel,
- .clkdm_name = "dpll3_clkdm",
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap3_core_dpll_m2_set_rate,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
- .name = "core_ck",
- .ops = &clkops_null,
- .parent = &dpll3_m2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dpll3_m2x2_ck = {
- .name = "dpll3_m2x2_ck",
- .ops = &clkops_null,
- .parent = &dpll3_m2_ck,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static const struct clksel div16_dpll3_clksel[] = {
- { .parent = &dpll3_ck, .rates = div16_dpll_rates },
- { .parent = NULL }
-};
-
-/* This virtual clock is the source for dpll3_m3x2_ck */
-static struct clk dpll3_m3_ck = {
- .name = "dpll3_m3_ck",
- .ops = &clkops_null,
- .parent = &dpll3_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_DIV_DPLL3_MASK,
- .clksel = div16_dpll3_clksel,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll3_m3x2_ck = {
- .name = "dpll3_m3x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll3_m3_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static struct clk emu_core_alwon_ck = {
- .name = "emu_core_alwon_ck",
- .ops = &clkops_null,
- .parent = &dpll3_m3x2_ck,
- .clkdm_name = "dpll3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* DPLL4 */
-/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
-/* Type: DPLL */
-static struct dpll_data dpll4_dd;
-
-static struct dpll_data dpll4_dd_34xx __initdata = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
- .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct dpll_data dpll4_dd_3630 __initdata = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
- .mult_mask = OMAP3630_PERIPH_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
- .dco_mask = OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
- .sddiv_mask = OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
- .max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
- .flags = DPLL_J_TYPE
-};
-
-static struct clk dpll4_ck = {
- .name = "dpll4_ck",
- .ops = &clkops_omap3_noncore_dpll_ops,
- .parent = &sys_ck,
- .dpll_data = &dpll4_dd,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_dpll4_set_rate,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed --
- * XXX does this serve any downstream clocks?
- */
-static struct clk dpll4_x2_ck = {
- .name = "dpll4_x2_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll4_clksel[] = {
- { .parent = &dpll4_ck, .rates = dpll4_rates },
- { .parent = NULL }
-};
-
-/* This virtual clock is the source for dpll4_m2x2_ck */
-static struct clk dpll4_m2_ck = {
- .name = "dpll4_m2_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
- .clksel_mask = OMAP3630_DIV_96M_MASK,
- .clksel = dpll4_clksel,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m2x2_ck = {
- .name = "dpll4_m2x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll4_m2_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_96M_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-/*
- * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as
- * PRM_96M_ALWON_(F)CLK. Two clocks then emerge from the PRM:
- * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and
- * CM_96K_(F)CLK.
- */
-
-/* Adding 192MHz Clock node needed by SGX */
-static struct clk omap_192m_alwon_fck = {
- .name = "omap_192m_alwon_fck",
- .ops = &clkops_null,
- .parent = &dpll4_m2x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate omap_96m_alwon_fck_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_36XX },
- { .div = 2, .val = 2, .flags = RATE_IN_36XX },
- { .div = 0 }
-};
-
-static const struct clksel omap_96m_alwon_fck_clksel[] = {
- { .parent = &omap_192m_alwon_fck, .rates = omap_96m_alwon_fck_rates },
- { .parent = NULL }
-};
-
-static const struct clksel_rate omap_96m_dpll_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate omap_96m_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static struct clk omap_96m_alwon_fck = {
- .name = "omap_96m_alwon_fck",
- .ops = &clkops_null,
- .parent = &dpll4_m2x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk omap_96m_alwon_fck_3630 = {
- .name = "omap_96m_alwon_fck",
- .parent = &omap_192m_alwon_fck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3630_CLKSEL_96M_MASK,
- .clksel = omap_96m_alwon_fck_clksel
-};
-
-static struct clk cm_96m_fck = {
- .name = "cm_96m_fck",
- .ops = &clkops_null,
- .parent = &omap_96m_alwon_fck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel omap_96m_fck_clksel[] = {
- { .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates },
- { .parent = &sys_ck, .rates = omap_96m_sys_rates },
- { .parent = NULL }
-};
-
-static struct clk omap_96m_fck = {
- .name = "omap_96m_fck",
- .ops = &clkops_null,
- .parent = &sys_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_SOURCE_96M_MASK,
- .clksel = omap_96m_fck_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m3x2_ck */
-static struct clk dpll4_m3_ck = {
- .name = "dpll4_m3_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3630_CLKSEL_TV_MASK,
- .clksel = dpll4_clksel,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m3x2_ck = {
- .name = "dpll4_m3x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll4_m3_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_TV_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate omap_54m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel omap_54m_clksel[] = {
- { .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates },
- { .parent = &sys_altclk, .rates = omap_54m_alt_rates },
- { .parent = NULL }
-};
-
-static struct clk omap_54m_fck = {
- .name = "omap_54m_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_SOURCE_54M_MASK,
- .clksel = omap_54m_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate omap_48m_cm96m_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate omap_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel omap_48m_clksel[] = {
- { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
- { .parent = &sys_altclk, .rates = omap_48m_alt_rates },
- { .parent = NULL }
-};
-
-static struct clk omap_48m_fck = {
- .name = "omap_48m_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_SOURCE_48M_MASK,
- .clksel = omap_48m_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk omap_12m_fck = {
- .name = "omap_12m_fck",
- .ops = &clkops_null,
- .parent = &omap_48m_fck,
- .fixed_div = 4,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m4x2_ck */
-static struct clk dpll4_m4_ck = {
- .name = "dpll4_m4_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3630_CLKSEL_DSS1_MASK,
- .clksel = dpll4_clksel,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m4x2_ck = {
- .name = "dpll4_m4x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll4_m4_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_DSS1_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m5x2_ck */
-static struct clk dpll4_m5_ck = {
- .name = "dpll4_m5_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3630_CLKSEL_CAM_MASK,
- .clksel = dpll4_clksel,
- .clkdm_name = "dpll4_clkdm",
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m5x2_ck = {
- .name = "dpll4_m5x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll4_m5_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_CAM_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m6x2_ck */
-static struct clk dpll4_m6_ck = {
- .name = "dpll4_m6_ck",
- .ops = &clkops_null,
- .parent = &dpll4_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3630_DIV_DPLL4_MASK,
- .clksel = dpll4_clksel,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m6x2_ck = {
- .name = "dpll4_m6x2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll4_m6_ck,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static struct clk emu_per_alwon_ck = {
- .name = "emu_per_alwon_ck",
- .ops = &clkops_null,
- .parent = &dpll4_m6x2_ck,
- .clkdm_name = "dpll4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* DPLL5 */
-/* Supplies 120MHz clock, USIM source clock */
-/* Type: DPLL */
-/* 3430ES2 only */
-static struct dpll_data dpll5_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
- .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
- .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
- .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
- .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
- .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll5_ck = {
- .name = "dpll5_ck",
- .ops = &clkops_omap3_noncore_dpll_ops,
- .parent = &sys_ck,
- .dpll_data = &dpll5_dd,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
- .clkdm_name = "dpll5_clkdm",
- .recalc = &omap3_dpll_recalc,
-};
-
-static const struct clksel div16_dpll5_clksel[] = {
- { .parent = &dpll5_ck, .rates = div16_dpll_rates },
- { .parent = NULL }
-};
-
-static struct clk dpll5_m2_ck = {
- .name = "dpll5_m2_ck",
- .ops = &clkops_null,
- .parent = &dpll5_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
- .clksel_mask = OMAP3430ES2_DIV_120M_MASK,
- .clksel = div16_dpll5_clksel,
- .clkdm_name = "dpll5_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* CM EXTERNAL CLOCK OUTPUTS */
-
-static const struct clksel_rate clkout2_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel clkout2_src_clksel[] = {
- { .parent = &core_ck, .rates = clkout2_src_core_rates },
- { .parent = &sys_ck, .rates = clkout2_src_sys_rates },
- { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates },
- { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates },
- { .parent = NULL }
-};
-
-static struct clk clkout2_src_ck = {
- .name = "clkout2_src_ck",
- .ops = &clkops_omap2_dflt,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP3430_CM_CLKOUT_CTRL,
- .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT,
- .clksel_reg = OMAP3430_CM_CLKOUT_CTRL,
- .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK,
- .clksel = clkout2_src_clksel,
- .clkdm_name = "core_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate sys_clkout2_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 16, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel sys_clkout2_clksel[] = {
- { .parent = &clkout2_src_ck, .rates = sys_clkout2_rates },
- { .parent = NULL },
-};
-
-static struct clk sys_clkout2 = {
- .name = "sys_clkout2",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP3430_CM_CLKOUT_CTRL,
- .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK,
- .clksel = sys_clkout2_clksel,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate
-};
-
-/* CM OUTPUT CLOCKS */
-
-static struct clk corex2_fck = {
- .name = "corex2_fck",
- .ops = &clkops_null,
- .parent = &dpll3_m2x2_ck,
- .recalc = &followparent_recalc,
-};
-
-/* DPLL power domain clock controls */
-
-static const struct clksel_rate div4_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel div4_core_clksel[] = {
- { .parent = &core_ck, .rates = div4_rates },
- { .parent = NULL }
-};
-
-/*
- * REVISIT: Are these in DPLL power domain or CM power domain? docs
- * may be inconsistent here?
- */
-static struct clk dpll1_fck = {
- .name = "dpll1_fck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK,
- .clksel = div4_core_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mpu_ck = {
- .name = "mpu_ck",
- .ops = &clkops_null,
- .parent = &dpll1_x2m2_ck,
- .clkdm_name = "mpu_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
-static const struct clksel_rate arm_fck_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel arm_fck_clksel[] = {
- { .parent = &mpu_ck, .rates = arm_fck_rates },
- { .parent = NULL }
-};
-
-static struct clk arm_fck = {
- .name = "arm_fck",
- .ops = &clkops_null,
- .parent = &mpu_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
- .clksel_mask = OMAP3430_ST_MPU_CLK_MASK,
- .clksel = arm_fck_clksel,
- .clkdm_name = "mpu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* XXX What about neon_clkdm ? */
-
-/*
- * REVISIT: This clock is never specifically defined in the 3430 TRM,
- * although it is referenced - so this is a guess
- */
-static struct clk emu_mpu_alwon_ck = {
- .name = "emu_mpu_alwon_ck",
- .ops = &clkops_null,
- .parent = &mpu_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dpll2_fck = {
- .name = "dpll2_fck",
- .ops = &clkops_null,
- .parent = &core_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK,
- .clksel = div4_core_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk iva2_ck = {
- .name = "iva2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll2_m2_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
- .clkdm_name = "iva2_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* Common interface clocks */
-
-static const struct clksel div2_core_clksel[] = {
- { .parent = &core_ck, .rates = div2_rates },
- { .parent = NULL }
-};
-
-static struct clk l3_ick = {
- .name = "l3_ick",
- .ops = &clkops_null,
- .parent = &core_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_L3_MASK,
- .clksel = div2_core_clksel,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel div2_l3_clksel[] = {
- { .parent = &l3_ick, .rates = div2_rates },
- { .parent = NULL }
-};
-
-static struct clk l4_ick = {
- .name = "l4_ick",
- .ops = &clkops_null,
- .parent = &l3_ick,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_L4_MASK,
- .clksel = div2_l3_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-
-};
-
-static const struct clksel div2_l4_clksel[] = {
- { .parent = &l4_ick, .rates = div2_rates },
- { .parent = NULL }
-};
-
-static struct clk rm_ick = {
- .name = "rm_ick",
- .ops = &clkops_null,
- .parent = &l4_ick,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_RM_MASK,
- .clksel = div2_l4_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* GFX power domain */
-
-/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */
-
-static const struct clksel gfx_l3_clksel[] = {
- { .parent = &l3_ick, .rates = gfx_l3_rates },
- { .parent = NULL }
-};
-
-/*
- * Virtual parent clock for gfx_l3_ick and gfx_l3_fck
- * This interface clock does not have a CM_AUTOIDLE bit
- */
-static struct clk gfx_l3_ck = {
- .name = "gfx_l3_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &l3_ick,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gfx_l3_fck = {
- .name = "gfx_l3_fck",
- .ops = &clkops_null,
- .parent = &gfx_l3_ck,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP_CLKSEL_GFX_MASK,
- .clksel = gfx_l3_clksel,
- .clkdm_name = "gfx_3430es1_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gfx_l3_ick = {
- .name = "gfx_l3_ick",
- .ops = &clkops_null,
- .parent = &gfx_l3_ck,
- .clkdm_name = "gfx_3430es1_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gfx_cg1_ck = {
- .name = "gfx_cg1_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &gfx_l3_fck, /* REVISIT: correct? */
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES1_EN_2D_SHIFT,
- .clkdm_name = "gfx_3430es1_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gfx_cg2_ck = {
- .name = "gfx_cg2_ck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &gfx_l3_fck, /* REVISIT: correct? */
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES1_EN_3D_SHIFT,
- .clkdm_name = "gfx_3430es1_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* SGX power domain - 3430ES2 only */
-
-static const struct clksel_rate sgx_core_rates[] = {
- { .div = 2, .val = 5, .flags = RATE_IN_36XX },
- { .div = 3, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate sgx_192m_rates[] = {
- { .div = 1, .val = 4, .flags = RATE_IN_36XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate sgx_corex2_rates[] = {
- { .div = 3, .val = 6, .flags = RATE_IN_36XX },
- { .div = 5, .val = 7, .flags = RATE_IN_36XX },
- { .div = 0 },
-};
-
-static const struct clksel_rate sgx_96m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel sgx_clksel[] = {
- { .parent = &core_ck, .rates = sgx_core_rates },
- { .parent = &cm_96m_fck, .rates = sgx_96m_rates },
- { .parent = &omap_192m_alwon_fck, .rates = sgx_192m_rates },
- { .parent = &corex2_fck, .rates = sgx_corex2_rates },
- { .parent = NULL }
-};
-
-static struct clk sgx_fck = {
- .name = "sgx_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK,
- .clksel = sgx_clksel,
- .clkdm_name = "sgx_clkdm",
- .recalc = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk sgx_ick = {
- .name = "sgx_ick",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &l3_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
- .clkdm_name = "sgx_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* CORE power domain */
-
-static struct clk d2d_26m_fck = {
- .name = "d2d_26m_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &sys_ck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES1_EN_D2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk modem_fck = {
- .name = "modem_fck",
- .ops = &clkops_omap2_mdmclk_dflt_wait,
- .parent = &sys_ck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MODEM_SHIFT,
- .clkdm_name = "d2d_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk sad2d_ick = {
- .name = "sad2d_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SAD2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mad2d_ick = {
- .name = "mad2d_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP3430_EN_MAD2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel omap343x_gpt_clksel[] = {
- { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = NULL}
-};
-
-static struct clk gpt10_fck = {
- .name = "gpt10_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &sys_ck,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_GPT10_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_fck = {
- .name = "gpt11_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &sys_ck,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_GPT11_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk cpefuse_fck = {
- .name = "cpefuse_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &sys_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ts_fck = {
- .name = "ts_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &omap_32k_fck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_TS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usbtll_fck = {
- .name = "usbtll_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &dpll5_m2_ck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* CORE 96M FCLK-derived clocks */
-
-static struct clk core_96m_fck = {
- .name = "core_96m_fck",
- .ops = &clkops_null,
- .parent = &omap_96m_fck,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs3_fck = {
- .name = "mmchs3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs2_fck = {
- .name = "mmchs2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MMC2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
- .name = "mspro_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs1_fck = {
- .name = "mmchs1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MMC1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c3_fck = {
- .name = "i2c3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
- .name = "i2c2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c1_fck = {
- .name = "i2c1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/*
- * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck;
- * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck.
- */
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_15_clksel[] = {
- { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL }
-};
-
-static struct clk mcbsp5_fck = {
- .name = "mcbsp5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
- .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP5_CLKS_MASK,
- .clksel = mcbsp_15_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_fck = {
- .name = "mcbsp1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
- .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP1_CLKS_MASK,
- .clksel = mcbsp_15_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* CORE_48M_FCK-derived clocks */
-
-static struct clk core_48m_fck = {
- .name = "core_48m_fck",
- .ops = &clkops_null,
- .parent = &omap_48m_fck,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi4_fck = {
- .name = "mcspi4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
- .recalc = &followparent_recalc,
- .clkdm_name = "core_l4_clkdm",
-};
-
-static struct clk mcspi3_fck = {
- .name = "mcspi3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
- .recalc = &followparent_recalc,
- .clkdm_name = "core_l4_clkdm",
-};
-
-static struct clk mcspi2_fck = {
- .name = "mcspi2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
- .recalc = &followparent_recalc,
- .clkdm_name = "core_l4_clkdm",
-};
-
-static struct clk mcspi1_fck = {
- .name = "mcspi1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
- .recalc = &followparent_recalc,
- .clkdm_name = "core_l4_clkdm",
-};
-
-static struct clk uart2_fck = {
- .name = "uart2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
- .name = "uart1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk fshostusb_fck = {
- .name = "fshostusb_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* CORE_12M_FCK based clocks */
-
-static struct clk core_12m_fck = {
- .name = "core_12m_fck",
- .ops = &clkops_null,
- .parent = &omap_12m_fck,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
- .name = "hdq_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_12m_fck,
- .clkdm_name = "core_l4_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_HDQ_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* DPLL3-derived clock */
-
-static const struct clksel_rate ssi_ssr_corex2_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_clksel[] = {
- { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
- { .parent = NULL }
-};
-
-static struct clk ssi_ssr_fck_3430es1 = {
- .name = "ssi_ssr_fck",
- .ops = &clkops_omap2_dflt,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_SSI_MASK,
- .clksel = ssi_ssr_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk ssi_ssr_fck_3430es2 = {
- .name = "ssi_ssr_fck",
- .ops = &clkops_omap3430es2_ssi_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_SSI_MASK,
- .clksel = ssi_ssr_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk ssi_sst_fck_3430es1 = {
- .name = "ssi_sst_fck",
- .ops = &clkops_null,
- .parent = &ssi_ssr_fck_3430es1,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk ssi_sst_fck_3430es2 = {
- .name = "ssi_sst_fck",
- .ops = &clkops_null,
- .parent = &ssi_ssr_fck_3430es2,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-
-
-/* CORE_L3_ICK based clocks */
-
-/*
- * XXX must add clk_enable/clk_disable for these if standard code won't
- * handle it
- */
-static struct clk core_l3_ick = {
- .name = "core_l3_ick",
- .ops = &clkops_null,
- .parent = &l3_ick,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_3430es1 = {
- .name = "hsotgusb_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &core_l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_3430es2 = {
- .name = "hsotgusb_ick",
- .ops = &clkops_omap3430es2_iclk_hsotgusb_wait,
- .parent = &core_l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk sdrc_ick = {
- .name = "sdrc_ick",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SDRC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpmc_fck = {
- .name = "gpmc_fck",
- .ops = &clkops_null,
- .parent = &core_l3_ick,
- .flags = ENABLE_ON_INIT, /* huh? */
- .clkdm_name = "core_l3_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* SECURITY_L3_ICK based clocks */
-
-static struct clk security_l3_ick = {
- .name = "security_l3_ick",
- .ops = &clkops_null,
- .parent = &l3_ick,
- .recalc = &followparent_recalc,
-};
-
-static struct clk pka_ick = {
- .name = "pka_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &security_l3_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_PKA_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* CORE_L4_ICK based clocks */
-
-static struct clk core_l4_ick = {
- .name = "core_l4_ick",
- .ops = &clkops_null,
- .parent = &l4_ick,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk usbtll_ick = {
- .name = "usbtll_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs3_ick = {
- .name = "mmchs3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* Intersystem Communication Registers - chassis mode only */
-static struct clk icr_ick = {
- .name = "icr_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_ICR_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk aes2_ick = {
- .name = "aes2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_AES2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk sha12_ick = {
- .name = "sha12_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SHA12_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk des2_ick = {
- .name = "des2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_DES2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs2_ick = {
- .name = "mmchs2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MMC2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmchs1_ick = {
- .name = "mmchs1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MMC1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
- .name = "mspro_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
- .name = "hdq_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi4_ick = {
- .name = "mcspi4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi3_ick = {
- .name = "mcspi3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
- .name = "mcspi2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi1_ick = {
- .name = "mcspi1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c3_ick = {
- .name = "i2c3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c2_ick = {
- .name = "i2c2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c1_ick = {
- .name = "i2c1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
- .name = "uart2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
- .name = "uart1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt11_ick = {
- .name = "gpt11_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_GPT11_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt10_ick = {
- .name = "gpt10_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_GPT10_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp5_ick = {
- .name = "mcbsp5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp1_ick = {
- .name = "mcbsp1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk fac_ick = {
- .name = "fac_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430ES1_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
- .name = "mailboxes_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
- .name = "omapctrl_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* SSI_L4_ICK based clocks */
-
-static struct clk ssi_l4_ick = {
- .name = "ssi_l4_ick",
- .ops = &clkops_null,
- .parent = &l4_ick,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk ssi_ick_3430es1 = {
- .name = "ssi_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &ssi_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk ssi_ick_3430es2 = {
- .name = "ssi_ick",
- .ops = &clkops_omap3430es2_iclk_ssi_wait,
- .parent = &ssi_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* REVISIT: Technically the TRM claims that this is CORE_CLK based,
- * but l4_ick makes more sense to me */
-
-static const struct clksel usb_l4_clksel[] = {
- { .parent = &l4_ick, .rates = div2_rates },
- { .parent = NULL },
-};
-
-static struct clk usb_l4_ick = {
- .name = "usb_l4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &l4_ick,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
- .clksel = usb_l4_clksel,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* SECURITY_L4_ICK2 based clocks */
-
-static struct clk security_l4_ick2 = {
- .name = "security_l4_ick2",
- .ops = &clkops_null,
- .parent = &l4_ick,
- .recalc = &followparent_recalc,
-};
-
-static struct clk aes1_ick = {
- .name = "aes1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &security_l4_ick2,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_AES1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk rng_ick = {
- .name = "rng_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &security_l4_ick2,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_RNG_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sha11_ick = {
- .name = "sha11_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &security_l4_ick2,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_SHA11_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk des1_ick = {
- .name = "des1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &security_l4_ick2,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_DES1_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/* DSS */
-static struct clk dss1_alwon_fck_3430es1 = {
- .name = "dss1_alwon_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &dpll4_m4x2_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss1_alwon_fck_3430es2 = {
- .name = "dss1_alwon_fck",
- .ops = &clkops_omap3430es2_dss_usbhost_wait,
- .parent = &dpll4_m4x2_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_tv_fck = {
- .name = "dss_tv_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &omap_54m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_96m_fck = {
- .name = "dss_96m_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &omap_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss2_alwon_fck = {
- .name = "dss2_alwon_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &sys_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS2_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_ick_3430es1 = {
- /* Handles both L3 and L4 clocks */
- .name = "dss_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_ick_3430es2 = {
- /* Handles both L3 and L4 clocks */
- .name = "dss_ick",
- .ops = &clkops_omap3430es2_iclk_dss_usbhost_wait,
- .parent = &l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
- .clkdm_name = "dss_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* CAM */
-
-static struct clk cam_mclk = {
- .name = "cam_mclk",
- .ops = &clkops_omap2_dflt,
- .parent = &dpll4_m5x2_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_CAM_SHIFT,
- .clkdm_name = "cam_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk cam_ick = {
- /* Handles both L3 and L4 clocks */
- .name = "cam_ick",
- .ops = &clkops_omap2_iclk_dflt,
- .parent = &l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_CAM_SHIFT,
- .clkdm_name = "cam_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk csi2_96m_fck = {
- .name = "csi2_96m_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &core_96m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_CSI2_SHIFT,
- .clkdm_name = "cam_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* USBHOST - 3430ES2 only */
-
-static struct clk usbhost_120m_fck = {
- .name = "usbhost_120m_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &dpll5_m2_ck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT,
- .clkdm_name = "usbhost_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk usbhost_48m_fck = {
- .name = "usbhost_48m_fck",
- .ops = &clkops_omap3430es2_dss_usbhost_wait,
- .parent = &omap_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT,
- .clkdm_name = "usbhost_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk usbhost_ick = {
- /* Handles both L3 and L4 clocks */
- .name = "usbhost_ick",
- .ops = &clkops_omap3430es2_iclk_dss_usbhost_wait,
- .parent = &l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT,
- .clkdm_name = "usbhost_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* WKUP */
-
-static const struct clksel_rate usim_96m_rates[] = {
- { .div = 2, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 5, .flags = RATE_IN_3XXX },
- { .div = 10, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate usim_120m_rates[] = {
- { .div = 4, .val = 7, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 16, .val = 9, .flags = RATE_IN_3XXX },
- { .div = 20, .val = 10, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel usim_clksel[] = {
- { .parent = &omap_96m_fck, .rates = usim_96m_rates },
- { .parent = &dpll5_m2_ck, .rates = usim_120m_rates },
- { .parent = &sys_ck, .rates = div2_rates },
- { .parent = NULL },
-};
-
-/* 3430ES2 only */
-static struct clk usim_fck = {
- .name = "usim_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430ES2_CLKSEL_USIMOCP_MASK,
- .clksel = usim_clksel,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */
-static struct clk gpt1_fck = {
- .name = "gpt1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT1_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "wkup_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk wkup_32k_fck = {
- .name = "wkup_32k_fck",
- .ops = &clkops_null,
- .parent = &omap_32k_fck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio1_dbck = {
- .name = "gpio1_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &wkup_32k_fck,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt2_fck = {
- .name = "wdt2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &wkup_32k_fck,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_WDT2_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wkup_l4_ick = {
- .name = "wkup_l4_ick",
- .ops = &clkops_null,
- .parent = &sys_ck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* 3430ES2 only */
-/* Never specifically named in the TRM, so we have to infer a likely name */
-static struct clk usim_ick = {
- .name = "usim_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt2_ick = {
- .name = "wdt2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT2_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
- .name = "wdt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio1_ick = {
- .name = "gpio1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk omap_32ksync_ick = {
- .name = "omap_32ksync_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_32KSYNC_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* XXX This clock no longer exists in 3430 TRM rev F */
-static struct clk gpt12_ick = {
- .name = "gpt12_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT12_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt1_ick = {
- .name = "gpt1_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &wkup_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-
-
-/* PER clock domain */
-
-static struct clk per_96m_fck = {
- .name = "per_96m_fck",
- .ops = &clkops_null,
- .parent = &omap_96m_alwon_fck,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk per_48m_fck = {
- .name = "per_48m_fck",
- .ops = &clkops_null,
- .parent = &omap_48m_fck,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
- .name = "uart3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &per_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_UART3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart4_fck = {
- .name = "uart4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &per_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3630_EN_UART4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart4_fck_am35xx = {
- .name = "uart4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &core_48m_fck,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = AM35XX_EN_UART4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
- .name = "gpt2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT2_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_fck = {
- .name = "gpt3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT3_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_fck = {
- .name = "gpt4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT4_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_fck = {
- .name = "gpt5_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT5_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_fck = {
- .name = "gpt6_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT6_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_fck = {
- .name = "gpt7_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT7_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_fck = {
- .name = "gpt8_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT8_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_fck = {
- .name = "gpt9_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPT9_SHIFT,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK,
- .clksel = omap343x_gpt_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk per_32k_alwon_fck = {
- .name = "per_32k_alwon_fck",
- .ops = &clkops_null,
- .parent = &omap_32k_fck,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio6_dbck = {
- .name = "gpio6_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_dbck = {
- .name = "gpio5_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio4_dbck = {
- .name = "gpio4_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio3_dbck = {
- .name = "gpio3_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio2_dbck = {
- .name = "gpio2_dbck",
- .ops = &clkops_omap2_dflt,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt3_fck = {
- .name = "wdt3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &per_32k_alwon_fck,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_WDT3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk per_l4_ick = {
- .name = "per_l4_ick",
- .ops = &clkops_null,
- .parent = &l4_ick,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio6_ick = {
- .name = "gpio6_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
- .name = "gpio5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio4_ick = {
- .name = "gpio4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio3_ick = {
- .name = "gpio3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio2_ick = {
- .name = "gpio2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt3_ick = {
- .name = "wdt3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
- .name = "uart3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_UART3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart4_ick = {
- .name = "uart4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3630_EN_UART4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt9_ick = {
- .name = "gpt9_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT9_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt8_ick = {
- .name = "gpt8_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT8_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt7_ick = {
- .name = "gpt7_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT7_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt6_ick = {
- .name = "gpt6_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT6_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt5_ick = {
- .name = "gpt5_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT5_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt4_ick = {
- .name = "gpt4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt3_ick = {
- .name = "gpt3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpt2_ick = {
- .name = "gpt2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT2_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp2_ick = {
- .name = "mcbsp2_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp3_ick = {
- .name = "mcbsp3_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcbsp4_ick = {
- .name = "mcbsp4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &per_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
- .clkdm_name = "per_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel mcbsp_234_clksel[] = {
- { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL }
-};
-
-static struct clk mcbsp2_fck = {
- .name = "mcbsp2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
- .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- .clksel_mask = OMAP2_MCBSP2_CLKS_MASK,
- .clksel = mcbsp_234_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp3_fck = {
- .name = "mcbsp3_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
- .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP3_CLKS_MASK,
- .clksel = mcbsp_234_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp4_fck = {
- .name = "mcbsp4_fck",
- .ops = &clkops_omap2_dflt_wait,
- .init = &omap2_init_clksel_parent,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
- .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- .clksel_mask = OMAP2_MCBSP4_CLKS_MASK,
- .clksel = mcbsp_234_clksel,
- .clkdm_name = "per_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* EMU clocks */
-
-/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */
-
-static const struct clksel_rate emu_src_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_per_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_mpu_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel emu_src_clksel[] = {
- { .parent = &sys_ck, .rates = emu_src_sys_rates },
- { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
- { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates },
- { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates },
- { .parent = NULL },
-};
-
-/*
- * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only
- * to switch the source of some of the EMU clocks.
- * XXX Are there CLKEN bits for these EMU clks?
- */
-static struct clk emu_src_ck = {
- .name = "emu_src_ck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_MUX_CTRL_MASK,
- .clksel = emu_src_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate pclk_emu_rates[] = {
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel pclk_emu_clksel[] = {
- { .parent = &emu_src_ck, .rates = pclk_emu_rates },
- { .parent = NULL },
-};
-
-static struct clk pclk_fck = {
- .name = "pclk_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK,
- .clksel = pclk_emu_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate pclkx2_emu_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel pclkx2_emu_clksel[] = {
- { .parent = &emu_src_ck, .rates = pclkx2_emu_rates },
- { .parent = NULL },
-};
-
-static struct clk pclkx2_fck = {
- .name = "pclkx2_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK,
- .clksel = pclkx2_emu_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel atclk_emu_clksel[] = {
- { .parent = &emu_src_ck, .rates = div2_rates },
- { .parent = NULL },
-};
-
-static struct clk atclk_fck = {
- .name = "atclk_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK,
- .clksel = atclk_emu_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk traceclk_src_fck = {
- .name = "traceclk_src_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK,
- .clksel = emu_src_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate traceclk_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel traceclk_clksel[] = {
- { .parent = &traceclk_src_fck, .rates = traceclk_rates },
- { .parent = NULL },
-};
-
-static struct clk traceclk_fck = {
- .name = "traceclk_fck",
- .ops = &clkops_null,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK,
- .clksel = traceclk_clksel,
- .clkdm_name = "emu_clkdm",
- .recalc = &omap2_clksel_recalc,
-};
-
-/* SR clocks */
-
-/* SmartReflex fclk (VDD1) */
-static struct clk sr1_fck = {
- .name = "sr1_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &sys_ck,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_SR1_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* SmartReflex fclk (VDD2) */
-static struct clk sr2_fck = {
- .name = "sr2_fck",
- .ops = &clkops_omap2_dflt_wait,
- .parent = &sys_ck,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_SR2_SHIFT,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk sr_l4_ick = {
- .name = "sr_l4_ick",
- .ops = &clkops_null, /* RMK: missing? */
- .parent = &l4_ick,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* SECURE_32K_FCK clocks */
-
-static struct clk gpt12_fck = {
- .name = "gpt12_fck",
- .ops = &clkops_null,
- .parent = &secure_32k_fck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk wdt1_fck = {
- .name = "wdt1_fck",
- .ops = &clkops_null,
- .parent = &secure_32k_fck,
- .clkdm_name = "wkup_clkdm",
- .recalc = &followparent_recalc,
-};
-
-/* Clocks for AM35XX */
-static struct clk ipss_ick = {
- .name = "ipss_ick",
- .ops = &clkops_am35xx_ipss_wait,
- .parent = &core_l3_ick,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = AM35XX_EN_IPSS_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk emac_ick = {
- .name = "emac_ick",
- .ops = &clkops_am35xx_ipss_module_wait,
- .parent = &ipss_ick,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk rmii_ck = {
- .name = "rmii_ck",
- .ops = &clkops_null,
- .rate = 50000000,
-};
-
-static struct clk emac_fck = {
- .name = "emac_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &rmii_ck,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_CPGMAC_FCLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_am35xx = {
- .name = "hsotgusb_ick",
- .ops = &clkops_am35xx_ipss_module_wait,
- .parent = &ipss_ick,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_USBOTG_VBUSP_CLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hsotgusb_fck_am35xx = {
- .name = "hsotgusb_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &sys_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_USBOTG_FCLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk hecc_ck = {
- .name = "hecc_ck",
- .ops = &clkops_am35xx_ipss_module_wait,
- .parent = &sys_ck,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_HECC_VBUSP_CLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk vpfe_ick = {
- .name = "vpfe_ick",
- .ops = &clkops_am35xx_ipss_module_wait,
- .parent = &ipss_ick,
- .clkdm_name = "core_l3_clkdm",
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_VPFE_VBUSP_CLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-static struct clk pclk_ck = {
- .name = "pclk_ck",
- .ops = &clkops_null,
- .rate = 27000000,
-};
-
-static struct clk vpfe_fck = {
- .name = "vpfe_fck",
- .ops = &clkops_omap2_dflt,
- .parent = &pclk_ck,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_VPFE_FCLK_SHIFT,
- .recalc = &followparent_recalc,
-};
-
-/*
- * The UART1/2 functional clock acts as the functional clock for
- * UART4. No separate fclk control available. XXX Well now we have a
- * uart4_fck that is apparently used as the UART4 functional clock,
- * but it also seems that uart1_fck or uart2_fck are still needed, at
- * least for UART4 softresets to complete. This really needs
- * clarification.
- */
-static struct clk uart4_ick_am35xx = {
- .name = "uart4_ick",
- .ops = &clkops_omap2_iclk_dflt_wait,
- .parent = &core_l4_ick,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = AM35XX_EN_UART4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
- .recalc = &followparent_recalc,
-};
-
-static struct clk dummy_apb_pclk = {
- .name = "apb_pclk",
- .ops = &clkops_null,
-};
-
-/*
- * clkdev
- */
-
-static struct omap_clk omap3xxx_clks[] = {
- CLK(NULL, "apb_pclk", &dummy_apb_pclk, CK_3XXX),
- CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_3XXX),
- CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_3XXX),
- CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_3XXX),
- CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_3XXX),
- CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_3XXX),
- CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
- CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_3XXX),
- CLK("twl", "fck", &osc_sys_ck, CK_3XXX),
- CLK(NULL, "sys_ck", &sys_ck, CK_3XXX),
- CLK(NULL, "sys_altclk", &sys_altclk, CK_3XXX),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX),
- CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX),
- CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX),
- CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_3XXX),
- CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
- CLK(NULL, "dpll2_ck", &dpll2_ck, CK_34XX | CK_36XX),
- CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_34XX | CK_36XX),
- CLK(NULL, "dpll3_ck", &dpll3_ck, CK_3XXX),
- CLK(NULL, "core_ck", &core_ck, CK_3XXX),
- CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_3XXX),
- CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_3XXX),
- CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
- CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_3XXX),
- CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
- CLK(NULL, "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
- CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
- CLK(NULL, "dpll4_ck", &dpll4_ck, CK_3XXX),
- CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_3XXX),
- CLK(NULL, "omap_192m_alwon_fck", &omap_192m_alwon_fck, CK_36XX),
- CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
- CLK(NULL, "omap_96m_alwon_fck_3630", &omap_96m_alwon_fck_3630, CK_36XX),
- CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_3XXX),
- CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_3XXX),
- CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_3XXX),
- CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_3XXX),
- CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_3XXX),
- CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_3XXX),
- CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_3XXX),
- CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_3XXX),
- CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_3XXX),
- CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_3XXX),
- CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_3XXX),
- CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_3XXX),
- CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
- CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_3XXX),
- CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
- CLK(NULL, "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
- CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
- CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
- CLK(NULL, "sys_clkout2", &sys_clkout2, CK_3XXX),
- CLK(NULL, "corex2_fck", &corex2_fck, CK_3XXX),
- CLK(NULL, "dpll1_fck", &dpll1_fck, CK_3XXX),
- CLK(NULL, "mpu_ck", &mpu_ck, CK_3XXX),
- CLK(NULL, "arm_fck", &arm_fck, CK_3XXX),
- CLK(NULL, "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
- CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
- CLK(NULL, "dpll2_fck", &dpll2_fck, CK_34XX | CK_36XX),
- CLK(NULL, "iva2_ck", &iva2_ck, CK_34XX | CK_36XX),
- CLK(NULL, "l3_ick", &l3_ick, CK_3XXX),
- CLK(NULL, "l4_ick", &l4_ick, CK_3XXX),
- CLK(NULL, "rm_ick", &rm_ick, CK_3XXX),
- CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1),
- CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1),
- CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1),
- CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1),
- CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1),
- CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
- CLK(NULL, "modem_fck", &modem_fck, CK_34XX | CK_36XX),
- CLK(NULL, "sad2d_ick", &sad2d_ick, CK_34XX | CK_36XX),
- CLK(NULL, "mad2d_ick", &mad2d_ick, CK_34XX | CK_36XX),
- CLK(NULL, "gpt10_fck", &gpt10_fck, CK_3XXX),
- CLK(NULL, "gpt11_fck", &gpt11_fck, CK_3XXX),
- CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs_tll", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
- CLK(NULL, "mmchs3_fck", &mmchs3_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "mmchs2_fck", &mmchs2_fck, CK_3XXX),
- CLK(NULL, "mspro_fck", &mspro_fck, CK_34XX | CK_36XX),
- CLK(NULL, "mmchs1_fck", &mmchs1_fck, CK_3XXX),
- CLK(NULL, "i2c3_fck", &i2c3_fck, CK_3XXX),
- CLK(NULL, "i2c2_fck", &i2c2_fck, CK_3XXX),
- CLK(NULL, "i2c1_fck", &i2c1_fck, CK_3XXX),
- CLK(NULL, "mcbsp5_fck", &mcbsp5_fck, CK_3XXX),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_3XXX),
- CLK(NULL, "core_48m_fck", &core_48m_fck, CK_3XXX),
- CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_3XXX),
- CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_3XXX),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_3XXX),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_3XXX),
- CLK(NULL, "uart2_fck", &uart2_fck, CK_3XXX),
- CLK(NULL, "uart1_fck", &uart1_fck, CK_3XXX),
- CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
- CLK(NULL, "core_12m_fck", &core_12m_fck, CK_3XXX),
- CLK("omap_hdq.0", "fck", &hdq_fck, CK_3XXX),
- CLK(NULL, "hdq_fck", &hdq_fck, CK_3XXX),
- CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1),
- CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1),
- CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "core_l3_ick", &core_l3_ick, CK_3XXX),
- CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es1, CK_3430ES1),
- CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es1, CK_3430ES1),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "sdrc_ick", &sdrc_ick, CK_3XXX),
- CLK(NULL, "gpmc_fck", &gpmc_fck, CK_3XXX),
- CLK(NULL, "security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
- CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX),
- CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
- CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs_tll", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "mmchs3_ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
- CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
- CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_36XX),
- CLK(NULL, "des2_ick", &des2_ick, CK_34XX | CK_36XX),
- CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_3XXX),
- CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_3XXX),
- CLK(NULL, "mmchs2_ick", &mmchs2_ick, CK_3XXX),
- CLK(NULL, "mmchs1_ick", &mmchs1_ick, CK_3XXX),
- CLK(NULL, "mspro_ick", &mspro_ick, CK_34XX | CK_36XX),
- CLK("omap_hdq.0", "ick", &hdq_ick, CK_3XXX),
- CLK(NULL, "hdq_ick", &hdq_ick, CK_3XXX),
- CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_3XXX),
- CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_3XXX),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_3XXX),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_3XXX),
- CLK(NULL, "mcspi4_ick", &mcspi4_ick, CK_3XXX),
- CLK(NULL, "mcspi3_ick", &mcspi3_ick, CK_3XXX),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick, CK_3XXX),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick, CK_3XXX),
- CLK("omap_i2c.3", "ick", &i2c3_ick, CK_3XXX),
- CLK("omap_i2c.2", "ick", &i2c2_ick, CK_3XXX),
- CLK("omap_i2c.1", "ick", &i2c1_ick, CK_3XXX),
- CLK(NULL, "i2c3_ick", &i2c3_ick, CK_3XXX),
- CLK(NULL, "i2c2_ick", &i2c2_ick, CK_3XXX),
- CLK(NULL, "i2c1_ick", &i2c1_ick, CK_3XXX),
- CLK(NULL, "uart2_ick", &uart2_ick, CK_3XXX),
- CLK(NULL, "uart1_ick", &uart1_ick, CK_3XXX),
- CLK(NULL, "gpt11_ick", &gpt11_ick, CK_3XXX),
- CLK(NULL, "gpt10_ick", &gpt10_ick, CK_3XXX),
- CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_3XXX),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_3XXX),
- CLK(NULL, "mcbsp5_ick", &mcbsp5_ick, CK_3XXX),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick, CK_3XXX),
- CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_3XXX),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_34XX | CK_36XX),
- CLK(NULL, "ssi_ick", &ssi_ick_3430es1, CK_3430ES1),
- CLK(NULL, "ssi_ick", &ssi_ick_3430es2, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1),
- CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_34XX | CK_36XX),
- CLK(NULL, "aes1_ick", &aes1_ick, CK_34XX | CK_36XX),
- CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX),
- CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX),
- CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX),
- CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
- CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "dss_tv_fck", &dss_tv_fck, CK_3XXX),
- CLK(NULL, "dss_96m_fck", &dss_96m_fck, CK_3XXX),
- CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck, CK_3XXX),
- CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1),
- CLK(NULL, "dss_ick", &dss_ick_3430es1, CK_3430ES1),
- CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "dss_ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX),
- CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
- CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
- CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
- CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
- CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
- CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
- CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
- CLK(NULL, "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs_tll", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
- CLK("usbhs_tll", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
- CLK(NULL, "init_60m_fclk", &dummy_ck, CK_3XXX),
- CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
- CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
- CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
- CLK(NULL, "wdt2_fck", &wdt2_fck, CK_3XXX),
- CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_34XX | CK_36XX),
- CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2PLUS | CK_36XX),
- CLK("omap_wdt", "ick", &wdt2_ick, CK_3XXX),
- CLK(NULL, "wdt2_ick", &wdt2_ick, CK_3XXX),
- CLK(NULL, "wdt1_ick", &wdt1_ick, CK_3XXX),
- CLK(NULL, "gpio1_ick", &gpio1_ick, CK_3XXX),
- CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
- CLK(NULL, "gpt12_ick", &gpt12_ick, CK_3XXX),
- CLK(NULL, "gpt1_ick", &gpt1_ick, CK_3XXX),
- CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX),
- CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX),
- CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX),
- CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX),
- CLK(NULL, "uart4_fck", &uart4_fck_am35xx, CK_AM35XX),
- CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX),
- CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX),
- CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX),
- CLK(NULL, "gpt5_fck", &gpt5_fck, CK_3XXX),
- CLK(NULL, "gpt6_fck", &gpt6_fck, CK_3XXX),
- CLK(NULL, "gpt7_fck", &gpt7_fck, CK_3XXX),
- CLK(NULL, "gpt8_fck", &gpt8_fck, CK_3XXX),
- CLK(NULL, "gpt9_fck", &gpt9_fck, CK_3XXX),
- CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
- CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_3XXX),
- CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_3XXX),
- CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_3XXX),
- CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_3XXX),
- CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_3XXX),
- CLK(NULL, "wdt3_fck", &wdt3_fck, CK_3XXX),
- CLK(NULL, "per_l4_ick", &per_l4_ick, CK_3XXX),
- CLK(NULL, "gpio6_ick", &gpio6_ick, CK_3XXX),
- CLK(NULL, "gpio5_ick", &gpio5_ick, CK_3XXX),
- CLK(NULL, "gpio4_ick", &gpio4_ick, CK_3XXX),
- CLK(NULL, "gpio3_ick", &gpio3_ick, CK_3XXX),
- CLK(NULL, "gpio2_ick", &gpio2_ick, CK_3XXX),
- CLK(NULL, "wdt3_ick", &wdt3_ick, CK_3XXX),
- CLK(NULL, "uart3_ick", &uart3_ick, CK_3XXX),
- CLK(NULL, "uart4_ick", &uart4_ick, CK_36XX),
- CLK(NULL, "gpt9_ick", &gpt9_ick, CK_3XXX),
- CLK(NULL, "gpt8_ick", &gpt8_ick, CK_3XXX),
- CLK(NULL, "gpt7_ick", &gpt7_ick, CK_3XXX),
- CLK(NULL, "gpt6_ick", &gpt6_ick, CK_3XXX),
- CLK(NULL, "gpt5_ick", &gpt5_ick, CK_3XXX),
- CLK(NULL, "gpt4_ick", &gpt4_ick, CK_3XXX),
- CLK(NULL, "gpt3_ick", &gpt3_ick, CK_3XXX),
- CLK(NULL, "gpt2_ick", &gpt2_ick, CK_3XXX),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_3XXX),
- CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_3XXX),
- CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_3XXX),
- CLK(NULL, "mcbsp4_ick", &mcbsp2_ick, CK_3XXX),
- CLK(NULL, "mcbsp3_ick", &mcbsp3_ick, CK_3XXX),
- CLK(NULL, "mcbsp2_ick", &mcbsp4_ick, CK_3XXX),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_3XXX),
- CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_3XXX),
- CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_3XXX),
- CLK(NULL, "emu_src_ck", &emu_src_ck, CK_3XXX),
- CLK("etb", "emu_src_ck", &emu_src_ck, CK_3XXX),
- CLK(NULL, "pclk_fck", &pclk_fck, CK_3XXX),
- CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_3XXX),
- CLK(NULL, "atclk_fck", &atclk_fck, CK_3XXX),
- CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
- CLK(NULL, "traceclk_fck", &traceclk_fck, CK_3XXX),
- CLK(NULL, "sr1_fck", &sr1_fck, CK_34XX | CK_36XX),
- CLK(NULL, "sr2_fck", &sr2_fck, CK_34XX | CK_36XX),
- CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_34XX | CK_36XX),
- CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_3XXX),
- CLK(NULL, "gpt12_fck", &gpt12_fck, CK_3XXX),
- CLK(NULL, "wdt1_fck", &wdt1_fck, CK_3XXX),
- CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX),
- CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX),
- CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX),
- CLK(NULL, "emac_ick", &emac_ick, CK_AM35XX),
- CLK(NULL, "emac_fck", &emac_fck, CK_AM35XX),
- CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX),
- CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX),
- CLK(NULL, "vpfe_ick", &emac_ick, CK_AM35XX),
- CLK(NULL, "vpfe_fck", &emac_fck, CK_AM35XX),
- CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX),
- CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx, CK_AM35XX),
- CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx, CK_AM35XX),
- CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
- CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
- CLK(NULL, "timer_32k_ck", &omap_32k_fck, CK_3XXX),
- CLK(NULL, "timer_sys_ck", &sys_ck, CK_3XXX),
- CLK(NULL, "cpufreq_ck", &dpll1_ck, CK_3XXX),
-};
-
-
-int __init omap3xxx_clk_init(void)
-{
- struct omap_clk *c;
- u32 cpu_clkflg = 0;
-
- if (soc_is_am35xx()) {
- cpu_mask = RATE_IN_34XX;
- cpu_clkflg = CK_AM35XX;
- } else if (cpu_is_omap3630()) {
- cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
- cpu_clkflg = CK_36XX;
- } else if (cpu_is_ti816x()) {
- cpu_mask = RATE_IN_TI816X;
- cpu_clkflg = CK_TI816X;
- } else if (soc_is_am33xx()) {
- cpu_mask = RATE_IN_AM33XX;
- } else if (cpu_is_ti814x()) {
- cpu_mask = RATE_IN_TI814X;
- } else if (cpu_is_omap34xx()) {
- if (omap_rev() == OMAP3430_REV_ES1_0) {
- cpu_mask = RATE_IN_3430ES1;
- cpu_clkflg = CK_3430ES1;
- } else {
- /*
- * Assume that anything that we haven't matched yet
- * has 3430ES2-type clocks.
- */
- cpu_mask = RATE_IN_3430ES2PLUS;
- cpu_clkflg = CK_3430ES2PLUS;
- }
- } else {
- WARN(1, "clock: could not identify OMAP3 variant\n");
- }
-
- if (omap3_has_192mhz_clk())
- omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
-
- if (cpu_is_omap3630()) {
- /*
- * XXX This type of dynamic rewriting of the clock tree is
- * deprecated and should be revised soon.
- *
- * For 3630: override clkops_omap2_dflt_wait for the
- * clocks affected from PWRDN reset Limitation
- */
- dpll3_m3x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- dpll4_m2x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- dpll4_m3x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- dpll4_m4x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- dpll4_m5x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- dpll4_m6x2_ck.ops =
- &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
- }
-
- /*
- * XXX This type of dynamic rewriting of the clock tree is
- * deprecated and should be revised soon.
- */
- if (cpu_is_omap3630())
- dpll4_dd = dpll4_dd_3630;
- else
- dpll4_dd = dpll4_dd_34xx;
-
- for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
- c++)
- clk_preinit(c->lk.clk);
-
- for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
- c++)
- if (c->cpu & cpu_clkflg) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- omap2_init_clk_clkdm(c->lk.clk);
- }
-
- /* Disable autoidle on all clocks; let the PM code enable it later */
- omap_clk_disable_autoidle_all();
-
- recalculate_root_clocks();
-
- pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
- (core_ck.rate / 1000000), (arm_fck.rate / 1000000));
-
- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable_init_clocks();
-
- /*
- * Lock DPLL5 -- here only until other device init code can
- * handle this
- */
- if (!cpu_is_ti81xx() && (omap_rev() >= OMAP3430_REV_ES2_0))
- omap3_clk_lock_dpll5();
-
- /* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
- sdrc_ick_p = clk_get(NULL, "sdrc_ick");
- arm_fck_p = clk_get(NULL, "arm_fck");
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
deleted file mode 100644
index 2a450c9b9a7b..000000000000
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ /dev/null
@@ -1,3398 +0,0 @@
-/*
- * OMAP4 Clock data
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Paul Walmsley (paul@pwsan.com)
- * Rajendra Nayak (rnayak@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * 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.
- *
- * XXX Some of the ES1 clocks have been removed/changed; once support
- * is added for discriminating clocks by ES level, these should be added back
- * in.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock44xx.h"
-#include "cm1_44xx.h"
-#include "cm2_44xx.h"
-#include "cm-regbits-44xx.h"
-#include "prm44xx.h"
-#include "prm-regbits-44xx.h"
-#include "control.h"
-#include "scrm44xx.h"
-
-/* OMAP4 modulemode control */
-#define OMAP4430_MODULEMODE_HWCTRL 0
-#define OMAP4430_MODULEMODE_SWCTRL 1
-
-/* Root clocks */
-
-static struct clk extalt_clkin_ck = {
- .name = "extalt_clkin_ck",
- .rate = 59000000,
- .ops = &clkops_null,
-};
-
-static struct clk pad_clks_ck = {
- .name = "pad_clks_ck",
- .rate = 12000000,
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CLKSEL_ABE,
- .enable_bit = OMAP4430_PAD_CLKS_GATE_SHIFT,
-};
-
-static struct clk pad_slimbus_core_clks_ck = {
- .name = "pad_slimbus_core_clks_ck",
- .rate = 12000000,
- .ops = &clkops_null,
-};
-
-static struct clk secure_32k_clk_src_ck = {
- .name = "secure_32k_clk_src_ck",
- .rate = 32768,
- .ops = &clkops_null,
-};
-
-static struct clk slimbus_clk = {
- .name = "slimbus_clk",
- .rate = 12000000,
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CLKSEL_ABE,
- .enable_bit = OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
-};
-
-static struct clk sys_32k_ck = {
- .name = "sys_32k_ck",
- .clkdm_name = "prm_clkdm",
- .rate = 32768,
- .ops = &clkops_null,
-};
-
-static struct clk virt_12000000_ck = {
- .name = "virt_12000000_ck",
- .ops = &clkops_null,
- .rate = 12000000,
-};
-
-static struct clk virt_13000000_ck = {
- .name = "virt_13000000_ck",
- .ops = &clkops_null,
- .rate = 13000000,
-};
-
-static struct clk virt_16800000_ck = {
- .name = "virt_16800000_ck",
- .ops = &clkops_null,
- .rate = 16800000,
-};
-
-static struct clk virt_27000000_ck = {
- .name = "virt_27000000_ck",
- .ops = &clkops_null,
- .rate = 27000000,
-};
-
-static struct clk virt_38400000_ck = {
- .name = "virt_38400000_ck",
- .ops = &clkops_null,
- .rate = 38400000,
-};
-
-static const struct clksel_rate div_1_5_rates[] = {
- { .div = 1, .val = 5, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel_rate div_1_6_rates[] = {
- { .div = 1, .val = 6, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel_rate div_1_7_rates[] = {
- { .div = 1, .val = 7, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel sys_clkin_sel[] = {
- { .parent = &virt_12000000_ck, .rates = div_1_1_rates },
- { .parent = &virt_13000000_ck, .rates = div_1_2_rates },
- { .parent = &virt_16800000_ck, .rates = div_1_3_rates },
- { .parent = &virt_19200000_ck, .rates = div_1_4_rates },
- { .parent = &virt_26000000_ck, .rates = div_1_5_rates },
- { .parent = &virt_27000000_ck, .rates = div_1_6_rates },
- { .parent = &virt_38400000_ck, .rates = div_1_7_rates },
- { .parent = NULL },
-};
-
-static struct clk sys_clkin_ck = {
- .name = "sys_clkin_ck",
- .rate = 38400000,
- .clksel = sys_clkin_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_SYS_CLKSEL,
- .clksel_mask = OMAP4430_SYS_CLKSEL_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk tie_low_clock_ck = {
- .name = "tie_low_clock_ck",
- .rate = 0,
- .ops = &clkops_null,
-};
-
-static struct clk utmi_phy_clkout_ck = {
- .name = "utmi_phy_clkout_ck",
- .rate = 60000000,
- .ops = &clkops_null,
-};
-
-static struct clk xclk60mhsp1_ck = {
- .name = "xclk60mhsp1_ck",
- .rate = 60000000,
- .ops = &clkops_null,
-};
-
-static struct clk xclk60mhsp2_ck = {
- .name = "xclk60mhsp2_ck",
- .rate = 60000000,
- .ops = &clkops_null,
-};
-
-static struct clk xclk60motg_ck = {
- .name = "xclk60motg_ck",
- .rate = 60000000,
- .ops = &clkops_null,
-};
-
-/* Module clocks and DPLL outputs */
-
-static const struct clksel abe_dpll_bypass_clk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &sys_32k_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk abe_dpll_bypass_clk_mux_ck = {
- .name = "abe_dpll_bypass_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk abe_dpll_refclk_mux_ck = {
- .name = "abe_dpll_refclk_mux_ck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_ABE_PLL_REF_CLKSEL,
- .clksel_mask = OMAP4430_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL_ABE */
-static struct dpll_data dpll_abe_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_ABE,
- .clk_bypass = &abe_dpll_bypass_clk_mux_ck,
- .clk_ref = &abe_dpll_refclk_mux_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_ABE,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_ABE,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_ABE,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = 2047,
- .max_divider = 128,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_abe_ck = {
- .name = "dpll_abe_ck",
- .parent = &abe_dpll_refclk_mux_ck,
- .dpll_data = &dpll_abe_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap4_dpll_regm4xen_recalc,
- .round_rate = &omap4_dpll_regm4xen_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_abe_x2_ck = {
- .name = "dpll_abe_x2_ck",
- .parent = &dpll_abe_ck,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_abe_m2x2_div[] = {
- { .parent = &dpll_abe_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_abe_m2x2_ck = {
- .name = "dpll_abe_m2x2_ck",
- .parent = &dpll_abe_x2_ck,
- .clksel = dpll_abe_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk abe_24m_fclk = {
- .name = "abe_24m_fclk",
- .parent = &dpll_abe_m2x2_ck,
- .ops = &clkops_null,
- .fixed_div = 8,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div3_1to4_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_4430 },
- { .div = 2, .val = 1, .flags = RATE_IN_4430 },
- { .div = 4, .val = 2, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel abe_clk_div[] = {
- { .parent = &dpll_abe_m2x2_ck, .rates = div3_1to4_rates },
- { .parent = NULL },
-};
-
-static struct clk abe_clk = {
- .name = "abe_clk",
- .parent = &dpll_abe_m2x2_ck,
- .clksel = abe_clk_div,
- .clksel_reg = OMAP4430_CM_CLKSEL_ABE,
- .clksel_mask = OMAP4430_CLKSEL_OPP_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div2_1to2_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_4430 },
- { .div = 2, .val = 1, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel aess_fclk_div[] = {
- { .parent = &abe_clk, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk aess_fclk = {
- .name = "aess_fclk",
- .parent = &abe_clk,
- .clksel = aess_fclk_div,
- .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_abe_m3x2_ck = {
- .name = "dpll_abe_m3x2_ck",
- .parent = &dpll_abe_x2_ck,
- .clksel = dpll_abe_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_ABE,
- .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel core_hsd_byp_clk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &dpll_abe_m3x2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk core_hsd_byp_clk_mux_ck = {
- .name = "core_hsd_byp_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .clksel = core_hsd_byp_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_CORE,
- .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_CORE,
- .clk_bypass = &core_hsd_byp_clk_mux_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_CORE,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_CORE,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = 2047,
- .max_divider = 128,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_core_ck = {
- .name = "dpll_core_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_core_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_core_dpll_ops,
- .recalc = &omap3_dpll_recalc,
-};
-
-static struct clk dpll_core_x2_ck = {
- .name = "dpll_core_x2_ck",
- .parent = &dpll_core_ck,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_null,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_core_m6x2_div[] = {
- { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_core_m6x2_ck = {
- .name = "dpll_core_m6x2_ck",
- .parent = &dpll_core_x2_ck,
- .clksel = dpll_core_m6x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_CORE,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel dbgclk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk dbgclk_mux_ck = {
- .name = "dbgclk_mux_ck",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel dpll_core_m2_div[] = {
- { .parent = &dpll_core_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_core_m2_ck = {
- .name = "dpll_core_m2_ck",
- .parent = &dpll_core_ck,
- .clksel = dpll_core_m2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_CORE,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk ddrphy_ck = {
- .name = "ddrphy_ck",
- .parent = &dpll_core_m2_ck,
- .ops = &clkops_null,
- .clkdm_name = "l3_emif_clkdm",
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk dpll_core_m5x2_ck = {
- .name = "dpll_core_m5x2_ck",
- .parent = &dpll_core_x2_ck,
- .clksel = dpll_core_m6x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_CORE,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel div_core_div[] = {
- { .parent = &dpll_core_m5x2_ck, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk div_core_ck = {
- .name = "div_core_ck",
- .parent = &dpll_core_m5x2_ck,
- .clksel = div_core_div,
- .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
- .clksel_mask = OMAP4430_CLKSEL_CORE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div4_1to8_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_4430 },
- { .div = 2, .val = 1, .flags = RATE_IN_4430 },
- { .div = 4, .val = 2, .flags = RATE_IN_4430 },
- { .div = 8, .val = 3, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel div_iva_hs_clk_div[] = {
- { .parent = &dpll_core_m5x2_ck, .rates = div4_1to8_rates },
- { .parent = NULL },
-};
-
-static struct clk div_iva_hs_clk = {
- .name = "div_iva_hs_clk",
- .parent = &dpll_core_m5x2_ck,
- .clksel = div_iva_hs_clk_div,
- .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_IVA,
- .clksel_mask = OMAP4430_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk div_mpu_hs_clk = {
- .name = "div_mpu_hs_clk",
- .parent = &dpll_core_m5x2_ck,
- .clksel = div_iva_hs_clk_div,
- .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_MPU,
- .clksel_mask = OMAP4430_CLKSEL_0_1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_core_m4x2_ck = {
- .name = "dpll_core_m4x2_ck",
- .parent = &dpll_core_x2_ck,
- .clksel = dpll_core_m6x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_CORE,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dll_clk_div_ck = {
- .name = "dll_clk_div_ck",
- .parent = &dpll_core_m4x2_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel dpll_abe_m2_div[] = {
- { .parent = &dpll_abe_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_abe_m2_ck = {
- .name = "dpll_abe_m2_ck",
- .parent = &dpll_abe_ck,
- .clksel = dpll_abe_m2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_core_m3x2_ck = {
- .name = "dpll_core_m3x2_ck",
- .parent = &dpll_core_x2_ck,
- .clksel = dpll_core_m6x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
- .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
- .enable_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
- .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
-};
-
-static struct clk dpll_core_m7x2_ck = {
- .name = "dpll_core_m7x2_ck",
- .parent = &dpll_core_x2_ck,
- .clksel = dpll_core_m6x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_CORE,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel iva_hsd_byp_clk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &div_iva_hs_clk, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk iva_hsd_byp_clk_mux_ck = {
- .name = "iva_hsd_byp_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .clksel = iva_hsd_byp_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_IVA,
- .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL_IVA */
-static struct dpll_data dpll_iva_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_IVA,
- .clk_bypass = &iva_hsd_byp_clk_mux_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_IVA,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_IVA,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = 2047,
- .max_divider = 128,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_iva_ck = {
- .name = "dpll_iva_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_iva_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_iva_x2_ck = {
- .name = "dpll_iva_x2_ck",
- .parent = &dpll_iva_ck,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_null,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_iva_m4x2_div[] = {
- { .parent = &dpll_iva_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_iva_m4x2_ck = {
- .name = "dpll_iva_m4x2_ck",
- .parent = &dpll_iva_x2_ck,
- .clksel = dpll_iva_m4x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_IVA,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_iva_m5x2_ck = {
- .name = "dpll_iva_m5x2_ck",
- .parent = &dpll_iva_x2_ck,
- .clksel = dpll_iva_m4x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_IVA,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_MPU,
- .clk_bypass = &div_mpu_hs_clk,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_MPU,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_MPU,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = 2047,
- .max_divider = 128,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_mpu_ck = {
- .name = "dpll_mpu_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_mpu_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-static const struct clksel dpll_mpu_m2_div[] = {
- { .parent = &dpll_mpu_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_mpu_m2_ck = {
- .name = "dpll_mpu_m2_ck",
- .parent = &dpll_mpu_ck,
- .clkdm_name = "cm_clkdm",
- .clksel = dpll_mpu_m2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk per_hs_clk_div_ck = {
- .name = "per_hs_clk_div_ck",
- .parent = &dpll_abe_m3x2_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel per_hsd_byp_clk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk per_hsd_byp_clk_mux_ck = {
- .name = "per_hsd_byp_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .clksel = per_hsd_byp_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_PER,
- .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_PER,
- .clk_bypass = &per_hsd_byp_clk_mux_ck,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_PER,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_PER,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_PER,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .max_multiplier = 2047,
- .max_divider = 128,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_per_ck = {
- .name = "dpll_per_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_per_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
-};
-
-static const struct clksel dpll_per_m2_div[] = {
- { .parent = &dpll_per_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_per_m2_ck = {
- .name = "dpll_per_m2_ck",
- .parent = &dpll_per_ck,
- .clksel = dpll_per_m2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_x2_ck = {
- .name = "dpll_per_x2_ck",
- .parent = &dpll_per_ck,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
- .flags = CLOCK_CLKOUTX2,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_per_m2x2_div[] = {
- { .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_per_m2x2_ck = {
- .name = "dpll_per_m2x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m3x2_ck = {
- .name = "dpll_per_m3x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
- .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
- .enable_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
- .enable_bit = OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
-};
-
-static struct clk dpll_per_m4x2_ck = {
- .name = "dpll_per_m4x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_PER,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m5x2_ck = {
- .name = "dpll_per_m5x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_PER,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m6x2_ck = {
- .name = "dpll_per_m6x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_PER,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m7x2_ck = {
- .name = "dpll_per_m7x2_ck",
- .parent = &dpll_per_x2_ck,
- .clksel = dpll_per_m2x2_div,
- .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_PER,
- .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk usb_hs_clk_div_ck = {
- .name = "usb_hs_clk_div_ck",
- .parent = &dpll_abe_m3x2_ck,
- .ops = &clkops_null,
- .fixed_div = 3,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-/* DPLL_USB */
-static struct dpll_data dpll_usb_dd = {
- .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_USB,
- .clk_bypass = &usb_hs_clk_div_ck,
- .flags = DPLL_J_TYPE,
- .clk_ref = &sys_clkin_ck,
- .control_reg = OMAP4430_CM_CLKMODE_DPLL_USB,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB,
- .idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB,
- .mult_mask = OMAP4430_DPLL_MULT_USB_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_0_7_MASK,
- .enable_mask = OMAP4430_DPLL_EN_MASK,
- .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
- .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
- .sddiv_mask = OMAP4430_DPLL_SD_DIV_MASK,
- .max_multiplier = 4095,
- .max_divider = 256,
- .min_divider = 1,
-};
-
-
-static struct clk dpll_usb_ck = {
- .name = "dpll_usb_ck",
- .parent = &sys_clkin_ck,
- .dpll_data = &dpll_usb_dd,
- .init = &omap2_init_dpll_parent,
- .ops = &clkops_omap3_noncore_dpll_ops,
- .recalc = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap3_noncore_dpll_set_rate,
- .clkdm_name = "l3_init_clkdm",
-};
-
-static struct clk dpll_usb_clkdcoldo_ck = {
- .name = "dpll_usb_clkdcoldo_ck",
- .parent = &dpll_usb_ck,
- .clksel_reg = OMAP4430_CM_CLKDCOLDO_DPLL_USB,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel dpll_usb_m2_div[] = {
- { .parent = &dpll_usb_ck, .rates = div31_1to31_rates },
- { .parent = NULL },
-};
-
-static struct clk dpll_usb_m2_ck = {
- .name = "dpll_usb_m2_ck",
- .parent = &dpll_usb_ck,
- .clksel = dpll_usb_m2_div,
- .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_USB,
- .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
- .ops = &clkops_omap4_dpllmx_ops,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel ducati_clk_mux_sel[] = {
- { .parent = &div_core_ck, .rates = div_1_0_rates },
- { .parent = &dpll_per_m6x2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk ducati_clk_mux_ck = {
- .name = "ducati_clk_mux_ck",
- .parent = &div_core_ck,
- .clksel = ducati_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT,
- .clksel_mask = OMAP4430_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk func_12m_fclk = {
- .name = "func_12m_fclk",
- .parent = &dpll_per_m2x2_ck,
- .ops = &clkops_null,
- .fixed_div = 16,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk func_24m_clk = {
- .name = "func_24m_clk",
- .parent = &dpll_per_m2_ck,
- .ops = &clkops_null,
- .fixed_div = 4,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk func_24mc_fclk = {
- .name = "func_24mc_fclk",
- .parent = &dpll_per_m2x2_ck,
- .ops = &clkops_null,
- .fixed_div = 8,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div2_4to8_rates[] = {
- { .div = 4, .val = 0, .flags = RATE_IN_4430 },
- { .div = 8, .val = 1, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel func_48m_fclk_div[] = {
- { .parent = &dpll_per_m2x2_ck, .rates = div2_4to8_rates },
- { .parent = NULL },
-};
-
-static struct clk func_48m_fclk = {
- .name = "func_48m_fclk",
- .parent = &dpll_per_m2x2_ck,
- .clksel = func_48m_fclk_div,
- .clksel_reg = OMAP4430_CM_SCALE_FCLK,
- .clksel_mask = OMAP4430_SCALE_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk func_48mc_fclk = {
- .name = "func_48mc_fclk",
- .parent = &dpll_per_m2x2_ck,
- .ops = &clkops_null,
- .fixed_div = 4,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div2_2to4_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_4430 },
- { .div = 4, .val = 1, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel func_64m_fclk_div[] = {
- { .parent = &dpll_per_m4x2_ck, .rates = div2_2to4_rates },
- { .parent = NULL },
-};
-
-static struct clk func_64m_fclk = {
- .name = "func_64m_fclk",
- .parent = &dpll_per_m4x2_ck,
- .clksel = func_64m_fclk_div,
- .clksel_reg = OMAP4430_CM_SCALE_FCLK,
- .clksel_mask = OMAP4430_SCALE_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel func_96m_fclk_div[] = {
- { .parent = &dpll_per_m2x2_ck, .rates = div2_2to4_rates },
- { .parent = NULL },
-};
-
-static struct clk func_96m_fclk = {
- .name = "func_96m_fclk",
- .parent = &dpll_per_m2x2_ck,
- .clksel = func_96m_fclk_div,
- .clksel_reg = OMAP4430_CM_SCALE_FCLK,
- .clksel_mask = OMAP4430_SCALE_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div2_1to8_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_4430 },
- { .div = 8, .val = 1, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel init_60m_fclk_div[] = {
- { .parent = &dpll_usb_m2_ck, .rates = div2_1to8_rates },
- { .parent = NULL },
-};
-
-static struct clk init_60m_fclk = {
- .name = "init_60m_fclk",
- .parent = &dpll_usb_m2_ck,
- .clksel = init_60m_fclk_div,
- .clksel_reg = OMAP4430_CM_CLKSEL_USB_60MHZ,
- .clksel_mask = OMAP4430_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel l3_div_div[] = {
- { .parent = &div_core_ck, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk l3_div_ck = {
- .name = "l3_div_ck",
- .parent = &div_core_ck,
- .clkdm_name = "cm_clkdm",
- .clksel = l3_div_div,
- .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
- .clksel_mask = OMAP4430_CLKSEL_L3_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel l4_div_div[] = {
- { .parent = &l3_div_ck, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk l4_div_ck = {
- .name = "l4_div_ck",
- .parent = &l3_div_ck,
- .clksel = l4_div_div,
- .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
- .clksel_mask = OMAP4430_CLKSEL_L4_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk lp_clk_div_ck = {
- .name = "lp_clk_div_ck",
- .parent = &dpll_abe_m2x2_ck,
- .ops = &clkops_null,
- .fixed_div = 16,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel l4_wkup_clk_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &lp_clk_div_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk l4_wkup_clk_mux_ck = {
- .name = "l4_wkup_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .clksel = l4_wkup_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4_WKUP_CLKSEL,
- .clksel_mask = OMAP4430_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div2_2to1_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_4430 },
- { .div = 2, .val = 0, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel ocp_abe_iclk_div[] = {
- { .parent = &aess_fclk, .rates = div2_2to1_rates },
- { .parent = NULL },
-};
-
-static struct clk mpu_periphclk = {
- .name = "mpu_periphclk",
- .parent = &dpll_mpu_ck,
- .ops = &clkops_null,
- .fixed_div = 2,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static struct clk ocp_abe_iclk = {
- .name = "ocp_abe_iclk",
- .parent = &aess_fclk,
- .clksel = ocp_abe_iclk_div,
- .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk per_abe_24m_fclk = {
- .name = "per_abe_24m_fclk",
- .parent = &dpll_abe_m2_ck,
- .ops = &clkops_null,
- .fixed_div = 4,
- .recalc = &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel per_abe_nc_fclk_div[] = {
- { .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk per_abe_nc_fclk = {
- .name = "per_abe_nc_fclk",
- .parent = &dpll_abe_m2_ck,
- .clksel = per_abe_nc_fclk_div,
- .clksel_reg = OMAP4430_CM_SCALE_FCLK,
- .clksel_mask = OMAP4430_SCALE_FCLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel pmd_stm_clock_mux_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
- { .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static struct clk pmd_stm_clock_mux_ck = {
- .name = "pmd_stm_clock_mux_ck",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static struct clk pmd_trace_clk_mux_ck = {
- .name = "pmd_trace_clk_mux_ck",
- .parent = &sys_clkin_ck,
- .ops = &clkops_null,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel syc_clk_div_div[] = {
- { .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
- { .parent = NULL },
-};
-
-static struct clk syc_clk_div_ck = {
- .name = "syc_clk_div_ck",
- .parent = &sys_clkin_ck,
- .clksel = syc_clk_div_div,
- .clksel_reg = OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
- .clksel_mask = OMAP4430_CLKSEL_0_0_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* Leaf clocks controlled by modules */
-
-static struct clk aes1_fck = {
- .name = "aes1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_AES1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk aes2_fck = {
- .name = "aes2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_AES2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk aess_fck = {
- .name = "aess_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
- .parent = &aess_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk bandgap_fclk = {
- .name = "bandgap_fclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk des3des_fck = {
- .name = "des3des_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel dmic_sync_mux_sel[] = {
- { .parent = &abe_24m_fclk, .rates = div_1_0_rates },
- { .parent = &syc_clk_div_ck, .rates = div_1_1_rates },
- { .parent = &func_24m_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static struct clk dmic_sync_mux_ck = {
- .name = "dmic_sync_mux_ck",
- .parent = &abe_24m_fclk,
- .clksel = dmic_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel func_dmic_abe_gfclk_sel[] = {
- { .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = &slimbus_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-/* Merged func_dmic_abe_gfclk into dmic */
-static struct clk dmic_fck = {
- .name = "dmic_fck",
- .parent = &dmic_sync_mux_ck,
- .clksel = func_dmic_abe_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-static struct clk dsp_fck = {
- .name = "dsp_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "tesla_clkdm",
- .parent = &dpll_iva_m4x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_sys_clk = {
- .name = "dss_sys_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT,
- .clkdm_name = "l3_dss_clkdm",
- .parent = &syc_clk_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_tv_clk = {
- .name = "dss_tv_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_TV_CLK_SHIFT,
- .clkdm_name = "l3_dss_clkdm",
- .parent = &extalt_clkin_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_dss_clk = {
- .name = "dss_dss_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
- .clkdm_name = "l3_dss_clkdm",
- .parent = &dpll_per_m5x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate div3_8to32_rates[] = {
- { .div = 8, .val = 0, .flags = RATE_IN_4460 },
- { .div = 16, .val = 1, .flags = RATE_IN_4460 },
- { .div = 32, .val = 2, .flags = RATE_IN_4460 },
- { .div = 0 },
-};
-
-static const struct clksel div_ts_div[] = {
- { .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
- { .parent = NULL },
-};
-
-static struct clk div_ts_ck = {
- .name = "div_ts_ck",
- .parent = &l4_wkup_clk_mux_ck,
- .clksel = div_ts_div,
- .clksel_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_24_25_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk bandgap_ts_fclk = {
- .name = "bandgap_ts_fclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
- .enable_bit = OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &div_ts_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_48mhz_clk = {
- .name = "dss_48mhz_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
- .clkdm_name = "l3_dss_clkdm",
- .parent = &func_48mc_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk dss_fck = {
- .name = "dss_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_dss_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk efuse_ctrl_cust_fck = {
- .name = "efuse_ctrl_cust_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_cefuse_clkdm",
- .parent = &sys_clkin_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk emif1_fck = {
- .name = "emif1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_emif_clkdm",
- .parent = &ddrphy_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk emif2_fck = {
- .name = "emif2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_emif_clkdm",
- .parent = &ddrphy_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel fdif_fclk_div[] = {
- { .parent = &dpll_per_m4x2_ck, .rates = div3_1to4_rates },
- { .parent = NULL },
-};
-
-/* Merged fdif_fclk into fdif */
-static struct clk fdif_fck = {
- .name = "fdif_fck",
- .parent = &dpll_per_m4x2_ck,
- .clksel = fdif_fclk_div,
- .clksel_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_FCLK_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
- .enable_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "iss_clkdm",
-};
-
-static struct clk fpka_fck = {
- .name = "fpka_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio1_dbclk = {
- .name = "gpio1_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio1_ick = {
- .name = "gpio1_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &l4_wkup_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio2_dbclk = {
- .name = "gpio2_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio2_ick = {
- .name = "gpio2_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio3_dbclk = {
- .name = "gpio3_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio3_ick = {
- .name = "gpio3_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio4_dbclk = {
- .name = "gpio4_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio4_ick = {
- .name = "gpio4_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_dbclk = {
- .name = "gpio5_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
- .name = "gpio5_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio6_dbclk = {
- .name = "gpio6_dbclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpio6_ick = {
- .name = "gpio6_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk gpmc_ick = {
- .name = "gpmc_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3_2_GPMC_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_2_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel sgx_clk_mux_sel[] = {
- { .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
- { .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-/* Merged sgx_clk_mux into gpu */
-static struct clk gpu_fck = {
- .name = "gpu_fck",
- .parent = &dpll_core_m7x2_ck,
- .clksel = sgx_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_GFX_GFX_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SGX_FCLK_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_GFX_GFX_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_gfx_clkdm",
-};
-
-static struct clk hdq1w_fck = {
- .name = "hdq1w_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_12m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel hsi_fclk_div[] = {
- { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
- { .parent = NULL },
-};
-
-/* Merged hsi_fclk into hsi */
-static struct clk hsi_fck = {
- .name = "hsi_fck",
- .parent = &dpll_per_m2x2_ck,
- .clksel = hsi_fclk_div,
- .clksel_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_24_25_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
- .enable_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_init_clkdm",
-};
-
-static struct clk i2c1_fck = {
- .name = "i2c1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_96m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
- .name = "i2c2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_96m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c3_fck = {
- .name = "i2c3_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_96m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk i2c4_fck = {
- .name = "i2c4_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_96m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ipu_fck = {
- .name = "ipu_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "ducati_clkdm",
- .parent = &ducati_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk iss_ctrlclk = {
- .name = "iss_ctrlclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
- .clkdm_name = "iss_clkdm",
- .parent = &func_96m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk iss_fck = {
- .name = "iss_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "iss_clkdm",
- .parent = &ducati_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk iva_fck = {
- .name = "iva_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "ivahd_clkdm",
- .parent = &dpll_iva_m5x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk kbd_fck = {
- .name = "kbd_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk l3_instr_ick = {
- .name = "l3_instr_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_instr_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk l3_main_3_ick = {
- .name = "l3_main_3_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_instr_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcasp_sync_mux_ck = {
- .name = "mcasp_sync_mux_ck",
- .parent = &abe_24m_fclk,
- .clksel = dmic_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcasp_abe_gfclk_sel[] = {
- { .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = &slimbus_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-/* Merged func_mcasp_abe_gfclk into mcasp */
-static struct clk mcasp_fck = {
- .name = "mcasp_fck",
- .parent = &mcasp_sync_mux_ck,
- .clksel = func_mcasp_abe_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-static struct clk mcbsp1_sync_mux_ck = {
- .name = "mcbsp1_sync_mux_ck",
- .parent = &abe_24m_fclk,
- .clksel = dmic_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp1_gfclk_sel[] = {
- { .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = &slimbus_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-/* Merged func_mcbsp1_gfclk into mcbsp1 */
-static struct clk mcbsp1_fck = {
- .name = "mcbsp1_fck",
- .parent = &mcbsp1_sync_mux_ck,
- .clksel = func_mcbsp1_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-static struct clk mcbsp2_sync_mux_ck = {
- .name = "mcbsp2_sync_mux_ck",
- .parent = &abe_24m_fclk,
- .clksel = dmic_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp2_gfclk_sel[] = {
- { .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = &slimbus_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-/* Merged func_mcbsp2_gfclk into mcbsp2 */
-static struct clk mcbsp2_fck = {
- .name = "mcbsp2_fck",
- .parent = &mcbsp2_sync_mux_ck,
- .clksel = func_mcbsp2_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-static struct clk mcbsp3_sync_mux_ck = {
- .name = "mcbsp3_sync_mux_ck",
- .parent = &abe_24m_fclk,
- .clksel = dmic_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp3_gfclk_sel[] = {
- { .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = &slimbus_clk, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-/* Merged func_mcbsp3_gfclk into mcbsp3 */
-static struct clk mcbsp3_fck = {
- .name = "mcbsp3_fck",
- .parent = &mcbsp3_sync_mux_ck,
- .clksel = func_mcbsp3_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-static const struct clksel mcbsp4_sync_mux_sel[] = {
- { .parent = &func_96m_fclk, .rates = div_1_0_rates },
- { .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk mcbsp4_sync_mux_ck = {
- .name = "mcbsp4_sync_mux_ck",
- .parent = &func_96m_fclk,
- .clksel = mcbsp4_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static const struct clksel per_mcbsp4_gfclk_sel[] = {
- { .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates },
- { .parent = &pad_clks_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-/* Merged per_mcbsp4_gfclk into mcbsp4 */
-static struct clk mcbsp4_fck = {
- .name = "mcbsp4_fck",
- .parent = &mcbsp4_sync_mux_ck,
- .clksel = per_mcbsp4_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_SOURCE_24_24_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-static struct clk mcpdm_fck = {
- .name = "mcpdm_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
- .parent = &pad_clks_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
- .name = "mcspi1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
- .name = "mcspi2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi3_fck = {
- .name = "mcspi3_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mcspi4_fck = {
- .name = "mcspi4_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel hsmmc1_fclk_sel[] = {
- { .parent = &func_64m_fclk, .rates = div_1_0_rates },
- { .parent = &func_96m_fclk, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-/* Merged hsmmc1_fclk into mmc1 */
-static struct clk mmc1_fck = {
- .name = "mmc1_fck",
- .parent = &func_64m_fclk,
- .clksel = hsmmc1_fclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_init_clkdm",
-};
-
-/* Merged hsmmc2_fclk into mmc2 */
-static struct clk mmc2_fck = {
- .name = "mmc2_fck",
- .parent = &func_64m_fclk,
- .clksel = hsmmc1_fclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_init_clkdm",
-};
-
-static struct clk mmc3_fck = {
- .name = "mmc3_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmc4_fck = {
- .name = "mmc4_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk mmc5_fck = {
- .name = "mmc5_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ocp2scp_usb_phy_phy_48m = {
- .name = "ocp2scp_usb_phy_phy_48m",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_PHY_48M_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ocp2scp_usb_phy_ick = {
- .name = "ocp2scp_usb_phy_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_init_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk ocp_wp_noc_ick = {
- .name = "ocp_wp_noc_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "l3_instr_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk rng_ick = {
- .name = "rng_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_RNG_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sha2md5_fck = {
- .name = "sha2md5_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_secure_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk sl2if_ick = {
- .name = "sl2if_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_IVAHD_SL2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "ivahd_clkdm",
- .parent = &dpll_iva_m5x2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_1 = {
- .name = "slimbus1_fclk_1",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_FCLK1_SHIFT,
- .clkdm_name = "abe_clkdm",
- .parent = &func_24m_clk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_0 = {
- .name = "slimbus1_fclk_0",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_FCLK0_SHIFT,
- .clkdm_name = "abe_clkdm",
- .parent = &abe_24m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_2 = {
- .name = "slimbus1_fclk_2",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_FCLK2_SHIFT,
- .clkdm_name = "abe_clkdm",
- .parent = &pad_clks_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus1_slimbus_clk = {
- .name = "slimbus1_slimbus_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT,
- .clkdm_name = "abe_clkdm",
- .parent = &slimbus_clk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus1_fck = {
- .name = "slimbus1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
- .parent = &ocp_abe_iclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus2_fclk_1 = {
- .name = "slimbus2_fclk_1",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &per_abe_24m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus2_fclk_0 = {
- .name = "slimbus2_fclk_0",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_24mc_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus2_slimbus_clk = {
- .name = "slimbus2_slimbus_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT,
- .clkdm_name = "l4_per_clkdm",
- .parent = &pad_slimbus_core_clks_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk slimbus2_fck = {
- .name = "slimbus2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk smartreflex_core_fck = {
- .name = "smartreflex_core_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_ao_clkdm",
- .parent = &l4_wkup_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk smartreflex_iva_fck = {
- .name = "smartreflex_iva_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_ao_clkdm",
- .parent = &l4_wkup_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk smartreflex_mpu_fck = {
- .name = "smartreflex_mpu_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_ao_clkdm",
- .parent = &l4_wkup_clk_mux_ck,
- .recalc = &followparent_recalc,
-};
-
-/* Merged dmt1_clk_mux into timer1 */
-static struct clk timer1_fck = {
- .name = "timer1_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_wkup_clkdm",
-};
-
-/* Merged cm2_dm10_mux into timer10 */
-static struct clk timer10_fck = {
- .name = "timer10_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-/* Merged cm2_dm11_mux into timer11 */
-static struct clk timer11_fck = {
- .name = "timer11_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-/* Merged cm2_dm2_mux into timer2 */
-static struct clk timer2_fck = {
- .name = "timer2_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-/* Merged cm2_dm3_mux into timer3 */
-static struct clk timer3_fck = {
- .name = "timer3_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-/* Merged cm2_dm4_mux into timer4 */
-static struct clk timer4_fck = {
- .name = "timer4_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-static const struct clksel timer5_sync_mux_sel[] = {
- { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
- { .parent = &sys_32k_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-/* Merged timer5_sync_mux into timer5 */
-static struct clk timer5_fck = {
- .name = "timer5_fck",
- .parent = &syc_clk_div_ck,
- .clksel = timer5_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-/* Merged timer6_sync_mux into timer6 */
-static struct clk timer6_fck = {
- .name = "timer6_fck",
- .parent = &syc_clk_div_ck,
- .clksel = timer5_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-/* Merged timer7_sync_mux into timer7 */
-static struct clk timer7_fck = {
- .name = "timer7_fck",
- .parent = &syc_clk_div_ck,
- .clksel = timer5_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-/* Merged timer8_sync_mux into timer8 */
-static struct clk timer8_fck = {
- .name = "timer8_fck",
- .parent = &syc_clk_div_ck,
- .clksel = timer5_sync_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
-};
-
-/* Merged cm2_dm9_mux into timer9 */
-static struct clk timer9_fck = {
- .name = "timer9_fck",
- .parent = &sys_clkin_ck,
- .clksel = abe_dpll_bypass_clk_mux_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_MASK,
- .ops = &clkops_omap2_dflt,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
-};
-
-static struct clk uart1_fck = {
- .name = "uart1_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
- .name = "uart2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
- .name = "uart3_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk uart4_fck = {
- .name = "uart4_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_per_clkdm",
- .parent = &func_48m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_fs_fck = {
- .name = "usb_host_fs_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_init_clkdm",
- .parent = &func_48mc_fclk,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel utmi_p1_gfclk_sel[] = {
- { .parent = &init_60m_fclk, .rates = div_1_0_rates },
- { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk utmi_p1_gfclk = {
- .name = "utmi_p1_gfclk",
- .parent = &init_60m_fclk,
- .clksel = utmi_p1_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_UTMI_P1_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p1_clk = {
- .name = "usb_host_hs_utmi_p1_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &utmi_p1_gfclk,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel utmi_p2_gfclk_sel[] = {
- { .parent = &init_60m_fclk, .rates = div_1_0_rates },
- { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk utmi_p2_gfclk = {
- .name = "utmi_p2_gfclk",
- .parent = &init_60m_fclk,
- .clksel = utmi_p2_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_UTMI_P2_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p2_clk = {
- .name = "usb_host_hs_utmi_p2_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &utmi_p2_gfclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p3_clk = {
- .name = "usb_host_hs_utmi_p3_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic480m_p1_clk = {
- .name = "usb_host_hs_hsic480m_p1_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &dpll_usb_m2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p1_clk = {
- .name = "usb_host_hs_hsic60m_p1_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p2_clk = {
- .name = "usb_host_hs_hsic60m_p2_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic480m_p2_clk = {
- .name = "usb_host_hs_hsic480m_p2_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &dpll_usb_m2_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_func48mclk = {
- .name = "usb_host_hs_func48mclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &func_48mc_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_host_hs_fck = {
- .name = "usb_host_hs_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel otg_60m_gfclk_sel[] = {
- { .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates },
- { .parent = &xclk60motg_ck, .rates = div_1_1_rates },
- { .parent = NULL },
-};
-
-static struct clk otg_60m_gfclk = {
- .name = "otg_60m_gfclk",
- .parent = &utmi_phy_clkout_ck,
- .clksel = otg_60m_gfclk_sel,
- .init = &omap2_init_clksel_parent,
- .clksel_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_60M_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk usb_otg_hs_xclk = {
- .name = "usb_otg_hs_xclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_XCLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &otg_60m_gfclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_otg_hs_ick = {
- .name = "usb_otg_hs_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_init_clkdm",
- .parent = &l3_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_phy_cm_clk32k = {
- .name = "usb_phy_cm_clk32k",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_CLK32K_SHIFT,
- .clkdm_name = "l4_ao_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch2_clk = {
- .name = "usb_tll_hs_usb_ch2_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch0_clk = {
- .name = "usb_tll_hs_usb_ch0_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch1_clk = {
- .name = "usb_tll_hs_usb_ch1_clk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT,
- .clkdm_name = "l3_init_clkdm",
- .parent = &init_60m_fclk,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_ick = {
- .name = "usb_tll_hs_ick",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l3_init_clkdm",
- .parent = &l4_div_ck,
- .recalc = &followparent_recalc,
-};
-
-static const struct clksel_rate div2_14to18_rates[] = {
- { .div = 14, .val = 0, .flags = RATE_IN_4430 },
- { .div = 18, .val = 1, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static const struct clksel usim_fclk_div[] = {
- { .parent = &dpll_per_m4x2_ck, .rates = div2_14to18_rates },
- { .parent = NULL },
-};
-
-static struct clk usim_ck = {
- .name = "usim_ck",
- .parent = &dpll_per_m4x2_ck,
- .clksel = usim_fclk_div,
- .clksel_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_DIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk usim_fclk = {
- .name = "usim_fclk",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL,
- .enable_bit = OMAP4430_OPTFCLKEN_FCLK_SHIFT,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &usim_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk usim_fck = {
- .name = "usim_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_USIM_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_HWCTRL,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wd_timer2_fck = {
- .name = "wd_timer2_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "l4_wkup_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-static struct clk wd_timer3_fck = {
- .name = "wd_timer3_fck",
- .ops = &clkops_omap2_dflt,
- .enable_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
- .enable_bit = OMAP4430_MODULEMODE_SWCTRL,
- .clkdm_name = "abe_clkdm",
- .parent = &sys_32k_ck,
- .recalc = &followparent_recalc,
-};
-
-/* Remaining optional clocks */
-static const struct clksel stm_clk_div_div[] = {
- { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
- { .parent = NULL },
-};
-
-static struct clk stm_clk_div_ck = {
- .name = "stm_clk_div_ck",
- .parent = &pmd_stm_clock_mux_ck,
- .clksel = stm_clk_div_div,
- .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel trace_clk_div_div[] = {
- { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
- { .parent = NULL },
-};
-
-static struct clk trace_clk_div_ck = {
- .name = "trace_clk_div_ck",
- .parent = &pmd_trace_clk_mux_ck,
- .clkdm_name = "emu_sys_clkdm",
- .clksel = trace_clk_div_div,
- .clksel_reg = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
- .clksel_mask = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-/* SCRM aux clk nodes */
-
-static const struct clksel auxclk_src_sel[] = {
- { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
- { .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
- { .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
- { .parent = NULL },
-};
-
-static const struct clksel_rate div16_1to16_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_4430 },
- { .div = 2, .val = 1, .flags = RATE_IN_4430 },
- { .div = 3, .val = 2, .flags = RATE_IN_4430 },
- { .div = 4, .val = 3, .flags = RATE_IN_4430 },
- { .div = 5, .val = 4, .flags = RATE_IN_4430 },
- { .div = 6, .val = 5, .flags = RATE_IN_4430 },
- { .div = 7, .val = 6, .flags = RATE_IN_4430 },
- { .div = 8, .val = 7, .flags = RATE_IN_4430 },
- { .div = 9, .val = 8, .flags = RATE_IN_4430 },
- { .div = 10, .val = 9, .flags = RATE_IN_4430 },
- { .div = 11, .val = 10, .flags = RATE_IN_4430 },
- { .div = 12, .val = 11, .flags = RATE_IN_4430 },
- { .div = 13, .val = 12, .flags = RATE_IN_4430 },
- { .div = 14, .val = 13, .flags = RATE_IN_4430 },
- { .div = 15, .val = 14, .flags = RATE_IN_4430 },
- { .div = 16, .val = 15, .flags = RATE_IN_4430 },
- { .div = 0 },
-};
-
-static struct clk auxclk0_src_ck = {
- .name = "auxclk0_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK0,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK0,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk0_sel[] = {
- { .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk0_ck = {
- .name = "auxclk0_ck",
- .parent = &auxclk0_src_ck,
- .clksel = auxclk0_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK0,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk1_src_ck = {
- .name = "auxclk1_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK1,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK1,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk1_sel[] = {
- { .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk1_ck = {
- .name = "auxclk1_ck",
- .parent = &auxclk1_src_ck,
- .clksel = auxclk1_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK1,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk2_src_ck = {
- .name = "auxclk2_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK2,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK2,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk2_sel[] = {
- { .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk2_ck = {
- .name = "auxclk2_ck",
- .parent = &auxclk2_src_ck,
- .clksel = auxclk2_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK2,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk3_src_ck = {
- .name = "auxclk3_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK3,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK3,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk3_sel[] = {
- { .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk3_ck = {
- .name = "auxclk3_ck",
- .parent = &auxclk3_src_ck,
- .clksel = auxclk3_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK3,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk4_src_ck = {
- .name = "auxclk4_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK4,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK4,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk4_sel[] = {
- { .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk4_ck = {
- .name = "auxclk4_ck",
- .parent = &auxclk4_src_ck,
- .clksel = auxclk4_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK4,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk5_src_ck = {
- .name = "auxclk5_src_ck",
- .parent = &sys_clkin_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_omap2_dflt,
- .clksel = auxclk_src_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK5,
- .clksel_mask = OMAP4_SRCSELECT_MASK,
- .recalc = &omap2_clksel_recalc,
- .enable_reg = OMAP4_SCRM_AUXCLK5,
- .enable_bit = OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk5_sel[] = {
- { .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclk5_ck = {
- .name = "auxclk5_ck",
- .parent = &auxclk5_src_ck,
- .clksel = auxclk5_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLK5,
- .clksel_mask = OMAP4_CLKDIV_MASK,
- .ops = &clkops_null,
- .recalc = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
- .set_rate = &omap2_clksel_set_rate,
-};
-
-static const struct clksel auxclkreq_sel[] = {
- { .parent = &auxclk0_ck, .rates = div_1_0_rates },
- { .parent = &auxclk1_ck, .rates = div_1_1_rates },
- { .parent = &auxclk2_ck, .rates = div_1_2_rates },
- { .parent = &auxclk3_ck, .rates = div_1_3_rates },
- { .parent = &auxclk4_ck, .rates = div_1_4_rates },
- { .parent = &auxclk5_ck, .rates = div_1_5_rates },
- { .parent = NULL },
-};
-
-static struct clk auxclkreq0_ck = {
- .name = "auxclkreq0_ck",
- .parent = &auxclk0_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ0,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq1_ck = {
- .name = "auxclkreq1_ck",
- .parent = &auxclk1_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ1,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq2_ck = {
- .name = "auxclkreq2_ck",
- .parent = &auxclk2_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ2,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq3_ck = {
- .name = "auxclkreq3_ck",
- .parent = &auxclk3_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ3,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq4_ck = {
- .name = "auxclkreq4_ck",
- .parent = &auxclk4_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ4,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq5_ck = {
- .name = "auxclkreq5_ck",
- .parent = &auxclk5_ck,
- .init = &omap2_init_clksel_parent,
- .ops = &clkops_null,
- .clksel = auxclkreq_sel,
- .clksel_reg = OMAP4_SCRM_AUXCLKREQ5,
- .clksel_mask = OMAP4_MAPPING_MASK,
- .recalc = &omap2_clksel_recalc,
-};
-
-/*
- * clkdev
- */
-
-static struct omap_clk omap44xx_clks[] = {
- CLK(NULL, "extalt_clkin_ck", &extalt_clkin_ck, CK_443X),
- CLK(NULL, "pad_clks_ck", &pad_clks_ck, CK_443X),
- CLK(NULL, "pad_slimbus_core_clks_ck", &pad_slimbus_core_clks_ck, CK_443X),
- CLK(NULL, "secure_32k_clk_src_ck", &secure_32k_clk_src_ck, CK_443X),
- CLK(NULL, "slimbus_clk", &slimbus_clk, CK_443X),
- CLK(NULL, "sys_32k_ck", &sys_32k_ck, CK_443X),
- CLK(NULL, "virt_12000000_ck", &virt_12000000_ck, CK_443X),
- CLK(NULL, "virt_13000000_ck", &virt_13000000_ck, CK_443X),
- CLK(NULL, "virt_16800000_ck", &virt_16800000_ck, CK_443X),
- CLK(NULL, "virt_19200000_ck", &virt_19200000_ck, CK_443X),
- CLK(NULL, "virt_26000000_ck", &virt_26000000_ck, CK_443X),
- CLK(NULL, "virt_27000000_ck", &virt_27000000_ck, CK_443X),
- CLK(NULL, "virt_38400000_ck", &virt_38400000_ck, CK_443X),
- CLK(NULL, "sys_clkin_ck", &sys_clkin_ck, CK_443X),
- CLK(NULL, "tie_low_clock_ck", &tie_low_clock_ck, CK_443X),
- CLK(NULL, "utmi_phy_clkout_ck", &utmi_phy_clkout_ck, CK_443X),
- CLK(NULL, "xclk60mhsp1_ck", &xclk60mhsp1_ck, CK_443X),
- CLK(NULL, "xclk60mhsp2_ck", &xclk60mhsp2_ck, CK_443X),
- CLK(NULL, "xclk60motg_ck", &xclk60motg_ck, CK_443X),
- CLK(NULL, "abe_dpll_bypass_clk_mux_ck", &abe_dpll_bypass_clk_mux_ck, CK_443X),
- CLK(NULL, "abe_dpll_refclk_mux_ck", &abe_dpll_refclk_mux_ck, CK_443X),
- CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_443X),
- CLK(NULL, "dpll_abe_x2_ck", &dpll_abe_x2_ck, CK_443X),
- CLK(NULL, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, CK_443X),
- CLK(NULL, "abe_24m_fclk", &abe_24m_fclk, CK_443X),
- CLK(NULL, "abe_clk", &abe_clk, CK_443X),
- CLK(NULL, "aess_fclk", &aess_fclk, CK_443X),
- CLK(NULL, "dpll_abe_m3x2_ck", &dpll_abe_m3x2_ck, CK_443X),
- CLK(NULL, "core_hsd_byp_clk_mux_ck", &core_hsd_byp_clk_mux_ck, CK_443X),
- CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_443X),
- CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_443X),
- CLK(NULL, "dpll_core_m6x2_ck", &dpll_core_m6x2_ck, CK_443X),
- CLK(NULL, "dbgclk_mux_ck", &dbgclk_mux_ck, CK_443X),
- CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_443X),
- CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_443X),
- CLK(NULL, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, CK_443X),
- CLK(NULL, "div_core_ck", &div_core_ck, CK_443X),
- CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_443X),
- CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_443X),
- CLK(NULL, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck, CK_443X),
- CLK(NULL, "dll_clk_div_ck", &dll_clk_div_ck, CK_443X),
- CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_443X),
- CLK(NULL, "dpll_core_m3x2_ck", &dpll_core_m3x2_ck, CK_443X),
- CLK(NULL, "dpll_core_m7x2_ck", &dpll_core_m7x2_ck, CK_443X),
- CLK(NULL, "iva_hsd_byp_clk_mux_ck", &iva_hsd_byp_clk_mux_ck, CK_443X),
- CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_443X),
- CLK(NULL, "dpll_iva_x2_ck", &dpll_iva_x2_ck, CK_443X),
- CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_443X),
- CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_443X),
- CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X),
- CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X),
- CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X),
- CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X),
- CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_443X),
- CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_443X),
- CLK(NULL, "dpll_per_x2_ck", &dpll_per_x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m3x2_ck", &dpll_per_m3x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m6x2_ck", &dpll_per_m6x2_ck, CK_443X),
- CLK(NULL, "dpll_per_m7x2_ck", &dpll_per_m7x2_ck, CK_443X),
- CLK(NULL, "usb_hs_clk_div_ck", &usb_hs_clk_div_ck, CK_443X),
- CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X),
- CLK(NULL, "dpll_usb_clkdcoldo_ck", &dpll_usb_clkdcoldo_ck, CK_443X),
- CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_443X),
- CLK(NULL, "ducati_clk_mux_ck", &ducati_clk_mux_ck, CK_443X),
- CLK(NULL, "func_12m_fclk", &func_12m_fclk, CK_443X),
- CLK(NULL, "func_24m_clk", &func_24m_clk, CK_443X),
- CLK(NULL, "func_24mc_fclk", &func_24mc_fclk, CK_443X),
- CLK(NULL, "func_48m_fclk", &func_48m_fclk, CK_443X),
- CLK(NULL, "func_48mc_fclk", &func_48mc_fclk, CK_443X),
- CLK(NULL, "func_64m_fclk", &func_64m_fclk, CK_443X),
- CLK(NULL, "func_96m_fclk", &func_96m_fclk, CK_443X),
- CLK(NULL, "init_60m_fclk", &init_60m_fclk, CK_443X),
- CLK(NULL, "l3_div_ck", &l3_div_ck, CK_443X),
- CLK(NULL, "l4_div_ck", &l4_div_ck, CK_443X),
- CLK(NULL, "lp_clk_div_ck", &lp_clk_div_ck, CK_443X),
- CLK(NULL, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, CK_443X),
- CLK("smp_twd", NULL, &mpu_periphclk, CK_443X),
- CLK(NULL, "ocp_abe_iclk", &ocp_abe_iclk, CK_443X),
- CLK(NULL, "per_abe_24m_fclk", &per_abe_24m_fclk, CK_443X),
- CLK(NULL, "per_abe_nc_fclk", &per_abe_nc_fclk, CK_443X),
- CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X),
- CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X),
- CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X),
- CLK(NULL, "aes1_fck", &aes1_fck, CK_443X),
- CLK(NULL, "aes2_fck", &aes2_fck, CK_443X),
- CLK(NULL, "aess_fck", &aess_fck, CK_443X),
- CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X),
- CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X),
- CLK(NULL, "des3des_fck", &des3des_fck, CK_443X),
- CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X),
- CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X),
- CLK(NULL, "dmic_fck", &dmic_fck, CK_443X),
- CLK(NULL, "dsp_fck", &dsp_fck, CK_443X),
- CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X),
- CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X),
- CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X),
- CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X),
- CLK(NULL, "dss_fck", &dss_fck, CK_443X),
- CLK("omapdss_dss", "ick", &dss_fck, CK_443X),
- CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X),
- CLK(NULL, "emif1_fck", &emif1_fck, CK_443X),
- CLK(NULL, "emif2_fck", &emif2_fck, CK_443X),
- CLK(NULL, "fdif_fck", &fdif_fck, CK_443X),
- CLK(NULL, "fpka_fck", &fpka_fck, CK_443X),
- CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_443X),
- CLK(NULL, "gpio1_ick", &gpio1_ick, CK_443X),
- CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_443X),
- CLK(NULL, "gpio2_ick", &gpio2_ick, CK_443X),
- CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_443X),
- CLK(NULL, "gpio3_ick", &gpio3_ick, CK_443X),
- CLK(NULL, "gpio4_dbclk", &gpio4_dbclk, CK_443X),
- CLK(NULL, "gpio4_ick", &gpio4_ick, CK_443X),
- CLK(NULL, "gpio5_dbclk", &gpio5_dbclk, CK_443X),
- CLK(NULL, "gpio5_ick", &gpio5_ick, CK_443X),
- CLK(NULL, "gpio6_dbclk", &gpio6_dbclk, CK_443X),
- CLK(NULL, "gpio6_ick", &gpio6_ick, CK_443X),
- CLK(NULL, "gpmc_ick", &gpmc_ick, CK_443X),
- CLK(NULL, "gpu_fck", &gpu_fck, CK_443X),
- CLK(NULL, "hdq1w_fck", &hdq1w_fck, CK_443X),
- CLK(NULL, "hsi_fck", &hsi_fck, CK_443X),
- CLK(NULL, "i2c1_fck", &i2c1_fck, CK_443X),
- CLK(NULL, "i2c2_fck", &i2c2_fck, CK_443X),
- CLK(NULL, "i2c3_fck", &i2c3_fck, CK_443X),
- CLK(NULL, "i2c4_fck", &i2c4_fck, CK_443X),
- CLK(NULL, "ipu_fck", &ipu_fck, CK_443X),
- CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_443X),
- CLK(NULL, "iss_fck", &iss_fck, CK_443X),
- CLK(NULL, "iva_fck", &iva_fck, CK_443X),
- CLK(NULL, "kbd_fck", &kbd_fck, CK_443X),
- CLK(NULL, "l3_instr_ick", &l3_instr_ick, CK_443X),
- CLK(NULL, "l3_main_3_ick", &l3_main_3_ick, CK_443X),
- CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X),
- CLK(NULL, "mcasp_fck", &mcasp_fck, CK_443X),
- CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_443X),
- CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_443X),
- CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X),
- CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_443X),
- CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X),
- CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_443X),
- CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_443X),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_443X),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_443X),
- CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_443X),
- CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_443X),
- CLK(NULL, "mmc1_fck", &mmc1_fck, CK_443X),
- CLK(NULL, "mmc2_fck", &mmc2_fck, CK_443X),
- CLK(NULL, "mmc3_fck", &mmc3_fck, CK_443X),
- CLK(NULL, "mmc4_fck", &mmc4_fck, CK_443X),
- CLK(NULL, "mmc5_fck", &mmc5_fck, CK_443X),
- CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X),
- CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_443X),
- CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_443X),
- CLK(NULL, "rng_ick", &rng_ick, CK_443X),
- CLK("omap_rng", "ick", &rng_ick, CK_443X),
- CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X),
- CLK(NULL, "sl2if_ick", &sl2if_ick, CK_443X),
- CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X),
- CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X),
- CLK(NULL, "slimbus1_fclk_2", &slimbus1_fclk_2, CK_443X),
- CLK(NULL, "slimbus1_slimbus_clk", &slimbus1_slimbus_clk, CK_443X),
- CLK(NULL, "slimbus1_fck", &slimbus1_fck, CK_443X),
- CLK(NULL, "slimbus2_fclk_1", &slimbus2_fclk_1, CK_443X),
- CLK(NULL, "slimbus2_fclk_0", &slimbus2_fclk_0, CK_443X),
- CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_443X),
- CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_443X),
- CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X),
- CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X),
- CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X),
- CLK(NULL, "timer1_fck", &timer1_fck, CK_443X),
- CLK(NULL, "timer10_fck", &timer10_fck, CK_443X),
- CLK(NULL, "timer11_fck", &timer11_fck, CK_443X),
- CLK(NULL, "timer2_fck", &timer2_fck, CK_443X),
- CLK(NULL, "timer3_fck", &timer3_fck, CK_443X),
- CLK(NULL, "timer4_fck", &timer4_fck, CK_443X),
- CLK(NULL, "timer5_fck", &timer5_fck, CK_443X),
- CLK(NULL, "timer6_fck", &timer6_fck, CK_443X),
- CLK(NULL, "timer7_fck", &timer7_fck, CK_443X),
- CLK(NULL, "timer8_fck", &timer8_fck, CK_443X),
- CLK(NULL, "timer9_fck", &timer9_fck, CK_443X),
- CLK(NULL, "uart1_fck", &uart1_fck, CK_443X),
- CLK(NULL, "uart2_fck", &uart2_fck, CK_443X),
- CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
- CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
- CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X),
- CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
- CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
- CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
- CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X),
- CLK(NULL, "usb_host_hs_utmi_p2_clk", &usb_host_hs_utmi_p2_clk, CK_443X),
- CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X),
- CLK(NULL, "usb_host_hs_hsic480m_p1_clk", &usb_host_hs_hsic480m_p1_clk, CK_443X),
- CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_443X),
- CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X),
- CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
- CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
- CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
- CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X),
- CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
- CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
- CLK(NULL, "usb_otg_hs_ick", &usb_otg_hs_ick, CK_443X),
- CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X),
- CLK(NULL, "usb_phy_cm_clk32k", &usb_phy_cm_clk32k, CK_443X),
- CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X),
- CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
- CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
- CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
- CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
- CLK("usbhs_tll", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
- CLK(NULL, "usim_ck", &usim_ck, CK_443X),
- CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
- CLK(NULL, "usim_fck", &usim_fck, CK_443X),
- CLK(NULL, "wd_timer2_fck", &wd_timer2_fck, CK_443X),
- CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_443X),
- CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X),
- CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck, CK_443X),
- CLK(NULL, "auxclk0_src_ck", &auxclk0_src_ck, CK_443X),
- CLK(NULL, "auxclk0_ck", &auxclk0_ck, CK_443X),
- CLK(NULL, "auxclkreq0_ck", &auxclkreq0_ck, CK_443X),
- CLK(NULL, "auxclk1_src_ck", &auxclk1_src_ck, CK_443X),
- CLK(NULL, "auxclk1_ck", &auxclk1_ck, CK_443X),
- CLK(NULL, "auxclkreq1_ck", &auxclkreq1_ck, CK_443X),
- CLK(NULL, "auxclk2_src_ck", &auxclk2_src_ck, CK_443X),
- CLK(NULL, "auxclk2_ck", &auxclk2_ck, CK_443X),
- CLK(NULL, "auxclkreq2_ck", &auxclkreq2_ck, CK_443X),
- CLK(NULL, "auxclk3_src_ck", &auxclk3_src_ck, CK_443X),
- CLK(NULL, "auxclk3_ck", &auxclk3_ck, CK_443X),
- CLK(NULL, "auxclkreq3_ck", &auxclkreq3_ck, CK_443X),
- CLK(NULL, "auxclk4_src_ck", &auxclk4_src_ck, CK_443X),
- CLK(NULL, "auxclk4_ck", &auxclk4_ck, CK_443X),
- CLK(NULL, "auxclkreq4_ck", &auxclkreq4_ck, CK_443X),
- CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_443X),
- CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
- CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X),
- CLK("omap-gpmc", "fck", &dummy_ck, CK_443X),
- CLK("omap_i2c.1", "ick", &dummy_ck, CK_443X),
- CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X),
- CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X),
- CLK("omap_i2c.4", "ick", &dummy_ck, CK_443X),
- CLK(NULL, "mailboxes_ick", &dummy_ck, CK_443X),
- CLK("omap_hsmmc.0", "ick", &dummy_ck, CK_443X),
- CLK("omap_hsmmc.1", "ick", &dummy_ck, CK_443X),
- CLK("omap_hsmmc.2", "ick", &dummy_ck, CK_443X),
- CLK("omap_hsmmc.3", "ick", &dummy_ck, CK_443X),
- CLK("omap_hsmmc.4", "ick", &dummy_ck, CK_443X),
- CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_443X),
- CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_443X),
- CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_443X),
- CLK("omap-mcbsp.4", "ick", &dummy_ck, CK_443X),
- CLK("omap2_mcspi.1", "ick", &dummy_ck, CK_443X),
- CLK("omap2_mcspi.2", "ick", &dummy_ck, CK_443X),
- CLK("omap2_mcspi.3", "ick", &dummy_ck, CK_443X),
- CLK("omap2_mcspi.4", "ick", &dummy_ck, CK_443X),
- CLK(NULL, "uart1_ick", &dummy_ck, CK_443X),
- CLK(NULL, "uart2_ick", &dummy_ck, CK_443X),
- CLK(NULL, "uart3_ick", &dummy_ck, CK_443X),
- CLK(NULL, "uart4_ick", &dummy_ck, CK_443X),
- CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X),
- CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X),
- CLK("usbhs_tll", "usbtll_fck", &dummy_ck, CK_443X),
- CLK("omap_wdt", "ick", &dummy_ck, CK_443X),
- CLK(NULL, "timer_32k_ck", &sys_32k_ck, CK_443X),
- /* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
- CLK("omap_timer.1", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.2", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.3", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.4", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.9", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.10", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.11", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("omap_timer.5", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("omap_timer.6", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("omap_timer.7", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("omap_timer.8", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("4a318000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("48032000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("48034000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("48036000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
- CLK("49038000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("4903a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("4903c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK("4903e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
- CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X),
-};
-
-int __init omap4xxx_clk_init(void)
-{
- struct omap_clk *c;
- u32 cpu_clkflg;
-
- if (cpu_is_omap443x()) {
- cpu_mask = RATE_IN_4430;
- cpu_clkflg = CK_443X;
- } else if (cpu_is_omap446x() || cpu_is_omap447x()) {
- cpu_mask = RATE_IN_4460 | RATE_IN_4430;
- cpu_clkflg = CK_446X | CK_443X;
-
- if (cpu_is_omap447x())
- pr_warn("WARNING: OMAP4470 clock data incomplete!\n");
- } else {
- return 0;
- }
-
- /*
- * Must stay commented until all OMAP SoC drivers are
- * converted to runtime PM, or drivers may start crashing
- *
- * omap2_clk_disable_clkdm_control();
- */
-
- for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
- c++)
- clk_preinit(c->lk.clk);
-
- for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
- c++)
- if (c->cpu & cpu_clkflg) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- omap2_init_clk_clkdm(c->lk.clk);
- }
-
- /* Disable autoidle on all clocks; let the PM code enable it later */
- omap_clk_disable_autoidle_all();
-
- recalculate_root_clocks();
-
- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable_init_clocks();
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index b9f3ba68148c..ef4d21bfb964 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -16,6 +16,7 @@
* OMAP3xxx clock definition files.
*/
+#include <linux/clk-private.h>
#include "clock.h"
/* clksel_rate data common to 24xx/343x */
@@ -52,6 +53,13 @@ const struct clksel_rate div_1_0_rates[] = {
{ .div = 0 },
};
+const struct clksel_rate div3_1to4_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+ { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+ { .div = 4, .val = 2, .flags = RATE_IN_4430 },
+ { .div = 0 },
+};
+
const struct clksel_rate div_1_1_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
@@ -109,14 +117,10 @@ const struct clksel_rate div31_1to31_rates[] = {
/* Clocks shared between various OMAP SoCs */
-struct clk virt_19200000_ck = {
- .name = "virt_19200000_ck",
- .ops = &clkops_null,
- .rate = 19200000,
-};
+static struct clk_ops dummy_ck_ops = {};
-struct clk virt_26000000_ck = {
- .name = "virt_26000000_ck",
- .ops = &clkops_null,
- .rate = 26000000,
+struct clk dummy_ck = {
+ .name = "dummy_clk",
+ .ops = &dummy_ck_ops,
+ .flags = CLK_IS_BASIC,
};
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 64e50465a4b5..384873580b23 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/limits.h>
#include <linux/err.h>
+#include <linux/clk-provider.h>
#include <linux/io.h>
@@ -947,35 +948,6 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
return 0;
}
-static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
-{
- unsigned long flags;
-
- if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
- return -EINVAL;
-
- spin_lock_irqsave(&clkdm->lock, flags);
-
- if (atomic_read(&clkdm->usecount) == 0) {
- spin_unlock_irqrestore(&clkdm->lock, flags);
- WARN_ON(1); /* underflow */
- return -ERANGE;
- }
-
- if (atomic_dec_return(&clkdm->usecount) > 0) {
- spin_unlock_irqrestore(&clkdm->lock, flags);
- return 0;
- }
-
- arch_clkdm->clkdm_clk_disable(clkdm);
- pwrdm_state_switch(clkdm->pwrdm.ptr);
- spin_unlock_irqrestore(&clkdm->lock, flags);
-
- pr_debug("clockdomain: %s: disabled\n", clkdm->name);
-
- return 0;
-}
-
/**
* clkdm_clk_enable - add an enabled downstream clock to this clkdm
* @clkdm: struct clockdomain *
@@ -1018,15 +990,37 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
*/
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
{
- /*
- * XXX Rewrite this code to maintain a list of enabled
- * downstream clocks for debugging purposes?
- */
+ unsigned long flags;
- if (!clk)
+ if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
return -EINVAL;
- return _clkdm_clk_hwmod_disable(clkdm);
+ spin_lock_irqsave(&clkdm->lock, flags);
+
+ /* corner case: disabling unused clocks */
+ if (__clk_get_enable_count(clk) == 0)
+ goto ccd_exit;
+
+ if (atomic_read(&clkdm->usecount) == 0) {
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ WARN_ON(1); /* underflow */
+ return -ERANGE;
+ }
+
+ if (atomic_dec_return(&clkdm->usecount) > 0) {
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ return 0;
+ }
+
+ arch_clkdm->clkdm_clk_disable(clkdm);
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
+
+ pr_debug("clockdomain: %s: disabled\n", clkdm->name);
+
+ccd_exit:
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+
+ return 0;
}
/**
@@ -1077,6 +1071,8 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
*/
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
{
+ unsigned long flags;
+
/* The clkdm attribute does not exist yet prior OMAP4 */
if (cpu_is_omap24xx() || cpu_is_omap34xx())
return 0;
@@ -1086,9 +1082,28 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
* downstream hwmods for debugging purposes?
*/
- if (!oh)
+ if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
return -EINVAL;
- return _clkdm_clk_hwmod_disable(clkdm);
+ spin_lock_irqsave(&clkdm->lock, flags);
+
+ if (atomic_read(&clkdm->usecount) == 0) {
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ WARN_ON(1); /* underflow */
+ return -ERANGE;
+ }
+
+ if (atomic_dec_return(&clkdm->usecount) > 0) {
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+ return 0;
+ }
+
+ arch_clkdm->clkdm_clk_disable(clkdm);
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
+ spin_unlock_irqrestore(&clkdm->lock, flags);
+
+ pr_debug("clockdomain: %s: disabled\n", clkdm->name);
+
+ return 0;
}
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index 11eaf16880c4..669ef51b17a8 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -59,6 +59,7 @@
/* CM_CLKSEL_MPU */
#define OMAP24XX_CLKSEL_MPU_SHIFT 0
#define OMAP24XX_CLKSEL_MPU_MASK (0x1f << 0)
+#define OMAP24XX_CLKSEL_MPU_WIDTH 5
/* CM_CLKSTCTRL_MPU */
#define OMAP24XX_AUTOSTATE_MPU_SHIFT 0
@@ -237,8 +238,10 @@
#define OMAP24XX_CLKSEL_DSS1_MASK (0x1f << 8)
#define OMAP24XX_CLKSEL_L4_SHIFT 5
#define OMAP24XX_CLKSEL_L4_MASK (0x3 << 5)
+#define OMAP24XX_CLKSEL_L4_WIDTH 2
#define OMAP24XX_CLKSEL_L3_SHIFT 0
#define OMAP24XX_CLKSEL_L3_MASK (0x1f << 0)
+#define OMAP24XX_CLKSEL_L3_WIDTH 5
/* CM_CLKSEL2_CORE */
#define OMAP24XX_CLKSEL_GPT12_SHIFT 22
@@ -363,8 +366,10 @@
#define OMAP24XX_DPLL_DIV_MASK (0xf << 8)
#define OMAP24XX_54M_SOURCE_SHIFT 5
#define OMAP24XX_54M_SOURCE_MASK (1 << 5)
+#define OMAP24XX_54M_SOURCE_WIDTH 1
#define OMAP2430_96M_SOURCE_SHIFT 4
#define OMAP2430_96M_SOURCE_MASK (1 << 4)
+#define OMAP2430_96M_SOURCE_WIDTH 1
#define OMAP24XX_48M_SOURCE_SHIFT 3
#define OMAP24XX_48M_SOURCE_MASK (1 << 3)
#define OMAP2430_ALTCLK_SOURCE_SHIFT 0
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 59598ffd8783..adf78d325804 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -81,6 +81,7 @@
/* CM_CLKSEL1_PLL_IVA2 */
#define OMAP3430_IVA2_CLK_SRC_SHIFT 19
#define OMAP3430_IVA2_CLK_SRC_MASK (0x7 << 19)
+#define OMAP3430_IVA2_CLK_SRC_WIDTH 3
#define OMAP3430_IVA2_DPLL_MULT_SHIFT 8
#define OMAP3430_IVA2_DPLL_MULT_MASK (0x7ff << 8)
#define OMAP3430_IVA2_DPLL_DIV_SHIFT 0
@@ -89,6 +90,7 @@
/* CM_CLKSEL2_PLL_IVA2 */
#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT 0
#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
+#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH 5
/* CM_CLKSTCTRL_IVA2 */
#define OMAP3430_CLKTRCTRL_IVA2_SHIFT 0
@@ -118,6 +120,7 @@
/* CM_IDLEST_PLL_MPU */
#define OMAP3430_ST_MPU_CLK_SHIFT 0
#define OMAP3430_ST_MPU_CLK_MASK (1 << 0)
+#define OMAP3430_ST_MPU_CLK_WIDTH 1
/* CM_AUTOIDLE_PLL_MPU */
#define OMAP3430_AUTO_MPU_DPLL_SHIFT 0
@@ -126,6 +129,7 @@
/* CM_CLKSEL1_PLL_MPU */
#define OMAP3430_MPU_CLK_SRC_SHIFT 19
#define OMAP3430_MPU_CLK_SRC_MASK (0x7 << 19)
+#define OMAP3430_MPU_CLK_SRC_WIDTH 3
#define OMAP3430_MPU_DPLL_MULT_SHIFT 8
#define OMAP3430_MPU_DPLL_MULT_MASK (0x7ff << 8)
#define OMAP3430_MPU_DPLL_DIV_SHIFT 0
@@ -134,6 +138,7 @@
/* CM_CLKSEL2_PLL_MPU */
#define OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT 0
#define OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
+#define OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH 5
/* CM_CLKSTCTRL_MPU */
#define OMAP3430_CLKTRCTRL_MPU_SHIFT 0
@@ -345,10 +350,13 @@
#define OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK (0x3 << 4)
#define OMAP3430_CLKSEL_L4_SHIFT 2
#define OMAP3430_CLKSEL_L4_MASK (0x3 << 2)
+#define OMAP3430_CLKSEL_L4_WIDTH 2
#define OMAP3430_CLKSEL_L3_SHIFT 0
#define OMAP3430_CLKSEL_L3_MASK (0x3 << 0)
+#define OMAP3430_CLKSEL_L3_WIDTH 2
#define OMAP3630_CLKSEL_96M_SHIFT 12
#define OMAP3630_CLKSEL_96M_MASK (0x3 << 12)
+#define OMAP3630_CLKSEL_96M_WIDTH 2
/* CM_CLKSTCTRL_CORE */
#define OMAP3430ES1_CLKTRCTRL_D2D_SHIFT 4
@@ -452,6 +460,7 @@
#define OMAP3430ES2_CLKSEL_USIMOCP_MASK (0xf << 3)
#define OMAP3430_CLKSEL_RM_SHIFT 1
#define OMAP3430_CLKSEL_RM_MASK (0x3 << 1)
+#define OMAP3430_CLKSEL_RM_WIDTH 2
#define OMAP3430_CLKSEL_GPT1_SHIFT 0
#define OMAP3430_CLKSEL_GPT1_MASK (1 << 0)
@@ -520,14 +529,17 @@
/* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT 27
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK (0x1f << 27)
+#define OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH 5
#define OMAP3430_CORE_DPLL_MULT_SHIFT 16
#define OMAP3430_CORE_DPLL_MULT_MASK (0x7ff << 16)
#define OMAP3430_CORE_DPLL_DIV_SHIFT 8
#define OMAP3430_CORE_DPLL_DIV_MASK (0x7f << 8)
#define OMAP3430_SOURCE_96M_SHIFT 6
#define OMAP3430_SOURCE_96M_MASK (1 << 6)
+#define OMAP3430_SOURCE_96M_WIDTH 1
#define OMAP3430_SOURCE_54M_SHIFT 5
#define OMAP3430_SOURCE_54M_MASK (1 << 5)
+#define OMAP3430_SOURCE_54M_WIDTH 1
#define OMAP3430_SOURCE_48M_SHIFT 3
#define OMAP3430_SOURCE_48M_MASK (1 << 3)
@@ -545,7 +557,9 @@
/* CM_CLKSEL3_PLL */
#define OMAP3430_DIV_96M_SHIFT 0
#define OMAP3430_DIV_96M_MASK (0x1f << 0)
+#define OMAP3430_DIV_96M_WIDTH 5
#define OMAP3630_DIV_96M_MASK (0x3f << 0)
+#define OMAP3630_DIV_96M_WIDTH 6
/* CM_CLKSEL4_PLL */
#define OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT 8
@@ -556,12 +570,14 @@
/* CM_CLKSEL5_PLL */
#define OMAP3430ES2_DIV_120M_SHIFT 0
#define OMAP3430ES2_DIV_120M_MASK (0x1f << 0)
+#define OMAP3430ES2_DIV_120M_WIDTH 5
/* CM_CLKOUT_CTRL */
#define OMAP3430_CLKOUT2_EN_SHIFT 7
#define OMAP3430_CLKOUT2_EN_MASK (1 << 7)
#define OMAP3430_CLKOUT2_DIV_SHIFT 3
#define OMAP3430_CLKOUT2_DIV_MASK (0x7 << 3)
+#define OMAP3430_CLKOUT2_DIV_WIDTH 3
#define OMAP3430_CLKOUT2SOURCE_SHIFT 0
#define OMAP3430_CLKOUT2SOURCE_MASK (0x3 << 0)
@@ -592,10 +608,14 @@
/* CM_CLKSEL_DSS */
#define OMAP3430_CLKSEL_TV_SHIFT 8
#define OMAP3430_CLKSEL_TV_MASK (0x1f << 8)
+#define OMAP3430_CLKSEL_TV_WIDTH 5
#define OMAP3630_CLKSEL_TV_MASK (0x3f << 8)
+#define OMAP3630_CLKSEL_TV_WIDTH 6
#define OMAP3430_CLKSEL_DSS1_SHIFT 0
#define OMAP3430_CLKSEL_DSS1_MASK (0x1f << 0)
+#define OMAP3430_CLKSEL_DSS1_WIDTH 5
#define OMAP3630_CLKSEL_DSS1_MASK (0x3f << 0)
+#define OMAP3630_CLKSEL_DSS1_WIDTH 6
/* CM_SLEEPDEP_DSS specific bits */
@@ -623,7 +643,9 @@
/* CM_CLKSEL_CAM */
#define OMAP3430_CLKSEL_CAM_SHIFT 0
#define OMAP3430_CLKSEL_CAM_MASK (0x1f << 0)
+#define OMAP3430_CLKSEL_CAM_WIDTH 5
#define OMAP3630_CLKSEL_CAM_MASK (0x3f << 0)
+#define OMAP3630_CLKSEL_CAM_WIDTH 6
/* CM_SLEEPDEP_CAM specific bits */
@@ -721,21 +743,30 @@
/* CM_CLKSEL1_EMU */
#define OMAP3430_DIV_DPLL4_SHIFT 24
#define OMAP3430_DIV_DPLL4_MASK (0x1f << 24)
+#define OMAP3430_DIV_DPLL4_WIDTH 5
#define OMAP3630_DIV_DPLL4_MASK (0x3f << 24)
+#define OMAP3630_DIV_DPLL4_WIDTH 6
#define OMAP3430_DIV_DPLL3_SHIFT 16
#define OMAP3430_DIV_DPLL3_MASK (0x1f << 16)
+#define OMAP3430_DIV_DPLL3_WIDTH 5
#define OMAP3430_CLKSEL_TRACECLK_SHIFT 11
#define OMAP3430_CLKSEL_TRACECLK_MASK (0x7 << 11)
+#define OMAP3430_CLKSEL_TRACECLK_WIDTH 3
#define OMAP3430_CLKSEL_PCLK_SHIFT 8
#define OMAP3430_CLKSEL_PCLK_MASK (0x7 << 8)
+#define OMAP3430_CLKSEL_PCLK_WIDTH 3
#define OMAP3430_CLKSEL_PCLKX2_SHIFT 6
#define OMAP3430_CLKSEL_PCLKX2_MASK (0x3 << 6)
+#define OMAP3430_CLKSEL_PCLKX2_WIDTH 2
#define OMAP3430_CLKSEL_ATCLK_SHIFT 4
#define OMAP3430_CLKSEL_ATCLK_MASK (0x3 << 4)
+#define OMAP3430_CLKSEL_ATCLK_WIDTH 2
#define OMAP3430_TRACE_MUX_CTRL_SHIFT 2
#define OMAP3430_TRACE_MUX_CTRL_MASK (0x3 << 2)
+#define OMAP3430_TRACE_MUX_CTRL_WIDTH 2
#define OMAP3430_MUX_CTRL_SHIFT 0
#define OMAP3430_MUX_CTRL_MASK (0x3 << 0)
+#define OMAP3430_MUX_CTRL_WIDTH 2
/* CM_CLKSTCTRL_EMU */
#define OMAP3430_CLKTRCTRL_EMU_SHIFT 0
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h
index 98e6b3c9cd9b..bfbd16fe9151 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h
@@ -108,6 +108,7 @@ extern void omap2xxx_cm_apll96_disable(void);
/* CM_CLKSEL_GFX */
#define OMAP_CLKSEL_GFX_SHIFT 0
#define OMAP_CLKSEL_GFX_MASK (0x7 << 0)
+#define OMAP_CLKSEL_GFX_WIDTH 3
/* CM_ICLKEN_GFX */
#define OMAP_EN_GFX_SHIFT 0
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index 4ca8747b3cc9..3d944d3263d2 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -201,6 +201,7 @@
#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249
#define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A
/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 3cff7dc514df..c67a731cfbb7 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -24,7 +24,7 @@
#include <asm/mach-types.h>
#include <asm/mach/map.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "iomap.h"
#include "omap_hwmod.h"
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e5aba58da5d2..612b98249873 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -28,7 +28,7 @@
#include <linux/init.h>
#include <linux/device.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "soc.h"
#include "omap_hwmod.h"
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index eacf51f2bc27..fafb28c0dcbc 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -29,6 +29,7 @@
#include <linux/clkdev.h>
#include "soc.h"
+#include "clockdomain.h"
#include "clock.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
@@ -42,7 +43,7 @@
/* Private functions */
/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
-static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
+static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
{
const struct dpll_data *dd;
u32 v;
@@ -56,7 +57,7 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
}
/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
-static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
+static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
{
const struct dpll_data *dd;
int i = 0;
@@ -64,7 +65,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
const char *clk_name;
dd = clk->dpll_data;
- clk_name = __clk_get_name(clk);
+ clk_name = __clk_get_name(clk->hw.clk);
state <<= __ffs(dd->idlest_mask);
@@ -88,7 +89,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
}
/* From 3430 TRM ES2 4.7.6.2 */
-static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
+static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
{
unsigned long fint;
u16 f = 0;
@@ -133,14 +134,14 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
* locked successfully, return 0; if the DPLL did not lock in the time
* allotted, or DPLL3 was passed in, return -EINVAL.
*/
-static int _omap3_noncore_dpll_lock(struct clk *clk)
+static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
{
const struct dpll_data *dd;
u8 ai;
u8 state = 1;
int r = 0;
- pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk));
+ pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
dd = clk->dpll_data;
state <<= __ffs(dd->idlest_mask);
@@ -178,7 +179,7 @@ done:
* DPLL3 was passed in, or the DPLL does not support low-power bypass,
* return -EINVAL.
*/
-static int _omap3_noncore_dpll_bypass(struct clk *clk)
+static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
{
int r;
u8 ai;
@@ -187,7 +188,7 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
return -EINVAL;
pr_debug("clock: configuring DPLL %s for low-power bypass\n",
- __clk_get_name(clk));
+ __clk_get_name(clk->hw.clk));
ai = omap3_dpll_autoidle_read(clk);
@@ -210,14 +211,14 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
* code. If DPLL3 was passed in, or the DPLL does not support
* low-power stop, return -EINVAL; otherwise, return 0.
*/
-static int _omap3_noncore_dpll_stop(struct clk *clk)
+static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
{
u8 ai;
if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
return -EINVAL;
- pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk));
+ pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
ai = omap3_dpll_autoidle_read(clk);
@@ -241,11 +242,11 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
* XXX This code is not needed for 3430/AM35xx; can it be optimized
* out in non-multi-OMAP builds for those chips?
*/
-static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
+static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
{
unsigned long fint, clkinp; /* watch out for overflow */
- clkinp = __clk_get_rate(__clk_get_parent(clk));
+ clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
fint = (clkinp / n) * m;
if (fint < 1000000000)
@@ -266,12 +267,12 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
* XXX This code is not needed for 3430/AM35xx; can it be optimized
* out in non-multi-OMAP builds for those chips?
*/
-static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
+static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
{
unsigned long clkinp, sd; /* watch out for overflow */
int mod1, mod2;
- clkinp = __clk_get_rate(__clk_get_parent(clk));
+ clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
/*
* target sigma-delta to near 250MHz
@@ -298,7 +299,8 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
* Program the DPLL with the supplied M, N values, and wait for the DPLL to
* lock.. Returns -EINVAL upon error, or 0 upon success.
*/
-static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
+static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
+ u16 freqsel)
{
struct dpll_data *dd = clk->dpll_data;
u8 dco, sd_div;
@@ -355,8 +357,10 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
*
* Recalculate and propagate the DPLL rate.
*/
-unsigned long omap3_dpll_recalc(struct clk *clk)
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
return omap2_get_dpll_rate(clk);
}
@@ -376,8 +380,9 @@ unsigned long omap3_dpll_recalc(struct clk *clk)
* support low-power stop, or if the DPLL took too long to enter
* bypass or lock, return -EINVAL; otherwise, return 0.
*/
-int omap3_noncore_dpll_enable(struct clk *clk)
+int omap3_noncore_dpll_enable(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int r;
struct dpll_data *dd;
struct clk *parent;
@@ -386,22 +391,26 @@ int omap3_noncore_dpll_enable(struct clk *clk)
if (!dd)
return -EINVAL;
- parent = __clk_get_parent(clk);
+ if (clk->clkdm) {
+ r = clkdm_clk_enable(clk->clkdm, hw->clk);
+ if (r) {
+ WARN(1,
+ "%s: could not enable %s's clockdomain %s: %d\n",
+ __func__, __clk_get_name(hw->clk),
+ clk->clkdm->name, r);
+ return r;
+ }
+ }
+
+ parent = __clk_get_parent(hw->clk);
- if (__clk_get_rate(clk) == __clk_get_rate(dd->clk_bypass)) {
+ if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
WARN_ON(parent != dd->clk_bypass);
r = _omap3_noncore_dpll_bypass(clk);
} else {
WARN_ON(parent != dd->clk_ref);
r = _omap3_noncore_dpll_lock(clk);
}
- /*
- *FIXME: this is dubious - if clk->rate has changed, what about
- * propagating?
- */
- if (!r)
- clk->rate = (clk->recalc) ? clk->recalc(clk) :
- omap2_get_dpll_rate(clk);
return r;
}
@@ -413,9 +422,13 @@ int omap3_noncore_dpll_enable(struct clk *clk)
* Instructs a non-CORE DPLL to enter low-power stop. This function is
* intended for use in struct clkops. No return value.
*/
-void omap3_noncore_dpll_disable(struct clk *clk)
+void omap3_noncore_dpll_disable(struct clk_hw *hw)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
_omap3_noncore_dpll_stop(clk);
+ if (clk->clkdm)
+ clkdm_clk_disable(clk->clkdm, hw->clk);
}
@@ -432,80 +445,72 @@ void omap3_noncore_dpll_disable(struct clk *clk)
* target rate if it hasn't been done already, then program and lock
* the DPLL. Returns -EINVAL upon error, or 0 upon success.
*/
-int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct clk *new_parent = NULL;
- unsigned long hw_rate, bypass_rate;
u16 freqsel = 0;
struct dpll_data *dd;
int ret;
- if (!clk || !rate)
+ if (!hw || !rate)
return -EINVAL;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
- hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
- if (rate == hw_rate)
- return 0;
-
- /*
- * Ensure both the bypass and ref clocks are enabled prior to
- * doing anything; we need the bypass clock running to reprogram
- * the DPLL.
- */
- omap2_clk_enable(dd->clk_bypass);
- omap2_clk_enable(dd->clk_ref);
+ __clk_prepare(dd->clk_bypass);
+ clk_enable(dd->clk_bypass);
+ __clk_prepare(dd->clk_ref);
+ clk_enable(dd->clk_ref);
- bypass_rate = __clk_get_rate(dd->clk_bypass);
- if (bypass_rate == rate &&
- (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
- pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
+ if (__clk_get_rate(dd->clk_bypass) == rate &&
+ (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+ pr_debug("%s: %s: set rate: entering bypass.\n",
+ __func__, __clk_get_name(hw->clk));
ret = _omap3_noncore_dpll_bypass(clk);
if (!ret)
new_parent = dd->clk_bypass;
} else {
if (dd->last_rounded_rate != rate)
- rate = clk->round_rate(clk, rate);
+ rate = __clk_round_rate(hw->clk, rate);
if (dd->last_rounded_rate == 0)
return -EINVAL;
/* No freqsel on OMAP4 and OMAP3630 */
- if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
+ if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
freqsel = _omap3_dpll_compute_freqsel(clk,
dd->last_rounded_n);
if (!freqsel)
WARN_ON(1);
}
- pr_debug("clock: %s: set rate: locking rate to %lu.\n",
- __clk_get_name(clk), rate);
+ pr_debug("%s: %s: set rate: locking rate to %lu.\n",
+ __func__, __clk_get_name(hw->clk), rate);
ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
- dd->last_rounded_n, freqsel);
+ dd->last_rounded_n, freqsel);
if (!ret)
new_parent = dd->clk_ref;
}
- if (!ret) {
- /*
- * Switch the parent clock in the hierarchy, and make sure
- * that the new parent's usecount is correct. Note: we
- * enable the new parent before disabling the old to avoid
- * any unnecessary hardware disable->enable transitions.
- */
- if (clk->usecount) {
- omap2_clk_enable(new_parent);
- omap2_clk_disable(clk->parent);
- }
- clk_reparent(clk, new_parent);
- clk->rate = rate;
- }
- omap2_clk_disable(dd->clk_ref);
- omap2_clk_disable(dd->clk_bypass);
+ /*
+ * FIXME - this is all wrong. common code handles reparenting and
+ * migrating prepare/enable counts. dplls should be a multiplexer
+ * clock and this should be a set_parent operation so that all of that
+ * stuff is inherited for free
+ */
+
+ if (!ret)
+ __clk_reparent(hw->clk, new_parent);
+
+ clk_disable(dd->clk_ref);
+ __clk_unprepare(dd->clk_ref);
+ clk_disable(dd->clk_bypass);
+ __clk_unprepare(dd->clk_bypass);
return 0;
}
@@ -520,7 +525,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
* -EINVAL if passed a null pointer or if the struct clk does not
* appear to refer to a DPLL.
*/
-u32 omap3_dpll_autoidle_read(struct clk *clk)
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
{
const struct dpll_data *dd;
u32 v;
@@ -549,7 +554,7 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
* OMAP3430. The DPLL will enter low-power stop when its downstream
* clocks are gated. No return value.
*/
-void omap3_dpll_allow_idle(struct clk *clk)
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
{
const struct dpll_data *dd;
u32 v;
@@ -559,11 +564,8 @@ void omap3_dpll_allow_idle(struct clk *clk)
dd = clk->dpll_data;
- if (!dd->autoidle_reg) {
- pr_debug("clock: DPLL %s: autoidle not supported\n",
- __clk_get_name(clk));
+ if (!dd->autoidle_reg)
return;
- }
/*
* REVISIT: CORE DPLL can optionally enter low-power bypass
@@ -583,7 +585,7 @@ void omap3_dpll_allow_idle(struct clk *clk)
*
* Disable DPLL automatic idle control. No return value.
*/
-void omap3_dpll_deny_idle(struct clk *clk)
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
{
const struct dpll_data *dd;
u32 v;
@@ -593,11 +595,8 @@ void omap3_dpll_deny_idle(struct clk *clk)
dd = clk->dpll_data;
- if (!dd->autoidle_reg) {
- pr_debug("clock: DPLL %s: autoidle not supported\n",
- __clk_get_name(clk));
+ if (!dd->autoidle_reg)
return;
- }
v = __raw_readl(dd->autoidle_reg);
v &= ~dd->autoidle_mask;
@@ -615,18 +614,25 @@ void omap3_dpll_deny_idle(struct clk *clk)
* Using parent clock DPLL data, look up DPLL state. If locked, set our
* rate to the dpll_clk * 2; otherwise, just use dpll_clk.
*/
-unsigned long omap3_clkoutx2_recalc(struct clk *clk)
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
{
const struct dpll_data *dd;
unsigned long rate;
u32 v;
- struct clk *pclk;
- unsigned long parent_rate;
+ struct clk_hw_omap *pclk = NULL;
+ struct clk *parent;
/* Walk up the parents of clk, looking for a DPLL */
- pclk = __clk_get_parent(clk);
- while (pclk && !pclk->dpll_data)
- pclk = __clk_get_parent(pclk);
+ do {
+ do {
+ parent = __clk_get_parent(hw->clk);
+ hw = __clk_get_hw(parent);
+ } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+ if (!hw)
+ break;
+ pclk = to_clk_hw_omap(hw);
+ } while (pclk && !pclk->dpll_data);
/* clk does not have a DPLL as a parent? error in the clock data */
if (!pclk) {
@@ -638,7 +644,6 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
WARN_ON(!dd->enable_mask);
- parent_rate = __clk_get_rate(__clk_get_parent(clk));
v = __raw_readl(dd->control_reg) & dd->enable_mask;
v >>= __ffs(dd->enable_mask);
if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
@@ -649,15 +654,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
}
/* OMAP3/4 non-CORE DPLL clkops */
-
-const struct clkops clkops_omap3_noncore_dpll_ops = {
- .enable = omap3_noncore_dpll_enable,
- .disable = omap3_noncore_dpll_disable,
- .allow_idle = omap3_dpll_allow_idle,
- .deny_idle = omap3_dpll_deny_idle,
-};
-
-const struct clkops clkops_omap3_core_dpll_ops = {
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
.allow_idle = omap3_dpll_allow_idle,
.deny_idle = omap3_dpll_deny_idle,
};
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 5854da168a9c..d3326c474fdc 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -21,7 +21,7 @@
#include "cm-regbits-44xx.h"
/* Supported only on OMAP4 */
-int omap4_dpllmx_gatectrl_read(struct clk *clk)
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
{
u32 v;
u32 mask;
@@ -40,7 +40,7 @@ int omap4_dpllmx_gatectrl_read(struct clk *clk)
return v;
}
-void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
{
u32 v;
u32 mask;
@@ -58,7 +58,7 @@ void omap4_dpllmx_allow_gatectrl(struct clk *clk)
__raw_writel(v, clk->clksel_reg);
}
-void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
{
u32 v;
u32 mask;
@@ -76,9 +76,9 @@ void omap4_dpllmx_deny_gatectrl(struct clk *clk)
__raw_writel(v, clk->clksel_reg);
}
-const struct clkops clkops_omap4_dpllmx_ops = {
+const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
.allow_idle = omap4_dpllmx_allow_gatectrl,
- .deny_idle = omap4_dpllmx_deny_gatectrl,
+ .deny_idle = omap4_dpllmx_deny_gatectrl,
};
/**
@@ -90,8 +90,10 @@ const struct clkops clkops_omap4_dpllmx_ops = {
* OMAP4 ABE DPLL. Returns the DPLL's output rate (before M-dividers)
* upon success, or 0 upon error.
*/
-unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 v;
unsigned long rate;
struct dpll_data *dd;
@@ -123,8 +125,11 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
* M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
* ~0 if an error occurred in omap2_dpll_round_rate().
*/
-long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+ unsigned long target_rate,
+ unsigned long *parent_rate)
{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 v;
struct dpll_data *dd;
long r;
@@ -140,7 +145,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
if (v)
target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
- r = omap2_dpll_round_rate(clk, target_rate);
+ r = omap2_dpll_round_rate(hw, target_rate, NULL);
if (r == ~0)
return r;
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 8607735b3ab3..db969a5c4998 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -52,27 +52,27 @@ static int omap2_nand_gpmc_retime(
memset(&t, 0, sizeof(t));
t.sync_clk = gpmc_t->sync_clk;
- t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on);
- t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on);
+ t.cs_on = gpmc_t->cs_on;
+ t.adv_on = gpmc_t->adv_on;
/* Read */
- t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off);
+ t.adv_rd_off = gpmc_t->adv_rd_off;
t.oe_on = t.adv_on;
- t.access = gpmc_round_ns_to_ticks(gpmc_t->access);
- t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off);
- t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off);
- t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle);
+ t.access = gpmc_t->access;
+ t.oe_off = gpmc_t->oe_off;
+ t.cs_rd_off = gpmc_t->cs_rd_off;
+ t.rd_cycle = gpmc_t->rd_cycle;
/* Write */
- t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off);
+ t.adv_wr_off = gpmc_t->adv_wr_off;
t.we_on = t.oe_on;
if (cpu_is_omap34xx()) {
- t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus);
- t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access);
+ t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus;
+ t.wr_access = gpmc_t->wr_access;
}
- t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off);
- t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off);
- t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle);
+ t.we_off = gpmc_t->we_off;
+ t.cs_wr_off = gpmc_t->cs_wr_off;
+ t.wr_cycle = gpmc_t->wr_cycle;
/* Configure GPMC */
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index d102183ed9a5..94a349e4dc96 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -33,7 +33,6 @@
static unsigned onenand_flags;
static unsigned latency;
-static int fclk_offset;
static struct omap_onenand_platform_data *gpmc_onenand_data;
@@ -50,6 +49,7 @@ static struct platform_device gpmc_onenand_device = {
static struct gpmc_timings omap2_onenand_calc_async_timings(void)
{
+ struct gpmc_device_timings dev_t;
struct gpmc_timings t;
const int t_cer = 15;
@@ -59,35 +59,24 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
const int t_aa = 76;
const int t_oe = 20;
const int t_cez = 20; /* max of t_cez, t_oez */
- const int t_ds = 30;
const int t_wpl = 40;
const int t_wph = 30;
- memset(&t, 0, sizeof(t));
- t.sync_clk = 0;
- t.cs_on = 0;
- t.adv_on = 0;
-
- /* Read */
- t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
- t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
- t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
- t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
- t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
- t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
- t.cs_rd_off = t.oe_off;
- t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
-
- /* Write */
- t.adv_wr_off = t.adv_rd_off;
- t.we_on = t.oe_on;
- if (cpu_is_omap34xx()) {
- t.wr_data_mux_bus = t.we_on;
- t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
- }
- t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
- t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
- t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
+ memset(&dev_t, 0, sizeof(dev_t));
+
+ dev_t.mux = true;
+ dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
+ dev_t.t_avdp_w = dev_t.t_avdp_r;
+ dev_t.t_aavdh = t_aavdh * 1000;
+ dev_t.t_aa = t_aa * 1000;
+ dev_t.t_ce = t_ce * 1000;
+ dev_t.t_oe = t_oe * 1000;
+ dev_t.t_cez_r = t_cez * 1000;
+ dev_t.t_cez_w = dev_t.t_cez_r;
+ dev_t.t_wpl = t_wpl * 1000;
+ dev_t.t_wph = t_wph * 1000;
+
+ gpmc_calc_timings(&t, &dev_t);
return t;
}
@@ -173,18 +162,15 @@ static struct gpmc_timings
omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
int freq)
{
+ struct gpmc_device_timings dev_t;
struct gpmc_timings t;
const int t_cer = 15;
const int t_avdp = 12;
const int t_cez = 20; /* max of t_cez, t_oez */
- const int t_ds = 30;
const int t_wpl = 40;
const int t_wph = 30;
int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
- u32 reg;
- int div, fclk_offset_ns, gpmc_clk_ns;
- int ticks_cez;
- int cs = cfg->cs;
+ int div, gpmc_clk_ns;
if (cfg->flags & ONENAND_SYNC_READ)
onenand_flags = ONENAND_FLAG_SYNCREAD;
@@ -251,77 +237,35 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
latency = 4;
/* Set synchronous read timings */
- memset(&t, 0, sizeof(t));
-
- if (div == 1) {
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
- reg |= (1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
- reg |= (1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
- reg |= (1 << 7);
- reg |= (1 << 23);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
- } else {
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
- reg &= ~(1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
- reg &= ~(1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
- reg &= ~(1 << 7);
- reg &= ~(1 << 23);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
- }
+ memset(&dev_t, 0, sizeof(dev_t));
- t.sync_clk = min_gpmc_clk_period;
- t.cs_on = 0;
- t.adv_on = 0;
- fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
- fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
- t.page_burst_access = gpmc_clk_ns;
-
- /* Read */
- t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
- t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
- /* Force at least 1 clk between AVD High to OE Low */
- if (t.oe_on <= t.adv_rd_off)
- t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
- t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
- t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
- t.cs_rd_off = t.oe_off;
- ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
- t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
- ticks_cez);
-
- /* Write */
+ dev_t.mux = true;
+ dev_t.sync_read = true;
if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
- t.adv_wr_off = t.adv_rd_off;
- t.we_on = 0;
- t.we_off = t.cs_rd_off;
- t.cs_wr_off = t.cs_rd_off;
- t.wr_cycle = t.rd_cycle;
- if (cpu_is_omap34xx()) {
- t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
- gpmc_ps_to_ticks(min_gpmc_clk_period +
- t_rdyo * 1000));
- t.wr_access = t.access;
- }
+ dev_t.sync_write = true;
} else {
- t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
- t_avdp, t_cer));
- t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
- t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
- t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
- t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
- if (cpu_is_omap34xx()) {
- t.wr_data_mux_bus = t.we_on;
- t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
- }
+ dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
+ dev_t.t_wpl = t_wpl * 1000;
+ dev_t.t_wph = t_wph * 1000;
+ dev_t.t_aavdh = t_aavdh * 1000;
}
+ dev_t.ce_xdelay = true;
+ dev_t.avd_xdelay = true;
+ dev_t.oe_xdelay = true;
+ dev_t.we_xdelay = true;
+ dev_t.clk = min_gpmc_clk_period;
+ dev_t.t_bacc = dev_t.clk;
+ dev_t.t_ces = t_ces * 1000;
+ dev_t.t_avds = t_avds * 1000;
+ dev_t.t_avdh = t_avdh * 1000;
+ dev_t.t_ach = t_ach * 1000;
+ dev_t.cyc_iaa = (latency + 1);
+ dev_t.t_cez_r = t_cez * 1000;
+ dev_t.t_cez_w = dev_t.t_cez_r;
+ dev_t.cyc_aavdh_oe = 1;
+ dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
+
+ gpmc_calc_timings(&t, &dev_t);
return t;
}
@@ -338,7 +282,6 @@ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
(sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
(sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
(sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
- GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
GPMC_CONFIG1_PAGE_LEN(2) |
(cpu_is_omap34xx() ? 0 :
(GPMC_CONFIG1_WAIT_READ_MON |
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index 6eed907d594c..11d0b756f098 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -58,6 +58,7 @@ static struct platform_device gpmc_smc91x_device = {
static int smc91c96_gpmc_retime(void)
{
struct gpmc_timings t;
+ struct gpmc_device_timings dev_t;
const int t3 = 10; /* Figure 12.2 read and 12.4 write */
const int t4_r = 20; /* Figure 12.2 read */
const int t4_w = 5; /* Figure 12.4 write */
@@ -68,32 +69,6 @@ static int smc91c96_gpmc_retime(void)
const int t20 = 185; /* Figure 12.2 read and 12.4 write */
u32 l;
- memset(&t, 0, sizeof(t));
-
- /* Read timings */
- t.cs_on = 0;
- t.adv_on = t.cs_on;
- t.oe_on = t.adv_on + t3;
- t.access = t.oe_on + t5;
- t.oe_off = t.access;
- t.adv_rd_off = t.oe_off + max(t4_r, t6);
- t.cs_rd_off = t.oe_off;
- t.rd_cycle = t20 - t.oe_on;
-
- /* Write timings */
- t.we_on = t.adv_on + t3;
-
- if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) {
- t.wr_data_mux_bus = t.we_on;
- t.we_off = t.wr_data_mux_bus + t7;
- } else
- t.we_off = t.we_on + t7;
- if (cpu_is_omap34xx())
- t.wr_access = t.we_off;
- t.adv_wr_off = t.we_off + max(t4_w, t8);
- t.cs_wr_off = t.we_off + t4_w;
- t.wr_cycle = t20 - t.we_on;
-
l = GPMC_CONFIG1_DEVICESIZE_16;
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
l |= GPMC_CONFIG1_MUXADDDATA;
@@ -115,6 +90,22 @@ static int smc91c96_gpmc_retime(void)
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
return 0;
+ memset(&dev_t, 0, sizeof(dev_t));
+
+ dev_t.t_oeasu = t3 * 1000;
+ dev_t.t_oe = t5 * 1000;
+ dev_t.t_cez_r = t4_r * 1000;
+ dev_t.t_oez = t6 * 1000;
+ dev_t.t_rd_cycle = (t20 - t3) * 1000;
+
+ dev_t.t_weasu = t3 * 1000;
+ dev_t.t_wpl = t7 * 1000;
+ dev_t.t_wph = t8 * 1000;
+ dev_t.t_cez_w = t4_w * 1000;
+ dev_t.t_wr_cycle = (t20 - t3) * 1000;
+
+ gpmc_calc_timings(&t, &dev_t);
+
return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index bf6117c32f4b..65468f6d7f0e 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -74,6 +74,13 @@
#define GPMC_ECC_CTRL_ECCREG8 0x008
#define GPMC_ECC_CTRL_ECCREG9 0x009
+#define GPMC_CONFIG2_CSEXTRADELAY BIT(7)
+#define GPMC_CONFIG3_ADVEXTRADELAY BIT(7)
+#define GPMC_CONFIG4_OEEXTRADELAY BIT(7)
+#define GPMC_CONFIG4_WEEXTRADELAY BIT(23)
+#define GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN BIT(6)
+#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN BIT(7)
+
#define GPMC_CS0_OFFSET 0x60
#define GPMC_CS_SIZE 0x30
#define GPMC_BCH_SIZE 0x10
@@ -223,6 +230,51 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
return ticks * gpmc_get_fclk_period() / 1000;
}
+static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
+{
+ return ticks * gpmc_get_fclk_period();
+}
+
+static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps)
+{
+ unsigned long ticks = gpmc_ps_to_ticks(time_ps);
+
+ return ticks * gpmc_get_fclk_period();
+}
+
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+ u32 l;
+
+ l = gpmc_cs_read_reg(cs, reg);
+ if (value)
+ l |= mask;
+ else
+ l &= ~mask;
+ gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_TIME_PARA_GRAN,
+ p->time_para_granularity);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+ GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+ GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+ GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+ GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+ GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+ p->cycle2cyclesamecsen);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+ GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+ p->cycle2cyclediffcsen);
+}
+
#ifdef DEBUG
static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
int time, const char *name)
@@ -316,6 +368,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
+ GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
+ GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+
+ GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
+ GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
+
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
if (gpmc_capability & GPMC_HAS_WR_ACCESS)
@@ -335,6 +393,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
}
+ gpmc_cs_bool_timings(cs, &t->bool_timings);
+
return 0;
}
@@ -748,6 +808,319 @@ static int __devinit gpmc_mem_init(void)
return 0;
}
+static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
+{
+ u32 temp;
+ int div;
+
+ div = gpmc_calc_divider(sync_clk);
+ temp = gpmc_ps_to_ticks(time_ps);
+ temp = (temp + div - 1) / div;
+ return gpmc_ticks_to_ps(temp * div);
+}
+
+/* XXX: can the cycles be avoided ? */
+static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_rd_off */
+ temp = dev_t->t_avdp_r;
+ /* XXX: mux check required ? */
+ if (mux) {
+ /* XXX: t_avdp not to be required for sync, only added for tusb
+ * this indirectly necessitates requirement of t_avdp_r and
+ * t_avdp_w instead of having a single t_avdp
+ */
+ temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_avdh);
+ temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+ }
+ gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+ /* oe_on */
+ temp = dev_t->t_oeasu; /* XXX: remove this ? */
+ if (mux) {
+ temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_ach);
+ temp = max_t(u32, temp, gpmc_t->adv_rd_off +
+ gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe));
+ }
+ gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+ /* access */
+ /* XXX: any scope for improvement ?, by combining oe_on
+ * and clk_activation, need to check whether
+ * access = clk_activation + round to sync clk ?
+ */
+ temp = max_t(u32, dev_t->t_iaa, dev_t->cyc_iaa * gpmc_t->sync_clk);
+ temp += gpmc_t->clk_activation;
+ if (dev_t->cyc_oe)
+ temp = max_t(u32, temp, gpmc_t->oe_on +
+ gpmc_ticks_to_ps(dev_t->cyc_oe));
+ gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+ gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+ gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+ /* rd_cycle */
+ temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez);
+ temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) +
+ gpmc_t->access;
+ /* XXX: barter t_ce_rdyz with t_cez_r ? */
+ if (dev_t->t_ce_rdyz)
+ temp = max_t(u32, temp, gpmc_t->cs_rd_off + dev_t->t_ce_rdyz);
+ gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+ return 0;
+}
+
+static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_wr_off */
+ temp = dev_t->t_avdp_w;
+ if (mux) {
+ temp = max_t(u32, temp,
+ gpmc_t->clk_activation + dev_t->t_avdh);
+ temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+ }
+ gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+ /* wr_data_mux_bus */
+ temp = max_t(u32, dev_t->t_weasu,
+ gpmc_t->clk_activation + dev_t->t_rdyo);
+ /* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?,
+ * and in that case remember to handle we_on properly
+ */
+ if (mux) {
+ temp = max_t(u32, temp,
+ gpmc_t->adv_wr_off + dev_t->t_aavdh);
+ temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+ gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+ }
+ gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+ /* we_on */
+ if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+ gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+ else
+ gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+ /* wr_access */
+ /* XXX: gpmc_capability check reqd ? , even if not, will not harm */
+ gpmc_t->wr_access = gpmc_t->access;
+
+ /* we_off */
+ temp = gpmc_t->we_on + dev_t->t_wpl;
+ temp = max_t(u32, temp,
+ gpmc_t->wr_access + gpmc_ticks_to_ps(1));
+ temp = max_t(u32, temp,
+ gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl));
+ gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+ gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+ dev_t->t_wph);
+
+ /* wr_cycle */
+ temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk);
+ temp += gpmc_t->wr_access;
+ /* XXX: barter t_ce_rdyz with t_cez_w ? */
+ if (dev_t->t_ce_rdyz)
+ temp = max_t(u32, temp,
+ gpmc_t->cs_wr_off + dev_t->t_ce_rdyz);
+ gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+ return 0;
+}
+
+static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_rd_off */
+ temp = dev_t->t_avdp_r;
+ if (mux)
+ temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+ gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+ /* oe_on */
+ temp = dev_t->t_oeasu;
+ if (mux)
+ temp = max_t(u32, temp,
+ gpmc_t->adv_rd_off + dev_t->t_aavdh);
+ gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+ /* access */
+ temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */
+ gpmc_t->oe_on + dev_t->t_oe);
+ temp = max_t(u32, temp,
+ gpmc_t->cs_on + dev_t->t_ce);
+ temp = max_t(u32, temp,
+ gpmc_t->adv_on + dev_t->t_aa);
+ gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+ gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+ gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+ /* rd_cycle */
+ temp = max_t(u32, dev_t->t_rd_cycle,
+ gpmc_t->cs_rd_off + dev_t->t_cez_r);
+ temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez);
+ gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+ return 0;
+}
+
+static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_wr_off */
+ temp = dev_t->t_avdp_w;
+ if (mux)
+ temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+ gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+ /* wr_data_mux_bus */
+ temp = dev_t->t_weasu;
+ if (mux) {
+ temp = max_t(u32, temp, gpmc_t->adv_wr_off + dev_t->t_aavdh);
+ temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+ gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+ }
+ gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+ /* we_on */
+ if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+ gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+ else
+ gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+ /* we_off */
+ temp = gpmc_t->we_on + dev_t->t_wpl;
+ gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+ gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+ dev_t->t_wph);
+
+ /* wr_cycle */
+ temp = max_t(u32, dev_t->t_wr_cycle,
+ gpmc_t->cs_wr_off + dev_t->t_cez_w);
+ gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+ return 0;
+}
+
+static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ u32 temp;
+
+ gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) *
+ gpmc_get_fclk_period();
+
+ gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk(
+ dev_t->t_bacc,
+ gpmc_t->sync_clk);
+
+ temp = max_t(u32, dev_t->t_ces, dev_t->t_avds);
+ gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp);
+
+ if (gpmc_calc_divider(gpmc_t->sync_clk) != 1)
+ return 0;
+
+ if (dev_t->ce_xdelay)
+ gpmc_t->bool_timings.cs_extra_delay = true;
+ if (dev_t->avd_xdelay)
+ gpmc_t->bool_timings.adv_extra_delay = true;
+ if (dev_t->oe_xdelay)
+ gpmc_t->bool_timings.oe_extra_delay = true;
+ if (dev_t->we_xdelay)
+ gpmc_t->bool_timings.we_extra_delay = true;
+
+ return 0;
+}
+
+static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ u32 temp;
+
+ /* cs_on */
+ gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu);
+
+ /* adv_on */
+ temp = dev_t->t_avdasu;
+ if (dev_t->t_ce_avd)
+ temp = max_t(u32, temp,
+ gpmc_t->cs_on + dev_t->t_ce_avd);
+ gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
+
+ if (dev_t->sync_write || dev_t->sync_read)
+ gpmc_calc_sync_common_timings(gpmc_t, dev_t);
+
+ return 0;
+}
+
+/* TODO: remove this function once all peripherals are confirmed to
+ * work with generic timing. Simultaneously gpmc_cs_set_timings()
+ * has to be modified to handle timings in ps instead of ns
+*/
+static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
+{
+ t->cs_on /= 1000;
+ t->cs_rd_off /= 1000;
+ t->cs_wr_off /= 1000;
+ t->adv_on /= 1000;
+ t->adv_rd_off /= 1000;
+ t->adv_wr_off /= 1000;
+ t->we_on /= 1000;
+ t->we_off /= 1000;
+ t->oe_on /= 1000;
+ t->oe_off /= 1000;
+ t->page_burst_access /= 1000;
+ t->access /= 1000;
+ t->rd_cycle /= 1000;
+ t->wr_cycle /= 1000;
+ t->bus_turnaround /= 1000;
+ t->cycle2cycle_delay /= 1000;
+ t->wait_monitoring /= 1000;
+ t->clk_activation /= 1000;
+ t->wr_access /= 1000;
+ t->wr_data_mux_bus /= 1000;
+}
+
+int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t)
+{
+ memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+ gpmc_calc_common_timings(gpmc_t, dev_t);
+
+ if (dev_t->sync_read)
+ gpmc_calc_sync_read_timings(gpmc_t, dev_t);
+ else
+ gpmc_calc_async_read_timings(gpmc_t, dev_t);
+
+ if (dev_t->sync_write)
+ gpmc_calc_sync_write_timings(gpmc_t, dev_t);
+ else
+ gpmc_calc_async_write_timings(gpmc_t, dev_t);
+
+ /* TODO: remove, see function definition */
+ gpmc_convert_ps_to_ns(gpmc_t);
+
+ return 0;
+}
+
static __devinit int gpmc_probe(struct platform_device *pdev)
{
int rc;
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
index 79f4dfc2adb3..fe0a844d5007 100644
--- a/arch/arm/mach-omap2/gpmc.h
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -74,6 +74,17 @@
#define GPMC_IRQ_COUNT_EVENT 0x02
+/* bool type time settings */
+struct gpmc_bool_timings {
+ bool cycle2cyclediffcsen;
+ bool cycle2cyclesamecsen;
+ bool we_extra_delay;
+ bool oe_extra_delay;
+ bool adv_extra_delay;
+ bool cs_extra_delay;
+ bool time_para_granularity;
+};
+
/*
* Note that all values in this struct are in nanoseconds except sync_clk
* (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -83,34 +94,104 @@ struct gpmc_timings {
u32 sync_clk;
/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
- u16 cs_on; /* Assertion time */
- u16 cs_rd_off; /* Read deassertion time */
- u16 cs_wr_off; /* Write deassertion time */
+ u32 cs_on; /* Assertion time */
+ u32 cs_rd_off; /* Read deassertion time */
+ u32 cs_wr_off; /* Write deassertion time */
/* ADV signal timings corresponding to GPMC_CONFIG3 */
- u16 adv_on; /* Assertion time */
- u16 adv_rd_off; /* Read deassertion time */
- u16 adv_wr_off; /* Write deassertion time */
+ u32 adv_on; /* Assertion time */
+ u32 adv_rd_off; /* Read deassertion time */
+ u32 adv_wr_off; /* Write deassertion time */
/* WE signals timings corresponding to GPMC_CONFIG4 */
- u16 we_on; /* WE assertion time */
- u16 we_off; /* WE deassertion time */
+ u32 we_on; /* WE assertion time */
+ u32 we_off; /* WE deassertion time */
/* OE signals timings corresponding to GPMC_CONFIG4 */
- u16 oe_on; /* OE assertion time */
- u16 oe_off; /* OE deassertion time */
+ u32 oe_on; /* OE assertion time */
+ u32 oe_off; /* OE deassertion time */
/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
- u16 page_burst_access; /* Multiple access word delay */
- u16 access; /* Start-cycle to first data valid delay */
- u16 rd_cycle; /* Total read cycle time */
- u16 wr_cycle; /* Total write cycle time */
+ u32 page_burst_access; /* Multiple access word delay */
+ u32 access; /* Start-cycle to first data valid delay */
+ u32 rd_cycle; /* Total read cycle time */
+ u32 wr_cycle; /* Total write cycle time */
+
+ u32 bus_turnaround;
+ u32 cycle2cycle_delay;
+
+ u32 wait_monitoring;
+ u32 clk_activation;
/* The following are only on OMAP3430 */
- u16 wr_access; /* WRACCESSTIME */
- u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */
+ u32 wr_access; /* WRACCESSTIME */
+ u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */
+
+ struct gpmc_bool_timings bool_timings;
+};
+
+/* Device timings in picoseconds */
+struct gpmc_device_timings {
+ u32 t_ceasu; /* address setup to CS valid */
+ u32 t_avdasu; /* address setup to ADV valid */
+ /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
+ * of tusb using these timings even for sync whilst
+ * ideally for adv_rd/(wr)_off it should have considered
+ * t_avdh instead. This indirectly necessitates r/w
+ * variations of t_avdp as it is possible to have one
+ * sync & other async
+ */
+ u32 t_avdp_r; /* ADV low time (what about t_cer ?) */
+ u32 t_avdp_w;
+ u32 t_aavdh; /* address hold time */
+ u32 t_oeasu; /* address setup to OE valid */
+ u32 t_aa; /* access time from ADV assertion */
+ u32 t_iaa; /* initial access time */
+ u32 t_oe; /* access time from OE assertion */
+ u32 t_ce; /* access time from CS asertion */
+ u32 t_rd_cycle; /* read cycle time */
+ u32 t_cez_r; /* read CS deassertion to high Z */
+ u32 t_cez_w; /* write CS deassertion to high Z */
+ u32 t_oez; /* OE deassertion to high Z */
+ u32 t_weasu; /* address setup to WE valid */
+ u32 t_wpl; /* write assertion time */
+ u32 t_wph; /* write deassertion time */
+ u32 t_wr_cycle; /* write cycle time */
+
+ u32 clk;
+ u32 t_bacc; /* burst access valid clock to output delay */
+ u32 t_ces; /* CS setup time to clk */
+ u32 t_avds; /* ADV setup time to clk */
+ u32 t_avdh; /* ADV hold time from clk */
+ u32 t_ach; /* address hold time from clk */
+ u32 t_rdyo; /* clk to ready valid */
+
+ u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */
+ u32 t_ce_avd; /* CS on to ADV on delay */
+
+ /* XXX: check the possibility of combining
+ * cyc_aavhd_oe & cyc_aavdh_we
+ */
+ u8 cyc_aavdh_oe;/* read address hold time in cycles */
+ u8 cyc_aavdh_we;/* write address hold time in cycles */
+ u8 cyc_oe; /* access time from OE assertion in cycles */
+ u8 cyc_wpl; /* write deassertion time in cycles */
+ u32 cyc_iaa; /* initial access time in cycles */
+
+ bool mux; /* address & data muxed */
+ bool sync_write;/* synchronous write */
+ bool sync_read; /* synchronous read */
+
+ /* extra delays */
+ bool ce_xdelay;
+ bool avd_xdelay;
+ bool oe_xdelay;
+ bool we_xdelay;
};
+extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+ struct gpmc_device_timings *dev_t);
+
extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
extern int gpmc_get_client_irq(unsigned irq_config);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 9df757644cce..2c3fdd65387b 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -25,7 +25,7 @@
#include <asm/tlb.h>
#include <asm/mach/map.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "omap_hwmod.h"
#include "soc.h"
@@ -50,6 +50,9 @@
#include "prcm_mpu44xx.h"
#include "prminst44xx.h"
#include "cminst44xx.h"
+#include "prm2xxx.h"
+#include "prm3xxx.h"
+#include "prm44xx.h"
/*
* The machine specific code may provide the extra mapping besides the
@@ -387,6 +390,7 @@ void __init omap2420_init_early(void)
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE));
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), NULL);
omap2xxx_check_revision();
+ omap2xxx_prm_init();
omap2xxx_cm_init();
omap2xxx_voltagedomains_init();
omap242x_powerdomains_init();
@@ -401,6 +405,7 @@ void __init omap2420_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap2_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
@@ -415,6 +420,7 @@ void __init omap2430_init_early(void)
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE));
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), NULL);
omap2xxx_check_revision();
+ omap2xxx_prm_init();
omap2xxx_cm_init();
omap2xxx_voltagedomains_init();
omap243x_powerdomains_init();
@@ -429,6 +435,7 @@ void __init omap2430_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap2_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
@@ -448,6 +455,7 @@ void __init omap3_init_early(void)
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), NULL);
omap3xxx_check_revision();
omap3xxx_check_features();
+ omap3xxx_prm_init();
omap3xxx_cm_init();
omap3xxx_voltagedomains_init();
omap3xxx_powerdomains_init();
@@ -500,6 +508,7 @@ void __init omap3_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
void __init omap3430_init_late(void)
@@ -507,6 +516,7 @@ void __init omap3430_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
void __init omap35xx_init_late(void)
@@ -514,6 +524,7 @@ void __init omap35xx_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
void __init omap3630_init_late(void)
@@ -521,6 +532,7 @@ void __init omap3630_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
void __init am35xx_init_late(void)
@@ -528,6 +540,7 @@ void __init am35xx_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
void __init ti81xx_init_late(void)
@@ -535,6 +548,7 @@ void __init ti81xx_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap3_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
@@ -573,6 +587,7 @@ void __init omap4430_init_early(void)
omap_cm_base_init();
omap4xxx_check_revision();
omap4xxx_check_features();
+ omap44xx_prm_init();
omap44xx_voltagedomains_init();
omap44xx_powerdomains_init();
omap44xx_clockdomains_init();
@@ -586,6 +601,7 @@ void __init omap4430_init_late(void)
omap_mux_late_init();
omap2_common_pm_late_init();
omap4_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index bf496510eb5e..df49f2a49461 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -21,7 +21,7 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/pm_runtime.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "omap_device.h"
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 0ef934fec364..e065daa537c0 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -441,19 +441,21 @@ int omap_device_get_context_loss_count(struct platform_device *pdev)
/**
* omap_device_count_resources - count number of struct resource entries needed
* @od: struct omap_device *
+ * @flags: Type of resources to include when counting (IRQ/DMA/MEM)
*
* Count the number of struct resource entries needed for this
* omap_device @od. Used by omap_device_build_ss() to determine how
* much memory to allocate before calling
* omap_device_fill_resources(). Returns the count.
*/
-static int omap_device_count_resources(struct omap_device *od)
+static int omap_device_count_resources(struct omap_device *od,
+ unsigned long flags)
{
int c = 0;
int i;
for (i = 0; i < od->hwmods_cnt; i++)
- c += omap_hwmod_count_resources(od->hwmods[i]);
+ c += omap_hwmod_count_resources(od->hwmods[i], flags);
pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
od->pdev->name, c, od->hwmods_cnt);
@@ -557,52 +559,73 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
od->hwmods = hwmods;
od->pdev = pdev;
- res_count = omap_device_count_resources(od);
/*
+ * Non-DT Boot:
+ * Here, pdev->num_resources = 0, and we should get all the
+ * resources from hwmod.
+ *
* DT Boot:
* OF framework will construct the resource structure (currently
* does for MEM & IRQ resource) and we should respect/use these
* resources, killing hwmod dependency.
* If pdev->num_resources > 0, we assume that MEM & IRQ resources
* have been allocated by OF layer already (through DTB).
- *
- * Non-DT Boot:
- * Here, pdev->num_resources = 0, and we should get all the
- * resources from hwmod.
+ * As preparation for the future we examine the OF provided resources
+ * to see if we have DMA resources provided already. In this case
+ * there is no need to update the resources for the device, we use the
+ * OF provided ones.
*
* TODO: Once DMA resource is available from OF layer, we should
* kill filling any resources from hwmod.
*/
- if (res_count > pdev->num_resources) {
- /* Allocate resources memory to account for new resources */
- res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
- if (!res)
- goto oda_exit3;
-
- /*
- * If pdev->num_resources > 0, then assume that,
- * MEM and IRQ resources will only come from DT and only
- * fill DMA resource from hwmod layer.
- */
- if (pdev->num_resources && pdev->resource) {
- dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
- __func__, res_count);
- memcpy(res, pdev->resource,
- sizeof(struct resource) * pdev->num_resources);
- _od_fill_dma_resources(od, &res[pdev->num_resources]);
- } else {
- dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
- __func__, res_count);
- omap_device_fill_resources(od, res);
+ if (!pdev->num_resources) {
+ /* Count all resources for the device */
+ res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
+ IORESOURCE_DMA |
+ IORESOURCE_MEM);
+ } else {
+ /* Take a look if we already have DMA resource via DT */
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+
+ /* We have it, no need to touch the resources */
+ if (r->flags == IORESOURCE_DMA)
+ goto have_everything;
}
+ /* Count only DMA resources for the device */
+ res_count = omap_device_count_resources(od, IORESOURCE_DMA);
+ /* The device has no DMA resource, no need for update */
+ if (!res_count)
+ goto have_everything;
- ret = platform_device_add_resources(pdev, res, res_count);
- kfree(res);
+ res_count += pdev->num_resources;
+ }
- if (ret)
- goto oda_exit3;
+ /* Allocate resources memory to account for new resources */
+ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+ if (!res)
+ goto oda_exit3;
+
+ if (!pdev->num_resources) {
+ dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
+ __func__, res_count);
+ omap_device_fill_resources(od, res);
+ } else {
+ dev_dbg(&pdev->dev,
+ "%s: appending %d DMA resources from hwmod\n",
+ __func__, res_count - pdev->num_resources);
+ memcpy(res, pdev->resource,
+ sizeof(struct resource) * pdev->num_resources);
+ _od_fill_dma_resources(od, &res[pdev->num_resources]);
}
+ ret = platform_device_add_resources(pdev, res, res_count);
+ kfree(res);
+
+ if (ret)
+ goto oda_exit3;
+
+have_everything:
if (!pm_lats) {
pm_lats = omap_default_latency;
pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index b3b00f43dd7c..4653efb87a27 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -130,7 +130,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/io.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/list.h>
@@ -187,6 +187,8 @@ struct omap_hwmod_soc_ops {
int (*is_hardreset_asserted)(struct omap_hwmod *oh,
struct omap_hwmod_rst_info *ohri);
int (*init_clkdm)(struct omap_hwmod *oh);
+ void (*update_context_lost)(struct omap_hwmod *oh);
+ int (*get_context_lost)(struct omap_hwmod *oh);
};
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
@@ -646,6 +648,19 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
return 0;
}
+static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
+{
+ struct clk_hw_omap *clk;
+
+ if (oh->clkdm) {
+ return oh->clkdm;
+ } else if (oh->_clk) {
+ clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
+ return clk->clkdm;
+ }
+ return NULL;
+}
+
/**
* _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active
* @oh: struct omap_hwmod *
@@ -661,13 +676,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
*/
static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
{
- if (!oh->_clk)
+ struct clockdomain *clkdm, *init_clkdm;
+
+ clkdm = _get_clkdm(oh);
+ init_clkdm = _get_clkdm(init_oh);
+
+ if (!clkdm || !init_clkdm)
return -EINVAL;
- if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+ if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
return 0;
- return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
+ return clkdm_add_sleepdep(clkdm, init_clkdm);
}
/**
@@ -685,13 +705,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
*/
static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
{
- if (!oh->_clk)
+ struct clockdomain *clkdm, *init_clkdm;
+
+ clkdm = _get_clkdm(oh);
+ init_clkdm = _get_clkdm(init_oh);
+
+ if (!clkdm || !init_clkdm)
return -EINVAL;
- if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+ if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
return 0;
- return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
+ return clkdm_del_sleepdep(clkdm, init_clkdm);
}
/**
@@ -725,7 +750,7 @@ static int _init_main_clk(struct omap_hwmod *oh)
*/
clk_prepare(oh->_clk);
- if (!oh->_clk->clkdm)
+ if (!_get_clkdm(oh))
pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
oh->name, oh->main_clk);
@@ -1308,6 +1333,7 @@ static void _enable_sysc(struct omap_hwmod *oh)
u8 idlemode, sf;
u32 v;
bool clkdm_act;
+ struct clockdomain *clkdm;
if (!oh->class->sysc)
return;
@@ -1327,11 +1353,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
v = oh->_sysc_cache;
sf = oh->class->sysc->sysc_flags;
+ clkdm = _get_clkdm(oh);
if (sf & SYSC_HAS_SIDLEMODE) {
- clkdm_act = ((oh->clkdm &&
- oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) ||
- (oh->_clk && oh->_clk->clkdm &&
- oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU));
+ clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
if (clkdm_act && !(oh->class->sysc->idlemodes &
(SIDLE_SMART | SIDLE_SMART_WKUP)))
idlemode = HWMOD_IDLEMODE_FORCE;
@@ -1533,11 +1557,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
+ if (soc_ops.init_clkdm)
+ ret |= soc_ops.init_clkdm(oh);
+
ret |= _init_main_clk(oh);
ret |= _init_interface_clks(oh);
ret |= _init_opt_clks(oh);
- if (soc_ops.init_clkdm)
- ret |= soc_ops.init_clkdm(oh);
if (!ret)
oh->_state = _HWMOD_STATE_CLKS_INITED;
@@ -1992,6 +2017,42 @@ static void _reconfigure_io_chain(void)
}
/**
+ * _omap4_update_context_lost - increment hwmod context loss counter if
+ * hwmod context was lost, and clear hardware context loss reg
+ * @oh: hwmod to check for context loss
+ *
+ * If the PRCM indicates that the hwmod @oh lost context, increment
+ * our in-memory context loss counter, and clear the RM_*_CONTEXT
+ * bits. No return value.
+ */
+static void _omap4_update_context_lost(struct omap_hwmod *oh)
+{
+ if (oh->prcm.omap4.flags & HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT)
+ return;
+
+ if (!prm_was_any_context_lost_old(oh->clkdm->pwrdm.ptr->prcm_partition,
+ oh->clkdm->pwrdm.ptr->prcm_offs,
+ oh->prcm.omap4.context_offs))
+ return;
+
+ oh->prcm.omap4.context_lost_counter++;
+ prm_clear_context_loss_flags_old(oh->clkdm->pwrdm.ptr->prcm_partition,
+ oh->clkdm->pwrdm.ptr->prcm_offs,
+ oh->prcm.omap4.context_offs);
+}
+
+/**
+ * _omap4_get_context_lost - get context loss counter for a hwmod
+ * @oh: hwmod to get context loss counter for
+ *
+ * Returns the in-memory context loss counter for a hwmod.
+ */
+static int _omap4_get_context_lost(struct omap_hwmod *oh)
+{
+ return oh->prcm.omap4.context_lost_counter;
+}
+
+/**
* _enable - enable an omap_hwmod
* @oh: struct omap_hwmod *
*
@@ -2074,6 +2135,9 @@ static int _enable(struct omap_hwmod *oh)
if (soc_ops.enable_module)
soc_ops.enable_module(oh);
+ if (soc_ops.update_context_lost)
+ soc_ops.update_context_lost(oh);
+
r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
-EINVAL;
if (!r) {
@@ -3398,7 +3462,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
/**
* omap_hwmod_count_resources - count number of struct resources needed by hwmod
* @oh: struct omap_hwmod *
- * @res: pointer to the first element of an array of struct resource to fill
+ * @flags: Type of resources to include when counting (IRQ/DMA/MEM)
*
* Count the number of struct resource array elements necessary to
* contain omap_hwmod @oh resources. Intended to be called by code
@@ -3411,20 +3475,25 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
* resource IDs.
*
*/
-int omap_hwmod_count_resources(struct omap_hwmod *oh)
+int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
{
- struct omap_hwmod_ocp_if *os;
- struct list_head *p;
- int ret;
- int i = 0;
+ int ret = 0;
- ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
+ if (flags & IORESOURCE_IRQ)
+ ret += _count_mpu_irqs(oh);
- p = oh->slave_ports.next;
+ if (flags & IORESOURCE_DMA)
+ ret += _count_sdma_reqs(oh);
- while (i < oh->slaves_cnt) {
- os = _fetch_next_ocp_if(&p, &i);
- ret += _count_ocp_if_addr_spaces(os);
+ if (flags & IORESOURCE_MEM) {
+ int i = 0;
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p = oh->slave_ports.next;
+
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+ ret += _count_ocp_if_addr_spaces(os);
+ }
}
return ret;
@@ -3591,10 +3660,15 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
{
struct clk *c;
struct omap_hwmod_ocp_if *oi;
+ struct clockdomain *clkdm;
+ struct clk_hw_omap *clk;
if (!oh)
return NULL;
+ if (oh->clkdm)
+ return oh->clkdm->pwrdm.ptr;
+
if (oh->_clk) {
c = oh->_clk;
} else {
@@ -3604,11 +3678,12 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
c = oi->_clk;
}
- if (!c->clkdm)
+ clk = to_clk_hw_omap(__clk_get_hw(c));
+ clkdm = clk->clkdm;
+ if (!clkdm)
return NULL;
- return c->clkdm->pwrdm.ptr;
-
+ return clkdm->pwrdm.ptr;
}
/**
@@ -3913,17 +3988,21 @@ ohsps_unlock:
* omap_hwmod_get_context_loss_count - get lost context count
* @oh: struct omap_hwmod *
*
- * Query the powerdomain of of @oh to get the context loss
- * count for this device.
+ * Returns the context loss count of associated @oh
+ * upon success, or zero if no context loss data is available.
*
- * Returns the context loss count of the powerdomain assocated with @oh
- * upon success, or zero if no powerdomain exists for @oh.
+ * On OMAP4, this queries the per-hwmod context loss register,
+ * assuming one exists. If not, or on OMAP2/3, this queries the
+ * enclosing powerdomain context loss count.
*/
int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
{
struct powerdomain *pwrdm;
int ret = 0;
+ if (soc_ops.get_context_lost)
+ return soc_ops.get_context_lost(oh);
+
pwrdm = omap_hwmod_get_pwrdm(oh);
if (pwrdm)
ret = pwrdm_get_context_loss_count(pwrdm);
@@ -4038,6 +4117,8 @@ void __init omap_hwmod_init(void)
soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
soc_ops.init_clkdm = _init_clkdm;
+ soc_ops.update_context_lost = _omap4_update_context_lost;
+ soc_ops.get_context_lost = _omap4_get_context_lost;
} else if (soc_is_am33xx()) {
soc_ops.enable_module = _am33xx_enable_module;
soc_ops.disable_module = _am33xx_disable_module;
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index 87a3c5b7aa74..3ae852a522f9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -2,7 +2,7 @@
* omap_hwmod macros, structures
*
* Copyright (C) 2009-2011 Nokia Corporation
- * Copyright (C) 2012 Texas Instruments, Inc.
+ * Copyright (C) 2011-2012 Texas Instruments, Inc.
* Paul Walmsley
*
* Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -394,12 +394,15 @@ struct omap_hwmod_omap2_prcm {
/**
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
- * @clkctrl_reg: PRCM address of the clock control register
- * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @clkctrl_offs: offset of the PRCM clock control register
+ * @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM
+ * @context_offs: offset of the RM_*_CONTEXT register
* @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
* @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
* @submodule_wkdep_bit: bit shift of the WKDEP range
* @flags: PRCM register capabilities for this IP block
+ * @modulemode: allowable modulemodes
+ * @context_lost_counter: Count of module level context lost
*
* If @lostcontext_mask is not defined, context loss check code uses
* whole register without masking. @lostcontext_mask should only be
@@ -415,6 +418,7 @@ struct omap_hwmod_omap4_prcm {
u8 submodule_wkdep_bit;
u8 modulemode;
u8 flags;
+ int context_lost_counter;
};
@@ -633,7 +637,7 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
int omap_hwmod_softreset(struct omap_hwmod *oh);
-int omap_hwmod_count_resources(struct omap_hwmod *oh);
+int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags);
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index e8efe3d1da6c..b5efe58c0be0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -15,8 +15,8 @@
#include <linux/i2c-omap.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
-
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
+#include <plat/dmtimer.h>
#include "omap_hwmod.h"
#include "l3_2xxx.h"
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 32d17e3fd727..6c8fa70ddadd 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -16,8 +16,8 @@
#include <linux/i2c-omap.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
-
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
+#include <plat/dmtimer.h>
#include "omap_hwmod.h"
#include "mmc.h"
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index 40d6c93d9853..534974e08add 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -10,7 +10,8 @@
* published by the Free Software Foundation.
*/
-#include <plat-omap/dma-omap.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
#include "omap_hwmod.h"
#include "hdq1w.h"
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 0db8f450bad9..e596117004d4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -10,7 +10,7 @@
*/
#include <linux/platform_data/gpio-omap.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <plat/dmtimer.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index ad8d43b33273..32820d89f5b4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -674,6 +674,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
.name = "cpgmac0",
.class = &am33xx_cpgmac0_hwmod_class,
.clkdm_name = "cpsw_125mhz_clkdm",
+ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
.mpu_irqs = am33xx_cpgmac0_irqs,
.main_clk = "cpsw_125mhz_gclk",
.prcm = {
@@ -685,6 +686,20 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
};
/*
+ * mdio class
+ */
+static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
+ .name = "davinci_mdio",
+};
+
+static struct omap_hwmod am33xx_mdio_hwmod = {
+ .name = "davinci_mdio",
+ .class = &am33xx_mdio_hwmod_class,
+ .clkdm_name = "cpsw_125mhz_clkdm",
+ .main_clk = "cpsw_125mhz_gclk",
+};
+
+/*
* dcan class
*/
static struct omap_hwmod_class am33xx_dcan_hwmod_class = {
@@ -2501,6 +2516,21 @@ static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
.user = OCP_USER_MPU,
};
+struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
+ {
+ .pa_start = 0x4A101000,
+ .pa_end = 0x4A101000 + SZ_256 - 1,
+ },
+ { }
+};
+
+struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+ .master = &am33xx_cpgmac0_hwmod,
+ .slave = &am33xx_mdio_hwmod,
+ .addr = am33xx_mdio_addr_space,
+ .user = OCP_USER_MPU,
+};
+
static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
{
.pa_start = 0x48080000,
@@ -3371,6 +3401,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_l3_main__tptc2,
&am33xx_l3_s__usbss,
&am33xx_l4_hs__cpgmac0,
+ &am33xx_cpgmac0__mdio,
NULL,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7f73f2132acc..ec4499e5a4c9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -19,7 +19,7 @@
#include <linux/power/smartreflex.h>
#include <linux/platform_data/gpio-omap.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "l3_3xxx.h"
#include "l4_3xxx.h"
#include <linux/platform_data/asoc-ti-mcbsp.h>
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 26f8e9f18190..eb61cfd9452b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -21,9 +21,10 @@
#include <linux/io.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
#include <linux/i2c-omap.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <linux/platform_data/omap_ocp2scp.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index 7e437bf6024c..336fdfcf88bb 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -89,8 +89,11 @@ extern struct omap_volt_data omap34xx_vddcore_volt_data[];
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
extern struct omap_volt_data omap36xx_vddcore_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap443x_vdd_core_volt_data[];
+extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap446x_vdd_core_volt_data[];
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index 4d76a3ca5bf3..e237602e10ea 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -33,6 +33,38 @@
#include "control.h"
#include "usb.h"
+#define CONTROL_DEV_CONF 0x300
+#define PHY_PD 0x1
+
+/**
+ * omap4430_phy_power_down: disable MUSB PHY during early init
+ *
+ * OMAP4 MUSB PHY module is enabled by default on reset, but this will
+ * prevent core retention if not disabled by SW. USB driver will
+ * later on enable this, once and if the driver needs it.
+ */
+static int __init omap4430_phy_power_down(void)
+{
+ void __iomem *ctrl_base;
+
+ if (!cpu_is_omap44xx())
+ return 0;
+
+ ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
+ if (!ctrl_base) {
+ pr_err("control module ioremap failed\n");
+ return -ENOMEM;
+ }
+
+ /* Power down the phy */
+ __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+
+ iounmap(ctrl_base);
+
+ return 0;
+}
+early_initcall(omap4430_phy_power_down);
+
void am35x_musb_reset(void)
{
u32 regval;
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 2bf35dc091be..fefd40166624 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -31,16 +31,6 @@
#define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
#define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
-#define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14
-#define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42
-#define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18
-#define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c
-
-#define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18
-#define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c
-#define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18
-#define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30
-
#define OMAP4_SRI2C_SLAVE_ADDR 0x12
#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
#define OMAP4_VDD_MPU_SR_CMD_REG 0x56
@@ -54,13 +44,6 @@
#define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04
#define OMAP4_VP_VLIMITTO_TIMEOUT_US 200
-#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA
-#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39
-#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA
-#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D
-#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA
-#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28
-
static bool is_offset_valid;
static u8 smps_offset;
/*
@@ -159,16 +142,11 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
static struct omap_voltdm_pmic omap3_mpu_pmic = {
.slew_rate = 4000,
.step_size = 12500,
- .on_volt = 1200000,
- .onlp_volt = 1000000,
- .ret_volt = 975000,
- .off_volt = 600000,
- .volt_setup_time = 0xfff,
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
- .vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
- .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
+ .vddmin = 600000,
+ .vddmax = 1450000,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
@@ -180,16 +158,11 @@ static struct omap_voltdm_pmic omap3_mpu_pmic = {
static struct omap_voltdm_pmic omap3_core_pmic = {
.slew_rate = 4000,
.step_size = 12500,
- .on_volt = 1200000,
- .onlp_volt = 1000000,
- .ret_volt = 975000,
- .off_volt = 600000,
- .volt_setup_time = 0xfff,
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
- .vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
- .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
+ .vddmin = 600000,
+ .vddmax = 1450000,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
@@ -201,21 +174,17 @@ static struct omap_voltdm_pmic omap3_core_pmic = {
static struct omap_voltdm_pmic omap4_mpu_pmic = {
.slew_rate = 4000,
.step_size = 12660,
- .on_volt = 1375000,
- .onlp_volt = 1375000,
- .ret_volt = 830000,
- .off_volt = 0,
- .volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
- .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
+ .vddmin = 0,
+ .vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
.i2c_high_speed = true,
+ .i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@@ -223,21 +192,17 @@ static struct omap_voltdm_pmic omap4_mpu_pmic = {
static struct omap_voltdm_pmic omap4_iva_pmic = {
.slew_rate = 4000,
.step_size = 12660,
- .on_volt = 1188000,
- .onlp_volt = 1188000,
- .ret_volt = 830000,
- .off_volt = 0,
- .volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
- .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
+ .vddmin = 0,
+ .vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
.i2c_high_speed = true,
+ .i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@@ -245,20 +210,17 @@ static struct omap_voltdm_pmic omap4_iva_pmic = {
static struct omap_voltdm_pmic omap4_core_pmic = {
.slew_rate = 4000,
.step_size = 12660,
- .on_volt = 1200000,
- .onlp_volt = 1200000,
- .ret_volt = 830000,
- .off_volt = 0,
- .volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
- .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
+ .vddmin = 0,
+ .vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
+ .i2c_high_speed = true,
+ .i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@@ -289,13 +251,6 @@ int __init omap3_twl_init(void)
if (!cpu_is_omap34xx())
return -ENODEV;
- if (cpu_is_omap3630()) {
- omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
- omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
- omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
- omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
- }
-
/*
* The smartreflex bit on twl4030 specifies if the setting of voltage
* is done over the I2C_SR path. Since this setting is independent of
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index a9fd6d5fe79e..d470b728e720 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP4 OPP table definitions.
*
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2010-2012 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
* Kevin Hilman
* Thara Gopinath
@@ -35,7 +35,7 @@
#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000
-struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
@@ -47,7 +47,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
#define OMAP4430_VDD_IVA_OPP100_UV 1188000
#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000
-struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
@@ -57,14 +57,14 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
#define OMAP4430_VDD_CORE_OPP50_UV 1025000
#define OMAP4430_VDD_CORE_OPP100_UV 1200000
-struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+struct omap_volt_data omap443x_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
-static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
+static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
/* MPU OPP2 - OPP100 */
@@ -86,6 +86,82 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/* TODO: add DSP, aess, fdif, gpu */
};
+#define OMAP4460_VDD_MPU_OPP50_UV 1025000
+#define OMAP4460_VDD_MPU_OPP100_UV 1200000
+#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_IVA_OPP50_UV 1025000
+#define OMAP4460_VDD_IVA_OPP100_UV 1200000
+#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_CORE_OPP50_UV 1025000
+#define OMAP4460_VDD_CORE_OPP100_UV 1200000
+#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000
+
+struct omap_volt_data omap446x_vdd_core_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
+ /* MPU OPP1 - OPP50 */
+ OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
+ /* MPU OPP2 - OPP100 */
+ OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
+ /* MPU OPP3 - OPP-Turbo */
+ OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
+ /*
+ * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
+ * recommends TPS623631 - confirm and enable the opp in board file
+ * XXX: May be we should enable these based on mpu capability and
+ * Exception board files disable it...
+ */
+ OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* MPU OPP4 - OPP-Nitro SpeedBin */
+ OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* L3 OPP1 - OPP50 */
+ OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* L3 OPP2 - OPP100 */
+ OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
+ /* IVA OPP1 - OPP50 */
+ OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
+ /* IVA OPP2 - OPP100 */
+ OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
+ /*
+ * IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
+ * recommends Phoenix VCORE2 which can supply only 600mA - so the ones
+ * above this OPP frequency, even though OMAP is capable, should be
+ * enabled by board file which is sure of the chip power capability
+ */
+ OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
+ /* IVA OPP4 - OPP-Nitro */
+ OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+ /* IVA OPP5 - OPP-Nitro SpeedBin*/
+ OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+
+ /* TODO: add DSP, aess, fdif, gpu */
+};
+
/**
* omap4_opp_init() - initialize omap4 opp table
*/
@@ -93,12 +169,12 @@ int __init omap4_opp_init(void)
{
int r = -ENODEV;
- if (!cpu_is_omap443x())
- return r;
-
- r = omap_init_opp_table(omap44xx_opp_def_list,
- ARRAY_SIZE(omap44xx_opp_def_list));
-
+ if (cpu_is_omap443x())
+ r = omap_init_opp_table(omap443x_opp_def_list,
+ ARRAY_SIZE(omap443x_opp_def_list));
+ else if (cpu_is_omap446x())
+ r = omap_init_opp_table(omap446x_opp_def_list,
+ ARRAY_SIZE(omap446x_opp_def_list));
return r;
}
device_initcall(omap4_opp_init);
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 331478f9b864..f4b3143a8b1d 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -40,6 +40,38 @@ static struct omap_device_pm_latency *pm_lats;
*/
int (*omap_pm_suspend)(void);
+#ifdef CONFIG_PM
+/**
+ * struct omap2_oscillator - Describe the board main oscillator latencies
+ * @startup_time: oscillator startup latency
+ * @shutdown_time: oscillator shutdown latency
+ */
+struct omap2_oscillator {
+ u32 startup_time;
+ u32 shutdown_time;
+};
+
+static struct omap2_oscillator oscillator = {
+ .startup_time = ULONG_MAX,
+ .shutdown_time = ULONG_MAX,
+};
+
+void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
+{
+ oscillator.startup_time = tstart;
+ oscillator.shutdown_time = tshut;
+}
+
+void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
+{
+ if (!tstart || !tshut)
+ return;
+
+ *tstart = oscillator.startup_time;
+ *tshut = oscillator.shutdown_time;
+}
+#endif
+
static int __init _init_omap_device(char *name)
{
struct omap_hwmod *oh;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index fc3c96d5e013..c22503b17abd 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -138,4 +138,14 @@ static inline int omap4_twl_init(void)
}
#endif
+#ifdef CONFIG_PM
+extern void omap_pm_setup_oscillator(u32 tstart, u32 tshut);
+extern void omap_pm_get_oscillator(u32 *tstart, u32 *tshut);
+extern void omap_pm_setup_sr_i2c_pcb_length(u32 mm);
+#else
+static inline void omap_pm_setup_oscillator(u32 tstart, u32 tshut) { }
+static inline void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) { *tstart = *tshut = 0; }
+static inline void omap_pm_setup_sr_i2c_pcb_length(u32 mm) { }
+#endif
+
#endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 13e1f4303989..c333fa6dffa8 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -25,7 +25,7 @@
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/irq.h>
#include <linux/time.h>
#include <linux/gpio.h>
@@ -38,7 +38,7 @@
#include <asm/mach-types.h>
#include <asm/system_misc.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "soc.h"
#include "common.h"
@@ -203,7 +203,7 @@ static int omap2_can_sleep(void)
{
if (omap2_fclks_active())
return 0;
- if (osc_ck->usecount > 1)
+ if (__clk_is_enabled(osc_ck))
return 0;
if (omap_dma_running())
return 0;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 770320061422..7be3622cfc85 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -28,6 +28,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/omap-dma.h>
#include <linux/platform_data/gpio-omap.h>
#include <trace/events/power.h>
@@ -38,8 +39,6 @@
#include "clockdomain.h"
#include "powerdomain.h"
-#include <plat-omap/dma-omap.h>
-
#include "soc.h"
#include "common.h"
#include "cm3xxx.h"
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 7da75aed1514..aa6fd98f606e 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -101,13 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
if (!strncmp(pwrdm->name, "cpu", 3))
return 0;
- /*
- * FIXME: Remove this check when core retention is supported
- * Only MPUSS power domain is added in the list.
- */
- if (strcmp(pwrdm->name, "mpu_pwrdm"))
- return 0;
-
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
index 638da6dd41c3..91aa5106d637 100644
--- a/arch/arm/mach-omap2/prm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
@@ -107,12 +107,14 @@
#define OMAP2420_CLKOUT2_EN_MASK (1 << 15)
#define OMAP2420_CLKOUT2_DIV_SHIFT 11
#define OMAP2420_CLKOUT2_DIV_MASK (0x7 << 11)
+#define OMAP2420_CLKOUT2_DIV_WIDTH 3
#define OMAP2420_CLKOUT2_SOURCE_SHIFT 8
#define OMAP2420_CLKOUT2_SOURCE_MASK (0x3 << 8)
#define OMAP24XX_CLKOUT_EN_SHIFT 7
#define OMAP24XX_CLKOUT_EN_MASK (1 << 7)
#define OMAP24XX_CLKOUT_DIV_SHIFT 3
#define OMAP24XX_CLKOUT_DIV_MASK (0x7 << 3)
+#define OMAP24XX_CLKOUT_DIV_WIDTH 3
#define OMAP24XX_CLKOUT_SOURCE_SHIFT 0
#define OMAP24XX_CLKOUT_SOURCE_MASK (0x3 << 0)
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 838b594d4e13..b0a2142eeb91 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -384,6 +384,7 @@
/* PRM_CLKSEL */
#define OMAP3430_SYS_CLKIN_SEL_SHIFT 0
#define OMAP3430_SYS_CLKIN_SEL_MASK (0x7 << 0)
+#define OMAP3430_SYS_CLKIN_SEL_WIDTH 3
/* PRM_CLKOUT_CTRL */
#define OMAP3430_CLKOUT_EN_MASK (1 << 7)
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index a1a266ce90da..ac25ae6667cf 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -114,16 +114,25 @@ struct prm_reset_src_map {
/**
* struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
- * @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
+ * @read_reset_sources: ptr to the SoC PRM-specific get_reset_source impl
+ * @was_any_context_lost_old: ptr to the SoC PRM context loss test fn
+ * @clear_context_loss_flags_old: ptr to the SoC PRM context loss flag clear fn
+ *
+ * XXX @was_any_context_lost_old and @clear_context_loss_flags_old are
+ * deprecated.
*/
struct prm_ll_data {
u32 (*read_reset_sources)(void);
+ bool (*was_any_context_lost_old)(u8 part, s16 inst, u16 idx);
+ void (*clear_context_loss_flags_old)(u8 part, s16 inst, u16 idx);
};
extern int prm_register(struct prm_ll_data *pld);
extern int prm_unregister(struct prm_ll_data *pld);
extern u32 prm_read_reset_sources(void);
+extern bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx);
+extern void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx);
#endif
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
index bf24fc47603b..faeab18696df 100644
--- a/arch/arm/mach-omap2/prm2xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -118,14 +118,13 @@ static struct prm_ll_data omap2xxx_prm_ll_data = {
.read_reset_sources = &omap2xxx_prm_read_reset_sources,
};
-static int __init omap2xxx_prm_init(void)
+int __init omap2xxx_prm_init(void)
{
if (!cpu_is_omap24xx())
return 0;
return prm_register(&omap2xxx_prm_ll_data);
}
-subsys_initcall(omap2xxx_prm_init);
static void __exit omap2xxx_prm_exit(void)
{
diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h
index fe8a14f190ab..3194dd87e0e4 100644
--- a/arch/arm/mach-omap2/prm2xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx.h
@@ -126,8 +126,7 @@ extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
extern void omap2xxx_prm_dpll_reset(void);
-extern int __init prm2xxx_init(void);
-extern int __exit prm2xxx_exit(void);
+extern int __init omap2xxx_prm_init(void);
#endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index 78532d6fecd7..9624b40836d4 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -152,6 +152,7 @@ extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
/* Named PRCM_CLKSRC_CTRL on the 24XX */
#define OMAP_SYSCLKDIV_SHIFT 6
#define OMAP_SYSCLKDIV_MASK (0x3 << 6)
+#define OMAP_SYSCLKDIV_WIDTH 2
#define OMAP_AUTOEXTCLKMODE_SHIFT 3
#define OMAP_AUTOEXTCLKMODE_MASK (0x3 << 3)
#define OMAP_SYSCLKSEL_SHIFT 0
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index b86116cf0db9..db198d058584 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -383,27 +383,30 @@ static struct prm_ll_data omap3xxx_prm_ll_data = {
.read_reset_sources = &omap3xxx_prm_read_reset_sources,
};
-static int __init omap3xxx_prm_init(void)
+int __init omap3xxx_prm_init(void)
+{
+ if (!cpu_is_omap34xx())
+ return 0;
+
+ return prm_register(&omap3xxx_prm_ll_data);
+}
+
+static int __init omap3xxx_prm_late_init(void)
{
int ret;
if (!cpu_is_omap34xx())
return 0;
- ret = prm_register(&omap3xxx_prm_ll_data);
- if (ret)
- return ret;
-
omap3xxx_prm_enable_io_wakeup();
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
if (!ret)
irq_set_status_flags(omap_prcm_event_to_irq("io"),
IRQ_NOAUTOEN);
-
return ret;
}
-subsys_initcall(omap3xxx_prm_init);
+subsys_initcall(omap3xxx_prm_late_init);
static void __exit omap3xxx_prm_exit(void)
{
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 10cd41a8129e..277f71794e61 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -154,6 +154,7 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
extern void omap3xxx_prm_dpll3_reset(void);
+extern int __init omap3xxx_prm_init(void);
extern u32 omap3xxx_prm_get_reset_sources(void);
#endif /* __ASSEMBLER */
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 6d3467af205d..7498bc77fe8b 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -346,6 +346,37 @@ static u32 omap44xx_prm_read_reset_sources(void)
return r;
}
+/**
+ * omap44xx_prm_was_any_context_lost_old - was module hardware context lost?
+ * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
+ * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
+ * @idx: CONTEXT register offset
+ *
+ * Return 1 if any bits were set in the *_CONTEXT_* register
+ * identified by (@part, @inst, @idx), which means that some context
+ * was lost for that module; otherwise, return 0.
+ */
+static bool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
+{
+ return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
+}
+
+/**
+ * omap44xx_prm_clear_context_lost_flags_old - clear context loss flags
+ * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
+ * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
+ * @idx: CONTEXT register offset
+ *
+ * Clear hardware context loss bits for the module identified by
+ * (@part, @inst, @idx). No return value. XXX Writes to reserved bits;
+ * is there a way to avoid this?
+ */
+static void omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
+ u16 idx)
+{
+ omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
+}
+
/* Powerdomain low-level functions */
static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
@@ -613,24 +644,28 @@ struct pwrdm_ops omap4_pwrdm_operations = {
*/
static struct prm_ll_data omap44xx_prm_ll_data = {
.read_reset_sources = &omap44xx_prm_read_reset_sources,
+ .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
+ .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
};
-static int __init omap44xx_prm_init(void)
+int __init omap44xx_prm_init(void)
{
- int ret;
-
if (!cpu_is_omap44xx())
return 0;
- ret = prm_register(&omap44xx_prm_ll_data);
- if (ret)
- return ret;
+ return prm_register(&omap44xx_prm_ll_data);
+}
+
+static int __init omap44xx_prm_late_init(void)
+{
+ if (!cpu_is_omap44xx())
+ return 0;
omap44xx_prm_enable_io_wakeup();
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
}
-subsys_initcall(omap44xx_prm_init);
+subsys_initcall(omap44xx_prm_late_init);
static void __exit omap44xx_prm_exit(void)
{
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index c8e1accdc90e..22b0979206ca 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -771,6 +771,7 @@ extern void omap44xx_prm_ocp_barrier(void);
extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
+extern int __init omap44xx_prm_init(void);
extern u32 omap44xx_prm_get_reset_sources(void);
# endif
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index f596e1e91ffd..228b850e632f 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -365,6 +365,51 @@ u32 prm_read_reset_sources(void)
}
/**
+ * prm_was_any_context_lost_old - was device context lost? (old API)
+ * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
+ * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
+ * @idx: CONTEXT register offset
+ *
+ * Return 1 if any bits were set in the *_CONTEXT_* register
+ * identified by (@part, @inst, @idx), which means that some context
+ * was lost for that module; otherwise, return 0. XXX Deprecated;
+ * callers need to use a less-SoC-dependent way to identify hardware
+ * IP blocks.
+ */
+bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
+{
+ bool ret = true;
+
+ if (prm_ll_data->was_any_context_lost_old)
+ ret = prm_ll_data->was_any_context_lost_old(part, inst, idx);
+ else
+ WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+ __func__);
+
+ return ret;
+}
+
+/**
+ * prm_clear_context_lost_flags_old - clear context loss flags (old API)
+ * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
+ * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
+ * @idx: CONTEXT register offset
+ *
+ * Clear hardware context loss bits for the module identified by
+ * (@part, @inst, @idx). No return value. XXX Deprecated; callers
+ * need to use a less-SoC-dependent way to identify hardware IP
+ * blocks.
+ */
+void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx)
+{
+ if (prm_ll_data->clear_context_loss_flags_old)
+ prm_ll_data->clear_context_loss_flags_old(part, inst, idx);
+ else
+ WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+ __func__);
+}
+
+/**
* prm_register - register per-SoC low-level data with the PRM
* @pld: low-level per-SoC OMAP PRM data & function pointers to register
*
diff --git a/arch/arm/mach-omap2/scrm44xx.h b/arch/arm/mach-omap2/scrm44xx.h
index 701bf2d32949..e897ac89a3fd 100644
--- a/arch/arm/mach-omap2/scrm44xx.h
+++ b/arch/arm/mach-omap2/scrm44xx.h
@@ -127,12 +127,14 @@
/* AUXCLKREQ0 */
#define OMAP4_MAPPING_SHIFT 2
#define OMAP4_MAPPING_MASK (0x7 << 2)
+#define OMAP4_MAPPING_WIDTH 3
#define OMAP4_ACCURACY_SHIFT 1
#define OMAP4_ACCURACY_MASK (1 << 1)
/* AUXCLK0 */
#define OMAP4_CLKDIV_SHIFT 16
#define OMAP4_CLKDIV_MASK (0xf << 16)
+#define OMAP4_CLKDIV_WIDTH 4
#define OMAP4_DISABLECLK_SHIFT 9
#define OMAP4_DISABLECLK_MASK (1 << 9)
#define OMAP4_ENABLE_SHIFT 8
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index aa30a3c20883..93d102535c85 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -26,9 +26,9 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/console.h>
+#include <linux/omap-dma.h>
#include <plat/omap-serial.h>
-#include <plat-omap/dma-omap.h>
#include "common.h"
#include "omap_hwmod.h"
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index b0e77a407047..b9753fe27232 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -121,6 +121,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->senn_mod = 0x1;
sr_data->senp_mod = 0x1;
+ if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
+ sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+ sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
+ if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
+ sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+ sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+ } else {
+ sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+ sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+ }
+ }
+
sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
if (!sr_data->voltdm) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index a8795ff19e6d..c5a3c6f9504e 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -27,180 +27,88 @@ static u8 async_cs, sync_cs;
static unsigned refclk_psec;
-/* t2_ps, when quantized to fclk units, must happen no earlier than
- * the clock after after t1_NS.
- *
- * Return a possibly updated value of t2_ps, converted to nsec.
- */
-static unsigned
-next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
-{
- unsigned t1_ps = t1_NS * 1000;
- unsigned t1_f, t2_f;
-
- if ((t1_ps + fclk_ps) < t2_ps)
- return t2_ps / 1000;
-
- t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
- t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
-
- if (t1_f >= t2_f)
- t2_f = t1_f + 1;
-
- return (t2_f * fclk_ps) / 1000;
-}
-
/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static int tusb_set_async_mode(unsigned sysclk_ps)
{
+ struct gpmc_device_timings dev_t;
struct gpmc_timings t;
unsigned t_acsnh_advnh = sysclk_ps + 3000;
- unsigned tmp;
-
- memset(&t, 0, sizeof(t));
-
- /* CS_ON = t_acsnh_acsnl */
- t.cs_on = 8;
- /* ADV_ON = t_acsnh_advnh - t_advn */
- t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
-
- /*
- * READ ... from omap2420 TRM fig 12-13
- */
-
- /* ADV_RD_OFF = t_acsnh_advnh */
- t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
-
- /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
- t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
-
- /* ACCESS = counters continue only after nRDY */
- tmp = t.oe_on * 1000 + 300;
- t.access = next_clk(t.oe_on, tmp, fclk_ps);
-
- /* OE_OFF = after data gets sampled */
- tmp = t.access * 1000;
- t.oe_off = next_clk(t.access, tmp, fclk_ps);
-
- t.cs_rd_off = t.oe_off;
-
- tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
- t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
-
- /*
- * WRITE ... from omap2420 TRM fig 12-15
- */
-
- /* ADV_WR_OFF = t_acsnh_advnh */
- t.adv_wr_off = t.adv_rd_off;
- /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
- t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
+ memset(&dev_t, 0, sizeof(dev_t));
- /* WE_OFF = after data gets sampled */
- tmp = t.we_on * 1000 + 300;
- t.we_off = next_clk(t.we_on, tmp, fclk_ps);
+ dev_t.mux = true;
- t.cs_wr_off = t.we_off;
+ dev_t.t_ceasu = 8 * 1000;
+ dev_t.t_avdasu = t_acsnh_advnh - 7000;
+ dev_t.t_ce_avd = 1000;
+ dev_t.t_avdp_r = t_acsnh_advnh;
+ dev_t.t_oeasu = t_acsnh_advnh + 1000;
+ dev_t.t_oe = 300;
+ dev_t.t_cez_r = 7000;
+ dev_t.t_cez_w = dev_t.t_cez_r;
+ dev_t.t_avdp_w = t_acsnh_advnh;
+ dev_t.t_weasu = t_acsnh_advnh + 1000;
+ dev_t.t_wpl = 300;
+ dev_t.cyc_aavdh_we = 1;
- tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
- t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+ gpmc_calc_timings(&t, &dev_t);
return gpmc_cs_set_timings(async_cs, &t);
}
-static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static int tusb_set_sync_mode(unsigned sysclk_ps)
{
+ struct gpmc_device_timings dev_t;
struct gpmc_timings t;
unsigned t_scsnh_advnh = sysclk_ps + 3000;
- unsigned tmp;
-
- memset(&t, 0, sizeof(t));
- t.cs_on = 8;
-
- /* ADV_ON = t_acsnh_advnh - t_advn */
- t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
-
- /* GPMC_CLK rate = fclk rate / div */
- t.sync_clk = 11100 /* 11.1 nsec */;
- tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
- if (tmp > 4)
- return -ERANGE;
- if (tmp == 0)
- tmp = 1;
- t.page_burst_access = (fclk_ps * tmp) / 1000;
-
- /*
- * READ ... based on omap2420 TRM fig 12-19, 12-20
- */
-
- /* ADV_RD_OFF = t_scsnh_advnh */
- t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
-
- /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
- tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
- t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
-
- /* ACCESS = number of clock cycles after t_adv_eon */
- tmp = (t.oe_on * 1000) + (5 * fclk_ps);
- t.access = next_clk(t.oe_on, tmp, fclk_ps);
- /* OE_OFF = after data gets sampled */
- tmp = (t.access * 1000) + (1 * fclk_ps);
- t.oe_off = next_clk(t.access, tmp, fclk_ps);
-
- t.cs_rd_off = t.oe_off;
-
- tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
- t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
-
- /*
- * WRITE ... based on omap2420 TRM fig 12-21
- */
-
- /* ADV_WR_OFF = t_scsnh_advnh */
- t.adv_wr_off = t.adv_rd_off;
-
- /* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
- tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
- t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
-
- /* WE_OFF = number of clock cycles after t_adv_wen */
- tmp = (t.we_on * 1000) + (6 * fclk_ps);
- t.we_off = next_clk(t.we_on, tmp, fclk_ps);
-
- t.cs_wr_off = t.we_off;
-
- tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
- t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+ memset(&dev_t, 0, sizeof(dev_t));
+
+ dev_t.mux = true;
+ dev_t.sync_read = true;
+ dev_t.sync_write = true;
+
+ dev_t.clk = 11100;
+ dev_t.t_bacc = 1000;
+ dev_t.t_ces = 1000;
+ dev_t.t_ceasu = 8 * 1000;
+ dev_t.t_avdasu = t_scsnh_advnh - 7000;
+ dev_t.t_ce_avd = 1000;
+ dev_t.t_avdp_r = t_scsnh_advnh;
+ dev_t.cyc_aavdh_oe = 3;
+ dev_t.cyc_oe = 5;
+ dev_t.t_ce_rdyz = 7000;
+ dev_t.t_avdp_w = t_scsnh_advnh;
+ dev_t.cyc_aavdh_we = 3;
+ dev_t.cyc_wpl = 6;
+ dev_t.t_ce_rdyz = 7000;
+
+ gpmc_calc_timings(&t, &dev_t);
return gpmc_cs_set_timings(sync_cs, &t);
}
-extern unsigned long gpmc_get_fclk_period(void);
-
/* tusb driver calls this when it changes the chip's clocking */
int tusb6010_platform_retime(unsigned is_refclk)
{
static const char error[] =
KERN_ERR "tusb6010 %s retime error %d\n";
- unsigned fclk_ps = gpmc_get_fclk_period();
unsigned sysclk_ps;
int status;
- if (!refclk_psec || fclk_ps == 0)
+ if (!refclk_psec)
return -ENODEV;
sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
- status = tusb_set_async_mode(sysclk_ps, fclk_ps);
+ status = tusb_set_async_mode(sysclk_ps);
if (status < 0) {
printk(error, "async", status);
goto done;
}
- status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
+ status = tusb_set_sync_mode(sysclk_ps);
if (status < 0)
printk(error, "sync", status);
done:
@@ -284,7 +192,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
| GPMC_CONFIG1_READTYPE_SYNC
| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
| GPMC_CONFIG1_WRITETYPE_SYNC
- | GPMC_CONFIG1_CLKACTIVATIONTIME(1)
| GPMC_CONFIG1_PAGE_LEN(2)
| GPMC_CONFIG1_WAIT_READ_MON
| GPMC_CONFIG1_WAIT_WRITE_MON
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 75878c37959b..49ac7977e03e 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -11,13 +11,20 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/bug.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+
+#include "iomap.h"
#include "soc.h"
#include "voltage.h"
#include "vc.h"
#include "prm-regbits-34xx.h"
#include "prm-regbits-44xx.h"
#include "prm44xx.h"
+#include "pm.h"
+#include "scrm44xx.h"
+#include "control.h"
/**
* struct omap_vc_channel_cfg - describe the cfg_channel bitfield
@@ -63,6 +70,9 @@ static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
};
static struct omap_vc_channel_cfg *vc_cfg_bits;
+
+/* Default I2C trace length on pcb, 6.3cm. Used for capacitance calculations. */
+static u32 sr_i2c_pcb_length = 63;
#define CFG_CHANNEL_MASK 0x1f
/**
@@ -135,6 +145,8 @@ int omap_vc_pre_scale(struct voltagedomain *voltdm,
vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
voltdm->write(vc_cmdval, vc->cmdval_reg);
+ voltdm->vc_param->on = target_volt;
+
omap_vp_update_errorgain(voltdm, target_volt);
return 0;
@@ -202,46 +214,389 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
return 0;
}
-static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+/* Convert microsecond value to number of 32kHz clock cycles */
+static inline u32 omap_usec_to_32k(u32 usec)
+{
+ return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
+}
+
+/* Set oscillator setup time for omap3 */
+static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
+{
+ voltdm->write(omap_usec_to_32k(usec), OMAP3_PRM_CLKSETUP_OFFSET);
+}
+
+/**
+ * omap3_set_i2c_timings - sets i2c sleep timings for a channel
+ * @voltdm: channel to configure
+ * @off_mode: select whether retention or off mode values used
+ *
+ * Calculates and sets up voltage controller to use I2C based
+ * voltage scaling for sleep modes. This can be used for either off mode
+ * or retention. Off mode has additionally an option to use sys_off_mode
+ * pad, which uses a global signal to program the whole power IC to
+ * off-mode.
+ */
+static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
{
+ unsigned long voltsetup1;
+ u32 tgt_volt;
+
+ /*
+ * Oscillator is shut down only if we are using sys_off_mode pad,
+ * thus we set a minimal setup time here
+ */
+ omap3_set_clksetup(1, voltdm);
+
+ if (off_mode)
+ tgt_volt = voltdm->vc_param->off;
+ else
+ tgt_volt = voltdm->vc_param->ret;
+
+ voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
+ voltdm->pmic->slew_rate;
+
+ voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
+
+ voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+ voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
+ voltdm->vfsm->voltsetup_reg);
+
/*
- * Voltage Manager FSM parameters init
- * XXX This data should be passed in from the board file
+ * pmic is not controlling the voltage scaling during retention,
+ * thus set voltsetup2 to 0
*/
- voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
- voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
- voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+ voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
}
-static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+/**
+ * omap3_set_off_timings - sets off-mode timings for a channel
+ * @voltdm: channel to configure
+ *
+ * Calculates and sets up off-mode timings for a channel. Off-mode
+ * can use either I2C based voltage scaling, or alternatively
+ * sys_off_mode pad can be used to send a global command to power IC.
+ * This function first checks which mode is being used, and calls
+ * omap3_set_i2c_timings() if the system is using I2C control mode.
+ * sys_off_mode has the additional benefit that voltages can be
+ * scaled to zero volt level with TWL4030 / TWL5030, I2C can only
+ * scale to 600mV.
+ */
+static void omap3_set_off_timings(struct voltagedomain *voltdm)
{
- static bool is_initialized;
+ unsigned long clksetup;
+ unsigned long voltsetup2;
+ unsigned long voltsetup2_old;
+ u32 val;
+ u32 tstart, tshut;
- if (is_initialized)
+ /* check if sys_off_mode is used to control off-mode voltages */
+ val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
+ if (!(val & OMAP3430_SEL_OFF_MASK)) {
+ /* No, omap is controlling them over I2C */
+ omap3_set_i2c_timings(voltdm, true);
return;
+ }
+
+ omap_pm_get_oscillator(&tstart, &tshut);
+ omap3_set_clksetup(tstart, voltdm);
+
+ clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
+
+ /* voltsetup 2 in us */
+ voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
+
+ /* convert to 32k clk cycles */
+ voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
+
+ voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+ /*
+ * Update voltsetup2 if higher than current value (needed because
+ * we have multiple channels with different ramp times), also
+ * update voltoffset always to value recommended by TRM
+ */
+ if (voltsetup2 > voltsetup2_old) {
+ voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+ voltdm->write(clksetup - voltsetup2,
+ OMAP3_PRM_VOLTOFFSET_OFFSET);
+ } else
+ voltdm->write(clksetup - voltsetup2_old,
+ OMAP3_PRM_VOLTOFFSET_OFFSET);
+
+ /*
+ * omap is not controlling voltage scaling during off-mode,
+ * thus set voltsetup1 to 0
+ */
+ voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
+ voltdm->vfsm->voltsetup_reg);
+
+ /* voltoffset must be clksetup minus voltsetup2 according to TRM */
+ voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+ omap3_set_off_timings(voltdm);
+}
+
+/**
+ * omap4_calc_volt_ramp - calculates voltage ramping delays on omap4
+ * @voltdm: channel to calculate values for
+ * @voltage_diff: voltage difference in microvolts
+ *
+ * Calculates voltage ramp prescaler + counter values for a voltage
+ * difference on omap4. Returns a field value suitable for writing to
+ * VOLTSETUP register for a channel in following format:
+ * bits[8:9] prescaler ... bits[0:5] counter. See OMAP4 TRM for reference.
+ */
+static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff)
+{
+ u32 prescaler;
+ u32 cycles;
+ u32 time;
+
+ time = voltage_diff / voltdm->pmic->slew_rate;
+
+ cycles = voltdm->sys_clk.rate / 1000 * time / 1000;
+
+ cycles /= 64;
+ prescaler = 0;
+
+ /* shift to next prescaler until no overflow */
+
+ /* scale for div 256 = 64 * 4 */
+ if (cycles > 63) {
+ cycles /= 4;
+ prescaler++;
+ }
+
+ /* scale for div 512 = 256 * 2 */
+ if (cycles > 63) {
+ cycles /= 2;
+ prescaler++;
+ }
+
+ /* scale for div 2048 = 512 * 4 */
+ if (cycles > 63) {
+ cycles /= 4;
+ prescaler++;
+ }
+
+ /* check for overflow => invalid ramp time */
+ if (cycles > 63) {
+ pr_warn("%s: invalid setuptime for vdd_%s\n", __func__,
+ voltdm->name);
+ return 0;
+ }
+
+ cycles++;
- omap3_vfsm_init(voltdm);
+ return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
+ (cycles << OMAP4430_RAMP_UP_COUNT_SHIFT);
+}
+
+/**
+ * omap4_usec_to_val_scrm - convert microsecond value to SCRM module bitfield
+ * @usec: microseconds
+ * @shift: number of bits to shift left
+ * @mask: bitfield mask
+ *
+ * Converts microsecond value to OMAP4 SCRM bitfield. Bitfield is
+ * shifted to requested position, and checked agains the mask value.
+ * If larger, forced to the max value of the field (i.e. the mask itself.)
+ * Returns the SCRM bitfield value.
+ */
+static u32 omap4_usec_to_val_scrm(u32 usec, int shift, u32 mask)
+{
+ u32 val;
+
+ val = omap_usec_to_32k(usec) << shift;
- is_initialized = true;
+ /* Check for overflow, if yes, force to max value */
+ if (val > mask)
+ val = mask;
+
+ return val;
}
+/**
+ * omap4_set_timings - set voltage ramp timings for a channel
+ * @voltdm: channel to configure
+ * @off_mode: whether off-mode values are used
+ *
+ * Calculates and sets the voltage ramp up / down values for a channel.
+ */
+static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode)
+{
+ u32 val;
+ u32 ramp;
+ int offset;
+ u32 tstart, tshut;
+
+ if (off_mode) {
+ ramp = omap4_calc_volt_ramp(voltdm,
+ voltdm->vc_param->on - voltdm->vc_param->off);
+ offset = voltdm->vfsm->voltsetup_off_reg;
+ } else {
+ ramp = omap4_calc_volt_ramp(voltdm,
+ voltdm->vc_param->on - voltdm->vc_param->ret);
+ offset = voltdm->vfsm->voltsetup_reg;
+ }
+
+ if (!ramp)
+ return;
+
+ val = voltdm->read(offset);
+
+ val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT;
+
+ val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT;
+
+ voltdm->write(val, offset);
+
+ omap_pm_get_oscillator(&tstart, &tshut);
+
+ val = omap4_usec_to_val_scrm(tstart, OMAP4_SETUPTIME_SHIFT,
+ OMAP4_SETUPTIME_MASK);
+ val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT,
+ OMAP4_DOWNTIME_MASK);
+
+ __raw_writel(val, OMAP4_SCRM_CLKSETUPTIME);
+}
/* OMAP4 specific voltage init functions */
static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
{
- static bool is_initialized;
- u32 vc_val;
+ omap4_set_timings(voltdm, true);
+ omap4_set_timings(voltdm, false);
+}
+
+struct i2c_init_data {
+ u8 loadbits;
+ u8 load;
+ u8 hsscll_38_4;
+ u8 hsscll_26;
+ u8 hsscll_19_2;
+ u8 hsscll_16_8;
+ u8 hsscll_12;
+};
- if (is_initialized)
+static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = {
+ {
+ .load = 50,
+ .loadbits = 0x3,
+ .hsscll_38_4 = 13,
+ .hsscll_26 = 11,
+ .hsscll_19_2 = 9,
+ .hsscll_16_8 = 9,
+ .hsscll_12 = 8,
+ },
+ {
+ .load = 25,
+ .loadbits = 0x2,
+ .hsscll_38_4 = 13,
+ .hsscll_26 = 11,
+ .hsscll_19_2 = 9,
+ .hsscll_16_8 = 9,
+ .hsscll_12 = 8,
+ },
+ {
+ .load = 12,
+ .loadbits = 0x1,
+ .hsscll_38_4 = 11,
+ .hsscll_26 = 10,
+ .hsscll_19_2 = 9,
+ .hsscll_16_8 = 9,
+ .hsscll_12 = 8,
+ },
+ {
+ .load = 0,
+ .loadbits = 0x0,
+ .hsscll_38_4 = 12,
+ .hsscll_26 = 10,
+ .hsscll_19_2 = 9,
+ .hsscll_16_8 = 8,
+ .hsscll_12 = 8,
+ },
+};
+
+/**
+ * omap4_vc_i2c_timing_init - sets up board I2C timing parameters
+ * @voltdm: voltagedomain pointer to get data from
+ *
+ * Use PMIC + board supplied settings for calculating the total I2C
+ * channel capacitance and set the timing parameters based on this.
+ * Pre-calculated values are provided in data tables, as it is not
+ * too straightforward to calculate these runtime.
+ */
+static void __init omap4_vc_i2c_timing_init(struct voltagedomain *voltdm)
+{
+ u32 capacitance;
+ u32 val;
+ u16 hsscll;
+ const struct i2c_init_data *i2c_data;
+
+ if (!voltdm->pmic->i2c_high_speed) {
+ pr_warn("%s: only high speed supported!\n", __func__);
return;
+ }
+
+ /* PCB trace capacitance, 0.125pF / mm => mm / 8 */
+ capacitance = DIV_ROUND_UP(sr_i2c_pcb_length, 8);
+
+ /* OMAP pad capacitance */
+ capacitance += 4;
+
+ /* PMIC pad capacitance */
+ capacitance += voltdm->pmic->i2c_pad_load;
+
+ /* Search for capacitance match in the table */
+ i2c_data = omap4_i2c_timing_data;
+
+ while (i2c_data->load > capacitance)
+ i2c_data++;
+
+ /* Select proper values based on sysclk frequency */
+ switch (voltdm->sys_clk.rate) {
+ case 38400000:
+ hsscll = i2c_data->hsscll_38_4;
+ break;
+ case 26000000:
+ hsscll = i2c_data->hsscll_26;
+ break;
+ case 19200000:
+ hsscll = i2c_data->hsscll_19_2;
+ break;
+ case 16800000:
+ hsscll = i2c_data->hsscll_16_8;
+ break;
+ case 12000000:
+ hsscll = i2c_data->hsscll_12;
+ break;
+ default:
+ pr_warn("%s: unsupported sysclk rate: %d!\n", __func__,
+ voltdm->sys_clk.rate);
+ return;
+ }
- /* XXX These are magic numbers and do not belong! */
- vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
- voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+ /* Loadbits define pull setup for the I2C channels */
+ val = i2c_data->loadbits << 25 | i2c_data->loadbits << 29;
- is_initialized = true;
+ /* Write to SYSCTRL_PADCONF_WKUP_CTRL_I2C_2 to setup I2C pull */
+ __raw_writel(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP +
+ OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2));
+
+ /* HSSCLH can always be zero */
+ val = hsscll << OMAP4430_HSSCLL_SHIFT;
+ val |= (0x28 << OMAP4430_SCLL_SHIFT | 0x2c << OMAP4430_SCLH_SHIFT);
+
+ /* Write setup times to I2C config register */
+ voltdm->write(val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
}
+
+
/**
* omap_vc_i2c_init - initialize I2C interface to PMIC
* @voltdm: voltage domain containing VC data
@@ -281,9 +636,51 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
mcode << __ffs(vc->common->i2c_mcode_mask),
vc->common->i2c_cfg_reg);
+ if (cpu_is_omap44xx())
+ omap4_vc_i2c_timing_init(voltdm);
+
initialized = true;
}
+/**
+ * omap_vc_calc_vsel - calculate vsel value for a channel
+ * @voltdm: channel to calculate value for
+ * @uvolt: microvolt value to convert to vsel
+ *
+ * Converts a microvolt value to vsel value for the used PMIC.
+ * This checks whether the microvolt value is out of bounds, and
+ * adjusts the value accordingly. If unsupported value detected,
+ * warning is thrown.
+ */
+static u8 omap_vc_calc_vsel(struct voltagedomain *voltdm, u32 uvolt)
+{
+ if (voltdm->pmic->vddmin > uvolt)
+ uvolt = voltdm->pmic->vddmin;
+ if (voltdm->pmic->vddmax < uvolt) {
+ WARN(1, "%s: voltage not supported by pmic: %u vs max %u\n",
+ __func__, uvolt, voltdm->pmic->vddmax);
+ /* Lets try maximum value anyway */
+ uvolt = voltdm->pmic->vddmax;
+ }
+
+ return voltdm->pmic->uv_to_vsel(uvolt);
+}
+
+#ifdef CONFIG_PM
+/**
+ * omap_pm_setup_sr_i2c_pcb_length - set length of SR I2C traces on PCB
+ * @mm: length of the PCB trace in millimetres
+ *
+ * Sets the PCB trace length for the I2C channel. By default uses 63mm.
+ * This is needed for properly calculating the capacitance value for
+ * the PCB trace, and for setting the SR I2C channel timing parameters.
+ */
+void __init omap_pm_setup_sr_i2c_pcb_length(u32 mm)
+{
+ sr_i2c_pcb_length = mm;
+}
+#endif
+
void __init omap_vc_init_channel(struct voltagedomain *voltdm)
{
struct omap_vc_channel *vc = voltdm->vc;
@@ -311,7 +708,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
- vc->setup_time = voltdm->pmic->volt_setup_time;
/* Configure the i2c slave address for this VC */
voltdm->rmw(vc->smps_sa_mask,
@@ -331,14 +727,18 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
voltdm->rmw(vc->smps_cmdra_mask,
vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
vc->smps_cmdra_reg);
- vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+ vc->cfg_channel |= vc_cfg_bits->rac;
}
+ if (vc->cmd_reg_addr == vc->volt_reg_addr)
+ vc->cfg_channel |= vc_cfg_bits->racen;
+
/* Set up the on, inactive, retention and off voltage */
- on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
- onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
- ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
- off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+ on_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->on);
+ onlp_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->onlp);
+ ret_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->ret);
+ off_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->off);
+
val = ((on_vsel << vc->common->cmd_on_shift) |
(onlp_vsel << vc->common->cmd_onlp_shift) |
(ret_vsel << vc->common->cmd_ret_shift) |
@@ -349,11 +749,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
/* Channel configuration */
omap_vc_config_channel(voltdm);
- /* Configure the setup times */
- voltdm->rmw(voltdm->vfsm->voltsetup_mask,
- vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
- voltdm->vfsm->voltsetup_reg);
-
omap_vc_i2c_init(voltdm);
if (cpu_is_omap34xx())
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index 478bf6b432c4..91c8d75bf2ea 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -86,7 +86,6 @@ struct omap_vc_channel {
u16 i2c_slave_addr;
u16 volt_reg_addr;
u16 cmd_reg_addr;
- u16 setup_time;
u8 cfg_channel;
bool i2c_high_speed;
@@ -111,6 +110,13 @@ extern struct omap_vc_channel omap4_vc_mpu;
extern struct omap_vc_channel omap4_vc_iva;
extern struct omap_vc_channel omap4_vc_core;
+extern struct omap_vc_param omap3_mpu_vc_data;
+extern struct omap_vc_param omap3_core_vc_data;
+
+extern struct omap_vc_param omap4_mpu_vc_data;
+extern struct omap_vc_param omap4_iva_vc_data;
+extern struct omap_vc_param omap4_core_vc_data;
+
void omap_vc_init_channel(struct voltagedomain *voltdm);
int omap_vc_pre_scale(struct voltagedomain *voltdm,
unsigned long target_volt,
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index 5d8eaf31569c..75bc4aa22b3a 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -71,3 +71,25 @@ struct omap_vc_channel omap3_vc_core = {
.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
};
+
+/*
+ * Voltage levels for different operating modes: on, sleep, retention and off
+ */
+#define OMAP3_ON_VOLTAGE_UV 1200000
+#define OMAP3_ONLP_VOLTAGE_UV 1000000
+#define OMAP3_RET_VOLTAGE_UV 975000
+#define OMAP3_OFF_VOLTAGE_UV 600000
+
+struct omap_vc_param omap3_mpu_vc_data = {
+ .on = OMAP3_ON_VOLTAGE_UV,
+ .onlp = OMAP3_ONLP_VOLTAGE_UV,
+ .ret = OMAP3_RET_VOLTAGE_UV,
+ .off = OMAP3_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap3_core_vc_data = {
+ .on = OMAP3_ON_VOLTAGE_UV,
+ .onlp = OMAP3_ONLP_VOLTAGE_UV,
+ .ret = OMAP3_RET_VOLTAGE_UV,
+ .off = OMAP3_OFF_VOLTAGE_UV,
+};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index d70b930f2739..085e5d6a04fd 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -87,3 +87,31 @@ struct omap_vc_channel omap4_vc_core = {
.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
};
+/*
+ * Voltage levels for different operating modes: on, sleep, retention and off
+ */
+#define OMAP4_ON_VOLTAGE_UV 1375000
+#define OMAP4_ONLP_VOLTAGE_UV 1375000
+#define OMAP4_RET_VOLTAGE_UV 837500
+#define OMAP4_OFF_VOLTAGE_UV 0
+
+struct omap_vc_param omap4_mpu_vc_data = {
+ .on = OMAP4_ON_VOLTAGE_UV,
+ .onlp = OMAP4_ONLP_VOLTAGE_UV,
+ .ret = OMAP4_RET_VOLTAGE_UV,
+ .off = OMAP4_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap4_iva_vc_data = {
+ .on = OMAP4_ON_VOLTAGE_UV,
+ .onlp = OMAP4_ONLP_VOLTAGE_UV,
+ .ret = OMAP4_RET_VOLTAGE_UV,
+ .off = OMAP4_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap4_core_vc_data = {
+ .on = OMAP4_ON_VOLTAGE_UV,
+ .onlp = OMAP4_ONLP_VOLTAGE_UV,
+ .ret = OMAP4_RET_VOLTAGE_UV,
+ .off = OMAP4_OFF_VOLTAGE_UV,
+};
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 7283b7ed7de8..a0ce4f10ff13 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -40,12 +40,14 @@ struct powerdomain;
* data
* @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
* @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
+ * @voltsetup_off_reg: register offset of PRM_VOLTSETUP_OFF from PRM base
*
* XXX What about VOLTOFFSET/VOLTCTRL?
*/
struct omap_vfsm_instance {
u32 voltsetup_mask;
u8 voltsetup_reg;
+ u8 voltsetup_off_reg;
};
/**
@@ -74,6 +76,8 @@ struct voltagedomain {
const struct omap_vfsm_instance *vfsm;
struct omap_vp_instance *vp;
struct omap_voltdm_pmic *pmic;
+ struct omap_vp_param *vp_param;
+ struct omap_vc_param *vc_param;
/* VC/VP register access functions: SoC specific */
u32 (*read) (u8 offset);
@@ -92,6 +96,24 @@ struct voltagedomain {
struct omap_volt_data *volt_data;
};
+/* Min and max voltages from OMAP perspective */
+#define OMAP3430_VP1_VLIMITTO_VDDMIN 850000
+#define OMAP3430_VP1_VLIMITTO_VDDMAX 1425000
+#define OMAP3430_VP2_VLIMITTO_VDDMIN 900000
+#define OMAP3430_VP2_VLIMITTO_VDDMAX 1150000
+
+#define OMAP3630_VP1_VLIMITTO_VDDMIN 900000
+#define OMAP3630_VP1_VLIMITTO_VDDMAX 1350000
+#define OMAP3630_VP2_VLIMITTO_VDDMIN 900000
+#define OMAP3630_VP2_VLIMITTO_VDDMAX 1200000
+
+#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 830000
+#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 1410000
+#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 830000
+#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 1260000
+#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 830000
+#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 1200000
+
/**
* struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
* @slew_rate: PMIC slew rate (in uv/us)
@@ -107,26 +129,34 @@ struct voltagedomain {
struct omap_voltdm_pmic {
int slew_rate;
int step_size;
- u32 on_volt;
- u32 onlp_volt;
- u32 ret_volt;
- u32 off_volt;
- u16 volt_setup_time;
u16 i2c_slave_addr;
u16 volt_reg_addr;
u16 cmd_reg_addr;
u8 vp_erroroffset;
u8 vp_vstepmin;
u8 vp_vstepmax;
- u8 vp_vddmin;
- u8 vp_vddmax;
+ u32 vddmin;
+ u32 vddmax;
u8 vp_timeout_us;
bool i2c_high_speed;
+ u32 i2c_pad_load;
u8 i2c_mcode;
unsigned long (*vsel_to_uv) (const u8 vsel);
u8 (*uv_to_vsel) (unsigned long uV);
};
+struct omap_vp_param {
+ u32 vddmax;
+ u32 vddmin;
+};
+
+struct omap_vc_param {
+ u32 on;
+ u32 onlp;
+ u32 ret;
+ u32 off;
+};
+
void omap_voltage_get_volttable(struct voltagedomain *voltdm,
struct omap_volt_data **volt_data);
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index 63afbfed3cbc..261bb7cb4e60 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -117,6 +117,11 @@ void __init omap3xxx_voltagedomains_init(void)
}
#endif
+ omap3_voltdm_mpu.vp_param = &omap3_mpu_vp_data;
+ omap3_voltdm_core.vp_param = &omap3_core_vp_data;
+ omap3_voltdm_mpu.vc_param = &omap3_mpu_vc_data;
+ omap3_voltdm_core.vc_param = &omap3_core_vc_data;
+
if (soc_is_am35xx())
voltdms = voltagedomains_am35xx;
else
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index c3115f6853d4..48b22a0a0c88 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -22,7 +22,7 @@
#include <linux/init.h>
#include "common.h"
-
+#include "soc.h"
#include "prm-regbits-44xx.h"
#include "prm44xx.h"
#include "prcm44xx.h"
@@ -34,14 +34,17 @@
static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
+ .voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_MPU_OFF_OFFSET,
};
static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+ .voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_IVA_OFF_OFFSET,
};
static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+ .voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_CORE_OFF_OFFSET,
};
static struct voltagedomain omap4_voltdm_mpu = {
@@ -101,11 +104,25 @@ void __init omap44xx_voltagedomains_init(void)
* for the currently-running IC
*/
#ifdef CONFIG_PM_OPP
- omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
- omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
- omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
+ if (cpu_is_omap443x()) {
+ omap4_voltdm_mpu.volt_data = omap443x_vdd_mpu_volt_data;
+ omap4_voltdm_iva.volt_data = omap443x_vdd_iva_volt_data;
+ omap4_voltdm_core.volt_data = omap443x_vdd_core_volt_data;
+ } else if (cpu_is_omap446x()) {
+ omap4_voltdm_mpu.volt_data = omap446x_vdd_mpu_volt_data;
+ omap4_voltdm_iva.volt_data = omap446x_vdd_iva_volt_data;
+ omap4_voltdm_core.volt_data = omap446x_vdd_core_volt_data;
+ }
#endif
+ omap4_voltdm_mpu.vp_param = &omap4_mpu_vp_data;
+ omap4_voltdm_iva.vp_param = &omap4_iva_vp_data;
+ omap4_voltdm_core.vp_param = &omap4_core_vp_data;
+
+ omap4_voltdm_mpu.vc_param = &omap4_mpu_vc_data;
+ omap4_voltdm_iva.vc_param = &omap4_iva_vc_data;
+ omap4_voltdm_core.vc_param = &omap4_core_vc_data;
+
for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
voltdm->sys_clk.name = sys_clk_name;
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index 85241b828c02..a3c30655aa30 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -58,8 +58,10 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
sys_clk_rate = voltdm->sys_clk.rate / 1000;
timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
- vddmin = voltdm->pmic->vp_vddmin;
- vddmax = voltdm->pmic->vp_vddmax;
+ vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin);
+ vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax);
+ vddmin = voltdm->pmic->uv_to_vsel(vddmin);
+ vddmax = voltdm->pmic->uv_to_vsel(vddmax);
waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
1000 * voltdm->pmic->slew_rate);
@@ -138,7 +140,7 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
udelay(1);
}
if (timeout >= VP_TRANXDONE_TIMEOUT) {
- pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted",
+ pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted\n",
__func__, voltdm->name);
return -ETIMEDOUT;
}
@@ -197,7 +199,7 @@ void omap_vp_enable(struct voltagedomain *voltdm)
u32 vpconfig, volt;
if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
+ pr_warn("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -214,8 +216,8 @@ void omap_vp_enable(struct voltagedomain *voltdm)
volt = voltdm_get_voltage(voltdm);
if (!volt) {
- pr_warning("%s: unable to find current voltage for %s\n",
- __func__, voltdm->name);
+ pr_warn("%s: unable to find current voltage for %s\n",
+ __func__, voltdm->name);
return;
}
@@ -242,7 +244,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
int timeout;
if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
+ pr_warn("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -272,8 +274,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
VP_IDLE_TIMEOUT, timeout);
if (timeout >= VP_IDLE_TIMEOUT)
- pr_warning("%s: vdd_%s idle timedout\n",
- __func__, voltdm->name);
+ pr_warn("%s: vdd_%s idle timedout\n", __func__, voltdm->name);
vp->enabled = false;
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7c155d248aa3..0fdf7080e4a6 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -117,6 +117,13 @@ extern struct omap_vp_instance omap4_vp_mpu;
extern struct omap_vp_instance omap4_vp_iva;
extern struct omap_vp_instance omap4_vp_core;
+extern struct omap_vp_param omap3_mpu_vp_data;
+extern struct omap_vp_param omap3_core_vp_data;
+
+extern struct omap_vp_param omap4_mpu_vp_data;
+extern struct omap_vp_param omap4_iva_vp_data;
+extern struct omap_vp_param omap4_core_vp_data;
+
void omap_vp_init(struct voltagedomain *voltdm);
void omap_vp_enable(struct voltagedomain *voltdm);
void omap_vp_disable(struct voltagedomain *voltdm);
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index bd89f80089f5..1914e026245e 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -77,3 +77,13 @@ struct omap_vp_instance omap3_vp_core = {
.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
};
+
+struct omap_vp_param omap3_mpu_vp_data = {
+ .vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
+ .vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap3_core_vp_data = {
+ .vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
+ .vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
+};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
index 8c031d16879e..e62f6b018beb 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -87,3 +87,18 @@ struct omap_vp_instance omap4_vp_core = {
.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
};
+
+struct omap_vp_param omap4_mpu_vp_data = {
+ .vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
+ .vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap4_iva_vp_data = {
+ .vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
+ .vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap4_core_vp_data = {
+ .vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
+ .vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
+};
diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-map.h b/arch/arm/mach-s3c24xx/include/mach/bast-map.h
index 6e7dc9d0cf0e..eecea2a50f8f 100644
--- a/arch/arm/mach-s3c24xx/include/mach/bast-map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/bast-map.h
@@ -74,7 +74,7 @@
/* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
* the correct access is made
*
* 0x10000000 of space, partitioned as so:
diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h
index ee99fd56c043..6b72d5a4b377 100644
--- a/arch/arm/mach-s3c24xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c24xx/include/mach/dma.h
@@ -88,7 +88,7 @@ enum s3c2410_dma_state {
*
* This represents the state of the DMA engine, wrt to the loaded / running
* transfers. Since we don't have any way of knowing exactly the state of
- * the DMA transfers, we need to know the state to make decisions on wether
+ * the DMA transfers, we need to know the state to make decisions on whether
* we can
*
* S3C2410_DMA_NONE
diff --git a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h b/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
index 99612fcc4eb2..28376e56dd3b 100644
--- a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
@@ -51,7 +51,7 @@
#define VR1000_VA_PC104_IRQMASK VR1000_IOADDR(0x00600000)
/* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
* the correct access is made
*
* 0x10000000 of space, partitioned as so:
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 4a963467b7ee..973b87ca87f4 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -521,7 +521,6 @@ static struct platform_device *gta02_devices[] __initdata = {
&gta02_nor_flash,
&s3c24xx_pwm_device,
&s3c_device_iis,
- &samsung_asoc_dma,
&s3c_device_i2c0,
&gta02_dfbmcs320_device,
&gta02_buttons_device,
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index 63aaf076f611..b23dd1b106e8 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -632,7 +632,6 @@ static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
- &samsung_asoc_dma,
&s3c_device_usbgadget,
&h1940_device_leds,
&h1940_device_bluetooth,
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 393c0f1ac11a..a31d5b83e5f7 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -519,7 +519,6 @@ static struct platform_device *mini2440_devices[] __initdata = {
&s3c_device_iis,
&uda1340_codec,
&mini2440_audio,
- &samsung_asoc_dma,
};
static void __init mini2440_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 379fde521d37..0606f2faaa5c 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -712,7 +712,6 @@ static struct platform_device *rx1950_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
- &samsung_asoc_dma,
&s3c_device_usbgadget,
&s3c_device_rtc,
&s3c_device_nand,
diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c
index 60627e63a254..724755f0b0f5 100644
--- a/arch/arm/mach-s3c24xx/pm.c
+++ b/arch/arm/mach-s3c24xx/pm.c
@@ -121,7 +121,7 @@ void s3c_pm_configure_extint(void)
int pin;
/* for each of the external interrupts (EINT0..EINT15) we
- * need to check wether it is an external interrupt source,
+ * need to check whether it is an external interrupt source,
* and then configure it as an input if it is not
*/
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 701f421de1a8..cdde249166b5 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -379,7 +379,6 @@ static struct platform_device *crag6410_devices[] __initdata = {
&s3c_device_timer[0],
&s3c64xx_device_iis0,
&s3c64xx_device_iis1,
- &samsung_asoc_dma,
&samsung_device_keypad,
&crag6410_gpio_keydev,
&crag6410_dm9k_device,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index da1a771a29e9..574a9eef588d 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -275,7 +275,6 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_fb,
&s3c_device_ohci,
&s3c_device_usb_hsotg,
- &samsung_asoc_dma,
&s3c64xx_device_iisv4,
&samsung_device_keypad,
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 96ea1fe0ec94..1af823558c60 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -165,7 +165,6 @@ static struct platform_device *smdk6440_devices[] __initdata = {
&s3c_device_i2c1,
&s3c_device_ts,
&s3c_device_wdt,
- &samsung_asoc_dma,
&s5p6440_device_iis,
&s3c_device_fb,
&smdk6440_lcd_lte480wv,
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index 12748b6eaa7b..62526ccf6b70 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -183,7 +183,6 @@ static struct platform_device *smdk6450_devices[] __initdata = {
&s3c_device_i2c1,
&s3c_device_ts,
&s3c_device_wdt,
- &samsung_asoc_dma,
&s5p6450_device_iis0,
&s3c_device_fb,
&smdk6450_lcd_lte480wv,
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index dba7384a87bd..9abe95e806ab 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -197,7 +197,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
&s3c_device_ts,
&s3c_device_wdt,
&smdkc100_lcd_powerdev,
- &samsung_asoc_dma,
&s5pc100_device_iis0,
&samsung_device_keypad,
&s5pc100_device_ac97,
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index d9c99fcc1aa7..f1f3bd37ecda 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -85,7 +85,6 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
};
static struct platform_device *smdkc110_devices[] __initdata = {
- &samsung_asoc_dma,
&s5pv210_device_iis0,
&s5pv210_device_ac97,
&s5pv210_device_spdif,
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 4cdb5bb7bbcf..6bc8404bf678 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -234,7 +234,6 @@ static struct platform_device *smdkv210_devices[] __initdata = {
&s5pv210_device_ac97,
&s5pv210_device_iis0,
&s5pv210_device_spdif,
- &samsung_asoc_dma,
&samsung_asoc_idma,
&samsung_device_keypad,
&smdkv210_dm9000,
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 4eddca14ae07..9255546e7bf6 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -29,6 +29,8 @@ config ARCH_R8A7779
select ARM_GIC
select CPU_V7
select SH_CLK_CPG
+ select USB_ARCH_HAS_EHCI
+ select USB_ARCH_HAS_OHCI
config ARCH_EMEV2
bool "Emma Mobile EV2"
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index cefdd030361d..40657854e3ad 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -658,133 +658,16 @@ static struct platform_device lcdc_device = {
/* FSI */
#define IRQ_FSI evt2irq(0x1840)
-static int __fsi_set_rate(struct clk *clk, long rate, int enable)
-{
- int ret = 0;
-
- if (rate <= 0)
- return ret;
-
- if (enable) {
- ret = clk_set_rate(clk, rate);
- if (0 == ret)
- ret = clk_enable(clk);
- } else {
- clk_disable(clk);
- }
-
- return ret;
-}
-
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
- return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
-}
-
-static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
-{
- struct clk *fsia_ick;
- struct clk *fsiack;
- int ret = -EIO;
-
- fsia_ick = clk_get(dev, "icka");
- if (IS_ERR(fsia_ick))
- return PTR_ERR(fsia_ick);
-
- /*
- * FSIACK is connected to AK4642,
- * and use external clock pin from it.
- * it is parent of fsia_ick now.
- */
- fsiack = clk_get_parent(fsia_ick);
- if (!fsiack)
- goto fsia_ick_out;
-
- /*
- * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
- *
- ** FIXME **
- * Because the freq_table of external clk (fsiack) are all 0,
- * the return value of clk_round_rate became 0.
- * So, it use __fsi_set_rate here.
- */
- ret = __fsi_set_rate(fsiack, rate, enable);
- if (ret < 0)
- goto fsiack_out;
-
- ret = __fsi_set_round_rate(fsia_ick, rate, enable);
- if ((ret < 0) && enable)
- __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
-
-fsiack_out:
- clk_put(fsiack);
-
-fsia_ick_out:
- clk_put(fsia_ick);
-
- return 0;
-}
-
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
- struct clk *fsib_clk;
- struct clk *fdiv_clk = clk_get(NULL, "fsidivb");
- long fsib_rate = 0;
- long fdiv_rate = 0;
- int ackmd_bpfmd;
- int ret;
-
- switch (rate) {
- case 44100:
- fsib_rate = rate * 256;
- ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
- break;
- case 48000:
- fsib_rate = 85428000; /* around 48kHz x 256 x 7 */
- fdiv_rate = rate * 256;
- ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
- break;
- default:
- pr_err("unsupported rate in FSI2 port B\n");
- return -EINVAL;
- }
-
- /* FSI B setting */
- fsib_clk = clk_get(dev, "ickb");
- if (IS_ERR(fsib_clk))
- return -EIO;
-
- ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
- if (ret < 0)
- goto fsi_set_rate_end;
-
- /* FSI DIV setting */
- ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
- if (ret < 0) {
- /* disable FSI B */
- if (enable)
- __fsi_set_round_rate(fsib_clk, fsib_rate, 0);
- goto fsi_set_rate_end;
- }
-
- ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
- clk_put(fsib_clk);
- return ret;
-}
-
static struct sh_fsi_platform_info fsi_info = {
.port_a = {
.flags = SH_FSI_BRS_INV,
- .set_rate = fsi_ak4642_set_rate,
},
.port_b = {
.flags = SH_FSI_BRS_INV |
SH_FSI_BRM_INV |
SH_FSI_LRS_INV |
+ SH_FSI_CLK_CPG |
SH_FSI_FMT_SPDIF,
- .set_rate = fsi_hdmi_set_rate,
},
};
@@ -1144,25 +1027,6 @@ out:
clk_put(hdmi_ick);
}
-static void __init fsi_init_pm_clock(void)
-{
- struct clk *fsia_ick;
- int ret;
-
- fsia_ick = clk_get(&fsi_device.dev, "icka");
- if (IS_ERR(fsia_ick)) {
- ret = PTR_ERR(fsia_ick);
- pr_err("Cannot get FSI ICK: %d\n", ret);
- return;
- }
-
- ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
- if (ret < 0)
- pr_err("Cannot set FSI-A parent: %d\n", ret);
-
- clk_put(fsia_ick);
-}
-
/* TouchScreen */
#ifdef CONFIG_AP4EVB_QHD
# define GPIO_TSC_IRQ GPIO_FN_IRQ28_123
@@ -1476,7 +1340,6 @@ static void __init ap4evb_init(void)
ARRAY_SIZE(domain_devices));
hdmi_init_pm_clock();
- fsi_init_pm_clock();
sh7372_pm_init();
pm_clk_add(&fsi_device.dev, "spu2");
pm_clk_add(&lcdc1_device.dev, "hdmi");
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 499e6e376666..5353adf6b828 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -768,32 +768,6 @@ static struct platform_device ceu0_device = {
};
/* FSI */
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
- struct clk *fsib;
- int ret;
-
- /* it support 48KHz only */
- if (48000 != rate)
- return -EINVAL;
-
- fsib = clk_get(dev, "ickb");
- if (IS_ERR(fsib))
- return -EINVAL;
-
- if (enable) {
- ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
- clk_enable(fsib);
- } else {
- ret = 0;
- clk_disable(fsib);
- }
-
- clk_put(fsib);
-
- return ret;
-}
-
static struct sh_fsi_platform_info fsi_info = {
/* FSI-WM8978 */
.port_a = {
@@ -802,8 +776,8 @@ static struct sh_fsi_platform_info fsi_info = {
/* FSI-HDMI */
.port_b = {
.flags = SH_FSI_FMT_SPDIF |
- SH_FSI_ENABLE_STREAM_MODE,
- .set_rate = fsi_hdmi_set_rate,
+ SH_FSI_ENABLE_STREAM_MODE |
+ SH_FSI_CLK_CPG,
.tx_id = SHDMA_SLAVE_FSIB_TX,
}
};
@@ -938,13 +912,11 @@ static void __init eva_clock_init(void)
struct clk *xtal1 = clk_get(NULL, "extal1");
struct clk *usb24s = clk_get(NULL, "usb24s");
struct clk *fsibck = clk_get(NULL, "fsibck");
- struct clk *fsib = clk_get(&fsi_device.dev, "ickb");
if (IS_ERR(system) ||
IS_ERR(xtal1) ||
IS_ERR(usb24s) ||
- IS_ERR(fsibck) ||
- IS_ERR(fsib)) {
+ IS_ERR(fsibck)) {
pr_err("armadillo800eva board clock init failed\n");
goto clock_error;
}
@@ -956,9 +928,7 @@ static void __init eva_clock_init(void)
clk_set_parent(usb24s, system);
/* FSIBCK is 12.288MHz, and it is parent of FSI-B */
- clk_set_parent(fsib, fsibck);
clk_set_rate(fsibck, 12288000);
- clk_set_rate(fsib, 12288000);
clock_error:
if (!IS_ERR(system))
@@ -969,8 +939,6 @@ clock_error:
clk_put(usb24s);
if (!IS_ERR(fsibck))
clk_put(fsibck);
- if (!IS_ERR(fsib))
- clk_put(fsib);
}
/*
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index f274252e4705..3f56e70795b7 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -816,6 +816,8 @@ static struct platform_device usbhs1_device = {
.id = 1,
.dev = {
.platform_data = &usbhs1_private.info,
+ .dma_mask = &usbhs1_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
.num_resources = ARRAY_SIZE(usbhs1_resources),
.resource = usbhs1_resources,
@@ -860,76 +862,6 @@ static struct platform_device leds_device = {
/* FSI */
#define IRQ_FSI evt2irq(0x1840)
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
- int ret;
-
- if (rate <= 0)
- return 0;
-
- if (!enable) {
- clk_disable(clk);
- return 0;
- }
-
- ret = clk_set_rate(clk, clk_round_rate(clk, rate));
- if (ret < 0)
- return ret;
-
- return clk_enable(clk);
-}
-
-static int fsi_b_set_rate(struct device *dev, int rate, int enable)
-{
- struct clk *fsib_clk;
- struct clk *fdiv_clk = clk_get(NULL, "fsidivb");
- long fsib_rate = 0;
- long fdiv_rate = 0;
- int ackmd_bpfmd;
- int ret;
-
- /* clock start */
- switch (rate) {
- case 44100:
- fsib_rate = rate * 256;
- ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
- break;
- case 48000:
- fsib_rate = 85428000; /* around 48kHz x 256 x 7 */
- fdiv_rate = rate * 256;
- ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
- break;
- default:
- pr_err("unsupported rate in FSI2 port B\n");
- return -EINVAL;
- }
-
- /* FSI B setting */
- fsib_clk = clk_get(dev, "ickb");
- if (IS_ERR(fsib_clk))
- return -EIO;
-
- /* fsib */
- ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
- if (ret < 0)
- goto fsi_set_rate_end;
-
- /* FSI DIV */
- ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
- if (ret < 0) {
- /* disable FSI B */
- if (enable)
- __fsi_set_round_rate(fsib_clk, fsib_rate, 0);
- goto fsi_set_rate_end;
- }
-
- ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
- clk_put(fsib_clk);
- return ret;
-}
-
static struct sh_fsi_platform_info fsi_info = {
.port_a = {
.flags = SH_FSI_BRS_INV,
@@ -940,8 +872,8 @@ static struct sh_fsi_platform_info fsi_info = {
.flags = SH_FSI_BRS_INV |
SH_FSI_BRM_INV |
SH_FSI_LRS_INV |
+ SH_FSI_CLK_CPG |
SH_FSI_FMT_SPDIF,
- .set_rate = fsi_b_set_rate,
}
};
@@ -1018,7 +950,11 @@ static struct resource nand_flash_resources[] = {
.start = 0xe6a30000,
.end = 0xe6a3009b,
.flags = IORESOURCE_MEM,
- }
+ },
+ [1] = {
+ .start = evt2irq(0x0d80), /* flstei: status error irq */
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct sh_flctl_platform_data nand_flash_data = {
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 69f7f464eff8..449f9289567d 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -34,6 +34,10 @@
#include <linux/spi/sh_hspi.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/pm_runtime.h>
#include <mach/hardware.h>
#include <mach/r8a7779.h>
#include <mach/common.h>
@@ -144,13 +148,185 @@ static struct platform_device hspi_device = {
.num_resources = ARRAY_SIZE(hspi_resources),
};
+/* USB PHY */
+static struct resource usb_phy_resources[] = {
+ [0] = {
+ .start = 0xffe70000,
+ .end = 0xffe70900 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 0xfff70000,
+ .end = 0xfff70900 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device usb_phy_device = {
+ .name = "rcar_usb_phy",
+ .resource = usb_phy_resources,
+ .num_resources = ARRAY_SIZE(usb_phy_resources),
+};
+
static struct platform_device *marzen_devices[] __initdata = {
&eth_device,
&sdhi0_device,
&thermal_device,
&hspi_device,
+ &usb_phy_device,
+};
+
+/* USB */
+static struct usb_phy *phy;
+static int usb_power_on(struct platform_device *pdev)
+{
+ if (!phy)
+ return -EIO;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ usb_phy_init(phy);
+
+ return 0;
+}
+
+static void usb_power_off(struct platform_device *pdev)
+{
+ if (!phy)
+ return;
+
+ usb_phy_shutdown(phy);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static struct usb_ehci_pdata ehcix_pdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+};
+
+static struct resource ehci0_resources[] = {
+ [0] = {
+ .start = 0xffe70000,
+ .end = 0xffe70400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(44),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ehci0_device = {
+ .name = "ehci-platform",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ehci0_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ehcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ehci0_resources),
+ .resource = ehci0_resources,
};
+static struct resource ehci1_resources[] = {
+ [0] = {
+ .start = 0xfff70000,
+ .end = 0xfff70400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(45),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ehci1_device = {
+ .name = "ehci-platform",
+ .id = 1,
+ .dev = {
+ .dma_mask = &ehci1_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ehcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ehci1_resources),
+ .resource = ehci1_resources,
+};
+
+static struct usb_ohci_pdata ohcix_pdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+};
+
+static struct resource ohci0_resources[] = {
+ [0] = {
+ .start = 0xffe70400,
+ .end = 0xffe70800 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(44),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ohci0_device = {
+ .name = "ohci-platform",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ohci0_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ohcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ohci0_resources),
+ .resource = ohci0_resources,
+};
+
+static struct resource ohci1_resources[] = {
+ [0] = {
+ .start = 0xfff70400,
+ .end = 0xfff70800 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(45),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ohci1_device = {
+ .name = "ohci-platform",
+ .id = 1,
+ .dev = {
+ .dma_mask = &ohci1_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ohcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ohci1_resources),
+ .resource = ohci1_resources,
+};
+
+static struct platform_device *marzen_late_devices[] __initdata = {
+ &ehci0_device,
+ &ehci1_device,
+ &ohci0_device,
+ &ohci1_device,
+};
+
+void __init marzen_init_late(void)
+{
+ /* get usb phy */
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+ shmobile_init_late();
+ platform_add_devices(marzen_late_devices,
+ ARRAY_SIZE(marzen_late_devices));
+}
+
static void __init marzen_init(void)
{
regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
@@ -188,6 +364,14 @@ static void __init marzen_init(void)
gpio_request(GPIO_FN_HSPI_TX0, NULL);
gpio_request(GPIO_FN_HSPI_RX0, NULL);
+ /* USB (CN21) */
+ gpio_request(GPIO_FN_USB_OVC0, NULL);
+ gpio_request(GPIO_FN_USB_OVC1, NULL);
+ gpio_request(GPIO_FN_USB_OVC2, NULL);
+
+ /* USB (CN22) */
+ gpio_request(GPIO_FN_USB_PENC2, NULL);
+
r8a7779_add_standard_devices();
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
}
@@ -200,6 +384,6 @@ MACHINE_START(MARZEN, "marzen")
.init_irq = r8a7779_init_irq,
.handle_irq = gic_handle_irq,
.init_machine = marzen_init,
- .init_late = shmobile_init_late,
+ .init_late = marzen_init_late,
.timer = &shmobile_timer,
MACHINE_END
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 9ff6f6ea3617..b442f15fd01a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -55,58 +55,7 @@ config TEGRA_AHB
help
Adds AHB configuration functionality for NVIDIA Tegra SoCs,
which controls AHB bus master arbitration and some
- perfomance parameters(priority, prefech size).
-
-choice
- prompt "Default low-level debug console UART"
- default TEGRA_DEBUG_UART_NONE
-
-config TEGRA_DEBUG_UART_NONE
- bool "None"
-
-config TEGRA_DEBUG_UARTA
- bool "UART-A"
-
-config TEGRA_DEBUG_UARTB
- bool "UART-B"
-
-config TEGRA_DEBUG_UARTC
- bool "UART-C"
-
-config TEGRA_DEBUG_UARTD
- bool "UART-D"
-
-config TEGRA_DEBUG_UARTE
- bool "UART-E"
-
-endchoice
-
-choice
- prompt "Automatic low-level debug console UART"
- default TEGRA_DEBUG_UART_AUTO_NONE
-
-config TEGRA_DEBUG_UART_AUTO_NONE
- bool "None"
-
-config TEGRA_DEBUG_UART_AUTO_ODMDATA
- bool "Via ODMDATA"
- help
- Automatically determines which UART to use for low-level debug based
- on the ODMDATA value. This value is part of the BCT, and is written
- to the boot memory device using nvflash, or other flashing tool.
- When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
- 0/1/2/3/4 are UART A/B/C/D/E.
-
-config TEGRA_DEBUG_UART_AUTO_SCRATCH
- bool "Via UART scratch register"
- help
- Automatically determines which UART to use for low-level debug based
- on the UART scratch register value. Some bootloaders put ASCII 'D'
- in this register when they initialize their own console UART output.
- Using this option allows the kernel to automatically pick the same
- UART.
-
-endchoice
+ performance parameters(priority, prefech size).
config TEGRA_EMC_SCALING_ENABLE
bool "Enable scaling the memory frequency"
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 11a74db51e5d..0816562725f6 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -45,14 +45,15 @@
* 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.
*/
-#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF)
-u32 tegra_uart_config[3] = {
+u32 tegra_uart_config[4] = {
/* Debug UART initialization required */
1,
/* Debug UART physical address */
- (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET),
+ 0,
/* Debug UART virtual address */
- (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET),
+ 0,
+ /* Scratch space for debug macro */
+ 0,
};
#ifdef CONFIG_OF
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
deleted file mode 100644
index 44ca7b1d8b8a..000000000000
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/debug-macro.S
- *
- * Copyright (C) 2010,2011 Google, Inc.
- * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
- *
- * Author:
- * Colin Cross <ccross@google.com>
- * Erik Gilling <konkers@google.com>
- * Doug Anderson <dianders@chromium.org>
- * Stephen Warren <swarren@nvidia.com>
- *
- * Portions based on mach-omap2's debug-macro.S
- * Copyright (C) 1994-1999 Russell King
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/serial_reg.h>
-
-#include "../../iomap.h"
-#include "../../irammap.h"
-
- .macro addruart, rp, rv, tmp
- adr \rp, 99f @ actual addr of 99f
- ldr \rv, [\rp] @ linked addr is stored there
- sub \rv, \rv, \rp @ offset between the two
- ldr \rp, [\rp, #4] @ linked tegra_uart_config
- sub \tmp, \rp, \rv @ actual tegra_uart_config
- ldr \rp, [\tmp] @ Load tegra_uart_config
- cmp \rp, #1 @ needs intitialization?
- bne 100f @ no; go load the addresses
- mov \rv, #0 @ yes; record init is done
- str \rv, [\tmp]
- mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM
- ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET]
- movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff
- movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16
- cmp \rv, \rp @ Cookie present?
- bne 100f @ No, use default UART
- mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM
- ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4]
- str \rv, [\tmp, #4] @ Store in tegra_uart_phys
- sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address
- add \rv, \rv, #IO_APB_VIRT
- str \rv, [\tmp, #8] @ Store in tegra_uart_virt
- b 100f
-
- .align
-99: .word .
- .word tegra_uart_config
- .ltorg
-
-100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
- ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
- .endm
-
-#define UART_SHIFT 2
-
-/*
- * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
- * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
- * We use the fact that all 5 valid UART addresses all have something in the
- * 2nd-to-lowest byte.
- */
-
- .macro senduart, rd, rx
- tst \rx, #0x0000ff00
- strneb \rd, [\rx, #UART_TX << UART_SHIFT]
-1001:
- .endm
-
- .macro busyuart, rd, rx
- tst \rx, #0x0000ff00
- 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
- bne 1001b
-1002:
- .endm
-
- .macro waituart, rd, rx
-#ifdef FLOW_CONTROL
- tst \rx, #0x0000ff00
- beq 1002f
-1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
- tst \rd, #UART_MSR_CTS
- beq 1001b
-1002:
-#endif
- .endm
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
deleted file mode 100644
index aad1a2c1d714..000000000000
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/irqs.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@google.com>
- * Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_IRQS_H
-#define __MACH_TEGRA_IRQS_H
-
-#define INT_GIC_BASE 0
-
-#define IRQ_LOCALTIMER 29
-
-/* Primary Interrupt Controller */
-#define INT_PRI_BASE (INT_GIC_BASE + 32)
-#define INT_TMR1 (INT_PRI_BASE + 0)
-#define INT_TMR2 (INT_PRI_BASE + 1)
-#define INT_RTC (INT_PRI_BASE + 2)
-#define INT_I2S2 (INT_PRI_BASE + 3)
-#define INT_SHR_SEM_INBOX_IBF (INT_PRI_BASE + 4)
-#define INT_SHR_SEM_INBOX_IBE (INT_PRI_BASE + 5)
-#define INT_SHR_SEM_OUTBOX_IBF (INT_PRI_BASE + 6)
-#define INT_SHR_SEM_OUTBOX_IBE (INT_PRI_BASE + 7)
-#define INT_VDE_UCQ_ERROR (INT_PRI_BASE + 8)
-#define INT_VDE_SYNC_TOKEN (INT_PRI_BASE + 9)
-#define INT_VDE_BSE_V (INT_PRI_BASE + 10)
-#define INT_VDE_BSE_A (INT_PRI_BASE + 11)
-#define INT_VDE_SXE (INT_PRI_BASE + 12)
-#define INT_I2S1 (INT_PRI_BASE + 13)
-#define INT_SDMMC1 (INT_PRI_BASE + 14)
-#define INT_SDMMC2 (INT_PRI_BASE + 15)
-#define INT_XIO (INT_PRI_BASE + 16)
-#define INT_VDE (INT_PRI_BASE + 17)
-#define INT_AVP_UCQ (INT_PRI_BASE + 18)
-#define INT_SDMMC3 (INT_PRI_BASE + 19)
-#define INT_USB (INT_PRI_BASE + 20)
-#define INT_USB2 (INT_PRI_BASE + 21)
-#define INT_PRI_RES_22 (INT_PRI_BASE + 22)
-#define INT_EIDE (INT_PRI_BASE + 23)
-#define INT_NANDFLASH (INT_PRI_BASE + 24)
-#define INT_VCP (INT_PRI_BASE + 25)
-#define INT_APB_DMA (INT_PRI_BASE + 26)
-#define INT_AHB_DMA (INT_PRI_BASE + 27)
-#define INT_GNT_0 (INT_PRI_BASE + 28)
-#define INT_GNT_1 (INT_PRI_BASE + 29)
-#define INT_OWR (INT_PRI_BASE + 30)
-#define INT_SDMMC4 (INT_PRI_BASE + 31)
-
-/* Secondary Interrupt Controller */
-#define INT_SEC_BASE (INT_PRI_BASE + 32)
-#define INT_GPIO1 (INT_SEC_BASE + 0)
-#define INT_GPIO2 (INT_SEC_BASE + 1)
-#define INT_GPIO3 (INT_SEC_BASE + 2)
-#define INT_GPIO4 (INT_SEC_BASE + 3)
-#define INT_UARTA (INT_SEC_BASE + 4)
-#define INT_UARTB (INT_SEC_BASE + 5)
-#define INT_I2C (INT_SEC_BASE + 6)
-#define INT_SPI (INT_SEC_BASE + 7)
-#define INT_TWC (INT_SEC_BASE + 8)
-#define INT_TMR3 (INT_SEC_BASE + 9)
-#define INT_TMR4 (INT_SEC_BASE + 10)
-#define INT_FLOW_RSM0 (INT_SEC_BASE + 11)
-#define INT_FLOW_RSM1 (INT_SEC_BASE + 12)
-#define INT_SPDIF (INT_SEC_BASE + 13)
-#define INT_UARTC (INT_SEC_BASE + 14)
-#define INT_MIPI (INT_SEC_BASE + 15)
-#define INT_EVENTA (INT_SEC_BASE + 16)
-#define INT_EVENTB (INT_SEC_BASE + 17)
-#define INT_EVENTC (INT_SEC_BASE + 18)
-#define INT_EVENTD (INT_SEC_BASE + 19)
-#define INT_VFIR (INT_SEC_BASE + 20)
-#define INT_DVC (INT_SEC_BASE + 21)
-#define INT_SYS_STATS_MON (INT_SEC_BASE + 22)
-#define INT_GPIO5 (INT_SEC_BASE + 23)
-#define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24)
-#define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25)
-#define INT_SEC_RES_26 (INT_SEC_BASE + 26)
-#define INT_S_LINK1 (INT_SEC_BASE + 27)
-#define INT_APB_DMA_COP (INT_SEC_BASE + 28)
-#define INT_AHB_DMA_COP (INT_SEC_BASE + 29)
-#define INT_DMA_TX (INT_SEC_BASE + 30)
-#define INT_DMA_RX (INT_SEC_BASE + 31)
-
-/* Tertiary Interrupt Controller */
-#define INT_TRI_BASE (INT_SEC_BASE + 32)
-#define INT_HOST1X_COP_SYNCPT (INT_TRI_BASE + 0)
-#define INT_HOST1X_MPCORE_SYNCPT (INT_TRI_BASE + 1)
-#define INT_HOST1X_COP_GENERAL (INT_TRI_BASE + 2)
-#define INT_HOST1X_MPCORE_GENERAL (INT_TRI_BASE + 3)
-#define INT_MPE_GENERAL (INT_TRI_BASE + 4)
-#define INT_VI_GENERAL (INT_TRI_BASE + 5)
-#define INT_EPP_GENERAL (INT_TRI_BASE + 6)
-#define INT_ISP_GENERAL (INT_TRI_BASE + 7)
-#define INT_2D_GENERAL (INT_TRI_BASE + 8)
-#define INT_DISPLAY_GENERAL (INT_TRI_BASE + 9)
-#define INT_DISPLAY_B_GENERAL (INT_TRI_BASE + 10)
-#define INT_HDMI (INT_TRI_BASE + 11)
-#define INT_TVO_GENERAL (INT_TRI_BASE + 12)
-#define INT_MC_GENERAL (INT_TRI_BASE + 13)
-#define INT_EMC_GENERAL (INT_TRI_BASE + 14)
-#define INT_TRI_RES_15 (INT_TRI_BASE + 15)
-#define INT_TRI_RES_16 (INT_TRI_BASE + 16)
-#define INT_AC97 (INT_TRI_BASE + 17)
-#define INT_SPI_2 (INT_TRI_BASE + 18)
-#define INT_SPI_3 (INT_TRI_BASE + 19)
-#define INT_I2C2 (INT_TRI_BASE + 20)
-#define INT_KBC (INT_TRI_BASE + 21)
-#define INT_EXTERNAL_PMU (INT_TRI_BASE + 22)
-#define INT_GPIO6 (INT_TRI_BASE + 23)
-#define INT_TVDAC (INT_TRI_BASE + 24)
-#define INT_GPIO7 (INT_TRI_BASE + 25)
-#define INT_UARTD (INT_TRI_BASE + 26)
-#define INT_UARTE (INT_TRI_BASE + 27)
-#define INT_I2C3 (INT_TRI_BASE + 28)
-#define INT_SPI_4 (INT_TRI_BASE + 29)
-#define INT_TRI_RES_30 (INT_TRI_BASE + 30)
-#define INT_SW_RESERVED (INT_TRI_BASE + 31)
-
-/* Quaternary Interrupt Controller */
-#define INT_QUAD_BASE (INT_TRI_BASE + 32)
-#define INT_SNOR (INT_QUAD_BASE + 0)
-#define INT_USB3 (INT_QUAD_BASE + 1)
-#define INT_PCIE_INTR (INT_QUAD_BASE + 2)
-#define INT_PCIE_MSI (INT_QUAD_BASE + 3)
-#define INT_QUAD_RES_4 (INT_QUAD_BASE + 4)
-#define INT_QUAD_RES_5 (INT_QUAD_BASE + 5)
-#define INT_QUAD_RES_6 (INT_QUAD_BASE + 6)
-#define INT_QUAD_RES_7 (INT_QUAD_BASE + 7)
-#define INT_APB_DMA_CH0 (INT_QUAD_BASE + 8)
-#define INT_APB_DMA_CH1 (INT_QUAD_BASE + 9)
-#define INT_APB_DMA_CH2 (INT_QUAD_BASE + 10)
-#define INT_APB_DMA_CH3 (INT_QUAD_BASE + 11)
-#define INT_APB_DMA_CH4 (INT_QUAD_BASE + 12)
-#define INT_APB_DMA_CH5 (INT_QUAD_BASE + 13)
-#define INT_APB_DMA_CH6 (INT_QUAD_BASE + 14)
-#define INT_APB_DMA_CH7 (INT_QUAD_BASE + 15)
-#define INT_APB_DMA_CH8 (INT_QUAD_BASE + 16)
-#define INT_APB_DMA_CH9 (INT_QUAD_BASE + 17)
-#define INT_APB_DMA_CH10 (INT_QUAD_BASE + 18)
-#define INT_APB_DMA_CH11 (INT_QUAD_BASE + 19)
-#define INT_APB_DMA_CH12 (INT_QUAD_BASE + 20)
-#define INT_APB_DMA_CH13 (INT_QUAD_BASE + 21)
-#define INT_APB_DMA_CH14 (INT_QUAD_BASE + 22)
-#define INT_APB_DMA_CH15 (INT_QUAD_BASE + 23)
-#define INT_QUAD_RES_24 (INT_QUAD_BASE + 24)
-#define INT_QUAD_RES_25 (INT_QUAD_BASE + 25)
-#define INT_QUAD_RES_26 (INT_QUAD_BASE + 26)
-#define INT_QUAD_RES_27 (INT_QUAD_BASE + 27)
-#define INT_QUAD_RES_28 (INT_QUAD_BASE + 28)
-#define INT_QUAD_RES_29 (INT_QUAD_BASE + 29)
-#define INT_QUAD_RES_30 (INT_QUAD_BASE + 30)
-#define INT_QUAD_RES_31 (INT_QUAD_BASE + 31)
-
-/* Tegra30 has 5 banks of 32 IRQs */
-#define INT_MAIN_NR (32 * 5)
-#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR)
-
-/* Tegra30 has 8 banks of 32 GPIOs */
-#define INT_GPIO_NR (32 * 8)
-
-#define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR)
-
-#define INT_BOARD_BASE TEGRA_NR_IRQS
-#define NR_BOARD_IRQS 32
-
-#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS)
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 27725750ca3e..485003f9b636 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -29,7 +29,6 @@
#include <linux/serial_reg.h>
#include "../../iomap.h"
-#include "../../irammap.h"
#define BIT(x) (1 << (x))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -52,17 +51,6 @@ static inline void flush(void)
{
}
-static inline void save_uart_address(void)
-{
- u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
-
- if (uart) {
- buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
- buf[1] = (u32)uart;
- } else
- buf[0] = 0;
-}
-
static const struct {
u32 base;
u32 reset_reg;
@@ -139,51 +127,19 @@ int auto_odmdata(void)
}
#endif
-#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
-int auto_scratch(void)
-{
- int i;
-
- /*
- * Look for the first UART that:
- * a) Is not in reset.
- * b) Is clocked.
- * c) Has a 'D' in the scratchpad register.
- *
- * Note that on Tegra30, the first two conditions are required, since
- * if not true, accesses to the UART scratch register will hang.
- * Tegra20 doesn't have this issue.
- *
- * The intent is that the bootloader will tell the kernel which UART
- * to use by setting up those conditions. If nothing found, we'll fall
- * back to what's specified in TEGRA_DEBUG_UART_BASE.
- */
- for (i = 0; i < ARRAY_SIZE(uarts); i++) {
- if (!uart_clocked(i))
- continue;
-
- uart = (volatile u8 *)uarts[i].base;
- if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
- continue;
-
- return i;
- }
-
- return -1;
-}
-#endif
-
/*
* Setup before decompression. This is where we do UART selection for
* earlyprintk and init the uart_base register.
*/
static inline void arch_decomp_setup(void)
{
- int uart_id, auto_uart_id;
+ int uart_id;
volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
u32 chip, div;
-#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ uart_id = auto_odmdata();
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
uart_id = 0;
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
uart_id = 1;
@@ -193,19 +149,7 @@ static inline void arch_decomp_setup(void)
uart_id = 3;
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
uart_id = 4;
-#else
- uart_id = -1;
-#endif
-
-#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
- auto_uart_id = auto_odmdata();
-#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
- auto_uart_id = auto_scratch();
-#else
- auto_uart_id = -1;
#endif
- if (auto_uart_id != -1)
- uart_id = auto_uart_id;
if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
!uart_clocked(uart_id))
@@ -213,7 +157,6 @@ static inline void arch_decomp_setup(void)
else
uart = (volatile u8 *)uarts[uart_id].base;
- save_uart_address();
if (uart == NULL)
return;
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 7d09f301b3a1..bb9c9c29d181 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -59,5 +59,6 @@ static struct map_desc tegra_io_desc[] __initdata = {
void __init tegra_map_common_io(void)
{
+ debug_ll_io_init();
iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc));
}
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 53151030a07d..db8be51cad80 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -261,20 +261,6 @@
#define TEGRA_SDMMC4_BASE 0xC8000600
#define TEGRA_SDMMC4_SIZE SZ_512
-#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
-# define TEGRA_DEBUG_UART_BASE 0
-#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
-#endif
-
/* On TEGRA, many peripherals are very closely packed in
* two 256MB io windows (that actually only use about 64KB
* at the start of each).
diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h
index 0cbe63261854..501952a84344 100644
--- a/arch/arm/mach-tegra/irammap.h
+++ b/arch/arm/mach-tegra/irammap.h
@@ -23,13 +23,4 @@
#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
-/*
- * These locations are written to by uncompress.h, and read by debug-macro.S.
- * The first word holds the cookie value if the data is valid. The second
- * word holds the UART physical address.
- */
-#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K
-#define TEGRA_IRAM_DEBUG_UART_SIZE 8
-#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254
-
#endif
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index f18fc3ab4e58..53d085871798 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -43,6 +43,9 @@
#include "board.h"
#include "iomap.h"
+/* Hack - need to parse this from DT */
+#define INT_PCIE_INTR 130
+
/* register definitions */
#define AFI_OFFSET 0x3800
#define PADS_OFFSET 0x3000
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 6ff503536512..e4863f3e9ee7 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -26,16 +26,14 @@
#include <linux/clocksource.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/mach/time.h>
#include <asm/smp_twd.h>
#include <asm/sched_clock.h>
-#include <mach/irqs.h>
-
#include "board.h"
-#include "clock.h"
-#include "iomap.h"
#define RTC_SECONDS 0x08
#define RTC_SHADOW_SECONDS 0x0c
@@ -53,8 +51,8 @@
#define TIMER_PTV 0x0
#define TIMER_PCR 0x4
-static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
-static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE);
+static void __iomem *timer_reg_base;
+static void __iomem *rtc_base;
static struct timespec persistent_ts;
static u64 persistent_ms, last_persistent_ms;
@@ -158,40 +156,66 @@ static struct irqaction tegra_timer_irq = {
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
.handler = tegra_timer_interrupt,
.dev_id = &tegra_clockevent,
- .irq = INT_TMR3,
};
-#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
- TEGRA_ARM_PERIF_BASE + 0x600,
- IRQ_LOCALTIMER);
+static const struct of_device_id timer_match[] __initconst = {
+ { .compatible = "nvidia,tegra20-timer" },
+ {}
+};
-static void __init tegra_twd_init(void)
-{
- int err = twd_local_timer_register(&twd_local_timer);
- if (err)
- pr_err("twd_local_timer_register failed %d\n", err);
-}
-#else
-#define tegra_twd_init() do {} while(0)
-#endif
+static const struct of_device_id rtc_match[] __initconst = {
+ { .compatible = "nvidia,tegra20-rtc" },
+ {}
+};
static void __init tegra_init_timer(void)
{
+ struct device_node *np;
struct clk *clk;
unsigned long rate;
int ret;
+ np = of_find_matching_node(NULL, timer_match);
+ if (!np) {
+ pr_err("Failed to find timer DT node\n");
+ BUG();
+ }
+
+ timer_reg_base = of_iomap(np, 0);
+ if (!timer_reg_base) {
+ pr_err("Can't map timer registers");
+ BUG();
+ }
+
+ tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
+ if (tegra_timer_irq.irq <= 0) {
+ pr_err("Failed to map timer IRQ\n");
+ BUG();
+ }
+
clk = clk_get_sys("timer", NULL);
if (IS_ERR(clk)) {
- pr_warn("Unable to get timer clock."
- " Assuming 12Mhz input clock.\n");
+ pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
rate = 12000000;
} else {
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
}
+ of_node_put(np);
+
+ np = of_find_matching_node(NULL, rtc_match);
+ if (!np) {
+ pr_err("Failed to find RTC DT node\n");
+ BUG();
+ }
+
+ rtc_base = of_iomap(np, 0);
+ if (!rtc_base) {
+ pr_err("Can't map RTC registers");
+ BUG();
+ }
+
/*
* rtc registers are used by read_persistent_clock, keep the rtc clock
* enabled
@@ -202,6 +226,8 @@ static void __init tegra_init_timer(void)
else
clk_prepare_enable(clk);
+ of_node_put(np);
+
switch (rate) {
case 12000000:
timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -223,13 +249,13 @@ static void __init tegra_init_timer(void)
if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
"timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
- printk(KERN_ERR "Failed to register clocksource\n");
+ pr_err("Failed to register clocksource\n");
BUG();
}
ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
if (ret) {
- printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret);
+ pr_err("Failed to register timer IRQ: %d\n", ret);
BUG();
}
@@ -241,7 +267,9 @@ static void __init tegra_init_timer(void)
tegra_clockevent.cpumask = cpu_all_mask;
tegra_clockevent.irq = tegra_timer_irq.irq;
clockevents_register_device(&tegra_clockevent);
- tegra_twd_init();
+#ifdef CONFIG_HAVE_ARM_TWD
+ twd_local_timer_of_register();
+#endif
register_persistent_clock(NULL, tegra_read_persistent_clock);
}
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index e8c3f0d70ca6..5dea90636d94 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -7,8 +7,8 @@ config UX500_SOC_COMMON
select ARM_ERRATA_764369 if SMP
select ARM_GIC
select CACHE_L2X0
+ select CLKSRC_NOMADIK_MTU
select COMMON_CLK
- select HAS_MTU
select PINCTRL
select PINCTRL_NOMADIK
select PL310_ERRATA_753970 if CACHE_PL310
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index 33631c9f1218..7209db7cdc72 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -8,8 +8,7 @@
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/platform_data/pinctrl-nomadik.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include <mach/devices.h>
#include <mach/hardware.h>
@@ -149,15 +148,6 @@ static struct platform_device snd_soc_mop500 = {
},
};
-/* Platform device for Ux500-PCM */
-static struct platform_device ux500_pcm = {
- .name = "ux500-pcm",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
struct msp_i2s_platform_data msp2_platform_data = {
.id = MSP_I2S_2,
.msp_i2s_dma_rx = &msp2_dma_rx,
@@ -185,10 +175,3 @@ void mop500_audio_init(struct device *parent)
db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
&msp3_platform_data);
}
-
-/* Due for removal once the MSP driver has been fully DT:ed. */
-void mop500_of_audio_init(struct device *parent)
-{
- pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
- platform_device_register(&ux500_pcm);
-}
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index c34d4efd0d5c..0a3f30df1eb8 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -33,8 +33,6 @@ 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(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP);
-BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
BIAS(out_hi, PIN_OUTPUT_HIGH);
BIAS(out_lo, PIN_OUTPUT_LOW);
BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
@@ -46,14 +44,34 @@ BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SL
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_nopull_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|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_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|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_nopull_wkup, PIN_SLEEPMODE_ENABLED|
+ PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+ PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+ PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+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, PIN_SLEEPMODE_ENABLED|
+ PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
+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) \
@@ -69,13 +87,16 @@ BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_S
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_SLEEP(pin, conf, dev) \
- PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
+#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) \
+#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)
/* Pin control settings */
static struct pinctrl_map __initdata mop500_family_pinmap[] = {
@@ -112,7 +133,7 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
* 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 to uart mop500_pins_uart0
+ * are configured by uart driver
*/
DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
@@ -123,12 +144,13 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
* TODO: is this used on U8500 variants and Snowball really?
* The setting on GPIO31 conflicts with magnetometer use on hrefv60
*/
- DB8500_MUX_HOG("u2rxtx_c_1", "u2"),
- DB8500_MUX_HOG("u2ctsrts_c_1", "u2"),
- DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */
- DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */
- DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */
- DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */
+ /* 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"
@@ -140,11 +162,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */
DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
- /* UART0 sleep state */
+ /* 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("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"),
DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"),
@@ -161,7 +190,10 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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", "av8100-hdmi"),
+ 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 */
@@ -194,6 +226,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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 */
@@ -203,6 +247,15 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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 */
@@ -216,6 +269,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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 */
@@ -229,6 +295,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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 */
DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
@@ -238,10 +317,232 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
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_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 */
/* 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 */
};
/*
@@ -267,32 +568,48 @@ static struct pinctrl_map __initdata mop500_pinmap[] = {
DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu),
/* Mux in UART1 and set the pull-ups */
DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
- DB8500_MUX_HOG("u1ctsrts_a_1", "u1"),
DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */
- DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* CTS */
- DB8500_PIN_HOG("GPIO7_AG5", out_hi), /* RTS */
/*
* Runtime stuff: make it possible to mux in the SKE keypad
* and bias the pins
*/
- DB8500_MUX("kp_a_2", "kp", "ske"),
- DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
- DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
- DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
- DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
- DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
- DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
- DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
- DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
- DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
- DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
- DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
- DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
- DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
- DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
- DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
- DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
+ /* 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"),
@@ -395,28 +712,6 @@ static struct pinctrl_map __initdata hrefv60_pinmap[] = {
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"),
- /*
- * Make it possible to mux in the SKE keypad and bias the pins
- * FIXME: what's the point with this on HREFv60? KP/SKE is already
- * muxed in at another place! Enabling this will bork.
- */
- DB8500_MUX("kp_a_2", "kp", "ske"),
- DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
- DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
- DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
- DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
- DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
- DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
- DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
- DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
- DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
- DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
- DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
- DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
- DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
- DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
- DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
- DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
};
static struct pinctrl_map __initdata u9500_pinmap[] = {
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 9c8e4a9e83ee..051b62c27102 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -11,9 +11,9 @@
#include <linux/amba/mmci.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include <asm/mach-types.h>
-#include <plat/ste_dma40.h>
#include <mach/devices.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
index 8c979770d872..564f57d5d8a7 100644
--- a/arch/arm/mach-ux500/board-mop500-stuib.c
+++ b/arch/arm/mach-ux500/board-mop500-stuib.c
@@ -162,18 +162,6 @@ static struct bu21013_platform_device tsc_plat_device = {
.y_flip = true,
};
-static struct bu21013_platform_device tsc_plat2_device = {
- .cs_en = bu21013_gpio_board_init,
- .cs_dis = bu21013_gpio_board_exit,
- .irq_read_val = bu21013_read_pin_val,
- .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
- .touch_x_max = TOUCH_XMAX,
- .touch_y_max = TOUCH_YMAX,
- .ext_clk = false,
- .x_flip = false,
- .y_flip = true,
-};
-
static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
{
I2C_BOARD_INFO("bu21013_tp", 0x5C),
@@ -181,21 +169,17 @@ static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
},
{
I2C_BOARD_INFO("bu21013_tp", 0x5D),
- .platform_data = &tsc_plat2_device,
+ .platform_data = &tsc_plat_device,
},
};
void __init mop500_stuib_init(void)
{
- if (machine_is_hrefv60()) {
+ if (machine_is_hrefv60())
tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
- tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
- } else {
+ else
tsc_plat_device.cs_pin = GPIO_BU21013_CS;
- tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
-
- }
mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
ARRAY_SIZE(mop500_i2c0_devices_stuib));
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index e6ad161449da..d453522edb0d 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -33,18 +33,15 @@
#include <linux/smsc911x.h>
#include <linux/gpio_keys.h>
#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.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 <asm/mach/arch.h>
#include <asm/hardware/gic.h>
-#include <plat/ste_dma40.h>
-
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
@@ -525,7 +522,7 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
};
#endif
-static struct pl022_ssp_controller ssp0_plat = {
+struct pl022_ssp_controller ssp0_plat = {
.bus_id = 0,
#ifdef CONFIG_STE_DMA40
.enable_dma = 1,
@@ -602,7 +599,7 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
};
#endif
-static struct amba_pl011_data uart0_plat = {
+struct amba_pl011_data uart0_plat = {
#ifdef CONFIG_STE_DMA40
.dma_filter = stedma40_filter,
.dma_rx_param = &uart0_dma_cfg_rx,
@@ -610,7 +607,7 @@ static struct amba_pl011_data uart0_plat = {
#endif
};
-static struct amba_pl011_data uart1_plat = {
+struct amba_pl011_data uart1_plat = {
#ifdef CONFIG_STE_DMA40
.dma_filter = stedma40_filter,
.dma_rx_param = &uart1_dma_cfg_rx,
@@ -618,7 +615,7 @@ static struct amba_pl011_data uart1_plat = {
#endif
};
-static struct amba_pl011_data uart2_plat = {
+struct amba_pl011_data uart2_plat = {
#ifdef CONFIG_STE_DMA40
.dma_filter = stedma40_filter,
.dma_rx_param = &uart2_dma_cfg_rx,
@@ -681,8 +678,6 @@ static void __init mop500_init_machine(void)
/* This board has full regulator constraints */
regulator_has_full_constraints();
-
- mop500_uib_init();
}
static void __init snowball_init_machine(void)
@@ -747,8 +742,6 @@ static void __init hrefv60_init_machine(void)
/* This board has full regulator constraints */
regulator_has_full_constraints();
-
- mop500_uib_init();
}
MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -794,135 +787,5 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
.timer = &ux500_timer,
.handle_irq = gic_handle_irq,
.init_machine = snowball_init_machine,
- .init_late = ux500_init_late,
+ .init_late = NULL,
MACHINE_END
-
-#ifdef CONFIG_MACH_UX500_DT
-
-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 and call-back bindings. */
- OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
- OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
- OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
- /* Requires DMA bindings. */
- OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat),
- 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),
- /* Requires clock name bindings. */
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e000, "gpio.2", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e080, "gpio.3", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e100, "gpio.4", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e180, "gpio.5", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
- OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
- OF_DEV_AUXDATA("st,nomadik-i2c", 0x80004000, "nmk-i2c.0", NULL),
- OF_DEV_AUXDATA("st,nomadik-i2c", 0x80122000, "nmk-i2c.1", NULL),
- OF_DEV_AUXDATA("st,nomadik-i2c", 0x80128000, "nmk-i2c.2", NULL),
- OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
- OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
- /* Requires device name bindings. */
- OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
- /* Requires clock name and DMA bindings. */
- OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
- "ux500-msp-i2s.0", &msp0_platform_data),
- OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
- "ux500-msp-i2s.1", &msp1_platform_data),
- OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
- "ux500-msp-i2s.2", &msp2_platform_data),
- OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
- "ux500-msp-i2s.3", &msp3_platform_data),
- {},
-};
-
-static const struct of_device_id u8500_local_bus_nodes[] = {
- /* only create devices below soc node */
- { .compatible = "stericsson,db8500", },
- { .compatible = "stericsson,db8500-prcmu", },
- { .compatible = "simple-bus"},
- { },
-};
-
-static void __init u8500_init_machine(void)
-{
- struct device *parent = NULL;
- int i2c0_devs;
- int i;
-
- /* Pinmaps must be in place before devices register */
- if (of_machine_is_compatible("st-ericsson,mop500"))
- mop500_pinmaps_init();
- else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
- snowball_pinmaps_init();
- else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
- hrefv60_pinmaps_init();
-
- parent = u8500_of_init_devices();
-
- for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
- mop500_platform_devs[i]->dev.parent = parent;
-
- /* automatically probe child nodes of db8500 device */
- of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
-
- if (of_machine_is_compatible("st-ericsson,mop500")) {
- mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-
- platform_add_devices(mop500_platform_devs,
- ARRAY_SIZE(mop500_platform_devs));
-
- mop500_sdi_init(parent);
- mop500_audio_init(parent);
- i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
- i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
- i2c_register_board_info(2, mop500_i2c2_devices,
- ARRAY_SIZE(mop500_i2c2_devices));
-
- mop500_uib_init();
-
- } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
- mop500_of_audio_init(parent);
- } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
- /*
- * The HREFv60 board removed a GPIO expander and routed
- * all these GPIO pins to the internal GPIO controller
- * instead.
- */
- mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
- platform_add_devices(mop500_platform_devs,
- ARRAY_SIZE(mop500_platform_devs));
-
- mop500_uib_init();
- }
-
- /* This board has full regulator constraints */
- regulator_has_full_constraints();
-}
-
-static const char * u8500_dt_board_compat[] = {
- "calaosystems,snowball-a9500",
- "st-ericsson,hrefv60+",
- "st-ericsson,u8500",
- "st-ericsson,mop500",
- NULL,
-};
-
-
-DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
- .smp = smp_ops(ux500_smp_ops),
- .map_io = u8500_map_io,
- .init_irq = ux500_init_irq,
- /* we re-use nomadik timer here */
- .timer = &ux500_timer,
- .handle_irq = gic_handle_irq,
- .init_machine = u8500_init_machine,
- .init_late = ux500_init_late,
- .dt_compat = u8500_dt_board_compat,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index aca39a68712a..eaa605f5d90d 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -89,6 +89,10 @@ 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 arm_pmu_platdata db8500_pmu_platdata;
+extern struct amba_pl011_data uart0_plat;
+extern struct amba_pl011_data uart1_plat;
+extern struct amba_pl011_data uart2_plat;
+extern struct pl022_ssp_controller ssp0_plat;
extern void mop500_sdi_init(struct device *parent);
extern void snowball_sdi_init(struct device *parent);
@@ -100,14 +104,8 @@ void __init mop500_pinmaps_init(void);
void __init snowball_pinmaps_init(void);
void __init hrefv60_pinmaps_init(void);
void mop500_audio_init(struct device *parent);
-/* Due for removal once the MSP driver has been fully DT:ed. */
-void mop500_of_audio_init(struct device *parent);
int __init mop500_uib_init(void);
void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
unsigned n);
-
-/* TODO: Once all pieces are DT:ed, remove completely. */
-struct device * __init u8500_of_init_devices(void);
-
#endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 5c5ad70e48be..db0bb75e2c76 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,19 +17,27 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#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 <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
#include <mach/db8500-regs.h>
+#include <mach/irqs.h>
#include "devices-db8500.h"
#include "ste-dma40-db8500.h"
+#include "board-mop500.h"
/* minimum static i/o mapping required to boot U8500 platforms */
static struct map_desc u8500_uart_io_desc[] __initdata = {
@@ -227,12 +235,12 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
return parent;
}
+#ifdef CONFIG_MACH_UX500_DT
+
/* TODO: Once all pieces are DT:ed, remove completely. */
-struct device * __init u8500_of_init_devices(void)
+static struct device * __init u8500_of_init_devices(void)
{
- struct device *parent;
-
- parent = db8500_soc_device_init();
+ struct device *parent = db8500_soc_device_init();
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
@@ -248,3 +256,95 @@ struct device * __init u8500_of_init_devices(void)
return parent;
}
+
+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,pl011", 0x80120000, "uart0", &uart0_plat),
+ OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
+ OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
+ OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat),
+ 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),
+ /* Requires clock name bindings. */
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e000, "gpio.2", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e080, "gpio.3", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e100, "gpio.4", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e180, "gpio.5", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
+ OF_DEV_AUXDATA("st,nomadik-i2c", 0x80004000, "nmk-i2c.0", NULL),
+ OF_DEV_AUXDATA("st,nomadik-i2c", 0x80122000, "nmk-i2c.1", NULL),
+ OF_DEV_AUXDATA("st,nomadik-i2c", 0x80128000, "nmk-i2c.2", NULL),
+ OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
+ OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
+ /* Requires device name bindings. */
+ OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
+ /* Requires clock name and DMA bindings. */
+ OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
+ "ux500-msp-i2s.0", &msp0_platform_data),
+ OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
+ "ux500-msp-i2s.1", &msp1_platform_data),
+ OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
+ "ux500-msp-i2s.2", &msp2_platform_data),
+ OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
+ "ux500-msp-i2s.3", &msp3_platform_data),
+ {},
+};
+
+static const struct of_device_id u8500_local_bus_nodes[] = {
+ /* only create devices below soc node */
+ { .compatible = "stericsson,db8500", },
+ { .compatible = "stericsson,db8500-prcmu", },
+ { .compatible = "simple-bus"},
+ { },
+};
+
+static void __init u8500_init_machine(void)
+{
+ struct device *parent = NULL;
+
+ /* Pinmaps must be in place before devices register */
+ if (of_machine_is_compatible("st-ericsson,mop500"))
+ mop500_pinmaps_init();
+ else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+ snowball_pinmaps_init();
+ else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+ hrefv60_pinmaps_init();
+ else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
+ /* TODO: Add pinmaps for ccu9540 board. */
+
+ /* TODO: Export SoC, USB, cpu-freq and DMA40 */
+ parent = u8500_of_init_devices();
+
+ /* automatically probe child nodes of db8500 device */
+ of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
+}
+
+static const char * stericsson_dt_platform_compat[] = {
+ "st-ericsson,u8500",
+ "st-ericsson,u8540",
+ "st-ericsson,u9500",
+ "st-ericsson,u9540",
+ NULL,
+};
+
+DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
+ .smp = smp_ops(ux500_smp_ops),
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ /* we re-use nomadik timer here */
+ .timer = &ux500_timer,
+ .handle_irq = gic_handle_irq,
+ .init_machine = u8500_init_machine,
+ .init_late = NULL,
+ .dt_compat = stericsson_dt_platform_compat,
+MACHINE_END
+
+#endif
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 1f3fbc2bb776..721e7b4275f3 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -26,6 +26,8 @@
#include <mach/setup.h>
#include <mach/devices.h>
+#include "board-mop500.h"
+
void __iomem *_PRCMU_BASE;
/*
@@ -82,6 +84,7 @@ void __init ux500_init_irq(void)
void __init ux500_init_late(void)
{
+ mop500_uib_init();
}
static const char * __init ux500_get_machine(void)
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index 692a77a1c153..16b5f71e6974 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -14,6 +14,7 @@
#include <linux/platform_data/pinctrl-nomadik.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
#include "devices-common.h"
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 91754a8a0d49..318d49020894 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -12,11 +12,11 @@
#include <linux/gpio.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl022.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include <mach/hardware.h>
#include <mach/setup.h>
+#include <mach/irqs.h>
#include "ste-dma40-db8500.h"
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
index 3c8010f4fb3f..4b24c9992654 100644
--- a/arch/arm/mach-ux500/devices-db8500.h
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -8,6 +8,7 @@
#ifndef __DEVICES_DB8500_H
#define __DEVICES_DB8500_H
+#include <mach/irqs.h>
#include "devices-common.h"
struct ske_keypad_platform_data;
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index e8928548b6a3..fc77b4274c8d 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -46,6 +46,6 @@
#include <mach/irqs-board-mop500.h>
#endif
-#define NR_IRQS IRQ_BOARD_END
+#define UX500_NR_IRQS IRQ_BOARD_END
#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h
index 3cc7142eee02..9991aea3d577 100644
--- a/arch/arm/mach-ux500/include/mach/msp.h
+++ b/arch/arm/mach-ux500/include/mach/msp.h
@@ -8,7 +8,7 @@
#ifndef __MSP_H
#define __MSP_H
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
enum msp_i2s_id {
MSP_I2S_0 = 0,
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 6f39731951b0..875309acb022 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -9,11 +9,10 @@
#include <linux/clksrc-dbx500-prcmu.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
#include <asm/smp_twd.h>
-#include <plat/mtu.h>
-
#include <mach/setup.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -96,7 +95,7 @@ dt_fail:
*
*/
- nmdk_timer_init(mtu_timer_base);
+ nmdk_timer_init(mtu_timer_base, IRQ_MTU0);
clksrc_dbx500_prcmu_init(prcmu_timer_base);
ux500_twd_init();
}
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
index 145482e74418..78ac65f62e87 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -7,10 +7,10 @@
#include <linux/platform_device.h>
#include <linux/usb/musb.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/platform_data/dma-ste-dma40.h>
-#include <plat/ste_dma40.h>
#include <mach/hardware.h>
-#include <linux/platform_data/usb-musb-ux500.h>
#define MUSB_DMA40_RX_CH { \
.mode = STEDMA40_MODE_LOGICAL, \
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
new file mode 100644
index 000000000000..465923aa3819
--- /dev/null
+++ b/arch/arm/mach-vexpress/reset.c
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/stat.h>
+#include <linux/vexpress.h>
+
+static void vexpress_reset_do(struct device *dev, const char *what)
+{
+ int err = -ENOENT;
+ struct vexpress_config_func *func =
+ vexpress_config_func_get_by_dev(dev);
+
+ if (func) {
+ unsigned long timeout;
+
+ err = vexpress_config_write(func, 0, 0);
+
+ timeout = jiffies + HZ;
+ while (time_before(jiffies, timeout))
+ cpu_relax();
+ }
+
+ dev_emerg(dev, "Unable to %s (%d)\n", what, err);
+}
+
+static struct device *vexpress_power_off_device;
+
+void vexpress_power_off(void)
+{
+ vexpress_reset_do(vexpress_power_off_device, "power off");
+}
+
+static struct device *vexpress_restart_device;
+
+void vexpress_restart(char str, const char *cmd)
+{
+ vexpress_reset_do(vexpress_restart_device, "restart");
+}
+
+static ssize_t vexpress_reset_active_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", vexpress_restart_device == dev);
+}
+
+static ssize_t vexpress_reset_active_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ long value;
+ int err = kstrtol(buf, 0, &value);
+
+ if (!err && value)
+ vexpress_restart_device = dev;
+
+ return err ? err : count;
+}
+
+DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
+ vexpress_reset_active_store);
+
+
+enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
+
+static struct of_device_id vexpress_reset_of_match[] = {
+ {
+ .compatible = "arm,vexpress-reset",
+ .data = (void *)FUNC_RESET,
+ }, {
+ .compatible = "arm,vexpress-shutdown",
+ .data = (void *)FUNC_SHUTDOWN
+ }, {
+ .compatible = "arm,vexpress-reboot",
+ .data = (void *)FUNC_REBOOT
+ },
+ {}
+};
+
+static int vexpress_reset_probe(struct platform_device *pdev)
+{
+ enum vexpress_reset_func func;
+ const struct of_device_id *match =
+ of_match_device(vexpress_reset_of_match, &pdev->dev);
+
+ if (match)
+ func = (enum vexpress_reset_func)match->data;
+ else
+ func = pdev->id_entry->driver_data;
+
+ switch (func) {
+ case FUNC_SHUTDOWN:
+ vexpress_power_off_device = &pdev->dev;
+ break;
+ case FUNC_RESET:
+ if (!vexpress_restart_device)
+ vexpress_restart_device = &pdev->dev;
+ device_create_file(&pdev->dev, &dev_attr_active);
+ break;
+ case FUNC_REBOOT:
+ vexpress_restart_device = &pdev->dev;
+ device_create_file(&pdev->dev, &dev_attr_active);
+ break;
+ };
+
+ return 0;
+}
+
+static const struct platform_device_id vexpress_reset_id_table[] = {
+ { .name = "vexpress-reset", .driver_data = FUNC_RESET, },
+ { .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
+ { .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
+ {}
+};
+
+static struct platform_driver vexpress_reset_driver = {
+ .probe = vexpress_reset_probe,
+ .driver = {
+ .name = "vexpress-reset",
+ .of_match_table = vexpress_reset_of_match,
+ },
+ .id_table = vexpress_reset_id_table,
+};
+
+static int __init vexpress_reset_init(void)
+{
+ return platform_driver_register(&vexpress_reset_driver);
+}
+device_initcall(vexpress_reset_init);
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
new file mode 100644
index 000000000000..2ed0b7d95db6
--- /dev/null
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -0,0 +1,12 @@
+config ARCH_VT8500
+ bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5
+ default ARCH_VT8500_SINGLE
+ select ARCH_HAS_CPUFREQ
+ select ARCH_REQUIRE_GPIOLIB
+ select CLKDEV_LOOKUP
+ select CPU_ARM926T
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_GPIO
+ select HAVE_CLK
+ help
+ Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 2b2419646e95..6f2b843115db 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -25,4 +25,7 @@ int __init vt8500_irq_init(struct device_node *node,
/* defined in drivers/clk/clk-vt8500.c */
void __init vtwm_clk_init(void __iomem *pmc_base);
+/* defined in irq.c */
+asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
+
#endif
diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S
deleted file mode 100644
index 367d1b55fb9a..000000000000
--- a/arch/arm/mach-vt8500/include/mach/entry-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-vt8500/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for VIA VT8500
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
- .macro get_irqnr_preamble, base, tmp
- @ physical 0xd8140000 is virtual 0xf8140000
- mov \base, #0xf8000000
- orr \base, \base, #0x00140000
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqnr, [\base]
- cmp \irqnr, #63 @ may be false positive, check interrupt status
- bne 1001f
- ldr \irqstat, [\base, #0x84]
- ands \irqstat, #0x80000000
- moveq \irqnr, #0
-1001:
- .endm
-
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
index f8f9ab9bc56e..b9cf5ce9efbb 100644
--- a/arch/arm/mach-vt8500/irq.c
+++ b/arch/arm/mach-vt8500/irq.c
@@ -36,7 +36,7 @@
#include <linux/of_address.h>
#include <asm/irq.h>
-
+#include <asm/exception.h>
#define VT8500_ICPC_IRQ 0x20
#define VT8500_ICPC_FIQ 0x24
@@ -66,30 +66,34 @@
#define VT8500_EDGE ( VT8500_TRIGGER_RISING \
| VT8500_TRIGGER_FALLING)
-static int irq_cnt;
+/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
+#define VT8500_INTC_MAX 2
-struct vt8500_irq_priv {
- void __iomem *base;
+struct vt8500_irq_data {
+ void __iomem *base; /* IO Memory base address */
+ struct irq_domain *domain; /* Domain for this controller */
};
+/* Global variable for accessing io-mem addresses */
+static struct vt8500_irq_data intc[VT8500_INTC_MAX];
+static u32 active_cnt = 0;
+
static void vt8500_irq_mask(struct irq_data *d)
{
- struct vt8500_irq_priv *priv =
- (struct vt8500_irq_priv *)(d->domain->host_data);
+ struct vt8500_irq_data *priv = d->domain->host_data;
void __iomem *base = priv->base;
- u8 edge;
+ void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
+ u8 edge, dctr;
+ u32 status;
edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
if (edge) {
- void __iomem *stat_reg = base + VT8500_ICIS
- + (d->hwirq < 32 ? 0 : 4);
- unsigned status = readl(stat_reg);
+ status = readl(stat_reg);
status |= (1 << (d->hwirq & 0x1f));
writel(status, stat_reg);
} else {
- u8 dctr = readb(base + VT8500_ICDC + d->hwirq);
-
+ dctr = readb(base + VT8500_ICDC + d->hwirq);
dctr &= ~VT8500_INT_ENABLE;
writeb(dctr, base + VT8500_ICDC + d->hwirq);
}
@@ -97,8 +101,7 @@ static void vt8500_irq_mask(struct irq_data *d)
static void vt8500_irq_unmask(struct irq_data *d)
{
- struct vt8500_irq_priv *priv =
- (struct vt8500_irq_priv *)(d->domain->host_data);
+ struct vt8500_irq_data *priv = d->domain->host_data;
void __iomem *base = priv->base;
u8 dctr;
@@ -109,8 +112,7 @@ static void vt8500_irq_unmask(struct irq_data *d)
static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
- struct vt8500_irq_priv *priv =
- (struct vt8500_irq_priv *)(d->domain->host_data);
+ struct vt8500_irq_data *priv = d->domain->host_data;
void __iomem *base = priv->base;
u8 dctr;
@@ -148,17 +150,15 @@ static struct irq_chip vt8500_irq_chip = {
static void __init vt8500_init_irq_hw(void __iomem *base)
{
- unsigned int i;
+ u32 i;
/* Enable rotating priority for IRQ */
writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
writel(0x00, base + VT8500_ICPC_FIQ);
- for (i = 0; i < 64; i++) {
- /* Disable all interrupts and route them to IRQ */
- writeb(VT8500_INT_DISABLE | ICDC_IRQ,
- base + VT8500_ICDC + i);
- }
+ /* Disable all interrupts and route them to IRQ */
+ for (i = 0; i < 64; i++)
+ writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
}
static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
@@ -175,33 +175,67 @@ static struct irq_domain_ops vt8500_irq_domain_ops = {
.xlate = irq_domain_xlate_onecell,
};
+asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
+{
+ u32 stat, i;
+ int irqnr, virq;
+ void __iomem *base;
+
+ /* Loop through each active controller */
+ for (i=0; i<active_cnt; i++) {
+ base = intc[i].base;
+ irqnr = readl_relaxed(base) & 0x3F;
+ /*
+ Highest Priority register default = 63, so check that this
+ is a real interrupt by checking the status register
+ */
+ if (irqnr == 63) {
+ stat = readl_relaxed(base + VT8500_ICIS + 4);
+ if (!(stat & BIT(31)))
+ continue;
+ }
+
+ virq = irq_find_mapping(intc[i].domain, irqnr);
+ handle_IRQ(virq, regs);
+ }
+}
+
int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
{
- struct irq_domain *vt8500_irq_domain;
- struct vt8500_irq_priv *priv;
int irq, i;
struct device_node *np = node;
- priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL);
- priv->base = of_iomap(np, 0);
+ if (active_cnt == VT8500_INTC_MAX) {
+ pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
+ __func__);
+ goto out;
+ }
+
+ intc[active_cnt].base = of_iomap(np, 0);
+ intc[active_cnt].domain = irq_domain_add_linear(node, 64,
+ &vt8500_irq_domain_ops, &intc[active_cnt]);
- vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0,
- &vt8500_irq_domain_ops, priv);
- if (!vt8500_irq_domain)
- pr_err("%s: Unable to add wmt irq domain!\n", __func__);
+ if (!intc[active_cnt].base) {
+ pr_err("%s: Unable to map IO memory\n", __func__);
+ goto out;
+ }
+
+ if (!intc[active_cnt].domain) {
+ pr_err("%s: Unable to add irq domain!\n", __func__);
+ goto out;
+ }
- irq_set_default_host(vt8500_irq_domain);
+ vt8500_init_irq_hw(intc[active_cnt].base);
- vt8500_init_irq_hw(priv->base);
+ pr_info("vt8500-irq: Added interrupt controller\n");
- pr_info("Added IRQ Controller @ %x [virq_base = %d]\n",
- (u32)(priv->base), irq_cnt);
+ active_cnt++;
/* check if this is a slaved controller */
if (of_irq_count(np) != 0) {
/* check that we have the correct number of interrupts */
if (of_irq_count(np) != 8) {
- pr_err("%s: Incorrect IRQ map for slave controller\n",
+ pr_err("%s: Incorrect IRQ map for slaved controller\n",
__func__);
return -EINVAL;
}
@@ -213,9 +247,7 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
}
-
- irq_cnt += 64;
-
+out:
return 0;
}
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index a5bd28692b06..3c66d48ea082 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -192,5 +192,6 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
.timer = &vt8500_timer,
.init_machine = vt8500_init,
.restart = vt8500_restart,
+ .handle_irq = vt8500_handle_irq,
MACHINE_END
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
new file mode 100644
index 000000000000..adb6c0ea0e53
--- /dev/null
+++ b/arch/arm/mach-zynq/Kconfig
@@ -0,0 +1,13 @@
+config ARCH_ZYNQ
+ bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
+ select ARM_AMBA
+ select ARM_GIC
+ select COMMON_CLK
+ select CPU_V7
+ select GENERIC_CLOCKEVENTS
+ select ICST
+ select MIGHT_HAVE_CACHE_L2X0
+ select USE_OF
+ select SPARSE_IRQ
+ help
+ Support for Xilinx Zynq ARM Cortex A9 Platform
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index ba8d14f78d4d..e16d4bed0f7a 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -19,18 +19,21 @@
#include <linux/cpumask.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/clk/zynq.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/page.h>
+#include <asm/pgtable.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
-#include <mach/zynq_soc.h>
#include "common.h"
static struct of_device_id zynq_of_bus_ids[] __initdata = {
@@ -65,32 +68,36 @@ static void __init xilinx_irq_init(void)
of_irq_init(irq_match);
}
-/* The minimum devices needed to be mapped before the VM system is up and
- * running include the GIC, UART and Timer Counter.
- */
+#define SCU_PERIPH_PHYS 0xF8F00000
+#define SCU_PERIPH_SIZE SZ_8K
+#define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE)
+
+static struct map_desc scu_desc __initdata = {
+ .virtual = SCU_PERIPH_VIRT,
+ .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
+ .length = SCU_PERIPH_SIZE,
+ .type = MT_DEVICE,
+};
+
+static void __init xilinx_zynq_timer_init(void)
+{
+ struct device_node *np;
+ void __iomem *slcr;
-static struct map_desc io_desc[] __initdata = {
- {
- .virtual = TTC0_VIRT,
- .pfn = __phys_to_pfn(TTC0_PHYS),
- .length = TTC0_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = SCU_PERIPH_VIRT,
- .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
- .length = SCU_PERIPH_SIZE,
- .type = MT_DEVICE,
- },
-
-#ifdef CONFIG_DEBUG_LL
- {
- .virtual = UART0_VIRT,
- .pfn = __phys_to_pfn(UART0_PHYS),
- .length = UART0_SIZE,
- .type = MT_DEVICE,
- },
-#endif
+ np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr");
+ slcr = of_iomap(np, 0);
+ WARN_ON(!slcr);
+ xilinx_zynq_clocks_init(slcr);
+
+ xttcpss_timer_init();
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+static struct sys_timer xttcpss_sys_timer = {
+ .init = xilinx_zynq_timer_init,
};
/**
@@ -98,11 +105,13 @@ static struct map_desc io_desc[] __initdata = {
*/
static void __init xilinx_map_io(void)
{
- iotable_init(io_desc, ARRAY_SIZE(io_desc));
+ debug_ll_io_init();
+ iotable_init(&scu_desc, 1);
}
static const char *xilinx_dt_match[] = {
- "xlnx,zynq-ep107",
+ "xlnx,zynq-zc702",
+ "xlnx,zynq-7000",
NULL
};
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index a009644a1555..954b91c13c91 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -17,8 +17,6 @@
#ifndef __MACH_ZYNQ_COMMON_H__
#define __MACH_ZYNQ_COMMON_H__
-#include <asm/mach/time.h>
-
-extern struct sys_timer xttcpss_sys_timer;
+void __init xttcpss_timer_init(void);
#endif
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
deleted file mode 100644
index d558d8a94be7..000000000000
--- a/arch/arm/mach-zynq/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/hardware.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_HARDWARE_H__
-#define __MACH_HARDWARE_H__
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
deleted file mode 100644
index 5fb04fd3bac8..000000000000
--- a/arch/arm/mach-zynq/include/mach/irqs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/irqs.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_IRQS_H
-#define __MACH_IRQS_H
-
-#define ARCH_NR_GPIOS 118
-#define NR_IRQS (128 + ARCH_NR_GPIOS)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
deleted file mode 100644
index 6c0245e42a5e..000000000000
--- a/arch/arm/mach-zynq/include/mach/timex.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/timex.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_TIMEX_H__
-#define __MACH_TIMEX_H__
-
-/* the following is needed for the system to build but will be removed
- in the future, the value is not important but won't hurt
-*/
-#define CLOCK_TICK_RATE (100 * HZ)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
deleted file mode 100644
index 5c47c97156f3..000000000000
--- a/arch/arm/mach-zynq/include/mach/uart.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/uart.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_UART_H__
-#define __MACH_UART_H__
-
-#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
-#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
-#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
-
-#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
-#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
deleted file mode 100644
index af4e8447bfa3..000000000000
--- a/arch/arm/mach-zynq/include/mach/uncompress.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/uncompress.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_UNCOMPRESS_H__
-#define __MACH_UNCOMPRESS_H__
-
-#include <linux/io.h>
-#include <asm/processor.h>
-#include <mach/zynq_soc.h>
-#include <mach/uart.h>
-
-void arch_decomp_setup(void)
-{
-}
-
-static inline void flush(void)
-{
- /*
- * Wait while the FIFO is not empty
- */
- while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
- UART_SR_TXEMPTY))
- cpu_relax();
-}
-
-#define arch_decomp_wdog()
-
-static void putc(char ch)
-{
- /*
- * Wait for room in the FIFO, then write the char into the FIFO
- */
- while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
- UART_SR_TXFULL)
- cpu_relax();
-
- __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
-}
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
deleted file mode 100644
index 1b8bf0ecbcb0..000000000000
--- a/arch/arm/mach-zynq/include/mach/zynq_soc.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/zynq_soc.h
- *
- * Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_XILINX_SOC_H__
-#define __MACH_XILINX_SOC_H__
-
-#include <asm/pgtable.h>
-
-#define PERIPHERAL_CLOCK_RATE 2500000
-
-/* Static peripheral mappings are mapped at the top of the vmalloc region. The
- * early uart mapping causes intermediate problems/failure at certain
- * addresses, including the very top of the vmalloc region. Map it at an
- * address that is known to work.
- */
-#define UART0_PHYS 0xE0000000
-#define UART0_SIZE SZ_4K
-#define UART0_VIRT 0xF0001000
-
-#define TTC0_PHYS 0xF8001000
-#define TTC0_SIZE SZ_4K
-#define TTC0_VIRT (VMALLOC_END - TTC0_SIZE)
-
-#define SCU_PERIPH_PHYS 0xF8F00000
-#define SCU_PERIPH_SIZE SZ_8K
-#define SCU_PERIPH_VIRT (TTC0_VIRT - SCU_PERIPH_SIZE)
-
-/* The following are intended for the devices that are mapped early */
-
-#define TTC0_BASE IOMEM(TTC0_VIRT)
-#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
-
-#define LL_UART_PADDR UART0_PHYS
-#define LL_UART_VADDR UART0_VIRT
-
-#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index c2c96cc7d6e7..de3df283da74 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -23,32 +23,14 @@
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
-#include <asm/mach/time.h>
-#include <mach/zynq_soc.h>
#include "common.h"
-#define IRQ_TIMERCOUNTER0 42
-
-/*
- * This driver configures the 2 16-bit count-up timers as follows:
- *
- * T1: Timer 1, clocksource for generic timekeeping
- * T2: Timer 2, clockevent source for hrtimers
- * T3: Timer 3, <unused>
- *
- * The input frequency to the timer module for emulation is 2.5MHz which is
- * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
- * the timers are clocked at 78.125KHz (12.8 us resolution).
- *
- * The input frequency to the timer module in silicon will be 200MHz. With the
- * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
- */
-#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
-#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
-
-#define XTTCPSS_TIMER_BASE TTC0_BASE
-#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
/*
* Timer Register Offset Definitions of Timer 1, Increment base address by 4
* and use same offsets for Timer 2
@@ -65,9 +47,14 @@
#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
-/* Setup the timers to use pre-scaling */
-
-#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+/* Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE 2048 /* The exponent must match this */
+#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN 1
+#define CNT_CNTRL_RESET (1<<4)
/**
* struct xttcpss_timer - This definition defines local timer structure
@@ -75,11 +62,25 @@
* @base_addr: Base address of timer
**/
struct xttcpss_timer {
- void __iomem *base_addr;
+ void __iomem *base_addr;
};
-static struct xttcpss_timer timers[2];
-static struct clock_event_device xttcpss_clockevent;
+struct xttcpss_timer_clocksource {
+ struct xttcpss_timer xttc;
+ struct clocksource cs;
+};
+
+#define to_xttcpss_timer_clksrc(x) \
+ container_of(x, struct xttcpss_timer_clocksource, cs)
+
+struct xttcpss_timer_clockevent {
+ struct xttcpss_timer xttc;
+ struct clock_event_device ce;
+ struct clk *clk;
+};
+
+#define to_xttcpss_timer_clkevent(x) \
+ container_of(x, struct xttcpss_timer_clockevent, ce)
/**
* xttcpss_set_interval - Set the timer interval value
@@ -101,7 +102,7 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
/* Reset the counter (0x10) so that it starts from 0, one-shot
mode makes this needed for timing to be right. */
- ctrl_reg |= 0x10;
+ ctrl_reg |= CNT_CNTRL_RESET;
ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
}
@@ -116,90 +117,31 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
**/
static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = &xttcpss_clockevent;
- struct xttcpss_timer *timer = dev_id;
+ struct xttcpss_timer_clockevent *xttce = dev_id;
+ struct xttcpss_timer *timer = &xttce->xttc;
/* Acknowledge the interrupt and call event handler */
__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
timer->base_addr + XTTCPSS_ISR_OFFSET);
- evt->event_handler(evt);
+ xttce->ce.event_handler(&xttce->ce);
return IRQ_HANDLED;
}
-static struct irqaction event_timer_irq = {
- .name = "xttcpss clockevent",
- .flags = IRQF_DISABLED | IRQF_TIMER,
- .handler = xttcpss_clock_event_interrupt,
-};
-
/**
- * xttcpss_timer_hardware_init - Initialize the timer hardware
- *
- * Initialize the hardware to start the clock source, get the clock
- * event timer ready to use, and hook up the interrupt.
- **/
-static void __init xttcpss_timer_hardware_init(void)
-{
- /* Setup the clock source counter to be an incrementing counter
- * with no interrupt and it rolls over at 0xFFFF. Pre-scale
- it by 32 also. Let it start running now.
- */
- timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
-
- __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_IER_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
-
- /* Setup the clock event timer to be an interval timer which
- * is prescaled by 32 using the interval interrupt. Leave it
- * disabled for now.
- */
-
- timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
-
- __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CNT_CNTRL_OFFSET);
- __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_CLK_CNTRL_OFFSET);
- __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
- XTTCPSS_IER_OFFSET);
-
- /* Setup IRQ the clock event timer */
- event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
- setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
-}
-
-/**
- * __raw_readl_cycles - Reads the timer counter register
+ * __xttc_clocksource_read - Reads the timer counter register
*
* returns: Current timer counter register value
**/
-static cycle_t __raw_readl_cycles(struct clocksource *cs)
+static cycle_t __xttc_clocksource_read(struct clocksource *cs)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+ struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc;
return (cycle_t)__raw_readl(timer->base_addr +
XTTCPSS_COUNT_VAL_OFFSET);
}
-
-/*
- * Instantiate and initialize the clock source structure
- */
-static struct clocksource clocksource_xttcpss = {
- .name = "xttcpss_timer1",
- .rating = 200, /* Reasonable clock source */
- .read = __raw_readl_cycles,
- .mask = CLOCKSOURCE_MASK(16),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
/**
* xttcpss_set_next_event - Sets the time interval for next event
*
@@ -211,7 +153,8 @@ static struct clocksource clocksource_xttcpss = {
static int xttcpss_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
xttcpss_set_interval(timer, cycles);
return 0;
@@ -226,12 +169,15 @@ static int xttcpss_set_next_event(unsigned long cycles,
static void xttcpss_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+ struct xttcpss_timer *timer = &xttce->xttc;
u32 ctrl_reg;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ xttcpss_set_interval(timer,
+ DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
+ PRESCALE * HZ));
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
@@ -252,15 +198,106 @@ static void xttcpss_set_mode(enum clock_event_mode mode,
}
}
-/*
- * Instantiate and initialize the clock event structure
- */
-static struct clock_event_device xttcpss_clockevent = {
- .name = "xttcpss_timer2",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = xttcpss_set_next_event,
- .set_mode = xttcpss_set_mode,
- .rating = 200,
+static void __init zynq_ttc_setup_clocksource(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clocksource *ttccs;
+ struct clk *clk;
+ int err;
+ u32 reg;
+
+ ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+ if (WARN_ON(!ttccs))
+ return;
+
+ err = of_property_read_u32(np, "reg", &reg);
+ if (WARN_ON(err))
+ return;
+
+ clk = of_clk_get_by_name(np, "cpu_1x");
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = clk_prepare_enable(clk);
+ if (WARN_ON(err))
+ return;
+
+ ttccs->xttc.base_addr = base + reg * 4;
+
+ ttccs->cs.name = np->name;
+ ttccs->cs.rating = 200;
+ ttccs->cs.read = __xttc_clocksource_read;
+ ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+ ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(CNT_CNTRL_RESET,
+ ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
+ if (WARN_ON(err))
+ return;
+}
+
+static void __init zynq_ttc_setup_clockevent(struct device_node *np,
+ void __iomem *base)
+{
+ struct xttcpss_timer_clockevent *ttcce;
+ int err, irq;
+ u32 reg;
+
+ ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+ if (WARN_ON(!ttcce))
+ return;
+
+ err = of_property_read_u32(np, "reg", &reg);
+ if (WARN_ON(err))
+ return;
+
+ ttcce->xttc.base_addr = base + reg * 4;
+
+ ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
+ if (WARN_ON(IS_ERR(ttcce->clk)))
+ return;
+
+ err = clk_prepare_enable(ttcce->clk);
+ if (WARN_ON(err))
+ return;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (WARN_ON(!irq))
+ return;
+
+ ttcce->ce.name = np->name;
+ ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ ttcce->ce.set_next_event = xttcpss_set_next_event;
+ ttcce->ce.set_mode = xttcpss_set_mode;
+ ttcce->ce.rating = 200;
+ ttcce->ce.irq = irq;
+
+ __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+ ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET);
+
+ err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER,
+ np->name, ttcce);
+ if (WARN_ON(err))
+ return;
+
+ clockevents_config_and_register(&ttcce->ce,
+ clk_get_rate(ttcce->clk) / PRESCALE,
+ 1, 0xfffe);
+}
+
+static const __initconst struct of_device_id zynq_ttc_match[] = {
+ { .compatible = "xlnx,ttc-counter-clocksource",
+ .data = zynq_ttc_setup_clocksource, },
+ { .compatible = "xlnx,ttc-counter-clockevent",
+ .data = zynq_ttc_setup_clockevent, },
+ {}
};
/**
@@ -269,30 +306,27 @@ static struct clock_event_device xttcpss_clockevent = {
* Initializes the timer hardware and register the clock source and clock event
* timers with Linux kernal timer framework
**/
-static void __init xttcpss_timer_init(void)
+void __init xttcpss_timer_init(void)
{
- xttcpss_timer_hardware_init();
- clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
-
- /* Calculate the parameters to allow the clockevent to operate using
- integer math
- */
- clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
-
- xttcpss_clockevent.max_delta_ns =
- clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
- xttcpss_clockevent.min_delta_ns =
- clockevent_delta2ns(1, &xttcpss_clockevent);
-
- /* Indicate that clock event is on 1st CPU as SMP boot needs it */
-
- xttcpss_clockevent.cpumask = cpumask_of(0);
- clockevents_register_device(&xttcpss_clockevent);
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "xlnx,ttc") {
+ struct device_node *np_chld;
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(!base))
+ return;
+
+ for_each_available_child_of_node(np, np_chld) {
+ int (*cb)(struct device_node *np, void __iomem *base);
+ const struct of_device_id *match;
+
+ match = of_match_node(zynq_ttc_match, np_chld);
+ if (match) {
+ cb = match->data;
+ cb(np_chld, base);
+ }
+ }
+ }
}
-
-/*
- * Instantiate and initialize the system timer structure
- */
-struct sys_timer xttcpss_sys_timer = {
- .init = xttcpss_timer_init,
-};
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index b6f305e3b908..a34f1e214116 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include <asm/cacheflush.h>
#include <asm/hwcap.h>
@@ -168,6 +169,8 @@ static inline bool is_load_to_a(u16 inst)
case BPF_S_ANC_MARK:
case BPF_S_ANC_PROTOCOL:
case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_QUEUE:
return true;
default:
@@ -646,6 +649,16 @@ load_ind:
update_on_xread(ctx);
emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
break;
+ case BPF_S_ALU_XOR_K:
+ /* A ^= K; */
+ OP_IMM3(ARM_EOR, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ANC_ALU_XOR_X:
+ case BPF_S_ALU_XOR_X:
+ /* A ^= X */
+ update_on_xread(ctx);
+ emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
+ break;
case BPF_S_ALU_AND_K:
/* A &= K */
OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
@@ -762,11 +775,6 @@ b_epilogue:
update_on_xread(ctx);
emit(ARM_MOV_R(r_A, r_X), ctx);
break;
- case BPF_S_ANC_ALU_XOR_X:
- /* A ^= X */
- update_on_xread(ctx);
- emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
- break;
case BPF_S_ANC_PROTOCOL:
/* A = ntohs(skb->protocol) */
ctx->seen |= SEEN_SKB;
@@ -810,6 +818,17 @@ b_epilogue:
off = offsetof(struct sk_buff, rxhash);
emit(ARM_LDR_I(r_A, r_skb, off), ctx);
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+ off = offsetof(struct sk_buff, vlan_tci);
+ emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+ if (inst->code == BPF_S_ANC_VLAN_TAG)
+ OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx);
+ else
+ OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx);
+ break;
case BPF_S_ANC_QUEUE:
ctx->seen |= SEEN_SKB;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index 7fa2f7d3cb90..afb84621ff6f 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -69,6 +69,7 @@
#define ARM_INST_CMP_I 0x03500000
#define ARM_INST_EOR_R 0x00200000
+#define ARM_INST_EOR_I 0x02200000
#define ARM_INST_LDRB_I 0x05d00000
#define ARM_INST_LDRB_R 0x07d00000
@@ -135,6 +136,7 @@
#define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm)
#define ARM_EOR_R(rd, rn, rm) _AL3_R(ARM_INST_EOR, rd, rn, rm)
+#define ARM_EOR_I(rd, rn, imm) _AL3_I(ARM_INST_EOR, rd, rn, imm)
#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
| (off))
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
deleted file mode 100644
index 19f55cae5d73..000000000000
--- a/arch/arm/plat-nomadik/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-# We keep common IP's here for Nomadik and other similar
-# familiy of processors from ST-Ericsson. At the moment we have
-# just MTU, others to follow soon.
-
-config PLAT_NOMADIK
- bool
- depends on ARCH_NOMADIK || ARCH_U8500
- default y
- select CLKSRC_MMIO
- help
- Common platform code for Nomadik and other ST-Ericsson
- platforms.
-
-if PLAT_NOMADIK
-
-config HAS_MTU
- bool
- help
- Support for Multi Timer Unit. MTU provides access
- to multiple interrupt generating programmable
- 32-bit free running decrementing counters.
-
-config NOMADIK_MTU_SCHED_CLOCK
- bool
- depends on HAS_MTU
- help
- Use the Multi Timer Unit as the sched_clock.
-
-endif
diff --git a/arch/arm/plat-nomadik/Makefile b/arch/arm/plat-nomadik/Makefile
deleted file mode 100644
index 37c7cdd0f8f0..000000000000
--- a/arch/arm/plat-nomadik/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# arch/arm/plat-nomadik/Makefile
-# Copyright 2009 ST-Ericsson
-# Licensed under GPLv2
-
-obj-$(CONFIG_HAS_MTU) += timer.o
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c288b76f8e6c..37a488aaa2ba 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -36,7 +36,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
/*
* MAX_LOGICAL_DMA_CH_COUNT: the maximum number of logical DMA
diff --git a/arch/arm/plat-omap/include/plat-omap/dma-omap.h b/arch/arm/plat-omap/include/plat-omap/dma-omap.h
deleted file mode 100644
index 6f506ba9e453..000000000000
--- a/arch/arm/plat-omap/include/plat-omap/dma-omap.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * OMAP DMA handling defines and function
- *
- * Copyright (C) 2003 Nokia Corporation
- * Author: Juha Yrjölä <juha.yrjola@nokia.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
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#include <linux/platform_device.h>
-
-#define INT_DMA_LCD 25
-
-#define OMAP1_DMA_TOUT_IRQ (1 << 0)
-#define OMAP_DMA_DROP_IRQ (1 << 1)
-#define OMAP_DMA_HALF_IRQ (1 << 2)
-#define OMAP_DMA_FRAME_IRQ (1 << 3)
-#define OMAP_DMA_LAST_IRQ (1 << 4)
-#define OMAP_DMA_BLOCK_IRQ (1 << 5)
-#define OMAP1_DMA_SYNC_IRQ (1 << 6)
-#define OMAP2_DMA_PKT_IRQ (1 << 7)
-#define OMAP2_DMA_TRANS_ERR_IRQ (1 << 8)
-#define OMAP2_DMA_SECURE_ERR_IRQ (1 << 9)
-#define OMAP2_DMA_SUPERVISOR_ERR_IRQ (1 << 10)
-#define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11)
-
-#define OMAP_DMA_CCR_EN (1 << 7)
-#define OMAP_DMA_CCR_RD_ACTIVE (1 << 9)
-#define OMAP_DMA_CCR_WR_ACTIVE (1 << 10)
-#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC (1 << 24)
-#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25)
-
-#define OMAP_DMA_DATA_TYPE_S8 0x00
-#define OMAP_DMA_DATA_TYPE_S16 0x01
-#define OMAP_DMA_DATA_TYPE_S32 0x02
-
-#define OMAP_DMA_SYNC_ELEMENT 0x00
-#define OMAP_DMA_SYNC_FRAME 0x01
-#define OMAP_DMA_SYNC_BLOCK 0x02
-#define OMAP_DMA_SYNC_PACKET 0x03
-
-#define OMAP_DMA_DST_SYNC_PREFETCH 0x02
-#define OMAP_DMA_SRC_SYNC 0x01
-#define OMAP_DMA_DST_SYNC 0x00
-
-#define OMAP_DMA_PORT_EMIFF 0x00
-#define OMAP_DMA_PORT_EMIFS 0x01
-#define OMAP_DMA_PORT_OCP_T1 0x02
-#define OMAP_DMA_PORT_TIPB 0x03
-#define OMAP_DMA_PORT_OCP_T2 0x04
-#define OMAP_DMA_PORT_MPUI 0x05
-
-#define OMAP_DMA_AMODE_CONSTANT 0x00
-#define OMAP_DMA_AMODE_POST_INC 0x01
-#define OMAP_DMA_AMODE_SINGLE_IDX 0x02
-#define OMAP_DMA_AMODE_DOUBLE_IDX 0x03
-
-#define DMA_DEFAULT_FIFO_DEPTH 0x10
-#define DMA_DEFAULT_ARB_RATE 0x01
-/* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */
-#define DMA_THREAD_RESERVE_NORM (0x00 << 12) /* Def */
-#define DMA_THREAD_RESERVE_ONET (0x01 << 12)
-#define DMA_THREAD_RESERVE_TWOT (0x02 << 12)
-#define DMA_THREAD_RESERVE_THREET (0x03 << 12)
-#define DMA_THREAD_FIFO_NONE (0x00 << 14) /* Def */
-#define DMA_THREAD_FIFO_75 (0x01 << 14)
-#define DMA_THREAD_FIFO_25 (0x02 << 14)
-#define DMA_THREAD_FIFO_50 (0x03 << 14)
-
-/* DMA4_OCP_SYSCONFIG bits */
-#define DMA_SYSCONFIG_MIDLEMODE_MASK (3 << 12)
-#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK (3 << 8)
-#define DMA_SYSCONFIG_EMUFREE (1 << 5)
-#define DMA_SYSCONFIG_SIDLEMODE_MASK (3 << 3)
-#define DMA_SYSCONFIG_SOFTRESET (1 << 2)
-#define DMA_SYSCONFIG_AUTOIDLE (1 << 0)
-
-#define DMA_SYSCONFIG_MIDLEMODE(n) ((n) << 12)
-#define DMA_SYSCONFIG_SIDLEMODE(n) ((n) << 3)
-
-#define DMA_IDLEMODE_SMARTIDLE 0x2
-#define DMA_IDLEMODE_NO_IDLE 0x1
-#define DMA_IDLEMODE_FORCE_IDLE 0x0
-
-/* Chaining modes*/
-#ifndef CONFIG_ARCH_OMAP1
-#define OMAP_DMA_STATIC_CHAIN 0x1
-#define OMAP_DMA_DYNAMIC_CHAIN 0x2
-#define OMAP_DMA_CHAIN_ACTIVE 0x1
-#define OMAP_DMA_CHAIN_INACTIVE 0x0
-#endif
-
-#define DMA_CH_PRIO_HIGH 0x1
-#define DMA_CH_PRIO_LOW 0x0 /* Def */
-
-/* Errata handling */
-#define IS_DMA_ERRATA(id) (errata & (id))
-#define SET_DMA_ERRATA(id) (errata |= (id))
-
-#define DMA_ERRATA_IFRAME_BUFFERING BIT(0x0)
-#define DMA_ERRATA_PARALLEL_CHANNELS BIT(0x1)
-#define DMA_ERRATA_i378 BIT(0x2)
-#define DMA_ERRATA_i541 BIT(0x3)
-#define DMA_ERRATA_i88 BIT(0x4)
-#define DMA_ERRATA_3_3 BIT(0x5)
-#define DMA_ROMCODE_BUG BIT(0x6)
-
-/* Attributes for OMAP DMA Contrller */
-#define DMA_LINKED_LCH BIT(0x0)
-#define GLOBAL_PRIORITY BIT(0x1)
-#define RESERVE_CHANNEL BIT(0x2)
-#define IS_CSSA_32 BIT(0x3)
-#define IS_CDSA_32 BIT(0x4)
-#define IS_RW_PRIORITY BIT(0x5)
-#define ENABLE_1510_MODE BIT(0x6)
-#define SRC_PORT BIT(0x7)
-#define DST_PORT BIT(0x8)
-#define SRC_INDEX BIT(0x9)
-#define DST_INDEX BIT(0xa)
-#define IS_BURST_ONLY4 BIT(0xb)
-#define CLEAR_CSR_ON_READ BIT(0xc)
-#define IS_WORD_16 BIT(0xd)
-#define ENABLE_16XX_MODE BIT(0xe)
-#define HS_CHANNELS_RESERVED BIT(0xf)
-
-/* Defines for DMA Capabilities */
-#define DMA_HAS_TRANSPARENT_CAPS (0x1 << 18)
-#define DMA_HAS_CONSTANT_FILL_CAPS (0x1 << 19)
-#define DMA_HAS_DESCRIPTOR_CAPS (0x3 << 20)
-
-enum omap_reg_offsets {
-
-GCR, GSCR, GRST1, HW_ID,
-PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
-PCHD_ID, CAPS_0, CAPS_1, CAPS_2,
-CAPS_3, CAPS_4, PCH2_SR, PCH0_SR,
-PCH1_SR, PCHD_SR, REVISION, IRQSTATUS_L0,
-IRQSTATUS_L1, IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0,
-IRQENABLE_L1, IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS,
-OCP_SYSCONFIG,
-
-/* omap1+ specific */
-CPC, CCR2, LCH_CTRL,
-
-/* Common registers for all omap's */
-CSDP, CCR, CICR, CSR,
-CEN, CFN, CSFI, CSEI,
-CSAC, CDAC, CDEI,
-CDFI, CLNK_CTRL,
-
-/* Channel specific registers */
-CSSA, CDSA, COLOR,
-CCEN, CCFN,
-
-/* omap3630 and omap4 specific */
-CDP, CNDP, CCDN,
-
-};
-
-enum omap_dma_burst_mode {
- OMAP_DMA_DATA_BURST_DIS = 0,
- OMAP_DMA_DATA_BURST_4,
- OMAP_DMA_DATA_BURST_8,
- OMAP_DMA_DATA_BURST_16,
-};
-
-enum end_type {
- OMAP_DMA_LITTLE_ENDIAN = 0,
- OMAP_DMA_BIG_ENDIAN
-};
-
-enum omap_dma_color_mode {
- OMAP_DMA_COLOR_DIS = 0,
- OMAP_DMA_CONSTANT_FILL,
- OMAP_DMA_TRANSPARENT_COPY
-};
-
-enum omap_dma_write_mode {
- OMAP_DMA_WRITE_NON_POSTED = 0,
- OMAP_DMA_WRITE_POSTED,
- OMAP_DMA_WRITE_LAST_NON_POSTED
-};
-
-enum omap_dma_channel_mode {
- OMAP_DMA_LCH_2D = 0,
- OMAP_DMA_LCH_G,
- OMAP_DMA_LCH_P,
- OMAP_DMA_LCH_PD
-};
-
-struct omap_dma_channel_params {
- int data_type; /* data type 8,16,32 */
- int elem_count; /* number of elements in a frame */
- int frame_count; /* number of frames in a element */
-
- int src_port; /* Only on OMAP1 REVISIT: Is this needed? */
- int src_amode; /* constant, post increment, indexed,
- double indexed */
- unsigned long src_start; /* source address : physical */
- int src_ei; /* source element index */
- int src_fi; /* source frame index */
-
- int dst_port; /* Only on OMAP1 REVISIT: Is this needed? */
- int dst_amode; /* constant, post increment, indexed,
- double indexed */
- unsigned long dst_start; /* source address : physical */
- int dst_ei; /* source element index */
- int dst_fi; /* source frame index */
-
- int trigger; /* trigger attached if the channel is
- synchronized */
- int sync_mode; /* sycn on element, frame , block or packet */
- int src_or_dst_synch; /* source synch(1) or destination synch(0) */
-
- int ie; /* interrupt enabled */
-
- unsigned char read_prio;/* read priority */
- unsigned char write_prio;/* write priority */
-
-#ifndef CONFIG_ARCH_OMAP1
- enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */
-#endif
-};
-
-struct omap_dma_lch {
- int next_lch;
- int dev_id;
- u16 saved_csr;
- u16 enabled_irqs;
- const char *dev_name;
- void (*callback)(int lch, u16 ch_status, void *data);
- void *data;
- long flags;
- /* required for Dynamic chaining */
- int prev_linked_ch;
- int next_linked_ch;
- int state;
- int chain_id;
- int status;
-};
-
-struct omap_dma_dev_attr {
- u32 dev_caps;
- u16 lch_count;
- u16 chan_count;
- struct omap_dma_lch *chan;
-};
-
-/* System DMA platform data structure */
-struct omap_system_dma_plat_info {
- struct omap_dma_dev_attr *dma_attr;
- u32 errata;
- void (*disable_irq_lch)(int lch);
- void (*show_dma_caps)(void);
- void (*clear_lch_regs)(int lch);
- void (*clear_dma)(int lch);
- void (*dma_write)(u32 val, int reg, int lch);
- u32 (*dma_read)(int reg, int lch);
-};
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-#define dma_omap2plus() 1
-#else
-#define dma_omap2plus() 0
-#endif
-#define dma_omap1() (!dma_omap2plus())
-#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
-#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
-
-extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-extern int omap_request_dma(int dev_id, const char *dev_name,
- void (*callback)(int lch, u16 ch_status, void *data),
- void *data, int *dma_ch);
-extern void omap_enable_dma_irq(int ch, u16 irq_bits);
-extern void omap_disable_dma_irq(int ch, u16 irq_bits);
-extern void omap_free_dma(int ch);
-extern void omap_start_dma(int lch);
-extern void omap_stop_dma(int lch);
-extern void omap_set_dma_transfer_params(int lch, int data_type,
- int elem_count, int frame_count,
- int sync_mode,
- int dma_trigger, int src_or_dst_synch);
-extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
- u32 color);
-extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
-extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode);
-
-extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
- unsigned long src_start,
- int src_ei, int src_fi);
-extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
-extern void omap_set_dma_src_data_pack(int lch, int enable);
-extern void omap_set_dma_src_burst_mode(int lch,
- enum omap_dma_burst_mode burst_mode);
-
-extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
- unsigned long dest_start,
- int dst_ei, int dst_fi);
-extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
-extern void omap_set_dma_dest_data_pack(int lch, int enable);
-extern void omap_set_dma_dest_burst_mode(int lch,
- enum omap_dma_burst_mode burst_mode);
-
-extern void omap_set_dma_params(int lch,
- struct omap_dma_channel_params *params);
-
-extern void omap_dma_link_lch(int lch_head, int lch_queue);
-extern void omap_dma_unlink_lch(int lch_head, int lch_queue);
-
-extern int omap_set_dma_callback(int lch,
- void (*callback)(int lch, u16 ch_status, void *data),
- void *data);
-extern dma_addr_t omap_get_dma_src_pos(int lch);
-extern dma_addr_t omap_get_dma_dst_pos(int lch);
-extern void omap_clear_dma(int lch);
-extern int omap_get_dma_active_status(int lch);
-extern int omap_dma_running(void);
-extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
- int tparams);
-extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
- unsigned char write_prio);
-extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype);
-extern void omap_set_dma_src_endian_type(int lch, enum end_type etype);
-extern int omap_get_dma_index(int lch, int *ei, int *fi);
-
-void omap_dma_global_context_save(void);
-void omap_dma_global_context_restore(void);
-
-extern void omap_dma_disable_irq(int lch);
-
-/* Chaining APIs */
-#ifndef CONFIG_ARCH_OMAP1
-extern int omap_request_dma_chain(int dev_id, const char *dev_name,
- void (*callback) (int lch, u16 ch_status,
- void *data),
- int *chain_id, int no_of_chans,
- int chain_mode,
- struct omap_dma_channel_params params);
-extern int omap_free_dma_chain(int chain_id);
-extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
- int dest_start, int elem_count,
- int frame_count, void *callbk_data);
-extern int omap_start_dma_chain_transfers(int chain_id);
-extern int omap_stop_dma_chain_transfers(int chain_id);
-extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
-extern int omap_get_dma_chain_dst_pos(int chain_id);
-extern int omap_get_dma_chain_src_pos(int chain_id);
-
-extern int omap_modify_dma_chain_params(int chain_id,
- struct omap_dma_channel_params params);
-extern int omap_dma_chain_status(int chain_id);
-#endif
-
-#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
-#include <mach/lcd_dma.h>
-#else
-static inline int omap_lcd_dma_running(void)
-{
- return 0;
-}
-#endif
-
-#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index 1867944415ca..8db0b981ca64 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -41,7 +41,7 @@ void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
static int __init orion_add_irq_domain(struct device_node *np,
struct device_node *interrupt_parent)
{
- int i = 0, irq_gpio;
+ int i = 0;
void __iomem *base;
do {
@@ -54,10 +54,6 @@ static int __init orion_add_irq_domain(struct device_node *np,
irq_domain_add_legacy(np, i * 32, 0, 0,
&irq_domain_simple_ops, NULL);
-
- irq_gpio = i * 32;
- orion_gpio_of_init(irq_gpio);
-
return 0;
}
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 0abd1c469887..ba3e76c95504 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -325,7 +325,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
chan->state = S3C2410_DMA_RUNNING;
- /* check wether there is anything to load, and if not, see
+ /* check whether there is anything to load, and if not, see
* if we can find anything to load
*/
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index a17d7b3e3725..51afedda9ab6 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -146,15 +146,6 @@ struct platform_device s3c_device_camif = {
/* ASOC DMA */
-struct platform_device samsung_asoc_dma = {
- .name = "samsung-audio",
- .id = -1,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- }
-};
-
struct platform_device samsung_asoc_idma = {
.name = "samsung-idma",
.id = -1,
@@ -929,6 +920,7 @@ struct platform_device s5p_device_mfc_r = {
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
+
#endif /* CONFIG_S5P_DEV_MFC */
/* MIPI CSIS */
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index a9b8096b8252..87d501ff3328 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -132,9 +132,6 @@ extern struct platform_device exynos4_device_pcm1;
extern struct platform_device exynos4_device_pcm2;
extern struct platform_device exynos4_device_spdif;
-extern struct platform_device exynos_device_drm;
-
-extern struct platform_device samsung_asoc_dma;
extern struct platform_device samsung_asoc_idma;
extern struct platform_device samsung_device_keypad;
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 1fe6917f6a2a..dfd8b7af8c7a 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -48,6 +48,7 @@ struct samsung_gpio_cfg;
* @config: special function and pull-resistor control information.
* @lock: Lock for exclusive access to this gpio bank.
* @pm_save: Save information for suspend/resume support.
+ * @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not.
*
* This wrapper provides the necessary information for the Samsung
* specific gpios being registered with gpiolib.
@@ -71,6 +72,7 @@ struct samsung_gpio_chip {
#ifdef CONFIG_PM
u32 pm_save[4];
#endif
+ u32 bitmap_gpio_int;
};
static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
diff --git a/arch/arm/plat-samsung/include/plat/mfc.h b/arch/arm/plat-samsung/include/plat/mfc.h
index ac13227272f0..e6d7c42d68b6 100644
--- a/arch/arm/plat-samsung/include/plat/mfc.h
+++ b/arch/arm/plat-samsung/include/plat/mfc.h
@@ -10,6 +10,14 @@
#ifndef __PLAT_SAMSUNG_MFC_H
#define __PLAT_SAMSUNG_MFC_H __FILE__
+struct s5p_mfc_dt_meminfo {
+ unsigned long loff;
+ unsigned long lsize;
+ unsigned long roff;
+ unsigned long rsize;
+ char *compatible;
+};
+
/**
* s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
* @rbase: base address for MFC 'right' memory interface
@@ -24,4 +32,7 @@
void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize);
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+ int depth, void *data);
+
#endif /* __PLAT_SAMSUNG_MFC_H */
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 61fc53740fbd..887a0c954379 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -107,10 +107,12 @@ extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
#ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
extern int s3c24xx_irq_suspend(void);
extern void s3c24xx_irq_resume(void);
#else
+#define s3c_irq_wake NULL
#define s3c_irqext_wake NULL
#define s3c24xx_irq_suspend NULL
#define s3c24xx_irq_resume NULL
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c
index ad6089465e2a..5ec104b5408b 100644
--- a/arch/arm/plat-samsung/s5p-dev-mfc.c
+++ b/arch/arm/plat-samsung/s5p-dev-mfc.c
@@ -14,6 +14,8 @@
#include <linux/dma-mapping.h>
#include <linux/memblock.h>
#include <linux/ioport.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
#include <mach/map.h>
#include <plat/devs.h>
@@ -69,3 +71,35 @@ static int __init s5p_mfc_memory_init(void)
return 0;
}
device_initcall(s5p_mfc_memory_init);
+
+#ifdef CONFIG_OF
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ __be32 *prop;
+ unsigned long len;
+ struct s5p_mfc_dt_meminfo *mfc_mem = data;
+
+ if (!data)
+ return 0;
+
+ if (!of_flat_dt_is_compatible(node, mfc_mem->compatible))
+ return 0;
+
+ prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len);
+ if (!prop || (len != 2 * sizeof(unsigned long)))
+ return 0;
+
+ mfc_mem->loff = be32_to_cpu(prop[0]);
+ mfc_mem->lsize = be32_to_cpu(prop[1]);
+
+ prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len);
+ if (!prop || (len != 2 * sizeof(unsigned long)))
+ return 0;
+
+ mfc_mem->roff = be32_to_cpu(prop[0]);
+ mfc_mem->rsize = be32_to_cpu(prop[1]);
+
+ return 1;
+}
+#endif
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c
index 23557d30e44c..bae56131a50a 100644
--- a/arch/arm/plat-samsung/s5p-irq-gpioint.c
+++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c
@@ -185,7 +185,7 @@ int __init s5p_register_gpio_interrupt(int pin)
/* check if the group has been already registered */
if (my_chip->irq_base)
- return my_chip->irq_base + offset;
+ goto success;
/* register gpio group */
ret = s5p_gpioint_add(my_chip);
@@ -193,9 +193,13 @@ int __init s5p_register_gpio_interrupt(int pin)
my_chip->chip.to_irq = samsung_gpiolib_to_irq;
printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
group);
- return my_chip->irq_base + offset;
+ goto success;
}
return ret;
+success:
+ my_chip->bitmap_gpio_int |= BIT(offset);
+
+ return my_chip->irq_base + offset;
}
int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 202d71a15be1..e40c9bd79143 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -82,7 +82,6 @@ config PLATFORM_AT32AP
select ARCH_REQUIRE_GPIOLIB
select GENERIC_ALLOCATOR
select HAVE_FB_ATMEL
- select HAVE_NET_MACB
#
# CPU types
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index a473f8c6a9aa..486df68abeec 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/blackfin/mach-bf609/Kconfig b/arch/blackfin/mach-bf609/Kconfig
index 101b33ee9bba..95a4f1b676ce 100644
--- a/arch/blackfin/mach-bf609/Kconfig
+++ b/arch/blackfin/mach-bf609/Kconfig
@@ -56,7 +56,7 @@ config SEC_IRQ_PRIORITY_LEVELS
default 7
range 0 7
help
- Devide the total number of interrupt priority levels into sub-levels.
+ Divide the total number of interrupt priority levels into sub-levels.
There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels.
endmenu
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
index 342e378da1ec..1f3b3ef3e103 100644
--- a/arch/blackfin/mm/sram-alloc.c
+++ b/arch/blackfin/mm/sram-alloc.c
@@ -191,7 +191,7 @@ static irqreturn_t l2_ecc_err(int irq, void *dev_id)
{
int status;
- printk(KERN_ERR "L2 ecc error happend\n");
+ printk(KERN_ERR "L2 ecc error happened\n");
status = bfin_read32(L2CTL0_STAT);
if (status & 0x1)
printk(KERN_ERR "Core channel error type:0x%x, addr:0x%x\n",
diff --git a/arch/cris/include/arch-v10/arch/irq.h b/arch/cris/include/arch-v10/arch/irq.h
index 7d345947b3ee..ca2675ae08ed 100644
--- a/arch/cris/include/arch-v10/arch/irq.h
+++ b/arch/cris/include/arch-v10/arch/irq.h
@@ -142,7 +142,7 @@ __asm__ ( \
* it here, we would not get the multiple_irq at all.
*
* The non-blocking here is based on the knowledge that the timer interrupt is
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
* be an sti() before the timer irq handler is run to acknowledge the interrupt.
*/
diff --git a/arch/cris/include/arch-v32/arch/irq.h b/arch/cris/include/arch-v32/arch/irq.h
index b31e9984f849..fe3cdd22bed4 100644
--- a/arch/cris/include/arch-v32/arch/irq.h
+++ b/arch/cris/include/arch-v32/arch/irq.h
@@ -103,7 +103,7 @@ __asm__ ( \
* if we had BLOCK'edit here, we would not get the multiple_irq at all.
*
* The non-blocking here is based on the knowledge that the timer interrupt is
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
* be an sti() before the timer irq handler is run to acknowledge the interrupt.
*/
#define BUILD_TIMER_IRQ(nr, mask) \
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index ae52825021af..b681b043f6c8 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -42,6 +42,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index a5b1d7dbb205..871f89b7fbda 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 4fb63a36bd52..f6084bc524e8 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -77,7 +77,7 @@ void __set_pmd(pmd_t *pmdptr, unsigned long pmd)
* checks at dup_mmap(), exec(), and other mmlist addition points
* could be used. The locking scheme was chosen on the basis of
* manfred's recommendations and having no core impact whatsoever.
- * -- wli
+ * -- nyc
*/
DEFINE_SPINLOCK(pgd_lock);
struct page *pgd_list;
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index ec4554e7b04b..90a2e573c7e6 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 41fc28a4a18a..23d6759bb57b 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -49,6 +49,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 8b3a9c0e771d..0a88cb5d316d 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1,5 +1,5 @@
/*
- * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ * kvm_ia64.c: Basic KVM support On Itanium series processors
*
*
* Copyright (C) 2007, Intel Corporation.
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index a15f40b52783..5e7088a26726 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
index d1be684edf97..285da3b6ad92 100644
--- a/arch/m68k/include/uapi/asm/socket.h
+++ b/arch/m68k/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
index 3384a5244fbd..0663067870f2 100644
--- a/arch/m68k/math-emu/fp_log.c
+++ b/arch/m68k/math-emu/fp_log.c
@@ -50,7 +50,7 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
* sqrt(m*2^e) =
* sqrt(2*m) * 2^(p) , if e = 2*p + 1
*
- * So we use the last bit of the exponent to decide wether to
+ * So we use the last bit of the exponent to decide whether to
* use the m or 2*m.
*
* Since only the fractional part of the mantissa is stored and
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index d43ceff5be47..48a4c70b3842 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -43,8 +43,8 @@ static void early_nvram_init(void)
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
- base = mcore_ssb->flash_window;
- lim = mcore_ssb->flash_window_size;
+ base = mcore_ssb->pflash.window;
+ lim = mcore_ssb->pflash.window_size;
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
index e9f9ec8d443b..e80d585731aa 100644
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
SSB_CHIPCO_IRQ_GPIO);
}
- wgt634u_flash_data.width = mcore->flash_buswidth;
- wgt634u_flash_resource.start = mcore->flash_window;
- wgt634u_flash_resource.end = mcore->flash_window
- + mcore->flash_window_size
+ wgt634u_flash_data.width = mcore->pflash.buswidth;
+ wgt634u_flash_resource.start = mcore->pflash.window;
+ wgt634u_flash_resource.end = mcore->pflash.window
+ + mcore->pflash.window_size
- 1;
return platform_add_devices(wgt634u_devices,
ARRAY_SIZE(wgt634u_devices));
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index c5ed59549cb8..17307ab90474 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -63,6 +63,7 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 4efd9185f294..b14ee53581a9 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -341,7 +341,7 @@ static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
static void __devinit tc35815_fixup(struct pci_dev *dev)
{
- /* This device may have PM registers but not they are not suported. */
+ /* This device may have PM registers but not they are not supported. */
if (dev->pm_cap) {
dev_info(&dev->dev, "PM disabled\n");
dev->pm_cap = 0;
diff --git a/arch/mn10300/include/asm/io.h b/arch/mn10300/include/asm/io.h
index 139df8c53de8..e6ed0d897ccc 100644
--- a/arch/mn10300/include/asm/io.h
+++ b/arch/mn10300/include/asm/io.h
@@ -14,6 +14,7 @@
#include <asm/page.h> /* I/O is all done through memory accesses */
#include <asm/cpu-regs.h>
#include <asm/cacheflush.h>
+#include <asm-generic/pci_iomap.h>
#define mmiowb() do {} while (0)
@@ -258,7 +259,7 @@ static inline void __iomem *__ioremap(unsigned long offset, unsigned long size,
static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
{
- return (void __iomem *) offset;
+ return (void __iomem *)(offset & ~0x20000000);
}
/*
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index 820463a484b8..af5366bbfe62 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 96f24fab7de6..47b3bb0c04ff 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -96,7 +96,7 @@ void foo(void)
OFFSET(__rx_outp, mn10300_serial_port, rx_outp);
OFFSET(__uart_state, mn10300_serial_port, uart.state);
OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar);
- OFFSET(__tx_break, mn10300_serial_port, tx_break);
+ OFFSET(__tx_flags, mn10300_serial_port, tx_flags);
OFFSET(__intr_flags, mn10300_serial_port, intr_flags);
OFFSET(__rx_icr, mn10300_serial_port, rx_icr);
OFFSET(__tx_icr, mn10300_serial_port, tx_icr);
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index 35932a8de8b8..6ab3b73efcf8 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -142,57 +142,11 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
bool force)
{
unsigned long flags;
- int err;
flags = arch_local_cli_save();
-
- /* check irq no */
- switch (d->irq) {
- case TMJCIRQ:
- case RESCHEDULE_IPI:
- case CALL_FUNC_SINGLE_IPI:
- case LOCAL_TIMER_IPI:
- case FLUSH_CACHE_IPI:
- case CALL_FUNCTION_NMI_IPI:
- case DEBUGGER_NMI_IPI:
-#ifdef CONFIG_MN10300_TTYSM0
- case SC0RXIRQ:
- case SC0TXIRQ:
-#ifdef CONFIG_MN10300_TTYSM0_TIMER8
- case TM8IRQ:
-#elif CONFIG_MN10300_TTYSM0_TIMER2
- case TM2IRQ:
-#endif /* CONFIG_MN10300_TTYSM0_TIMER8 */
-#endif /* CONFIG_MN10300_TTYSM0 */
-
-#ifdef CONFIG_MN10300_TTYSM1
- case SC1RXIRQ:
- case SC1TXIRQ:
-#ifdef CONFIG_MN10300_TTYSM1_TIMER12
- case TM12IRQ:
-#elif defined(CONFIG_MN10300_TTYSM1_TIMER9)
- case TM9IRQ:
-#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
- case TM3IRQ:
-#endif /* CONFIG_MN10300_TTYSM1_TIMER12 */
-#endif /* CONFIG_MN10300_TTYSM1 */
-
-#ifdef CONFIG_MN10300_TTYSM2
- case SC2RXIRQ:
- case SC2TXIRQ:
- case TM10IRQ:
-#endif /* CONFIG_MN10300_TTYSM2 */
- err = -1;
- break;
-
- default:
- set_bit(d->irq, irq_affinity_request);
- err = 0;
- break;
- }
-
+ set_bit(d->irq, irq_affinity_request);
arch_local_irq_restore(flags);
- return err;
+ return 0;
}
#endif /* CONFIG_SMP */
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
index dfc1b6f2fa9a..b95e76caf4fa 100644
--- a/arch/mn10300/kernel/mn10300-serial-low.S
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -118,8 +118,8 @@ ENTRY(mn10300_serial_vdma_tx_handler)
movbu d2,(e3) # ACK the interrupt
movhu (e3),d2 # flush
- btst 0x01,(__tx_break,a3) # handle transmit break request
- bne mnsc_vdma_tx_break
+ btst 0xFF,(__tx_flags,a3) # handle transmit flags
+ bne mnsc_vdma_tx_flags
movbu (SCxSTR,e2),d2 # don't try and transmit a char if the
# buffer is not empty
@@ -171,10 +171,13 @@ mnsc_vdma_tx_empty:
bset MNSCx_TX_EMPTY,(__intr_flags,a3)
bra mnsc_vdma_tx_done
-mnsc_vdma_tx_break:
+mnsc_vdma_tx_flags:
+ btst MNSCx_TX_STOP,(__tx_flags,a3)
+ bne mnsc_vdma_tx_stop
movhu (SCxCTR,e2),d2 # turn on break mode
or SC01CTR_BKE,d2
movhu d2,(SCxCTR,e2)
+mnsc_vdma_tx_stop:
mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
movhu d2,(e3) # disable transmit interrupts on this
# channel
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index 339cef4c8256..81d5cb9b6569 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -408,6 +408,34 @@ static struct irq_chip mn10300_serial_pic = {
.irq_unmask = mn10300_serial_nop,
};
+static void mn10300_serial_low_mask(struct irq_data *d)
+{
+ unsigned long flags;
+ u16 tmp;
+
+ flags = arch_local_cli_save();
+ GxICR(d->irq) = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ tmp = GxICR(d->irq); /* flush write buffer */
+ arch_local_irq_restore(flags);
+}
+
+static void mn10300_serial_low_unmask(struct irq_data *d)
+{
+ unsigned long flags;
+ u16 tmp;
+
+ flags = arch_local_cli_save();
+ GxICR(d->irq) =
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
+ tmp = GxICR(d->irq); /* flush write buffer */
+ arch_local_irq_restore(flags);
+}
+
+static struct irq_chip mn10300_serial_low_pic = {
+ .name = "mnserial-low",
+ .irq_mask = mn10300_serial_low_mask,
+ .irq_unmask = mn10300_serial_low_unmask,
+};
/*
* serial virtual DMA interrupt jump table
@@ -416,25 +444,53 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
{
- unsigned long flags;
+ int retries = 100;
u16 x;
- flags = arch_local_cli_save();
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->tx_icr;
- arch_local_irq_restore(flags);
+ /* nothing to do if irq isn't set up */
+ if (!mn10300_serial_int_tbl[port->tx_irq].port)
+ return;
+
+ port->tx_flags |= MNSCx_TX_STOP;
+ mb();
+
+ /*
+ * Here we wait for the irq to be disabled. Either it already is
+ * disabled or we wait some number of retries for the VDMA handler
+ * to disable it. The retries give the VDMA handler enough time to
+ * run to completion if it was already in progress. If the VDMA IRQ
+ * is enabled but the handler is not yet running when arrive here,
+ * the STOP flag will prevent the handler from conflicting with the
+ * driver code following this loop.
+ */
+ while ((*port->tx_icr & GxICR_ENABLE) && retries-- > 0)
+ ;
+ if (retries <= 0) {
+ *port->tx_icr =
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ x = *port->tx_icr;
+ }
}
static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
{
- unsigned long flags;
u16 x;
- flags = arch_local_cli_save();
+ /* nothing to do if irq isn't set up */
+ if (!mn10300_serial_int_tbl[port->tx_irq].port)
+ return;
+
+ /* stop vdma irq if not already stopped */
+ if (!(port->tx_flags & MNSCx_TX_STOP))
+ mn10300_serial_dis_tx_intr(port);
+
+ port->tx_flags &= ~MNSCx_TX_STOP;
+ mb();
+
*port->tx_icr =
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) |
+ GxICR_ENABLE | GxICR_REQUEST | GxICR_DETECT;
x = *port->tx_icr;
- arch_local_irq_restore(flags);
}
static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
@@ -487,16 +543,17 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
try_again:
/* pull chars out of the hat */
- ix = port->rx_outp;
- if (ix == port->rx_inp) {
+ ix = ACCESS_ONCE(port->rx_outp);
+ if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) {
if (push && !tty->low_latency)
tty_flip_buffer_push(tty);
return;
}
+ smp_read_barrier_depends();
ch = port->rx_buffer[ix++];
st = port->rx_buffer[ix++];
- smp_rmb();
+ smp_mb();
port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
port->uart.icount.rx++;
@@ -778,8 +835,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
- u16 x;
-
_enter("%s{%lu}",
port->name,
CIRC_CNT(&port->uart.state->xmit.head,
@@ -787,14 +842,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
UART_XMIT_SIZE));
/* kick the virtual DMA controller */
- arch_local_cli();
- x = *port->tx_icr;
- x |= GxICR_ENABLE;
-
- if (*port->_status & SC01STR_TBF)
- x &= ~(GxICR_REQUEST | GxICR_DETECT);
- else
- x |= GxICR_REQUEST | GxICR_DETECT;
+ mn10300_serial_en_tx_intr(port);
_debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
*port->_control, *port->_intr, *port->_status,
@@ -802,10 +850,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
(port->div_timer == MNSCx_DIV_TIMER_8BIT) ?
*(volatile u8 *)port->_tmxbr : *port->_tmxbr,
*port->tx_icr);
-
- *port->tx_icr = x;
- x = *port->tx_icr;
- arch_local_sti();
}
/*
@@ -815,13 +859,17 @@ static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
{
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
+ unsigned long flags;
_enter("%s,%02x", port->name, ch);
if (likely(port->gdbstub)) {
port->tx_xchar = ch;
- if (ch)
+ if (ch) {
+ spin_lock_irqsave(&port->uart.lock, flags);
mn10300_serial_en_tx_intr(port);
+ spin_unlock_irqrestore(&port->uart.lock, flags);
+ }
}
}
@@ -882,18 +930,21 @@ static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
{
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
+ unsigned long flags;
_enter("%s,%d", port->name, ctl);
+ spin_lock_irqsave(&port->uart.lock, flags);
if (ctl) {
/* tell the virtual DMA handler to assert BREAK */
- port->tx_break = 1;
+ port->tx_flags |= MNSCx_TX_BREAK;
mn10300_serial_en_tx_intr(port);
} else {
- port->tx_break = 0;
+ port->tx_flags &= ~MNSCx_TX_BREAK;
*port->_control &= ~SC01CTR_BKE;
mn10300_serial_en_tx_intr(port);
}
+ spin_unlock_irqrestore(&port->uart.lock, flags);
}
/*
@@ -916,6 +967,7 @@ static int mn10300_serial_startup(struct uart_port *_port)
return -ENOMEM;
port->rx_inp = port->rx_outp = 0;
+ port->tx_flags = 0;
/* finally, enable the device */
*port->_intr = SC01ICR_TI;
@@ -928,22 +980,23 @@ static int mn10300_serial_startup(struct uart_port *_port)
pint->port = port;
pint->vdma = mn10300_serial_vdma_tx_handler;
- set_intr_level(port->rx_irq,
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
- set_intr_level(port->tx_irq,
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
+ irq_set_chip(port->rx_irq, &mn10300_serial_low_pic);
+ irq_set_chip(port->tx_irq, &mn10300_serial_low_pic);
irq_set_chip(port->tm_irq, &mn10300_serial_pic);
if (request_irq(port->rx_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->rx_name, port) < 0)
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ port->rx_name, port) < 0)
goto error;
if (request_irq(port->tx_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->tx_name, port) < 0)
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ port->tx_name, port) < 0)
goto error2;
if (request_irq(port->tm_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->tm_name, port) < 0)
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ port->tm_name, port) < 0)
goto error3;
mn10300_serial_mask_ack(port->tm_irq);
@@ -964,14 +1017,22 @@ error:
*/
static void mn10300_serial_shutdown(struct uart_port *_port)
{
+ unsigned long flags;
u16 x;
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
_enter("%s", port->name);
+ spin_lock_irqsave(&_port->lock, flags);
+ mn10300_serial_dis_tx_intr(port);
+
+ *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ x = *port->rx_icr;
+ port->tx_flags = 0;
+ spin_unlock_irqrestore(&_port->lock, flags);
+
/* disable the serial port and its baud rate timer */
- port->tx_break = 0;
*port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
*port->_tmxmd = 0;
@@ -986,12 +1047,8 @@ static void mn10300_serial_shutdown(struct uart_port *_port)
free_irq(port->rx_irq, port);
free_irq(port->tx_irq, port);
- arch_local_cli();
- *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->rx_icr;
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_int_tbl[port->tx_irq].port = NULL;
+ mn10300_serial_int_tbl[port->rx_irq].port = NULL;
}
/*
@@ -1317,7 +1374,8 @@ timer_okay:
if ((new->c_cflag & CREAD) == 0)
port->uart.ignore_status_mask |= (1 << TTY_NORMAL);
- scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
+ scxctr |= SC01CTR_TXE | SC01CTR_RXE;
+ scxctr |= *port->_control & SC01CTR_BKE;
*port->_control = scxctr;
spin_unlock_irqrestore(&port->uart.lock, flags);
@@ -1519,17 +1577,24 @@ static void mn10300_serial_console_write(struct console *co,
{
struct mn10300_serial_port *port;
unsigned i;
- u16 scxctr, txicr, tmp;
+ u16 scxctr;
u8 tmxmd;
+ unsigned long flags;
+ int locked = 1;
port = mn10300_serial_ports[co->index];
+ local_irq_save(flags);
+ if (port->uart.sysrq) {
+ /* mn10300_serial_interrupt() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->uart.lock);
+ } else
+ spin_lock(&port->uart.lock);
+
/* firstly hijack the serial port from the "virtual DMA" controller */
- arch_local_cli();
- txicr = *port->tx_icr;
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- tmp = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_dis_tx_intr(port);
/* the transmitter may be disabled */
scxctr = *port->_control;
@@ -1565,12 +1630,12 @@ static void mn10300_serial_console_write(struct console *co,
while (*port->_status & SC01STR_TBF)
continue;
- *(u8 *) port->_txb = ch;
+ *port->_txb = ch;
if (ch == 0x0a) {
while (*port->_status & SC01STR_TBF)
continue;
- *(u8 *) port->_txb = 0xd;
+ *port->_txb = 0xd;
}
}
@@ -1583,10 +1648,11 @@ static void mn10300_serial_console_write(struct console *co,
if (!(scxctr & SC01CTR_TXE))
*port->_control = scxctr;
- arch_local_cli();
- *port->tx_icr = txicr;
- tmp = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_en_tx_intr(port);
+
+ if (locked)
+ spin_unlock(&port->uart.lock);
+ local_irq_restore(flags);
}
/*
@@ -1655,18 +1721,29 @@ static int mn10300_serial_poll_get_char(struct uart_port *_port)
_enter("%s", port->name);
- do {
- /* pull chars out of the hat */
- ix = port->rx_outp;
- if (ix == port->rx_inp)
- return NO_POLL_CHAR;
+ if (mn10300_serial_int_tbl[port->rx_irq].port != NULL) {
+ do {
+ /* pull chars out of the hat */
+ ix = ACCESS_ONCE(port->rx_outp);
+ if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0)
+ return NO_POLL_CHAR;
- ch = port->rx_buffer[ix++];
- st = port->rx_buffer[ix++];
- smp_rmb();
- port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+ smp_read_barrier_depends();
+ ch = port->rx_buffer[ix++];
+ st = port->rx_buffer[ix++];
+ smp_mb();
+ port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
- } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+ } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+ } else {
+ do {
+ st = *port->_status;
+ if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
+ continue;
+ } while (!(st & SC01STR_RBF));
+
+ ch = *port->_rxb;
+ }
return ch;
}
@@ -1693,12 +1770,12 @@ static void mn10300_serial_poll_put_char(struct uart_port *_port,
tmp = *port->_intr;
if (ch == 0x0a) {
- *(u8 *) port->_txb = 0x0d;
+ *port->_txb = 0x0d;
while (*port->_status & SC01STR_TBF)
continue;
}
- *(u8 *) port->_txb = ch;
+ *port->_txb = ch;
while (*port->_status & SC01STR_TBF)
continue;
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
index 6796499bf789..01791c68ea1f 100644
--- a/arch/mn10300/kernel/mn10300-serial.h
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -29,6 +29,10 @@
#define MNSCx_TX_SPACE 0x04
#define MNSCx_TX_EMPTY 0x08
+/* tx_flags bits */
+#define MNSCx_TX_BREAK 0x01
+#define MNSCx_TX_STOP 0x02
+
#ifndef __ASSEMBLY__
struct mn10300_serial_port {
@@ -36,7 +40,7 @@ struct mn10300_serial_port {
unsigned rx_inp; /* pointer to rx input offset */
unsigned rx_outp; /* pointer to rx output offset */
u8 tx_xchar; /* high-priority XON/XOFF buffer */
- u8 tx_break; /* transmit break request */
+ u8 tx_flags; /* transmit break/stop request */
u8 intr_flags; /* interrupt flags */
volatile u16 *rx_icr; /* Rx interrupt control register */
volatile u16 *tx_icr; /* Tx interrupt control register */
@@ -54,8 +58,8 @@ struct mn10300_serial_port {
volatile u16 *_control; /* control register pointer */
volatile u8 *_status; /* status register pointer */
volatile u8 *_intr; /* interrupt register pointer */
- volatile void *_rxb; /* receive buffer register pointer */
- volatile void *_txb; /* transmit buffer register pointer */
+ volatile u8 *_rxb; /* receive buffer register pointer */
+ volatile u8 *_txb; /* transmit buffer register pointer */
volatile u16 *_tmicr; /* timer interrupt control register */
volatile u8 *_tmxmd; /* baud rate timer mode register */
volatile u16 *_tmxbr; /* baud rate timer base register */
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
index e62c223e4c45..95983cd21e77 100644
--- a/arch/mn10300/kernel/smp.c
+++ b/arch/mn10300/kernel/smp.c
@@ -130,10 +130,12 @@ static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id);
static struct irqaction reschedule_ipi = {
.handler = smp_reschedule_interrupt,
+ .flags = IRQF_NOBALANCING,
.name = "smp reschedule IPI"
};
static struct irqaction call_function_ipi = {
.handler = smp_call_function_interrupt,
+ .flags = IRQF_NOBALANCING,
.name = "smp call function IPI"
};
@@ -141,7 +143,7 @@ static struct irqaction call_function_ipi = {
static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
static struct irqaction local_timer_ipi = {
.handler = smp_ipi_timer_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED | IRQF_NOBALANCING,
.name = "smp local timer IPI"
};
#endif
@@ -180,6 +182,7 @@ static void init_ipi(void)
#ifdef CONFIG_MN10300_CACHE_ENABLED
/* set up the cache flush IPI */
+ irq_set_chip(FLUSH_CACHE_IPI, &mn10300_ipi_type);
flags = arch_local_cli_save();
__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV),
mn10300_low_ipi_handler);
@@ -189,6 +192,7 @@ static void init_ipi(void)
#endif
/* set up the NMI call function IPI */
+ irq_set_chip(CALL_FUNCTION_NMI_IPI, &mn10300_ipi_type);
flags = arch_local_cli_save();
GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
@@ -199,6 +203,10 @@ static void init_ipi(void)
__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV),
mn10300_low_ipi_handler);
arch_local_irq_restore(flags);
+
+#ifdef CONFIG_KERNEL_DEBUGGER
+ irq_set_chip(DEBUGGER_NMI_IPI, &mn10300_ipi_type);
+#endif
}
/**
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 90f346f7392d..d48a84fd7fae 100644
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -123,7 +123,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
struct mm_struct *mm;
unsigned long page;
siginfo_t info;
- int write, fault;
+ int fault;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
#ifdef CONFIG_GDBSTUB
/* handle GDB stub causing a fault */
@@ -170,6 +171,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
if (in_atomic() || !mm)
goto no_context;
+retry:
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -220,7 +222,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
*/
good_area:
info.si_code = SEGV_ACCERR;
- write = 0;
switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
default: /* 3: write, present */
case MMUFCR_xFC_TYPE_WRITE:
@@ -232,7 +233,7 @@ good_area:
case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
- write++;
+ flags |= FAULT_FLAG_WRITE;
break;
/* read from protected page */
@@ -251,7 +252,11 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -259,10 +264,22 @@ good_area:
goto do_sigbus;
BUG();
}
- if (fault & VM_FAULT_MAJOR)
- current->maj_flt++;
- else
- current->min_flt++;
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /* No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
+ }
up_read(&mm->mmap_sem);
return;
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
index 4ebf117c3285..bd9ada693f95 100644
--- a/arch/mn10300/mm/pgtable.c
+++ b/arch/mn10300/mm/pgtable.c
@@ -95,7 +95,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
* checks at dup_mmap(), exec(), and other mmlist addition points
* could be used. The locking scheme was chosen on the basis of
* manfred's recommendations and having no core impact whatsoever.
- * -- wli
+ * -- nyc
*/
DEFINE_SPINLOCK(pgd_lock);
struct page *pgd_list;
diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c
new file mode 100644
index 000000000000..bd65dae17f32
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-iomap.c
@@ -0,0 +1,35 @@
+/* ASB2305 PCI I/O mapping handler
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+
+/*
+ * Create a virtual mapping cookie for a PCI BAR (memory or IO)
+ */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ resource_size_t start = pci_resource_start(dev, bar);
+ resource_size_t len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+ return NULL;
+
+ if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) {
+ if (flags & IORESOURCE_CACHEABLE && !(flags & IORESOURCE_IO))
+ return ioremap(start, len);
+ else
+ return ioremap_nocache(start, len);
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 6dce9fc2cf3c..e2059486d3f8 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/delay.h>
+#include <linux/irq.h>
#include <asm/io.h>
#include "pci-asb2305.h"
@@ -303,9 +304,7 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
{
- struct pci_bus_region region;
- int i;
- int limit;
+ int limit, i;
if (dev->bus->number != 0)
return;
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index e7f1a2993f78..ec37e185d20d 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -146,7 +146,7 @@ config DEBUG_STACKOVERFLOW
help
Make extra checks for space available on stack in some
critical functions. This will cause kernel to run a bit slower,
- but will catch most of kernel stack overruns and exit gracefuly.
+ but will catch most of kernel stack overruns and exit gracefully.
Say Y if you are unsure.
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 1b52c2c31a7a..d9ff4731253b 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -48,6 +48,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 0x401a
#define SO_DETACH_FILTER 0x401b
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_ACCEPTCONN 0x401c
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h
index 639dc96077ab..d697b08994c9 100644
--- a/arch/powerpc/include/asm/oprofile_impl.h
+++ b/arch/powerpc/include/asm/oprofile_impl.h
@@ -34,7 +34,7 @@ struct op_system_config {
unsigned long mmcra;
#ifdef CONFIG_OPROFILE_CELL
/* Register for oprofile user tool to check cell kernel profiling
- * suport.
+ * support.
*/
unsigned long cell_support;
#endif
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 5f73ce63fcae..42b1f43b943b 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -168,9 +168,12 @@
#define PPC_INST_AND 0x7c000038
#define PPC_INST_ANDDOT 0x7c000039
#define PPC_INST_OR 0x7c000378
+#define PPC_INST_XOR 0x7c000278
#define PPC_INST_ANDI 0x70000000
#define PPC_INST_ORI 0x60000000
#define PPC_INST_ORIS 0x64000000
+#define PPC_INST_XORI 0x68000000
+#define PPC_INST_XORIS 0x6c000000
#define PPC_INST_NEG 0x7c0000d0
#define PPC_INST_BRANCH 0x48000000
#define PPC_INST_BRANCH_COND 0x40800000
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h
index eedf427c9124..3e13e23e4fdf 100644
--- a/arch/powerpc/include/asm/pte-hash64-64k.h
+++ b/arch/powerpc/include/asm/pte-hash64-64k.h
@@ -23,7 +23,7 @@
/* Note the full page bits must be in the same location as for normal
* 4k pages as the same assembly will be used to insert 64K pages
- * wether the kernel has CONFIG_PPC_64K_PAGES or not
+ * whether the kernel has CONFIG_PPC_64K_PAGES or not
*/
#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */
#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */
diff --git a/arch/powerpc/include/asm/smu.h b/arch/powerpc/include/asm/smu.h
index ae20ce1af4c7..6e909f3e6a46 100644
--- a/arch/powerpc/include/asm/smu.h
+++ b/arch/powerpc/include/asm/smu.h
@@ -132,7 +132,7 @@
*
* At this point, the OF driver seems to have a limitation on transfer
* sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
- * wether this is just an OF limit due to some temporary buffer size
+ * whether this is just an OF limit due to some temporary buffer size
* or if this is an SMU imposed limit. This driver has the same limitation
* for now as I use a 0x10 bytes temporary buffer as well
*
@@ -236,7 +236,7 @@
* 3 (optional): enable nmi? [0x00 or 0x01]
*
* Returns:
- * If parameter 2 is 0x00 and parameter 3 is not specified, returns wether
+ * If parameter 2 is 0x00 and parameter 3 is not specified, returns whether
* NMI is enabled. Otherwise unknown.
*/
#define SMU_CMD_MISC_df_NMI_OPTION 0x04
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 3d5179bb122f..eb0b1864d400 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -47,6 +47,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index bedd12e1cfbc..0733b05eb856 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -387,7 +387,7 @@ void __init find_legacy_serial_ports(void)
of_node_put(parent);
continue;
}
- /* Check for known pciclass, and also check wether we have
+ /* Check for known pciclass, and also check whether we have
* a device with child nodes for ports or not
*/
if (of_device_is_compatible(np, "pciclass,0700") ||
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 2049f2d00ffe..9db8ec07ec94 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -82,7 +82,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
return -ENXIO;
/* Claim resources. This might need some rework as well depending
- * wether we are doing probe-only or not, like assigning unassigned
+ * whether we are doing probe-only or not, like assigning unassigned
* resources etc...
*/
pcibios_claim_one_bus(phb->bus);
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index d183f8719a50..1ca045d44324 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -83,7 +83,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* the context). This is very important because we must ensure we
* don't lose the VRSAVE content that may have been set prior to
* the process doing its first vector operation
- * Userland shall check AT_HWCAP to know wether it can rely on the
+ * Userland shall check AT_HWCAP to know whether it can rely on the
* v_regs pointer or not
*/
#ifdef CONFIG_ALTIVEC
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 5829d2a950d4..cf9dada734b6 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -722,7 +722,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
}
/*
- * is_hugepage_only_range() is used by generic code to verify wether
+ * is_hugepage_only_range() is used by generic code to verify whether
* a normal mmap mapping (non hugetlbfs) is valid on a given area.
*
* until the generic code provides a more generic hook and/or starts
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 1fc8109bf2f9..8a5dfaf5c6b7 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -134,6 +134,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
___PPC_RS(a) | IMM_L(i))
#define PPC_ORIS(d, a, i) EMIT(PPC_INST_ORIS | ___PPC_RA(d) | \
___PPC_RS(a) | IMM_L(i))
+#define PPC_XOR(d, a, b) EMIT(PPC_INST_XOR | ___PPC_RA(d) | \
+ ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_XORI(d, a, i) EMIT(PPC_INST_XORI | ___PPC_RA(d) | \
+ ___PPC_RS(a) | IMM_L(i))
+#define PPC_XORIS(d, a, i) EMIT(PPC_INST_XORIS | ___PPC_RA(d) | \
+ ___PPC_RS(a) | IMM_L(i))
#define PPC_SLW(d, a, s) EMIT(PPC_INST_SLW | ___PPC_RA(d) | \
___PPC_RS(a) | ___PPC_RB(s))
#define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | ___PPC_RA(d) | \
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index dd1130642d07..e834f1ec23c8 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -13,6 +13,8 @@
#include <asm/cacheflush.h>
#include <linux/netdevice.h>
#include <linux/filter.h>
+#include <linux/if_vlan.h>
+
#include "bpf_jit.h"
#ifndef __BIG_ENDIAN
@@ -89,6 +91,8 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
case BPF_S_ANC_IFINDEX:
case BPF_S_ANC_MARK:
case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_CPU:
case BPF_S_ANC_QUEUE:
case BPF_S_LD_W_ABS:
@@ -232,6 +236,17 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
if (K >= 65536)
PPC_ORIS(r_A, r_A, IMM_H(K));
break;
+ case BPF_S_ANC_ALU_XOR_X:
+ case BPF_S_ALU_XOR_X: /* A ^= X */
+ ctx->seen |= SEEN_XREG;
+ PPC_XOR(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_XOR_K: /* A ^= K */
+ if (IMM_L(K))
+ PPC_XORI(r_A, r_A, IMM_L(K));
+ if (K >= 65536)
+ PPC_XORIS(r_A, r_A, IMM_H(K));
+ break;
case BPF_S_ALU_LSH_X: /* A <<= X; */
ctx->seen |= SEEN_XREG;
PPC_SLW(r_A, r_A, r_X);
@@ -371,6 +386,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
rxhash));
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+ PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ vlan_tci));
+ if (filter[i].code == BPF_S_ANC_VLAN_TAG)
+ PPC_ANDI(r_A, r_A, VLAN_VID_MASK);
+ else
+ PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
+ break;
case BPF_S_ANC_QUEUE:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
queue_mapping) != 2);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 028470b95886..a51cb07bd663 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -526,7 +526,7 @@ EXPORT_SYMBOL(mpc52xx_gpt_timer_period);
#define WDT_IDENTITY "mpc52xx watchdog on GPT0"
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
static unsigned long wdt_is_active;
/* wdt-capable gpt */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index dca213666747..e56bb651da1a 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -728,7 +728,7 @@ static struct cbe_iommu * __init cell_iommu_alloc(struct device_node *np)
nid, np->full_name);
/* XXX todo: If we can have multiple windows on the same IOMMU, which
- * isn't the case today, we probably want here to check wether the
+ * isn't the case today, we probably want here to check whether the
* iommu for that node is already setup.
* However, there might be issue with getting the size right so let's
* ignore that for now. We might want to completely get rid of the
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index d8b7cc8a66ca..8e299447127e 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -148,7 +148,7 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
/* Configure the source. One gross hack that was there before and
* that I've kept around is the priority to the BE which I set to
- * be the same as the interrupt source number. I don't know wether
+ * be the same as the interrupt source number. I don't know whether
* that's supposed to make any kind of sense however, we'll have to
* decide that, but for now, I'm not changing the behaviour.
*/
@@ -220,7 +220,7 @@ static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
/* For hooking up the cascace we have a problem. Our device-tree is
* crap and we don't know on which BE iic interrupt we are hooked on at
* least not the "standard" way. We can reconstitute it based on two
- * informations though: which BE node we are connected to and wether
+ * informations though: which BE node we are connected to and whether
* we are connected to IOIF0 or IOIF1. Right now, we really only care
* about the IBM cell blade and we know that its firmware gives us an
* interrupt-map property which is pretty strange.
@@ -232,7 +232,7 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
int imaplen, intsize, unit;
struct device_node *iic;
- /* First, we check wether we have a real "interrupts" in the device
+ /* First, we check whether we have a real "interrupts" in the device
* tree in case the device-tree is ever fixed
*/
struct of_irq oirq;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index c4e630576ff2..31036b56670e 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -529,7 +529,7 @@ static int __init pmac_pic_probe_mpic(void)
void __init pmac_pic_init(void)
{
/* We configure the OF parsing based on our oldworld vs. newworld
- * platform type and wether we were booted by BootX.
+ * platform type and whether we were booted by BootX.
*/
#ifdef CONFIG_PPC32
if (!pmac_newworld)
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 69718cd6d635..436d07c23be8 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -46,6 +46,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
index 6cba0a7068bc..d71a0bcf8145 100644
--- a/arch/sh/boards/board-espt.c
+++ b/arch/sh/boards/board-espt.c
@@ -1,5 +1,5 @@
/*
- * Data Technology Inc. ESPT-GIGA board suport
+ * Data Technology Inc. ESPT-GIGA board support
*
* Copyright (C) 2008, 2009 Renesas Solutions Corp.
* Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index bea1568ae4af..c83a937ead00 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -41,6 +41,7 @@
#define SO_ATTACH_FILTER 0x001a
#define SO_DETACH_FILTER 0x001b
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 0x001c
#define SO_TIMESTAMP 0x001d
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 28368701ef79..3109ca684a99 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -3,6 +3,7 @@
#include <linux/netdevice.h>
#include <linux/filter.h>
#include <linux/cache.h>
+#include <linux/if_vlan.h>
#include <asm/cacheflush.h>
#include <asm/ptrace.h>
@@ -312,6 +313,12 @@ do { *prog++ = BR_OPC | WDISP22(OFF); \
#define emit_addi(R1, IMM, R3) \
*prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+#define emit_and(R1, R2, R3) \
+ *prog++ = (AND | RS1(R1) | RS2(R2) | RD(R3))
+
+#define emit_andi(R1, IMM, R3) \
+ *prog++ = (AND | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+
#define emit_alloc_stack(SZ) \
*prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
@@ -415,6 +422,8 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_ANC_IFINDEX:
case BPF_S_ANC_MARK:
case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_CPU:
case BPF_S_ANC_QUEUE:
case BPF_S_LD_W_ABS:
@@ -600,6 +609,16 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_ANC_RXHASH:
emit_skb_load32(rxhash, r_A);
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ emit_skb_load16(vlan_tci, r_A);
+ if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+ emit_andi(r_A, VLAN_VID_MASK, r_A);
+ } else {
+ emit_loadimm(VLAN_TAG_PRESENT, r_TMP);
+ emit_and(r_A, r_TMP, r_A);
+ }
+ break;
case BPF_S_LD_IMM:
emit_loadimm(K, r_A);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9195fd80e11e..65a872bf72f9 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -370,6 +370,7 @@ config X86_NUMACHIP
depends on NUMA
depends on SMP
depends on X86_X2APIC
+ depends on PCI_MMCONFIG
---help---
Adds support for Numascale NumaChip large-SMP systems. Needed to
enable more than ~168 cores.
diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
index 851fe936d242..e3cf9f682be5 100644
--- a/arch/x86/boot/.gitignore
+++ b/arch/x86/boot/.gitignore
@@ -2,7 +2,6 @@ bootsect
bzImage
cpustr.h
mkcpustr
-offsets.h
voffset.h
zoffset.h
setup
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index e87b0cac14b5..b1942e222768 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -8,6 +8,7 @@
* ----------------------------------------------------------------------- */
#include <linux/efi.h>
+#include <linux/pci.h>
#include <asm/efi.h>
#include <asm/setup.h>
#include <asm/desc.h>
@@ -245,6 +246,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
*size = len;
}
+static efi_status_t setup_efi_pci(struct boot_params *params)
+{
+ efi_pci_io_protocol *pci;
+ efi_status_t status;
+ void **pci_handle;
+ efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+ unsigned long nr_pci, size = 0;
+ int i;
+ struct setup_data *data;
+
+ data = (struct setup_data *)params->hdr.setup_data;
+
+ while (data && data->next)
+ data = (struct setup_data *)data->next;
+
+ status = efi_call_phys5(sys_table->boottime->locate_handle,
+ EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+ NULL, &size, pci_handle);
+
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ status = efi_call_phys3(sys_table->boottime->allocate_pool,
+ EFI_LOADER_DATA, size, &pci_handle);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_call_phys5(sys_table->boottime->locate_handle,
+ EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+ NULL, &size, pci_handle);
+ }
+
+ if (status != EFI_SUCCESS)
+ goto free_handle;
+
+ nr_pci = size / sizeof(void *);
+ for (i = 0; i < nr_pci; i++) {
+ void *h = pci_handle[i];
+ uint64_t attributes;
+ struct pci_setup_rom *rom;
+
+ status = efi_call_phys3(sys_table->boottime->handle_protocol,
+ h, &pci_proto, &pci);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ if (!pci)
+ continue;
+
+ status = efi_call_phys4(pci->attributes, pci,
+ EfiPciIoAttributeOperationGet, 0,
+ &attributes);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ continue;
+
+ if (!pci->romimage || !pci->romsize)
+ continue;
+
+ size = pci->romsize + sizeof(*rom);
+
+ status = efi_call_phys3(sys_table->boottime->allocate_pool,
+ EFI_LOADER_DATA, size, &rom);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ rom->data.type = SETUP_PCI;
+ rom->data.len = size - sizeof(struct setup_data);
+ rom->data.next = 0;
+ rom->pcilen = pci->romsize;
+
+ status = efi_call_phys5(pci->pci.read, pci,
+ EfiPciIoWidthUint16, PCI_VENDOR_ID,
+ 1, &(rom->vendor));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ status = efi_call_phys5(pci->pci.read, pci,
+ EfiPciIoWidthUint16, PCI_DEVICE_ID,
+ 1, &(rom->devid));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ status = efi_call_phys5(pci->get_location, pci,
+ &(rom->segment), &(rom->bus),
+ &(rom->device), &(rom->function));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ memcpy(rom->romdata, pci->romimage, pci->romsize);
+
+ if (data)
+ data->next = (uint64_t)rom;
+ else
+ params->hdr.setup_data = (uint64_t)rom;
+
+ data = (struct setup_data *)rom;
+
+ continue;
+ free_struct:
+ efi_call_phys1(sys_table->boottime->free_pool, rom);
+ }
+
+free_handle:
+ efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
+ return status;
+}
+
/*
* See if we have Graphics Output Protocol
*/
@@ -1028,6 +1144,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
setup_graphics(boot_params);
+ setup_efi_pci(boot_params);
+
status = efi_call_phys3(sys_table->boottime->allocate_pool,
EFI_LOADER_DATA, sizeof(*gdt),
(void **)&gdt);
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index 2ad874cb661c..92862cd90201 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -13,6 +13,7 @@
#define SETUP_NONE 0
#define SETUP_E820_EXT 1
#define SETUP_DTB 2
+#define SETUP_PCI 3
/* extensible setup data list node */
struct setup_data {
diff --git a/arch/x86/include/asm/numachip/numachip.h b/arch/x86/include/asm/numachip/numachip.h
new file mode 100644
index 000000000000..1c6f7f6212c1
--- /dev/null
+++ b/arch/x86/include/asm/numachip/numachip.h
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ *
+ * Numascale NumaConnect-specific header file
+ *
+ * Copyright (C) 2012 Numascale AS. All rights reserved.
+ *
+ * Send feedback to <support@numascale.com>
+ *
+ */
+
+#ifndef _ASM_X86_NUMACHIP_NUMACHIP_H
+#define _ASM_X86_NUMACHIP_NUMACHIP_H
+
+extern int __init pci_numachip_init(void);
+
+#endif /* _ASM_X86_NUMACHIP_NUMACHIP_H */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 6e41b9343928..dba7805176bf 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
}
#endif
+struct pci_setup_rom {
+ struct setup_data data;
+ uint16_t vendor;
+ uint16_t devid;
+ uint64_t pcilen;
+ unsigned long segment;
+ unsigned long bus;
+ unsigned long device;
+ unsigned long function;
+ uint8_t romdata[0];
+};
+
#endif /* _ASM_X86_PCI_H */
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index a65829ac2b9a..9c2aa89a11cb 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -22,6 +22,7 @@
#include <linux/hardirq.h>
#include <linux/delay.h>
+#include <asm/numachip/numachip.h>
#include <asm/numachip/numachip_csr.h>
#include <asm/smp.h>
#include <asm/apic.h>
@@ -179,6 +180,7 @@ static int __init numachip_system_init(void)
return 0;
x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
+ x86_init.pci.arch_init = pci_numachip_init;
map_csrs();
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index e4c1a4184531..726bf963c227 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -606,7 +606,7 @@ void __init mtrr_bp_init(void)
/*
* This is an AMD specific MSR, but we assume(hope?) that
- * Intel will implement it to when they extend the address
+ * Intel will implement it too when they extend the address
* bus of the Xeon.
*/
if (cpuid_eax(0x80000000) >= 0x80000008) {
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index ca45696f30fb..c228322ca180 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -143,11 +143,7 @@ int default_check_phys_apicid_present(int phys_apicid)
}
#endif
-#ifndef CONFIG_DEBUG_BOOT_PARAMS
-struct boot_params __initdata boot_params;
-#else
struct boot_params boot_params;
-#endif
/*
* Machine setup..
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 8573b83a63d0..217eb705fac0 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -137,7 +137,7 @@ static void pgd_dtor(pgd_t *pgd)
* against pageattr.c; it is the unique case in which a valid change
* of kernel pagetables can't be lazily synchronized by vmalloc faults.
* vmalloc faults work because attached pagetables are never freed.
- * -- wli
+ * -- nyc
*/
#ifdef CONFIG_X86_PAE
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 520d2bd0b9c5..d11a47099d33 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -11,6 +11,7 @@
#include <asm/cacheflush.h>
#include <linux/netdevice.h>
#include <linux/filter.h>
+#include <linux/if_vlan.h>
/*
* Conventions :
@@ -212,6 +213,8 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_ANC_MARK:
case BPF_S_ANC_RXHASH:
case BPF_S_ANC_CPU:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_QUEUE:
case BPF_S_LD_W_ABS:
case BPF_S_LD_H_ABS:
@@ -515,6 +518,24 @@ void bpf_jit_compile(struct sk_filter *fp)
CLEAR_A();
#endif
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+ if (is_imm8(offsetof(struct sk_buff, vlan_tci))) {
+ /* movzwl off8(%rdi),%eax */
+ EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, vlan_tci));
+ } else {
+ EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */
+ EMIT(offsetof(struct sk_buff, vlan_tci), 4);
+ }
+ BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
+ if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+ EMIT3(0x80, 0xe4, 0xef); /* and $0xef,%ah */
+ } else {
+ EMIT3(0xc1, 0xe8, 0x0c); /* shr $0xc,%eax */
+ EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */
+ }
+ break;
case BPF_S_LD_W_ABS:
func = CHOOSE_LOAD_FUNC(K, sk_load_word);
common_load: seen |= SEEN_DATAREF;
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index 3af5a1e79c9c..ee0af58ca5bd 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_STA2X11) += sta2x11-fixup.o
obj-$(CONFIG_X86_VISWS) += visws.o
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
+obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-$(CONFIG_X86_INTEL_MID) += mrst.o
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 192397c98606..0c01261fe5a8 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,6 +12,7 @@ struct pci_root_info {
char name[16];
unsigned int res_num;
struct resource *res;
+ resource_size_t *res_offset;
struct pci_sysdata sd;
#ifdef CONFIG_PCI_MMCONFIG
bool mcfg_added;
@@ -22,6 +23,7 @@ struct pci_root_info {
};
static bool pci_use_crs = true;
+static bool pci_ignore_seg = false;
static int __init set_use_crs(const struct dmi_system_id *id)
{
@@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
return 0;
}
-static const struct dmi_system_id pci_use_crs_table[] __initconst = {
+static int __init set_ignore_seg(const struct dmi_system_id *id)
+{
+ printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
+ pci_ignore_seg = true;
+ return 0;
+}
+
+static const struct dmi_system_id pci_crs_quirks[] __initconst = {
/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
{
.callback = set_use_crs,
@@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
},
},
+
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
+ {
+ .callback = set_ignore_seg,
+ .ident = "HP xw9300",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
+ },
+ },
{}
};
@@ -108,7 +127,7 @@ void __init pci_acpi_crs_quirks(void)
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
pci_use_crs = false;
- dmi_check_system(pci_use_crs_table);
+ dmi_check_system(pci_crs_quirks);
/*
* If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
@@ -305,6 +324,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
res->flags = flags;
res->start = start;
res->end = end;
+ info->res_offset[info->res_num] = addr.translation_offset;
if (!pci_use_crs) {
dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -374,7 +394,8 @@ static void add_resources(struct pci_root_info *info,
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
else
- pci_add_resource(resources, res);
+ pci_add_resource_offset(resources, res,
+ info->res_offset[i]);
}
}
@@ -382,6 +403,8 @@ static void free_pci_root_info_res(struct pci_root_info *info)
{
kfree(info->res);
info->res = NULL;
+ kfree(info->res_offset);
+ info->res_offset = NULL;
info->res_num = 0;
}
@@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
return;
size = sizeof(*info->res) * info->res_num;
- info->res_num = 0;
info->res = kzalloc(size, GFP_KERNEL);
- if (!info->res)
+ if (!info->res) {
+ info->res_num = 0;
+ return;
+ }
+
+ size = sizeof(*info->res_offset) * info->res_num;
+ info->res_num = 0;
+ info->res_offset = kzalloc(size, GFP_KERNEL);
+ if (!info->res_offset) {
+ kfree(info->res);
+ info->res = NULL;
return;
+ }
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
@@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
int pxm;
#endif
+ if (pci_ignore_seg)
+ domain = 0;
+
if (domain && !pci_domains_supported) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (multiple domains not supported)\n",
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 720e973fc34a..1b1dda90a945 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -17,6 +17,7 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/pci_x86.h>
+#include <asm/setup.h>
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
@@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
}
+int pcibios_add_device(struct pci_dev *dev)
+{
+ struct setup_data *data;
+ struct pci_setup_rom *rom;
+ u64 pa_data;
+
+ pa_data = boot_params.hdr.setup_data;
+ while (pa_data) {
+ data = phys_to_virt(pa_data);
+
+ if (data->type == SETUP_PCI) {
+ rom = (struct pci_setup_rom *)data;
+
+ if ((pci_domain_nr(dev->bus) == rom->segment) &&
+ (dev->bus->number == rom->bus) &&
+ (PCI_SLOT(dev->devfn) == rom->device) &&
+ (PCI_FUNC(dev->devfn) == rom->function) &&
+ (dev->vendor == rom->vendor) &&
+ (dev->device == rom->devid)) {
+ dev->rom = pa_data +
+ offsetof(struct pci_setup_rom, romdata);
+ dev->romlen = rom->pcilen;
+ }
+ }
+ pa_data = data->next;
+ }
+ return 0;
+}
+
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
int err;
@@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
pcibios_disable_irq(dev);
}
-int pci_ext_cfg_avail(struct pci_dev *dev)
+int pci_ext_cfg_avail(void)
{
if (raw_pci_ext_ops)
return 1;
diff --git a/arch/x86/pci/numachip.c b/arch/x86/pci/numachip.c
new file mode 100644
index 000000000000..7307d9d12d15
--- /dev/null
+++ b/arch/x86/pci/numachip.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * Numascale NumaConnect-specific PCI code
+ *
+ * Copyright (C) 2012 Numascale AS. All rights reserved.
+ *
+ * Send feedback to <support@numascale.com>
+ *
+ * PCI accessor functions derived from mmconfig_64.c
+ *
+ */
+
+#include <linux/pci.h>
+#include <asm/pci_x86.h>
+
+static u8 limit __read_mostly;
+
+static inline char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
+{
+ struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
+
+ if (cfg && cfg->virt)
+ return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
+ return NULL;
+}
+
+static int pci_mmcfg_read_numachip(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
+{
+ char __iomem *addr;
+
+ /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+err: *value = -1;
+ return -EINVAL;
+ }
+
+ /* Ensure AMD Northbridges don't decode reads to other devices */
+ if (unlikely(bus == 0 && devfn >= limit)) {
+ *value = -1;
+ return 0;
+ }
+
+ rcu_read_lock();
+ addr = pci_dev_base(seg, bus, devfn);
+ if (!addr) {
+ rcu_read_unlock();
+ goto err;
+ }
+
+ switch (len) {
+ case 1:
+ *value = mmio_config_readb(addr + reg);
+ break;
+ case 2:
+ *value = mmio_config_readw(addr + reg);
+ break;
+ case 4:
+ *value = mmio_config_readl(addr + reg);
+ break;
+ }
+ rcu_read_unlock();
+
+ return 0;
+}
+
+static int pci_mmcfg_write_numachip(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
+{
+ char __iomem *addr;
+
+ /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
+ return -EINVAL;
+
+ /* Ensure AMD Northbridges don't decode writes to other devices */
+ if (unlikely(bus == 0 && devfn >= limit))
+ return 0;
+
+ rcu_read_lock();
+ addr = pci_dev_base(seg, bus, devfn);
+ if (!addr) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+
+ switch (len) {
+ case 1:
+ mmio_config_writeb(addr + reg, value);
+ break;
+ case 2:
+ mmio_config_writew(addr + reg, value);
+ break;
+ case 4:
+ mmio_config_writel(addr + reg, value);
+ break;
+ }
+ rcu_read_unlock();
+
+ return 0;
+}
+
+const struct pci_raw_ops pci_mmcfg_numachip = {
+ .read = pci_mmcfg_read_numachip,
+ .write = pci_mmcfg_write_numachip,
+};
+
+int __init pci_numachip_init(void)
+{
+ int ret = 0;
+ u32 val;
+
+ /* For remote I/O, restrict bus 0 access to the actual number of AMD
+ Northbridges, which starts at device number 0x18 */
+ ret = raw_pci_read(0, 0, PCI_DEVFN(0x18, 0), 0x60, sizeof(val), &val);
+ if (ret)
+ goto out;
+
+ /* HyperTransport fabric size in bits 6:4 */
+ limit = PCI_DEVFN(0x18 + ((val >> 4) & 7) + 1, 0);
+
+ /* Use NumaChip PCI accessors for non-extended and extended access */
+ raw_pci_ops = raw_pci_ext_ops = &pci_mmcfg_numachip;
+out:
+ return ret;
+}
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index e36c68184920..38079be1cf1e 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -52,6 +52,7 @@
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 0df024e5fb63..d09c6b4bab2c 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Module Name: dsopcode - Dispatcher suport for regions and fields
+ * Module Name: dsopcode - Dispatcher support for regions and fields
*
*****************************************************************************/
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 2ef04098cc1d..a1dee29beed3 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
device_set_run_wake(&dev->dev, false);
pci_acpi_remove_pm_notifier(device);
+ acpi_power_resource_unregister_device(&dev->dev, device->handle);
if (!dev->subordinate)
goto out;
- acpi_pci_irq_del_prt(dev->subordinate);
+ acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
device->ops.bind = NULL;
device->ops.unbind = NULL;
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
{
acpi_status status;
acpi_handle handle;
- struct pci_bus *bus;
+ unsigned char bus;
struct pci_dev *dev;
dev = acpi_get_pci_dev(device->handle);
@@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
return 0;
pci_acpi_add_pm_notifier(device, dev);
+ acpi_power_resource_register_device(&dev->dev, device->handle);
if (device->wakeup.flags.run_wake)
device_set_run_wake(&dev->dev, true);
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
goto out;
if (dev->subordinate)
- bus = dev->subordinate;
+ bus = dev->subordinate->number;
else
- bus = dev->bus;
+ bus = dev->bus->number;
- acpi_pci_irq_add_prt(device->handle, bus);
+ acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
out:
pci_dev_put(dev);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 23a032490130..68a921d03247 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
}
}
-static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
struct acpi_pci_routing_table *prt)
{
struct acpi_prt_entry *entry;
@@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
* 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
* it here.
*/
- entry->id.segment = pci_domain_nr(bus);
- entry->id.bus = bus->number;
+ entry->id.segment = segment;
+ entry->id.bus = bus;
entry->id.device = (prt->address >> 16) & 0xFFFF;
entry->pin = prt->pin + 1;
@@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
return 0;
}
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
entry = buffer.pointer;
while (entry && (entry->length > 0)) {
- acpi_pci_irq_add_entry(handle, bus, entry);
+ acpi_pci_irq_add_entry(handle, segment, bus, entry);
entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length);
}
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
return 0;
}
-void acpi_pci_irq_del_prt(struct pci_bus *bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
{
struct acpi_prt_entry *entry, *tmp;
printk(KERN_DEBUG
"ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
- pci_domain_nr(bus), bus->number);
+ segment, bus);
spin_lock(&acpi_prt_lock);
list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
- if (pci_domain_nr(bus) == entry->id.segment
- && bus->number == entry->id.bus) {
+ if (segment == entry->id.segment && bus == entry->id.bus) {
list_del(&entry->list);
kfree(entry);
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index f70b9e5fc1b5..7928d4dc7056 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_handle handle;
struct acpi_device *child;
u32 flags, base_flags;
+ bool is_osc_granted = false;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
@@ -501,85 +502,47 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
- root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
-
- /*
- * All supported architectures that use ACPI have support for
- * PCI domains, so we indicate this in _OSC support capabilities.
- */
- flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
- acpi_pci_osc_support(root, flags);
-
- /*
- * TBD: Need PCI interface for enumeration/configuration of roots.
- */
-
- mutex_lock(&acpi_pci_root_lock);
- list_add_tail(&root->node, &acpi_pci_roots);
- mutex_unlock(&acpi_pci_root_lock);
-
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
/*
- * Scan the Root Bridge
- * --------------------
- * Must do this prior to any attempt to bind the root device, as the
- * PCI namespace does not get created until this call is made (and
- * thus the root bridge's pci_dev does not exist).
- */
- root->bus = pci_acpi_scan_root(root);
- if (!root->bus) {
- printk(KERN_ERR PREFIX
- "Bus %04x:%02x not present in PCI namespace\n",
- root->segment, (unsigned int)root->secondary.start);
- result = -ENODEV;
- goto out_del_root;
- }
-
- /*
- * Attach ACPI-PCI Context
- * -----------------------
- * Thus binding the ACPI and PCI devices.
- */
- result = acpi_pci_bind_root(device);
- if (result)
- goto out_del_root;
-
- /*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists.
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
- result = acpi_pci_irq_add_prt(device->handle, root->bus);
+ result = acpi_pci_irq_add_prt(device->handle, root->segment,
+ root->secondary.start);
+
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
/*
- * Scan and bind all _ADR-Based Devices
+ * All supported architectures that use ACPI have support for
+ * PCI domains, so we indicate this in _OSC support capabilities.
*/
- list_for_each_entry(child, &device->children, node)
- acpi_pci_bridge_scan(child);
+ flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+ acpi_pci_osc_support(root, flags);
/* Indicate support for various _OSC capabilities. */
- if (pci_ext_cfg_avail(root->bus->self))
+ if (pci_ext_cfg_avail())
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
- if (pcie_aspm_support_enabled())
+ if (pcie_aspm_support_enabled()) {
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
- OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+ }
if (pci_msi_enabled())
flags |= OSC_MSI_SUPPORT;
if (flags != base_flags) {
status = acpi_pci_osc_support(root, flags);
if (ACPI_FAILURE(status)) {
- dev_info(root->bus->bridge, "ACPI _OSC support "
+ dev_info(&device->dev, "ACPI _OSC support "
"notification failed, disabling PCIe ASPM\n");
pcie_no_aspm();
flags = base_flags;
}
}
-
if (!pcie_ports_disabled
&& (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device)
if (pci_aer_available()) {
if (aer_acpi_firmware_first())
- dev_dbg(root->bus->bridge,
+ dev_dbg(&device->dev,
"PCIe errors handled by BIOS.\n");
else
flags |= OSC_PCI_EXPRESS_AER_CONTROL;
}
- dev_info(root->bus->bridge,
+ dev_info(&device->dev,
"Requesting ACPI _OSC control (0x%02x)\n", flags);
status = acpi_pci_osc_control_set(device->handle, &flags,
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_SUCCESS(status)) {
- dev_info(root->bus->bridge,
+ is_osc_granted = true;
+ dev_info(&device->dev,
"ACPI _OSC control (0x%02x) granted\n", flags);
- if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
- /*
- * We have ASPM control, but the FADT indicates
- * that it's unsupported. Clear it.
- */
- pcie_clear_aspm(root->bus);
- }
} else {
- dev_info(root->bus->bridge,
+ is_osc_granted = false;
+ dev_info(&device->dev,
"ACPI _OSC request failed (%s), "
"returned control mask: 0x%02x\n",
acpi_format_exception(status), flags);
- pr_info("ACPI _OSC control for PCIe not granted, "
- "disabling ASPM\n");
- pcie_no_aspm();
}
} else {
- dev_info(root->bus->bridge,
- "Unable to request _OSC control "
- "(_OSC support mask: 0x%02x)\n", flags);
+ dev_info(&device->dev,
+ "Unable to request _OSC control "
+ "(_OSC support mask: 0x%02x)\n", flags);
+ }
+
+ /*
+ * TBD: Need PCI interface for enumeration/configuration of roots.
+ */
+
+ mutex_lock(&acpi_pci_root_lock);
+ list_add_tail(&root->node, &acpi_pci_roots);
+ mutex_unlock(&acpi_pci_root_lock);
+
+ /*
+ * Scan the Root Bridge
+ * --------------------
+ * Must do this prior to any attempt to bind the root device, as the
+ * PCI namespace does not get created until this call is made (and
+ * thus the root bridge's pci_dev does not exist).
+ */
+ root->bus = pci_acpi_scan_root(root);
+ if (!root->bus) {
+ printk(KERN_ERR PREFIX
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->segment, (unsigned int)root->secondary.start);
+ result = -ENODEV;
+ goto out_del_root;
+ }
+
+ /*
+ * Attach ACPI-PCI Context
+ * -----------------------
+ * Thus binding the ACPI and PCI devices.
+ */
+ result = acpi_pci_bind_root(device);
+ if (result)
+ goto out_del_root;
+
+ /*
+ * Scan and bind all _ADR-Based Devices
+ */
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+
+ /* ASPM setting */
+ if (is_osc_granted) {
+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
+ pcie_clear_aspm(root->bus);
+ } else {
+ pr_info("ACPI _OSC control for PCIe not granted, "
+ "disabling ASPM\n");
+ pcie_no_aspm();
}
pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -634,6 +638,8 @@ out_del_root:
mutex_lock(&acpi_pci_root_lock);
list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock);
+
+ acpi_pci_irq_del_prt(root->segment, root->secondary.start);
end:
kfree(root);
return result;
@@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
struct acpi_pci_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver;
+ if (system_state != SYSTEM_BOOTING)
+ pci_assign_unassigned_bus_resources(root->bus);
+
mutex_lock(&acpi_pci_root_lock);
list_for_each_entry(driver, &acpi_pci_drivers, node)
if (driver->add)
driver->add(root);
mutex_unlock(&acpi_pci_root_lock);
+ /* need to after hot-added ioapic is registered */
+ if (system_state != SYSTEM_BOOTING)
+ pci_enable_bridges(root->bus);
+
pci_bus_add_devices(root->bus);
return 0;
@@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
static int acpi_pci_root_remove(struct acpi_device *device, int type)
{
+ acpi_status status;
+ acpi_handle handle;
struct acpi_pci_root *root = acpi_driver_data(device);
struct acpi_pci_driver *driver;
+ pci_stop_root_bus(root->bus);
+
mutex_lock(&acpi_pci_root_lock);
- list_for_each_entry(driver, &acpi_pci_drivers, node)
+ list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
if (driver->remove)
driver->remove(root);
+ mutex_unlock(&acpi_pci_root_lock);
device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device);
+ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+ if (ACPI_SUCCESS(status))
+ acpi_pci_irq_del_prt(root->segment, root->secondary.start);
+
+ pci_remove_root_bus(root->bus);
+
+ mutex_lock(&acpi_pci_root_lock);
list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock);
kfree(root);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 98510931c815..c909b7b7d5f1 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -164,7 +164,6 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
static uint32_t fpga_tx(struct solos_card *);
static irqreturn_t solos_irq(int irq, void *dev_id);
static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
-static int list_vccs(int vci);
static int atm_init(struct solos_card *, struct device *);
static void atm_remove(struct solos_card *);
static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -710,7 +709,8 @@ void solos_bh(unsigned long card_arg)
dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
port);
- continue;
+ dev_kfree_skb_any(skb);
+ break;
}
atm_charge(vcc, skb->truesize);
vcc->push(vcc, skb);
@@ -790,44 +790,6 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci)
return vcc;
}
-static int list_vccs(int vci)
-{
- struct hlist_head *head;
- struct atm_vcc *vcc;
- struct hlist_node *node;
- struct sock *s;
- int num_found = 0;
- int i;
-
- read_lock(&vcc_sklist_lock);
- if (vci != 0){
- head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
- sk_for_each(s, node, head) {
- num_found ++;
- vcc = atm_sk(s);
- printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
- vcc->dev->number,
- vcc->vpi,
- vcc->vci);
- }
- } else {
- for(i = 0; i < VCC_HTABLE_SIZE; i++){
- head = &vcc_hash[i];
- sk_for_each(s, node, head) {
- num_found ++;
- vcc = atm_sk(s);
- printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
- vcc->dev->number,
- vcc->vpi,
- vcc->vci);
- }
- }
- }
- read_unlock(&vcc_sklist_lock);
- return num_found;
-}
-
-
static int popen(struct atm_vcc *vcc)
{
struct solos_card *card = vcc->dev->dev_data;
@@ -840,7 +802,7 @@ static int popen(struct atm_vcc *vcc)
return -EINVAL;
}
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
if (net_ratelimit())
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
@@ -857,8 +819,6 @@ static int popen(struct atm_vcc *vcc)
set_bit(ATM_VF_ADDR, &vcc->flags);
set_bit(ATM_VF_READY, &vcc->flags);
- list_vccs(0);
-
return 0;
}
@@ -866,10 +826,21 @@ static int popen(struct atm_vcc *vcc)
static void pclose(struct atm_vcc *vcc)
{
struct solos_card *card = vcc->dev->dev_data;
- struct sk_buff *skb;
+ unsigned char port = SOLOS_CHAN(vcc->dev);
+ struct sk_buff *skb, *tmpskb;
struct pkt_hdr *header;
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ /* Remove any yet-to-be-transmitted packets from the pending queue */
+ spin_lock(&card->tx_queue_lock);
+ skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
+ if (SKB_CB(skb)->vcc == vcc) {
+ skb_unlink(skb, &card->tx_queue[port]);
+ solos_pop(vcc, skb);
+ }
+ }
+ spin_unlock(&card->tx_queue_lock);
+
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n");
return;
@@ -881,15 +852,22 @@ static void pclose(struct atm_vcc *vcc)
header->vci = cpu_to_le16(vcc->vci);
header->type = cpu_to_le16(PKT_PCLOSE);
- fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
+ skb_get(skb);
+ fpga_queue(card, port, skb, NULL);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- clear_bit(ATM_VF_READY, &vcc->flags);
+ if (!wait_event_timeout(card->param_wq, !skb_shared(skb), 5 * HZ))
+ dev_warn(&card->dev->dev,
+ "Timeout waiting for VCC close on port %d\n", port);
+
+ dev_kfree_skb(skb);
/* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
tasklet has finished processing any incoming packets (and, more to
the point, using the vcc pointer). */
tasklet_unlock_wait(&card->tlet);
+
+ clear_bit(ATM_VF_ADDR, &vcc->flags);
+
return;
}
@@ -967,10 +945,11 @@ static uint32_t fpga_tx(struct solos_card *card)
for (port = 0; tx_pending; tx_pending >>= 1, port++) {
if (tx_pending & 1) {
struct sk_buff *oldskb = card->tx_skb[port];
- if (oldskb)
+ if (oldskb) {
pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
oldskb->len, PCI_DMA_TODEVICE);
-
+ card->tx_skb[port] = NULL;
+ }
spin_lock(&card->tx_queue_lock);
skb = skb_dequeue(&card->tx_queue[port]);
if (!skb)
@@ -1011,9 +990,10 @@ static uint32_t fpga_tx(struct solos_card *card)
if (vcc) {
atomic_inc(&vcc->stats->tx);
solos_pop(vcc, oldskb);
- } else
+ } else {
dev_kfree_skb_irq(oldskb);
-
+ wake_up(&card->param_wq);
+ }
}
}
/* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
@@ -1248,7 +1228,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
card->atmdev[i]->phy_data = (void *)(unsigned long)i;
atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
- skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+ skb = alloc_skb(sizeof(*header), GFP_KERNEL);
if (!skb) {
dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
continue;
@@ -1345,6 +1325,8 @@ static struct pci_driver fpga_driver = {
static int __init solos_pci_init(void)
{
+ BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
+
printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
return pci_register_driver(&fpga_driver);
}
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 169fc58427d3..537ae53231cd 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -48,8 +48,8 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
#endif /* CONFIG_BCMA_DRIVER_MIPS */
/* driver_chipcommon_pmu.c */
-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
+u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
+u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
#ifdef CONFIG_BCMA_SFLASH
/* driver_chipcommon_sflash.c */
@@ -84,6 +84,8 @@ extern void __exit bcma_host_pci_exit(void);
/* driver_pci.c */
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
+extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc);
+
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index a4c3ebcc4c86..dc96dd8ebff2 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -4,12 +4,15 @@
*
* Copyright 2005, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include "bcma_private.h"
+#include <linux/bcm47xx_wdt.h>
#include <linux/export.h>
+#include <linux/platform_device.h>
#include <linux/bcma/bcma.h>
static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
@@ -22,12 +25,93 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
return value;
}
-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
{
- u32 leddc_on = 10;
- u32 leddc_off = 90;
+ if (cc->capabilities & BCMA_CC_CAP_PMU)
+ return bcma_pmu_get_alp_clock(cc);
- if (cc->setup_done)
+ return 20000000;
+}
+
+static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+ u32 nb;
+
+ if (cc->capabilities & BCMA_CC_CAP_PMU) {
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
+ nb = 32;
+ else if (cc->core->id.rev < 26)
+ nb = 16;
+ else
+ nb = (cc->core->id.rev >= 37) ? 32 : 24;
+ } else {
+ nb = 28;
+ }
+ if (nb == 32)
+ return 0xffffffff;
+ else
+ return (1 << nb) - 1;
+}
+
+static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
+ u32 ticks)
+{
+ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
+
+ return bcma_chipco_watchdog_timer_set(cc, ticks);
+}
+
+static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
+ u32 ms)
+{
+ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
+ u32 ticks;
+
+ ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
+ return ticks / cc->ticks_per_ms;
+}
+
+static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ if (cc->capabilities & BCMA_CC_CAP_PMU) {
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
+ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
+ return bcma_chipco_get_alp_clock(cc) / 4000;
+ else
+ /* based on 32KHz ILP clock */
+ return 32;
+ } else {
+ return bcma_chipco_get_alp_clock(cc) / 1000;
+ }
+}
+
+int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
+{
+ struct bcm47xx_wdt wdt = {};
+ struct platform_device *pdev;
+
+ wdt.driver_data = cc;
+ wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
+ wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
+ wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
+
+ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
+ cc->core->bus->num, &wdt,
+ sizeof(wdt));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ cc->watchdog = pdev;
+
+ return 0;
+}
+
+void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
+{
+ if (cc->early_setup_done)
return;
if (cc->core->id.rev >= 11)
@@ -36,6 +120,22 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
if (cc->core->id.rev >= 35)
cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
+ if (cc->capabilities & BCMA_CC_CAP_PMU)
+ bcma_pmu_early_init(cc);
+
+ cc->early_setup_done = true;
+}
+
+void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+{
+ u32 leddc_on = 10;
+ u32 leddc_off = 90;
+
+ if (cc->setup_done)
+ return;
+
+ bcma_core_chipcommon_early_init(cc);
+
if (cc->core->id.rev >= 20) {
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
@@ -56,15 +156,33 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
(leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
}
+ cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
cc->setup_done = true;
}
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
-void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
+u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
{
- /* instant NMI */
- bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
+ u32 maxt;
+ enum bcma_clkmode clkmode;
+
+ maxt = bcma_chipco_watchdog_get_max_timer(cc);
+ if (cc->capabilities & BCMA_CC_CAP_PMU) {
+ if (ticks == 1)
+ ticks = 2;
+ else if (ticks > maxt)
+ ticks = maxt;
+ bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
+ } else {
+ clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
+ bcma_core_set_clockmode(cc->core, clkmode);
+ if (ticks > maxt)
+ ticks = maxt;
+ /* instant NMI */
+ bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
+ }
+ return ticks;
}
void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
@@ -118,8 +236,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
struct bcma_serial_port *ports = cc->serial_ports;
if (ccrev >= 11 && ccrev != 15) {
- /* Fixed ALP clock */
- baud_base = bcma_pmu_alp_clock(cc);
+ baud_base = bcma_chipco_get_alp_clock(cc);
if (ccrev >= 21) {
/* Turn off UART clock before switching clocksource. */
bcma_cc_write32(cc, BCMA_CC_CORECTL,
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c
index 9042781edec3..dbda91e4dff5 100644
--- a/drivers/bcma/driver_chipcommon_nflash.c
+++ b/drivers/bcma/driver_chipcommon_nflash.c
@@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
}
cc->nflash.present = true;
+ if (cc->core->id.rev == 38 &&
+ (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
+ cc->nflash.boot = true;
/* Prepare platform device, but don't register it yet. It's too early,
* malloc (required by device_private_init) is not available yet. */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 201faf106b3f..e162999bf916 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -144,7 +144,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
}
}
-void bcma_pmu_init(struct bcma_drv_cc *cc)
+void bcma_pmu_early_init(struct bcma_drv_cc *cc)
{
u32 pmucap;
@@ -153,7 +153,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
cc->pmu.rev, pmucap);
+}
+void bcma_pmu_init(struct bcma_drv_cc *cc)
+{
if (cc->pmu.rev == 1)
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
~BCMA_CC_PMU_CTL_NOILPONW);
@@ -165,7 +168,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
bcma_pmu_workarounds(cc);
}
-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
+u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
@@ -193,7 +196,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
/* Find the output of the "m" pll divider given pll controls that start with
* pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
*/
-static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
{
u32 tmp, div, ndiv, p1, p2, fc;
struct bcma_bus *bus = cc->core->bus;
@@ -222,14 +225,14 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
/* Do calculation in Mhz */
- fc = bcma_pmu_alp_clock(cc) / 1000000;
+ fc = bcma_pmu_get_alp_clock(cc) / 1000000;
fc = (p1 * ndiv * fc) / p2;
/* Return clock in Hertz */
return (fc / div) * 1000000;
}
-static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
{
u32 tmp, ndiv, p1div, p2div;
u32 clock;
@@ -260,7 +263,7 @@ static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
}
/* query bus clock frequency for PMU-enabled chipcommon */
-static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
@@ -268,40 +271,42 @@ static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
case BCMA_CHIP_ID_BCM4716:
case BCMA_CHIP_ID_BCM4748:
case BCMA_CHIP_ID_BCM47162:
- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
- BCMA_CC_PMU5_MAINPLL_SSB);
+ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
case BCMA_CHIP_ID_BCM5356:
- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
- BCMA_CC_PMU5_MAINPLL_SSB);
+ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
case BCMA_CHIP_ID_BCM5357:
case BCMA_CHIP_ID_BCM4749:
- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
- BCMA_CC_PMU5_MAINPLL_SSB);
+ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
case BCMA_CHIP_ID_BCM4706:
- return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
- BCMA_CC_PMU5_MAINPLL_SSB);
+ return bcma_pmu_pll_clock_bcm4706(cc,
+ BCMA_CC_PMU4706_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
case BCMA_CHIP_ID_BCM53572:
return 75000000;
default:
- bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+ bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
}
return BCMA_CC_PMU_HT_CLOCK;
}
/* query cpu clock frequency for PMU-enabled chipcommon */
-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
+u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
return 300000000;
+ /* New PMUs can have different clock for bus and CPU */
if (cc->pmu.rev >= 5) {
u32 pll;
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM4706:
- return bcma_pmu_clock_bcm4706(cc,
+ return bcma_pmu_pll_clock_bcm4706(cc,
BCMA_CC_PMU4706_MAINPLL_PLL0,
BCMA_CC_PMU5_MAINPLL_CPU);
case BCMA_CHIP_ID_BCM5356:
@@ -316,10 +321,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
break;
}
- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
+ return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
}
- return bcma_pmu_get_clockcontrol(cc);
+ /* On old PMUs CPU has the same clock as the bus */
+ return bcma_pmu_get_bus_clock(cc);
}
static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c
index 2c4eec2ca5a0..63e688393825 100644
--- a/drivers/bcma/driver_chipcommon_sflash.c
+++ b/drivers/bcma/driver_chipcommon_sflash.c
@@ -12,7 +12,7 @@
static struct resource bcma_sflash_resource = {
.name = "bcma_sflash",
- .start = BCMA_SFLASH,
+ .start = BCMA_SOC_FLASH2,
.end = 0,
.flags = IORESOURCE_MEM | IORESOURCE_READONLY,
};
@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
};
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
- { "", 0x14, 0x10000, 32, },
+ { "M25P20", 0x11, 0x10000, 4, },
+ { "M25P40", 0x12, 0x10000, 8, },
+
+ { "M25P16", 0x14, 0x10000, 32, },
+ { "M25P32", 0x14, 0x10000, 64, },
+ { "M25P64", 0x16, 0x10000, 128, },
+ { "M25FL128", 0x17, 0x10000, 256, },
{ 0 },
};
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
+ { "SST25WF512", 1, 0x1000, 16, },
+ { "SST25VF512", 0x48, 0x1000, 16, },
+ { "SST25WF010", 2, 0x1000, 32, },
+ { "SST25VF010", 0x49, 0x1000, 32, },
+ { "SST25WF020", 3, 0x1000, 64, },
+ { "SST25VF020", 0x43, 0x1000, 64, },
+ { "SST25WF040", 4, 0x1000, 128, },
+ { "SST25VF040", 0x44, 0x1000, 128, },
+ { "SST25VF040B", 0x8d, 0x1000, 128, },
+ { "SST25WF080", 5, 0x1000, 256, },
+ { "SST25VF080B", 0x8e, 0x1000, 256, },
+ { "SST25VF016", 0x41, 0x1000, 512, },
+ { "SST25VF032", 0x4a, 0x1000, 1024, },
+ { "SST25VF064", 0x4b, 0x1000, 2048, },
{ 0 },
};
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
+ { "AT45DB011", 0xc, 256, 512, },
+ { "AT45DB021", 0x14, 256, 1024, },
+ { "AT45DB041", 0x1c, 256, 2048, },
+ { "AT45DB081", 0x24, 256, 4096, },
+ { "AT45DB161", 0x2c, 512, 4096, },
+ { "AT45DB321", 0x34, 512, 8192, },
+ { "AT45DB642", 0x3c, 1024, 8192, },
{ 0 },
};
@@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
break;
}
break;
+ case 0x13:
+ return -ENOTSUPP;
default:
for (e = bcma_sflash_st_tbl; e->name; e++) {
if (e->id == id)
@@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
return -ENOTSUPP;
}
- sflash->window = BCMA_SFLASH;
+ sflash->window = BCMA_SOC_FLASH2;
sflash->blocksize = e->blocksize;
sflash->numblocks = e->numblocks;
sflash->size = sflash->blocksize * sflash->numblocks;
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index cc65b45b4368..792daad28cbc 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
~(1 << irqflag));
else
- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
/* assign the new one */
if (irq == 0) {
@@ -171,7 +171,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
struct bcma_bus *bus = mcore->core->bus;
if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
- return bcma_pmu_get_clockcpu(&bus->drv_cc);
+ return bcma_pmu_get_cpu_clock(&bus->drv_cc);
bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
return 0;
@@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock);
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
{
struct bcma_bus *bus = mcore->core->bus;
+ struct bcma_drv_cc *cc = &bus->drv_cc;
- switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
case BCMA_CC_FLASHT_STSER:
case BCMA_CC_FLASHT_ATSER:
bcma_debug(bus, "Found serial flash\n");
- bcma_sflash_init(&bus->drv_cc);
+ bcma_sflash_init(cc);
break;
case BCMA_CC_FLASHT_PARA:
bcma_debug(bus, "Found parallel flash\n");
- bus->drv_cc.pflash.window = 0x1c000000;
- bus->drv_cc.pflash.window_size = 0x02000000;
+ cc->pflash.present = true;
+ cc->pflash.window = BCMA_SOC_FLASH2;
+ cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
- if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+ if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
BCMA_CC_FLASH_CFG_DS) == 0)
- bus->drv_cc.pflash.buswidth = 1;
+ cc->pflash.buswidth = 1;
else
- bus->drv_cc.pflash.buswidth = 2;
+ cc->pflash.buswidth = 2;
break;
default:
bcma_err(bus, "Flash type not supported\n");
}
- if (bus->drv_cc.core->id.rev == 38 ||
+ if (cc->core->id.rev == 38 ||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
- if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
+ if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
bcma_debug(bus, "Found NAND flash\n");
- bcma_nflash_init(&bus->drv_cc);
+ bcma_nflash_init(cc);
}
}
}
+void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus = mcore->core->bus;
+
+ if (mcore->early_setup_done)
+ return;
+
+ bcma_chipco_serial_init(&bus->drv_cc);
+ bcma_core_mips_flash_detect(mcore);
+
+ mcore->early_setup_done = true;
+}
+
void bcma_core_mips_init(struct bcma_drv_mips *mcore)
{
struct bcma_bus *bus;
struct bcma_device *core;
bus = mcore->core->bus;
+ if (mcore->setup_done)
+ return;
+
bcma_info(bus, "Initializing MIPS core...\n");
- if (!mcore->setup_done)
- mcore->assigned_irqs = 1;
+ bcma_core_mips_early_init(mcore);
+
+ mcore->assigned_irqs = 1;
/* Assign IRQs to all cores on the bus */
list_for_each_entry(core, &bus->cores, list) {
@@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
bcma_info(bus, "IRQ reconfiguration done\n");
bcma_core_mips_dump_irq(bus);
- if (mcore->setup_done)
- return;
-
- bcma_chipco_serial_init(&bus->drv_cc);
- bcma_core_mips_flash_detect(mcore);
mcore->setup_done = true;
}
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index 9baf886e82df..e6b5c89469dc 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
chipid_top != 0x5300)
return false;
- if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
- bcma_info(bus, "This PCI core is disabled and not working\n");
- return false;
- }
-
bcma_core_enable(pc->core, 0);
return !mips_busprobe32(tmp, pc->core->io_addr);
@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
bcma_info(bus, "PCIEcore in host mode found\n");
+ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
+ bcma_info(bus, "This PCIE core is disabled and not working\n");
+ return;
+ }
+
pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
if (!pc_host) {
bcma_err(bus, "can not allocate memory");
@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
BCMA_SOC_PCI_MEM_SZ - 1;
+ pc_host->io_resource.start = 0x100;
+ pc_host->io_resource.end = 0x47F;
pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
tmp | BCMA_SOC_PCI_MEM);
@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
BCMA_SOC_PCI_MEM_SZ - 1;
+ pc_host->io_resource.start = 0x480;
+ pc_host->io_resource.end = 0x7FF;
pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
@@ -534,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
{
struct resource *res;
- int pos;
+ int pos, err;
if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
/* This is not a device on the PCI-core bridge. */
@@ -547,8 +551,12 @@ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
for (pos = 0; pos < 6; pos++) {
res = &dev->resource[pos];
- if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
- pci_assign_resource(dev, pos);
+ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) {
+ err = pci_assign_resource(dev, pos);
+ if (err)
+ pr_err("PCI: Problem fixing up the addresses on %s\n",
+ pci_name(dev));
+ }
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index b6b4b5ebd4c2..98fdc3e014e7 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int bcma_host_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
bcma_host_pci_resume);
#define BCMA_PM_OPS (&bcma_pm_ops)
-#else /* CONFIG_PM */
+#else /* CONFIG_PM_SLEEP */
#define BCMA_PM_OPS NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index d865470bc951..debd4f142f93 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
}
EXPORT_SYMBOL_GPL(bcma_find_core);
+static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+ u8 unit)
+{
+ struct bcma_device *core;
+
+ list_for_each_entry(core, &bus->cores, list) {
+ if (core->id.id == coreid && core->core_unit == unit)
+ return core;
+ }
+ return NULL;
+}
+
static void bcma_release_core_dev(struct device *dev)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
@@ -153,6 +165,12 @@ static int bcma_register_cores(struct bcma_bus *bus)
}
#endif
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ err = bcma_chipco_watchdog_register(&bus->drv_cc);
+ if (err)
+ bcma_err(bus, "Error registering watchdog driver\n");
+ }
+
return 0;
}
@@ -165,6 +183,8 @@ static void bcma_unregister_cores(struct bcma_bus *bus)
if (core->dev_registered)
device_unregister(&core->dev);
}
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+ platform_device_unregister(bus->drv_cc.watchdog);
}
int __devinit bcma_bus_register(struct bcma_bus *bus)
@@ -183,6 +203,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
return -1;
}
+ /* Early init CC core */
+ core = bcma_find_core(bus, bcma_cc_core_id(bus));
+ if (core) {
+ bus->drv_cc.core = core;
+ bcma_core_chipcommon_early_init(&bus->drv_cc);
+ }
+
+ /* Try to get SPROM */
+ err = bcma_sprom_get(bus);
+ if (err == -ENOENT) {
+ bcma_err(bus, "No SPROM available\n");
+ } else if (err)
+ bcma_err(bus, "Failed to get SPROM: %d\n", err);
+
/* Init CC core */
core = bcma_find_core(bus, bcma_cc_core_id(bus));
if (core) {
@@ -198,10 +232,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
}
/* Init PCIE core */
- core = bcma_find_core(bus, BCMA_CORE_PCIE);
+ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
+ if (core) {
+ bus->drv_pci[0].core = core;
+ bcma_core_pci_init(&bus->drv_pci[0]);
+ }
+
+ /* Init PCIE core */
+ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
if (core) {
- bus->drv_pci.core = core;
- bcma_core_pci_init(&bus->drv_pci);
+ bus->drv_pci[1].core = core;
+ bcma_core_pci_init(&bus->drv_pci[1]);
}
/* Init GBIT MAC COMMON core */
@@ -211,13 +252,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
}
- /* Try to get SPROM */
- err = bcma_sprom_get(bus);
- if (err == -ENOENT) {
- bcma_err(bus, "No SPROM available\n");
- } else if (err)
- bcma_err(bus, "Failed to get SPROM: %d\n", err);
-
/* Register found cores */
bcma_register_cores(bus);
@@ -275,18 +309,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
return -1;
}
- /* Init CC core */
+ /* Early init CC core */
core = bcma_find_core(bus, bcma_cc_core_id(bus));
if (core) {
bus->drv_cc.core = core;
- bcma_core_chipcommon_init(&bus->drv_cc);
+ bcma_core_chipcommon_early_init(&bus->drv_cc);
}
- /* Init MIPS core */
+ /* Early init MIPS core */
core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
if (core) {
bus->drv_mips.core = core;
- bcma_core_mips_init(&bus->drv_mips);
+ bcma_core_mips_early_init(&bus->drv_mips);
}
bcma_info(bus, "Early bus registered\n");
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 0d546b64be34..4adf9ef9a113 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
err = bcma_sprom_valid(sprom);
- if (err)
+ if (err) {
+ bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
+ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
goto out;
+ }
bcma_sprom_extract_r8(bus, sprom);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 3f4bfc814dc7..9959d4cb23dc 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -492,7 +492,7 @@ done:
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
{
u16 buf_len = 0;
- int ret, buf_block_len, blksz;
+ int ret, num_blocks, blksz;
struct sk_buff *skb = NULL;
u32 type;
u8 *payload = NULL;
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
}
blksz = SDIO_BLOCK_SIZE;
- buf_block_len = (buf_len + blksz - 1) / blksz;
+ num_blocks = DIV_ROUND_UP(buf_len, blksz);
if (buf_len <= SDIO_HEADER_LEN
- || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+ || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
BT_ERR("invalid packet length: %d", buf_len);
ret = -EINVAL;
goto exit;
}
/* Allocate buffer */
- skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
- GFP_ATOMIC);
+ skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
goto exit;
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
payload = skb->data;
ret = sdio_readsb(card->func, payload, card->ioport,
- buf_block_len * blksz);
+ num_blocks * blksz);
if (ret < 0) {
BT_ERR("readsb failed: %d", ret);
ret = -EIO;
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
*/
buf_len = payload[0];
- buf_len |= (u16) payload[1] << 8;
+ buf_len |= payload[1] << 8;
+ buf_len |= payload[2] << 16;
+
+ if (buf_len > blksz * num_blocks) {
+ BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
+ buf_len, blksz * num_blocks);
+ ret = -EIO;
+ goto exit;
+ }
+
type = payload[3];
switch (type) {
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
default:
BT_ERR("Unknown packet type:%d", type);
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
- blksz * buf_block_len);
+ BT_ERR("hex: %*ph", blksz * num_blocks, payload);
kfree_skb(skb);
skb = NULL;
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
if (ret < 0) {
i++;
BT_ERR("i=%d writesb failed: %d", i, ret);
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- payload, nb);
+ BT_ERR("hex: %*ph", nb, payload);
ret = -EIO;
if (i > MAX_WRITE_IOMEM_RETRY)
goto exit;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ee82f2fb65f0..a1d4ede5b892 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index c58ea9b80b1a..c5a0262251bc 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -216,7 +216,7 @@ config HW_RANDOM_MXC_RNGA
config HW_RANDOM_NOMADIK
tristate "ST-Ericsson Nomadik Random Number Generator support"
- depends on HW_RANDOM && PLAT_NOMADIK
+ depends on HW_RANDOM && ARCH_NOMADIK
---help---
This driver provides kernel-side support for the Random Number
Generator hardware found on ST-Ericsson SoCs (8815 and 8500).
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a0c84bb30856..053201b062a4 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3789,7 +3789,7 @@ static int handle_one_recv_msg(ipmi_smi_t intf,
} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
&& (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) {
- /* It's an asyncronous event. */
+ /* It's an asynchronous event. */
requeue = handle_read_event_rsp(intf, msg);
} else {
/* It's a response from the local BMC. */
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 20ab5b3a8915..cfdfecd5bc76 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -155,7 +155,7 @@ enum si_stat_indexes {
/* Number of watchdog pretimeouts. */
SI_STAT_watchdog_pretimeouts,
- /* Number of asyncronous messages received. */
+ /* Number of asynchronous messages received. */
SI_STAT_incoming_messages,
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index d0d824ebf2c1..1cd49241e60e 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -251,12 +251,8 @@ static ssize_t pp_write (struct file * file, const char __user * buf,
break;
}
- if (signal_pending (current)) {
- if (!bytes_written) {
- bytes_written = -EINTR;
- }
+ if (signal_pending (current))
break;
- }
cond_resched();
}
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a96bda3d3b84..4e1ccb1e6614 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o
+obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
new file mode 100644
index 000000000000..37a30514fd66
--- /dev/null
+++ b/drivers/clk/clk-zynq.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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/>.
+ */
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+
+static void __iomem *slcr_base;
+
+struct zynq_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pll_ctrl;
+ void __iomem *pll_cfg;
+};
+
+#define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
+
+#define CTRL_PLL_FDIV(x) ((x) >> 12)
+
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
+ return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
+}
+
+static const struct clk_ops zynq_pll_clk_ops = {
+ .recalc_rate = zynq_pll_recalc_rate,
+};
+
+static void __init zynq_pll_clk_setup(struct device_node *np)
+{
+ struct clk_init_data init;
+ struct zynq_pll_clk *pll;
+ const char *parent_name;
+ struct clk *clk;
+ u32 regs[2];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
+ if (WARN_ON(ret))
+ return;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (WARN_ON(!pll))
+ return;
+
+ pll->pll_ctrl = slcr_base + regs[0];
+ pll->pll_cfg = slcr_base + regs[1];
+
+ of_property_read_string(np, "clock-output-names", &init.name);
+
+ init.ops = &zynq_pll_clk_ops;
+ parent_name = of_clk_get_parent_name(np, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(ret))
+ return;
+}
+
+struct zynq_periph_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *gates[2];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
+
+static const u8 periph_clk_parent_map[] = {
+ 0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
+}
+
+static u8 zynq_periph_get_parent(struct clk_hw *hw)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+ .recalc_rate = zynq_periph_recalc_rate,
+ .get_parent = zynq_periph_get_parent,
+};
+
+static void __init zynq_periph_clk_setup(struct device_node *np)
+{
+ struct zynq_periph_clk *periph;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ int clk_num = 0, err;
+ const char *name;
+ struct clk *clk;
+ u32 reg;
+ int i;
+
+ err = of_property_read_u32(np, "reg", &reg);
+ if (WARN_ON(err))
+ return;
+
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ if (WARN_ON(!periph))
+ return;
+
+ periph->clk_ctrl = slcr_base + reg;
+ spin_lock_init(&periph->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_periph_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ periph->hw.init = &init;
+
+ clk = clk_register(NULL, &periph->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ err = of_property_read_string_index(np, "clock-output-names", 0,
+ &name);
+ if (WARN_ON(err))
+ return;
+
+ periph->gates[0] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 0, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[0])))
+ return;
+ clk_num++;
+
+ /* some periph clks have 2 downstream gates */
+ err = of_property_read_string_index(np, "clock-output-names", 1,
+ &name);
+ if (err != -ENODATA) {
+ periph->gates[1] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 1, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[1])))
+ return;
+ clk_num++;
+ }
+
+ periph->onecell_data.clks = periph->gates;
+ periph->onecell_data.clk_num = clk_num;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &periph->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *subclks[4];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+ 1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
+#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
+}
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+ .get_parent = zynq_cpu_clk_get_parent,
+ .recalc_rate = zynq_cpu_clk_recalc_rate,
+};
+
+struct zynq_cpu_subclk {
+ struct clk_hw hw;
+ void __iomem *clk_621;
+ enum {
+ CPU_SUBCLK_6X4X,
+ CPU_SUBCLK_3X2X,
+ CPU_SUBCLK_2X,
+ CPU_SUBCLK_1X,
+ } which;
+};
+
+#define CLK_621_TRUE(x) ((x) & 1)
+
+#define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long uninitialized_var(rate);
+ struct zynq_cpu_subclk *subclk;
+ bool is_621;
+
+ subclk = to_zynq_cpu_subclk(hw)
+ is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
+
+ switch (subclk->which) {
+ case CPU_SUBCLK_6X4X:
+ rate = parent_rate;
+ break;
+ case CPU_SUBCLK_3X2X:
+ rate = parent_rate / 2;
+ break;
+ case CPU_SUBCLK_2X:
+ rate = parent_rate / (is_621 ? 3 : 2);
+ break;
+ case CPU_SUBCLK_1X:
+ rate = parent_rate / (is_621 ? 6 : 4);
+ break;
+ };
+
+ return rate;
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+ .recalc_rate = zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
+ void __iomem *clk_621)
+{
+ struct zynq_cpu_subclk *subclk;
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+
+ err = of_property_read_string_index(np, "clock-output-names",
+ which, &init.name);
+ if (WARN_ON(err))
+ goto err_read_output_name;
+
+ subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
+ if (!subclk)
+ goto err_subclk_alloc;
+
+ subclk->clk_621 = clk_621;
+ subclk->which = which;
+
+ init.ops = &zynq_cpu_subclk_ops;
+ init.parent_names = &np->name;
+ init.num_parents = 1;
+
+ subclk->hw.init = &init;
+
+ clk = clk_register(NULL, &subclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_clk_register;
+
+ return clk;
+
+err_clk_register:
+ kfree(subclk);
+err_subclk_alloc:
+err_read_output_name:
+ return ERR_PTR(-EINVAL);
+}
+
+static void __init zynq_cpu_clk_setup(struct device_node *np)
+{
+ struct zynq_cpu_clk *cpuclk;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ void __iomem *clk_621;
+ struct clk *clk;
+ u32 reg[2];
+ int err;
+ int i;
+
+ err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+ if (WARN_ON(err))
+ return;
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ if (WARN_ON(!cpuclk))
+ return;
+
+ cpuclk->clk_ctrl = slcr_base + reg[0];
+ clk_621 = slcr_base + reg[1];
+ spin_lock_init(&cpuclk->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_cpu_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ cpuclk->hw.init = &init;
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ for (i = 0; i < 4; i++) {
+ cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
+ if (WARN_ON(IS_ERR(cpuclk->subclks[i])))
+ return;
+ }
+
+ cpuclk->onecell_data.clks = cpuclk->subclks;
+ cpuclk->onecell_data.clk_num = i;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &cpuclk->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+static const __initconst struct of_device_id zynq_clk_match[] = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
+ { .compatible = "xlnx,zynq-periph-clock",
+ .data = zynq_periph_clk_setup, },
+ { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
+ {}
+};
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr)
+{
+ slcr_base = slcr;
+ of_clk_init(zynq_clk_match);
+}
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index 7d0e0258f204..6b889a0e90b3 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -12,7 +12,7 @@
#include <linux/clk-provider.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/platform_data/clk-ux500.h>
-
+#include <mach/db8500-regs.h>
#include "clk.h"
void u8500_clk_init(void)
@@ -160,12 +160,6 @@ void u8500_clk_init(void)
clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
clk_register_clkdev(clk, NULL, "uicc");
- /*
- * FIXME: The MTU clocks might need some kind of "parent muxed join"
- * and these have no K-clocks. For now, we ignore the missing
- * connection to the corresponding P-clocks, p6_mtu0_clk and
- * p6_mtu1_clk. Instead timclk is used which is the valid parent.
- */
clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
clk_register_clkdev(clk, NULL, "mtu0");
clk_register_clkdev(clk, NULL, "mtu1");
@@ -405,8 +399,11 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", U8500_CLKRST6_BASE,
BIT(6), 0);
+ clk_register_clkdev(clk, "apb_pclk", "mtu0");
+
clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", U8500_CLKRST6_BASE,
BIT(7), 0);
+ clk_register_clkdev(clk, "apb_pclk", "mtu1");
/* PRCC K-clocks
*
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a0985732f1e2..7fdcbd3f4da5 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -25,6 +25,21 @@ config ARMADA_370_XP_TIMER
config SUNXI_TIMER
bool
+config CLKSRC_NOMADIK_MTU
+ bool
+ depends on (ARCH_NOMADIK || ARCH_U8500)
+ select CLKSRC_MMIO
+ help
+ Support for Multi Timer Unit. MTU provides access
+ to multiple interrupt generating programmable
+ 32-bit free running decrementing counters.
+
+config CLKSRC_NOMADIK_MTU_SCHED_CLOCK
+ bool
+ depends on CLKSRC_NOMADIK_MTU
+ help
+ Use the Multi Timer Unit as the sched_clock.
+
config CLKSRC_DBX500_PRCMU
bool "Clocksource PRCMU Timer"
depends on UX500_SOC_DB8500
@@ -34,7 +49,7 @@ config CLKSRC_DBX500_PRCMU
config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
bool "Clocksource PRCMU Timer sched_clock"
- depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+ depends on (CLKSRC_DBX500_PRCMU && !CLKSRC_NOMADIK_MTU_SCHED_CLOCK)
default y
help
Use the always on PRCMU Timer as sched_clock
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 36f06de4c5ab..f93453d01673 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
+obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
diff --git a/arch/arm/plat-nomadik/timer.c b/drivers/clocksource/nomadik-mtu.c
index 9222e5522a43..8914c3c1c88b 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -1,6 +1,4 @@
/*
- * linux/arch/arm/plat-nomadik/timer.c
- *
* Copyright (C) 2008 STMicroelectronics
* Copyright (C) 2010 Alessandro Rubini
* Copyright (C) 2010 Linus Walleij for ST-Ericsson
@@ -14,9 +12,11 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/clk.h>
#include <linux/jiffies.h>
#include <linux/err.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
#include <asm/mach/time.h>
#include <asm/sched_clock.h>
@@ -174,12 +174,18 @@ void nmdk_clksrc_reset(void)
mtu_base + MTU_CR(0));
}
-void __init nmdk_timer_init(void __iomem *base)
+void __init nmdk_timer_init(void __iomem *base, int irq)
{
unsigned long rate;
- struct clk *clk0;
+ struct clk *clk0, *pclk0;
mtu_base = base;
+
+ pclk0 = clk_get_sys("mtu0", "apb_pclk");
+ BUG_ON(IS_ERR(pclk0));
+ BUG_ON(clk_prepare(pclk0) < 0);
+ BUG_ON(clk_enable(pclk0) < 0);
+
clk0 = clk_get_sys("mtu0", NULL);
BUG_ON(IS_ERR(clk0));
BUG_ON(clk_prepare(clk0) < 0);
@@ -201,7 +207,8 @@ void __init nmdk_timer_init(void __iomem *base)
clk_prescale = MTU_CRn_PRESCALE_1;
}
- nmdk_cycle = (rate + HZ/2) / HZ;
+ /* Cycles for periodic mode */
+ nmdk_cycle = DIV_ROUND_CLOSEST(rate, HZ);
/* Timer 0 is the free running clocksource */
@@ -217,7 +224,7 @@ void __init nmdk_timer_init(void __iomem *base)
#endif
/* Timer 1 is used for events, register irq and clockevents */
- setup_irq(IRQ_MTU0, &nmdk_timer_irq);
+ setup_irq(irq, &nmdk_timer_irq);
nmdk_clkevt.cpumask = cpumask_of(0);
clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);
}
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 649a146e1382..e66e8ee5a9af 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -29,7 +29,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
/* OMAP TRM gives bitfields as start:end, where start is the higher bit
number. For example 7:0 */
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index d76fe06b9417..1d75e6f95a58 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -37,7 +37,7 @@
#include <crypto/hash.h>
#include <crypto/internal/hash.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/irqs.h>
#define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index bc615cc56266..8bc5fef07e7a 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/semaphore.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
@@ -30,8 +31,6 @@
#include <crypto/des.h>
#include <crypto/scatterwalk.h>
-#include <plat/ste_dma40.h>
-
#include <linux/platform_data/crypto-ux500.h>
#include <mach/hardware.h>
diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c
index abd9038e06b1..d6668071bd0d 100644
--- a/drivers/dma/ioat/dca.c
+++ b/drivers/dma/ioat/dca.c
@@ -604,6 +604,23 @@ static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
return slots;
}
+static inline int dca3_tag_map_invalid(u8 *tag_map)
+{
+ /*
+ * If the tag map is not programmed by the BIOS the default is:
+ * 0x80 0x80 0x80 0x80 0x80 0x00 0x00 0x00
+ *
+ * This an invalid map and will result in only 2 possible tags
+ * 0x1F and 0x00. 0x00 is an invalid DCA tag so we know that
+ * this entire definition is invalid.
+ */
+ return ((tag_map[0] == DCA_TAG_MAP_VALID) &&
+ (tag_map[1] == DCA_TAG_MAP_VALID) &&
+ (tag_map[2] == DCA_TAG_MAP_VALID) &&
+ (tag_map[3] == DCA_TAG_MAP_VALID) &&
+ (tag_map[4] == DCA_TAG_MAP_VALID));
+}
+
struct dca_provider * __devinit
ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
{
@@ -674,6 +691,12 @@ ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
}
+ if (dca3_tag_map_invalid(ioatdca->tag_map)) {
+ dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n");
+ free_dca_provider(dca);
+ return NULL;
+ }
+
err = register_dca_provider(dca, &pdev->dev);
if (err) {
free_dca_provider(dca);
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 7d35c237fbf1..5a31264f2bd1 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -19,8 +19,6 @@
#include "virt-dma.h"
-#include <plat-omap/dma-omap.h>
-
struct omap_dmadev {
struct dma_device ddev;
spinlock_t lock;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ae55091c2272..23c5573e62dd 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -19,8 +19,7 @@
#include <linux/err.h>
#include <linux/amba/bus.h>
#include <linux/regulator/consumer.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include "dmaengine.h"
#include "ste_dma40_ll.h"
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index cad9e1daedff..851ad56e8409 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -6,7 +6,7 @@
*/
#include <linux/kernel.h>
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include "ste_dma40_ll.h"
diff --git a/drivers/eisa/eisa.ids b/drivers/eisa/eisa.ids
index 6cbb7a514436..2d864b48a48f 100644
--- a/drivers/eisa/eisa.ids
+++ b/drivers/eisa/eisa.ids
@@ -985,8 +985,8 @@ ISABD00 "Racal-Interlan NP600A Ethernet 16bit"
ISABD02 "Racal-Interlan NI5210/8 Ethernet"
ISABD03 "Racal-Interlan NI5210/16 Ethernet"
ISABE00 "Qua Tech PXB-1608 Parallel Expansion Board"
-ISABE01 "Qua Tech ES-100 8 Channel Asyncronous"
-ISABE02 "Qua Tech QS-100M 4 Channel Asyncronous"
+ISABE01 "Qua Tech ES-100 8 Channel Asynchronous"
+ISABE02 "Qua Tech QS-100M 4 Channel Asynchronous"
ISABE03 "Qua Tech MXI-100 IEEE 488 GPIB"
ISABE04 "Qua Tech DS-201 Dual Channel RS-422"
ISABE05 "Qua Tech PXB-721 Parallel Expansion"
diff --git a/drivers/firewire/init_ohci1394_dma.c b/drivers/firewire/init_ohci1394_dma.c
index a9a347adb353..2cc89ce745c9 100644
--- a/drivers/firewire/init_ohci1394_dma.c
+++ b/drivers/firewire/init_ohci1394_dma.c
@@ -149,10 +149,10 @@ static inline void __init init_ohci1394_initialize(struct ohci *ohci)
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
- /* Accept asyncronous transfer requests from all nodes for now */
+ /* Accept asynchronous transfer requests from all nodes for now */
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
- /* Specify asyncronous transfer retries */
+ /* Specify asynchronous transfer retries */
reg_write(ohci, OHCI1394_ATRetries,
OHCI1394_MAX_AT_REQ_RETRIES |
(OHCI1394_MAX_AT_RESP_RETRIES<<4) |
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 08c674957af8..e7a711f53a6f 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -828,7 +828,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
{
struct fwnet_device *dev;
struct fw_iso_packet packet;
- struct fw_card *card;
__be16 *hdr_ptr;
__be32 *buf_ptr;
int retval;
@@ -840,7 +839,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
unsigned long flags;
dev = data;
- card = dev->card;
hdr_ptr = header;
length = be16_to_cpup(hdr_ptr);
@@ -861,8 +859,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
buf_ptr += 2;
length -= IEEE1394_GASP_HDR_SIZE;
- fwnet_incoming_packet(dev, buf_ptr, length,
- source_node_id, -1, true);
+ fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
+ context->card->generation, true);
}
packet.payload_length = dev->rcv_buffer_size;
@@ -958,7 +956,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
break;
}
- skb_pull(skb, ptask->max_payload);
+ if (ptask->dest_node == IEEE1394_ALL_NODES) {
+ skb_pull(skb,
+ ptask->max_payload + IEEE1394_GASP_HDR_SIZE);
+ } else {
+ skb_pull(skb, ptask->max_payload);
+ }
if (ptask->outstanding_pkts > 1) {
fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
dg_size, fg_off, datagram_label);
@@ -1062,7 +1065,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
smp_rmb();
node_id = dev->card->node_id;
- p = skb_push(ptask->skb, 8);
+ p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
| RFC2734_SW_VERSION, &p[4]);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index f25610bb3148..6ce6e07c38c1 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1281,7 +1281,7 @@ static int at_context_queue_packet(struct context *ctx,
d[0].res_count = cpu_to_le16(packet->timestamp);
/*
- * The DMA format for asyncronous link packets is different
+ * The DMA format for asynchronous link packets is different
* from the IEEE1394 layout, so shift the fields around
* accordingly.
*/
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index bb1b392f5cda..1162d6b3bf85 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1546,8 +1546,6 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
struct sbp2_logical_unit *lu = sdev->hostdata;
sdev->use_10_for_rw = 1;
- sdev->no_report_opcodes = 1;
- sdev->no_write_same = 1;
if (sbp2_param_exclusive_login)
sdev->manage_start_stop = 1;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 14a6c2913e49..bf892bd68c17 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -171,7 +171,7 @@ config GPIO_MSM_V2
config GPIO_MVEBU
def_bool y
- depends on ARCH_MVEBU
+ depends on PLAT_ORION
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
@@ -504,7 +504,7 @@ config GPIO_ADNP
help
This option enables support for N GPIOs found on Avionic Design
I2C GPIO expanders. The register space will be extended by powers
- of two, so the controller will need to accomodate for that. For
+ of two, so the controller will need to accommodate for that. For
example: if a controller provides 48 pins, 6 registers will be
enough to represent all pins, but the driver will assume a
register layout for 64 pins (8 registers).
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a006f0db15af..01f7fe955590 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -42,12 +42,6 @@
#include <plat/gpio-fns.h>
#include <plat/pm.h>
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull)
{
@@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
unsigned long con;
con = __raw_readl(base + GPIOCON_OFF);
- con &= ~(0xf << con_4bit_shift(offset));
+ if (ourchip->bitmap_gpio_int & BIT(offset))
+ con |= 0xf << con_4bit_shift(offset);
+ else
+ con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, base + GPIOCON_OFF);
- gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+ pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
return 0;
}
@@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
__raw_writel(con, base + GPIOCON_OFF);
__raw_writel(dat, base + GPIODAT_OFF);
- gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+ pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
return 0;
}
@@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, regcon);
- gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+ pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
return 0;
}
@@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
__raw_writel(con, regcon);
__raw_writel(dat, base + GPIODAT_OFF);
- gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+ pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
return 0;
}
@@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
#ifdef CONFIG_PM
if (chip->pm != NULL) {
if (!chip->pm->save || !chip->pm->resume)
- printk(KERN_ERR "gpio: %s has missing PM functions\n",
+ pr_err("gpio: %s has missing PM functions\n",
gc->label);
} else
- printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+ pr_err("gpio: %s has no PM function\n", gc->label);
#endif
/* gpiochip_add() prints own failure message on error. */
@@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
if ((base != NULL) && (chip->base == NULL))
chip->base = base + ((i) * 0x20);
+ chip->bitmap_gpio_int = 0;
+
samsung_gpiolib_add(chip);
}
}
@@ -2797,27 +2796,6 @@ static __init void exynos4_gpiolib_init(void)
int group = 0;
void __iomem *gpx_base;
-#ifdef CONFIG_PINCTRL_SAMSUNG
- /*
- * This gpio driver includes support for device tree support and
- * there are platforms using it. In order to maintain
- * compatibility with those platforms, and to allow non-dt
- * Exynos4210 platforms to use this gpiolib support, a check
- * is added to find out if there is a active pin-controller
- * driver support available. If it is available, this gpiolib
- * support is ignored and the gpiolib support available in
- * pin-controller driver is used. This is a temporary check and
- * will go away when all of the Exynos4210 platforms have
- * switched to using device tree and the pin-ctrl driver.
- */
- struct device_node *pctrl_np;
- const char *pctrl_compat = "samsung,pinctrl-exynos4210";
- pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
- if (pctrl_np)
- if (of_device_is_available(pctrl_np))
- return;
-#endif
-
/* gpio part1 */
gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
if (gpio_base1 == NULL) {
@@ -3032,6 +3010,28 @@ static __init int samsung_gpiolib_init(void)
int i, nr_chips;
int group = 0;
+#ifdef CONFIG_PINCTRL_SAMSUNG
+ /*
+ * This gpio driver includes support for device tree support and there
+ * are platforms using it. In order to maintain compatibility with those
+ * platforms, and to allow non-dt Exynos4210 platforms to use this
+ * gpiolib support, a check is added to find out if there is a active
+ * pin-controller driver support available. If it is available, this
+ * gpiolib support is ignored and the gpiolib support available in
+ * pin-controller driver is used. This is a temporary check and will go
+ * away when all of the Exynos4210 platforms have switched to using
+ * device tree and the pin-ctrl driver.
+ */
+ struct device_node *pctrl_np;
+ static const struct of_device_id exynos_pinctrl_ids[] = {
+ { .compatible = "samsung,pinctrl-exynos4210", },
+ { .compatible = "samsung,pinctrl-exynos4x12", },
+ };
+ for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
+ if (pctrl_np && of_device_is_available(pctrl_np))
+ return -ENODEV;
+#endif
+
samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
if (soc_is_s3c24xx()) {
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 219942c660d7..5d1d21a6dcdd 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1650,7 +1650,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
ring->wptr = 0;
WREG32(CP_RB_WPTR, ring->wptr);
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
WREG32(CP_RB_RPTR_ADDR,
((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 81e6a568c29d..cda01f808f12 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1059,7 +1059,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
WREG32(CP_DEBUG, (1 << 27));
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
WREG32(SCRATCH_UMSK, 0xff);
@@ -1076,7 +1076,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
#endif
WREG32(cp_rb_cntl[i], rb_cntl);
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 47634f27f2e5..ebd69562ef6c 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -459,7 +459,7 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *r
*
* @ring: radeon_ring structure holding ring information
*
- * Reset the driver's copy of the wtpr (all asics).
+ * Reset the driver's copy of the wptr (all asics).
*/
void radeon_ring_undo(struct radeon_ring *ring)
{
@@ -503,7 +503,7 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
}
/**
- * radeon_ring_force_activity - update lockup variables
+ * radeon_ring_lockup_update - update lockup variables
*
* @ring: radeon_ring structure holding ring information
*
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 4422d630b33b..010156dd949f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2007,7 +2007,7 @@ static int si_cp_resume(struct radeon_device *rdev)
ring->wptr = 0;
WREG32(CP_RB0_WPTR, ring->wptr);
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
@@ -2040,7 +2040,7 @@ static int si_cp_resume(struct radeon_device *rdev)
ring->wptr = 0;
WREG32(CP_RB1_WPTR, ring->wptr);
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
@@ -2066,7 +2066,7 @@ static int si_cp_resume(struct radeon_device *rdev)
ring->wptr = 0;
WREG32(CP_RB2_WPTR, ring->wptr);
- /* set the wb address wether it's enabled or not */
+ /* set the wb address whether it's enabled or not */
WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1630150ad2b1..e7d6a13ec6a6 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -265,6 +265,15 @@ config HID_GYRATION
---help---
Support for Gyration remote control.
+config HID_ICADE
+ tristate "ION iCade arcade controller"
+ depends on BT_HIDP
+ ---help---
+ Support for the ION iCade arcade controller to work as a joystick.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hid-icade.
+
config HID_TWINHAN
tristate "Twinhan IR remote control"
depends on USB_HID
@@ -728,4 +737,6 @@ endif # HID
source "drivers/hid/usbhid/Kconfig"
+source "drivers/hid/i2c-hid/Kconfig"
+
endmenu
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cef68ca859d3..b62215716b2f 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
+obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
@@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
- hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
- hid-roccat-savu.o
+ hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
+ hid-roccat-pyra.o hid-roccat-savu.o
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
@@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
obj-$(CONFIG_USB_KBD) += usbhid/
+obj-$(CONFIG_I2C_HID) += i2c-hid/
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index fd7722aecf77..d0f7662aacca 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_RDESC_JIS },
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f4109fd657ff..eb2ee11b6412 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
{
struct hid_field *field;
+ int i;
if (report->maxfield == HID_MAX_FIELDS) {
hid_err(report->device, "too many fields in report\n");
@@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
field->value = (s32 *)(field->usage + usages);
field->report = report;
+ for (i = 0; i < usages; i++)
+ field->usage[i].usage_index = i;
+
return field;
}
@@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item)
static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
{
+ __u32 raw_value;
switch (item->tag) {
case HID_GLOBAL_ITEM_TAG_PUSH:
@@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
return 0;
case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
- parser->global.unit_exponent = item_sdata(item);
+ /* Units exponent negative numbers are given through a
+ * two's complement.
+ * See "6.2.2.7 Global Items" for more information. */
+ raw_value = item_udata(item);
+ if (!(raw_value & 0xfffffff0))
+ parser->global.unit_exponent = hid_snto32(raw_value, 4);
+ else
+ parser->global.unit_exponent = raw_value;
return 0;
case HID_GLOBAL_ITEM_TAG_UNIT:
@@ -713,7 +725,12 @@ static int hid_scan_report(struct hid_device *hid)
hid_scan_usage(hid, u);
break;
}
- }
+ } else if (page == HID_UP_SENSOR &&
+ item.type == HID_ITEM_TYPE_MAIN &&
+ item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
+ (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
+ hid->bus == BUS_USB)
+ hid->group = HID_GROUP_SENSOR_HUB;
}
return 0;
@@ -865,6 +882,12 @@ static s32 snto32(__u32 value, unsigned n)
return value & (1 << (n - 1)) ? value | (-1 << n) : value;
}
+s32 hid_snto32(__u32 value, unsigned n)
+{
+ return snto32(value, n);
+}
+EXPORT_SYMBOL_GPL(hid_snto32);
+
/*
* Convert a signed 32-bit integer to a signed n-bit integer.
*/
@@ -1465,6 +1488,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
* there is a proper autodetection and autoloading in place (based on presence
* of HID_DG_CONTACTID), so those devices don't need to be added to this list,
* as we are doing the right thing in hid_scan_usage().
+ *
+ * Autodetection for (USB) HID sensor hubs exists too. If a collection of type
+ * physical is found inside a usage page of type sensor, hid-sensor-hub will be
+ * used as a driver. See hid_scan_report().
*/
static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
@@ -1538,6 +1565,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
@@ -1571,10 +1599,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1658,6 +1683,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
@@ -1672,7 +1698,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -2150,8 +2175,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ }
};
-static bool hid_ignore(struct hid_device *hdev)
+bool hid_ignore(struct hid_device *hdev)
{
+ if (hdev->quirks & HID_QUIRK_NO_IGNORE)
+ return false;
+ if (hdev->quirks & HID_QUIRK_IGNORE)
+ return true;
+
switch (hdev->vendor) {
case USB_VENDOR_ID_CODEMERCS:
/* ignore all Code Mercenaries IOWarrior devices */
@@ -2188,7 +2218,16 @@ static bool hid_ignore(struct hid_device *hdev)
if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
hdev->type == HID_TYPE_USBNONE)
return true;
- break;
+ break;
+ case USB_VENDOR_ID_DWAV:
+ /* These are handled by usbtouchscreen. hdev->type is probably
+ * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match
+ * usbtouchscreen. */
+ if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER ||
+ hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) &&
+ hdev->type != HID_TYPE_USBMOUSE)
+ return true;
+ break;
}
if (hdev->type == HID_TYPE_USBMOUSE &&
@@ -2197,6 +2236,7 @@ static bool hid_ignore(struct hid_device *hdev)
return !!hid_match_id(hdev, hid_ignore_list);
}
+EXPORT_SYMBOL_GPL(hid_ignore);
int hid_add_device(struct hid_device *hdev)
{
@@ -2208,8 +2248,7 @@ int hid_add_device(struct hid_device *hdev)
/* we need to kill them here, otherwise they will stay allocated to
* wait for coming driver */
- if (!(hdev->quirks & HID_QUIRK_NO_IGNORE)
- && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
+ if (hid_ignore(hdev))
return -ENODEV;
/*
diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
new file mode 100644
index 000000000000..1d6565e37ba3
--- /dev/null
+++ b/drivers/hid/hid-icade.c
@@ -0,0 +1,259 @@
+/*
+ * ION iCade input driver
+ *
+ * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * ↑ A C Y L
+ * ← →
+ * ↓ B X Z R
+ *
+ *
+ * UP ON,OFF = w,e
+ * RT ON,OFF = d,c
+ * DN ON,OFF = x,z
+ * LT ON,OFF = a,q
+ * A ON,OFF = y,t
+ * B ON,OFF = h,r
+ * C ON,OFF = u,f
+ * X ON,OFF = j,n
+ * Y ON,OFF = i,m
+ * Z ON,OFF = k,p
+ * L ON,OFF = o,g
+ * R ON,OFF = l,v
+ */
+
+/* The translation code uses HID usage instead of input layer
+ * keys. This code generates a lookup table that makes
+ * translation quick.
+ *
+ * #include <linux/input.h>
+ * #include <stdio.h>
+ * #include <assert.h>
+ *
+ * #define unk KEY_UNKNOWN
+ *
+ * < copy of hid_keyboard[] from hid-input.c >
+ *
+ * struct icade_key_translation {
+ * int from;
+ * const char *to;
+ * int press;
+ * };
+ *
+ * static const struct icade_key_translation icade_keys[] = {
+ * { KEY_W, "KEY_UP", 1 },
+ * { KEY_E, "KEY_UP", 0 },
+ * { KEY_D, "KEY_RIGHT", 1 },
+ * { KEY_C, "KEY_RIGHT", 0 },
+ * { KEY_X, "KEY_DOWN", 1 },
+ * { KEY_Z, "KEY_DOWN", 0 },
+ * { KEY_A, "KEY_LEFT", 1 },
+ * { KEY_Q, "KEY_LEFT", 0 },
+ * { KEY_Y, "BTN_A", 1 },
+ * { KEY_T, "BTN_A", 0 },
+ * { KEY_H, "BTN_B", 1 },
+ * { KEY_R, "BTN_B", 0 },
+ * { KEY_U, "BTN_C", 1 },
+ * { KEY_F, "BTN_C", 0 },
+ * { KEY_J, "BTN_X", 1 },
+ * { KEY_N, "BTN_X", 0 },
+ * { KEY_I, "BTN_Y", 1 },
+ * { KEY_M, "BTN_Y", 0 },
+ * { KEY_K, "BTN_Z", 1 },
+ * { KEY_P, "BTN_Z", 0 },
+ * { KEY_O, "BTN_THUMBL", 1 },
+ * { KEY_G, "BTN_THUMBL", 0 },
+ * { KEY_L, "BTN_THUMBR", 1 },
+ * { KEY_V, "BTN_THUMBR", 0 },
+ *
+ * { }
+ * };
+ *
+ * static int
+ * usage_for_key (int key)
+ * {
+ * int i;
+ * for (i = 0; i < 256; i++) {
+ * if (hid_keyboard[i] == key)
+ * return i;
+ * }
+ * assert(0);
+ * }
+ *
+ * int main (int argc, char **argv)
+ * {
+ * const struct icade_key_translation *trans;
+ * int max_usage = 0;
+ *
+ * for (trans = icade_keys; trans->from; trans++) {
+ * int usage = usage_for_key (trans->from);
+ * max_usage = usage > max_usage ? usage : max_usage;
+ * }
+ *
+ * printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
+ * printf ("struct icade_key {\n");
+ * printf ("\tu16 to;\n");
+ * printf ("\tu8 press:1;\n");
+ * printf ("};\n\n");
+ * printf ("static const struct icade_key "
+ * "icade_usage_table[%d] = {\n", max_usage + 1);
+ * for (trans = icade_keys; trans->from; trans++) {
+ * printf ("\t[%d] = { %s, %d },\n",
+ * usage_for_key (trans->from), trans->to, trans->press);
+ * }
+ * printf ("};\n");
+ *
+ * return 0;
+ * }
+ */
+
+#define ICADE_MAX_USAGE 29
+
+struct icade_key {
+ u16 to;
+ u8 press:1;
+};
+
+static const struct icade_key icade_usage_table[30] = {
+ [26] = { KEY_UP, 1 },
+ [8] = { KEY_UP, 0 },
+ [7] = { KEY_RIGHT, 1 },
+ [6] = { KEY_RIGHT, 0 },
+ [27] = { KEY_DOWN, 1 },
+ [29] = { KEY_DOWN, 0 },
+ [4] = { KEY_LEFT, 1 },
+ [20] = { KEY_LEFT, 0 },
+ [28] = { BTN_A, 1 },
+ [23] = { BTN_A, 0 },
+ [11] = { BTN_B, 1 },
+ [21] = { BTN_B, 0 },
+ [24] = { BTN_C, 1 },
+ [9] = { BTN_C, 0 },
+ [13] = { BTN_X, 1 },
+ [17] = { BTN_X, 0 },
+ [12] = { BTN_Y, 1 },
+ [16] = { BTN_Y, 0 },
+ [14] = { BTN_Z, 1 },
+ [19] = { BTN_Z, 0 },
+ [18] = { BTN_THUMBL, 1 },
+ [10] = { BTN_THUMBL, 0 },
+ [15] = { BTN_THUMBR, 1 },
+ [25] = { BTN_THUMBR, 0 },
+};
+
+static const struct icade_key *icade_find_translation(u16 from)
+{
+ if (from < 0 || from > ICADE_MAX_USAGE)
+ return NULL;
+ return &icade_usage_table[from];
+}
+
+static int icade_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ const struct icade_key *trans;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ /* We ignore the fake key up, and act only on key down */
+ if (!value)
+ return 1;
+
+ trans = icade_find_translation(usage->hid & HID_USAGE);
+
+ if (!trans)
+ return 1;
+
+ input_event(field->hidinput->input, usage->type,
+ trans->to, trans->press);
+
+ return 1;
+}
+
+static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ const struct icade_key *trans;
+
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
+ trans = icade_find_translation(usage->hid & HID_USAGE);
+
+ if (!trans)
+ return -1;
+
+ hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
+ set_bit(trans->to, hi->input->keybit);
+
+ return 1;
+ }
+
+ /* ignore others */
+ return -1;
+
+}
+
+static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->type == EV_KEY)
+ set_bit(usage->type, hi->input->evbit);
+
+ return -1;
+}
+
+static const struct hid_device_id icade_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, icade_devices);
+
+static struct hid_driver icade_driver = {
+ .name = "icade",
+ .id_table = icade_devices,
+ .event = icade_event,
+ .input_mapped = icade_input_mapped,
+ .input_mapping = icade_input_mapping,
+};
+
+static int __init icade_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&icade_driver);
+ if (ret)
+ pr_err("can't register icade driver\n");
+
+ return ret;
+}
+
+static void __exit icade_exit(void)
+{
+ hid_unregister_driver(&icade_driver);
+}
+
+module_init(icade_init);
+module_exit(icade_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("ION iCade input driver");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9d7a42857ea1..4dfa605e2d14 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -257,6 +257,7 @@
#define USB_VENDOR_ID_DWAV 0x0eef
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
+#define USB_DEVICE_ID_DWAV_TOUCHCONTROLLER 0x0002
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 0x7207
@@ -423,6 +424,9 @@
#define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
+#define USB_VENDOR_ID_ION 0x15e4
+#define USB_DEVICE_ID_ICADE 0x0132
+
#define USB_VENDOR_ID_HOLTEK 0x1241
#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
@@ -432,11 +436,6 @@
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
-#define USB_VENDOR_ID_INTEL_8086 0x8086
-#define USB_VENDOR_ID_INTEL_8087 0x8087
-#define USB_DEVICE_ID_SENSOR_HUB_1020 0x1020
-#define USB_DEVICE_ID_SENSOR_HUB_09FA 0x09FA
-
#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070
@@ -603,6 +602,7 @@
#define USB_VENDOR_ID_NOVATEK 0x0603
#define USB_DEVICE_ID_NOVATEK_PCT 0x0600
+#define USB_DEVICE_ID_NOVATEK_MOUSE 0x1602
#define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
@@ -677,7 +677,9 @@
#define USB_DEVICE_ID_ROCCAT_ISKU 0x319c
#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
+#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22
#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
+#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
#define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a
@@ -696,6 +698,9 @@
#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002
+#define USB_VENDOR_ID_SIGMATEL 0x066F
+#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780
+
#define USB_VENDOR_ID_SKYCABLE 0x1223
#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
@@ -714,7 +719,6 @@
#define USB_VENDOR_ID_STANTUM_STM 0x0483
#define USB_DEVICE_ID_MTP_STM 0x3261
-#define USB_DEVICE_ID_SENSOR_HUB_7014 0x7014
#define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403
#define USB_DEVICE_ID_MTP_SITRONIX 0x5001
@@ -762,6 +766,9 @@
#define USB_VENDOR_ID_TOUCHPACK 0x1bfd
#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
+#define USB_VENDOR_ID_TPV 0x25aa
+#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN 0x8883
+
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d917c0d53685..21b196c394b1 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev,
return -EINVAL;
}
-
/**
* hidinput_calc_abs_res - calculate an absolute axis resolution
* @field: the HID report field to calculate resolution for
@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
* Only exponent 1 length units are processed. Centimeters and inches are
* converted to millimeters. Degrees are converted to radians.
*/
-static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
{
__s32 unit_exponent = field->unit_exponent;
__s32 logical_extents = field->logical_maximum -
@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
case ABS_X:
case ABS_Y:
case ABS_Z:
- if (field->unit == 0x11) { /* If centimeters */
+ case ABS_MT_POSITION_X:
+ case ABS_MT_POSITION_Y:
+ case ABS_MT_TOOL_X:
+ case ABS_MT_TOOL_Y:
+ case ABS_MT_TOUCH_MAJOR:
+ case ABS_MT_TOUCH_MINOR:
+ if (field->unit & 0xffffff00) /* Not a length */
+ return 0;
+ unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
+ switch (field->unit & 0xf) {
+ case 0x1: /* If centimeters */
/* Convert to millimeters */
unit_exponent += 1;
- } else if (field->unit == 0x13) { /* If inches */
+ break;
+ case 0x3: /* If inches */
/* Convert to millimeters */
prev = physical_extents;
physical_extents *= 254;
if (physical_extents < prev)
return 0;
unit_exponent -= 1;
- } else {
+ break;
+ default:
return 0;
}
break;
@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
}
/* Calculate resolution */
- return logical_extents / physical_extents;
+ return DIV_ROUND_CLOSEST(logical_extents, physical_extents);
}
+EXPORT_SYMBOL_GPL(hidinput_calc_abs_res);
#ifdef CONFIG_HID_BATTERY_STRENGTH
static enum power_supply_property hidinput_battery_props[] = {
@@ -299,6 +311,9 @@ static enum power_supply_property hidinput_battery_props[] = {
static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+ HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (code <= 0xf)
code += BTN_JOYSTICK;
else
- code += BTN_TRIGGER_HAPPY;
+ code += BTN_TRIGGER_HAPPY - 0x10;
+ break;
+ case HID_GD_GAMEPAD:
+ if (code <= 0xf)
+ code += BTN_GAMEPAD;
+ else
+ code += BTN_TRIGGER_HAPPY - 0x10;
break;
- case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break;
default:
switch (field->physical) {
case HID_GD_MOUSE:
@@ -1146,6 +1166,38 @@ static void report_features(struct hid_device *hid)
}
}
+static struct hid_input *hidinput_allocate(struct hid_device *hid)
+{
+ struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
+ struct input_dev *input_dev = input_allocate_device();
+ if (!hidinput || !input_dev) {
+ kfree(hidinput);
+ input_free_device(input_dev);
+ hid_err(hid, "Out of memory during hid input probe\n");
+ return NULL;
+ }
+
+ input_set_drvdata(input_dev, hid);
+ input_dev->event = hid->ll_driver->hidinput_input_event;
+ input_dev->open = hidinput_open;
+ input_dev->close = hidinput_close;
+ input_dev->setkeycode = hidinput_setkeycode;
+ input_dev->getkeycode = hidinput_getkeycode;
+
+ input_dev->name = hid->name;
+ input_dev->phys = hid->phys;
+ input_dev->uniq = hid->uniq;
+ input_dev->id.bustype = hid->bus;
+ input_dev->id.vendor = hid->vendor;
+ input_dev->id.product = hid->product;
+ input_dev->id.version = hid->version;
+ input_dev->dev.parent = hid->dev.parent;
+ hidinput->input = input_dev;
+ list_add_tail(&hidinput->list, &hid->inputs);
+
+ return hidinput;
+}
+
/*
* Register the input device; print a message.
* Configure the input layer interface
@@ -1157,7 +1209,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
struct hid_driver *drv = hid->driver;
struct hid_report *report;
struct hid_input *hidinput = NULL;
- struct input_dev *input_dev;
int i, j, k;
INIT_LIST_HEAD(&hid->inputs);
@@ -1188,33 +1239,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
continue;
if (!hidinput) {
- hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!hidinput || !input_dev) {
- kfree(hidinput);
- input_free_device(input_dev);
- hid_err(hid, "Out of memory during hid input probe\n");
+ hidinput = hidinput_allocate(hid);
+ if (!hidinput)
goto out_unwind;
- }
-
- input_set_drvdata(input_dev, hid);
- input_dev->event =
- hid->ll_driver->hidinput_input_event;
- input_dev->open = hidinput_open;
- input_dev->close = hidinput_close;
- input_dev->setkeycode = hidinput_setkeycode;
- input_dev->getkeycode = hidinput_getkeycode;
-
- input_dev->name = hid->name;
- input_dev->phys = hid->phys;
- input_dev->uniq = hid->uniq;
- input_dev->id.bustype = hid->bus;
- input_dev->id.vendor = hid->vendor;
- input_dev->id.product = hid->product;
- input_dev->id.version = hid->version;
- input_dev->dev.parent = hid->dev.parent;
- hidinput->input = input_dev;
- list_add_tail(&hidinput->list, &hid->inputs);
}
for (i = 0; i < report->maxfield; i++)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 7867d69f0efe..61543c02ea0b 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -52,11 +52,14 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
#define MT_QUIRK_NO_AREA (1 << 9)
+#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
+#define MT_QUIRK_HOVERING (1 << 11)
struct mt_slot {
- __s32 x, y, p, w, h;
+ __s32 x, y, cx, cy, p, w, h;
__s32 contactid; /* the device ContactID assigned to this slot */
bool touch_state; /* is the touch valid? */
+ bool inrange_state; /* is the finger in proximity of the sensor? */
};
struct mt_class {
@@ -121,6 +124,7 @@ struct mt_device {
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
#define MT_DEFAULT_MAXCONTACT 10
+#define MT_MAX_MAXCONTACT 250
#define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
#define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
@@ -282,11 +286,26 @@ static void mt_feature_mapping(struct hid_device *hdev,
case HID_DG_CONTACTMAX:
td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0];
+ if (!td->maxcontacts &&
+ field->logical_maximum <= MT_MAX_MAXCONTACT)
+ td->maxcontacts = field->logical_maximum;
if (td->mtclass.maxcontacts)
/* check if the maxcontacts is given by the class */
td->maxcontacts = td->mtclass.maxcontacts;
break;
+ case 0xff0000c5:
+ if (field->report_count == 256 && field->report_size == 8) {
+ /* Win 8 devices need special quirks */
+ __s32 *quirks = &td->mtclass.quirks;
+ *quirks |= MT_QUIRK_ALWAYS_VALID;
+ *quirks |= MT_QUIRK_IGNORE_DUPLICATES;
+ *quirks |= MT_QUIRK_HOVERING;
+ *quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
+ *quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
+ *quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
+ }
+ break;
}
}
@@ -297,6 +316,7 @@ static void set_abs(struct input_dev *input, unsigned int code,
int fmax = field->logical_maximum;
int fuzz = snratio ? (fmax - fmin) / snratio : 0;
input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+ input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
}
static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
@@ -317,6 +337,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
int code;
+ struct hid_usage *prev_usage = NULL;
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
@@ -339,23 +360,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->physical == HID_DG_STYLUS)
return -1;
+ if (usage->usage_index)
+ prev_usage = &field->usage[usage->usage_index - 1];
+
switch (usage->hid & HID_USAGE_PAGE) {
case HID_UP_GENDESK:
switch (usage->hid) {
case HID_GD_X:
- hid_map_usage(hi, usage, bit, max,
+ if (prev_usage && (prev_usage->hid == usage->hid)) {
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_TOOL_X);
+ set_abs(hi->input, ABS_MT_TOOL_X, field,
+ cls->sn_move);
+ } else {
+ hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_POSITION_X);
- set_abs(hi->input, ABS_MT_POSITION_X, field,
- cls->sn_move);
+ set_abs(hi->input, ABS_MT_POSITION_X, field,
+ cls->sn_move);
+ }
+
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_GD_Y:
- hid_map_usage(hi, usage, bit, max,
+ if (prev_usage && (prev_usage->hid == usage->hid)) {
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_TOOL_Y);
+ set_abs(hi->input, ABS_MT_TOOL_Y, field,
+ cls->sn_move);
+ } else {
+ hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_POSITION_Y);
- set_abs(hi->input, ABS_MT_POSITION_Y, field,
- cls->sn_move);
+ set_abs(hi->input, ABS_MT_POSITION_Y, field,
+ cls->sn_move);
+ }
+
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -365,6 +405,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_DIGITIZER:
switch (usage->hid) {
case HID_DG_INRANGE:
+ if (cls->quirks & MT_QUIRK_HOVERING) {
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_DISTANCE);
+ input_set_abs_params(hi->input,
+ ABS_MT_DISTANCE, 0, 1, 0, 0);
+ }
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -477,18 +523,26 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
*/
static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
{
- if (td->curvalid) {
+ if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
int slotnum = mt_compute_slot(td, input);
struct mt_slot *s = &td->curdata;
+ struct input_mt *mt = input->mt;
if (slotnum < 0 || slotnum >= td->maxcontacts)
return;
+ if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+ struct input_mt_slot *slot = &mt->slots[slotnum];
+ if (input_mt_is_active(slot) &&
+ input_mt_is_used(mt, slot))
+ return;
+ }
+
input_mt_slot(input, slotnum);
input_mt_report_slot_state(input, MT_TOOL_FINGER,
- s->touch_state);
- if (s->touch_state) {
- /* this finger is on the screen */
+ s->touch_state || s->inrange_state);
+ if (s->touch_state || s->inrange_state) {
+ /* this finger is in proximity of the sensor */
int wide = (s->w > s->h);
/* divided by two to match visual scale of touch */
int major = max(s->w, s->h) >> 1;
@@ -496,6 +550,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+ input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
+ input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
+ input_event(input, EV_ABS, ABS_MT_DISTANCE,
+ !s->touch_state);
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
@@ -526,10 +584,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
if (hid->claimed & HID_CLAIMED_INPUT) {
switch (usage->hid) {
case HID_DG_INRANGE:
- if (quirks & MT_QUIRK_ALWAYS_VALID)
- td->curvalid = true;
- else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+ if (quirks & MT_QUIRK_VALID_IS_INRANGE)
td->curvalid = value;
+ if (quirks & MT_QUIRK_HOVERING)
+ td->curdata.inrange_state = value;
break;
case HID_DG_TIPSWITCH:
if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
@@ -547,10 +605,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
td->curdata.p = value;
break;
case HID_GD_X:
- td->curdata.x = value;
+ if (usage->code == ABS_MT_TOOL_X)
+ td->curdata.cx = value;
+ else
+ td->curdata.x = value;
break;
case HID_GD_Y:
- td->curdata.y = value;
+ if (usage->code == ABS_MT_TOOL_Y)
+ td->curdata.cy = value;
+ else
+ td->curdata.y = value;
break;
case HID_DG_WIDTH:
td->curdata.w = value;
@@ -575,12 +639,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
return 0;
}
- if (usage->hid == td->last_slot_field)
- mt_complete_slot(td, field->hidinput->input);
+ if (usage->usage_index + 1 == field->report_count) {
+ /* we only take into account the last report. */
+ if (usage->hid == td->last_slot_field)
+ mt_complete_slot(td, field->hidinput->input);
- if (field->index == td->last_field_index
- && td->num_received >= td->num_expected)
- mt_sync_frame(td, field->hidinput->input);
+ if (field->index == td->last_field_index
+ && td->num_received >= td->num_expected)
+ mt_sync_frame(td, field->hidinput->input);
+ }
}
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 5669916c2943..1219998a02d6 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -167,7 +167,7 @@ static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj
loff_t off, size_t count) \
{ \
return isku_sysfs_write(fp, kobj, buf, off, count, \
- sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+ ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
}
#define ISKU_SYSFS_R(thingy, THINGY) \
@@ -176,32 +176,32 @@ static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj,
loff_t off, size_t count) \
{ \
return isku_sysfs_read(fp, kobj, buf, off, count, \
- sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+ ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
}
#define ISKU_SYSFS_RW(thingy, THINGY) \
ISKU_SYSFS_R(thingy, THINGY) \
ISKU_SYSFS_W(thingy, THINGY)
-#define ISKU_BIN_ATTR_RW(thingy) \
+#define ISKU_BIN_ATTR_RW(thingy, THINGY) \
{ \
.attr = { .name = #thingy, .mode = 0660 }, \
- .size = sizeof(struct isku_ ## thingy), \
+ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \
.write = isku_sysfs_write_ ## thingy \
}
-#define ISKU_BIN_ATTR_R(thingy) \
+#define ISKU_BIN_ATTR_R(thingy, THINGY) \
{ \
.attr = { .name = #thingy, .mode = 0440 }, \
- .size = sizeof(struct isku_ ## thingy), \
+ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \
}
-#define ISKU_BIN_ATTR_W(thingy) \
+#define ISKU_BIN_ATTR_W(thingy, THINGY) \
{ \
.attr = { .name = #thingy, .mode = 0220 }, \
- .size = sizeof(struct isku_ ## thingy), \
+ .size = ISKU_SIZE_ ## THINGY, \
.write = isku_sysfs_write_ ## thingy \
}
@@ -218,21 +218,23 @@ ISKU_SYSFS_RW(last_set, LAST_SET)
ISKU_SYSFS_W(talk, TALK)
ISKU_SYSFS_R(info, INFO)
ISKU_SYSFS_W(control, CONTROL)
+ISKU_SYSFS_W(reset, RESET)
static struct bin_attribute isku_bin_attributes[] = {
- ISKU_BIN_ATTR_RW(macro),
- ISKU_BIN_ATTR_RW(keys_function),
- ISKU_BIN_ATTR_RW(keys_easyzone),
- ISKU_BIN_ATTR_RW(keys_media),
- ISKU_BIN_ATTR_RW(keys_thumbster),
- ISKU_BIN_ATTR_RW(keys_macro),
- ISKU_BIN_ATTR_RW(keys_capslock),
- ISKU_BIN_ATTR_RW(light),
- ISKU_BIN_ATTR_RW(key_mask),
- ISKU_BIN_ATTR_RW(last_set),
- ISKU_BIN_ATTR_W(talk),
- ISKU_BIN_ATTR_R(info),
- ISKU_BIN_ATTR_W(control),
+ ISKU_BIN_ATTR_RW(macro, MACRO),
+ ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
+ ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
+ ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
+ ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
+ ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
+ ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
+ ISKU_BIN_ATTR_RW(light, LIGHT),
+ ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
+ ISKU_BIN_ATTR_RW(last_set, LAST_SET),
+ ISKU_BIN_ATTR_W(talk, TALK),
+ ISKU_BIN_ATTR_R(info, INFO),
+ ISKU_BIN_ATTR_W(control, CONTROL),
+ ISKU_BIN_ATTR_W(reset, RESET),
__ATTR_NULL
};
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h
index 605b3ce21638..cf6896c83867 100644
--- a/drivers/hid/hid-roccat-isku.h
+++ b/drivers/hid/hid-roccat-isku.h
@@ -15,76 +15,33 @@
#include <linux/types.h>
enum {
+ ISKU_SIZE_CONTROL = 0x03,
+ ISKU_SIZE_INFO = 0x06,
+ ISKU_SIZE_KEY_MASK = 0x06,
+ ISKU_SIZE_KEYS_FUNCTION = 0x29,
+ ISKU_SIZE_KEYS_EASYZONE = 0x41,
+ ISKU_SIZE_KEYS_MEDIA = 0x1d,
+ ISKU_SIZE_KEYS_THUMBSTER = 0x17,
+ ISKU_SIZE_KEYS_MACRO = 0x23,
+ ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
+ ISKU_SIZE_LAST_SET = 0x14,
+ ISKU_SIZE_LIGHT = 0x0a,
+ ISKU_SIZE_MACRO = 0x823,
+ ISKU_SIZE_RESET = 0x03,
+ ISKU_SIZE_TALK = 0x10,
+};
+
+enum {
ISKU_PROFILE_NUM = 5,
ISKU_USB_INTERFACE_PROTOCOL = 0,
};
-struct isku_control {
- uint8_t command; /* ISKU_COMMAND_CONTROL */
- uint8_t value;
- uint8_t request;
-} __packed;
-
struct isku_actual_profile {
uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
uint8_t size; /* always 3 */
uint8_t actual_profile;
} __packed;
-struct isku_key_mask {
- uint8_t command; /* ISKU_COMMAND_KEY_MASK */
- uint8_t size; /* 6 */
- uint8_t profile_number; /* 0-4 */
- uint8_t mask;
- uint16_t checksum;
-} __packed;
-
-struct isku_keys_function {
- uint8_t data[0x29];
-} __packed;
-
-struct isku_keys_easyzone {
- uint8_t data[0x41];
-} __packed;
-
-struct isku_keys_media {
- uint8_t data[0x1d];
-} __packed;
-
-struct isku_keys_thumbster {
- uint8_t data[0x17];
-} __packed;
-
-struct isku_keys_macro {
- uint8_t data[0x23];
-} __packed;
-
-struct isku_keys_capslock {
- uint8_t data[0x6];
-} __packed;
-
-struct isku_macro {
- uint8_t data[0x823];
-} __packed;
-
-struct isku_light {
- uint8_t data[0xa];
-} __packed;
-
-struct isku_info {
- uint8_t data[2];
- uint8_t firmware_version;
- uint8_t unknown[3];
-} __packed;
-
-struct isku_talk {
- uint8_t data[0x10];
-} __packed;
-
-struct isku_last_set {
- uint8_t data[0x14];
-} __packed;
-
enum isku_commands {
ISKU_COMMAND_CONTROL = 0x4,
ISKU_COMMAND_ACTUAL_PROFILE = 0x5,
@@ -97,6 +54,7 @@ enum isku_commands {
ISKU_COMMAND_MACRO = 0xe,
ISKU_COMMAND_INFO = 0xf,
ISKU_COMMAND_LIGHT = 0x10,
+ ISKU_COMMAND_RESET = 0x11,
ISKU_COMMAND_KEYS_CAPSLOCK = 0x13,
ISKU_COMMAND_LAST_SET = 0x14,
ISKU_COMMAND_15 = 0x15,
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index f5602fec4865..6a48fa3c7da9 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -14,6 +14,7 @@
/*
* Roccat Kone[+] is an updated/improved version of the Kone with more memory
* and functionality and without the non-standard behaviours the Kone had.
+ * KoneXTD has same capabilities but updated sensor.
*/
#include <linux/device.h>
@@ -55,56 +56,6 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value,
&control, sizeof(struct roccat_common2_control));
}
-static int koneplus_get_info(struct usb_device *usb_dev,
- struct koneplus_info *buf)
-{
- return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
- buf, sizeof(struct koneplus_info));
-}
-
-static int koneplus_get_profile_settings(struct usb_device *usb_dev,
- struct koneplus_profile_settings *buf, uint number)
-{
- int retval;
-
- retval = koneplus_send_control(usb_dev, number,
- KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
- if (retval)
- return retval;
-
- return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
- buf, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_set_profile_settings(struct usb_device *usb_dev,
- struct koneplus_profile_settings const *settings)
-{
- return roccat_common2_send_with_status(usb_dev,
- KONEPLUS_COMMAND_PROFILE_SETTINGS,
- settings, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
- struct koneplus_profile_buttons *buf, int number)
-{
- int retval;
-
- retval = koneplus_send_control(usb_dev, number,
- KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
-
- return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
- buf, sizeof(struct koneplus_profile_buttons));
-}
-
-static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
- struct koneplus_profile_buttons const *buttons)
-{
- return roccat_common2_send_with_status(usb_dev,
- KONEPLUS_COMMAND_PROFILE_BUTTONS,
- buttons, sizeof(struct koneplus_profile_buttons));
-}
/* retval is 0-4 on success, < 0 on error */
static int koneplus_get_actual_profile(struct usb_device *usb_dev)
@@ -113,7 +64,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
int retval;
retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, sizeof(struct koneplus_actual_profile));
+ &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
return retval ? retval : buf.actual_profile;
}
@@ -124,12 +75,12 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
struct koneplus_actual_profile buf;
buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
- buf.size = sizeof(struct koneplus_actual_profile);
+ buf.size = KONEPLUS_SIZE_ACTUAL_PROFILE;
buf.actual_profile = new_profile;
return roccat_common2_send_with_status(usb_dev,
KONEPLUS_COMMAND_ACTUAL_PROFILE,
- &buf, sizeof(struct koneplus_actual_profile));
+ &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
}
static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -182,111 +133,77 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
return real_size;
}
-static ssize_t koneplus_sysfs_write_talk(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK);
+#define KONEPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return koneplus_sysfs_write(fp, kobj, buf, off, count, \
+ KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
}
-static ssize_t koneplus_sysfs_write_macro(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO);
+#define KONEPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return koneplus_sysfs_read(fp, kobj, buf, off, count, \
+ KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
}
-static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
-}
+#define KONEPLUS_SYSFS_RW(thingy, THINGY) \
+KONEPLUS_SYSFS_W(thingy, THINGY) \
+KONEPLUS_SYSFS_R(thingy, THINGY)
-static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
+#define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0660 }, \
+ .size = KONEPLUS_SIZE_ ## THINGY, \
+ .read = koneplus_sysfs_read_ ## thingy, \
+ .write = koneplus_sysfs_write_ ## thingy \
}
-static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_write(fp, kobj, buf, off, count,
- sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0440 }, \
+ .size = KONEPLUS_SIZE_ ## THINGY, \
+ .read = koneplus_sysfs_read_ ## thingy, \
}
-static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- return koneplus_sysfs_read(fp, kobj, buf, off, count,
- sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0220 }, \
+ .size = KONEPLUS_SIZE_ ## THINGY, \
+ .write = koneplus_sysfs_write_ ## thingy \
}
-static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
- if (off >= sizeof(struct koneplus_profile_settings))
- return 0;
+KONEPLUS_SYSFS_W(control, CONTROL)
+KONEPLUS_SYSFS_RW(info, INFO)
+KONEPLUS_SYSFS_W(talk, TALK)
+KONEPLUS_SYSFS_W(macro, MACRO)
+KONEPLUS_SYSFS_RW(sensor, SENSOR)
+KONEPLUS_SYSFS_RW(tcu, TCU)
+KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
+KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
- if (off + count > sizeof(struct koneplus_profile_settings))
- count = sizeof(struct koneplus_profile_settings) - off;
-
- mutex_lock(&koneplus->koneplus_lock);
- memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
- count);
- mutex_unlock(&koneplus->koneplus_lock);
-
- return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
+static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- int profile_number;
- struct koneplus_profile_settings *profile_settings;
-
- if (off != 0 || count != sizeof(struct koneplus_profile_settings))
- return -EINVAL;
-
- profile_number = ((struct koneplus_profile_settings const *)buf)->number;
- profile_settings = &koneplus->profile_settings[profile_number];
-
- mutex_lock(&koneplus->koneplus_lock);
- difference = memcmp(buf, profile_settings,
- sizeof(struct koneplus_profile_settings));
- if (difference) {
- retval = koneplus_set_profile_settings(usb_dev,
- (struct koneplus_profile_settings const *)buf);
- if (!retval)
- memcpy(profile_settings, buf,
- sizeof(struct koneplus_profile_settings));
- }
- mutex_unlock(&koneplus->koneplus_lock);
+ ssize_t retval;
+ retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+ KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
if (retval)
return retval;
- return sizeof(struct koneplus_profile_settings);
+ return koneplus_sysfs_read(fp, kobj, buf, off, count,
+ KONEPLUS_SIZE_PROFILE_SETTINGS,
+ KONEPLUS_COMMAND_PROFILE_SETTINGS);
}
static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
@@ -295,57 +212,17 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
- if (off >= sizeof(struct koneplus_profile_buttons))
- return 0;
-
- if (off + count > sizeof(struct koneplus_profile_buttons))
- count = sizeof(struct koneplus_profile_buttons) - off;
-
- mutex_lock(&koneplus->koneplus_lock);
- memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
- count);
- mutex_unlock(&koneplus->koneplus_lock);
-
- return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- uint profile_number;
- struct koneplus_profile_buttons *profile_buttons;
-
- if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
- return -EINVAL;
-
- profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
- profile_buttons = &koneplus->profile_buttons[profile_number];
-
- mutex_lock(&koneplus->koneplus_lock);
- difference = memcmp(buf, profile_buttons,
- sizeof(struct koneplus_profile_buttons));
- if (difference) {
- retval = koneplus_set_profile_buttons(usb_dev,
- (struct koneplus_profile_buttons const *)buf);
- if (!retval)
- memcpy(profile_buttons, buf,
- sizeof(struct koneplus_profile_buttons));
- }
- mutex_unlock(&koneplus->koneplus_lock);
+ ssize_t retval;
+ retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+ KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
if (retval)
return retval;
- return sizeof(struct koneplus_profile_buttons);
+ return koneplus_sysfs_read(fp, kobj, buf, off, count,
+ KONEPLUS_SIZE_PROFILE_BUTTONS,
+ KONEPLUS_COMMAND_PROFILE_BUTTONS);
}
static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
@@ -401,9 +278,20 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct koneplus_device *koneplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
+ struct koneplus_device *koneplus;
+ struct usb_device *usb_dev;
+ struct koneplus_info info;
+
+ dev = dev->parent->parent;
+ koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+ usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+ mutex_lock(&koneplus->koneplus_lock);
+ roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
+ &info, KONEPLUS_SIZE_INFO);
+ mutex_unlock(&koneplus->koneplus_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
}
static struct device_attribute koneplus_attributes[] = {
@@ -419,132 +307,85 @@ static struct device_attribute koneplus_attributes[] = {
};
static struct bin_attribute koneplus_bin_attributes[] = {
- {
- .attr = { .name = "sensor", .mode = 0660 },
- .size = sizeof(struct koneplus_sensor),
- .read = koneplus_sysfs_read_sensor,
- .write = koneplus_sysfs_write_sensor
- },
- {
- .attr = { .name = "tcu", .mode = 0220 },
- .size = sizeof(struct koneplus_tcu),
- .write = koneplus_sysfs_write_tcu
- },
- {
- .attr = { .name = "tcu_image", .mode = 0440 },
- .size = sizeof(struct koneplus_tcu_image),
- .read = koneplus_sysfs_read_tcu_image
- },
- {
- .attr = { .name = "profile_settings", .mode = 0220 },
- .size = sizeof(struct koneplus_profile_settings),
- .write = koneplus_sysfs_write_profile_settings
- },
+ KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+ KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+ KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
+ KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
+ KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
+ KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
+ KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
+ KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+ KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
{
.attr = { .name = "profile1_settings", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_settings),
+ .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
.read = koneplus_sysfs_read_profilex_settings,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_settings", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_settings),
+ .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
.read = koneplus_sysfs_read_profilex_settings,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_settings", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_settings),
+ .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
.read = koneplus_sysfs_read_profilex_settings,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_settings", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_settings),
+ .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
.read = koneplus_sysfs_read_profilex_settings,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_settings", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_settings),
+ .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
.read = koneplus_sysfs_read_profilex_settings,
.private = &profile_numbers[4]
},
{
- .attr = { .name = "profile_buttons", .mode = 0220 },
- .size = sizeof(struct koneplus_profile_buttons),
- .write = koneplus_sysfs_write_profile_buttons
- },
- {
.attr = { .name = "profile1_buttons", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_buttons),
+ .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
.read = koneplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_buttons", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_buttons),
+ .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
.read = koneplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_buttons", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_buttons),
+ .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
.read = koneplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_buttons", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_buttons),
+ .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
.read = koneplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_buttons", .mode = 0440 },
- .size = sizeof(struct koneplus_profile_buttons),
+ .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
.read = koneplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[4]
},
- {
- .attr = { .name = "macro", .mode = 0220 },
- .size = sizeof(struct koneplus_macro),
- .write = koneplus_sysfs_write_macro
- },
- {
- .attr = { .name = "talk", .mode = 0220 },
- .size = sizeof(struct koneplus_talk),
- .write = koneplus_sysfs_write_talk
- },
__ATTR_NULL
};
static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
struct koneplus_device *koneplus)
{
- int retval, i;
- static uint wait = 200;
+ int retval;
mutex_init(&koneplus->koneplus_lock);
- retval = koneplus_get_info(usb_dev, &koneplus->info);
- if (retval)
- return retval;
-
- for (i = 0; i < 5; ++i) {
- msleep(wait);
- retval = koneplus_get_profile_settings(usb_dev,
- &koneplus->profile_settings[i], i);
- if (retval)
- return retval;
-
- msleep(wait);
- retval = koneplus_get_profile_buttons(usb_dev,
- &koneplus->profile_buttons[i], i);
- if (retval)
- return retval;
- }
-
- msleep(wait);
retval = koneplus_get_actual_profile(usb_dev);
if (retval < 0)
return retval;
@@ -709,6 +550,7 @@ static int koneplus_raw_event(struct hid_device *hdev,
static const struct hid_device_id koneplus_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
{ }
};
@@ -749,5 +591,5 @@ module_init(koneplus_init);
module_exit(koneplus_exit);
MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
+MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
index 7074b2a4b94b..af7f57e8cf3b 100644
--- a/drivers/hid/hid-roccat-koneplus.h
+++ b/drivers/hid/hid-roccat-koneplus.h
@@ -14,11 +14,19 @@
#include <linux/types.h>
-struct koneplus_talk {
- uint8_t command; /* KONEPLUS_COMMAND_TALK */
- uint8_t size; /* always 0x10 */
- uint8_t data[14];
-} __packed;
+enum {
+ KONEPLUS_SIZE_ACTUAL_PROFILE = 0x03,
+ KONEPLUS_SIZE_CONTROL = 0x03,
+ KONEPLUS_SIZE_FIRMWARE_WRITE = 0x0402,
+ KONEPLUS_SIZE_INFO = 0x06,
+ KONEPLUS_SIZE_MACRO = 0x0822,
+ KONEPLUS_SIZE_PROFILE_SETTINGS = 0x2b,
+ KONEPLUS_SIZE_PROFILE_BUTTONS = 0x4d,
+ KONEPLUS_SIZE_SENSOR = 0x06,
+ KONEPLUS_SIZE_TALK = 0x10,
+ KONEPLUS_SIZE_TCU = 0x04,
+ KONEPLUS_SIZE_TCU_IMAGE = 0x0404,
+};
enum koneplus_control_requests {
KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
@@ -31,45 +39,6 @@ struct koneplus_actual_profile {
uint8_t actual_profile; /* Range 0-4! */
} __attribute__ ((__packed__));
-struct koneplus_profile_settings {
- uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
- uint8_t size; /* always 43 */
- uint8_t number; /* range 0-4 */
- uint8_t advanced_sensitivity;
- uint8_t sensitivity_x;
- uint8_t sensitivity_y;
- uint8_t cpi_levels_enabled;
- uint8_t cpi_levels_x[5];
- uint8_t cpi_startup_level; /* range 0-4 */
- uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
- uint8_t unknown1;
- uint8_t polling_rate;
- uint8_t lights_enabled;
- uint8_t light_effect_mode;
- uint8_t color_flow_effect;
- uint8_t light_effect_type;
- uint8_t light_effect_speed;
- uint8_t lights[16];
- uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_profile_buttons {
- uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
- uint8_t size; /* always 77 */
- uint8_t number; /* range 0-4 */
- uint8_t data[72];
- uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_macro {
- uint8_t command; /* KONEPLUS_COMMAND_MACRO */
- uint16_t size; /* always 0x822 little endian */
- uint8_t profile; /* range 0-4 */
- uint8_t button; /* range 0-23 */
- uint8_t data[2075];
- uint16_t checksum;
-} __attribute__ ((__packed__));
-
struct koneplus_info {
uint8_t command; /* KONEPLUS_COMMAND_INFO */
uint8_t size; /* always 6 */
@@ -77,51 +46,15 @@ struct koneplus_info {
uint8_t unknown[3];
} __attribute__ ((__packed__));
-struct koneplus_e {
- uint8_t command; /* KONEPLUS_COMMAND_E */
- uint8_t size; /* always 3 */
- uint8_t unknown; /* TODO 1; 0 before firmware update */
-} __attribute__ ((__packed__));
-
-struct koneplus_sensor {
- uint8_t command; /* KONEPLUS_COMMAND_SENSOR */
- uint8_t size; /* always 6 */
- uint8_t data[4];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write {
- uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
- uint8_t unknown[1025];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write_control {
- uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
- /*
- * value is 1 on success
- * 3 means "not finished yet"
- */
- uint8_t value;
- uint8_t unknown; /* always 0x75 */
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu {
- uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
- uint8_t data[2];
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu_image {
- uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
- uint8_t data[1024];
- uint16_t checksum;
-} __attribute__ ((__packed__));
-
enum koneplus_commands {
KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+ KONEPLUS_COMMAND_CONTROL = 0x4,
KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
KONEPLUS_COMMAND_MACRO = 0x8,
KONEPLUS_COMMAND_INFO = 0x9,
KONEPLUS_COMMAND_TCU = 0xc,
+ KONEPLUS_COMMAND_TCU_IMAGE = 0xc,
KONEPLUS_COMMAND_E = 0xe,
KONEPLUS_COMMAND_SENSOR = 0xf,
KONEPLUS_COMMAND_TALK = 0x10,
@@ -187,10 +120,6 @@ struct koneplus_device {
int chrdev_minor;
struct mutex koneplus_lock;
-
- struct koneplus_info info;
- struct koneplus_profile_settings profile_settings[5];
- struct koneplus_profile_buttons profile_buttons[5];
};
#endif
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index ca6527ac655d..b8b37789b864 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -70,13 +70,6 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
return kovaplus_send_control(usb_dev, number, request);
}
-static int kovaplus_get_info(struct usb_device *usb_dev,
- struct kovaplus_info *buf)
-{
- return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
- buf, sizeof(struct kovaplus_info));
-}
-
static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
struct kovaplus_profile_settings *buf, uint number)
{
@@ -88,15 +81,7 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
return retval;
return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
- buf, sizeof(struct kovaplus_profile_settings));
-}
-
-static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
- struct kovaplus_profile_settings const *settings)
-{
- return roccat_common2_send_with_status(usb_dev,
- KOVAPLUS_COMMAND_PROFILE_SETTINGS,
- settings, sizeof(struct kovaplus_profile_settings));
+ buf, KOVAPLUS_SIZE_PROFILE_SETTINGS);
}
static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -110,15 +95,7 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
return retval;
return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
- buf, sizeof(struct kovaplus_profile_buttons));
-}
-
-static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
- struct kovaplus_profile_buttons const *buttons)
-{
- return roccat_common2_send_with_status(usb_dev,
- KOVAPLUS_COMMAND_PROFILE_BUTTONS,
- buttons, sizeof(struct kovaplus_profile_buttons));
+ buf, KOVAPLUS_SIZE_PROFILE_BUTTONS);
}
/* retval is 0-4 on success, < 0 on error */
@@ -147,122 +124,141 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
&buf, sizeof(struct kovaplus_actual_profile));
}
-static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj,
+ char *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ int retval;
- if (off >= sizeof(struct kovaplus_profile_settings))
+ if (off >= real_size)
return 0;
- if (off + count > sizeof(struct kovaplus_profile_settings))
- count = sizeof(struct kovaplus_profile_settings) - off;
+ if (off != 0 || count != real_size)
+ return -EINVAL;
mutex_lock(&kovaplus->kovaplus_lock);
- memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off,
- count);
+ retval = roccat_common2_receive(usb_dev, command, buf, real_size);
mutex_unlock(&kovaplus->kovaplus_lock);
- return count;
+ if (retval)
+ return retval;
+
+ return real_size;
}
-static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj,
+ void const *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- int profile_index;
- struct kovaplus_profile_settings *profile_settings;
+ int retval;
- if (off != 0 || count != sizeof(struct kovaplus_profile_settings))
+ if (off != 0 || count != real_size)
return -EINVAL;
- profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index;
- profile_settings = &kovaplus->profile_settings[profile_index];
-
mutex_lock(&kovaplus->kovaplus_lock);
- difference = memcmp(buf, profile_settings,
- sizeof(struct kovaplus_profile_settings));
- if (difference) {
- retval = kovaplus_set_profile_settings(usb_dev,
- (struct kovaplus_profile_settings const *)buf);
- if (!retval)
- memcpy(profile_settings, buf,
- sizeof(struct kovaplus_profile_settings));
- }
+ retval = roccat_common2_send_with_status(usb_dev, command,
+ buf, real_size);
mutex_unlock(&kovaplus->kovaplus_lock);
if (retval)
return retval;
- return sizeof(struct kovaplus_profile_settings);
+ return real_size;
}
-static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+#define KOVAPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_write_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return kovaplus_sysfs_write(fp, kobj, buf, off, count, \
+ KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
- if (off >= sizeof(struct kovaplus_profile_buttons))
- return 0;
+#define KOVAPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_read_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return kovaplus_sysfs_read(fp, kobj, buf, off, count, \
+ KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
- if (off + count > sizeof(struct kovaplus_profile_buttons))
- count = sizeof(struct kovaplus_profile_buttons) - off;
+#define KOVAPLUS_SYSFS_RW(thingy, THINGY) \
+KOVAPLUS_SYSFS_W(thingy, THINGY) \
+KOVAPLUS_SYSFS_R(thingy, THINGY)
- mutex_lock(&kovaplus->kovaplus_lock);
- memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off,
- count);
- mutex_unlock(&kovaplus->kovaplus_lock);
+#define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0660 }, \
+ .size = KOVAPLUS_SIZE_ ## THINGY, \
+ .read = kovaplus_sysfs_read_ ## thingy, \
+ .write = kovaplus_sysfs_write_ ## thingy \
+}
+
+#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0440 }, \
+ .size = KOVAPLUS_SIZE_ ## THINGY, \
+ .read = kovaplus_sysfs_read_ ## thingy, \
+}
- return count;
+#define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0220 }, \
+ .size = KOVAPLUS_SIZE_ ## THINGY, \
+ .write = kovaplus_sysfs_write_ ## thingy \
}
-static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp,
+KOVAPLUS_SYSFS_W(control, CONTROL)
+KOVAPLUS_SYSFS_RW(info, INFO)
+KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+
+static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
- struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- uint profile_index;
- struct kovaplus_profile_buttons *profile_buttons;
+ ssize_t retval;
- if (off != 0 || count != sizeof(struct kovaplus_profile_buttons))
- return -EINVAL;
+ retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+ KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+ if (retval)
+ return retval;
- profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index;
- profile_buttons = &kovaplus->profile_buttons[profile_index];
+ return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+ KOVAPLUS_SIZE_PROFILE_SETTINGS,
+ KOVAPLUS_COMMAND_PROFILE_SETTINGS);
+}
- mutex_lock(&kovaplus->kovaplus_lock);
- difference = memcmp(buf, profile_buttons,
- sizeof(struct kovaplus_profile_buttons));
- if (difference) {
- retval = kovaplus_set_profile_buttons(usb_dev,
- (struct kovaplus_profile_buttons const *)buf);
- if (!retval)
- memcpy(profile_buttons, buf,
- sizeof(struct kovaplus_profile_buttons));
- }
- mutex_unlock(&kovaplus->kovaplus_lock);
+static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
+ struct kobject *kobj, struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ struct device *dev =
+ container_of(kobj, struct device, kobj)->parent->parent;
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ ssize_t retval;
+ retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+ KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
if (retval)
return retval;
- return sizeof(struct kovaplus_profile_buttons);
+ return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+ KOVAPLUS_SIZE_PROFILE_BUTTONS,
+ KOVAPLUS_COMMAND_PROFILE_BUTTONS);
}
static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
@@ -342,9 +338,20 @@ static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct kovaplus_device *kovaplus =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version);
+ struct kovaplus_device *kovaplus;
+ struct usb_device *usb_dev;
+ struct kovaplus_info info;
+
+ dev = dev->parent->parent;
+ kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+ usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+ mutex_lock(&kovaplus->kovaplus_lock);
+ roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
+ &info, KOVAPLUS_SIZE_INFO);
+ mutex_unlock(&kovaplus->kovaplus_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
}
static struct device_attribute kovaplus_attributes[] = {
@@ -363,73 +370,67 @@ static struct device_attribute kovaplus_attributes[] = {
};
static struct bin_attribute kovaplus_bin_attributes[] = {
- {
- .attr = { .name = "profile_settings", .mode = 0220 },
- .size = sizeof(struct kovaplus_profile_settings),
- .write = kovaplus_sysfs_write_profile_settings
- },
+ KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+ KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+ KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+ KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
{
.attr = { .name = "profile1_settings", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_settings),
+ .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
.read = kovaplus_sysfs_read_profilex_settings,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_settings", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_settings),
+ .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
.read = kovaplus_sysfs_read_profilex_settings,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_settings", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_settings),
+ .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
.read = kovaplus_sysfs_read_profilex_settings,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_settings", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_settings),
+ .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
.read = kovaplus_sysfs_read_profilex_settings,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_settings", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_settings),
+ .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
.read = kovaplus_sysfs_read_profilex_settings,
.private = &profile_numbers[4]
},
{
- .attr = { .name = "profile_buttons", .mode = 0220 },
- .size = sizeof(struct kovaplus_profile_buttons),
- .write = kovaplus_sysfs_write_profile_buttons
- },
- {
.attr = { .name = "profile1_buttons", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_buttons),
+ .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
.read = kovaplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_buttons", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_buttons),
+ .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
.read = kovaplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_buttons", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_buttons),
+ .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
.read = kovaplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_buttons", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_buttons),
+ .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
.read = kovaplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_buttons", .mode = 0440 },
- .size = sizeof(struct kovaplus_profile_buttons),
+ .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
.read = kovaplus_sysfs_read_profilex_buttons,
.private = &profile_numbers[4]
},
@@ -444,10 +445,6 @@ static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
mutex_init(&kovaplus->kovaplus_lock);
- retval = kovaplus_get_info(usb_dev, &kovaplus->info);
- if (retval)
- return retval;
-
for (i = 0; i < 5; ++i) {
msleep(wait);
retval = kovaplus_get_profile_settings(usb_dev,
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
index f82daa1cdcb9..fbb7a16a7e54 100644
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -14,6 +14,13 @@
#include <linux/types.h>
+enum {
+ KOVAPLUS_SIZE_CONTROL = 0x03,
+ KOVAPLUS_SIZE_INFO = 0x06,
+ KOVAPLUS_SIZE_PROFILE_SETTINGS = 0x10,
+ KOVAPLUS_SIZE_PROFILE_BUTTONS = 0x17,
+};
+
enum kovaplus_control_requests {
/* write; value = profile number range 0-4 */
KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -53,15 +60,9 @@ struct kovaplus_info {
uint8_t unknown[3];
} __packed;
-/* writes 1 on plugin */
-struct kovaplus_a {
- uint8_t command; /* KOVAPLUS_COMMAND_A */
- uint8_t size; /* 3 */
- uint8_t unknown;
-} __packed;
-
enum kovaplus_commands {
KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+ KOVAPLUS_COMMAND_CONTROL = 0x4,
KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
KOVAPLUS_COMMAND_INFO = 0x9,
@@ -125,7 +126,6 @@ struct kovaplus_device {
int roccat_claimed;
int chrdev_minor;
struct mutex kovaplus_lock;
- struct kovaplus_info info;
struct kovaplus_profile_settings profile_settings[5];
struct kovaplus_profile_buttons profile_buttons[5];
};
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
new file mode 100644
index 000000000000..5084fb4b7e91
--- /dev/null
+++ b/drivers/hid/hid-roccat-lua.c
@@ -0,0 +1,227 @@
+/*
+ * Roccat Lua driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * Roccat Lua is a gamer mouse which cpi, button and light settings can be
+ * configured.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-lua.h"
+
+static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
+ char *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ int retval;
+
+ if (off >= real_size)
+ return 0;
+
+ if (off != 0 || count != real_size)
+ return -EINVAL;
+
+ mutex_lock(&lua->lua_lock);
+ retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+ mutex_unlock(&lua->lua_lock);
+
+ return retval ? retval : real_size;
+}
+
+static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
+ void const *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ int retval;
+
+ if (off != 0 || count != real_size)
+ return -EINVAL;
+
+ mutex_lock(&lua->lua_lock);
+ retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+ mutex_unlock(&lua->lua_lock);
+
+ return retval ? retval : real_size;
+}
+
+#define LUA_SYSFS_W(thingy, THINGY) \
+static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, \
+ char *buf, loff_t off, size_t count) \
+{ \
+ return lua_sysfs_write(fp, kobj, buf, off, count, \
+ LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_SYSFS_R(thingy, THINGY) \
+static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, \
+ char *buf, loff_t off, size_t count) \
+{ \
+ return lua_sysfs_read(fp, kobj, buf, off, count, \
+ LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+LUA_SYSFS_W(thingy, THINGY) \
+LUA_SYSFS_R(thingy, THINGY) \
+static struct bin_attribute lua_ ## thingy ## _attr = { \
+ .attr = { .name = #thingy, .mode = 0660 }, \
+ .size = LUA_SIZE_ ## THINGY, \
+ .read = lua_sysfs_read_ ## thingy, \
+ .write = lua_sysfs_write_ ## thingy \
+};
+
+LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+
+static int lua_create_sysfs_attributes(struct usb_interface *intf)
+{
+ return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static void lua_remove_sysfs_attributes(struct usb_interface *intf)
+{
+ sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static int lua_init_lua_device_struct(struct usb_device *usb_dev,
+ struct lua_device *lua)
+{
+ mutex_init(&lua->lua_lock);
+
+ return 0;
+}
+
+static int lua_init_specials(struct hid_device *hdev)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct lua_device *lua;
+ int retval;
+
+ lua = kzalloc(sizeof(*lua), GFP_KERNEL);
+ if (!lua) {
+ hid_err(hdev, "can't alloc device descriptor\n");
+ return -ENOMEM;
+ }
+ hid_set_drvdata(hdev, lua);
+
+ retval = lua_init_lua_device_struct(usb_dev, lua);
+ if (retval) {
+ hid_err(hdev, "couldn't init struct lua_device\n");
+ goto exit;
+ }
+
+ retval = lua_create_sysfs_attributes(intf);
+ if (retval) {
+ hid_err(hdev, "cannot create sysfs files\n");
+ goto exit;
+ }
+
+ return 0;
+exit:
+ kfree(lua);
+ return retval;
+}
+
+static void lua_remove_specials(struct hid_device *hdev)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct lua_device *lua;
+
+ lua_remove_sysfs_attributes(intf);
+
+ lua = hid_get_drvdata(hdev);
+ kfree(lua);
+}
+
+static int lua_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int retval;
+
+ retval = hid_parse(hdev);
+ if (retval) {
+ hid_err(hdev, "parse failed\n");
+ goto exit;
+ }
+
+ retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (retval) {
+ hid_err(hdev, "hw start failed\n");
+ goto exit;
+ }
+
+ retval = lua_init_specials(hdev);
+ if (retval) {
+ hid_err(hdev, "couldn't install mouse\n");
+ goto exit_stop;
+ }
+
+ return 0;
+
+exit_stop:
+ hid_hw_stop(hdev);
+exit:
+ return retval;
+}
+
+static void lua_remove(struct hid_device *hdev)
+{
+ lua_remove_specials(hdev);
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lua_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(hid, lua_devices);
+
+static struct hid_driver lua_driver = {
+ .name = "lua",
+ .id_table = lua_devices,
+ .probe = lua_probe,
+ .remove = lua_remove
+};
+
+static int __init lua_init(void)
+{
+ return hid_register_driver(&lua_driver);
+}
+
+static void __exit lua_exit(void)
+{
+ hid_unregister_driver(&lua_driver);
+}
+
+module_init(lua_init);
+module_exit(lua_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Lua driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-lua.h b/drivers/hid/hid-roccat-lua.h
new file mode 100644
index 000000000000..547d77a375d1
--- /dev/null
+++ b/drivers/hid/hid-roccat-lua.h
@@ -0,0 +1,29 @@
+#ifndef __HID_ROCCAT_LUA_H
+#define __HID_ROCCAT_LUA_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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/types.h>
+
+enum {
+ LUA_SIZE_CONTROL = 8,
+};
+
+enum lua_commands {
+ LUA_COMMAND_CONTROL = 3,
+};
+
+struct lua_device {
+ struct mutex lua_lock;
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 1317c177a3e2..d4f1e3bee590 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -66,48 +66,14 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
if (retval)
return retval;
return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
- buf, sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_get_profile_buttons(struct usb_device *usb_dev,
- struct pyra_profile_buttons *buf, int number)
-{
- int retval;
- retval = pyra_send_control(usb_dev, number,
- PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
- if (retval)
- return retval;
- return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
- buf, sizeof(struct pyra_profile_buttons));
+ buf, PYRA_SIZE_PROFILE_SETTINGS);
}
static int pyra_get_settings(struct usb_device *usb_dev,
struct pyra_settings *buf)
{
return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
- buf, sizeof(struct pyra_settings));
-}
-
-static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
-{
- return roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
- buf, sizeof(struct pyra_info));
-}
-
-static int pyra_set_profile_settings(struct usb_device *usb_dev,
- struct pyra_profile_settings const *settings)
-{
- return roccat_common2_send_with_status(usb_dev,
- PYRA_COMMAND_PROFILE_SETTINGS, settings,
- sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_set_profile_buttons(struct usb_device *usb_dev,
- struct pyra_profile_buttons const *buttons)
-{
- return roccat_common2_send_with_status(usb_dev,
- PYRA_COMMAND_PROFILE_BUTTONS, buttons,
- sizeof(struct pyra_profile_buttons));
+ buf, PYRA_SIZE_SETTINGS);
}
static int pyra_set_settings(struct usb_device *usb_dev,
@@ -115,146 +81,144 @@ static int pyra_set_settings(struct usb_device *usb_dev,
{
return roccat_common2_send_with_status(usb_dev,
PYRA_COMMAND_SETTINGS, settings,
- sizeof(struct pyra_settings));
+ PYRA_SIZE_SETTINGS);
}
-static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
+static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj,
+ char *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ int retval;
- if (off >= sizeof(struct pyra_profile_settings))
+ if (off >= real_size)
return 0;
- if (off + count > sizeof(struct pyra_profile_settings))
- count = sizeof(struct pyra_profile_settings) - off;
+ if (off != 0 || count != real_size)
+ return -EINVAL;
mutex_lock(&pyra->pyra_lock);
- memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off,
- count);
+ retval = roccat_common2_receive(usb_dev, command, buf, real_size);
mutex_unlock(&pyra->pyra_lock);
- return count;
+ if (retval)
+ return retval;
+
+ return real_size;
}
-static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
+static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj,
+ void const *buf, loff_t off, size_t count,
+ size_t real_size, uint command)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ int retval;
- if (off >= sizeof(struct pyra_profile_buttons))
- return 0;
-
- if (off + count > sizeof(struct pyra_profile_buttons))
- count = sizeof(struct pyra_profile_buttons) - off;
+ if (off != 0 || count != real_size)
+ return -EINVAL;
mutex_lock(&pyra->pyra_lock);
- memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off,
- count);
+ retval = roccat_common2_send_with_status(usb_dev, command, (void *)buf, real_size);
mutex_unlock(&pyra->pyra_lock);
- return count;
+ if (retval)
+ return retval;
+
+ return real_size;
}
-static ssize_t pyra_sysfs_write_profile_settings(struct file *fp,
- struct kobject *kobj, struct bin_attribute *attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
- struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- int profile_number;
- struct pyra_profile_settings *profile_settings;
+#define PYRA_SYSFS_W(thingy, THINGY) \
+static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return pyra_sysfs_write(fp, kobj, buf, off, count, \
+ PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
- if (off != 0 || count != sizeof(struct pyra_profile_settings))
- return -EINVAL;
+#define PYRA_SYSFS_R(thingy, THINGY) \
+static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \
+ struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ return pyra_sysfs_read(fp, kobj, buf, off, count, \
+ PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
- profile_number = ((struct pyra_profile_settings const *)buf)->number;
- profile_settings = &pyra->profile_settings[profile_number];
+#define PYRA_SYSFS_RW(thingy, THINGY) \
+PYRA_SYSFS_W(thingy, THINGY) \
+PYRA_SYSFS_R(thingy, THINGY)
- mutex_lock(&pyra->pyra_lock);
- difference = memcmp(buf, profile_settings,
- sizeof(struct pyra_profile_settings));
- if (difference) {
- retval = pyra_set_profile_settings(usb_dev,
- (struct pyra_profile_settings const *)buf);
- if (!retval)
- memcpy(profile_settings, buf,
- sizeof(struct pyra_profile_settings));
- }
- mutex_unlock(&pyra->pyra_lock);
+#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0660 }, \
+ .size = PYRA_SIZE_ ## THINGY, \
+ .read = pyra_sysfs_read_ ## thingy, \
+ .write = pyra_sysfs_write_ ## thingy \
+}
- if (retval)
- return retval;
+#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0440 }, \
+ .size = PYRA_SIZE_ ## THINGY, \
+ .read = pyra_sysfs_read_ ## thingy, \
+}
- return sizeof(struct pyra_profile_settings);
+#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+ .attr = { .name = #thingy, .mode = 0220 }, \
+ .size = PYRA_SIZE_ ## THINGY, \
+ .write = pyra_sysfs_write_ ## thingy \
}
-static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp,
+PYRA_SYSFS_W(control, CONTROL)
+PYRA_SYSFS_RW(info, INFO)
+PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+PYRA_SYSFS_R(settings, SETTINGS)
+
+static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0;
- int difference;
- int profile_number;
- struct pyra_profile_buttons *profile_buttons;
-
- if (off != 0 || count != sizeof(struct pyra_profile_buttons))
- return -EINVAL;
-
- profile_number = ((struct pyra_profile_buttons const *)buf)->number;
- profile_buttons = &pyra->profile_buttons[profile_number];
-
- mutex_lock(&pyra->pyra_lock);
- difference = memcmp(buf, profile_buttons,
- sizeof(struct pyra_profile_buttons));
- if (difference) {
- retval = pyra_set_profile_buttons(usb_dev,
- (struct pyra_profile_buttons const *)buf);
- if (!retval)
- memcpy(profile_buttons, buf,
- sizeof(struct pyra_profile_buttons));
- }
- mutex_unlock(&pyra->pyra_lock);
+ ssize_t retval;
+ retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+ PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
if (retval)
return retval;
- return sizeof(struct pyra_profile_buttons);
+ return pyra_sysfs_read(fp, kobj, buf, off, count,
+ PYRA_SIZE_PROFILE_SETTINGS,
+ PYRA_COMMAND_PROFILE_SETTINGS);
}
-static ssize_t pyra_sysfs_read_settings(struct file *fp,
+static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev =
container_of(kobj, struct device, kobj)->parent->parent;
- struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
-
- if (off >= sizeof(struct pyra_settings))
- return 0;
-
- if (off + count > sizeof(struct pyra_settings))
- count = sizeof(struct pyra_settings) - off;
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ ssize_t retval;
- mutex_lock(&pyra->pyra_lock);
- memcpy(buf, ((char const *)&pyra->settings) + off, count);
- mutex_unlock(&pyra->pyra_lock);
+ retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+ PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
+ if (retval)
+ return retval;
- return count;
+ return pyra_sysfs_read(fp, kobj, buf, off, count,
+ PYRA_SIZE_PROFILE_BUTTONS,
+ PYRA_COMMAND_PROFILE_BUTTONS);
}
static ssize_t pyra_sysfs_write_settings(struct file *fp,
@@ -266,35 +230,32 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval = 0;
- int difference;
struct pyra_roccat_report roccat_report;
+ struct pyra_settings const *settings;
- if (off != 0 || count != sizeof(struct pyra_settings))
+ if (off != 0 || count != PYRA_SIZE_SETTINGS)
return -EINVAL;
mutex_lock(&pyra->pyra_lock);
- difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings));
- if (difference) {
- retval = pyra_set_settings(usb_dev,
- (struct pyra_settings const *)buf);
- if (retval) {
- mutex_unlock(&pyra->pyra_lock);
- return retval;
- }
-
- memcpy(&pyra->settings, buf,
- sizeof(struct pyra_settings));
- profile_activated(pyra, pyra->settings.startup_profile);
+ settings = (struct pyra_settings const *)buf;
- roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
- roccat_report.value = pyra->settings.startup_profile + 1;
- roccat_report.key = 0;
- roccat_report_event(pyra->chrdev_minor,
- (uint8_t const *)&roccat_report);
+ retval = pyra_set_settings(usb_dev, settings);
+ if (retval) {
+ mutex_unlock(&pyra->pyra_lock);
+ return retval;
}
+
+ profile_activated(pyra, settings->startup_profile);
+
+ roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
+ roccat_report.value = settings->startup_profile + 1;
+ roccat_report.key = 0;
+ roccat_report_event(pyra->chrdev_minor,
+ (uint8_t const *)&roccat_report);
+
mutex_unlock(&pyra->pyra_lock);
- return sizeof(struct pyra_settings);
+ return PYRA_SIZE_SETTINGS;
}
@@ -311,23 +272,34 @@ static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
{
struct pyra_device *pyra =
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
+ struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+ struct pyra_settings settings;
+
+ mutex_lock(&pyra->pyra_lock);
+ roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
+ &settings, PYRA_SIZE_SETTINGS);
+ mutex_unlock(&pyra->pyra_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
}
static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct pyra_device *pyra =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
-}
+ struct pyra_device *pyra;
+ struct usb_device *usb_dev;
+ struct pyra_info info;
-static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pyra_device *pyra =
- hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
- return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
+ dev = dev->parent->parent;
+ pyra = hid_get_drvdata(dev_get_drvdata(dev));
+ usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+ mutex_lock(&pyra->pyra_lock);
+ roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
+ &info, PYRA_SIZE_INFO);
+ mutex_unlock(&pyra->pyra_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
}
static struct device_attribute pyra_attributes[] = {
@@ -336,105 +308,88 @@ static struct device_attribute pyra_attributes[] = {
__ATTR(firmware_version, 0440,
pyra_sysfs_show_firmware_version, NULL),
__ATTR(startup_profile, 0440,
- pyra_sysfs_show_startup_profile, NULL),
+ pyra_sysfs_show_actual_profile, NULL),
__ATTR_NULL
};
static struct bin_attribute pyra_bin_attributes[] = {
- {
- .attr = { .name = "profile_settings", .mode = 0220 },
- .size = sizeof(struct pyra_profile_settings),
- .write = pyra_sysfs_write_profile_settings
- },
+ PYRA_BIN_ATTRIBUTE_W(control, CONTROL),
+ PYRA_BIN_ATTRIBUTE_RW(info, INFO),
+ PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+ PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
+ PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS),
{
.attr = { .name = "profile1_settings", .mode = 0440 },
- .size = sizeof(struct pyra_profile_settings),
+ .size = PYRA_SIZE_PROFILE_SETTINGS,
.read = pyra_sysfs_read_profilex_settings,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_settings", .mode = 0440 },
- .size = sizeof(struct pyra_profile_settings),
+ .size = PYRA_SIZE_PROFILE_SETTINGS,
.read = pyra_sysfs_read_profilex_settings,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_settings", .mode = 0440 },
- .size = sizeof(struct pyra_profile_settings),
+ .size = PYRA_SIZE_PROFILE_SETTINGS,
.read = pyra_sysfs_read_profilex_settings,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_settings", .mode = 0440 },
- .size = sizeof(struct pyra_profile_settings),
+ .size = PYRA_SIZE_PROFILE_SETTINGS,
.read = pyra_sysfs_read_profilex_settings,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_settings", .mode = 0440 },
- .size = sizeof(struct pyra_profile_settings),
+ .size = PYRA_SIZE_PROFILE_SETTINGS,
.read = pyra_sysfs_read_profilex_settings,
.private = &profile_numbers[4]
},
{
- .attr = { .name = "profile_buttons", .mode = 0220 },
- .size = sizeof(struct pyra_profile_buttons),
- .write = pyra_sysfs_write_profile_buttons
- },
- {
.attr = { .name = "profile1_buttons", .mode = 0440 },
- .size = sizeof(struct pyra_profile_buttons),
+ .size = PYRA_SIZE_PROFILE_BUTTONS,
.read = pyra_sysfs_read_profilex_buttons,
.private = &profile_numbers[0]
},
{
.attr = { .name = "profile2_buttons", .mode = 0440 },
- .size = sizeof(struct pyra_profile_buttons),
+ .size = PYRA_SIZE_PROFILE_BUTTONS,
.read = pyra_sysfs_read_profilex_buttons,
.private = &profile_numbers[1]
},
{
.attr = { .name = "profile3_buttons", .mode = 0440 },
- .size = sizeof(struct pyra_profile_buttons),
+ .size = PYRA_SIZE_PROFILE_BUTTONS,
.read = pyra_sysfs_read_profilex_buttons,
.private = &profile_numbers[2]
},
{
.attr = { .name = "profile4_buttons", .mode = 0440 },
- .size = sizeof(struct pyra_profile_buttons),
+ .size = PYRA_SIZE_PROFILE_BUTTONS,
.read = pyra_sysfs_read_profilex_buttons,
.private = &profile_numbers[3]
},
{
.attr = { .name = "profile5_buttons", .mode = 0440 },
- .size = sizeof(struct pyra_profile_buttons),
+ .size = PYRA_SIZE_PROFILE_BUTTONS,
.read = pyra_sysfs_read_profilex_buttons,
.private = &profile_numbers[4]
},
- {
- .attr = { .name = "settings", .mode = 0660 },
- .size = sizeof(struct pyra_settings),
- .read = pyra_sysfs_read_settings,
- .write = pyra_sysfs_write_settings
- },
__ATTR_NULL
};
static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
struct pyra_device *pyra)
{
- struct pyra_info info;
+ struct pyra_settings settings;
int retval, i;
mutex_init(&pyra->pyra_lock);
- retval = pyra_get_info(usb_dev, &info);
- if (retval)
- return retval;
-
- pyra->firmware_version = info.firmware_version;
-
- retval = pyra_get_settings(usb_dev, &pyra->settings);
+ retval = pyra_get_settings(usb_dev, &settings);
if (retval)
return retval;
@@ -443,14 +398,9 @@ static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
&pyra->profile_settings[i], i);
if (retval)
return retval;
-
- retval = pyra_get_profile_buttons(usb_dev,
- &pyra->profile_buttons[i], i);
- if (retval)
- return retval;
}
- profile_activated(pyra, pyra->settings.startup_profile);
+ profile_activated(pyra, settings.startup_profile);
return 0;
}
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
index eada7830fa99..beedcf001ceb 100644
--- a/drivers/hid/hid-roccat-pyra.h
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -14,11 +14,13 @@
#include <linux/types.h>
-struct pyra_b {
- uint8_t command; /* PYRA_COMMAND_B */
- uint8_t size; /* always 3 */
- uint8_t unknown; /* 1 */
-} __attribute__ ((__packed__));
+enum {
+ PYRA_SIZE_CONTROL = 0x03,
+ PYRA_SIZE_INFO = 0x06,
+ PYRA_SIZE_PROFILE_SETTINGS = 0x0d,
+ PYRA_SIZE_PROFILE_BUTTONS = 0x13,
+ PYRA_SIZE_SETTINGS = 0x03,
+};
enum pyra_control_requests {
PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -46,14 +48,6 @@ struct pyra_profile_settings {
uint16_t checksum; /* byte sum */
} __attribute__ ((__packed__));
-struct pyra_profile_buttons {
- uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
- uint8_t size; /* always 0x13 */
- uint8_t number; /* Range 0-4 */
- uint8_t buttons[14];
- uint16_t checksum; /* byte sum */
-} __attribute__ ((__packed__));
-
struct pyra_info {
uint8_t command; /* PYRA_COMMAND_INFO */
uint8_t size; /* always 6 */
@@ -64,6 +58,7 @@ struct pyra_info {
} __attribute__ ((__packed__));
enum pyra_commands {
+ PYRA_COMMAND_CONTROL = 0x4,
PYRA_COMMAND_SETTINGS = 0x5,
PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
@@ -148,13 +143,10 @@ struct pyra_roccat_report {
struct pyra_device {
int actual_profile;
int actual_cpi;
- int firmware_version;
int roccat_claimed;
int chrdev_minor;
struct mutex pyra_lock;
- struct pyra_settings settings;
struct pyra_profile_settings profile_settings[5];
- struct pyra_profile_buttons profile_buttons[5];
};
#endif
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c
index 014afba407e0..31747a29c093 100644
--- a/drivers/hid/hid-roccat-savu.c
+++ b/drivers/hid/hid-roccat-savu.c
@@ -120,7 +120,7 @@ SAVU_SYSFS_RW(profile, PROFILE)
SAVU_SYSFS_RW(general, GENERAL)
SAVU_SYSFS_RW(buttons, BUTTONS)
SAVU_SYSFS_RW(macro, MACRO)
-SAVU_SYSFS_R(info, INFO)
+SAVU_SYSFS_RW(info, INFO)
SAVU_SYSFS_RW(sensor, SENSOR)
static struct bin_attribute savu_bin_attributes[] = {
@@ -129,7 +129,7 @@ static struct bin_attribute savu_bin_attributes[] = {
SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
- SAVU_BIN_ATTRIBUTE_R(info, INFO),
+ SAVU_BIN_ATTRIBUTE_RW(info, INFO),
SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
__ATTR_NULL
};
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index d9d73e9163eb..0bc58bd8d4f5 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -82,23 +82,6 @@ struct hid_sensor_hub_callbacks_list {
void *priv;
};
-static int sensor_hub_check_for_sensor_page(struct hid_device *hdev)
-{
- int i;
- int ret = -EINVAL;
-
- for (i = 0; i < hdev->maxcollection; i++) {
- struct hid_collection *col = &hdev->collection[i];
- if (col->type == HID_COLLECTION_PHYSICAL &&
- (col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) {
- ret = 0;
- break;
- }
- }
-
- return ret;
-}
-
static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
int dir)
{
@@ -437,9 +420,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
ptr = raw_data;
ptr++; /*Skip report id*/
- if (!report)
- goto err_report;
-
spin_lock_irqsave(&pdata->lock, flags);
for (i = 0; i < report->maxfield; ++i) {
@@ -485,7 +465,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
callback->pdev);
spin_unlock_irqrestore(&pdata->lock, flags);
-err_report:
return 1;
}
@@ -524,10 +503,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
hid_err(hdev, "parse failed\n");
goto err_free;
}
- if (sensor_hub_check_for_sensor_page(hdev) < 0) {
- hid_err(hdev, "sensor page not found\n");
- goto err_free;
- }
INIT_LIST_HEAD(&hdev->inputs);
ret = hid_hw_start(hdev, 0);
@@ -630,16 +605,7 @@ static void sensor_hub_remove(struct hid_device *hdev)
}
static const struct hid_device_id sensor_hub_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
- USB_DEVICE_ID_SENSOR_HUB_1020) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
- USB_DEVICE_ID_SENSOR_HUB_1020) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
- USB_DEVICE_ID_SENSOR_HUB_09FA) },
- { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
- USB_DEVICE_ID_SENSOR_HUB_09FA) },
- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
- USB_DEVICE_ID_SENSOR_HUB_7014) },
+ { HID_DEVICE(BUS_USB, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) },
{ }
};
MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7c47fc3f7b2b..413a73187d33 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
ret = -EIO;
break;
}
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
/* allow O_NONBLOCK to work well from other threads */
mutex_unlock(&list->read_mutex);
@@ -295,6 +295,13 @@ out:
}
+static int hidraw_fasync(int fd, struct file *file, int on)
+{
+ struct hidraw_list *list = file->private_data;
+
+ return fasync_helper(fd, file, on, &list->fasync);
+}
+
static int hidraw_release(struct inode * inode, struct file * file)
{
unsigned int minor = iminor(inode);
@@ -438,6 +445,7 @@ static const struct file_operations hidraw_ops = {
.open = hidraw_open,
.release = hidraw_release,
.unlocked_ioctl = hidraw_ioctl,
+ .fasync = hidraw_fasync,
#ifdef CONFIG_COMPAT
.compat_ioctl = hidraw_ioctl,
#endif
diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig
new file mode 100644
index 000000000000..b66617a020bd
--- /dev/null
+++ b/drivers/hid/i2c-hid/Kconfig
@@ -0,0 +1,18 @@
+menu "I2C HID support"
+ depends on I2C
+
+config I2C_HID
+ tristate "HID over I2C transport layer"
+ default n
+ depends on I2C && INPUT
+ select HID
+ ---help---
+ Say Y here if you use a keyboard, a touchpad, a touchscreen, or any
+ other HID based devices which is connected to your computer via I2C.
+
+ If unsure, say N.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-hid.
+
+endmenu
diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
new file mode 100644
index 000000000000..832d8f9aaba2
--- /dev/null
+++ b/drivers/hid/i2c-hid/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the I2C input drivers
+#
+
+obj-$(CONFIG_I2C_HID) += i2c-hid.o
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
new file mode 100644
index 000000000000..9ef222442ca0
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -0,0 +1,979 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ * Copyright (c) 2012 Red Hat, Inc
+ *
+ * This code is partly based on "USB HID support for Linux":
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2007-2008 Oliver Neukum
+ * Copyright (c) 2006-2010 Jiri Kosina
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/hid.h>
+#include <linux/mutex.h>
+
+#include <linux/i2c/i2c-hid.h>
+
+/* flags */
+#define I2C_HID_STARTED (1 << 0)
+#define I2C_HID_RESET_PENDING (1 << 1)
+#define I2C_HID_READ_PENDING (1 << 2)
+
+#define I2C_HID_PWR_ON 0x00
+#define I2C_HID_PWR_SLEEP 0x01
+
+/* debug option */
+static bool debug;
+module_param(debug, bool, 0444);
+MODULE_PARM_DESC(debug, "print a lot of debug information");
+
+#define i2c_hid_dbg(ihid, fmt, arg...) \
+do { \
+ if (debug) \
+ dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg); \
+} while (0)
+
+struct i2c_hid_desc {
+ __le16 wHIDDescLength;
+ __le16 bcdVersion;
+ __le16 wReportDescLength;
+ __le16 wReportDescRegister;
+ __le16 wInputRegister;
+ __le16 wMaxInputLength;
+ __le16 wOutputRegister;
+ __le16 wMaxOutputLength;
+ __le16 wCommandRegister;
+ __le16 wDataRegister;
+ __le16 wVendorID;
+ __le16 wProductID;
+ __le16 wVersionID;
+ __le32 reserved;
+} __packed;
+
+struct i2c_hid_cmd {
+ unsigned int registerIndex;
+ __u8 opcode;
+ unsigned int length;
+ bool wait;
+};
+
+union command {
+ u8 data[0];
+ struct cmd {
+ __le16 reg;
+ __u8 reportTypeID;
+ __u8 opcode;
+ } __packed c;
+};
+
+#define I2C_HID_CMD(opcode_) \
+ .opcode = opcode_, .length = 4, \
+ .registerIndex = offsetof(struct i2c_hid_desc, wCommandRegister)
+
+/* fetch HID descriptor */
+static const struct i2c_hid_cmd hid_descr_cmd = { .length = 2 };
+/* fetch report descriptors */
+static const struct i2c_hid_cmd hid_report_descr_cmd = {
+ .registerIndex = offsetof(struct i2c_hid_desc,
+ wReportDescRegister),
+ .opcode = 0x00,
+ .length = 2 };
+/* commands */
+static const struct i2c_hid_cmd hid_reset_cmd = { I2C_HID_CMD(0x01),
+ .wait = true };
+static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) };
+static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) };
+static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) };
+
+/*
+ * These definitions are not used here, but are defined by the spec.
+ * Keeping them here for documentation purposes.
+ *
+ * static const struct i2c_hid_cmd hid_get_idle_cmd = { I2C_HID_CMD(0x04) };
+ * static const struct i2c_hid_cmd hid_set_idle_cmd = { I2C_HID_CMD(0x05) };
+ * static const struct i2c_hid_cmd hid_get_protocol_cmd = { I2C_HID_CMD(0x06) };
+ * static const struct i2c_hid_cmd hid_set_protocol_cmd = { I2C_HID_CMD(0x07) };
+ */
+
+static DEFINE_MUTEX(i2c_hid_open_mut);
+
+/* The main device structure */
+struct i2c_hid {
+ struct i2c_client *client; /* i2c client */
+ struct hid_device *hid; /* pointer to corresponding HID dev */
+ union {
+ __u8 hdesc_buffer[sizeof(struct i2c_hid_desc)];
+ struct i2c_hid_desc hdesc; /* the HID Descriptor */
+ };
+ __le16 wHIDDescRegister; /* location of the i2c
+ * register of the HID
+ * descriptor. */
+ unsigned int bufsize; /* i2c buffer size */
+ char *inbuf; /* Input buffer */
+ char *cmdbuf; /* Command buffer */
+ char *argsbuf; /* Command arguments buffer */
+
+ unsigned long flags; /* device flags */
+
+ wait_queue_head_t wait; /* For waiting the interrupt */
+};
+
+static int __i2c_hid_command(struct i2c_client *client,
+ const struct i2c_hid_cmd *command, u8 reportID,
+ u8 reportType, u8 *args, int args_len,
+ unsigned char *buf_recv, int data_len)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ union command *cmd = (union command *)ihid->cmdbuf;
+ int ret;
+ struct i2c_msg msg[2];
+ int msg_num = 1;
+
+ int length = command->length;
+ bool wait = command->wait;
+ unsigned int registerIndex = command->registerIndex;
+
+ /* special case for hid_descr_cmd */
+ if (command == &hid_descr_cmd) {
+ cmd->c.reg = ihid->wHIDDescRegister;
+ } else {
+ cmd->data[0] = ihid->hdesc_buffer[registerIndex];
+ cmd->data[1] = ihid->hdesc_buffer[registerIndex + 1];
+ }
+
+ if (length > 2) {
+ cmd->c.opcode = command->opcode;
+ cmd->c.reportTypeID = reportID | reportType << 4;
+ }
+
+ memcpy(cmd->data + length, args, args_len);
+ length += args_len;
+
+ i2c_hid_dbg(ihid, "%s: cmd=%*ph\n", __func__, length, cmd->data);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags & I2C_M_TEN;
+ msg[0].len = length;
+ msg[0].buf = cmd->data;
+ if (data_len > 0) {
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags & I2C_M_TEN;
+ msg[1].flags |= I2C_M_RD;
+ msg[1].len = data_len;
+ msg[1].buf = buf_recv;
+ msg_num = 2;
+ set_bit(I2C_HID_READ_PENDING, &ihid->flags);
+ }
+
+ if (wait)
+ set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+
+ ret = i2c_transfer(client->adapter, msg, msg_num);
+
+ if (data_len > 0)
+ clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
+
+ if (ret != msg_num)
+ return ret < 0 ? ret : -EIO;
+
+ ret = 0;
+
+ if (wait) {
+ i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
+ if (!wait_event_timeout(ihid->wait,
+ !test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
+ msecs_to_jiffies(5000)))
+ ret = -ENODATA;
+ i2c_hid_dbg(ihid, "%s: finished.\n", __func__);
+ }
+
+ return ret;
+}
+
+static int i2c_hid_command(struct i2c_client *client,
+ const struct i2c_hid_cmd *command,
+ unsigned char *buf_recv, int data_len)
+{
+ return __i2c_hid_command(client, command, 0, 0, NULL, 0,
+ buf_recv, data_len);
+}
+
+static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
+ u8 reportID, unsigned char *buf_recv, int data_len)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ u8 args[3];
+ int ret;
+ int args_len = 0;
+ u16 readRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+ i2c_hid_dbg(ihid, "%s\n", __func__);
+
+ if (reportID >= 0x0F) {
+ args[args_len++] = reportID;
+ reportID = 0x0F;
+ }
+
+ args[args_len++] = readRegister & 0xFF;
+ args[args_len++] = readRegister >> 8;
+
+ ret = __i2c_hid_command(client, &hid_get_report_cmd, reportID,
+ reportType, args, args_len, buf_recv, data_len);
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to retrieve report from device.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
+ u8 reportID, unsigned char *buf, size_t data_len)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ u8 *args = ihid->argsbuf;
+ int ret;
+ u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+ /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
+ u16 size = 2 /* size */ +
+ (reportID ? 1 : 0) /* reportID */ +
+ data_len /* buf */;
+ int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
+ 2 /* dataRegister */ +
+ size /* args */;
+ int index = 0;
+
+ i2c_hid_dbg(ihid, "%s\n", __func__);
+
+ if (reportID >= 0x0F) {
+ args[index++] = reportID;
+ reportID = 0x0F;
+ }
+
+ args[index++] = dataRegister & 0xFF;
+ args[index++] = dataRegister >> 8;
+
+ args[index++] = size & 0xFF;
+ args[index++] = size >> 8;
+
+ if (reportID)
+ args[index++] = reportID;
+
+ memcpy(&args[index], buf, data_len);
+
+ ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID,
+ reportType, args, args_len, NULL, 0);
+ if (ret) {
+ dev_err(&client->dev, "failed to set a report to device.\n");
+ return ret;
+ }
+
+ return data_len;
+}
+
+static int i2c_hid_set_power(struct i2c_client *client, int power_state)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret;
+
+ i2c_hid_dbg(ihid, "%s\n", __func__);
+
+ ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
+ 0, NULL, 0, NULL, 0);
+ if (ret)
+ dev_err(&client->dev, "failed to change power setting.\n");
+
+ return ret;
+}
+
+static int i2c_hid_hwreset(struct i2c_client *client)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret;
+
+ i2c_hid_dbg(ihid, "%s\n", __func__);
+
+ ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+ if (ret)
+ return ret;
+
+ i2c_hid_dbg(ihid, "resetting...\n");
+
+ ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
+ if (ret) {
+ dev_err(&client->dev, "failed to reset device.\n");
+ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void i2c_hid_get_input(struct i2c_hid *ihid)
+{
+ int ret, ret_size;
+ int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
+
+ ret = i2c_master_recv(ihid->client, ihid->inbuf, size);
+ if (ret != size) {
+ if (ret < 0)
+ return;
+
+ dev_err(&ihid->client->dev, "%s: got %d data instead of %d\n",
+ __func__, ret, size);
+ return;
+ }
+
+ ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8;
+
+ if (!ret_size) {
+ /* host or device initiated RESET completed */
+ if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags))
+ wake_up(&ihid->wait);
+ return;
+ }
+
+ if (ret_size > size) {
+ dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+ __func__, size, ret_size);
+ return;
+ }
+
+ i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
+
+ if (test_bit(I2C_HID_STARTED, &ihid->flags))
+ hid_input_report(ihid->hid, HID_INPUT_REPORT, ihid->inbuf + 2,
+ ret_size - 2, 1);
+
+ return;
+}
+
+static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
+{
+ struct i2c_hid *ihid = dev_id;
+
+ if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
+ return IRQ_HANDLED;
+
+ i2c_hid_get_input(ihid);
+
+ return IRQ_HANDLED;
+}
+
+static int i2c_hid_get_report_length(struct hid_report *report)
+{
+ return ((report->size - 1) >> 3) + 1 +
+ report->device->report_enum[report->type].numbered + 2;
+}
+
+static void i2c_hid_init_report(struct hid_report *report, u8 *buffer,
+ size_t bufsize)
+{
+ struct hid_device *hid = report->device;
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ unsigned int size, ret_size;
+
+ size = i2c_hid_get_report_length(report);
+ if (i2c_hid_get_report(client,
+ report->type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+ report->id, buffer, size))
+ return;
+
+ i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf);
+
+ ret_size = buffer[0] | (buffer[1] << 8);
+
+ if (ret_size != size) {
+ dev_err(&client->dev, "error in %s size:%d / ret_size:%d\n",
+ __func__, size, ret_size);
+ return;
+ }
+
+ /* hid->driver_lock is held as we are in probe function,
+ * we just need to setup the input fields, so using
+ * hid_report_raw_event is safe. */
+ hid_report_raw_event(hid, report->type, buffer + 2, size - 2, 1);
+}
+
+/*
+ * Initialize all reports
+ */
+static void i2c_hid_init_reports(struct hid_device *hid)
+{
+ struct hid_report *report;
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ u8 *inbuf = kzalloc(ihid->bufsize, GFP_KERNEL);
+
+ if (!inbuf) {
+ dev_err(&client->dev, "can not retrieve initial reports\n");
+ return;
+ }
+
+ list_for_each_entry(report,
+ &hid->report_enum[HID_INPUT_REPORT].report_list, list)
+ i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+ list_for_each_entry(report,
+ &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
+ i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+ kfree(inbuf);
+}
+
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type,
+ unsigned int *max)
+{
+ struct hid_report *report;
+ unsigned int size;
+
+ /* We should not rely on wMaxInputLength, as some devices may set it to
+ * a wrong length. */
+ list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+ size = i2c_hid_get_report_length(report);
+ if (*max < size)
+ *max = size;
+ }
+}
+
+static void i2c_hid_free_buffers(struct i2c_hid *ihid)
+{
+ kfree(ihid->inbuf);
+ kfree(ihid->argsbuf);
+ kfree(ihid->cmdbuf);
+ ihid->inbuf = NULL;
+ ihid->cmdbuf = NULL;
+ ihid->argsbuf = NULL;
+ ihid->bufsize = 0;
+}
+
+static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size)
+{
+ /* the worst case is computed from the set_report command with a
+ * reportID > 15 and the maximum report length */
+ int args_len = sizeof(__u8) + /* optional ReportID byte */
+ sizeof(__u16) + /* data register */
+ sizeof(__u16) + /* size of the report */
+ report_size; /* report */
+
+ ihid->inbuf = kzalloc(report_size, GFP_KERNEL);
+ ihid->argsbuf = kzalloc(args_len, GFP_KERNEL);
+ ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL);
+
+ if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) {
+ i2c_hid_free_buffers(ihid);
+ return -ENOMEM;
+ }
+
+ ihid->bufsize = report_size;
+
+ return 0;
+}
+
+static int i2c_hid_get_raw_report(struct hid_device *hid,
+ unsigned char report_number, __u8 *buf, size_t count,
+ unsigned char report_type)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ size_t ret_count, ask_count;
+ int ret;
+
+ if (report_type == HID_OUTPUT_REPORT)
+ return -EINVAL;
+
+ /* +2 bytes to include the size of the reply in the query buffer */
+ ask_count = min(count + 2, (size_t)ihid->bufsize);
+
+ ret = i2c_hid_get_report(client,
+ report_type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+ report_number, ihid->inbuf, ask_count);
+
+ if (ret < 0)
+ return ret;
+
+ ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8);
+
+ if (ret_count <= 2)
+ return 0;
+
+ ret_count = min(ret_count, ask_count);
+
+ /* The query buffer contains the size, dropping it in the reply */
+ count = min(count, ret_count - 2);
+ memcpy(buf, ihid->inbuf + 2, count);
+
+ return count;
+}
+
+static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
+ size_t count, unsigned char report_type)
+{
+ struct i2c_client *client = hid->driver_data;
+ int report_id = buf[0];
+
+ if (report_type == HID_INPUT_REPORT)
+ return -EINVAL;
+
+ return i2c_hid_set_report(client,
+ report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
+ report_id, buf, count);
+}
+
+static int i2c_hid_parse(struct hid_device *hid)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ struct i2c_hid_desc *hdesc = &ihid->hdesc;
+ unsigned int rsize;
+ char *rdesc;
+ int ret;
+ int tries = 3;
+
+ i2c_hid_dbg(ihid, "entering %s\n", __func__);
+
+ rsize = le16_to_cpu(hdesc->wReportDescLength);
+ if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+ dbg_hid("weird size of report descriptor (%u)\n", rsize);
+ return -EINVAL;
+ }
+
+ do {
+ ret = i2c_hid_hwreset(client);
+ if (ret)
+ msleep(1000);
+ } while (tries-- > 0 && ret);
+
+ if (ret)
+ return ret;
+
+ rdesc = kzalloc(rsize, GFP_KERNEL);
+
+ if (!rdesc) {
+ dbg_hid("couldn't allocate rdesc memory\n");
+ return -ENOMEM;
+ }
+
+ i2c_hid_dbg(ihid, "asking HID report descriptor\n");
+
+ ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize);
+ if (ret) {
+ hid_err(hid, "reading report descriptor failed\n");
+ kfree(rdesc);
+ return -EIO;
+ }
+
+ i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
+
+ ret = hid_parse_report(hid, rdesc, rsize);
+ kfree(rdesc);
+ if (ret) {
+ dbg_hid("parsing report descriptor failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int i2c_hid_start(struct hid_device *hid)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret;
+ unsigned int bufsize = HID_MIN_BUFFER_SIZE;
+
+ i2c_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize);
+ i2c_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize);
+ i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize);
+
+ if (bufsize > ihid->bufsize) {
+ i2c_hid_free_buffers(ihid);
+
+ ret = i2c_hid_alloc_buffers(ihid, bufsize);
+
+ if (ret)
+ return ret;
+ }
+
+ if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+ i2c_hid_init_reports(hid);
+
+ return 0;
+}
+
+static void i2c_hid_stop(struct hid_device *hid)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+ hid->claimed = 0;
+
+ i2c_hid_free_buffers(ihid);
+}
+
+static int i2c_hid_open(struct hid_device *hid)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret = 0;
+
+ mutex_lock(&i2c_hid_open_mut);
+ if (!hid->open++) {
+ ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+ if (ret) {
+ hid->open--;
+ goto done;
+ }
+ set_bit(I2C_HID_STARTED, &ihid->flags);
+ }
+done:
+ mutex_unlock(&i2c_hid_open_mut);
+ return ret;
+}
+
+static void i2c_hid_close(struct hid_device *hid)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+ /* protecting hid->open to make sure we don't restart
+ * data acquistion due to a resumption we no longer
+ * care about
+ */
+ mutex_lock(&i2c_hid_open_mut);
+ if (!--hid->open) {
+ clear_bit(I2C_HID_STARTED, &ihid->flags);
+
+ /* Save some power */
+ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+ }
+ mutex_unlock(&i2c_hid_open_mut);
+}
+
+static int i2c_hid_power(struct hid_device *hid, int lvl)
+{
+ struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret = 0;
+
+ i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
+
+ switch (lvl) {
+ case PM_HINT_FULLON:
+ ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+ break;
+ case PM_HINT_NORMAL:
+ ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+ break;
+ }
+ return ret;
+}
+
+static int i2c_hid_hidinput_input_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct hid_field *field;
+ int offset;
+
+ if (type == EV_FF)
+ return input_ff_event(dev, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ offset = hidinput_find_field(hid, type, code, &field);
+
+ if (offset == -1) {
+ hid_warn(dev, "event field not found\n");
+ return -1;
+ }
+
+ return hid_set_field(field, offset, value);
+}
+
+static struct hid_ll_driver i2c_hid_ll_driver = {
+ .parse = i2c_hid_parse,
+ .start = i2c_hid_start,
+ .stop = i2c_hid_stop,
+ .open = i2c_hid_open,
+ .close = i2c_hid_close,
+ .power = i2c_hid_power,
+ .hidinput_input_event = i2c_hid_hidinput_input_event,
+};
+
+static int __devinit i2c_hid_init_irq(struct i2c_client *client)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ int ret;
+
+ dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
+
+ ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->name, ihid);
+ if (ret < 0) {
+ dev_warn(&client->dev,
+ "Could not register for %s interrupt, irq = %d,"
+ " ret = %d\n",
+ client->name, client->irq, ret);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
+{
+ struct i2c_client *client = ihid->client;
+ struct i2c_hid_desc *hdesc = &ihid->hdesc;
+ unsigned int dsize;
+ int ret;
+
+ /* Fetch the length of HID description, retrieve the 4 first bytes:
+ * bytes 0-1 -> length
+ * bytes 2-3 -> bcdVersion (has to be 1.00) */
+ ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
+
+ i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n",
+ __func__, 4, ihid->hdesc_buffer);
+
+ if (ret) {
+ dev_err(&client->dev,
+ "unable to fetch the size of HID descriptor (ret=%d)\n",
+ ret);
+ return -ENODEV;
+ }
+
+ dsize = le16_to_cpu(hdesc->wHIDDescLength);
+ /*
+ * the size of the HID descriptor should at least contain
+ * its size and the bcdVersion (4 bytes), and should not be greater
+ * than sizeof(struct i2c_hid_desc) as we directly fill this struct
+ * through i2c_hid_command.
+ */
+ if (dsize < 4 || dsize > sizeof(struct i2c_hid_desc)) {
+ dev_err(&client->dev, "weird size of HID descriptor (%u)\n",
+ dsize);
+ return -ENODEV;
+ }
+
+ /* check bcdVersion == 1.0 */
+ if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) {
+ dev_err(&client->dev,
+ "unexpected HID descriptor bcdVersion (0x%04hx)\n",
+ le16_to_cpu(hdesc->bcdVersion));
+ return -ENODEV;
+ }
+
+ i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
+
+ ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
+ dsize);
+ if (ret) {
+ dev_err(&client->dev, "hid_descr_cmd Fail\n");
+ return -ENODEV;
+ }
+
+ i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer);
+
+ return 0;
+}
+
+static int __devinit i2c_hid_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int ret;
+ struct i2c_hid *ihid;
+ struct hid_device *hid;
+ __u16 hidRegister;
+ struct i2c_hid_platform_data *platform_data = client->dev.platform_data;
+
+ dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
+
+ if (!platform_data) {
+ dev_err(&client->dev, "HID register address not provided\n");
+ return -EINVAL;
+ }
+
+ if (!client->irq) {
+ dev_err(&client->dev,
+ "HID over i2c has not been provided an Int IRQ\n");
+ return -EINVAL;
+ }
+
+ ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+ if (!ihid)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, ihid);
+
+ ihid->client = client;
+
+ hidRegister = platform_data->hid_descriptor_address;
+ ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
+
+ init_waitqueue_head(&ihid->wait);
+
+ /* we need to allocate the command buffer without knowing the maximum
+ * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the
+ * real computation later. */
+ ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_hid_fetch_hid_descriptor(ihid);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_hid_init_irq(client);
+ if (ret < 0)
+ goto err;
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid)) {
+ ret = PTR_ERR(hid);
+ goto err_irq;
+ }
+
+ ihid->hid = hid;
+
+ hid->driver_data = client;
+ hid->ll_driver = &i2c_hid_ll_driver;
+ hid->hid_get_raw_report = i2c_hid_get_raw_report;
+ hid->hid_output_raw_report = i2c_hid_output_raw_report;
+ hid->dev.parent = &client->dev;
+ hid->bus = BUS_I2C;
+ hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
+ hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
+ hid->product = le16_to_cpu(ihid->hdesc.wProductID);
+
+ snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
+ client->name, hid->vendor, hid->product);
+
+ ret = hid_add_device(hid);
+ if (ret) {
+ if (ret != -ENODEV)
+ hid_err(client, "can't add hid device: %d\n", ret);
+ goto err_mem_free;
+ }
+
+ return 0;
+
+err_mem_free:
+ hid_destroy_device(hid);
+
+err_irq:
+ free_irq(client->irq, ihid);
+
+err:
+ i2c_hid_free_buffers(ihid);
+ kfree(ihid);
+ return ret;
+}
+
+static int __devexit i2c_hid_remove(struct i2c_client *client)
+{
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ struct hid_device *hid;
+
+ hid = ihid->hid;
+ hid_destroy_device(hid);
+
+ free_irq(client->irq, ihid);
+
+ if (ihid->bufsize)
+ i2c_hid_free_buffers(ihid);
+
+ kfree(ihid);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int i2c_hid_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ if (device_may_wakeup(&client->dev))
+ enable_irq_wake(client->irq);
+
+ /* Save some power */
+ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+
+ return 0;
+}
+
+static int i2c_hid_resume(struct device *dev)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ ret = i2c_hid_hwreset(client);
+ if (ret)
+ return ret;
+
+ if (device_may_wakeup(&client->dev))
+ disable_irq_wake(client->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+
+static const struct i2c_device_id i2c_hid_id_table[] = {
+ { "hid", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table);
+
+
+static struct i2c_driver i2c_hid_driver = {
+ .driver = {
+ .name = "i2c_hid",
+ .owner = THIS_MODULE,
+ .pm = &i2c_hid_pm,
+ },
+
+ .probe = i2c_hid_probe,
+ .remove = __devexit_p(i2c_hid_remove),
+
+ .id_table = i2c_hid_id_table,
+};
+
+module_i2c_driver(i2c_hid_driver);
+
+MODULE_DESCRIPTION("HID over I2C core driver");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 11c7932dc7e6..ac9e35228254 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -72,6 +72,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
@@ -79,9 +80,11 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
{ 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_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 },
+ { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 14599e256791..87bd64959a91 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -361,10 +361,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
@@ -373,6 +369,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
retval = -EIO;
break;
}
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
/* let O_NONBLOCK tasks run */
mutex_unlock(&list->thread_lock);
@@ -625,7 +625,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case HIDIOCAPPLICATION:
- if (arg < 0 || arg >= hid->maxapplication)
+ if (arg >= hid->maxapplication)
break;
for (i = 0; i < hid->maxcollection; i++)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4800d4c2a7b7..32f238f3caea 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1208,6 +1208,14 @@ config SENSORS_TWL4030_MADC
This driver can also be built as a module. If so it will be called
twl4030-madc-hwmon.
+config SENSORS_VEXPRESS
+ tristate "Versatile Express"
+ depends on VEXPRESS_CONFIG
+ help
+ This driver provides support for hardware sensors available on
+ the ARM Ltd's Versatile Express platform. It can provide wide
+ range of information like temperature, power, energy.
+
config SENSORS_VIA_CPUTEMP
tristate "VIA CPU temperature sensor"
depends on X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index a930f0997d25..5da287443f6c 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
+obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
new file mode 100644
index 000000000000..59fd1268e58a
--- /dev/null
+++ b/drivers/hwmon/vexpress.c
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-hwmon"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/vexpress.h>
+
+struct vexpress_hwmon_data {
+ struct device *hwmon_dev;
+ struct vexpress_config_func *func;
+};
+
+static ssize_t vexpress_hwmon_name_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ const char *compatible = of_get_property(dev->of_node, "compatible",
+ NULL);
+
+ return sprintf(buffer, "%s\n", compatible);
+}
+
+static ssize_t vexpress_hwmon_label_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ const char *label = of_get_property(dev->of_node, "label", NULL);
+
+ if (!label)
+ return -ENOENT;
+
+ return snprintf(buffer, PAGE_SIZE, "%s\n", label);
+}
+
+static ssize_t vexpress_hwmon_u32_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+ int err;
+ u32 value;
+
+ err = vexpress_config_read(data->func, 0, &value);
+ if (err)
+ return err;
+
+ return snprintf(buffer, PAGE_SIZE, "%u\n", value /
+ to_sensor_dev_attr(dev_attr)->index);
+}
+
+static ssize_t vexpress_hwmon_u64_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buffer)
+{
+ struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+ int err;
+ u32 value_hi, value_lo;
+
+ err = vexpress_config_read(data->func, 0, &value_lo);
+ if (err)
+ return err;
+
+ err = vexpress_config_read(data->func, 1, &value_hi);
+ if (err)
+ return err;
+
+ return snprintf(buffer, PAGE_SIZE, "%llu\n",
+ div_u64(((u64)value_hi << 32) | value_lo,
+ to_sensor_dev_attr(dev_attr)->index));
+}
+
+static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
+
+#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \
+struct attribute *vexpress_hwmon_attrs_##_name[] = { \
+ &dev_attr_name.attr, \
+ &dev_attr_##_label_attr.attr, \
+ &sensor_dev_attr_##_input_attr.dev_attr.attr, \
+ NULL \
+}
+
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
+ NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input);
+static struct attribute_group vexpress_hwmon_group_volt = {
+ .attrs = vexpress_hwmon_attrs_volt,
+};
+#endif
+
+static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
+ NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input);
+static struct attribute_group vexpress_hwmon_group_amp = {
+ .attrs = vexpress_hwmon_attrs_amp,
+};
+
+static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
+ NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input);
+static struct attribute_group vexpress_hwmon_group_temp = {
+ .attrs = vexpress_hwmon_attrs_temp,
+};
+
+static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
+ NULL, 1);
+static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input);
+static struct attribute_group vexpress_hwmon_group_power = {
+ .attrs = vexpress_hwmon_attrs_power,
+};
+
+static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
+ NULL, 1);
+static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input);
+static struct attribute_group vexpress_hwmon_group_energy = {
+ .attrs = vexpress_hwmon_attrs_energy,
+};
+
+static struct of_device_id vexpress_hwmon_of_match[] = {
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+ {
+ .compatible = "arm,vexpress-volt",
+ .data = &vexpress_hwmon_group_volt,
+ },
+#endif
+ {
+ .compatible = "arm,vexpress-amp",
+ .data = &vexpress_hwmon_group_amp,
+ }, {
+ .compatible = "arm,vexpress-temp",
+ .data = &vexpress_hwmon_group_temp,
+ }, {
+ .compatible = "arm,vexpress-power",
+ .data = &vexpress_hwmon_group_power,
+ }, {
+ .compatible = "arm,vexpress-energy",
+ .data = &vexpress_hwmon_group_energy,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
+
+static int vexpress_hwmon_probe(struct platform_device *pdev)
+{
+ int err;
+ const struct of_device_id *match;
+ struct vexpress_hwmon_data *data;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, data);
+
+ match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ data->func = vexpress_config_func_get_by_dev(&pdev->dev);
+ if (!data->func)
+ return -ENODEV;
+
+ err = sysfs_create_group(&pdev->dev.kobj, match->data);
+ if (err)
+ goto error;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ sysfs_remove_group(&pdev->dev.kobj, match->data);
+ vexpress_config_func_put(data->func);
+ return err;
+}
+
+static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
+{
+ struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
+ const struct of_device_id *match;
+
+ hwmon_device_unregister(data->hwmon_dev);
+
+ match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
+ sysfs_remove_group(&pdev->dev.kobj, match->data);
+
+ vexpress_config_func_put(data->func);
+
+ return 0;
+}
+
+static struct platform_driver vexpress_hwmon_driver = {
+ .probe = vexpress_hwmon_probe,
+ .remove = __devexit_p(vexpress_hwmon_remove),
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = vexpress_hwmon_of_match,
+ },
+};
+
+module_platform_driver(vexpress_hwmon_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-hwmon");
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index f41502ef3f55..a23b91b0b738 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -304,7 +304,7 @@ retry_write:
case STATE_READ:
/* we have a byte of data in the data register, do
- * something with it, and then work out wether we are
+ * something with it, and then work out whether we are
* going to do any more read/write
*/
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9d902725bac9..b33d95ebc890 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -208,7 +208,7 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
- /* todo - check for wether ack wanted or not */
+ /* todo - check for whether ack wanted or not */
s3c24xx_i2c_enable_ack(i2c);
iiccon = readl(i2c->regs + S3C2410_IICCON);
@@ -397,7 +397,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_READ:
/* we have a byte of data in the data register, do
- * something with it, and then work out wether we are
+ * something with it, and then work out whether we are
* going to do any more read/write
*/
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 1abbc170d8b7..8c4b50fd9a79 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -251,7 +251,7 @@ void input_mt_sync_frame(struct input_dev *dev)
if (mt->flags & INPUT_MT_DROP_UNUSED) {
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
- if (s->frame == mt->frame)
+ if (input_mt_is_used(mt, s))
continue;
input_mt_slot(dev, s - mt->slots);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index de0874054e9f..77629d33f03f 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -409,7 +409,7 @@ config KEYBOARD_NEWTON
config KEYBOARD_NOMADIK
tristate "ST-Ericsson Nomadik SKE keyboard"
- depends on PLAT_NOMADIK
+ depends on (ARCH_NOMADIK || ARCH_U8500)
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a keypad provided on the SKE controller
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7c0f1ecfdd7a..104a7c3153c0 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
To compile this driver as a module, choose M here: the
module will be called ad714x-spi.
+config INPUT_ARIZONA_HAPTICS
+ tristate "Arizona haptics support"
+ depends on MFD_ARIZONA && SND_SOC
+ select INPUT_FF_MEMLESS
+ help
+ Say Y to enable support for the haptics module in Arizona CODECs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called arizona-haptics.
+
config INPUT_BMA150
tristate "BMA150/SMB380 acceleration sensor support"
depends on I2C
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 83fe6f5b77d1..5ea769eda999 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o
obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o
obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
+obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
new file mode 100644
index 000000000000..7a04f54ef961
--- /dev/null
+++ b/drivers/input/misc/arizona-haptics.c
@@ -0,0 +1,255 @@
+/*
+ * Arizona haptics driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_haptics {
+ struct arizona *arizona;
+ struct input_dev *input_dev;
+ struct work_struct work;
+
+ struct mutex mutex;
+ u8 intensity;
+};
+
+static void arizona_haptics_work(struct work_struct *work)
+{
+ struct arizona_haptics *haptics = container_of(work,
+ struct arizona_haptics,
+ work);
+ struct arizona *arizona = haptics->arizona;
+ struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
+ int ret;
+
+ if (!haptics->arizona->dapm) {
+ dev_err(arizona->dev, "No DAPM context\n");
+ return;
+ }
+
+ if (haptics->intensity) {
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_HAPTICS_PHASE_2_INTENSITY,
+ ARIZONA_PHASE2_INTENSITY_MASK,
+ haptics->intensity);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to set intensity: %d\n",
+ ret);
+ return;
+ }
+
+ /* This enable sequence will be a noop if already enabled */
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_HAPTICS_CONTROL_1,
+ ARIZONA_HAP_CTRL_MASK,
+ 1 << ARIZONA_HAP_CTRL_SHIFT);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to start haptics: %d\n",
+ ret);
+ return;
+ }
+
+ mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+ ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
+ ret);
+ mutex_unlock(dapm_mutex);
+ return;
+ }
+
+ ret = snd_soc_dapm_sync(arizona->dapm);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+ ret);
+ mutex_unlock(dapm_mutex);
+ return;
+ }
+
+ mutex_unlock(dapm_mutex);
+
+ } else {
+ /* This disable sequence will be a noop if already enabled */
+ mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+ ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
+ ret);
+ mutex_unlock(dapm_mutex);
+ return;
+ }
+
+ ret = snd_soc_dapm_sync(arizona->dapm);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+ ret);
+ mutex_unlock(dapm_mutex);
+ return;
+ }
+
+ mutex_unlock(dapm_mutex);
+
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_HAPTICS_CONTROL_1,
+ ARIZONA_HAP_CTRL_MASK,
+ 1 << ARIZONA_HAP_CTRL_SHIFT);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to stop haptics: %d\n",
+ ret);
+ return;
+ }
+ }
+}
+
+static int arizona_haptics_play(struct input_dev *input, void *data,
+ struct ff_effect *effect)
+{
+ struct arizona_haptics *haptics = input_get_drvdata(input);
+ struct arizona *arizona = haptics->arizona;
+
+ if (!arizona->dapm) {
+ dev_err(arizona->dev, "No DAPM context\n");
+ return -EBUSY;
+ }
+
+ if (effect->u.rumble.strong_magnitude) {
+ /* Scale the magnitude into the range the device supports */
+ if (arizona->pdata.hap_act) {
+ haptics->intensity =
+ effect->u.rumble.strong_magnitude >> 9;
+ if (effect->direction < 0x8000)
+ haptics->intensity += 0x7f;
+ } else {
+ haptics->intensity =
+ effect->u.rumble.strong_magnitude >> 8;
+ }
+ } else {
+ haptics->intensity = 0;
+ }
+
+ schedule_work(&haptics->work);
+
+ return 0;
+}
+
+static void arizona_haptics_close(struct input_dev *input)
+{
+ struct arizona_haptics *haptics = input_get_drvdata(input);
+ struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
+
+ cancel_work_sync(&haptics->work);
+
+ mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+ if (haptics->arizona->dapm)
+ snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+
+ mutex_unlock(dapm_mutex);
+}
+
+static int arizona_haptics_probe(struct platform_device *pdev)
+{
+ struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ struct arizona_haptics *haptics;
+ int ret;
+
+ haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+ if (!haptics)
+ return -ENOMEM;
+
+ haptics->arizona = arizona;
+
+ ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
+ ARIZONA_HAP_ACT, arizona->pdata.hap_act);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
+ ret);
+ return ret;
+ }
+
+ INIT_WORK(&haptics->work, arizona_haptics_work);
+
+ haptics->input_dev = input_allocate_device();
+ if (haptics->input_dev == NULL) {
+ dev_err(arizona->dev, "Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ input_set_drvdata(haptics->input_dev, haptics);
+
+ haptics->input_dev->name = "arizona:haptics";
+ haptics->input_dev->dev.parent = pdev->dev.parent;
+ haptics->input_dev->close = arizona_haptics_close;
+ __set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
+
+ ret = input_ff_create_memless(haptics->input_dev, NULL,
+ arizona_haptics_play);
+ if (ret < 0) {
+ dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+ ret);
+ goto err_ialloc;
+ }
+
+ ret = input_register_device(haptics->input_dev);
+ if (ret < 0) {
+ dev_err(arizona->dev, "couldn't register input device: %d\n",
+ ret);
+ goto err_iff;
+ }
+
+ platform_set_drvdata(pdev, haptics);
+
+ return 0;
+
+err_iff:
+ if (haptics->input_dev)
+ input_ff_destroy(haptics->input_dev);
+err_ialloc:
+ input_free_device(haptics->input_dev);
+
+ return ret;
+}
+
+static int arizona_haptics_remove(struct platform_device *pdev)
+{
+ struct arizona_haptics *haptics = platform_get_drvdata(pdev);
+
+ input_unregister_device(haptics->input_dev);
+
+ return 0;
+}
+
+static struct platform_driver arizona_haptics_driver = {
+ .probe = arizona_haptics_probe,
+ .remove = arizona_haptics_remove,
+ .driver = {
+ .name = "arizona-haptics",
+ .owner = THIS_MODULE,
+ },
+};
+module_platform_driver(arizona_haptics_driver);
+
+MODULE_ALIAS("platform:arizona-haptics");
+MODULE_DESCRIPTION("Arizona haptics driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 81363ffa5357..6e99d73563b8 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -490,7 +490,7 @@ receive_dmsg(struct hfc_pci *hc)
(df->data[le16_to_cpu(zp->z1)])) {
if (dch->debug & DEBUG_HW)
printk(KERN_DEBUG
- "empty_fifo hfcpci paket inv. len "
+ "empty_fifo hfcpci packet inv. len "
"%d or crc %d\n",
rcnt,
df->data[le16_to_cpu(zp->z1)]);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 182ecf0626c2..feafa91c2ed9 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -1302,7 +1302,7 @@ modeisar(struct isar_ch *ch, u32 bprotocol)
&ch->is->Flags))
ch->dpath = 1;
else {
- pr_info("modeisar both pathes in use\n");
+ pr_info("modeisar both paths in use\n");
return -EBUSY;
}
if (bprotocol == ISDN_P_B_HDLC)
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 89342f7e0c5b..525471e776a7 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -628,7 +628,7 @@ Amd7930_l1hw(struct PStack *st, int pr, void *arg)
if ((cs->dc.amd7930.ph_state == 8)) {
/* b-channels off, PH-AR cleared
* change to F3 */
- Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
+ Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5
spin_unlock_irqrestore(&cs->lock, flags);
} else {
Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index a47637be0cc5..ddec47a911a0 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -35,7 +35,7 @@ static int chancount;
/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
#define ALERT_REJECT 0
-/* Value to delay the sending of the first B-channel paket after CONNECT
+/* Value to delay the sending of the first B-channel packet after CONNECT
* here is no value given by ITU, but experience shows that 300 ms will
* work on many networks, if you or your other side is behind local exchanges
* a greater value may be recommented. If the delay is to short the first paket
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 334fa90bed8e..f60d4be58941 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -354,7 +354,7 @@ receive_dmsg(struct IsdnCardState *cs)
if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
(df->data[zp->z1])) {
if (cs->debug & L1_DEB_WARN)
- debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
+ debugl1(cs, "empty_fifo hfcpci packet inv. len %d or crc %d", rcnt, df->data[zp->z1]);
#ifdef ERROR_STATISTIC
cs->err_rx++;
#endif
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 4db846be4369..4ec279ce052f 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -270,7 +270,7 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
if ((count > fifo_size) || (count < 4)) {
if (cs->debug & L1_DEB_WARN)
- debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
+ debugl1(cs, "hfcsx_read_fifo %d packet inv. len %d ", fifo , count);
while (count) {
count--; /* empty fifo */
Read_hfc(cs, HFCSX_FIF_DRD);
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index ff5e139f4850..7fdf34704fe5 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -1417,7 +1417,7 @@ modeisar(struct BCState *bcs, int mode, int bc)
&bcs->hw.isar.reg->Flags))
bcs->hw.isar.dpath = 1;
else {
- printk(KERN_WARNING"isar modeisar both pathes in use\n");
+ printk(KERN_WARNING"isar modeisar both paths in use\n");
return (1);
}
break;
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index db50f788855d..f8e405c383a0 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -277,7 +277,6 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
u16 timebase, u8 *buf, int len)
{
u8 *p;
- int multi = 0;
u8 frame[len + 32];
struct socket *socket = NULL;
@@ -317,9 +316,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
*p++ = hc->id >> 8;
*p++ = hc->id;
}
- *p++ = (multi == 1) ? 0x80 : 0x00 + channel; /* m-flag, channel */
- if (multi == 1)
- *p++ = len; /* length */
+ *p++ = 0x00 + channel; /* m-flag, channel */
*p++ = timebase >> 8; /* time base */
*p++ = timebase;
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index be88728f1106..592f597d8951 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -250,7 +250,7 @@ tei_debug(struct FsmInst *fi, char *fmt, ...)
static int
get_free_id(struct manager *mgr)
{
- u64 ids = 0;
+ DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
int i;
struct layer2 *l2;
@@ -261,11 +261,11 @@ get_free_id(struct manager *mgr)
__func__);
return -EBUSY;
}
- test_and_set_bit(l2->ch.nr, (u_long *)&ids);
+ __set_bit(l2->ch.nr, ids);
}
- for (i = 1; i < 64; i++)
- if (!test_bit(i, (u_long *)&ids))
- return i;
+ i = find_next_zero_bit(ids, 64, 1);
+ if (i < 64)
+ return i;
printk(KERN_WARNING "%s: more as 63 layer2 for one device\n",
__func__);
return -EBUSY;
@@ -274,7 +274,7 @@ get_free_id(struct manager *mgr)
static int
get_free_tei(struct manager *mgr)
{
- u64 ids = 0;
+ DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
int i;
struct layer2 *l2;
@@ -288,11 +288,11 @@ get_free_tei(struct manager *mgr)
continue;
i -= 64;
- test_and_set_bit(i, (u_long *)&ids);
+ __set_bit(i, ids);
}
- for (i = 0; i < 64; i++)
- if (!test_bit(i, (u_long *)&ids))
- return i + 64;
+ i = find_first_zero_bit(ids, 64);
+ if (i < 64)
+ return i + 64;
printk(KERN_WARNING "%s: more as 63 dynamic tei for one device\n",
__func__);
return -1;
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index a18e639b40d7..42ecfef80132 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -508,7 +508,7 @@ pcbit_irq_handler(int interrupt, void *devptr)
return IRQ_NONE;
}
if (dev->interrupt) {
- printk(KERN_DEBUG "pcbit: reentering interrupt hander\n");
+ printk(KERN_DEBUG "pcbit: reentering interrupt handler\n");
return IRQ_HANDLED;
}
dev->interrupt = 1;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 61200717687b..bd8bf0953fe3 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4124,7 +4124,7 @@ static struct md_sysfs_entry md_size =
__ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
-/* Metdata version.
+/* Metadata version.
* This is one of
* 'none' for arrays with no metadata (good luck...)
* 'external' for arrays with externally managed metadata,
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 5ba277768d99..a3ae09124a67 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -25,7 +25,7 @@
* may be held at once. This is just an implementation detail.
*
* ii) Recursive locking attempts are detected and return EINVAL. A stack
- * trace is also emitted for the previous lock aquisition.
+ * trace is also emitted for the previous lock acquisition.
*
* iii) Priority is given to write locks.
*/
@@ -109,7 +109,7 @@ static int __check_holder(struct block_lock *lock)
DMERR("previously held here:");
print_stack_trace(lock->traces + i, 4);
- DMERR("subsequent aquisition attempted here:");
+ DMERR("subsequent acquisition attempted here:");
t.nr_entries = 0;
t.max_entries = MAX_STACK;
t.entries = entries;
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index ae02c84410ff..a2cd50441ca1 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -35,7 +35,7 @@ struct dm_transaction_manager;
*/
/*
- * Infomation about the values stored within the btree.
+ * Information about the values stored within the btree.
*/
struct dm_btree_value_type {
void *context;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index a4502686e7a8..3380372c0393 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1576,7 +1576,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
* This happens in stages:
* 1/ create a new kmem_cache and allocate the required number of
* stripe_heads.
- * 2/ gather all the old stripe_heads and tranfer the pages across
+ * 2/ gather all the old stripe_heads and transfer the pages across
* to the new stripe_heads. This will have the side effect of
* freezing the array as once all stripe_heads have been collected,
* no IO will be possible. Old stripe heads are freed once their
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index 8b4c6d5f8f36..df9abe83f877 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -948,7 +948,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
state->m_oscClockFreq = 20250;
break;
default:
- printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n");
+ printk(KERN_ERR "drxk: Clock Frequency is unknown\n");
return -EINVAL;
}
/*
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 8f22ce543cf7..bfa65079fc38 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -371,7 +371,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data)
if (!curr_ctx->aborting) {
if ((irqst & PRP_INTR_ST_RDERR) ||
(irqst & PRP_INTR_ST_CH2WERR)) {
- pr_err("PrP bus error ocurred, this transfer is probably corrupted\n");
+ pr_err("PrP bus error occurred, this transfer is probably corrupted\n");
writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
} else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 4b1becc86e54..993504015963 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -45,7 +45,7 @@
#include <media/v4l2-ioctl.h>
#include <plat/cpu.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <video/omapvrfb.h>
#include <video/omapdss.h>
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 8340445a0ee5..cf1c437a8687 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -16,7 +16,7 @@
#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <video/omapvrfb.h>
#include "omap_voutdef.h"
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 99cf10449cf5..fd15094de34a 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -30,7 +30,7 @@
#include <linux/types.h>
#include <linux/omap3isp.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <media/v4l2-event.h>
#include "isp.h"
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index d3cfe65c0494..39a77f0b8860 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -34,7 +34,7 @@
#include <media/videobuf-dma-contig.h>
#include <media/videobuf-dma-sg.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#define DRIVER_NAME "omap1-camera"
diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl
index 5fb195af43e2..4a7d2ebdfc97 100644
--- a/drivers/message/i2o/README.ioctl
+++ b/drivers/message/i2o/README.ioctl
@@ -138,7 +138,7 @@ VI. Setting Parameters
The return value is the size in bytes of the data written into
ops->resbuf if no errors occur. If an error occurs, -1 is returned
- and errno is set appropriatly:
+ and errno is set appropriately:
EFAULT Invalid user space pointer was passed
ENXIO Invalid IOP number
@@ -222,7 +222,7 @@ VIII. Downloading Software
RETURNS
This function returns 0 no errors occur. If an error occurs, -1
- is returned and errno is set appropriatly:
+ is returned and errno is set appropriately:
EFAULT Invalid user space pointer was passed
ENXIO Invalid IOP number
@@ -264,7 +264,7 @@ IX. Uploading Software
RETURNS
This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriatly:
+ is returned and errno is set appropriately:
EFAULT Invalid user space pointer was passed
ENXIO Invalid IOP number
@@ -301,7 +301,7 @@ X. Removing Software
RETURNS
This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriatly:
+ is returned and errno is set appropriately:
EFAULT Invalid user space pointer was passed
ENXIO Invalid IOP number
@@ -325,7 +325,7 @@ X. Validating Configuration
RETURNS
This function returns 0 if no erro occur. If an error occurs, -1 is
- returned and errno is set appropriatly:
+ returned and errno is set appropriately:
ETIMEDOUT Timeout waiting for reply message
ENXIO Invalid IOP number
@@ -360,7 +360,7 @@ XI. Configuration Dialog
RETURNS
This function returns 0 if no error occur. If an error occurs, -1
- is returned and errno is set appropriatly:
+ is returned and errno is set appropriately:
EFAULT Invalid user space pointer was passed
ENXIO Invalid IOP number
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 4796bbf0ae4e..49e86aed2bc4 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -609,7 +609,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
u8 operation;
/*
- * This is to deail with the case of an application
+ * This is to deal with the case of an application
* opening a device and then the device disappears while
* it's in use, and then the application tries to release
* it. ex: Unmounting a deleted RAID volume at reboot.
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 9a49c243a6ac..5451beff183f 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -189,7 +189,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
return -ENXIO;
/*
- * Stop users being able to try and allocate arbitary amounts
+ * Stop users being able to try and allocate arbitrary amounts
* of DMA space. 64K is way more than sufficient for this.
*/
if (kcmd.oplen > 65536)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 94bdf83b4bc8..b63987c6ed20 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -211,7 +211,6 @@ config MFD_TPS6586X
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
select REGMAP_I2C
- depends on REGULATOR
help
If you say yes here you get support for the TPS6586X series of
Power Management chips.
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 127b00aadae3..3e27c031aeaa 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -565,15 +565,10 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
else
num_irqs = AB8500_NR_IRQS;
- if (ab8500->irq_base) {
- ab8500->domain = irq_domain_add_legacy(
- NULL, num_irqs, ab8500->irq_base,
- 0, &ab8500_irq_ops, ab8500);
- }
- else {
- ab8500->domain = irq_domain_add_linear(
- np, num_irqs, &ab8500_irq_ops, ab8500);
- }
+ /* If ->irq_base is zero this will give a linear mapping */
+ ab8500->domain = irq_domain_add_simple(NULL,
+ num_irqs, ab8500->irq_base,
+ &ab8500_irq_ops, ab8500);
if (!ab8500->domain) {
dev_err(ab8500->dev, "Failed to create irqdomain\n");
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 1a6f943f7337..c784f4602a74 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
static struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
+ { .name = "arizona-haptics" },
{ .name = "arizona-micsupp" },
{ .name = "arizona-pwm" },
{ .name = "wm5102-codec" },
@@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = {
static struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
+ { .name = "arizona-haptics" },
{ .name = "arizona-micsupp" },
{ .name = "arizona-pwm" },
{ .name = "wm5110-codec" },
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index dc5691569370..29710565a08f 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2743,9 +2743,15 @@ static struct irq_domain_ops db8500_irq_ops = {
static int db8500_irq_init(struct device_node *np)
{
- db8500_irq_domain = irq_domain_add_legacy(
- np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE,
- 0, &db8500_irq_ops, NULL);
+ int irq_base = -1;
+
+ /* In the device tree case, just take some IRQs */
+ if (!np)
+ irq_base = IRQ_PRCMU_BASE;
+
+ db8500_irq_domain = irq_domain_add_simple(
+ np, NUM_PRCMU_WAKEUPS, irq_base,
+ &db8500_irq_ops, NULL);
if (!db8500_irq_domain) {
pr_err("Failed to create irqdomain\n");
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index f123517065ec..abd5c80c7cf5 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -21,8 +21,10 @@
* This driver is based on max8998.c
*/
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
{ .name = "max8997-led", .id = 2 },
};
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+ { .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+ {},
+};
+#endif
+
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
{
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
@@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
}
EXPORT_SYMBOL_GPL(max8997_update_reg);
+#ifdef CONFIG_OF
+/*
+ * Only the common platform data elements for max8997 are parsed here from the
+ * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8997 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ struct max8997_platform_data *pd;
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ dev_err(dev, "could not allocate memory for pdata\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+ /*
+ * ToDo: the 'wakeup' member in the platform data is more of a linux
+ * specfic information. Hence, there is no binding for that yet and
+ * not parsed here.
+ */
+
+ return pd;
+}
+#else
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ return 0;
+}
+#endif
+
+static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+#ifdef CONFIG_OF
+ if (i2c->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
+ return (int)match->data;
+ }
+#endif
+ return (int)id->driver_data;
+}
+
static int max8997_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, max8997);
max8997->dev = &i2c->dev;
max8997->i2c = i2c;
- max8997->type = id->driver_data;
+ max8997->type = max8997_i2c_get_driver_data(i2c, id);
max8997->irq = i2c->irq;
+ if (max8997->dev->of_node) {
+ pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto err;
+ }
+ }
+
if (!pdata)
goto err;
+ max8997->pdata = pdata;
max8997->ono = pdata->ono;
mutex_init(&max8997->iolock);
@@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
.name = "max8997",
.owner = THIS_MODULE,
.pm = &max8997_pm,
+ .of_match_table = of_match_ptr(max8997_pmic_dt_match),
},
.probe = max8997_i2c_probe,
.remove = max8997_i2c_remove,
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 9f92c3b22093..87ba7ada3bbc 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -24,8 +24,6 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/regulator/machine.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6586x.h>
@@ -99,6 +97,9 @@ static struct mfd_cell tps6586x_cell[] = {
.name = "tps6586x-gpio",
},
{
+ .name = "tps6586x-pmic",
+ },
+ {
.name = "tps6586x-rtc",
},
{
@@ -350,80 +351,19 @@ failed:
}
#ifdef CONFIG_OF
-static struct of_regulator_match tps6586x_matches[] = {
- { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
- { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
- { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
- { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
- { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
- { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
- { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
- { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
- { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
- { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
- { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
- { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
- { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
- { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
- { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
-};
-
static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
{
- const unsigned int num = ARRAY_SIZE(tps6586x_matches);
struct device_node *np = client->dev.of_node;
struct tps6586x_platform_data *pdata;
- struct tps6586x_subdev_info *devs;
- struct device_node *regs;
- const char *sys_rail_name = NULL;
- unsigned int count;
- unsigned int i, j;
- int err;
-
- regs = of_find_node_by_name(np, "regulators");
- if (!regs)
- return NULL;
-
- err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
- if (err < 0) {
- of_node_put(regs);
- return NULL;
- }
-
- of_node_put(regs);
- count = err;
-
- devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
- if (!devs)
- return NULL;
-
- for (i = 0, j = 0; i < num && j < count; i++) {
- struct regulator_init_data *reg_idata;
-
- if (!tps6586x_matches[i].init_data)
- continue;
-
- reg_idata = tps6586x_matches[i].init_data;
- devs[j].name = "tps6586x-regulator";
- devs[j].platform_data = tps6586x_matches[i].init_data;
- devs[j].id = (int)tps6586x_matches[i].driver_data;
- if (devs[j].id == TPS6586X_ID_SYS)
- sys_rail_name = reg_idata->constraints.name;
-
- if ((devs[j].id == TPS6586X_ID_LDO_5) ||
- (devs[j].id == TPS6586X_ID_LDO_RTC))
- reg_idata->supply_regulator = sys_rail_name;
-
- devs[j].of_node = tps6586x_matches[i].of_node;
- j++;
- }
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
+ if (!pdata) {
+ dev_err(&client->dev, "Memory allocation failed\n");
return NULL;
+ }
- pdata->num_subdevs = count;
- pdata->subdevs = devs;
+ pdata->num_subdevs = 0;
+ pdata->subdevs = NULL;
pdata->gpio_base = -1;
pdata->irq_base = -1;
pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 14490cc785d2..3141c4a173a7 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -258,6 +258,7 @@ static const struct reg_default wm5102_reg_default[] = {
{ 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */
{ 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */
{ 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */
+ { 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */
{ 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */
{ 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */
{ 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */
@@ -1047,6 +1048,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_RATE_ESTIMATOR_3:
case ARIZONA_RATE_ESTIMATOR_4:
case ARIZONA_RATE_ESTIMATOR_5:
+ case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
case ARIZONA_FLL1_CONTROL_1:
case ARIZONA_FLL1_CONTROL_2:
case ARIZONA_FLL1_CONTROL_3:
@@ -1079,6 +1081,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_FLL2_GPIO_CLOCK:
case ARIZONA_MIC_CHARGE_PUMP_1:
case ARIZONA_LDO1_CONTROL_1:
+ case ARIZONA_LDO1_CONTROL_2:
case ARIZONA_LDO2_CONTROL_1:
case ARIZONA_MIC_BIAS_CTRL_1:
case ARIZONA_MIC_BIAS_CTRL_2:
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index c7f62ac544ad..bcb226ff9d2b 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -401,13 +401,19 @@ static const struct reg_default wm1811_reva_patch[] = {
*/
static int wm8994_device_init(struct wm8994 *wm8994, int irq)
{
- struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ struct wm8994_pdata *pdata;
struct regmap_config *regmap_config;
const struct reg_default *regmap_patch = NULL;
const char *devname;
int ret, i, patch_regs;
int pulls = 0;
+ if (dev_get_platdata(wm8994->dev)) {
+ pdata = dev_get_platdata(wm8994->dev);
+ wm8994->pdata = *pdata;
+ }
+ pdata = &wm8994->pdata;
+
dev_set_drvdata(wm8994->dev, wm8994);
/* Add the on-chip regulators first for bootstrapping */
@@ -604,24 +610,21 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
}
}
- if (pdata) {
- wm8994->irq_base = pdata->irq_base;
- wm8994->gpio_base = pdata->gpio_base;
-
- /* GPIO configuration is only applied if it's non-zero */
- for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
- if (pdata->gpio_defaults[i]) {
- wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
- 0xffff,
- pdata->gpio_defaults[i]);
- }
+ wm8994->irq_base = pdata->irq_base;
+ wm8994->gpio_base = pdata->gpio_base;
+
+ /* GPIO configuration is only applied if it's non-zero */
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+ if (pdata->gpio_defaults[i]) {
+ wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
+ 0xffff, pdata->gpio_defaults[i]);
}
+ }
- wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+ wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
- if (pdata->spkmode_pu)
- pulls |= WM8994_SPKMODE_PU;
- }
+ if (pdata->spkmode_pu)
+ pulls |= WM8994_SPKMODE_PU;
/* Disable unneeded pulls */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index c58f9abcb356..158da5a81a66 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -18,6 +18,8 @@
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/of.h>
+
/* Serialize access to ssc_list and user count */
static DEFINE_SPINLOCK(user_lock);
static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
spin_lock(&user_lock);
list_for_each_entry(ssc, &ssc_list, list) {
- if (ssc->pdev->id == ssc_num) {
+ if (ssc->pdev->dev.of_node) {
+ if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
+ == ssc_num) {
+ ssc_valid = 1;
+ break;
+ }
+ } else if (ssc->pdev->id == ssc_num) {
ssc_valid = 1;
break;
}
@@ -68,39 +76,93 @@ void ssc_free(struct ssc_device *ssc)
}
EXPORT_SYMBOL(ssc_free);
-static int __init ssc_probe(struct platform_device *pdev)
+static struct atmel_ssc_platform_data at91rm9200_config = {
+ .use_dma = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9g45_config = {
+ .use_dma = 1,
+};
+
+static const struct platform_device_id atmel_ssc_devtypes[] = {
+ {
+ .name = "at91rm9200_ssc",
+ .driver_data = (unsigned long) &at91rm9200_config,
+ }, {
+ .name = "at91sam9g45_ssc",
+ .driver_data = (unsigned long) &at91sam9g45_config,
+ }, {
+ /* sentinel */
+ }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ssc_dt_ids[] = {
+ {
+ .compatible = "atmel,at91rm9200-ssc",
+ .data = &at91rm9200_config,
+ }, {
+ .compatible = "atmel,at91sam9g45-ssc",
+ .data = &at91sam9g45_config,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
+#endif
+
+static inline const struct atmel_ssc_platform_data * __init
+ atmel_ssc_get_driver_data(struct platform_device *pdev)
+{
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
+ if (match == NULL)
+ return NULL;
+ return match->data;
+ }
+
+ return (struct atmel_ssc_platform_data *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
+static int ssc_probe(struct platform_device *pdev)
{
- int retval = 0;
struct resource *regs;
struct ssc_device *ssc;
+ const struct atmel_ssc_platform_data *plat_dat;
- ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+ ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
if (!ssc) {
dev_dbg(&pdev->dev, "out of memory\n");
- retval = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
+ ssc->pdev = pdev;
+
+ plat_dat = atmel_ssc_get_driver_data(pdev);
+ if (!plat_dat)
+ return -ENODEV;
+ ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_dbg(&pdev->dev, "no mmio resource defined\n");
- retval = -ENXIO;
- goto out_free;
+ return -ENXIO;
}
- ssc->clk = clk_get(&pdev->dev, "pclk");
- if (IS_ERR(ssc->clk)) {
- dev_dbg(&pdev->dev, "no pclk clock defined\n");
- retval = -ENXIO;
- goto out_free;
- }
-
- ssc->pdev = pdev;
- ssc->regs = ioremap(regs->start, resource_size(regs));
+ ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
if (!ssc->regs) {
dev_dbg(&pdev->dev, "ioremap failed\n");
- retval = -EINVAL;
- goto out_clk;
+ return -EINVAL;
+ }
+
+ ssc->phybase = regs->start;
+
+ ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(ssc->clk)) {
+ dev_dbg(&pdev->dev, "no pclk clock defined\n");
+ return -ENXIO;
}
/* disable all interrupts */
@@ -112,8 +174,7 @@ static int __init ssc_probe(struct platform_device *pdev)
ssc->irq = platform_get_irq(pdev, 0);
if (!ssc->irq) {
dev_dbg(&pdev->dev, "could not get irq\n");
- retval = -ENXIO;
- goto out_unmap;
+ return -ENXIO;
}
spin_lock(&user_lock);
@@ -125,16 +186,7 @@ static int __init ssc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
ssc->regs, ssc->irq);
- goto out;
-
-out_unmap:
- iounmap(ssc->regs);
-out_clk:
- clk_put(ssc->clk);
-out_free:
- kfree(ssc);
-out:
- return retval;
+ return 0;
}
static int ssc_remove(struct platform_device *pdev)
@@ -142,34 +194,23 @@ static int ssc_remove(struct platform_device *pdev)
struct ssc_device *ssc = platform_get_drvdata(pdev);
spin_lock(&user_lock);
- iounmap(ssc->regs);
- clk_put(ssc->clk);
list_del(&ssc->list);
- kfree(ssc);
spin_unlock(&user_lock);
return 0;
}
static struct platform_driver ssc_driver = {
- .remove = ssc_remove,
.driver = {
.name = "ssc",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(atmel_ssc_dt_ids),
},
+ .id_table = atmel_ssc_devtypes,
+ .probe = ssc_probe,
+ .remove = ssc_remove,
};
-
-static int __init ssc_init(void)
-{
- return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
- platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 737e4edc241b..8d13c6594520 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -533,7 +533,7 @@ config MMC_DW_PLTFM
If unsure, say Y.
config MMC_DW_EXYNOS
- tristate "Exynos specific extentions for Synopsys DW Memory Card Interface"
+ tristate "Exynos specific extensions for Synopsys DW Memory Card Interface"
depends on MMC_DW
select MMC_DW_PLTFM
help
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 891558de3ec1..2de66b062f0d 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -219,7 +219,7 @@ static int platram_probe(struct platform_device *pdev)
platram_setrw(info, PLATRAM_RW);
- /* check to see if there are any available partitions, or wether
+ /* check to see if there are any available partitions, or whether
* to add this device whole */
err = mtd_device_parse_register(info->mtd, pdata->probes, NULL,
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 531807dec6b3..dae191b3c081 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -546,7 +546,7 @@ config MTD_NAND_JZ4740
config MTD_NAND_FSMC
tristate "Support for NAND on ST Micros FSMC"
- depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300
+ depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
help
Enables support for NAND Flash chips on the ST Microelectronics
Flexible Static Memory Controller (FSMC)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5c8978e90240..1f34ba104ef4 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,7 +27,6 @@
#include <linux/bch.h>
#endif
-#include <plat-omap/dma-omap.h>
#include <linux/platform_data/mtd-nand-omap2.h>
#define DRIVER_NAME "omap2-nand"
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 295e4bedad96..79ded48e7427 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -879,7 +879,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
if (chip->ecc.mode != NAND_ECC_HW)
return;
- /* change the behaviour depending on wether we are using
+ /* change the behaviour depending on whether we are using
* the large or small page nand device */
if (chip->page_shift > 10) {
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 99f96e19ebea..00cd3da29435 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -41,7 +41,7 @@
#include <linux/platform_data/mtd-onenand-omap2.h>
#include <asm/gpio.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#define DRIVER_NAME "omap2-onenand"
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index d427493997b6..cbc44f53755a 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -61,7 +61,7 @@ module_param(clockp, int, 0);
module_param(clockm, int, 0);
MODULE_LICENSE("GPL");
-static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *dev;
struct arcnet_local *lp;
@@ -135,7 +135,7 @@ out_dev:
return err;
}
-static void __devexit com20020pci_remove(struct pci_dev *pdev)
+static void com20020pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
unregister_netdev(dev);
@@ -178,7 +178,7 @@ static struct pci_driver com20020pci_driver = {
.name = "com20020",
.id_table = com20020pci_id_table,
.probe = com20020pci_probe,
- .remove = __devexit_p(com20020pci_remove),
+ .remove = com20020pci_remove,
};
static int __init com20020pci_init(void)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index e15cc11edbbe..7c9d136e74be 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -84,6 +84,10 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
/* Forward declaration */
static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp);
+static void rlb_src_unlink(struct bonding *bond, u32 index);
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash,
+ u32 ip_dst_hash);
static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
{
@@ -354,6 +358,18 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
if (!arp)
goto out;
+ /* We received an ARP from arp->ip_src.
+ * We might have used this IP address previously (on the bonding host
+ * itself or on a system that is bridged together with the bond).
+ * However, if arp->mac_src is different than what is stored in
+ * rx_hashtbl, some other host is now using the IP and we must prevent
+ * sending out client updates with this IP address and the old MAC
+ * address.
+ * Clean up all hash table entries that have this address as ip_src but
+ * have a different mac_src.
+ */
+ rlb_purge_src_ip(bond, arp);
+
if (arp->op_code == htons(ARPOP_REPLY)) {
/* update rx hash table for this ARP */
rlb_update_entry_from_arp(bond, arp);
@@ -432,9 +448,9 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_lock_rx_hashtbl_bh(bond);
rx_hash_table = bond_info->rx_hashtbl;
- index = bond_info->rx_hashtbl_head;
+ index = bond_info->rx_hashtbl_used_head;
for (; index != RLB_NULL_INDEX; index = next_index) {
- next_index = rx_hash_table[index].next;
+ next_index = rx_hash_table[index].used_next;
if (rx_hash_table[index].slave == slave) {
struct slave *assigned_slave = rlb_next_rx_slave(bond);
@@ -519,8 +535,9 @@ static void rlb_update_rx_clients(struct bonding *bond)
_lock_rx_hashtbl_bh(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX;
+ hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (client_info->ntt) {
rlb_update_client(client_info);
@@ -548,8 +565,9 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
_lock_rx_hashtbl_bh(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX;
+ hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if ((client_info->slave == slave) &&
@@ -578,8 +596,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
_lock_rx_hashtbl(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX;
+ hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (!client_info->slave) {
@@ -625,6 +644,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
/* update mac address from arp */
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
}
+ memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
assigned_slave = client_info->slave;
if (assigned_slave) {
@@ -647,6 +667,17 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
assigned_slave = rlb_next_rx_slave(bond);
if (assigned_slave) {
+ if (!(client_info->assigned &&
+ client_info->ip_src == arp->ip_src)) {
+ /* ip_src is going to be updated,
+ * fix the src hash list
+ */
+ u32 hash_src = _simple_hash((u8 *)&arp->ip_src,
+ sizeof(arp->ip_src));
+ rlb_src_unlink(bond, hash_index);
+ rlb_src_link(bond, hash_src, hash_index);
+ }
+
client_info->ip_src = arp->ip_src;
client_info->ip_dst = arp->ip_dst;
/* arp->mac_dst is broadcast for arp reqeusts.
@@ -654,6 +685,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
* upon receiving an arp reply.
*/
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+ memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
client_info->slave = assigned_slave;
if (!ether_addr_equal_64bits(client_info->mac_dst, mac_bcast)) {
@@ -669,11 +701,11 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
}
if (!client_info->assigned) {
- u32 prev_tbl_head = bond_info->rx_hashtbl_head;
- bond_info->rx_hashtbl_head = hash_index;
- client_info->next = prev_tbl_head;
+ u32 prev_tbl_head = bond_info->rx_hashtbl_used_head;
+ bond_info->rx_hashtbl_used_head = hash_index;
+ client_info->used_next = prev_tbl_head;
if (prev_tbl_head != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[prev_tbl_head].prev =
+ bond_info->rx_hashtbl[prev_tbl_head].used_prev =
hash_index;
}
client_info->assigned = 1;
@@ -694,6 +726,12 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
struct arp_pkt *arp = arp_pkt(skb);
struct slave *tx_slave = NULL;
+ /* Don't modify or load balance ARPs that do not originate locally
+ * (e.g.,arrive via a bridge).
+ */
+ if (!bond_slave_has_mac(bond, arp->mac_src))
+ return NULL;
+
if (arp->op_code == htons(ARPOP_REPLY)) {
/* the arp must be sent on the selected
* rx channel
@@ -740,8 +778,9 @@ static void rlb_rebalance(struct bonding *bond)
_lock_rx_hashtbl_bh(bond);
ntt = 0;
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX;
+ hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
assigned_slave = rlb_next_rx_slave(bond);
if (assigned_slave && (client_info->slave != assigned_slave)) {
@@ -759,11 +798,113 @@ static void rlb_rebalance(struct bonding *bond)
}
/* Caller must hold rx_hashtbl lock */
+static void rlb_init_table_entry_dst(struct rlb_client_info *entry)
+{
+ entry->used_next = RLB_NULL_INDEX;
+ entry->used_prev = RLB_NULL_INDEX;
+ entry->assigned = 0;
+ entry->slave = NULL;
+ entry->tag = 0;
+}
+static void rlb_init_table_entry_src(struct rlb_client_info *entry)
+{
+ entry->src_first = RLB_NULL_INDEX;
+ entry->src_prev = RLB_NULL_INDEX;
+ entry->src_next = RLB_NULL_INDEX;
+}
+
static void rlb_init_table_entry(struct rlb_client_info *entry)
{
memset(entry, 0, sizeof(struct rlb_client_info));
- entry->next = RLB_NULL_INDEX;
- entry->prev = RLB_NULL_INDEX;
+ rlb_init_table_entry_dst(entry);
+ rlb_init_table_entry_src(entry);
+}
+
+static void rlb_delete_table_entry_dst(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next_index = bond_info->rx_hashtbl[index].used_next;
+ u32 prev_index = bond_info->rx_hashtbl[index].used_prev;
+
+ if (index == bond_info->rx_hashtbl_used_head)
+ bond_info->rx_hashtbl_used_head = next_index;
+ if (prev_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[prev_index].used_next = next_index;
+ if (next_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next_index].used_prev = prev_index;
+}
+
+/* unlink a rlb hash table entry from the src list */
+static void rlb_src_unlink(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next_index = bond_info->rx_hashtbl[index].src_next;
+ u32 prev_index = bond_info->rx_hashtbl[index].src_prev;
+
+ bond_info->rx_hashtbl[index].src_next = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl[index].src_prev = RLB_NULL_INDEX;
+
+ if (next_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next_index].src_prev = prev_index;
+
+ if (prev_index == RLB_NULL_INDEX)
+ return;
+
+ /* is prev_index pointing to the head of this list? */
+ if (bond_info->rx_hashtbl[prev_index].src_first == index)
+ bond_info->rx_hashtbl[prev_index].src_first = next_index;
+ else
+ bond_info->rx_hashtbl[prev_index].src_next = next_index;
+
+}
+
+static void rlb_delete_table_entry(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+
+ rlb_delete_table_entry_dst(bond, index);
+ rlb_init_table_entry_dst(entry);
+
+ rlb_src_unlink(bond, index);
+}
+
+/* add the rx_hashtbl[ip_dst_hash] entry to the list
+ * of entries with identical ip_src_hash
+ */
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next;
+
+ bond_info->rx_hashtbl[ip_dst_hash].src_prev = ip_src_hash;
+ next = bond_info->rx_hashtbl[ip_src_hash].src_first;
+ bond_info->rx_hashtbl[ip_dst_hash].src_next = next;
+ if (next != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next].src_prev = ip_dst_hash;
+ bond_info->rx_hashtbl[ip_src_hash].src_first = ip_dst_hash;
+}
+
+/* deletes all rx_hashtbl entries with arp->ip_src if their mac_src does
+ * not match arp->mac_src */
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 ip_src_hash = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
+ u32 index;
+
+ _lock_rx_hashtbl_bh(bond);
+
+ index = bond_info->rx_hashtbl[ip_src_hash].src_first;
+ while (index != RLB_NULL_INDEX) {
+ struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+ u32 next_index = entry->src_next;
+ if (entry->ip_src == arp->ip_src &&
+ !ether_addr_equal_64bits(arp->mac_src, entry->mac_src))
+ rlb_delete_table_entry(bond, index);
+ index = next_index;
+ }
+ _unlock_rx_hashtbl_bh(bond);
}
static int rlb_initialize(struct bonding *bond)
@@ -781,7 +922,7 @@ static int rlb_initialize(struct bonding *bond)
bond_info->rx_hashtbl = new_hashtbl;
- bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
rlb_init_table_entry(bond_info->rx_hashtbl + i);
@@ -803,7 +944,7 @@ static void rlb_deinitialize(struct bonding *bond)
kfree(bond_info->rx_hashtbl);
bond_info->rx_hashtbl = NULL;
- bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
_unlock_rx_hashtbl_bh(bond);
}
@@ -815,25 +956,13 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
_lock_rx_hashtbl_bh(bond);
- curr_index = bond_info->rx_hashtbl_head;
+ curr_index = bond_info->rx_hashtbl_used_head;
while (curr_index != RLB_NULL_INDEX) {
struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
- u32 next_index = bond_info->rx_hashtbl[curr_index].next;
- u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
-
- if (curr->tag && (curr->vlan_id == vlan_id)) {
- if (curr_index == bond_info->rx_hashtbl_head) {
- bond_info->rx_hashtbl_head = next_index;
- }
- if (prev_index != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[prev_index].next = next_index;
- }
- if (next_index != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[next_index].prev = prev_index;
- }
+ u32 next_index = bond_info->rx_hashtbl[curr_index].used_next;
- rlb_init_table_entry(curr);
- }
+ if (curr->tag && (curr->vlan_id == vlan_id))
+ rlb_delete_table_entry(bond, curr_index);
curr_index = next_index;
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 90f140a2d197..e7a5b8b37ea3 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -94,15 +94,35 @@ struct tlb_client_info {
/* -------------------------------------------------------------------------
* struct rlb_client_info contains all info related to a specific rx client
- * connection. This is the Clients Hash Table entry struct
+ * connection. This is the Clients Hash Table entry struct.
+ * Note that this is not a proper hash table; if a new client's IP address
+ * hash collides with an existing client entry, the old entry is replaced.
+ *
+ * There is a linked list (linked by the used_next and used_prev members)
+ * linking all the used entries of the hash table. This allows updating
+ * all the clients without walking over all the unused elements of the table.
+ *
+ * There are also linked lists of entries with identical hash(ip_src). These
+ * allow cleaning up the table from ip_src<->mac_src associations that have
+ * become outdated and would cause sending out invalid ARP updates to the
+ * network. These are linked by the (src_next and src_prev members).
* -------------------------------------------------------------------------
*/
struct rlb_client_info {
__be32 ip_src; /* the server IP address */
__be32 ip_dst; /* the client IP address */
+ u8 mac_src[ETH_ALEN]; /* the server MAC address */
u8 mac_dst[ETH_ALEN]; /* the client MAC address */
- u32 next; /* The next Hash table entry index */
- u32 prev; /* The previous Hash table entry index */
+
+ /* list of used hash table entries, starting at rx_hashtbl_used_head */
+ u32 used_next;
+ u32 used_prev;
+
+ /* ip_src based hashing */
+ u32 src_next; /* next entry with same hash(ip_src) */
+ u32 src_prev; /* prev entry with same hash(ip_src) */
+ u32 src_first; /* first entry with hash(ip_src) == this entry's index */
+
u8 assigned; /* checking whether this entry is assigned */
u8 ntt; /* flag - need to transmit client info */
struct slave *slave; /* the slave assigned to this client */
@@ -131,7 +151,7 @@ struct alb_bond_info {
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
spinlock_t rx_hashtbl_lock;
- u32 rx_hashtbl_head;
+ u32 rx_hashtbl_used_head;
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 2cf084eb9d52..5fc4c2351478 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -31,8 +31,9 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX;
+ hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n",
&client_info->ip_src,
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a7d47350ea4b..ef2cb2418535 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -615,15 +615,9 @@ static int bond_check_dev_link(struct bonding *bond,
return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
/* Try to get link status using Ethtool first. */
- if (slave_dev->ethtool_ops) {
- if (slave_dev->ethtool_ops->get_link) {
- u32 link;
-
- link = slave_dev->ethtool_ops->get_link(slave_dev);
-
- return link ? BMSR_LSTATUS : 0;
- }
- }
+ if (slave_dev->ethtool_ops->get_link)
+ return slave_dev->ethtool_ops->get_link(slave_dev) ?
+ BMSR_LSTATUS : 0;
/* Ethtool can't be used, fallback to MII ioctls. */
ioctl = slave_ops->ndo_do_ioctl;
@@ -1510,8 +1504,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
int link_reporting;
int res = 0;
- if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
- slave_ops->ndo_do_ioctl == NULL) {
+ if (!bond->params.use_carrier &&
+ slave_dev->ethtool_ops->get_link == NULL &&
+ slave_ops->ndo_do_ioctl == NULL) {
pr_warning("%s: Warning: no link monitoring support for %s\n",
bond_dev->name, slave_dev->name);
}
@@ -1838,7 +1833,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* anyway (it holds no special properties of the bond device),
* so we can change it without calling change_active_interface()
*/
- if (!bond->curr_active_slave)
+ if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
bond->curr_active_slave = new_slave;
break;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index f8af2fcd3d16..21b68e5c14fd 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,6 +22,7 @@
#include <linux/in6.h>
#include <linux/netpoll.h>
#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -244,7 +245,7 @@ struct bonding {
struct delayed_work ad_work;
struct delayed_work mcast_work;
#ifdef CONFIG_DEBUG_FS
- /* debugging suport via debugfs */
+ /* debugging support via debugfs */
struct dentry *debug_dir;
#endif /* CONFIG_DEBUG_FS */
};
@@ -450,6 +451,18 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
}
#endif
+static inline struct slave *bond_slave_has_mac(struct bonding *bond,
+ const u8 *mac)
+{
+ int i = 0;
+ struct slave *tmp;
+
+ bond_for_each_slave(bond, tmp, i)
+ if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
+ return tmp;
+
+ return NULL;
+}
/* exported from bond_main.c */
extern int bond_net_id;
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index bb709fd66993..b56bd9e80957 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -110,6 +110,15 @@ config PCH_CAN
is an IOH for x86 embedded processor (Intel Atom E6xx series).
This driver can access CAN bus.
+config CAN_GRCAN
+ tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
+ depends on CAN_DEV && OF
+ ---help---
+ Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
+ Note that the driver supports little endian, even though little
+ endian syntheses of the cores would need some modifications on
+ the hardware level to work.
+
source "drivers/net/can/mscan/Kconfig"
source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 938be37b670c..7de59862bbe9 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -22,5 +22,6 @@ obj-$(CONFIG_CAN_BFIN) += bfin_can.o
obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
obj-$(CONFIG_PCH_CAN) += pch_can.o
+obj-$(CONFIG_CAN_GRCAN) += grcan.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 994b6acd65f4..81baefda037b 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -154,7 +154,7 @@ struct at91_priv {
canid_t mb0_id;
};
-static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+static const struct at91_devtype_data at91_devtype_data[] = {
[AT91_DEVTYPE_SAM9263] = {
.rx_first = 1,
.rx_split = 8,
@@ -1241,7 +1241,7 @@ static struct attribute_group at91_sysfs_attr_group = {
.attrs = at91_sysfs_attrs,
};
-static int __devinit at91_can_probe(struct platform_device *pdev)
+static int at91_can_probe(struct platform_device *pdev)
{
const struct at91_devtype_data *devtype_data;
enum at91_devtype devtype;
@@ -1338,7 +1338,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
return err;
}
-static int __devexit at91_can_remove(struct platform_device *pdev)
+static int at91_can_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct at91_priv *priv = netdev_priv(dev);
@@ -1371,10 +1371,11 @@ static const struct platform_device_id at91_can_id_table[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(platform, at91_can_id_table);
static struct platform_driver at91_can_driver = {
.probe = at91_can_probe,
- .remove = __devexit_p(at91_can_remove),
+ .remove = at91_can_remove,
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index f2d6d258a286..6a0532176b69 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -531,7 +531,7 @@ static const struct net_device_ops bfin_can_netdev_ops = {
.ndo_start_xmit = bfin_can_start_xmit,
};
-static int __devinit bfin_can_probe(struct platform_device *pdev)
+static int bfin_can_probe(struct platform_device *pdev)
{
int err;
struct net_device *dev;
@@ -611,7 +611,7 @@ exit:
return err;
}
-static int __devexit bfin_can_remove(struct platform_device *pdev)
+static int bfin_can_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
@@ -677,7 +677,7 @@ static int bfin_can_resume(struct platform_device *pdev)
static struct platform_driver bfin_can_driver = {
.probe = bfin_can_probe,
- .remove = __devexit_p(bfin_can_remove),
+ .remove = bfin_can_remove,
.suspend = bfin_can_suspend,
.resume = bfin_can_resume,
.driver = {
@@ -691,3 +691,4 @@ module_platform_driver(bfin_can_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e5180dfddba5..5233b8f58d77 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -233,6 +233,12 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
pm_runtime_put_sync(priv->device);
}
+static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
+{
+ if (priv->raminit)
+ priv->raminit(priv, enable);
+}
+
static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
{
return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
@@ -1090,6 +1096,7 @@ static int c_can_open(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev);
c_can_pm_runtime_get_sync(priv);
+ c_can_reset_ram(priv, true);
/* open the can device */
err = open_candev(dev);
@@ -1118,6 +1125,7 @@ static int c_can_open(struct net_device *dev)
exit_irq_fail:
close_candev(dev);
exit_open_fail:
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return err;
}
@@ -1131,6 +1139,8 @@ static int c_can_close(struct net_device *dev)
c_can_stop(dev);
free_irq(dev->irq, dev);
close_candev(dev);
+
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1188,6 +1198,7 @@ int c_can_power_down(struct net_device *dev)
c_can_stop(dev);
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1206,6 +1217,7 @@ int c_can_power_up(struct net_device *dev)
WARN_ON(priv->type != BOSCH_D_CAN);
c_can_pm_runtime_get_sync(priv);
+ c_can_reset_ram(priv, true);
/* Clear PDR and INIT bits */
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e5ed41dafa1b..d2e1c21b143f 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -169,6 +169,9 @@ struct c_can_priv {
void *priv; /* for board-specific data */
u16 irqstatus;
enum c_can_dev_id type;
+ u32 __iomem *raminit_ctrlreg;
+ unsigned int instance;
+ void (*raminit) (const struct c_can_priv *priv, bool enable);
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 3d7830bcd2bf..b374be7891a2 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -63,8 +63,8 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
-static int __devinit c_can_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int c_can_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
struct c_can_priv *priv;
@@ -174,7 +174,7 @@ out:
return ret;
}
-static void __devexit c_can_pci_remove(struct pci_dev *pdev)
+static void c_can_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -210,7 +210,7 @@ static struct pci_driver c_can_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = c_can_pci_tbl,
.probe = c_can_pci_probe,
- .remove = __devexit_p(c_can_pci_remove),
+ .remove = c_can_pci_remove,
};
module_pci_driver(c_can_pci_driver);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index ee1416132aba..d63b91904f82 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -38,6 +38,8 @@
#include "c_can.h"
+#define CAN_RAMINIT_START_MASK(i) (1 << (i))
+
/*
* 16-bit c_can registers can be arranged differently in the memory
* architecture of different implementations. For example: 16-bit
@@ -68,6 +70,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
+static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
+{
+ u32 val;
+
+ val = readl(priv->raminit_ctrlreg);
+ if (enable)
+ val |= CAN_RAMINIT_START_MASK(priv->instance);
+ else
+ val &= ~CAN_RAMINIT_START_MASK(priv->instance);
+ writel(val, priv->raminit_ctrlreg);
+}
+
static struct platform_device_id c_can_id_table[] = {
[BOSCH_C_CAN_PLATFORM] = {
.name = KBUILD_MODNAME,
@@ -83,14 +97,16 @@ static struct platform_device_id c_can_id_table[] = {
}, {
}
};
+MODULE_DEVICE_TABLE(platform, c_can_id_table);
static const struct of_device_id c_can_of_table[] = {
{ .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] },
{ .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, c_can_of_table);
-static int __devinit c_can_plat_probe(struct platform_device *pdev)
+static int c_can_plat_probe(struct platform_device *pdev)
{
int ret;
void __iomem *addr;
@@ -99,7 +115,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
const struct of_device_id *match;
const struct platform_device_id *id;
struct pinctrl *pinctrl;
- struct resource *mem;
+ struct resource *mem, *res;
int irq;
struct clk *clk;
@@ -178,6 +194,18 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+
+ if (pdev->dev.of_node)
+ priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can");
+ else
+ priv->instance = pdev->id;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->raminit_ctrlreg = devm_request_and_ioremap(&pdev->dev, res);
+ if (!priv->raminit_ctrlreg || priv->instance < 0)
+ dev_info(&pdev->dev, "control memory is not used for raminit\n");
+ else
+ priv->raminit = c_can_hw_raminit;
break;
default:
ret = -EINVAL;
@@ -220,7 +248,7 @@ exit:
return ret;
}
-static int __devexit c_can_plat_remove(struct platform_device *pdev)
+static int c_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -306,7 +334,7 @@ static struct platform_driver c_can_plat_driver = {
.of_match_table = of_match_ptr(c_can_of_table),
},
.probe = c_can_plat_probe,
- .remove = __devexit_p(c_can_plat_remove),
+ .remove = c_can_plat_remove,
.suspend = c_can_suspend,
.resume = c_can_resume,
.id_table = c_can_id_table,
diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
index 9f3a25ccd665..8eaaac81f320 100644
--- a/drivers/net/can/cc770/cc770_isa.c
+++ b/drivers/net/can/cc770/cc770_isa.c
@@ -75,12 +75,12 @@ MODULE_LICENSE("GPL v2");
static unsigned long port[MAXDEV];
static unsigned long mem[MAXDEV];
-static int __devinitdata irq[MAXDEV];
-static int __devinitdata clk[MAXDEV];
-static u8 __devinitdata cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static u8 __devinitdata cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static u8 __devinitdata bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static int irq[MAXDEV];
+static int clk[MAXDEV];
+static u8 cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
module_param_array(port, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(port, "I/O port number");
@@ -166,7 +166,7 @@ static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
}
-static int __devinit cc770_isa_probe(struct platform_device *pdev)
+static int cc770_isa_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct cc770_priv *priv;
@@ -291,7 +291,7 @@ static int __devinit cc770_isa_probe(struct platform_device *pdev)
return err;
}
-static int __devexit cc770_isa_remove(struct platform_device *pdev)
+static int cc770_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -316,7 +316,7 @@ static int __devexit cc770_isa_remove(struct platform_device *pdev)
static struct platform_driver cc770_isa_driver = {
.probe = cc770_isa_probe,
- .remove = __devexit_p(cc770_isa_remove),
+ .remove = cc770_isa_remove,
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index 688371cda37a..d0f6bfc45aea 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -60,6 +60,7 @@
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the platform bus");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
#define CC770_PLATFORM_CAN_CLOCK 16000000
@@ -74,8 +75,8 @@ static void cc770_platform_write_reg(const struct cc770_priv *priv, int reg,
iowrite8(val, priv->reg_base + reg);
}
-static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
- struct cc770_priv *priv)
+static int cc770_get_of_node_data(struct platform_device *pdev,
+ struct cc770_priv *priv)
{
struct device_node *np = pdev->dev.of_node;
const u32 *prop;
@@ -147,8 +148,8 @@ static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
return 0;
}
-static int __devinit cc770_get_platform_data(struct platform_device *pdev,
- struct cc770_priv *priv)
+static int cc770_get_platform_data(struct platform_device *pdev,
+ struct cc770_priv *priv)
{
struct cc770_platform_data *pdata = pdev->dev.platform_data;
@@ -163,7 +164,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev,
return 0;
}
-static int __devinit cc770_platform_probe(struct platform_device *pdev)
+static int cc770_platform_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct cc770_priv *priv;
@@ -237,7 +238,7 @@ exit_release_mem:
return err;
}
-static int __devexit cc770_platform_remove(struct platform_device *pdev)
+static int cc770_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -253,11 +254,12 @@ static int __devexit cc770_platform_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id __devinitdata cc770_platform_table[] = {
+static struct of_device_id cc770_platform_table[] = {
{.compatible = "bosch,cc770"}, /* CC770 from Bosch */
{.compatible = "intc,82527"}, /* AN82527 from Intel CP */
{},
};
+MODULE_DEVICE_TABLE(of, cc770_platform_table);
static struct platform_driver cc770_platform_driver = {
.driver = {
@@ -266,7 +268,7 @@ static struct platform_driver cc770_platform_driver = {
.of_match_table = cc770_platform_table,
},
.probe = cc770_platform_probe,
- .remove = __devexit_p(cc770_platform_remove),
+ .remove = cc770_platform_remove,
};
module_platform_driver(cc770_platform_driver);
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 963e2ccd10db..8233e5ed2939 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -609,8 +609,7 @@ void close_candev(struct net_device *dev)
{
struct can_priv *priv = netdev_priv(dev);
- if (del_timer_sync(&priv->restart_timer))
- dev_put(dev);
+ del_timer_sync(&priv->restart_timer);
can_flush_echo_skb(dev);
}
EXPORT_SYMBOL_GPL(close_candev);
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index a412bf6d73ef..0289a6d86f66 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -922,7 +922,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
.ndo_start_xmit = flexcan_start_xmit,
};
-static int __devinit register_flexcandev(struct net_device *dev)
+static int register_flexcandev(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base;
@@ -968,7 +968,7 @@ static int __devinit register_flexcandev(struct net_device *dev)
return err;
}
-static void __devexit unregister_flexcandev(struct net_device *dev)
+static void unregister_flexcandev(struct net_device *dev)
{
unregister_candev(dev);
}
@@ -979,13 +979,15 @@ static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, flexcan_of_match);
static const struct platform_device_id flexcan_id_table[] = {
{ .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(platform, flexcan_id_table);
-static int __devinit flexcan_probe(struct platform_device *pdev)
+static int flexcan_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
const struct flexcan_devtype_data *devtype_data;
@@ -1107,7 +1109,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
return err;
}
-static int __devexit flexcan_remove(struct platform_device *pdev)
+static int flexcan_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct flexcan_priv *priv = netdev_priv(dev);
@@ -1168,7 +1170,7 @@ static struct platform_driver flexcan_driver = {
.of_match_table = flexcan_of_match,
},
.probe = flexcan_probe,
- .remove = __devexit_p(flexcan_remove),
+ .remove = flexcan_remove,
.suspend = flexcan_suspend,
.resume = flexcan_resume,
.id_table = flexcan_id_table,
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
new file mode 100644
index 000000000000..17fbc7a09224
--- /dev/null
+++ b/drivers/net/can/grcan.c
@@ -0,0 +1,1756 @@
+/*
+ * Socket CAN driver for Aeroflex Gaisler GRCAN and GRHCAN.
+ *
+ * 2012 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRCAN and GRHCAN CAN controllers available in the GRLIB
+ * VHDL IP core library.
+ *
+ * Full documentation of the GRCAN core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on
+ * open firmware properties.
+ *
+ * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
+ * sysfs interface.
+ *
+ * See "Documentation/kernel-parameters.txt" for information on the module
+ * parameters.
+ *
+ * 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.
+ *
+ * Contributors: Andreas Larsson <andreas@gaisler.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/can/dev.h>
+#include <linux/spinlock.h>
+
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+#include <linux/of_irq.h>
+
+#include <linux/dma-mapping.h>
+
+#define DRV_NAME "grcan"
+
+#define GRCAN_NAPI_WEIGHT 32
+
+#define GRCAN_RESERVE_SIZE(slot1, slot2) (((slot2) - (slot1)) / 4 - 1)
+
+struct grcan_registers {
+ u32 conf; /* 0x00 */
+ u32 stat; /* 0x04 */
+ u32 ctrl; /* 0x08 */
+ u32 __reserved1[GRCAN_RESERVE_SIZE(0x08, 0x18)];
+ u32 smask; /* 0x18 - CanMASK */
+ u32 scode; /* 0x1c - CanCODE */
+ u32 __reserved2[GRCAN_RESERVE_SIZE(0x1c, 0x100)];
+ u32 pimsr; /* 0x100 */
+ u32 pimr; /* 0x104 */
+ u32 pisr; /* 0x108 */
+ u32 pir; /* 0x10C */
+ u32 imr; /* 0x110 */
+ u32 picr; /* 0x114 */
+ u32 __reserved3[GRCAN_RESERVE_SIZE(0x114, 0x200)];
+ u32 txctrl; /* 0x200 */
+ u32 txaddr; /* 0x204 */
+ u32 txsize; /* 0x208 */
+ u32 txwr; /* 0x20C */
+ u32 txrd; /* 0x210 */
+ u32 txirq; /* 0x214 */
+ u32 __reserved4[GRCAN_RESERVE_SIZE(0x214, 0x300)];
+ u32 rxctrl; /* 0x300 */
+ u32 rxaddr; /* 0x304 */
+ u32 rxsize; /* 0x308 */
+ u32 rxwr; /* 0x30C */
+ u32 rxrd; /* 0x310 */
+ u32 rxirq; /* 0x314 */
+ u32 rxmask; /* 0x318 */
+ u32 rxcode; /* 0x31C */
+};
+
+#define GRCAN_CONF_ABORT 0x00000001
+#define GRCAN_CONF_ENABLE0 0x00000002
+#define GRCAN_CONF_ENABLE1 0x00000004
+#define GRCAN_CONF_SELECT 0x00000008
+#define GRCAN_CONF_SILENT 0x00000010
+#define GRCAN_CONF_SAM 0x00000020 /* Available in some hardware */
+#define GRCAN_CONF_BPR 0x00000300 /* Note: not BRP */
+#define GRCAN_CONF_RSJ 0x00007000
+#define GRCAN_CONF_PS1 0x00f00000
+#define GRCAN_CONF_PS2 0x000f0000
+#define GRCAN_CONF_SCALER 0xff000000
+#define GRCAN_CONF_OPERATION \
+ (GRCAN_CONF_ABORT | GRCAN_CONF_ENABLE0 | GRCAN_CONF_ENABLE1 \
+ | GRCAN_CONF_SELECT | GRCAN_CONF_SILENT | GRCAN_CONF_SAM)
+#define GRCAN_CONF_TIMING \
+ (GRCAN_CONF_BPR | GRCAN_CONF_RSJ | GRCAN_CONF_PS1 \
+ | GRCAN_CONF_PS2 | GRCAN_CONF_SCALER)
+
+#define GRCAN_CONF_RSJ_MIN 1
+#define GRCAN_CONF_RSJ_MAX 4
+#define GRCAN_CONF_PS1_MIN 1
+#define GRCAN_CONF_PS1_MAX 15
+#define GRCAN_CONF_PS2_MIN 2
+#define GRCAN_CONF_PS2_MAX 8
+#define GRCAN_CONF_SCALER_MIN 0
+#define GRCAN_CONF_SCALER_MAX 255
+#define GRCAN_CONF_SCALER_INC 1
+
+#define GRCAN_CONF_BPR_BIT 8
+#define GRCAN_CONF_RSJ_BIT 12
+#define GRCAN_CONF_PS1_BIT 20
+#define GRCAN_CONF_PS2_BIT 16
+#define GRCAN_CONF_SCALER_BIT 24
+
+#define GRCAN_STAT_PASS 0x000001
+#define GRCAN_STAT_OFF 0x000002
+#define GRCAN_STAT_OR 0x000004
+#define GRCAN_STAT_AHBERR 0x000008
+#define GRCAN_STAT_ACTIVE 0x000010
+#define GRCAN_STAT_RXERRCNT 0x00ff00
+#define GRCAN_STAT_TXERRCNT 0xff0000
+
+#define GRCAN_STAT_ERRCTR_RELATED (GRCAN_STAT_PASS | GRCAN_STAT_OFF)
+
+#define GRCAN_STAT_RXERRCNT_BIT 8
+#define GRCAN_STAT_TXERRCNT_BIT 16
+
+#define GRCAN_STAT_ERRCNT_WARNING_LIMIT 96
+#define GRCAN_STAT_ERRCNT_PASSIVE_LIMIT 127
+
+#define GRCAN_CTRL_RESET 0x2
+#define GRCAN_CTRL_ENABLE 0x1
+
+#define GRCAN_TXCTRL_ENABLE 0x1
+#define GRCAN_TXCTRL_ONGOING 0x2
+#define GRCAN_TXCTRL_SINGLE 0x4
+
+#define GRCAN_RXCTRL_ENABLE 0x1
+#define GRCAN_RXCTRL_ONGOING 0x2
+
+/* Relative offset of IRQ sources to AMBA Plug&Play */
+#define GRCAN_IRQIX_IRQ 0
+#define GRCAN_IRQIX_TXSYNC 1
+#define GRCAN_IRQIX_RXSYNC 2
+
+#define GRCAN_IRQ_PASS 0x00001
+#define GRCAN_IRQ_OFF 0x00002
+#define GRCAN_IRQ_OR 0x00004
+#define GRCAN_IRQ_RXAHBERR 0x00008
+#define GRCAN_IRQ_TXAHBERR 0x00010
+#define GRCAN_IRQ_RXIRQ 0x00020
+#define GRCAN_IRQ_TXIRQ 0x00040
+#define GRCAN_IRQ_RXFULL 0x00080
+#define GRCAN_IRQ_TXEMPTY 0x00100
+#define GRCAN_IRQ_RX 0x00200
+#define GRCAN_IRQ_TX 0x00400
+#define GRCAN_IRQ_RXSYNC 0x00800
+#define GRCAN_IRQ_TXSYNC 0x01000
+#define GRCAN_IRQ_RXERRCTR 0x02000
+#define GRCAN_IRQ_TXERRCTR 0x04000
+#define GRCAN_IRQ_RXMISS 0x08000
+#define GRCAN_IRQ_TXLOSS 0x10000
+
+#define GRCAN_IRQ_NONE 0
+#define GRCAN_IRQ_ALL \
+ (GRCAN_IRQ_PASS | GRCAN_IRQ_OFF | GRCAN_IRQ_OR \
+ | GRCAN_IRQ_RXAHBERR | GRCAN_IRQ_TXAHBERR \
+ | GRCAN_IRQ_RXIRQ | GRCAN_IRQ_TXIRQ \
+ | GRCAN_IRQ_RXFULL | GRCAN_IRQ_TXEMPTY \
+ | GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_RXSYNC \
+ | GRCAN_IRQ_TXSYNC | GRCAN_IRQ_RXERRCTR \
+ | GRCAN_IRQ_TXERRCTR | GRCAN_IRQ_RXMISS \
+ | GRCAN_IRQ_TXLOSS)
+
+#define GRCAN_IRQ_ERRCTR_RELATED (GRCAN_IRQ_RXERRCTR | GRCAN_IRQ_TXERRCTR \
+ | GRCAN_IRQ_PASS | GRCAN_IRQ_OFF)
+#define GRCAN_IRQ_ERRORS (GRCAN_IRQ_ERRCTR_RELATED | GRCAN_IRQ_OR \
+ | GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR \
+ | GRCAN_IRQ_TXLOSS)
+#define GRCAN_IRQ_DEFAULT (GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_ERRORS)
+
+#define GRCAN_MSG_SIZE 16
+
+#define GRCAN_MSG_IDE 0x80000000
+#define GRCAN_MSG_RTR 0x40000000
+#define GRCAN_MSG_BID 0x1ffc0000
+#define GRCAN_MSG_EID 0x1fffffff
+#define GRCAN_MSG_IDE_BIT 31
+#define GRCAN_MSG_RTR_BIT 30
+#define GRCAN_MSG_BID_BIT 18
+#define GRCAN_MSG_EID_BIT 0
+
+#define GRCAN_MSG_DLC 0xf0000000
+#define GRCAN_MSG_TXERRC 0x00ff0000
+#define GRCAN_MSG_RXERRC 0x0000ff00
+#define GRCAN_MSG_DLC_BIT 28
+#define GRCAN_MSG_TXERRC_BIT 16
+#define GRCAN_MSG_RXERRC_BIT 8
+#define GRCAN_MSG_AHBERR 0x00000008
+#define GRCAN_MSG_OR 0x00000004
+#define GRCAN_MSG_OFF 0x00000002
+#define GRCAN_MSG_PASS 0x00000001
+
+#define GRCAN_MSG_DATA_SLOT_INDEX(i) (2 + (i) / 4)
+#define GRCAN_MSG_DATA_SHIFT(i) ((3 - (i) % 4) * 8)
+
+#define GRCAN_BUFFER_ALIGNMENT 1024
+#define GRCAN_DEFAULT_BUFFER_SIZE 1024
+#define GRCAN_VALID_TR_SIZE_MASK 0x001fffc0
+
+#define GRCAN_INVALID_BUFFER_SIZE(s) \
+ ((s) == 0 || ((s) & ~GRCAN_VALID_TR_SIZE_MASK))
+
+#if GRCAN_INVALID_BUFFER_SIZE(GRCAN_DEFAULT_BUFFER_SIZE)
+#error "Invalid default buffer size"
+#endif
+
+struct grcan_dma_buffer {
+ size_t size;
+ void *buf;
+ dma_addr_t handle;
+};
+
+struct grcan_dma {
+ size_t base_size;
+ void *base_buf;
+ dma_addr_t base_handle;
+ struct grcan_dma_buffer tx;
+ struct grcan_dma_buffer rx;
+};
+
+/* GRCAN configuration parameters */
+struct grcan_device_config {
+ unsigned short enable0;
+ unsigned short enable1;
+ unsigned short select;
+ unsigned int txsize;
+ unsigned int rxsize;
+};
+
+#define GRCAN_DEFAULT_DEVICE_CONFIG { \
+ .enable0 = 0, \
+ .enable1 = 0, \
+ .select = 0, \
+ .txsize = GRCAN_DEFAULT_BUFFER_SIZE, \
+ .rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \
+ }
+
+#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100
+#define GRLIB_VERSION_MASK 0xffff
+
+/* GRCAN private data structure */
+struct grcan_priv {
+ struct can_priv can; /* must be the first member */
+ struct net_device *dev;
+ struct napi_struct napi;
+
+ struct grcan_registers __iomem *regs; /* ioremap'ed registers */
+ struct grcan_device_config config;
+ struct grcan_dma dma;
+
+ struct sk_buff **echo_skb; /* We allocate this on our own */
+ u8 *txdlc; /* Length of queued frames */
+
+ /* The echo skb pointer, pointing into echo_skb and indicating which
+ * frames can be echoed back. See the "Notes on the tx cyclic buffer
+ * handling"-comment for grcan_start_xmit for more details.
+ */
+ u32 eskbp;
+
+ /* Lock for controlling changes to the netif tx queue state, accesses to
+ * the echo_skb pointer eskbp and for making sure that a running reset
+ * and/or a close of the interface is done without interference from
+ * other parts of the code.
+ *
+ * The echo_skb pointer, eskbp, should only be accessed under this lock
+ * as it can be changed in several places and together with decisions on
+ * whether to wake up the tx queue.
+ *
+ * The tx queue must never be woken up if there is a running reset or
+ * close in progress.
+ *
+ * A running reset (see below on need_txbug_workaround) should never be
+ * done if the interface is closing down and several running resets
+ * should never be scheduled simultaneously.
+ */
+ spinlock_t lock;
+
+ /* Whether a workaround is needed due to a bug in older hardware. In
+ * this case, the driver both tries to prevent the bug from being
+ * triggered and recovers, if the bug nevertheless happens, by doing a
+ * running reset. A running reset, resets the device and continues from
+ * where it were without being noticeable from outside the driver (apart
+ * from slight delays).
+ */
+ bool need_txbug_workaround;
+
+ /* To trigger initization of running reset and to trigger running reset
+ * respectively in the case of a hanged device due to a txbug.
+ */
+ struct timer_list hang_timer;
+ struct timer_list rr_timer;
+
+ /* To avoid waking up the netif queue and restarting timers
+ * when a reset is scheduled or when closing of the device is
+ * undergoing
+ */
+ bool resetting;
+ bool closing;
+};
+
+/* Wait time for a short wait for ongoing to clear */
+#define GRCAN_SHORTWAIT_USECS 10
+
+/* Limit on the number of transmitted bits of an eff frame according to the CAN
+ * specification: 1 bit start of frame, 32 bits arbitration field, 6 bits
+ * control field, 8 bytes data field, 16 bits crc field, 2 bits ACK field and 7
+ * bits end of frame
+ */
+#define GRCAN_EFF_FRAME_MAX_BITS (1+32+6+8*8+16+2+7)
+
+#if defined(__BIG_ENDIAN)
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+ return ioread32be(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+ iowrite32be(val, reg);
+}
+#else
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+ return ioread32(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+ iowrite32(val, reg);
+}
+#endif
+
+static inline void grcan_clear_bits(u32 __iomem *reg, u32 mask)
+{
+ grcan_write_reg(reg, grcan_read_reg(reg) & ~mask);
+}
+
+static inline void grcan_set_bits(u32 __iomem *reg, u32 mask)
+{
+ grcan_write_reg(reg, grcan_read_reg(reg) | mask);
+}
+
+static inline u32 grcan_read_bits(u32 __iomem *reg, u32 mask)
+{
+ return grcan_read_reg(reg) & mask;
+}
+
+static inline void grcan_write_bits(u32 __iomem *reg, u32 value, u32 mask)
+{
+ u32 old = grcan_read_reg(reg);
+
+ grcan_write_reg(reg, (old & ~mask) | (value & mask));
+}
+
+/* a and b should both be in [0,size] and a == b == size should not hold */
+static inline u32 grcan_ring_add(u32 a, u32 b, u32 size)
+{
+ u32 sum = a + b;
+
+ if (sum < size)
+ return sum;
+ else
+ return sum - size;
+}
+
+/* a and b should both be in [0,size) */
+static inline u32 grcan_ring_sub(u32 a, u32 b, u32 size)
+{
+ return grcan_ring_add(a, size - b, size);
+}
+
+/* Available slots for new transmissions */
+static inline u32 grcan_txspace(size_t txsize, u32 txwr, u32 eskbp)
+{
+ u32 slots = txsize / GRCAN_MSG_SIZE - 1;
+ u32 used = grcan_ring_sub(txwr, eskbp, txsize) / GRCAN_MSG_SIZE;
+
+ return slots - used;
+}
+
+/* Configuration parameters that can be set via module parameters */
+static struct grcan_device_config grcan_module_config =
+ GRCAN_DEFAULT_DEVICE_CONFIG;
+
+static const struct can_bittiming_const grcan_bittiming_const = {
+ .name = DRV_NAME,
+ .tseg1_min = GRCAN_CONF_PS1_MIN + 1,
+ .tseg1_max = GRCAN_CONF_PS1_MAX + 1,
+ .tseg2_min = GRCAN_CONF_PS2_MIN,
+ .tseg2_max = GRCAN_CONF_PS2_MAX,
+ .sjw_max = GRCAN_CONF_RSJ_MAX,
+ .brp_min = GRCAN_CONF_SCALER_MIN + 1,
+ .brp_max = GRCAN_CONF_SCALER_MAX + 1,
+ .brp_inc = GRCAN_CONF_SCALER_INC,
+};
+
+static int grcan_set_bittiming(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct can_bittiming *bt = &priv->can.bittiming;
+ u32 timing = 0;
+ int bpr, rsj, ps1, ps2, scaler;
+
+ /* Should never happen - function will not be called when
+ * device is up
+ */
+ if (grcan_read_bits(&regs->ctrl, GRCAN_CTRL_ENABLE))
+ return -EBUSY;
+
+ bpr = 0; /* Note bpr and brp are different concepts */
+ rsj = bt->sjw;
+ ps1 = (bt->prop_seg + bt->phase_seg1) - 1; /* tseg1 - 1 */
+ ps2 = bt->phase_seg2;
+ scaler = (bt->brp - 1);
+ netdev_dbg(dev, "Request for BPR=%d, RSJ=%d, PS1=%d, PS2=%d, SCALER=%d",
+ bpr, rsj, ps1, ps2, scaler);
+ if (!(ps1 > ps2)) {
+ netdev_err(dev, "PS1 > PS2 must hold: PS1=%d, PS2=%d\n",
+ ps1, ps2);
+ return -EINVAL;
+ }
+ if (!(ps2 >= rsj)) {
+ netdev_err(dev, "PS2 >= RSJ must hold: PS2=%d, RSJ=%d\n",
+ ps2, rsj);
+ return -EINVAL;
+ }
+
+ timing |= (bpr << GRCAN_CONF_BPR_BIT) & GRCAN_CONF_BPR;
+ timing |= (rsj << GRCAN_CONF_RSJ_BIT) & GRCAN_CONF_RSJ;
+ timing |= (ps1 << GRCAN_CONF_PS1_BIT) & GRCAN_CONF_PS1;
+ timing |= (ps2 << GRCAN_CONF_PS2_BIT) & GRCAN_CONF_PS2;
+ timing |= (scaler << GRCAN_CONF_SCALER_BIT) & GRCAN_CONF_SCALER;
+ netdev_info(dev, "setting timing=0x%x\n", timing);
+ grcan_write_bits(&regs->conf, timing, GRCAN_CONF_TIMING);
+
+ return 0;
+}
+
+static int grcan_get_berr_counter(const struct net_device *dev,
+ struct can_berr_counter *bec)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ u32 status = grcan_read_reg(&regs->stat);
+
+ bec->txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT;
+ bec->rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT;
+ return 0;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget);
+
+/* Reset device, but keep configuration information */
+static void grcan_reset(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ u32 config = grcan_read_reg(&regs->conf);
+
+ grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+ grcan_write_reg(&regs->conf, config);
+
+ priv->eskbp = grcan_read_reg(&regs->txrd);
+ priv->can.state = CAN_STATE_STOPPED;
+
+ /* Turn off hardware filtering - regs->rxcode set to 0 by reset */
+ grcan_write_reg(&regs->rxmask, 0);
+}
+
+/* stop device without changing any configurations */
+static void grcan_stop_hardware(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+
+ grcan_write_reg(&regs->imr, GRCAN_IRQ_NONE);
+ grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+ grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+ grcan_clear_bits(&regs->ctrl, GRCAN_CTRL_ENABLE);
+}
+
+/* Let priv->eskbp catch up to regs->txrd and echo back the skbs if echo
+ * is true and free them otherwise.
+ *
+ * If budget is >= 0, stop after handling at most budget skbs. Otherwise,
+ * continue until priv->eskbp catches up to regs->txrd.
+ *
+ * priv->lock *must* be held when calling this function
+ */
+static int catch_up_echo_skb(struct net_device *dev, int budget, bool echo)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ struct net_device_stats *stats = &dev->stats;
+ int i, work_done;
+
+ /* Updates to priv->eskbp and wake-ups of the queue needs to
+ * be atomic towards the reads of priv->eskbp and shut-downs
+ * of the queue in grcan_start_xmit.
+ */
+ u32 txrd = grcan_read_reg(&regs->txrd);
+
+ for (work_done = 0; work_done < budget || budget < 0; work_done++) {
+ if (priv->eskbp == txrd)
+ break;
+ i = priv->eskbp / GRCAN_MSG_SIZE;
+ if (echo) {
+ /* Normal echo of messages */
+ stats->tx_packets++;
+ stats->tx_bytes += priv->txdlc[i];
+ priv->txdlc[i] = 0;
+ can_get_echo_skb(dev, i);
+ } else {
+ /* For cleanup of untransmitted messages */
+ can_free_echo_skb(dev, i);
+ }
+
+ priv->eskbp = grcan_ring_add(priv->eskbp, GRCAN_MSG_SIZE,
+ dma->tx.size);
+ txrd = grcan_read_reg(&regs->txrd);
+ }
+ return work_done;
+}
+
+static void grcan_lost_one_shot_frame(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ u32 txrd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ catch_up_echo_skb(dev, -1, true);
+
+ if (unlikely(grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE))) {
+ /* Should never happen */
+ netdev_err(dev, "TXCTRL enabled at TXLOSS in one shot mode\n");
+ } else {
+ /* By the time an GRCAN_IRQ_TXLOSS is generated in
+ * one-shot mode there is no problem in writing
+ * to TXRD even in versions of the hardware in
+ * which GRCAN_TXCTRL_ONGOING is not cleared properly
+ * in one-shot mode.
+ */
+
+ /* Skip message and discard echo-skb */
+ txrd = grcan_read_reg(&regs->txrd);
+ txrd = grcan_ring_add(txrd, GRCAN_MSG_SIZE, dma->tx.size);
+ grcan_write_reg(&regs->txrd, txrd);
+ catch_up_echo_skb(dev, -1, false);
+
+ if (!priv->resetting && !priv->closing &&
+ !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) {
+ netif_wake_queue(dev);
+ grcan_set_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+ }
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_err(struct net_device *dev, u32 sources, u32 status)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame cf;
+
+ /* Zero potential error_frame */
+ memset(&cf, 0, sizeof(cf));
+
+ /* Message lost interrupt. This might be due to arbitration error, but
+ * is also triggered when there is no one else on the can bus or when
+ * there is a problem with the hardware interface or the bus itself. As
+ * arbitration errors can not be singled out, no error frames are
+ * generated reporting this event as an arbitration error.
+ */
+ if (sources & GRCAN_IRQ_TXLOSS) {
+ /* Take care of failed one-shot transmit */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ grcan_lost_one_shot_frame(dev);
+
+ /* Stop printing as soon as error passive or bus off is in
+ * effect to limit the amount of txloss debug printouts.
+ */
+ if (!(status & GRCAN_STAT_ERRCTR_RELATED)) {
+ netdev_dbg(dev, "tx message lost\n");
+ stats->tx_errors++;
+ }
+ }
+
+ /* Conditions dealing with the error counters. There is no interrupt for
+ * error warning, but there are interrupts for increases of the error
+ * counters.
+ */
+ if ((sources & GRCAN_IRQ_ERRCTR_RELATED) ||
+ (status & GRCAN_STAT_ERRCTR_RELATED)) {
+ enum can_state state = priv->can.state;
+ enum can_state oldstate = state;
+ u32 txerr = (status & GRCAN_STAT_TXERRCNT)
+ >> GRCAN_STAT_TXERRCNT_BIT;
+ u32 rxerr = (status & GRCAN_STAT_RXERRCNT)
+ >> GRCAN_STAT_RXERRCNT_BIT;
+
+ /* Figure out current state */
+ if (status & GRCAN_STAT_OFF) {
+ state = CAN_STATE_BUS_OFF;
+ } else if (status & GRCAN_STAT_PASS) {
+ state = CAN_STATE_ERROR_PASSIVE;
+ } else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT ||
+ rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) {
+ state = CAN_STATE_ERROR_WARNING;
+ } else {
+ state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ /* Handle and report state changes */
+ if (state != oldstate) {
+ switch (state) {
+ case CAN_STATE_BUS_OFF:
+ netdev_dbg(dev, "bus-off\n");
+ netif_carrier_off(dev);
+ priv->can.can_stats.bus_off++;
+
+ /* Prevent the hardware from recovering from bus
+ * off on its own if restart is disabled.
+ */
+ if (!priv->can.restart_ms)
+ grcan_stop_hardware(dev);
+
+ cf.can_id |= CAN_ERR_BUSOFF;
+ break;
+
+ case CAN_STATE_ERROR_PASSIVE:
+ netdev_dbg(dev, "Error passive condition\n");
+ priv->can.can_stats.error_passive++;
+
+ cf.can_id |= CAN_ERR_CRTL;
+ if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+ cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+ cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ break;
+
+ case CAN_STATE_ERROR_WARNING:
+ netdev_dbg(dev, "Error warning condition\n");
+ priv->can.can_stats.error_warning++;
+
+ cf.can_id |= CAN_ERR_CRTL;
+ if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+ cf.data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+ cf.data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ break;
+
+ case CAN_STATE_ERROR_ACTIVE:
+ netdev_dbg(dev, "Error active condition\n");
+ cf.can_id |= CAN_ERR_CRTL;
+ break;
+
+ default:
+ /* There are no others at this point */
+ break;
+ }
+ cf.data[6] = txerr;
+ cf.data[7] = rxerr;
+ priv->can.state = state;
+ }
+
+ /* Report automatic restarts */
+ if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) {
+ unsigned long flags;
+
+ cf.can_id |= CAN_ERR_RESTARTED;
+ netdev_dbg(dev, "restarted\n");
+ priv->can.can_stats.restarts++;
+ netif_carrier_on(dev);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!priv->resetting && !priv->closing) {
+ u32 txwr = grcan_read_reg(&regs->txwr);
+
+ if (grcan_txspace(dma->tx.size, txwr,
+ priv->eskbp))
+ netif_wake_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ }
+
+ /* Data overrun interrupt */
+ if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) {
+ netdev_dbg(dev, "got data overrun interrupt\n");
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+
+ cf.can_id |= CAN_ERR_CRTL;
+ cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+
+ /* AHB bus error interrupts (not CAN bus errors) - shut down the
+ * device.
+ */
+ if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) ||
+ (status & GRCAN_STAT_AHBERR)) {
+ char *txrx = "";
+ unsigned long flags;
+
+ if (sources & GRCAN_IRQ_TXAHBERR) {
+ txrx = "on tx ";
+ stats->tx_errors++;
+ } else if (sources & GRCAN_IRQ_RXAHBERR) {
+ txrx = "on rx ";
+ stats->rx_errors++;
+ }
+ netdev_err(dev, "Fatal AHB buss error %s- halting device\n",
+ txrx);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Prevent anything to be enabled again and halt device */
+ priv->closing = true;
+ netif_stop_queue(dev);
+ grcan_stop_hardware(dev);
+ priv->can.state = CAN_STATE_STOPPED;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ /* Pass on error frame if something to report,
+ * i.e. id contains some information
+ */
+ if (cf.can_id) {
+ struct can_frame *skb_cf;
+ struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf);
+
+ if (skb == NULL) {
+ netdev_dbg(dev, "could not allocate error frame\n");
+ return;
+ }
+ skb_cf->can_id |= cf.can_id;
+ memcpy(skb_cf->data, cf.data, sizeof(cf.data));
+
+ netif_rx(skb);
+ }
+}
+
+static irqreturn_t grcan_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ u32 sources, status;
+
+ /* Find out the source */
+ sources = grcan_read_reg(&regs->pimsr);
+ if (!sources)
+ return IRQ_NONE;
+ grcan_write_reg(&regs->picr, sources);
+ status = grcan_read_reg(&regs->stat);
+
+ /* If we got TX progress, the device has not hanged,
+ * so disable the hang timer
+ */
+ if (priv->need_txbug_workaround &&
+ (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_TXLOSS))) {
+ del_timer(&priv->hang_timer);
+ }
+
+ /* Frame(s) received or transmitted */
+ if (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_RX)) {
+ /* Disable tx/rx interrupts and schedule poll(). No need for
+ * locking as interference from a running reset at worst leads
+ * to an extra interrupt.
+ */
+ grcan_clear_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+ napi_schedule(&priv->napi);
+ }
+
+ /* (Potential) error conditions to take care of */
+ if (sources & GRCAN_IRQ_ERRORS)
+ grcan_err(dev, sources, status);
+
+ return IRQ_HANDLED;
+}
+
+/* Reset device and restart operations from where they were.
+ *
+ * This assumes that RXCTRL & RXCTRL is properly disabled and that RX
+ * is not ONGOING (TX might be stuck in ONGOING due to a harwrware bug
+ * for single shot)
+ */
+static void grcan_running_reset(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ unsigned long flags;
+
+ /* This temporarily messes with eskbp, so we need to lock
+ * priv->lock
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->resetting = false;
+ del_timer(&priv->hang_timer);
+ del_timer(&priv->rr_timer);
+
+ if (!priv->closing) {
+ /* Save and reset - config register preserved by grcan_reset */
+ u32 imr = grcan_read_reg(&regs->imr);
+
+ u32 txaddr = grcan_read_reg(&regs->txaddr);
+ u32 txsize = grcan_read_reg(&regs->txsize);
+ u32 txwr = grcan_read_reg(&regs->txwr);
+ u32 txrd = grcan_read_reg(&regs->txrd);
+ u32 eskbp = priv->eskbp;
+
+ u32 rxaddr = grcan_read_reg(&regs->rxaddr);
+ u32 rxsize = grcan_read_reg(&regs->rxsize);
+ u32 rxwr = grcan_read_reg(&regs->rxwr);
+ u32 rxrd = grcan_read_reg(&regs->rxrd);
+
+ grcan_reset(dev);
+
+ /* Restore */
+ grcan_write_reg(&regs->txaddr, txaddr);
+ grcan_write_reg(&regs->txsize, txsize);
+ grcan_write_reg(&regs->txwr, txwr);
+ grcan_write_reg(&regs->txrd, txrd);
+ priv->eskbp = eskbp;
+
+ grcan_write_reg(&regs->rxaddr, rxaddr);
+ grcan_write_reg(&regs->rxsize, rxsize);
+ grcan_write_reg(&regs->rxwr, rxwr);
+ grcan_write_reg(&regs->rxrd, rxrd);
+
+ /* Turn on device again */
+ grcan_write_reg(&regs->imr, imr);
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ grcan_write_reg(&regs->txctrl, GRCAN_TXCTRL_ENABLE
+ | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+ ? GRCAN_TXCTRL_SINGLE : 0));
+ grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+ grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+ /* Start queue if there is size and listen-onle mode is not
+ * enabled
+ */
+ if (grcan_txspace(priv->dma.tx.size, txwr, priv->eskbp) &&
+ !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+ netif_wake_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ netdev_err(dev, "Device reset and restored\n");
+}
+
+/* Waiting time in usecs corresponding to the transmission of three maximum
+ * sized can frames in the given bitrate (in bits/sec). Waiting for this amount
+ * of time makes sure that the can controller have time to finish sending or
+ * receiving a frame with a good margin.
+ *
+ * usecs/sec * number of frames * bits/frame / bits/sec
+ */
+static inline u32 grcan_ongoing_wait_usecs(__u32 bitrate)
+{
+ return 1000000 * 3 * GRCAN_EFF_FRAME_MAX_BITS / bitrate;
+}
+
+/* Set timer so that it will not fire until after a period in which the can
+ * controller have a good margin to finish transmitting a frame unless it has
+ * hanged
+ */
+static inline void grcan_reset_timer(struct timer_list *timer, __u32 bitrate)
+{
+ u32 wait_jiffies = usecs_to_jiffies(grcan_ongoing_wait_usecs(bitrate));
+
+ mod_timer(timer, jiffies + wait_jiffies);
+}
+
+/* Disable channels and schedule a running reset */
+static void grcan_initiate_running_reset(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ unsigned long flags;
+
+ netdev_err(dev, "Device seems hanged - reset scheduled\n");
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* The main body of this function must never be executed again
+ * until after an execution of grcan_running_reset
+ */
+ if (!priv->resetting && !priv->closing) {
+ priv->resetting = true;
+ netif_stop_queue(dev);
+ grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+ grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+ grcan_reset_timer(&priv->rr_timer, priv->can.bittiming.bitrate);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_free_dma_buffers(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_dma *dma = &priv->dma;
+
+ dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
+ dma->base_handle);
+ memset(dma, 0, sizeof(*dma));
+}
+
+static int grcan_allocate_dma_buffers(struct net_device *dev,
+ size_t tsize, size_t rsize)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_dma *dma = &priv->dma;
+ struct grcan_dma_buffer *large = rsize > tsize ? &dma->rx : &dma->tx;
+ struct grcan_dma_buffer *small = rsize > tsize ? &dma->tx : &dma->rx;
+ size_t shift;
+
+ /* Need a whole number of GRCAN_BUFFER_ALIGNMENT for the large,
+ * i.e. first buffer
+ */
+ size_t maxs = max(tsize, rsize);
+ size_t lsize = ALIGN(maxs, GRCAN_BUFFER_ALIGNMENT);
+
+ /* Put the small buffer after that */
+ size_t ssize = min(tsize, rsize);
+
+ /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
+ dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
+ dma->base_buf = dma_alloc_coherent(&dev->dev,
+ dma->base_size,
+ &dma->base_handle,
+ GFP_KERNEL);
+
+ if (!dma->base_buf)
+ return -ENOMEM;
+
+ dma->tx.size = tsize;
+ dma->rx.size = rsize;
+
+ large->handle = ALIGN(dma->base_handle, GRCAN_BUFFER_ALIGNMENT);
+ small->handle = large->handle + lsize;
+ shift = large->handle - dma->base_handle;
+
+ large->buf = dma->base_buf + shift;
+ small->buf = large->buf + lsize;
+
+ return 0;
+}
+
+/* priv->lock *must* be held when calling this function */
+static int grcan_start(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ u32 confop, txctrl;
+
+ grcan_reset(dev);
+
+ grcan_write_reg(&regs->txaddr, priv->dma.tx.handle);
+ grcan_write_reg(&regs->txsize, priv->dma.tx.size);
+ /* regs->txwr, regs->txrd and priv->eskbp already set to 0 by reset */
+
+ grcan_write_reg(&regs->rxaddr, priv->dma.rx.handle);
+ grcan_write_reg(&regs->rxsize, priv->dma.rx.size);
+ /* regs->rxwr and regs->rxrd already set to 0 by reset */
+
+ /* Enable interrupts */
+ grcan_read_reg(&regs->pir);
+ grcan_write_reg(&regs->imr, GRCAN_IRQ_DEFAULT);
+
+ /* Enable interfaces, channels and device */
+ confop = GRCAN_CONF_ABORT
+ | (priv->config.enable0 ? GRCAN_CONF_ENABLE0 : 0)
+ | (priv->config.enable1 ? GRCAN_CONF_ENABLE1 : 0)
+ | (priv->config.select ? GRCAN_CONF_SELECT : 0)
+ | (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY ?
+ GRCAN_CONF_SILENT : 0)
+ | (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ?
+ GRCAN_CONF_SAM : 0);
+ grcan_write_bits(&regs->conf, confop, GRCAN_CONF_OPERATION);
+ txctrl = GRCAN_TXCTRL_ENABLE
+ | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+ ? GRCAN_TXCTRL_SINGLE : 0);
+ grcan_write_reg(&regs->txctrl, txctrl);
+ grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+ grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ return 0;
+}
+
+static int grcan_set_mode(struct net_device *dev, enum can_mode mode)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+ int err = 0;
+
+ if (mode == CAN_MODE_START) {
+ /* This might be called to restart the device to recover from
+ * bus off errors
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->closing || priv->resetting) {
+ err = -EBUSY;
+ } else {
+ netdev_info(dev, "Restarting device\n");
+ grcan_start(dev);
+ if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+ netif_wake_queue(dev);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return err;
+ }
+ return -EOPNOTSUPP;
+}
+
+static int grcan_open(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_dma *dma = &priv->dma;
+ unsigned long flags;
+ int err;
+
+ /* Allocate memory */
+ err = grcan_allocate_dma_buffers(dev, priv->config.txsize,
+ priv->config.rxsize);
+ if (err) {
+ netdev_err(dev, "could not allocate DMA buffers\n");
+ return err;
+ }
+
+ priv->echo_skb = kzalloc(dma->tx.size * sizeof(*priv->echo_skb),
+ GFP_KERNEL);
+ if (!priv->echo_skb) {
+ err = -ENOMEM;
+ goto exit_free_dma_buffers;
+ }
+ priv->can.echo_skb_max = dma->tx.size;
+ priv->can.echo_skb = priv->echo_skb;
+
+ priv->txdlc = kzalloc(dma->tx.size * sizeof(*priv->txdlc), GFP_KERNEL);
+ if (!priv->txdlc) {
+ err = -ENOMEM;
+ goto exit_free_echo_skb;
+ }
+
+ /* Get can device up */
+ err = open_candev(dev);
+ if (err)
+ goto exit_free_txdlc;
+
+ err = request_irq(dev->irq, grcan_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (err)
+ goto exit_close_candev;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ napi_enable(&priv->napi);
+ grcan_start(dev);
+ if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+ netif_start_queue(dev);
+ priv->resetting = false;
+ priv->closing = false;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+
+exit_close_candev:
+ close_candev(dev);
+exit_free_txdlc:
+ kfree(priv->txdlc);
+exit_free_echo_skb:
+ kfree(priv->echo_skb);
+exit_free_dma_buffers:
+ grcan_free_dma_buffers(dev);
+ return err;
+}
+
+static int grcan_close(struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ napi_disable(&priv->napi);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->closing = true;
+ if (priv->need_txbug_workaround) {
+ del_timer_sync(&priv->hang_timer);
+ del_timer_sync(&priv->rr_timer);
+ }
+ netif_stop_queue(dev);
+ grcan_stop_hardware(dev);
+ priv->can.state = CAN_STATE_STOPPED;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ free_irq(dev->irq, dev);
+ close_candev(dev);
+
+ grcan_free_dma_buffers(dev);
+ priv->can.echo_skb_max = 0;
+ priv->can.echo_skb = NULL;
+ kfree(priv->echo_skb);
+ kfree(priv->txdlc);
+
+ return 0;
+}
+
+static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+ int work_done;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ work_done = catch_up_echo_skb(dev, budget, true);
+ if (work_done) {
+ if (!priv->resetting && !priv->closing &&
+ !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+ netif_wake_queue(dev);
+
+ /* With napi we don't get TX interrupts for a while,
+ * so prevent a running reset while catching up
+ */
+ if (priv->need_txbug_workaround)
+ del_timer(&priv->hang_timer);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return work_done;
+}
+
+static int grcan_receive(struct net_device *dev, int budget)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ u32 wr, rd, startrd;
+ u32 *slot;
+ u32 i, rtr, eff, j, shift;
+ int work_done = 0;
+
+ rd = grcan_read_reg(&regs->rxrd);
+ startrd = rd;
+ for (work_done = 0; work_done < budget; work_done++) {
+ /* Check for packet to receive */
+ wr = grcan_read_reg(&regs->rxwr);
+ if (rd == wr)
+ break;
+
+ /* Take care of packet */
+ skb = alloc_can_skb(dev, &cf);
+ if (skb == NULL) {
+ netdev_err(dev,
+ "dropping frame: skb allocation failed\n");
+ stats->rx_dropped++;
+ continue;
+ }
+
+ slot = dma->rx.buf + rd;
+ eff = slot[0] & GRCAN_MSG_IDE;
+ rtr = slot[0] & GRCAN_MSG_RTR;
+ if (eff) {
+ cf->can_id = ((slot[0] & GRCAN_MSG_EID)
+ >> GRCAN_MSG_EID_BIT);
+ cf->can_id |= CAN_EFF_FLAG;
+ } else {
+ cf->can_id = ((slot[0] & GRCAN_MSG_BID)
+ >> GRCAN_MSG_BID_BIT);
+ }
+ cf->can_dlc = get_can_dlc((slot[1] & GRCAN_MSG_DLC)
+ >> GRCAN_MSG_DLC_BIT);
+ if (rtr) {
+ cf->can_id |= CAN_RTR_FLAG;
+ } else {
+ for (i = 0; i < cf->can_dlc; i++) {
+ j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+ shift = GRCAN_MSG_DATA_SHIFT(i);
+ cf->data[i] = (u8)(slot[j] >> shift);
+ }
+ }
+ netif_receive_skb(skb);
+
+ /* Update statistics and read pointer */
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size);
+ }
+
+ /* Make sure everything is read before allowing hardware to
+ * use the memory
+ */
+ mb();
+
+ /* Update read pointer - no need to check for ongoing */
+ if (likely(rd != startrd))
+ grcan_write_reg(&regs->rxrd, rd);
+
+ return work_done;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget)
+{
+ struct grcan_priv *priv = container_of(napi, struct grcan_priv, napi);
+ struct net_device *dev = priv->dev;
+ struct grcan_registers __iomem *regs = priv->regs;
+ unsigned long flags;
+ int tx_work_done, rx_work_done;
+ int rx_budget = budget / 2;
+ int tx_budget = budget - rx_budget;
+
+ /* Half of the budget for receiveing messages */
+ rx_work_done = grcan_receive(dev, rx_budget);
+
+ /* Half of the budget for transmitting messages as that can trigger echo
+ * frames being received
+ */
+ tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
+
+ if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
+ napi_complete(napi);
+
+ /* Guarantee no interference with a running reset that otherwise
+ * could turn off interrupts.
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Enable tx and rx interrupts again. No need to check
+ * priv->closing as napi_disable in grcan_close is waiting for
+ * scheduled napi calls to finish.
+ */
+ grcan_set_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ return rx_work_done + tx_work_done;
+}
+
+/* Work tx bug by waiting while for the risky situation to clear. If that fails,
+ * drop a frame in one-shot mode or indicate a busy device otherwise.
+ *
+ * Returns 0 on successful wait. Otherwise it sets *netdev_tx_status to the
+ * value that should be returned by grcan_start_xmit when aborting the xmit.
+ */
+static int grcan_txbug_workaround(struct net_device *dev, struct sk_buff *skb,
+ u32 txwr, u32 oneshotmode,
+ netdev_tx_t *netdev_tx_status)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ int i;
+ unsigned long flags;
+
+ /* Wait a while for ongoing to be cleared or read pointer to catch up to
+ * write pointer. The latter is needed due to a bug in older versions of
+ * GRCAN in which ONGOING is not cleared properly one-shot mode when a
+ * transmission fails.
+ */
+ for (i = 0; i < GRCAN_SHORTWAIT_USECS; i++) {
+ udelay(1);
+ if (!grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ONGOING) ||
+ grcan_read_reg(&regs->txrd) == txwr) {
+ return 0;
+ }
+ }
+
+ /* Clean up, in case the situation was not resolved */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->resetting && !priv->closing) {
+ /* Queue might have been stopped earlier in grcan_start_xmit */
+ if (grcan_txspace(dma->tx.size, txwr, priv->eskbp))
+ netif_wake_queue(dev);
+ /* Set a timer to resolve a hanged tx controller */
+ if (!timer_pending(&priv->hang_timer))
+ grcan_reset_timer(&priv->hang_timer,
+ priv->can.bittiming.bitrate);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (oneshotmode) {
+ /* In one-shot mode we should never end up here because
+ * then the interrupt handler increases txrd on TXLOSS,
+ * but it is consistent with one-shot mode to drop the
+ * frame in this case.
+ */
+ kfree_skb(skb);
+ *netdev_tx_status = NETDEV_TX_OK;
+ } else {
+ /* In normal mode the socket-can transmission queue get
+ * to keep the frame so that it can be retransmitted
+ * later
+ */
+ *netdev_tx_status = NETDEV_TX_BUSY;
+ }
+ return -EBUSY;
+}
+
+/* Notes on the tx cyclic buffer handling:
+ *
+ * regs->txwr - the next slot for the driver to put data to be sent
+ * regs->txrd - the next slot for the device to read data
+ * priv->eskbp - the next slot for the driver to call can_put_echo_skb for
+ *
+ * grcan_start_xmit can enter more messages as long as regs->txwr does
+ * not reach priv->eskbp (within 1 message gap)
+ *
+ * The device sends messages until regs->txrd reaches regs->txwr
+ *
+ * The interrupt calls handler calls can_put_echo_skb until
+ * priv->eskbp reaches regs->txrd
+ */
+static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct grcan_priv *priv = netdev_priv(dev);
+ struct grcan_registers __iomem *regs = priv->regs;
+ struct grcan_dma *dma = &priv->dma;
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ u32 id, txwr, txrd, space, txctrl;
+ int slotindex;
+ u32 *slot;
+ u32 i, rtr, eff, dlc, tmp, err;
+ int j, shift;
+ unsigned long flags;
+ u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
+
+ if (can_dropped_invalid_skb(dev, skb))
+ return NETDEV_TX_OK;
+
+ /* Trying to transmit in silent mode will generate error interrupts, but
+ * this should never happen - the queue should not have been started.
+ */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ return NETDEV_TX_BUSY;
+
+ /* Reads of priv->eskbp and shut-downs of the queue needs to
+ * be atomic towards the updates to priv->eskbp and wake-ups
+ * of the queue in the interrupt handler.
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ txwr = grcan_read_reg(&regs->txwr);
+ space = grcan_txspace(dma->tx.size, txwr, priv->eskbp);
+
+ slotindex = txwr / GRCAN_MSG_SIZE;
+ slot = dma->tx.buf + txwr;
+
+ if (unlikely(space == 1))
+ netif_stop_queue(dev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /* End of critical section*/
+
+ /* This should never happen. If circular buffer is full, the
+ * netif_stop_queue should have been stopped already.
+ */
+ if (unlikely(!space)) {
+ netdev_err(dev, "No buffer space, but queue is non-stopped.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ /* Convert and write CAN message to DMA buffer */
+ eff = cf->can_id & CAN_EFF_FLAG;
+ rtr = cf->can_id & CAN_RTR_FLAG;
+ id = cf->can_id & (eff ? CAN_EFF_MASK : CAN_SFF_MASK);
+ dlc = cf->can_dlc;
+ if (eff)
+ tmp = (id << GRCAN_MSG_EID_BIT) & GRCAN_MSG_EID;
+ else
+ tmp = (id << GRCAN_MSG_BID_BIT) & GRCAN_MSG_BID;
+ slot[0] = (eff ? GRCAN_MSG_IDE : 0) | (rtr ? GRCAN_MSG_RTR : 0) | tmp;
+
+ slot[1] = ((dlc << GRCAN_MSG_DLC_BIT) & GRCAN_MSG_DLC);
+ slot[2] = 0;
+ slot[3] = 0;
+ for (i = 0; i < dlc; i++) {
+ j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+ shift = GRCAN_MSG_DATA_SHIFT(i);
+ slot[j] |= cf->data[i] << shift;
+ }
+
+ /* Checking that channel has not been disabled. These cases
+ * should never happen
+ */
+ txctrl = grcan_read_reg(&regs->txctrl);
+ if (!(txctrl & GRCAN_TXCTRL_ENABLE))
+ netdev_err(dev, "tx channel spuriously disabled\n");
+
+ if (oneshotmode && !(txctrl & GRCAN_TXCTRL_SINGLE))
+ netdev_err(dev, "one-shot mode spuriously disabled\n");
+
+ /* Bug workaround for old version of grcan where updating txwr
+ * in the same clock cycle as the controller updates txrd to
+ * the current txwr could hang the can controller
+ */
+ if (priv->need_txbug_workaround) {
+ txrd = grcan_read_reg(&regs->txrd);
+ if (unlikely(grcan_ring_sub(txwr, txrd, dma->tx.size) == 1)) {
+ netdev_tx_t txstatus;
+
+ err = grcan_txbug_workaround(dev, skb, txwr,
+ oneshotmode, &txstatus);
+ if (err)
+ return txstatus;
+ }
+ }
+
+ /* Prepare skb for echoing. This must be after the bug workaround above
+ * as ownership of the skb is passed on by calling can_put_echo_skb.
+ * Returning NETDEV_TX_BUSY or accessing skb or cf after a call to
+ * can_put_echo_skb would be an error unless other measures are
+ * taken.
+ */
+ priv->txdlc[slotindex] = cf->can_dlc; /* Store dlc for statistics */
+ can_put_echo_skb(skb, dev, slotindex);
+
+ /* Make sure everything is written before allowing hardware to
+ * read from the memory
+ */
+ wmb();
+
+ /* Update write pointer to start transmission */
+ grcan_write_reg(&regs->txwr,
+ grcan_ring_add(txwr, GRCAN_MSG_SIZE, dma->tx.size));
+
+ return NETDEV_TX_OK;
+}
+
+/* ========== Setting up sysfs interface and module parameters ========== */
+
+#define GRCAN_NOT_BOOL(unsigned_val) ((unsigned_val) > 1)
+
+#define GRCAN_MODULE_PARAM(name, mtype, valcheckf, desc) \
+ static void grcan_sanitize_##name(struct platform_device *pd) \
+ { \
+ struct grcan_device_config grcan_default_config \
+ = GRCAN_DEFAULT_DEVICE_CONFIG; \
+ if (valcheckf(grcan_module_config.name)) { \
+ dev_err(&pd->dev, \
+ "Invalid module parameter value for " \
+ #name " - setting default\n"); \
+ grcan_module_config.name = \
+ grcan_default_config.name; \
+ } \
+ } \
+ module_param_named(name, grcan_module_config.name, \
+ mtype, S_IRUGO); \
+ MODULE_PARM_DESC(name, desc)
+
+#define GRCAN_CONFIG_ATTR(name, desc) \
+ static ssize_t grcan_store_##name(struct device *sdev, \
+ struct device_attribute *att, \
+ const char *buf, \
+ size_t count) \
+ { \
+ struct net_device *dev = to_net_dev(sdev); \
+ struct grcan_priv *priv = netdev_priv(dev); \
+ u8 val; \
+ int ret; \
+ if (dev->flags & IFF_UP) \
+ return -EBUSY; \
+ ret = kstrtou8(buf, 0, &val); \
+ if (ret < 0 || val > 1) \
+ return -EINVAL; \
+ priv->config.name = val; \
+ return count; \
+ } \
+ static ssize_t grcan_show_##name(struct device *sdev, \
+ struct device_attribute *att, \
+ char *buf) \
+ { \
+ struct net_device *dev = to_net_dev(sdev); \
+ struct grcan_priv *priv = netdev_priv(dev); \
+ return sprintf(buf, "%d\n", priv->config.name); \
+ } \
+ static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \
+ grcan_show_##name, \
+ grcan_store_##name); \
+ GRCAN_MODULE_PARAM(name, ushort, GRCAN_NOT_BOOL, desc)
+
+/* The following configuration options are made available both via module
+ * parameters and writable sysfs files. See the chapter about GRCAN in the
+ * documentation for the GRLIB VHDL library for further details.
+ */
+GRCAN_CONFIG_ATTR(enable0,
+ "Configuration of physical interface 0. Determines\n" \
+ "the \"Enable 0\" bit of the configuration register.\n" \
+ "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(enable1,
+ "Configuration of physical interface 1. Determines\n" \
+ "the \"Enable 1\" bit of the configuration register.\n" \
+ "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(select,
+ "Select which physical interface to use.\n" \
+ "Format: 0 | 1\nDefault: 0\n");
+
+/* The tx and rx buffer size configuration options are only available via module
+ * parameters.
+ */
+GRCAN_MODULE_PARAM(txsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+ "Sets the size of the tx buffer.\n" \
+ "Format: <unsigned int> where (txsize & ~0x1fffc0) == 0\n" \
+ "Default: 1024\n");
+GRCAN_MODULE_PARAM(rxsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+ "Sets the size of the rx buffer.\n" \
+ "Format: <unsigned int> where (size & ~0x1fffc0) == 0\n" \
+ "Default: 1024\n");
+
+/* Function that makes sure that configuration done using
+ * module parameters are set to valid values
+ */
+static void grcan_sanitize_module_config(struct platform_device *ofdev)
+{
+ grcan_sanitize_enable0(ofdev);
+ grcan_sanitize_enable1(ofdev);
+ grcan_sanitize_select(ofdev);
+ grcan_sanitize_txsize(ofdev);
+ grcan_sanitize_rxsize(ofdev);
+}
+
+static const struct attribute *const sysfs_grcan_attrs[] = {
+ /* Config attrs */
+ &dev_attr_enable0.attr,
+ &dev_attr_enable1.attr,
+ &dev_attr_select.attr,
+ NULL,
+};
+
+static const struct attribute_group sysfs_grcan_group = {
+ .name = "grcan",
+ .attrs = (struct attribute **)sysfs_grcan_attrs,
+};
+
+/* ========== Setting up the driver ========== */
+
+static const struct net_device_ops grcan_netdev_ops = {
+ .ndo_open = grcan_open,
+ .ndo_stop = grcan_close,
+ .ndo_start_xmit = grcan_start_xmit,
+};
+
+static int grcan_setup_netdev(struct platform_device *ofdev,
+ void __iomem *base,
+ int irq, u32 ambafreq, bool txbug)
+{
+ struct net_device *dev;
+ struct grcan_priv *priv;
+ struct grcan_registers __iomem *regs;
+ int err;
+
+ dev = alloc_candev(sizeof(struct grcan_priv), 0);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->irq = irq;
+ dev->flags |= IFF_ECHO;
+ dev->netdev_ops = &grcan_netdev_ops;
+ dev->sysfs_groups[0] = &sysfs_grcan_group;
+
+ priv = netdev_priv(dev);
+ memcpy(&priv->config, &grcan_module_config,
+ sizeof(struct grcan_device_config));
+ priv->dev = dev;
+ priv->regs = base;
+ priv->can.bittiming_const = &grcan_bittiming_const;
+ priv->can.do_set_bittiming = grcan_set_bittiming;
+ priv->can.do_set_mode = grcan_set_mode;
+ priv->can.do_get_berr_counter = grcan_get_berr_counter;
+ priv->can.clock.freq = ambafreq;
+ priv->can.ctrlmode_supported =
+ CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_ONE_SHOT;
+ priv->need_txbug_workaround = txbug;
+
+ /* Discover if triple sampling is supported by hardware */
+ regs = priv->regs;
+ grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+ grcan_set_bits(&regs->conf, GRCAN_CONF_SAM);
+ if (grcan_read_bits(&regs->conf, GRCAN_CONF_SAM)) {
+ priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+ dev_dbg(&ofdev->dev, "Hardware supports triple-sampling\n");
+ }
+
+ spin_lock_init(&priv->lock);
+
+ if (priv->need_txbug_workaround) {
+ init_timer(&priv->rr_timer);
+ priv->rr_timer.function = grcan_running_reset;
+ priv->rr_timer.data = (unsigned long)dev;
+
+ init_timer(&priv->hang_timer);
+ priv->hang_timer.function = grcan_initiate_running_reset;
+ priv->hang_timer.data = (unsigned long)dev;
+ }
+
+ netif_napi_add(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT);
+
+ SET_NETDEV_DEV(dev, &ofdev->dev);
+ dev_info(&ofdev->dev, "regs=0x%p, irq=%d, clock=%d\n",
+ priv->regs, dev->irq, priv->can.clock.freq);
+
+ err = register_candev(dev);
+ if (err)
+ goto exit_free_candev;
+
+ dev_set_drvdata(&ofdev->dev, dev);
+
+ /* Reset device to allow bit-timing to be set. No need to call
+ * grcan_reset at this stage. That is done in grcan_open.
+ */
+ grcan_write_reg(&regs->ctrl, GRCAN_CTRL_RESET);
+
+ return 0;
+exit_free_candev:
+ free_candev(dev);
+ return err;
+}
+
+static int grcan_probe(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+ struct resource *res;
+ u32 sysid, ambafreq;
+ int irq, err;
+ void __iomem *base;
+ bool txbug = true;
+
+ /* Compare GRLIB version number with the first that does not
+ * have the tx bug (see start_xmit)
+ */
+ err = of_property_read_u32(np, "systemid", &sysid);
+ if (!err && ((sysid & GRLIB_VERSION_MASK)
+ >= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
+ txbug = false;
+
+ err = of_property_read_u32(np, "freq", &ambafreq);
+ if (err) {
+ dev_err(&ofdev->dev, "unable to fetch \"freq\" property\n");
+ goto exit_error;
+ }
+
+ res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+ base = devm_request_and_ioremap(&ofdev->dev, res);
+ if (!base) {
+ dev_err(&ofdev->dev, "couldn't map IO resource\n");
+ err = -EADDRNOTAVAIL;
+ goto exit_error;
+ }
+
+ irq = irq_of_parse_and_map(np, GRCAN_IRQIX_IRQ);
+ if (!irq) {
+ dev_err(&ofdev->dev, "no irq found\n");
+ err = -ENODEV;
+ goto exit_error;
+ }
+
+ grcan_sanitize_module_config(ofdev);
+
+ err = grcan_setup_netdev(ofdev, base, irq, ambafreq, txbug);
+ if (err)
+ goto exit_dispose_irq;
+
+ return 0;
+
+exit_dispose_irq:
+ irq_dispose_mapping(irq);
+exit_error:
+ dev_err(&ofdev->dev,
+ "%s socket CAN driver initialization failed with error %d\n",
+ DRV_NAME, err);
+ return err;
+}
+
+static int grcan_remove(struct platform_device *ofdev)
+{
+ struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+ struct grcan_priv *priv = netdev_priv(dev);
+
+ unregister_candev(dev); /* Will in turn call grcan_close */
+
+ irq_dispose_mapping(dev->irq);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ netif_napi_del(&priv->napi);
+ free_candev(dev);
+
+ return 0;
+}
+
+static struct of_device_id grcan_match[] = {
+ {.name = "GAISLER_GRCAN"},
+ {.name = "01_03d"},
+ {.name = "GAISLER_GRHCAN"},
+ {.name = "01_034"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, grcan_match);
+
+static struct platform_driver grcan_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = grcan_match,
+ },
+ .probe = grcan_probe,
+ .remove = grcan_remove,
+};
+
+module_platform_driver(grcan_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION("Socket CAN driver for Aeroflex Gaisler GRCAN");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 7edadee487ba..c4bc1d2e2033 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -365,7 +365,7 @@ static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
* ICAN3 "new-style" Host Interface Setup
*/
-static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
+static void ican3_init_new_host_interface(struct ican3_dev *mod)
{
struct ican3_new_desc desc;
unsigned long flags;
@@ -444,7 +444,7 @@ static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
* ICAN3 Fast Host Interface Setup
*/
-static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
+static void ican3_init_fast_host_interface(struct ican3_dev *mod)
{
struct ican3_fast_desc desc;
unsigned long flags;
@@ -631,7 +631,7 @@ static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
* Quick Pre-constructed Messages
*/
-static int __devinit ican3_msg_connect(struct ican3_dev *mod)
+static int ican3_msg_connect(struct ican3_dev *mod)
{
struct ican3_msg msg;
@@ -642,7 +642,7 @@ static int __devinit ican3_msg_connect(struct ican3_dev *mod)
return ican3_send_msg(mod, &msg);
}
-static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
+static int ican3_msg_disconnect(struct ican3_dev *mod)
{
struct ican3_msg msg;
@@ -653,7 +653,7 @@ static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
return ican3_send_msg(mod, &msg);
}
-static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
+static int ican3_msg_newhostif(struct ican3_dev *mod)
{
struct ican3_msg msg;
int ret;
@@ -674,7 +674,7 @@ static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
return 0;
}
-static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
+static int ican3_msg_fasthostif(struct ican3_dev *mod)
{
struct ican3_msg msg;
unsigned int addr;
@@ -707,7 +707,7 @@ static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
* Setup the CAN filter to either accept or reject all
* messages from the CAN bus.
*/
-static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept)
+static int ican3_set_id_filter(struct ican3_dev *mod, bool accept)
{
struct ican3_msg msg;
int ret;
@@ -1421,7 +1421,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
return -ETIMEDOUT;
}
-static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
+static void ican3_shutdown_module(struct ican3_dev *mod)
{
ican3_msg_disconnect(mod);
ican3_reset_module(mod);
@@ -1430,7 +1430,7 @@ static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
/*
* Startup an ICAN module, bringing it into fast mode
*/
-static int __devinit ican3_startup_module(struct ican3_dev *mod)
+static int ican3_startup_module(struct ican3_dev *mod)
{
int ret;
@@ -1692,7 +1692,7 @@ static int ican3_get_berr_counter(const struct net_device *ndev,
return ret;
ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);
- if (ret <= 0) {
+ if (ret == 0) {
dev_info(mod->dev, "%s timed out\n", __func__);
return -ETIMEDOUT;
}
@@ -1718,7 +1718,7 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,
return ret;
ret = wait_for_completion_timeout(&mod->termination_comp, HZ);
- if (ret <= 0) {
+ if (ret == 0) {
dev_info(mod->dev, "%s timed out\n", __func__);
return -ETIMEDOUT;
}
@@ -1760,7 +1760,7 @@ static struct attribute_group ican3_sysfs_attr_group = {
* PCI Subsystem
*/
-static int __devinit ican3_probe(struct platform_device *pdev)
+static int ican3_probe(struct platform_device *pdev)
{
struct janz_platform_data *pdata;
struct net_device *ndev;
@@ -1898,7 +1898,7 @@ out_return:
return ret;
}
-static int __devexit ican3_remove(struct platform_device *pdev)
+static int ican3_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ican3_dev *mod = netdev_priv(ndev);
@@ -1927,7 +1927,7 @@ static struct platform_driver ican3_driver = {
.owner = THIS_MODULE,
},
.probe = ican3_probe,
- .remove = __devexit_p(ican3_remove),
+ .remove = ican3_remove,
};
module_platform_driver(ican3_driver);
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 26e7129332ab..5eaf47b8e37b 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -981,7 +981,7 @@ static const struct net_device_ops mcp251x_netdev_ops = {
.ndo_start_xmit = mcp251x_hard_start_xmit,
};
-static int __devinit mcp251x_can_probe(struct spi_device *spi)
+static int mcp251x_can_probe(struct spi_device *spi)
{
struct net_device *net;
struct mcp251x_priv *priv;
@@ -1100,7 +1100,7 @@ error_out:
return ret;
}
-static int __devexit mcp251x_can_remove(struct spi_device *spi)
+static int mcp251x_can_remove(struct spi_device *spi)
{
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
@@ -1198,7 +1198,7 @@ static struct spi_driver mcp251x_can_driver = {
.id_table = mcp251x_id_table,
.probe = mcp251x_can_probe,
- .remove = __devexit_p(mcp251x_can_remove),
+ .remove = mcp251x_can_remove,
.suspend = mcp251x_can_suspend,
.resume = mcp251x_can_resume,
};
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 799c354083c4..668850e441dc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -43,14 +43,13 @@ struct mpc5xxx_can_data {
};
#ifdef CONFIG_PPC_MPC52xx
-static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = {
+static struct of_device_id mpc52xx_cdm_ids[] = {
{ .compatible = "fsl,mpc5200-cdm", },
{}
};
-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
- const char *clock_name,
- int *mscan_clksrc)
+static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+ const char *clock_name, int *mscan_clksrc)
{
unsigned int pvr;
struct mpc52xx_cdm __iomem *cdm;
@@ -101,9 +100,8 @@ static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
return freq;
}
#else /* !CONFIG_PPC_MPC52xx */
-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
- const char *clock_name,
- int *mscan_clksrc)
+static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+ const char *clock_name, int *mscan_clksrc)
{
return 0;
}
@@ -124,14 +122,13 @@ struct mpc512x_clockctl {
u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */
};
-static struct of_device_id __devinitdata mpc512x_clock_ids[] = {
+static struct of_device_id mpc512x_clock_ids[] = {
{ .compatible = "fsl,mpc5121-clock", },
{}
};
-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
- const char *clock_name,
- int *mscan_clksrc)
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+ const char *clock_name, int *mscan_clksrc)
{
struct mpc512x_clockctl __iomem *clockctl;
struct device_node *np_clock;
@@ -239,16 +236,15 @@ exit_put:
return freq;
}
#else /* !CONFIG_PPC_MPC512x */
-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
- const char *clock_name,
- int *mscan_clksrc)
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+ const char *clock_name, int *mscan_clksrc)
{
return 0;
}
#endif /* CONFIG_PPC_MPC512x */
static const struct of_device_id mpc5xxx_can_table[];
-static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
+static int mpc5xxx_can_probe(struct platform_device *ofdev)
{
const struct of_device_id *match;
const struct mpc5xxx_can_data *data;
@@ -323,7 +319,7 @@ exit_unmap_mem:
return err;
}
-static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev)
+static int mpc5xxx_can_remove(struct platform_device *ofdev)
{
struct net_device *dev = dev_get_drvdata(&ofdev->dev);
struct mscan_priv *priv = netdev_priv(dev);
@@ -380,22 +376,23 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
}
#endif
-static const struct mpc5xxx_can_data __devinitconst mpc5200_can_data = {
+static const struct mpc5xxx_can_data mpc5200_can_data = {
.type = MSCAN_TYPE_MPC5200,
.get_clock = mpc52xx_can_get_clock,
};
-static const struct mpc5xxx_can_data __devinitconst mpc5121_can_data = {
+static const struct mpc5xxx_can_data mpc5121_can_data = {
.type = MSCAN_TYPE_MPC5121,
.get_clock = mpc512x_can_get_clock,
};
-static const struct of_device_id __devinitconst mpc5xxx_can_table[] = {
+static const struct of_device_id mpc5xxx_can_table[] = {
{ .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, },
/* Note that only MPC5121 Rev. 2 (and later) is supported */
{ .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
{},
};
+MODULE_DEVICE_TABLE(of, mpc5xxx_can_table);
static struct platform_driver mpc5xxx_can_driver = {
.driver = {
@@ -404,7 +401,7 @@ static struct platform_driver mpc5xxx_can_driver = {
.of_match_table = mpc5xxx_can_table,
},
.probe = mpc5xxx_can_probe,
- .remove = __devexit_p(mpc5xxx_can_remove),
+ .remove = mpc5xxx_can_remove,
#ifdef CONFIG_PM
.suspend = mpc5xxx_can_suspend,
.resume = mpc5xxx_can_resume,
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 2b104d5f422c..e6b40954e204 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -517,12 +517,8 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
{
- struct mscan_priv *priv = netdev_priv(dev);
int ret = 0;
- if (!priv->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
ret = mscan_restart(dev);
@@ -590,8 +586,6 @@ static int mscan_open(struct net_device *dev)
goto exit_napi_disable;
}
- priv->open_time = jiffies;
-
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
setbits8(&regs->canctl1, MSCAN_LISTEN);
else
@@ -606,7 +600,6 @@ static int mscan_open(struct net_device *dev)
return 0;
exit_free_irq:
- priv->open_time = 0;
free_irq(dev->irq, dev);
exit_napi_disable:
napi_disable(&priv->napi);
@@ -627,7 +620,6 @@ static int mscan_close(struct net_device *dev)
mscan_set_mode(dev, MSCAN_INIT_MODE);
close_candev(dev);
free_irq(dev->irq, dev);
- priv->open_time = 0;
return 0;
}
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index b43e9f5d3268..af2ed8baf0a3 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -281,7 +281,6 @@ struct tx_queue_entry {
struct mscan_priv {
struct can_priv can; /* must be the first member */
unsigned int type; /* MSCAN type variants */
- long open_time;
unsigned long flags;
void __iomem *reg_base; /* ioremap'ed address to registers */
u8 shadow_statflg;
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 48b3d62b34cb..7d1748575b1f 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -954,7 +954,7 @@ static const struct net_device_ops pch_can_netdev_ops = {
.ndo_start_xmit = pch_xmit,
};
-static void __devexit pch_can_remove(struct pci_dev *pdev)
+static void pch_can_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct pch_can_priv *priv = netdev_priv(ndev);
@@ -1178,7 +1178,7 @@ static int pch_can_get_berr_counter(const struct net_device *dev,
return 0;
}
-static int __devinit pch_can_probe(struct pci_dev *pdev,
+static int pch_can_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct net_device *ndev;
@@ -1269,7 +1269,7 @@ static struct pci_driver pch_can_pci_driver = {
.name = "pch_can",
.id_table = pch_pci_tbl,
.probe = pch_can_probe,
- .remove = __devexit_p(pch_can_remove),
+ .remove = pch_can_remove,
.suspend = pch_can_suspend,
.resume = pch_can_resume,
};
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 03df9a8f2bbf..92f73c708a3d 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -21,7 +21,7 @@ config CAN_SJA1000_PLATFORM
config CAN_SJA1000_OF_PLATFORM
tristate "Generic OF Platform Bus based SJA1000 driver"
- depends on PPC_OF
+ depends on OF
---help---
This driver adds support for the SJA1000 chips connected to
the OpenFirmware "platform bus" found on embedded systems with
@@ -93,6 +93,7 @@ config CAN_PLX_PCI
- Marathon CAN-bus-PCI card (http://www.marathon.ru/)
- TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
- IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
+ - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
config CAN_TSCAN1
tristate "TS-CAN1 PC104 boards"
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
index 5c6d412bafb5..036a326836b2 100644
--- a/drivers/net/can/sja1000/ems_pci.c
+++ b/drivers/net/can/sja1000/ems_pci.c
@@ -220,8 +220,8 @@ static void ems_pci_card_reset(struct ems_pci_card *card)
* Probe PCI device for EMS CAN signature and register each available
* CAN channel to SJA1000 Socket-CAN subsystem.
*/
-static int __devinit ems_pci_add_card(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ems_pci_add_card(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct sja1000_priv *priv;
struct net_device *dev;
diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
index 075a5457a190..5c2f3fbbf5ae 100644
--- a/drivers/net/can/sja1000/ems_pcmcia.c
+++ b/drivers/net/can/sja1000/ems_pcmcia.c
@@ -166,8 +166,7 @@ static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
* Probe PCI device for EMS CAN signature and register each available
* CAN channel to SJA1000 Socket-CAN subsystem.
*/
-static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
- unsigned long base)
+static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
{
struct sja1000_priv *priv;
struct net_device *dev;
@@ -256,7 +255,7 @@ failure_cleanup:
/*
* Setup PCMCIA socket and probe for EMS CPC-CARD
*/
-static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
+static int ems_pcmcia_probe(struct pcmcia_device *dev)
{
int csval;
diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
index 23ed6ea4c7c3..37b0381f532e 100644
--- a/drivers/net/can/sja1000/kvaser_pci.c
+++ b/drivers/net/can/sja1000/kvaser_pci.c
@@ -290,8 +290,8 @@ failure:
return err;
}
-static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int kvaser_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int err;
struct net_device *master_dev = NULL;
@@ -379,7 +379,7 @@ failure:
}
-static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev)
+static void kvaser_pci_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -394,7 +394,7 @@ static struct pci_driver kvaser_pci_driver = {
.name = DRV_NAME,
.id_table = kvaser_pci_tbl,
.probe = kvaser_pci_init_one,
- .remove = __devexit_p(kvaser_pci_remove_one),
+ .remove = kvaser_pci_remove_one,
};
module_pci_driver(kvaser_pci_driver);
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index 6525dbcca4e3..d84888f03d92 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -551,8 +551,7 @@ static void peak_pci_post_irq(const struct sja1000_priv *priv)
writew(chan->icr_mask, chan->cfg_base + PITA_ICR);
}
-static int __devinit peak_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct sja1000_priv *priv;
struct peak_pci_chan *chan;
@@ -717,7 +716,7 @@ failure_disable_pci:
return err;
}
-static void __devexit peak_pci_remove(struct pci_dev *pdev)
+static void peak_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
struct sja1000_priv *priv = netdev_priv(dev);
@@ -757,7 +756,7 @@ static struct pci_driver peak_pci_driver = {
.name = DRV_NAME,
.id_table = peak_pci_tbl,
.probe = peak_pci_probe,
- .remove = __devexit_p(peak_pci_remove),
+ .remove = peak_pci_remove,
};
module_pci_driver(peak_pci_driver);
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
index 272a85f32b14..f1175142b0a0 100644
--- a/drivers/net/can/sja1000/peak_pcmcia.c
+++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -632,7 +632,7 @@ static void pcan_free(struct pcmcia_device *pdev)
/*
* setup PCMCIA socket and probe for PEAK-System PC-CARD
*/
-static int __devinit pcan_probe(struct pcmcia_device *pdev)
+static int pcan_probe(struct pcmcia_device *pdev)
{
struct pcan_pccard *card;
int err;
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 8bc95982840f..11d1062a9449 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -44,6 +44,7 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
"esd CAN-PCI/CPCI/PCI104/200, "
"esd CAN-PCI/PMC/266, "
"esd CAN-PCIe/2000, "
+ "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
"IXXAT PC-I 04/PCI")
MODULE_LICENSE("GPL v2");
@@ -131,6 +132,9 @@ struct plx_pci_card {
#define TEWS_PCI_VENDOR_ID 0x1498
#define TEWS_PCI_DEVICE_ID_TMPC810 0x032A
+#define CTI_PCI_VENDOR_ID 0x12c4
+#define CTI_PCI_DEVICE_ID_CRG001 0x0900
+
static void plx_pci_reset_common(struct pci_dev *pdev);
static void plx_pci_reset_marathon(struct pci_dev *pdev);
static void plx9056_pci_reset_common(struct pci_dev *pdev);
@@ -158,7 +162,7 @@ struct plx_pci_card_info {
void (*reset_func)(struct pci_dev *pdev);
};
-static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_adlink = {
"Adlink PCI-7841/cPCI-7841", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{1, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
@@ -166,7 +170,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
/* based on PLX9052 */
};
-static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_adlink_se = {
"Adlink PCI-7841/cPCI-7841 SE", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
@@ -174,7 +178,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
/* based on PLX9052 */
};
-static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd200 = {
"esd CAN-PCI/CPCI/PCI104/200", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -182,7 +186,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
/* based on PLX9030/9050 */
};
-static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd266 = {
"esd CAN-PCI/PMC/266", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -190,7 +194,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
/* based on PLX9056 */
};
-static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd2000 = {
"esd CAN-PCIe/2000", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -198,7 +202,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
/* based on PEX8311 */
};
-static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_ixxat = {
"IXXAT PC-I 04/PCI", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x200, 0x80} },
@@ -206,7 +210,7 @@ static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
/* based on PLX9050 */
};
-static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_marathon = {
"Marathon CAN-bus-PCI", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
@@ -214,7 +218,7 @@ static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
/* based on PLX9052 */
};
-static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_tews = {
"TEWS TECHNOLOGIES TPMC810", 2,
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
{0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
@@ -222,6 +226,14 @@ static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
/* based on PLX9030 */
};
+static struct plx_pci_card_info plx_pci_card_info_cti = {
+ "Connect Tech Inc. CANpro/104-Plus Opto (CRG001)", 2,
+ PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ {0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
+ &plx_pci_reset_common
+ /* based on PLX9030 */
+};
+
static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
{
/* Adlink PCI-7841/cPCI-7841 */
@@ -300,6 +312,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
0, 0,
(kernel_ulong_t)&plx_pci_card_info_tews
},
+ {
+ /* Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card */
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+ CTI_PCI_VENDOR_ID, CTI_PCI_DEVICE_ID_CRG001,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_cti
+ },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -465,8 +484,8 @@ static void plx_pci_del_card(struct pci_dev *pdev)
* Probe PLX90xx based device for the SJA1000 chips and register each
* available CAN channel to SJA1000 Socket-CAN subsystem.
*/
-static int __devinit plx_pci_add_card(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int plx_pci_add_card(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct sja1000_priv *priv;
struct net_device *dev;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 25011dbe1b96..83ee11eca0e2 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -188,11 +188,6 @@ static void sja1000_start(struct net_device *dev)
static int sja1000_set_mode(struct net_device *dev, enum can_mode mode)
{
- struct sja1000_priv *priv = netdev_priv(dev);
-
- if (!priv->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
sja1000_start(dev);
@@ -579,7 +574,6 @@ static int sja1000_open(struct net_device *dev)
/* init and start chi */
sja1000_start(dev);
- priv->open_time = jiffies;
netif_start_queue(dev);
@@ -598,8 +592,6 @@ static int sja1000_close(struct net_device *dev)
close_candev(dev);
- priv->open_time = 0;
-
return 0;
}
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 23fff06875f5..afa99847a510 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -152,7 +152,6 @@
*/
struct sja1000_priv {
struct can_priv can; /* must be the first member */
- int open_time;
struct sk_buff *echo_skb;
/* the lower-layer is responsible for appropriate locking */
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index 90c5c2dfd2fd..5c8da4661489 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -42,11 +42,11 @@ MODULE_LICENSE("GPL v2");
static unsigned long port[MAXDEV];
static unsigned long mem[MAXDEV];
-static int __devinitdata irq[MAXDEV];
-static int __devinitdata clk[MAXDEV];
-static unsigned char __devinitdata cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static unsigned char __devinitdata ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static int irq[MAXDEV];
+static int clk[MAXDEV];
+static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
module_param_array(port, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(port, "I/O port number");
@@ -117,7 +117,7 @@ static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
outb(val, base + 1);
}
-static int __devinit sja1000_isa_probe(struct platform_device *pdev)
+static int sja1000_isa_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sja1000_priv *priv;
@@ -223,7 +223,7 @@ static int __devinit sja1000_isa_probe(struct platform_device *pdev)
return err;
}
-static int __devexit sja1000_isa_remove(struct platform_device *pdev)
+static int sja1000_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct sja1000_priv *priv = netdev_priv(dev);
@@ -248,7 +248,7 @@ static int __devexit sja1000_isa_remove(struct platform_device *pdev)
static struct platform_driver sja1000_isa_driver = {
.probe = sja1000_isa_probe,
- .remove = __devexit_p(sja1000_isa_remove),
+ .remove = sja1000_isa_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index f2683eb6a3d5..0f5917000aa2 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -42,6 +42,8 @@
#include <linux/can/dev.h>
#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/prom.h>
#include "sja1000.h"
@@ -59,16 +61,16 @@ MODULE_LICENSE("GPL v2");
static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
{
- return in_8(priv->reg_base + reg);
+ return ioread8(priv->reg_base + reg);
}
static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
int reg, u8 val)
{
- out_8(priv->reg_base + reg, val);
+ iowrite8(val, priv->reg_base + reg);
}
-static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
+static int sja1000_ofp_remove(struct platform_device *ofdev)
{
struct net_device *dev = dev_get_drvdata(&ofdev->dev);
struct sja1000_priv *priv = netdev_priv(dev);
@@ -88,7 +90,7 @@ static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
return 0;
}
-static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
+static int sja1000_ofp_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct net_device *dev;
@@ -204,7 +206,7 @@ exit_release_mem:
return err;
}
-static struct of_device_id __devinitdata sja1000_ofp_table[] = {
+static struct of_device_id sja1000_ofp_table[] = {
{.compatible = "nxp,sja1000"},
{},
};
@@ -217,7 +219,7 @@ static struct platform_driver sja1000_ofp_driver = {
.of_match_table = sja1000_ofp_table,
},
.probe = sja1000_ofp_probe,
- .remove = __devexit_p(sja1000_ofp_remove),
+ .remove = sja1000_ofp_remove,
};
module_platform_driver(sja1000_ofp_driver);
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 662c5f7eb0c5..21619bb5b869 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -34,6 +34,7 @@
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
+MODULE_ALIAS("platform:" DRV_NAME);
MODULE_LICENSE("GPL v2");
static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg)
diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c
index 9756099a883a..76513dd780c7 100644
--- a/drivers/net/can/sja1000/tscan1.c
+++ b/drivers/net/can/sja1000/tscan1.c
@@ -71,7 +71,7 @@ MODULE_LICENSE("GPL");
#define TSCAN1_SJA1000_XTAL 16000000
/* SJA1000 IO base addresses */
-static const unsigned short tscan1_sja1000_addresses[] __devinitconst = {
+static const unsigned short tscan1_sja1000_addresses[] = {
0x100, 0x120, 0x180, 0x1a0, 0x200, 0x240, 0x280, 0x320
};
@@ -88,7 +88,7 @@ static void tscan1_write(const struct sja1000_priv *priv, int reg, u8 val)
}
/* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */
-static int __devinit tscan1_probe(struct device *dev, unsigned id)
+static int tscan1_probe(struct device *dev, unsigned id)
{
struct net_device *netdev;
struct sja1000_priv *priv;
@@ -171,7 +171,7 @@ static int __devinit tscan1_probe(struct device *dev, unsigned id)
return -ENXIO;
}
-static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
+static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
{
struct net_device *netdev;
struct sja1000_priv *priv;
@@ -197,7 +197,7 @@ static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
static struct isa_driver tscan1_isa_driver = {
.probe = tscan1_probe,
- .remove = __devexit_p(tscan1_remove),
+ .remove = tscan1_remove,
.driver = {
.name = "tscan1",
},
diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c
index c0e1b1eb87a9..c2c0a5bb0b21 100644
--- a/drivers/net/can/softing/softing_cs.c
+++ b/drivers/net/can/softing/softing_cs.c
@@ -159,7 +159,7 @@ MODULE_FIRMWARE(fw_dir "bcard2.bin");
MODULE_FIRMWARE(fw_dir "ldcard2.bin");
MODULE_FIRMWARE(fw_dir "cancrd2.bin");
-static __devinit const struct softing_platform_data
+static const struct softing_platform_data
*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
{
const struct softing_platform_data *lp;
@@ -193,8 +193,7 @@ static int softingcs_enable_irq(struct platform_device *pdev, int v)
/*
* pcmcia check
*/
-static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
- void *priv_data)
+static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)
{
struct softing_platform_data *pdat = priv_data;
struct resource *pres;
@@ -215,7 +214,7 @@ static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
return pcmcia_request_window(pcmcia, pres, memspeed);
}
-static __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
+static void softingcs_remove(struct pcmcia_device *pcmcia)
{
struct platform_device *pdev = pcmcia->priv;
@@ -235,7 +234,7 @@ static void softingcs_pdev_release(struct device *dev)
kfree(pdev);
}
-static __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
+static int softingcs_probe(struct pcmcia_device *pcmcia)
{
int ret;
struct platform_device *pdev;
@@ -338,7 +337,7 @@ static struct pcmcia_driver softingcs_driver = {
.name = "softingcs",
.id_table = softingcs_ids,
.probe = softingcs_probe,
- .remove = __devexit_p(softingcs_remove),
+ .remove = softingcs_remove,
};
static int __init softingcs_start(void)
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index f2a221e7b968..3a2b45601ec2 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -478,7 +478,7 @@ static void softing_card_shutdown(struct softing *card)
mutex_unlock(&card->fw.lock);
}
-static __devinit int softing_card_boot(struct softing *card)
+static int softing_card_boot(struct softing *card)
{
int ret, j;
static const uint8_t stream[] = {
@@ -645,8 +645,8 @@ static const struct can_bittiming_const softing_btr_const = {
};
-static __devinit struct net_device *softing_netdev_create(struct softing *card,
- uint16_t chip_id)
+static struct net_device *softing_netdev_create(struct softing *card,
+ uint16_t chip_id)
{
struct net_device *netdev;
struct softing_priv *priv;
@@ -676,7 +676,7 @@ static __devinit struct net_device *softing_netdev_create(struct softing *card,
return netdev;
}
-static __devinit int softing_netdev_register(struct net_device *netdev)
+static int softing_netdev_register(struct net_device *netdev)
{
int ret;
@@ -745,7 +745,7 @@ static const struct attribute_group softing_pdev_group = {
/*
* platform driver
*/
-static __devexit int softing_pdev_remove(struct platform_device *pdev)
+static int softing_pdev_remove(struct platform_device *pdev)
{
struct softing *card = platform_get_drvdata(pdev);
int j;
@@ -766,7 +766,7 @@ static __devexit int softing_pdev_remove(struct platform_device *pdev)
return 0;
}
-static __devinit int softing_pdev_probe(struct platform_device *pdev)
+static int softing_pdev_probe(struct platform_device *pdev)
{
const struct softing_platform_data *pdat = pdev->dev.platform_data;
struct softing *card;
@@ -871,7 +871,7 @@ static struct platform_driver softing_driver = {
.owner = THIS_MODULE,
},
.probe = softing_pdev_probe,
- .remove = __devexit_p(softing_pdev_remove),
+ .remove = softing_pdev_remove,
};
module_platform_driver(softing_driver);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 9ded21e79db5..f898c6363729 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -978,7 +978,7 @@ probe_exit:
return err;
}
-static int __devexit ti_hecc_remove(struct platform_device *pdev)
+static int ti_hecc_remove(struct platform_device *pdev)
{
struct resource *res;
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1045,7 +1045,7 @@ static struct platform_driver ti_hecc_driver = {
.owner = THIS_MODULE,
},
.probe = ti_hecc_probe,
- .remove = __devexit_p(ti_hecc_remove),
+ .remove = ti_hecc_remove,
.suspend = ti_hecc_suspend,
.resume = ti_hecc_resume,
};
@@ -1055,3 +1055,4 @@ module_platform_driver(ti_hecc_driver);
MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 0a6876841c20..a4e4bee35710 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -13,6 +13,35 @@ config CAN_ESD_USB2
This driver supports the CAN-USB/2 interface
from esd electronic system design gmbh (http://www.esd.eu).
+config CAN_KVASER_USB
+ tristate "Kvaser CAN/USB interface"
+ ---help---
+ This driver adds support for Kvaser CAN/USB devices like Kvaser
+ Leaf Light.
+
+ The driver gives support for the following devices:
+ - Kvaser Leaf Light
+ - Kvaser Leaf Professional HS
+ - Kvaser Leaf SemiPro HS
+ - Kvaser Leaf Professional LS
+ - Kvaser Leaf Professional SWC
+ - Kvaser Leaf Professional LIN
+ - Kvaser Leaf SemiPro LS
+ - Kvaser Leaf SemiPro SWC
+ - Kvaser Memorator II HS/HS
+ - Kvaser USBcan Professional HS/HS
+ - Kvaser Leaf Light GI
+ - Kvaser Leaf Professional HS (OBD-II connector)
+ - Kvaser Memorator Professional HS/LS
+ - Kvaser Leaf Light "China"
+ - Kvaser BlackBird SemiPro
+ - Kvaser USBcan R
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called kvaser_usb.
+
config CAN_PEAK_USB
tristate "PEAK PCAN-USB/USB Pro interfaces"
---help---
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index da6d1d3b2969..80a2ee41fd61 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
+obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 086fa321677a..c69f0b72b352 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -245,7 +245,6 @@ struct ems_tx_urb_context {
struct ems_usb {
struct can_priv can; /* must be the first member */
- int open_time;
struct sk_buff *echo_skb[MAX_TX_URBS];
@@ -728,7 +727,6 @@ static int ems_usb_open(struct net_device *netdev)
return err;
}
- dev->open_time = jiffies;
netif_start_queue(netdev);
@@ -878,8 +876,6 @@ static int ems_usb_close(struct net_device *netdev)
close_candev(netdev);
- dev->open_time = 0;
-
return 0;
}
@@ -905,9 +901,6 @@ static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
{
struct ems_usb *dev = netdev_priv(netdev);
- if (!dev->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index bd36e5517173..9b74d1e3ad44 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -1,7 +1,7 @@
/*
- * CAN driver for esd CAN-USB/2
+ * CAN driver for esd CAN-USB/2 and CAN-USB/Micro
*
- * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2010-2012 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
@@ -28,14 +28,16 @@
#include <linux/can/error.h>
MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>");
-MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 interfaces");
+MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces");
MODULE_LICENSE("GPL v2");
/* Define these values to match your devices */
#define USB_ESDGMBH_VENDOR_ID 0x0ab4
#define USB_CANUSB2_PRODUCT_ID 0x0010
+#define USB_CANUSBM_PRODUCT_ID 0x0011
#define ESD_USB2_CAN_CLOCK 60000000
+#define ESD_USBM_CAN_CLOCK 36000000
#define ESD_USB2_MAX_NETS 2
/* USB2 commands */
@@ -69,6 +71,7 @@ MODULE_LICENSE("GPL v2");
#define ESD_USB2_TSEG2_SHIFT 20
#define ESD_USB2_SJW_MAX 4
#define ESD_USB2_SJW_SHIFT 14
+#define ESD_USBM_SJW_SHIFT 24
#define ESD_USB2_BRP_MIN 1
#define ESD_USB2_BRP_MAX 1024
#define ESD_USB2_BRP_INC 1
@@ -183,6 +186,7 @@ struct __attribute__ ((packed)) esd_usb2_msg {
static struct usb_device_id esd_usb2_table[] = {
{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
+ {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb, esd_usb2_table);
@@ -213,7 +217,6 @@ struct esd_usb2_net_priv {
struct usb_anchor tx_submitted;
struct esd_tx_urb_context tx_contexts[MAX_TX_URBS];
- int open_time;
struct esd_usb2 *usb2;
struct net_device *netdev;
int index;
@@ -691,8 +694,6 @@ static int esd_usb2_open(struct net_device *netdev)
return err;
}
- priv->open_time = jiffies;
-
netif_start_queue(netdev);
return 0;
@@ -860,8 +861,6 @@ static int esd_usb2_close(struct net_device *netdev)
close_candev(netdev);
- priv->open_time = 0;
-
return 0;
}
@@ -889,11 +888,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
struct can_bittiming *bt = &priv->can.bittiming;
struct esd_usb2_msg msg;
u32 canbtr;
+ int sjw_shift;
canbtr = ESD_USB2_UBR;
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ canbtr |= ESD_USB2_LOM;
+
canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
+
+ if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) ==
+ USB_CANUSBM_PRODUCT_ID)
+ sjw_shift = ESD_USBM_SJW_SHIFT;
+ else
+ sjw_shift = ESD_USB2_SJW_SHIFT;
+
canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1))
- << ESD_USB2_SJW_SHIFT;
+ << sjw_shift;
canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)
& (ESD_USB2_TSEG1_MAX - 1))
<< ESD_USB2_TSEG1_SHIFT;
@@ -926,11 +936,6 @@ static int esd_usb2_get_berr_counter(const struct net_device *netdev,
static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode)
{
- struct esd_usb2_net_priv *priv = netdev_priv(netdev);
-
- if (!priv->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
netif_wake_queue(netdev);
@@ -971,12 +976,20 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
priv->index = index;
priv->can.state = CAN_STATE_STOPPED;
- priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY;
+
+ if (le16_to_cpu(dev->udev->descriptor.idProduct) ==
+ USB_CANUSBM_PRODUCT_ID)
+ priv->can.clock.freq = ESD_USBM_CAN_CLOCK;
+ else {
+ priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+ priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+ }
+
priv->can.bittiming_const = &esd_usb2_bittiming_const;
priv->can.do_set_bittiming = esd_usb2_set_bittiming;
priv->can.do_set_mode = esd_usb2_set_mode;
priv->can.do_get_berr_counter = esd_usb2_get_berr_counter;
- priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
netdev->flags |= IFF_ECHO; /* we support local echo */
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
new file mode 100644
index 000000000000..5b58a4d87397
--- /dev/null
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -0,0 +1,1627 @@
+/*
+ * 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.
+ *
+ * Parts of this driver are based on the following:
+ * - Kvaser linux leaf driver (version 4.78)
+ * - CAN driver for esd CAN-USB/2
+ *
+ * Copyright (C) 2002-2006 KVASER AB, Sweden. All rights reserved.
+ * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
+ */
+
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#define MAX_TX_URBS 16
+#define MAX_RX_URBS 4
+#define START_TIMEOUT 1000 /* msecs */
+#define STOP_TIMEOUT 1000 /* msecs */
+#define USB_SEND_TIMEOUT 1000 /* msecs */
+#define USB_RECV_TIMEOUT 1000 /* msecs */
+#define RX_BUFFER_SIZE 3072
+#define CAN_USB_CLOCK 8000000
+#define MAX_NET_DEVICES 3
+
+/* Kvaser USB devices */
+#define KVASER_VENDOR_ID 0x0bfd
+#define USB_LEAF_DEVEL_PRODUCT_ID 10
+#define USB_LEAF_LITE_PRODUCT_ID 11
+#define USB_LEAF_PRO_PRODUCT_ID 12
+#define USB_LEAF_SPRO_PRODUCT_ID 14
+#define USB_LEAF_PRO_LS_PRODUCT_ID 15
+#define USB_LEAF_PRO_SWC_PRODUCT_ID 16
+#define USB_LEAF_PRO_LIN_PRODUCT_ID 17
+#define USB_LEAF_SPRO_LS_PRODUCT_ID 18
+#define USB_LEAF_SPRO_SWC_PRODUCT_ID 19
+#define USB_MEMO2_DEVEL_PRODUCT_ID 22
+#define USB_MEMO2_HSHS_PRODUCT_ID 23
+#define USB_UPRO_HSHS_PRODUCT_ID 24
+#define USB_LEAF_LITE_GI_PRODUCT_ID 25
+#define USB_LEAF_PRO_OBDII_PRODUCT_ID 26
+#define USB_MEMO2_HSLS_PRODUCT_ID 27
+#define USB_LEAF_LITE_CH_PRODUCT_ID 28
+#define USB_BLACKBIRD_SPRO_PRODUCT_ID 29
+#define USB_OEM_MERCURY_PRODUCT_ID 34
+#define USB_OEM_LEAF_PRODUCT_ID 35
+#define USB_CAN_R_PRODUCT_ID 39
+
+/* USB devices features */
+#define KVASER_HAS_SILENT_MODE BIT(0)
+#define KVASER_HAS_TXRX_ERRORS BIT(1)
+
+/* Message header size */
+#define MSG_HEADER_LEN 2
+
+/* Can message flags */
+#define MSG_FLAG_ERROR_FRAME BIT(0)
+#define MSG_FLAG_OVERRUN BIT(1)
+#define MSG_FLAG_NERR BIT(2)
+#define MSG_FLAG_WAKEUP BIT(3)
+#define MSG_FLAG_REMOTE_FRAME BIT(4)
+#define MSG_FLAG_RESERVED BIT(5)
+#define MSG_FLAG_TX_ACK BIT(6)
+#define MSG_FLAG_TX_REQUEST BIT(7)
+
+/* Can states */
+#define M16C_STATE_BUS_RESET BIT(0)
+#define M16C_STATE_BUS_ERROR BIT(4)
+#define M16C_STATE_BUS_PASSIVE BIT(5)
+#define M16C_STATE_BUS_OFF BIT(6)
+
+/* Can msg ids */
+#define CMD_RX_STD_MESSAGE 12
+#define CMD_TX_STD_MESSAGE 13
+#define CMD_RX_EXT_MESSAGE 14
+#define CMD_TX_EXT_MESSAGE 15
+#define CMD_SET_BUS_PARAMS 16
+#define CMD_GET_BUS_PARAMS 17
+#define CMD_GET_BUS_PARAMS_REPLY 18
+#define CMD_GET_CHIP_STATE 19
+#define CMD_CHIP_STATE_EVENT 20
+#define CMD_SET_CTRL_MODE 21
+#define CMD_GET_CTRL_MODE 22
+#define CMD_GET_CTRL_MODE_REPLY 23
+#define CMD_RESET_CHIP 24
+#define CMD_RESET_CARD 25
+#define CMD_START_CHIP 26
+#define CMD_START_CHIP_REPLY 27
+#define CMD_STOP_CHIP 28
+#define CMD_STOP_CHIP_REPLY 29
+#define CMD_GET_CARD_INFO2 32
+#define CMD_GET_CARD_INFO 34
+#define CMD_GET_CARD_INFO_REPLY 35
+#define CMD_GET_SOFTWARE_INFO 38
+#define CMD_GET_SOFTWARE_INFO_REPLY 39
+#define CMD_ERROR_EVENT 45
+#define CMD_FLUSH_QUEUE 48
+#define CMD_RESET_ERROR_COUNTER 49
+#define CMD_TX_ACKNOWLEDGE 50
+#define CMD_CAN_ERROR_EVENT 51
+#define CMD_USB_THROTTLE 77
+#define CMD_LOG_MESSAGE 106
+
+/* error factors */
+#define M16C_EF_ACKE BIT(0)
+#define M16C_EF_CRCE BIT(1)
+#define M16C_EF_FORME BIT(2)
+#define M16C_EF_STFE BIT(3)
+#define M16C_EF_BITE0 BIT(4)
+#define M16C_EF_BITE1 BIT(5)
+#define M16C_EF_RCVE BIT(6)
+#define M16C_EF_TRE BIT(7)
+
+/* bittiming parameters */
+#define KVASER_USB_TSEG1_MIN 1
+#define KVASER_USB_TSEG1_MAX 16
+#define KVASER_USB_TSEG2_MIN 1
+#define KVASER_USB_TSEG2_MAX 8
+#define KVASER_USB_SJW_MAX 4
+#define KVASER_USB_BRP_MIN 1
+#define KVASER_USB_BRP_MAX 64
+#define KVASER_USB_BRP_INC 1
+
+/* ctrl modes */
+#define KVASER_CTRL_MODE_NORMAL 1
+#define KVASER_CTRL_MODE_SILENT 2
+#define KVASER_CTRL_MODE_SELFRECEPTION 3
+#define KVASER_CTRL_MODE_OFF 4
+
+struct kvaser_msg_simple {
+ u8 tid;
+ u8 channel;
+} __packed;
+
+struct kvaser_msg_cardinfo {
+ u8 tid;
+ u8 nchannels;
+ __le32 serial_number;
+ __le32 padding;
+ __le32 clock_resolution;
+ __le32 mfgdate;
+ u8 ean[8];
+ u8 hw_revision;
+ u8 usb_hs_mode;
+ __le16 padding2;
+} __packed;
+
+struct kvaser_msg_cardinfo2 {
+ u8 tid;
+ u8 channel;
+ u8 pcb_id[24];
+ __le32 oem_unlock_code;
+} __packed;
+
+struct kvaser_msg_softinfo {
+ u8 tid;
+ u8 channel;
+ __le32 sw_options;
+ __le32 fw_version;
+ __le16 max_outstanding_tx;
+ __le16 padding[9];
+} __packed;
+
+struct kvaser_msg_busparams {
+ u8 tid;
+ u8 channel;
+ __le32 bitrate;
+ u8 tseg1;
+ u8 tseg2;
+ u8 sjw;
+ u8 no_samp;
+} __packed;
+
+struct kvaser_msg_tx_can {
+ u8 channel;
+ u8 tid;
+ u8 msg[14];
+ u8 padding;
+ u8 flags;
+} __packed;
+
+struct kvaser_msg_rx_can {
+ u8 channel;
+ u8 flag;
+ __le16 time[3];
+ u8 msg[14];
+} __packed;
+
+struct kvaser_msg_chip_state_event {
+ u8 tid;
+ u8 channel;
+ __le16 time[3];
+ u8 tx_errors_count;
+ u8 rx_errors_count;
+ u8 status;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg_tx_acknowledge {
+ u8 channel;
+ u8 tid;
+ __le16 time[3];
+ u8 flags;
+ u8 time_offset;
+} __packed;
+
+struct kvaser_msg_error_event {
+ u8 tid;
+ u8 flags;
+ __le16 time[3];
+ u8 channel;
+ u8 padding;
+ u8 tx_errors_count;
+ u8 rx_errors_count;
+ u8 status;
+ u8 error_factor;
+} __packed;
+
+struct kvaser_msg_ctrl_mode {
+ u8 tid;
+ u8 channel;
+ u8 ctrl_mode;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg_flush_queue {
+ u8 tid;
+ u8 channel;
+ u8 flags;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg_log_message {
+ u8 channel;
+ u8 flags;
+ __le16 time[3];
+ u8 dlc;
+ u8 time_offset;
+ __le32 id;
+ u8 data[8];
+} __packed;
+
+struct kvaser_msg {
+ u8 len;
+ u8 id;
+ union {
+ struct kvaser_msg_simple simple;
+ struct kvaser_msg_cardinfo cardinfo;
+ struct kvaser_msg_cardinfo2 cardinfo2;
+ struct kvaser_msg_softinfo softinfo;
+ struct kvaser_msg_busparams busparams;
+ struct kvaser_msg_tx_can tx_can;
+ struct kvaser_msg_rx_can rx_can;
+ struct kvaser_msg_chip_state_event chip_state_event;
+ struct kvaser_msg_tx_acknowledge tx_acknowledge;
+ struct kvaser_msg_error_event error_event;
+ struct kvaser_msg_ctrl_mode ctrl_mode;
+ struct kvaser_msg_flush_queue flush_queue;
+ struct kvaser_msg_log_message log_message;
+ } u;
+} __packed;
+
+struct kvaser_usb_tx_urb_context {
+ struct kvaser_usb_net_priv *priv;
+ u32 echo_index;
+ int dlc;
+};
+
+struct kvaser_usb {
+ struct usb_device *udev;
+ struct kvaser_usb_net_priv *nets[MAX_NET_DEVICES];
+
+ struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+ struct usb_anchor rx_submitted;
+
+ u32 fw_version;
+ unsigned int nchannels;
+
+ bool rxinitdone;
+ void *rxbuf[MAX_RX_URBS];
+ dma_addr_t rxbuf_dma[MAX_RX_URBS];
+};
+
+struct kvaser_usb_net_priv {
+ struct can_priv can;
+
+ atomic_t active_tx_urbs;
+ struct usb_anchor tx_submitted;
+ struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+ struct completion start_comp, stop_comp;
+
+ struct kvaser_usb *dev;
+ struct net_device *netdev;
+ int channel;
+
+ struct can_berr_counter bec;
+};
+
+static const struct usb_device_id kvaser_usb_table[] = {
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS |
+ KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
+ .driver_info = KVASER_HAS_TXRX_ERRORS },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
+
+static inline int kvaser_usb_send_msg(const struct kvaser_usb *dev,
+ struct kvaser_msg *msg)
+{
+ int actual_len;
+
+ return usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ msg, msg->len, &actual_len,
+ USB_SEND_TIMEOUT);
+}
+
+static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
+ struct kvaser_msg *msg)
+{
+ struct kvaser_msg *tmp;
+ void *buf;
+ int actual_len;
+ int err;
+ int pos = 0;
+
+ buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ err = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ buf, RX_BUFFER_SIZE, &actual_len,
+ USB_RECV_TIMEOUT);
+ if (err < 0)
+ goto end;
+
+ while (pos <= actual_len - MSG_HEADER_LEN) {
+ tmp = buf + pos;
+
+ if (!tmp->len)
+ break;
+
+ if (pos + tmp->len > actual_len) {
+ dev_err(dev->udev->dev.parent, "Format error\n");
+ break;
+ }
+
+ if (tmp->id == id) {
+ memcpy(msg, tmp, tmp->len);
+ goto end;
+ }
+
+ pos += tmp->len;
+ }
+
+ err = -EINVAL;
+
+end:
+ kfree(buf);
+
+ return err;
+}
+
+static int kvaser_usb_send_simple_msg(const struct kvaser_usb *dev,
+ u8 msg_id, int channel)
+{
+ struct kvaser_msg *msg;
+ int rc;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->id = msg_id;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+ msg->u.simple.channel = channel;
+ msg->u.simple.tid = 0xff;
+
+ rc = kvaser_usb_send_msg(dev, msg);
+
+ kfree(msg);
+ return rc;
+}
+
+static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
+{
+ struct kvaser_msg msg;
+ int err;
+
+ err = kvaser_usb_send_simple_msg(dev, CMD_GET_SOFTWARE_INFO, 0);
+ if (err)
+ return err;
+
+ err = kvaser_usb_wait_msg(dev, CMD_GET_SOFTWARE_INFO_REPLY, &msg);
+ if (err)
+ return err;
+
+ dev->fw_version = le32_to_cpu(msg.u.softinfo.fw_version);
+
+ return 0;
+}
+
+static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
+{
+ struct kvaser_msg msg;
+ int err;
+
+ err = kvaser_usb_send_simple_msg(dev, CMD_GET_CARD_INFO, 0);
+ if (err)
+ return err;
+
+ err = kvaser_usb_wait_msg(dev, CMD_GET_CARD_INFO_REPLY, &msg);
+ if (err)
+ return err;
+
+ dev->nchannels = msg.u.cardinfo.nchannels;
+
+ return 0;
+}
+
+static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct net_device_stats *stats;
+ struct kvaser_usb_tx_urb_context *context;
+ struct kvaser_usb_net_priv *priv;
+ struct sk_buff *skb;
+ struct can_frame *cf;
+ u8 channel = msg->u.tx_acknowledge.channel;
+ u8 tid = msg->u.tx_acknowledge.tid;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ if (!netif_device_present(priv->netdev))
+ return;
+
+ stats = &priv->netdev->stats;
+
+ context = &priv->tx_contexts[tid % MAX_TX_URBS];
+
+ /* Sometimes the state change doesn't come after a bus-off event */
+ if (priv->can.restart_ms &&
+ (priv->can.state >= CAN_STATE_BUS_OFF)) {
+ skb = alloc_can_err_skb(priv->netdev, &cf);
+ if (skb) {
+ cf->can_id |= CAN_ERR_RESTARTED;
+ netif_rx(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ } else {
+ netdev_err(priv->netdev,
+ "No memory left for err_skb\n");
+ }
+
+ priv->can.can_stats.restarts++;
+ netif_carrier_on(priv->netdev);
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ stats->tx_packets++;
+ stats->tx_bytes += context->dlc;
+ can_get_echo_skb(priv->netdev, context->echo_index);
+
+ context->echo_index = MAX_TX_URBS;
+ atomic_dec(&priv->active_tx_urbs);
+
+ netif_wake_queue(priv->netdev);
+}
+
+static void kvaser_usb_simple_msg_callback(struct urb *urb)
+{
+ struct net_device *netdev = urb->context;
+
+ kfree(urb->transfer_buffer);
+
+ if (urb->status)
+ netdev_warn(netdev, "urb status received: %d\n",
+ urb->status);
+}
+
+static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
+ u8 msg_id)
+{
+ struct kvaser_usb *dev = priv->dev;
+ struct net_device *netdev = priv->netdev;
+ struct kvaser_msg *msg;
+ struct urb *urb;
+ void *buf;
+ int err;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(netdev, "No memory left for URBs\n");
+ return -ENOMEM;
+ }
+
+ buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+ if (!buf) {
+ netdev_err(netdev, "No memory left for USB buffer\n");
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ msg = (struct kvaser_msg *)buf;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+ msg->id = msg_id;
+ msg->u.simple.channel = priv->channel;
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ buf, msg->len,
+ kvaser_usb_simple_msg_callback, priv);
+ usb_anchor_urb(urb, &priv->tx_submitted);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err) {
+ netdev_err(netdev, "Error transmitting URB\n");
+ usb_unanchor_urb(urb);
+ usb_free_urb(urb);
+ kfree(buf);
+ return err;
+ }
+
+ usb_free_urb(urb);
+
+ return 0;
+}
+
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+ int i;
+
+ usb_kill_anchored_urbs(&priv->tx_submitted);
+ atomic_set(&priv->active_tx_urbs, 0);
+
+ for (i = 0; i < MAX_TX_URBS; i++)
+ priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats;
+ struct kvaser_usb_net_priv *priv;
+ unsigned int new_state;
+ u8 channel, status, txerr, rxerr, error_factor;
+
+ switch (msg->id) {
+ case CMD_CAN_ERROR_EVENT:
+ channel = msg->u.error_event.channel;
+ status = msg->u.error_event.status;
+ txerr = msg->u.error_event.tx_errors_count;
+ rxerr = msg->u.error_event.rx_errors_count;
+ error_factor = msg->u.error_event.error_factor;
+ break;
+ case CMD_LOG_MESSAGE:
+ channel = msg->u.log_message.channel;
+ status = msg->u.log_message.data[0];
+ txerr = msg->u.log_message.data[2];
+ rxerr = msg->u.log_message.data[3];
+ error_factor = msg->u.log_message.data[1];
+ break;
+ case CMD_CHIP_STATE_EVENT:
+ channel = msg->u.chip_state_event.channel;
+ status = msg->u.chip_state_event.status;
+ txerr = msg->u.chip_state_event.tx_errors_count;
+ rxerr = msg->u.chip_state_event.rx_errors_count;
+ error_factor = 0;
+ break;
+ default:
+ dev_err(dev->udev->dev.parent, "Invalid msg id (%d)\n",
+ msg->id);
+ return;
+ }
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+ stats = &priv->netdev->stats;
+
+ if (status & M16C_STATE_BUS_RESET) {
+ kvaser_usb_unlink_tx_urbs(priv);
+ return;
+ }
+
+ skb = alloc_can_err_skb(priv->netdev, &cf);
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ new_state = priv->can.state;
+
+ netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status);
+
+ if (status & M16C_STATE_BUS_OFF) {
+ cf->can_id |= CAN_ERR_BUSOFF;
+
+ priv->can.can_stats.bus_off++;
+ if (!priv->can.restart_ms)
+ kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP);
+
+ netif_carrier_off(priv->netdev);
+
+ new_state = CAN_STATE_BUS_OFF;
+ } else if (status & M16C_STATE_BUS_PASSIVE) {
+ if (priv->can.state != CAN_STATE_ERROR_PASSIVE) {
+ cf->can_id |= CAN_ERR_CRTL;
+
+ if (txerr || rxerr)
+ cf->data[1] = (txerr > rxerr)
+ ? CAN_ERR_CRTL_TX_PASSIVE
+ : CAN_ERR_CRTL_RX_PASSIVE;
+ else
+ cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE |
+ CAN_ERR_CRTL_RX_PASSIVE;
+
+ priv->can.can_stats.error_passive++;
+ }
+
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ }
+
+ if (status == M16C_STATE_BUS_ERROR) {
+ if ((priv->can.state < CAN_STATE_ERROR_WARNING) &&
+ ((txerr >= 96) || (rxerr >= 96))) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = (txerr > rxerr)
+ ? CAN_ERR_CRTL_TX_WARNING
+ : CAN_ERR_CRTL_RX_WARNING;
+
+ priv->can.can_stats.error_warning++;
+ new_state = CAN_STATE_ERROR_WARNING;
+ } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) {
+ cf->can_id |= CAN_ERR_PROT;
+ cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ }
+ }
+
+ if (!status) {
+ cf->can_id |= CAN_ERR_PROT;
+ cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ if (priv->can.restart_ms &&
+ (priv->can.state >= CAN_STATE_BUS_OFF) &&
+ (new_state < CAN_STATE_BUS_OFF)) {
+ cf->can_id |= CAN_ERR_RESTARTED;
+ netif_carrier_on(priv->netdev);
+
+ priv->can.can_stats.restarts++;
+ }
+
+ if (error_factor) {
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+
+ cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
+
+ if (error_factor & M16C_EF_ACKE)
+ cf->data[3] |= (CAN_ERR_PROT_LOC_ACK);
+ if (error_factor & M16C_EF_CRCE)
+ cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+ CAN_ERR_PROT_LOC_CRC_DEL);
+ if (error_factor & M16C_EF_FORME)
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ if (error_factor & M16C_EF_STFE)
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ if (error_factor & M16C_EF_BITE0)
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ if (error_factor & M16C_EF_BITE1)
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ if (error_factor & M16C_EF_TRE)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ }
+
+ cf->data[6] = txerr;
+ cf->data[7] = rxerr;
+
+ priv->bec.txerr = txerr;
+ priv->bec.rxerr = rxerr;
+
+ priv->can.state = new_state;
+
+ netif_rx(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
+ const struct kvaser_msg *msg)
+{
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats = &priv->netdev->stats;
+
+ if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
+ MSG_FLAG_NERR)) {
+ netdev_err(priv->netdev, "Unknow error (flags: 0x%02x)\n",
+ msg->u.rx_can.flag);
+
+ stats->rx_errors++;
+ return;
+ }
+
+ if (msg->u.rx_can.flag & MSG_FLAG_OVERRUN) {
+ skb = alloc_can_err_skb(priv->netdev, &cf);
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+
+ netif_rx(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ }
+}
+
+static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats;
+ u8 channel = msg->u.rx_can.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+ stats = &priv->netdev->stats;
+
+ if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR |
+ MSG_FLAG_OVERRUN)) {
+ kvaser_usb_rx_can_err(priv, msg);
+ return;
+ } else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
+ netdev_warn(priv->netdev,
+ "Unhandled frame (flags: 0x%02x)",
+ msg->u.rx_can.flag);
+ return;
+ }
+
+ skb = alloc_can_skb(priv->netdev, &cf);
+ if (!skb) {
+ stats->tx_dropped++;
+ return;
+ }
+
+ cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
+ (msg->u.rx_can.msg[1] & 0x3f);
+ cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+
+ if (msg->id == CMD_RX_EXT_MESSAGE) {
+ cf->can_id <<= 18;
+ cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
+ ((msg->u.rx_can.msg[3] & 0xff) << 6) |
+ (msg->u.rx_can.msg[4] & 0x3f);
+ cf->can_id |= CAN_EFF_FLAG;
+ }
+
+ if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
+ cf->can_id |= CAN_RTR_FLAG;
+ else
+ memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
+
+ netif_rx(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ u8 channel = msg->u.simple.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ if (completion_done(&priv->start_comp) &&
+ netif_queue_stopped(priv->netdev)) {
+ netif_wake_queue(priv->netdev);
+ } else {
+ netif_start_queue(priv->netdev);
+ complete(&priv->start_comp);
+ }
+}
+
+static void kvaser_usb_stop_chip_reply(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ u8 channel = msg->u.simple.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ complete(&priv->stop_comp);
+}
+
+static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ switch (msg->id) {
+ case CMD_START_CHIP_REPLY:
+ kvaser_usb_start_chip_reply(dev, msg);
+ break;
+
+ case CMD_STOP_CHIP_REPLY:
+ kvaser_usb_stop_chip_reply(dev, msg);
+ break;
+
+ case CMD_RX_STD_MESSAGE:
+ case CMD_RX_EXT_MESSAGE:
+ kvaser_usb_rx_can_msg(dev, msg);
+ break;
+
+ case CMD_CHIP_STATE_EVENT:
+ case CMD_CAN_ERROR_EVENT:
+ kvaser_usb_rx_error(dev, msg);
+ break;
+
+ case CMD_LOG_MESSAGE:
+ if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
+ kvaser_usb_rx_error(dev, msg);
+ break;
+
+ case CMD_TX_ACKNOWLEDGE:
+ kvaser_usb_tx_acknowledge(dev, msg);
+ break;
+
+ default:
+ dev_warn(dev->udev->dev.parent,
+ "Unhandled message (%d)\n", msg->id);
+ break;
+ }
+}
+
+static void kvaser_usb_read_bulk_callback(struct urb *urb)
+{
+ struct kvaser_usb *dev = urb->context;
+ struct kvaser_msg *msg;
+ int pos = 0;
+ int err, i;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default:
+ dev_info(dev->udev->dev.parent, "Rx URB aborted (%d)\n",
+ urb->status);
+ goto resubmit_urb;
+ }
+
+ while (pos <= urb->actual_length - MSG_HEADER_LEN) {
+ msg = urb->transfer_buffer + pos;
+
+ if (!msg->len)
+ break;
+
+ if (pos + msg->len > urb->actual_length) {
+ dev_err(dev->udev->dev.parent, "Format error\n");
+ break;
+ }
+
+ kvaser_usb_handle_message(dev, msg);
+
+ pos += msg->len;
+ }
+
+resubmit_urb:
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ urb->transfer_buffer, RX_BUFFER_SIZE,
+ kvaser_usb_read_bulk_callback, dev);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err == -ENODEV) {
+ for (i = 0; i < dev->nchannels; i++) {
+ if (!dev->nets[i])
+ continue;
+
+ netif_device_detach(dev->nets[i]->netdev);
+ }
+ } else if (err) {
+ dev_err(dev->udev->dev.parent,
+ "Failed resubmitting read bulk urb: %d\n", err);
+ }
+
+ return;
+}
+
+static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev)
+{
+ int i, err = 0;
+
+ if (dev->rxinitdone)
+ return 0;
+
+ for (i = 0; i < MAX_RX_URBS; i++) {
+ struct urb *urb = NULL;
+ u8 *buf = NULL;
+ dma_addr_t buf_dma;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ dev_warn(dev->udev->dev.parent,
+ "No memory left for URBs\n");
+ err = -ENOMEM;
+ break;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE,
+ GFP_KERNEL, &buf_dma);
+ if (!buf) {
+ dev_warn(dev->udev->dev.parent,
+ "No memory left for USB buffer\n");
+ usb_free_urb(urb);
+ err = -ENOMEM;
+ break;
+ }
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ buf, RX_BUFFER_SIZE,
+ kvaser_usb_read_bulk_callback,
+ dev);
+ urb->transfer_dma = buf_dma;
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &dev->rx_submitted);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ usb_unanchor_urb(urb);
+ usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+ buf_dma);
+ usb_free_urb(urb);
+ break;
+ }
+
+ dev->rxbuf[i] = buf;
+ dev->rxbuf_dma[i] = buf_dma;
+
+ usb_free_urb(urb);
+ }
+
+ if (i == 0) {
+ dev_warn(dev->udev->dev.parent,
+ "Cannot setup read URBs, error %d\n", err);
+ return err;
+ } else if (i < MAX_RX_URBS) {
+ dev_warn(dev->udev->dev.parent,
+ "RX performances may be slow\n");
+ }
+
+ dev->rxinitdone = true;
+
+ return 0;
+}
+
+static int kvaser_usb_set_opt_mode(const struct kvaser_usb_net_priv *priv)
+{
+ struct kvaser_msg *msg;
+ int rc;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->id = CMD_SET_CTRL_MODE;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_ctrl_mode);
+ msg->u.ctrl_mode.tid = 0xff;
+ msg->u.ctrl_mode.channel = priv->channel;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT;
+ else
+ msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL;
+
+ rc = kvaser_usb_send_msg(priv->dev, msg);
+
+ kfree(msg);
+ return rc;
+}
+
+static int kvaser_usb_start_chip(struct kvaser_usb_net_priv *priv)
+{
+ int err;
+
+ init_completion(&priv->start_comp);
+
+ err = kvaser_usb_send_simple_msg(priv->dev, CMD_START_CHIP,
+ priv->channel);
+ if (err)
+ return err;
+
+ if (!wait_for_completion_timeout(&priv->start_comp,
+ msecs_to_jiffies(START_TIMEOUT)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int kvaser_usb_open(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ int err;
+
+ err = open_candev(netdev);
+ if (err)
+ return err;
+
+ err = kvaser_usb_setup_rx_urbs(dev);
+ if (err)
+ goto error;
+
+ err = kvaser_usb_set_opt_mode(priv);
+ if (err)
+ goto error;
+
+ err = kvaser_usb_start_chip(priv);
+ if (err) {
+ netdev_warn(netdev, "Cannot start device, error %d\n", err);
+ goto error;
+ }
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ return 0;
+
+error:
+ close_candev(netdev);
+ return err;
+}
+
+static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
+{
+ int i;
+
+ usb_kill_anchored_urbs(&dev->rx_submitted);
+
+ for (i = 0; i < MAX_RX_URBS; i++)
+ usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+ dev->rxbuf[i],
+ dev->rxbuf_dma[i]);
+
+ for (i = 0; i < MAX_NET_DEVICES; i++) {
+ struct kvaser_usb_net_priv *priv = dev->nets[i];
+
+ if (priv)
+ kvaser_usb_unlink_tx_urbs(priv);
+ }
+}
+
+static int kvaser_usb_stop_chip(struct kvaser_usb_net_priv *priv)
+{
+ int err;
+
+ init_completion(&priv->stop_comp);
+
+ err = kvaser_usb_send_simple_msg(priv->dev, CMD_STOP_CHIP,
+ priv->channel);
+ if (err)
+ return err;
+
+ if (!wait_for_completion_timeout(&priv->stop_comp,
+ msecs_to_jiffies(STOP_TIMEOUT)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int kvaser_usb_flush_queue(struct kvaser_usb_net_priv *priv)
+{
+ struct kvaser_msg *msg;
+ int rc;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->id = CMD_FLUSH_QUEUE;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_flush_queue);
+ msg->u.flush_queue.channel = priv->channel;
+ msg->u.flush_queue.flags = 0x00;
+
+ rc = kvaser_usb_send_msg(priv->dev, msg);
+
+ kfree(msg);
+ return rc;
+}
+
+static int kvaser_usb_close(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ int err;
+
+ netif_stop_queue(netdev);
+
+ err = kvaser_usb_flush_queue(priv);
+ if (err)
+ netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
+
+ if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
+ netdev_warn(netdev, "Cannot reset card, error %d\n", err);
+
+ err = kvaser_usb_stop_chip(priv);
+ if (err)
+ netdev_warn(netdev, "Cannot stop device, error %d\n", err);
+
+ priv->can.state = CAN_STATE_STOPPED;
+ close_candev(priv->netdev);
+
+ return 0;
+}
+
+static void kvaser_usb_write_bulk_callback(struct urb *urb)
+{
+ struct kvaser_usb_tx_urb_context *context = urb->context;
+ struct kvaser_usb_net_priv *priv;
+ struct net_device *netdev;
+
+ if (WARN_ON(!context))
+ return;
+
+ priv = context->priv;
+ netdev = priv->netdev;
+
+ kfree(urb->transfer_buffer);
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
+}
+
+static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ struct kvaser_usb_tx_urb_context *context = NULL;
+ struct urb *urb;
+ void *buf;
+ struct kvaser_msg *msg;
+ int i, err;
+ int ret = NETDEV_TX_OK;
+
+ if (can_dropped_invalid_skb(netdev, skb))
+ return NETDEV_TX_OK;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(netdev, "No memory left for URBs\n");
+ stats->tx_dropped++;
+ goto nourbmem;
+ }
+
+ buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+ if (!buf) {
+ netdev_err(netdev, "No memory left for USB buffer\n");
+ stats->tx_dropped++;
+ goto nobufmem;
+ }
+
+ msg = buf;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
+ msg->u.tx_can.flags = 0;
+ msg->u.tx_can.channel = priv->channel;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ msg->id = CMD_TX_EXT_MESSAGE;
+ msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
+ msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
+ msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
+ msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
+ msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
+ } else {
+ msg->id = CMD_TX_STD_MESSAGE;
+ msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
+ msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
+ }
+
+ msg->u.tx_can.msg[5] = cf->can_dlc;
+ memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
+
+ for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
+ if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+ context = &priv->tx_contexts[i];
+ break;
+ }
+ }
+
+ if (!context) {
+ netdev_warn(netdev, "cannot find free context\n");
+ ret = NETDEV_TX_BUSY;
+ goto releasebuf;
+ }
+
+ context->priv = priv;
+ context->echo_index = i;
+ context->dlc = cf->can_dlc;
+
+ msg->u.tx_can.tid = context->echo_index;
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ buf, msg->len,
+ kvaser_usb_write_bulk_callback, context);
+ usb_anchor_urb(urb, &priv->tx_submitted);
+
+ can_put_echo_skb(skb, netdev, context->echo_index);
+
+ atomic_inc(&priv->active_tx_urbs);
+
+ if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+ netif_stop_queue(netdev);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err)) {
+ can_free_echo_skb(netdev, context->echo_index);
+
+ skb = NULL; /* set to NULL to avoid double free in
+ * dev_kfree_skb(skb) */
+
+ atomic_dec(&priv->active_tx_urbs);
+ usb_unanchor_urb(urb);
+
+ stats->tx_dropped++;
+
+ if (err == -ENODEV)
+ netif_device_detach(netdev);
+ else
+ netdev_warn(netdev, "Failed tx_urb %d\n", err);
+
+ goto releasebuf;
+ }
+
+ usb_free_urb(urb);
+
+ return NETDEV_TX_OK;
+
+releasebuf:
+ kfree(buf);
+nobufmem:
+ usb_free_urb(urb);
+nourbmem:
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static const struct net_device_ops kvaser_usb_netdev_ops = {
+ .ndo_open = kvaser_usb_open,
+ .ndo_stop = kvaser_usb_close,
+ .ndo_start_xmit = kvaser_usb_start_xmit,
+};
+
+static const struct can_bittiming_const kvaser_usb_bittiming_const = {
+ .name = "kvaser_usb",
+ .tseg1_min = KVASER_USB_TSEG1_MIN,
+ .tseg1_max = KVASER_USB_TSEG1_MAX,
+ .tseg2_min = KVASER_USB_TSEG2_MIN,
+ .tseg2_max = KVASER_USB_TSEG2_MAX,
+ .sjw_max = KVASER_USB_SJW_MAX,
+ .brp_min = KVASER_USB_BRP_MIN,
+ .brp_max = KVASER_USB_BRP_MAX,
+ .brp_inc = KVASER_USB_BRP_INC,
+};
+
+static int kvaser_usb_set_bittiming(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ struct kvaser_usb *dev = priv->dev;
+ struct kvaser_msg *msg;
+ int rc;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->id = CMD_SET_BUS_PARAMS;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_busparams);
+ msg->u.busparams.channel = priv->channel;
+ msg->u.busparams.tid = 0xff;
+ msg->u.busparams.bitrate = cpu_to_le32(bt->bitrate);
+ msg->u.busparams.sjw = bt->sjw;
+ msg->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1;
+ msg->u.busparams.tseg2 = bt->phase_seg2;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ msg->u.busparams.no_samp = 3;
+ else
+ msg->u.busparams.no_samp = 1;
+
+ rc = kvaser_usb_send_msg(dev, msg);
+
+ kfree(msg);
+ return rc;
+}
+
+static int kvaser_usb_set_mode(struct net_device *netdev,
+ enum can_mode mode)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ int err;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ err = kvaser_usb_simple_msg_async(priv, CMD_START_CHIP);
+ if (err)
+ return err;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int kvaser_usb_get_berr_counter(const struct net_device *netdev,
+ struct can_berr_counter *bec)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+
+ *bec = priv->bec;
+
+ return 0;
+}
+
+static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->nchannels; i++) {
+ if (!dev->nets[i])
+ continue;
+
+ unregister_netdev(dev->nets[i]->netdev);
+ }
+
+ kvaser_usb_unlink_all_urbs(dev);
+
+ for (i = 0; i < dev->nchannels; i++) {
+ if (!dev->nets[i])
+ continue;
+
+ free_candev(dev->nets[i]->netdev);
+ }
+}
+
+static int kvaser_usb_init_one(struct usb_interface *intf,
+ const struct usb_device_id *id, int channel)
+{
+ struct kvaser_usb *dev = usb_get_intfdata(intf);
+ struct net_device *netdev;
+ struct kvaser_usb_net_priv *priv;
+ int i, err;
+
+ netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+ if (!netdev) {
+ dev_err(&intf->dev, "Cannot alloc candev\n");
+ return -ENOMEM;
+ }
+
+ priv = netdev_priv(netdev);
+
+ init_completion(&priv->start_comp);
+ init_completion(&priv->stop_comp);
+
+ init_usb_anchor(&priv->tx_submitted);
+ atomic_set(&priv->active_tx_urbs, 0);
+
+ for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
+ priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+ priv->dev = dev;
+ priv->netdev = netdev;
+ priv->channel = channel;
+
+ priv->can.state = CAN_STATE_STOPPED;
+ priv->can.clock.freq = CAN_USB_CLOCK;
+ priv->can.bittiming_const = &kvaser_usb_bittiming_const;
+ priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
+ priv->can.do_set_mode = kvaser_usb_set_mode;
+ if (id->driver_info & KVASER_HAS_TXRX_ERRORS)
+ priv->can.do_get_berr_counter = kvaser_usb_get_berr_counter;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+ if (id->driver_info & KVASER_HAS_SILENT_MODE)
+ priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
+
+ netdev->flags |= IFF_ECHO;
+
+ netdev->netdev_ops = &kvaser_usb_netdev_ops;
+
+ SET_NETDEV_DEV(netdev, &intf->dev);
+
+ dev->nets[channel] = priv;
+
+ err = register_candev(netdev);
+ if (err) {
+ dev_err(&intf->dev, "Failed to register can device\n");
+ free_candev(netdev);
+ dev->nets[channel] = NULL;
+ return err;
+ }
+
+ netdev_dbg(netdev, "device registered\n");
+
+ return 0;
+}
+
+static void kvaser_usb_get_endpoints(const struct usb_interface *intf,
+ struct usb_endpoint_descriptor **in,
+ struct usb_endpoint_descriptor **out)
+{
+ const struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+
+ iface_desc = &intf->altsetting[0];
+
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_bulk_in(endpoint))
+ *in = endpoint;
+
+ if (usb_endpoint_is_bulk_out(endpoint))
+ *out = endpoint;
+ }
+}
+
+static int kvaser_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct kvaser_usb *dev;
+ int err = -ENOMEM;
+ int i;
+
+ dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
+ if (!dev->bulk_in || !dev->bulk_out) {
+ dev_err(&intf->dev, "Cannot get usb endpoint(s)");
+ return err;
+ }
+
+ dev->udev = interface_to_usbdev(intf);
+
+ init_usb_anchor(&dev->rx_submitted);
+
+ usb_set_intfdata(intf, dev);
+
+ for (i = 0; i < MAX_NET_DEVICES; i++)
+ kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
+
+ err = kvaser_usb_get_software_info(dev);
+ if (err) {
+ dev_err(&intf->dev,
+ "Cannot get software infos, error %d\n", err);
+ return err;
+ }
+
+ err = kvaser_usb_get_card_info(dev);
+ if (err) {
+ dev_err(&intf->dev,
+ "Cannot get card infos, error %d\n", err);
+ return err;
+ }
+
+ dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
+ ((dev->fw_version >> 24) & 0xff),
+ ((dev->fw_version >> 16) & 0xff),
+ (dev->fw_version & 0xffff));
+
+ for (i = 0; i < dev->nchannels; i++) {
+ err = kvaser_usb_init_one(intf, id, i);
+ if (err) {
+ kvaser_usb_remove_interfaces(dev);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static void kvaser_usb_disconnect(struct usb_interface *intf)
+{
+ struct kvaser_usb *dev = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (!dev)
+ return;
+
+ kvaser_usb_remove_interfaces(dev);
+}
+
+static struct usb_driver kvaser_usb_driver = {
+ .name = "kvaser_usb",
+ .probe = kvaser_usb_probe,
+ .disconnect = kvaser_usb_disconnect,
+ .id_table = kvaser_usb_table,
+};
+
+module_usb_driver(kvaser_usb_driver);
+
+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
+MODULE_DESCRIPTION("CAN driver for Kvaser CAN/USB devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index c4643c400d46..d9290ea788e0 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -520,7 +520,6 @@ static int peak_usb_ndo_open(struct net_device *netdev)
return err;
}
- dev->open_time = jiffies;
netif_start_queue(netdev);
return 0;
@@ -576,7 +575,6 @@ static int peak_usb_ndo_stop(struct net_device *netdev)
close_candev(netdev);
- dev->open_time = 0;
dev->can.state = CAN_STATE_STOPPED;
/* can set bus off now */
@@ -661,9 +659,6 @@ static int peak_usb_set_mode(struct net_device *netdev, enum can_mode mode)
struct peak_usb_device *dev = netdev_priv(netdev);
int err = 0;
- if (!dev->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
err = peak_usb_restart(dev);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h
index c8e5e91d7cb5..073b47ff8eee 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h
@@ -104,7 +104,6 @@ struct peak_usb_device {
struct can_priv can;
struct peak_usb_adapter *adapter;
unsigned int ctrl_idx;
- int open_time;
u32 state;
struct sk_buff *echo_skb[PCAN_USB_MAX_TX_URBS];
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index dd151d53d506..b8fe808b7957 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -1,5 +1,5 @@
menu "Distributed Switch Architecture drivers"
- depends on NET_DSA
+ depends on HAVE_NET_DSA
config NET_DSA_MV88E6XXX
tristate
@@ -7,6 +7,7 @@ config NET_DSA_MV88E6XXX
config NET_DSA_MV88E6060
tristate "Marvell 88E6060 ethernet switch chip support"
+ select NET_DSA
select NET_DSA_TAG_TRAILER
---help---
This enables support for the Marvell 88E6060 ethernet switch
@@ -18,6 +19,7 @@ config NET_DSA_MV88E6XXX_NEED_PPU
config NET_DSA_MV88E6131
tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
+ select NET_DSA
select NET_DSA_MV88E6XXX
select NET_DSA_MV88E6XXX_NEED_PPU
select NET_DSA_TAG_DSA
@@ -27,6 +29,7 @@ config NET_DSA_MV88E6131
config NET_DSA_MV88E6123_61_65
tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
+ select NET_DSA
select NET_DSA_MV88E6XXX
select NET_DSA_TAG_EDSA
---help---
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 1a8eef2c3d58..633c709b9d99 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -92,7 +92,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
+static char version[] = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
#ifdef EL3_DEBUG
static int el3_debug = EL3_DEBUG;
@@ -184,7 +184,7 @@ static int max_interrupt_work = 10;
static int nopnp;
#endif
-static int __devinit el3_common_init(struct net_device *dev);
+static int el3_common_init(struct net_device *dev);
static void el3_common_remove(struct net_device *dev);
static ushort id_read_eeprom(int index);
static ushort read_eeprom(int ioaddr, int index);
@@ -270,9 +270,8 @@ static int el3_isa_id_sequence(__be16 *phys_addr)
}
-static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
- int ioaddr, int irq, int if_port,
- enum el3_cardtype type)
+static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
+ int irq, int if_port, enum el3_cardtype type)
{
struct el3_private *lp = netdev_priv(dev);
@@ -283,8 +282,7 @@ static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
lp->type = type;
}
-static int __devinit el3_isa_match(struct device *pdev,
- unsigned int ndev)
+static int el3_isa_match(struct device *pdev, unsigned int ndev)
{
struct net_device *dev;
int ioaddr, isa_irq, if_port, err;
@@ -341,7 +339,7 @@ static int __devinit el3_isa_match(struct device *pdev,
return 1;
}
-static int __devexit el3_isa_remove(struct device *pdev,
+static int el3_isa_remove(struct device *pdev,
unsigned int ndev)
{
el3_device_remove(pdev);
@@ -382,7 +380,7 @@ static int el3_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver el3_isa_driver = {
.match = el3_isa_match,
- .remove = __devexit_p(el3_isa_remove),
+ .remove = el3_isa_remove,
#ifdef CONFIG_PM
.suspend = el3_isa_suspend,
.resume = el3_isa_resume,
@@ -406,8 +404,7 @@ static struct pnp_device_id el3_pnp_ids[] = {
};
MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
-static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
- const struct pnp_device_id *id)
+static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
{
short i;
int ioaddr, irq, if_port;
@@ -445,7 +442,7 @@ static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
return 0;
}
-static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
+static void el3_pnp_remove(struct pnp_dev *pdev)
{
el3_common_remove(pnp_get_drvdata(pdev));
pnp_set_drvdata(pdev, NULL);
@@ -467,7 +464,7 @@ static struct pnp_driver el3_pnp_driver = {
.name = "3c509",
.id_table = el3_pnp_ids,
.probe = el3_pnp_probe,
- .remove = __devexit_p(el3_pnp_remove),
+ .remove = el3_pnp_remove,
#ifdef CONFIG_PM
.suspend = el3_pnp_suspend,
.resume = el3_pnp_resume,
@@ -496,7 +493,7 @@ static struct eisa_driver el3_eisa_driver = {
.driver = {
.name = "3c579",
.probe = el3_eisa_probe,
- .remove = __devexit_p (el3_device_remove),
+ .remove = el3_device_remove,
.suspend = el3_suspend,
.resume = el3_resume,
}
@@ -519,7 +516,7 @@ static const struct net_device_ops netdev_ops = {
#endif
};
-static int __devinit el3_common_init(struct net_device *dev)
+static int el3_common_init(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
int err;
@@ -618,7 +615,7 @@ static int __init el3_eisa_probe (struct device *device)
/* This remove works for all device types.
*
* The net dev must be stored in the driver data field */
-static int __devexit el3_device_remove (struct device *device)
+static int el3_device_remove(struct device *device)
{
struct net_device *dev;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index e463d1036829..ed0feb3cc6fa 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -102,7 +102,7 @@ static int vortex_debug = 1;
#include <linux/delay.h>
-static const char version[] __devinitconst =
+static const char version[] =
DRV_NAME ": Donald Becker and others.\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -277,7 +277,7 @@ static struct vortex_chip_info {
int flags;
int drv_flags;
int io_size;
-} vortex_info_tbl[] __devinitdata = {
+} vortex_info_tbl[] = {
{"3c590 Vortex 10Mbps",
PCI_USES_MASTER, IS_VORTEX, 32, },
{"3c592 EISA 10Mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */
@@ -931,7 +931,7 @@ static int __init vortex_eisa_probe(struct device *device)
return 0;
}
-static int __devexit vortex_eisa_remove(struct device *device)
+static int vortex_eisa_remove(struct device *device)
{
struct eisa_device *edev;
struct net_device *dev;
@@ -962,7 +962,7 @@ static struct eisa_driver vortex_eisa_driver = {
.driver = {
.name = "3c59x",
.probe = vortex_eisa_probe,
- .remove = __devexit_p(vortex_eisa_remove)
+ .remove = vortex_eisa_remove
}
};
@@ -1000,8 +1000,8 @@ static int __init vortex_eisa_init(void)
}
/* returns count (>= 0), or negative on error */
-static int __devinit vortex_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int vortex_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int rc, unit, pci_bar;
struct vortex_chip_info *vci;
@@ -1088,9 +1088,8 @@ static const struct net_device_ops vortex_netdev_ops = {
*
* NOTE: pdev can be NULL, for the case of a Compaq device
*/
-static int __devinit vortex_probe1(struct device *gendev,
- void __iomem *ioaddr, int irq,
- int chip_idx, int card_idx)
+static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
+ int chip_idx, int card_idx)
{
struct vortex_private *vp;
int option;
@@ -3222,7 +3221,7 @@ static void acpi_set_WOL(struct net_device *dev)
}
-static void __devexit vortex_remove_one(struct pci_dev *pdev)
+static void vortex_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct vortex_private *vp;
@@ -3265,7 +3264,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev)
static struct pci_driver vortex_driver = {
.name = "3c59x",
.probe = vortex_init_one,
- .remove = __devexit_p(vortex_remove_one),
+ .remove = vortex_remove_one,
.id_table = vortex_pci_tbl,
.driver.pm = VORTEX_PM_OPS,
};
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
index bad4fa6815c5..eb56174469a7 100644
--- a/drivers/net/ethernet/3com/Kconfig
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -80,7 +80,7 @@ config PCMCIA_3C589
config VORTEX
tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
- depends on (PCI || EISA)
+ depends on (PCI || EISA) && HAS_IOPORT
select NET_CORE
select MII
---help---
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index bb9670f29b59..27aaaf99e73e 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -168,7 +168,7 @@ enum typhoon_cards {
};
/* directly indexed by enum typhoon_cards, above */
-static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+static struct typhoon_card_info typhoon_card_info[] = {
{ "3Com Typhoon (3C990-TX)",
TYPHOON_CRYPTO_NONE},
{ "3Com Typhoon (3CR990-TX-95)",
@@ -2200,7 +2200,7 @@ need_resume:
}
#endif
-static int __devinit
+static int
typhoon_test_mmio(struct pci_dev *pdev)
{
void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
@@ -2258,7 +2258,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit
+static int
typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
@@ -2509,7 +2509,7 @@ error_out:
return err;
}
-static void __devexit
+static void
typhoon_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2533,7 +2533,7 @@ static struct pci_driver typhoon_driver = {
.name = KBUILD_MODNAME,
.id_table = typhoon_pci_tbl,
.probe = typhoon_init_one,
- .remove = __devexit_p(typhoon_remove_one),
+ .remove = typhoon_remove_one,
#ifdef CONFIG_PM
.suspend = typhoon_suspend,
.resume = typhoon_resume,
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 203ff9dccadb..70dba5d01ad3 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -109,7 +109,7 @@ static inline struct ax_device *to_ax_dev(struct net_device *dev)
/*
* ax_initial_check
*
- * do an initial probe for the card to check wether it exists
+ * do an initial probe for the card to check whether it exists
* and is functional
*/
static int ax_initial_check(struct net_device *dev)
@@ -191,11 +191,11 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
if (ei_local->word16)
- readsw(nic_base + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr) >> 1);
+ ioread16_rep(nic_base + NE_DATAPORT, hdr,
+ sizeof(struct e8390_pkt_hdr) >> 1);
else
- readsb(nic_base + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr));
+ ioread8_rep(nic_base + NE_DATAPORT, hdr,
+ sizeof(struct e8390_pkt_hdr));
ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_local->dmaing &= ~0x01;
@@ -237,12 +237,12 @@ static void ax_block_input(struct net_device *dev, int count,
ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
if (ei_local->word16) {
- readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+ ioread16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
if (count & 0x01)
buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
} else {
- readsb(nic_base + NE_DATAPORT, buf, count);
+ ioread8_rep(nic_base + NE_DATAPORT, buf, count);
}
ei_local->dmaing &= ~1;
@@ -286,9 +286,9 @@ static void ax_block_output(struct net_device *dev, int count,
ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
if (ei_local->word16)
- writesw(nic_base + NE_DATAPORT, buf, count >> 1);
+ iowrite16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
else
- writesb(nic_base + NE_DATAPORT, buf, count);
+ iowrite8_rep(nic_base + NE_DATAPORT, buf, count);
dma_start = jiffies;
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
index 8322c54972f3..78c6fb4b1143 100644
--- a/drivers/net/ethernet/8390/etherh.c
+++ b/drivers/net/ethernet/8390/etherh.c
@@ -463,12 +463,6 @@ etherh_open(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
return -EAGAIN;
@@ -527,7 +521,7 @@ static void __init etherh_banner(void)
* Read the ethernet address string from the on board rom.
* This is an ascii string...
*/
-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
+static int etherh_addr(char *addr, struct expansion_card *ec)
{
struct in_chunk_dir cd;
char *s;
@@ -657,7 +651,7 @@ static const struct net_device_ops etherh_netdev_ops = {
static u32 etherh_regoffsets[16];
static u32 etherm_regoffsets[16];
-static int __devinit
+static int
etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{
const struct etherh_data *data = id->data;
@@ -775,7 +769,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit etherh_remove(struct expansion_card *ec)
+static void etherh_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
@@ -839,7 +833,7 @@ static const struct ecard_id etherh_ids[] = {
static struct ecard_driver etherh_driver = {
.probe = etherh_probe,
- .remove = __devexit_p(etherh_remove),
+ .remove = etherh_remove,
.id_table = etherh_ids,
.drv = {
.name = DRV_NAME,
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
index 5370c884620b..fb3dd4399cf3 100644
--- a/drivers/net/ethernet/8390/hydra.c
+++ b/drivers/net/ethernet/8390/hydra.c
@@ -53,9 +53,9 @@ static const char version[] =
#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-static int __devinit hydra_init_one(struct zorro_dev *z,
+static int hydra_init_one(struct zorro_dev *z,
const struct zorro_device_id *ent);
-static int __devinit hydra_init(struct zorro_dev *z);
+static int hydra_init(struct zorro_dev *z);
static int hydra_open(struct net_device *dev);
static int hydra_close(struct net_device *dev);
static void hydra_reset_8390(struct net_device *dev);
@@ -65,9 +65,9 @@ static void hydra_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset);
static void hydra_block_output(struct net_device *dev, int count,
const unsigned char *buf, int start_page);
-static void __devexit hydra_remove_one(struct zorro_dev *z);
+static void hydra_remove_one(struct zorro_dev *z);
-static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id hydra_zorro_tbl[] = {
{ ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
{ 0 }
};
@@ -77,11 +77,11 @@ static struct zorro_driver hydra_driver = {
.name = "hydra",
.id_table = hydra_zorro_tbl,
.probe = hydra_init_one,
- .remove = __devexit_p(hydra_remove_one),
+ .remove = hydra_remove_one,
};
-static int __devinit hydra_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int hydra_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
int err;
@@ -110,7 +110,7 @@ static const struct net_device_ops hydra_netdev_ops = {
#endif
};
-static int __devinit hydra_init(struct zorro_dev *z)
+static int hydra_init(struct zorro_dev *z)
{
struct net_device *dev;
unsigned long board = ZTWO_VADDR(z->resource.start);
@@ -247,7 +247,7 @@ static void hydra_block_output(struct net_device *dev, int count,
z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
}
-static void __devexit hydra_remove_one(struct zorro_dev *z)
+static void hydra_remove_one(struct zorro_dev *z)
{
struct net_device *dev = zorro_get_drvdata(z);
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index 5e8845febfb8..c0c127913dec 100644
--- a/drivers/net/ethernet/8390/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -61,7 +61,7 @@ static int options[MAX_UNITS];
#include "8390.h"
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
" D. Becker/P. Gortmaker\n";
@@ -119,7 +119,7 @@ enum ne2k_pci_chipsets {
static struct {
char *name;
int flags;
-} pci_clone_list[] __devinitdata = {
+} pci_clone_list[] = {
{"RealTek RTL-8029", REALTEK_FDX},
{"Winbond 89C940", 0},
{"Compex RL2000", 0},
@@ -215,8 +215,8 @@ static const struct net_device_ops ne2k_netdev_ops = {
#endif
};
-static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ne2k_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
int i;
@@ -647,7 +647,7 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = {
.get_drvinfo = ne2k_pci_get_drvinfo,
};
-static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
+static void ne2k_pci_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -696,7 +696,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev)
static struct pci_driver ne2k_driver = {
.name = DRV_NAME,
.probe = ne2k_pci_init_one,
- .remove = __devexit_p(ne2k_pci_remove_one),
+ .remove = ne2k_pci_remove_one,
.id_table = ne2k_pci_tbl,
#ifdef CONFIG_PM
.suspend = ne2k_pci_suspend,
diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c
index e3f57427d5c5..ebcdb52ec739 100644
--- a/drivers/net/ethernet/8390/ne3210.c
+++ b/drivers/net/ethernet/8390/ne3210.c
@@ -222,7 +222,7 @@ static int __init ne3210_eisa_probe (struct device *device)
return retval;
}
-static int __devexit ne3210_eisa_remove (struct device *device)
+static int ne3210_eisa_remove(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
unsigned long ioaddr = to_eisa_device (device)->base_addr;
@@ -324,7 +324,7 @@ static struct eisa_driver ne3210_eisa_driver = {
.driver = {
.name = "ne3210",
.probe = ne3210_eisa_probe,
- .remove = __devexit_p (ne3210_eisa_remove),
+ .remove = ne3210_eisa_remove,
},
};
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
index 7818e6397e91..85ec4c2d2645 100644
--- a/drivers/net/ethernet/8390/zorro8390.c
+++ b/drivers/net/ethernet/8390/zorro8390.c
@@ -75,7 +75,7 @@ static struct card_info {
zorro_id id;
const char *name;
unsigned int offset;
-} cards[] __devinitdata = {
+} cards[] = {
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
};
@@ -254,7 +254,7 @@ static int zorro8390_close(struct net_device *dev)
return 0;
}
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+static void zorro8390_remove_one(struct zorro_dev *z)
{
struct net_device *dev = zorro_get_drvdata(z);
@@ -264,7 +264,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z)
free_netdev(dev);
}
-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id zorro8390_zorro_tbl[] = {
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
{ 0 }
@@ -286,9 +286,8 @@ static const struct net_device_ops zorro8390_netdev_ops = {
#endif
};
-static int __devinit zorro8390_init(struct net_device *dev,
- unsigned long board, const char *name,
- unsigned long ioaddr)
+static int zorro8390_init(struct net_device *dev, unsigned long board,
+ const char *name, unsigned long ioaddr)
{
int i;
int err;
@@ -396,8 +395,8 @@ static int __devinit zorro8390_init(struct net_device *dev,
return 0;
}
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int zorro8390_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
struct net_device *dev;
unsigned long board, ioaddr;
@@ -432,7 +431,7 @@ static struct zorro_driver zorro8390_driver = {
.name = "zorro8390",
.id_table = zorro8390_zorro_tbl,
.probe = zorro8390_init_one,
- .remove = __devexit_p(zorro8390_remove_one),
+ .remove = zorro8390_remove_one,
};
static int __init zorro8390_init_module(void)
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 5b65992c2a0a..549b77500579 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -166,7 +166,7 @@ static int rx_copybreak /* = 0 */;
#define FIRMWARE_TX "adaptec/starfire_tx.bin"
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"
" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
static const struct chip_info {
const char *name;
int drv_flags;
-} netdrv_tbl[] __devinitconst = {
+} netdrv_tbl[] = {
{ "Adaptec Starfire 6915", CanHaveMII },
};
@@ -641,8 +641,8 @@ static const struct net_device_ops netdev_ops = {
#endif
};
-static int __devinit starfire_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int starfire_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct device *d = &pdev->dev;
struct netdev_private *np;
@@ -1990,7 +1990,7 @@ static int starfire_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
-static void __devexit starfire_remove_one (struct pci_dev *pdev)
+static void starfire_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct netdev_private *np = netdev_priv(dev);
@@ -2018,7 +2018,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
static struct pci_driver starfire_driver = {
.name = DRV_NAME,
.probe = starfire_init_one,
- .remove = __devexit_p(starfire_remove_one),
+ .remove = starfire_remove_one,
#ifdef CONFIG_PM
.suspend = starfire_suspend,
.resume = starfire_resume,
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index 49a30d37ae4a..e49c0eff040b 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -61,7 +61,7 @@ config BFIN_RX_DESC_NUM
config BFIN_MAC_USE_HWSTAMP
bool "Use IEEE 1588 hwstamp"
- depends on BFIN_MAC && BF518
+ select PTP_1588_CLOCK
default y
---help---
To support the IEEE 1588 Precision Time Protocol (PTP), select y here
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index f816426e1085..c1fdb8be8bee 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -548,14 +548,17 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev,
return 0;
}
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
+ struct bfin_mac_local *lp = netdev_priv(dev);
+
info->so_timestamping =
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
- SOF_TIMESTAMPING_SYS_HARDWARE;
- info->phc_index = -1;
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = lp->phc_index;
info->tx_types =
(1 << HWTSTAMP_TX_OFF) |
(1 << HWTSTAMP_TX_ON);
@@ -566,6 +569,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
return 0;
}
+#endif
static const struct ethtool_ops bfin_mac_ethtool_ops = {
.get_settings = bfin_mac_ethtool_getsettings,
@@ -574,7 +578,9 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
.get_drvinfo = bfin_mac_ethtool_getdrvinfo,
.get_wol = bfin_mac_ethtool_getwol,
.set_wol = bfin_mac_ethtool_setwol,
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
.get_ts_info = bfin_mac_ethtool_get_ts_info,
+#endif
};
/**************************************************************************/
@@ -649,6 +655,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
+static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
+{
+ u32 ipn = 1000000000UL / input_clk;
+ u32 ppn = 1;
+ unsigned int shift = 0;
+
+ while (ppn <= ipn) {
+ ppn <<= 1;
+ shift++;
+ }
+ *shift_result = shift;
+ return 1000000000UL / ppn;
+}
+
static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd)
{
@@ -798,19 +818,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
bfin_read_EMAC_PTP_TXSNAPLO();
bfin_read_EMAC_PTP_TXSNAPHI();
- /*
- * Set registers so that rollover occurs soon to test this.
- */
- bfin_write_EMAC_PTP_TIMELO(0x00000000);
- bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
-
SSYNC();
-
- lp->compare.last_update = 0;
- timecounter_init(&lp->clock,
- &lp->cycles,
- ktime_to_ns(ktime_get_real()));
- timecompare_update(&lp->compare, 0);
}
lp->stamp_cfg = config;
@@ -818,15 +826,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
-EFAULT : 0;
}
-static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
-{
- ktime_t sys = ktime_get_real();
-
- pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
- __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
- sys.tv.nsec, cmp->offset, cmp->skew);
-}
-
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
{
struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -857,15 +856,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
regval = bfin_read_EMAC_PTP_TXSNAPLO();
regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
- ns = timecounter_cyc2time(&lp->clock,
- regval);
- timecompare_update(&lp->compare, ns);
+ ns = regval << lp->shift;
shhwtstamps.hwtstamp = ns_to_ktime(ns);
- shhwtstamps.syststamp =
- timecompare_transform(&lp->compare, ns);
skb_tstamp_tx(skb, &shhwtstamps);
-
- bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
}
}
}
@@ -888,55 +881,184 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
regval = bfin_read_EMAC_PTP_RXSNAPLO();
regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
- ns = timecounter_cyc2time(&lp->clock, regval);
- timecompare_update(&lp->compare, ns);
+ ns = regval << lp->shift;
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
shhwtstamps->hwtstamp = ns_to_ktime(ns);
- shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
+}
+
+static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+{
+ struct bfin_mac_local *lp = netdev_priv(netdev);
+ u64 addend, ppb;
+ u32 input_clk, phc_clk;
+
+ /* Initialize hardware timer */
+ input_clk = get_sclk();
+ phc_clk = bfin_select_phc_clock(input_clk, &lp->shift);
+ addend = phc_clk * (1ULL << 32);
+ do_div(addend, input_clk);
+ bfin_write_EMAC_PTP_ADDEND((u32)addend);
+
+ lp->addend = addend;
+ ppb = 1000000000ULL * input_clk;
+ do_div(ppb, phc_clk);
+ lp->max_ppb = ppb - 1000000000ULL - 1ULL;
- bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
+ /* Initialize hwstamp config */
+ lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+ lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
}
-/*
- * bfin_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t bfin_read_clock(const struct cyclecounter *tc)
+static u64 bfin_ptp_time_read(struct bfin_mac_local *lp)
{
- u64 stamp;
+ u64 ns;
+ u32 lo, hi;
+
+ lo = bfin_read_EMAC_PTP_TIMELO();
+ hi = bfin_read_EMAC_PTP_TIMEHI();
- stamp = bfin_read_EMAC_PTP_TIMELO();
- stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
+ ns = ((u64) hi) << 32;
+ ns |= lo;
+ ns <<= lp->shift;
- return stamp;
+ return ns;
}
-#define PTP_CLK 25000000
+static void bfin_ptp_time_write(struct bfin_mac_local *lp, u64 ns)
+{
+ u32 hi, lo;
-static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+ ns >>= lp->shift;
+ hi = ns >> 32;
+ lo = ns & 0xffffffff;
+
+ bfin_write_EMAC_PTP_TIMELO(lo);
+ bfin_write_EMAC_PTP_TIMEHI(hi);
+}
+
+/* PTP Hardware Clock operations */
+
+static int bfin_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ u64 adj;
+ u32 diff, addend;
+ int neg_adj = 0;
+ struct bfin_mac_local *lp =
+ container_of(ptp, struct bfin_mac_local, caps);
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ addend = lp->addend;
+ adj = addend;
+ adj *= ppb;
+ diff = div_u64(adj, 1000000000ULL);
+
+ addend = neg_adj ? addend - diff : addend + diff;
+
+ bfin_write_EMAC_PTP_ADDEND(addend);
+
+ return 0;
+}
+
+static int bfin_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ s64 now;
+ unsigned long flags;
+ struct bfin_mac_local *lp =
+ container_of(ptp, struct bfin_mac_local, caps);
+
+ spin_lock_irqsave(&lp->phc_lock, flags);
+
+ now = bfin_ptp_time_read(lp);
+ now += delta;
+ bfin_ptp_time_write(lp, now);
+
+ spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+ return 0;
+}
+
+static int bfin_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+ struct bfin_mac_local *lp =
+ container_of(ptp, struct bfin_mac_local, caps);
+
+ spin_lock_irqsave(&lp->phc_lock, flags);
+
+ ns = bfin_ptp_time_read(lp);
+
+ spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+ return 0;
+}
+
+static int bfin_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ u64 ns;
+ unsigned long flags;
+ struct bfin_mac_local *lp =
+ container_of(ptp, struct bfin_mac_local, caps);
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&lp->phc_lock, flags);
+
+ bfin_ptp_time_write(lp, ns);
+
+ spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+ return 0;
+}
+
+static int bfin_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info bfin_ptp_caps = {
+ .owner = THIS_MODULE,
+ .name = "BF518 clock",
+ .max_adj = 0,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .pps = 0,
+ .adjfreq = bfin_ptp_adjfreq,
+ .adjtime = bfin_ptp_adjtime,
+ .gettime = bfin_ptp_gettime,
+ .settime = bfin_ptp_settime,
+ .enable = bfin_ptp_enable,
+};
+
+static int bfin_phc_init(struct net_device *netdev, struct device *dev)
{
struct bfin_mac_local *lp = netdev_priv(netdev);
- u64 append;
- /* Initialize hardware timer */
- append = PTP_CLK * (1ULL << 32);
- do_div(append, get_sclk());
- bfin_write_EMAC_PTP_ADDEND((u32)append);
-
- memset(&lp->cycles, 0, sizeof(lp->cycles));
- lp->cycles.read = bfin_read_clock;
- lp->cycles.mask = CLOCKSOURCE_MASK(64);
- lp->cycles.mult = 1000000000 / PTP_CLK;
- lp->cycles.shift = 0;
-
- /* Synchronize our NIC clock against system wall clock */
- memset(&lp->compare, 0, sizeof(lp->compare));
- lp->compare.source = &lp->clock;
- lp->compare.target = ktime_get_real;
- lp->compare.num_samples = 10;
+ lp->caps = bfin_ptp_caps;
+ lp->caps.max_adj = lp->max_ppb;
+ lp->clock = ptp_clock_register(&lp->caps, dev);
+ if (IS_ERR(lp->clock))
+ return PTR_ERR(lp->clock);
- /* Initialize hwstamp config */
- lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
- lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+ lp->phc_index = ptp_clock_index(lp->clock);
+ spin_lock_init(&lp->phc_lock);
+
+ return 0;
+}
+
+static void bfin_phc_release(struct bfin_mac_local *lp)
+{
+ ptp_clock_unregister(lp->clock);
}
#else
@@ -945,6 +1067,8 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev)
# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
# define bfin_rx_hwtstamp(dev, skb)
# define bfin_tx_hwtstamp(dev, skb)
+# define bfin_phc_init(netdev, dev) 0
+# define bfin_phc_release(lp)
#endif
static inline void _tx_reclaim_skb(void)
@@ -1479,7 +1603,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
#endif
};
-static int __devinit bfin_mac_probe(struct platform_device *pdev)
+static int bfin_mac_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct bfin_mac_local *lp;
@@ -1579,12 +1703,17 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
}
bfin_mac_hwtstamp_init(ndev);
+ if (bfin_phc_init(ndev, &pdev->dev)) {
+ dev_err(&pdev->dev, "Cannot register PHC device!\n");
+ goto out_err_phc;
+ }
/* now, print out the card info, in a short format.. */
netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
return 0;
+out_err_phc:
out_err_reg_ndev:
free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
@@ -1598,11 +1727,13 @@ out_err_probe_mac:
return rc;
}
-static int __devexit bfin_mac_remove(struct platform_device *pdev)
+static int bfin_mac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct bfin_mac_local *lp = netdev_priv(ndev);
+ bfin_phc_release(lp);
+
platform_set_drvdata(pdev, NULL);
lp->mii_bus->priv = NULL;
@@ -1655,7 +1786,7 @@ static int bfin_mac_resume(struct platform_device *pdev)
#define bfin_mac_resume NULL
#endif /* CONFIG_PM */
-static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+static int bfin_mii_bus_probe(struct platform_device *pdev)
{
struct mii_bus *miibus;
struct bfin_mii_bus_platform_data *mii_bus_pd;
@@ -1733,7 +1864,7 @@ out_err_alloc:
return rc;
}
-static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+static int bfin_mii_bus_remove(struct platform_device *pdev)
{
struct mii_bus *miibus = platform_get_drvdata(pdev);
struct bfin_mii_bus_platform_data *mii_bus_pd =
@@ -1750,7 +1881,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
static struct platform_driver bfin_mii_bus_driver = {
.probe = bfin_mii_bus_probe,
- .remove = __devexit_p(bfin_mii_bus_remove),
+ .remove = bfin_mii_bus_remove,
.driver = {
.name = "bfin_mii_bus",
.owner = THIS_MODULE,
@@ -1759,7 +1890,7 @@ static struct platform_driver bfin_mii_bus_driver = {
static struct platform_driver bfin_mac_driver = {
.probe = bfin_mac_probe,
- .remove = __devexit_p(bfin_mac_remove),
+ .remove = bfin_mac_remove,
.resume = bfin_mac_resume,
.suspend = bfin_mac_suspend,
.driver = {
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index 960905c08223..7a07ee07906b 100644
--- a/drivers/net/ethernet/adi/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
@@ -11,8 +11,7 @@
#define _BFIN_MAC_H_
#include <linux/net_tstamp.h>
-#include <linux/clocksource.h>
-#include <linux/timecompare.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/timer.h>
#include <linux/etherdevice.h>
#include <linux/bfin_mac.h>
@@ -94,10 +93,14 @@ struct bfin_mac_local {
struct mii_bus *mii_bus;
#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
- struct cyclecounter cycles;
- struct timecounter clock;
- struct timecompare compare;
+ u32 addend;
+ unsigned int shift;
+ s32 max_ppb;
struct hwtstamp_config stamp_cfg;
+ struct ptp_clock_info caps;
+ struct ptp_clock *clock;
+ int phc_index;
+ spinlock_t phc_lock; /* protects time lo/hi registers */
#endif
};
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 9c77c736f171..aa53115bb38b 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1376,7 +1376,7 @@ error:
}
/* Initialize the GRETH MAC */
-static int __devinit greth_of_probe(struct platform_device *ofdev)
+static int greth_of_probe(struct platform_device *ofdev)
{
struct net_device *dev;
struct greth_private *greth;
@@ -1576,7 +1576,7 @@ error1:
return err;
}
-static int __devexit greth_of_remove(struct platform_device *of_dev)
+static int greth_of_remove(struct platform_device *of_dev)
{
struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
struct greth_private *greth = netdev_priv(ndev);
@@ -1619,7 +1619,7 @@ static struct platform_driver greth_of_driver = {
.of_match_table = greth_of_match,
},
.probe = greth_of_probe,
- .remove = __devexit_p(greth_of_remove),
+ .remove = greth_of_remove,
};
module_platform_driver(greth_of_driver);
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 7219123fa0a4..c0bc41a784ca 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -426,7 +426,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript
MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
-static const char version[] __devinitconst =
+static const char version[] =
"acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
" http://home.cern.ch/~jes/gige/acenic.html\n";
@@ -454,8 +454,8 @@ static const struct net_device_ops ace_netdev_ops = {
.ndo_change_mtu = ace_change_mtu,
};
-static int __devinit acenic_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int acenic_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct net_device *dev;
struct ace_private *ap;
@@ -603,7 +603,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
return -ENODEV;
}
-static void __devexit acenic_remove_one(struct pci_dev *pdev)
+static void acenic_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct ace_private *ap = netdev_priv(dev);
@@ -699,7 +699,7 @@ static struct pci_driver acenic_pci_driver = {
.name = "acenic",
.id_table = acenic_pci_tbl,
.probe = acenic_probe_one,
- .remove = __devexit_p(acenic_remove_one),
+ .remove = acenic_remove_one,
};
static int __init acenic_init(void)
@@ -871,7 +871,7 @@ static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
}
-static int __devinit ace_init(struct net_device *dev)
+static int ace_init(struct net_device *dev)
{
struct ace_private *ap;
struct ace_regs __iomem *regs;
@@ -2824,8 +2824,8 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
}
-static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
- u32 dest, int size)
+static void ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+ u32 dest, int size)
{
void __iomem *tdest;
short tsize, i;
@@ -2851,7 +2851,7 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
}
-static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
+static void ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
{
void __iomem *tdest;
short tsize = 0, i;
@@ -2882,7 +2882,7 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
* This operation requires the NIC to be halted and is performed with
* interrupts disabled and with the spinlock hold.
*/
-static int __devinit ace_load_firmware(struct net_device *dev)
+static int ace_load_firmware(struct net_device *dev)
{
const struct firmware *fw;
const char *fw_name = "acenic/tg2.bin";
@@ -2962,7 +2962,7 @@ static int __devinit ace_load_firmware(struct net_device *dev)
* Thanks to Stevarino Webinski for helping tracking down the bugs in the
* code i2c readout code by beta testing all my hacks.
*/
-static void __devinit eeprom_start(struct ace_regs __iomem *regs)
+static void eeprom_start(struct ace_regs __iomem *regs)
{
u32 local;
@@ -2991,7 +2991,7 @@ static void __devinit eeprom_start(struct ace_regs __iomem *regs)
}
-static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
+static void eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
{
short i;
u32 local;
@@ -3028,7 +3028,7 @@ static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
}
-static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
+static int eeprom_check_ack(struct ace_regs __iomem *regs)
{
int state;
u32 local;
@@ -3056,7 +3056,7 @@ static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
}
-static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
+static void eeprom_stop(struct ace_regs __iomem *regs)
{
u32 local;
@@ -3091,8 +3091,7 @@ static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
/*
* Read a whole byte from the EEPROM.
*/
-static int __devinit read_eeprom_byte(struct net_device *dev,
- unsigned long offset)
+static int read_eeprom_byte(struct net_device *dev, unsigned long offset)
{
struct ace_private *ap = netdev_priv(dev);
struct ace_regs __iomem *regs = ap->regs;
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
index 689dfcafc6d4..3789affbc0e5 100644
--- a/drivers/net/ethernet/amd/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -639,12 +639,12 @@ static void lance_set_multicast(struct net_device *dev)
netif_wake_queue(dev);
}
-static int __devinit a2065_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static void __devexit a2065_remove_one(struct zorro_dev *z);
+static int a2065_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent);
+static void a2065_remove_one(struct zorro_dev *z);
-static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id a2065_zorro_tbl[] = {
{ ZORRO_PROD_CBM_A2065_1 },
{ ZORRO_PROD_CBM_A2065_2 },
{ ZORRO_PROD_AMERISTAR_A2065 },
@@ -656,7 +656,7 @@ static struct zorro_driver a2065_driver = {
.name = "a2065",
.id_table = a2065_zorro_tbl,
.probe = a2065_init_one,
- .remove = __devexit_p(a2065_remove_one),
+ .remove = a2065_remove_one,
};
static const struct net_device_ops lance_netdev_ops = {
@@ -670,8 +670,8 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit a2065_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int a2065_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
struct net_device *dev;
struct lance_private *priv;
@@ -754,7 +754,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
}
-static void __devexit a2065_remove_one(struct zorro_dev *z)
+static void a2065_remove_one(struct zorro_dev *z)
{
struct net_device *dev = zorro_get_drvdata(z);
diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index e10ffad525a7..60e2b701afe7 100644
--- a/drivers/net/ethernet/amd/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -671,7 +671,7 @@ static const struct net_device_ops am79c961_netdev_ops = {
#endif
};
-static int __devinit am79c961_probe(struct platform_device *pdev)
+static int am79c961_probe(struct platform_device *pdev)
{
struct resource *res;
struct net_device *dev;
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 3491d4312fc9..42d4e6ad58a5 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1702,7 +1702,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev)
}
-static void __devexit amd8111e_remove_one(struct pci_dev *pdev)
+static void amd8111e_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
@@ -1774,7 +1774,7 @@ static void amd8111e_config_ipg(struct net_device* dev)
}
-static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
+static void amd8111e_probe_ext_phy(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
int i;
@@ -1810,7 +1810,7 @@ static const struct net_device_ops amd8111e_netdev_ops = {
#endif
};
-static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
+static int amd8111e_probe_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int err,i,pm_cap;
@@ -1976,7 +1976,7 @@ static struct pci_driver amd8111e_driver = {
.name = MODULE_NAME,
.id_table = amd8111e_pci_tbl,
.probe = amd8111e_probe_one,
- .remove = __devexit_p(amd8111e_remove_one),
+ .remove = amd8111e_remove_one,
.suspend = amd8111e_suspend,
.resume = amd8111e_resume
};
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index f2958df9a1e4..98f4522fd17b 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -682,7 +682,7 @@ static void set_multicast_list(struct net_device *dev)
}
-static void __devexit ariadne_remove_one(struct zorro_dev *z)
+static void ariadne_remove_one(struct zorro_dev *z)
{
struct net_device *dev = zorro_get_drvdata(z);
@@ -692,7 +692,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z)
free_netdev(dev);
}
-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id ariadne_zorro_tbl[] = {
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
{ 0 }
};
@@ -710,8 +710,8 @@ static const struct net_device_ops ariadne_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int ariadne_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
unsigned long board = z->resource.start;
unsigned long base_addr = board + ARIADNE_LANCE;
@@ -774,7 +774,7 @@ static struct zorro_driver ariadne_driver = {
.name = "ariadne",
.id_table = ariadne_zorro_tbl,
.probe = ariadne_init_one,
- .remove = __devexit_p(ariadne_remove_one),
+ .remove = ariadne_remove_one,
};
static int __init ariadne_init_module(void)
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index f195acfa2df7..2ea221ed4777 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1016,7 +1016,7 @@ static const struct net_device_ops au1000_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit au1000_probe(struct platform_device *pdev)
+static int au1000_probe(struct platform_device *pdev)
{
static unsigned version_printed;
struct au1000_private *aup = NULL;
@@ -1295,7 +1295,7 @@ out:
return err;
}
-static int __devexit au1000_remove(struct platform_device *pdev)
+static int au1000_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct au1000_private *aup = netdev_priv(dev);
@@ -1340,7 +1340,7 @@ static int __devexit au1000_remove(struct platform_device *pdev)
static struct platform_driver au1000_eth_driver = {
.probe = au1000_probe,
- .remove = __devexit_p(au1000_remove),
+ .remove = au1000_remove,
.driver = {
.name = "au1000-eth",
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 7203b522f234..baca0bd1b393 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -72,7 +72,7 @@
#include <asm/dec/machtype.h>
#include <asm/dec/system.h>
-static char version[] __devinitdata =
+static char version[] =
"declance.c: v0.011 by Linux MIPS DECstation task force\n";
MODULE_AUTHOR("Linux MIPS DECstation task force");
@@ -1020,7 +1020,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit dec_lance_probe(struct device *bdev, const int type)
+static int dec_lance_probe(struct device *bdev, const int type)
{
static unsigned version_printed;
static const char fmt[] = "declance%d";
@@ -1322,7 +1322,7 @@ static void __exit dec_lance_platform_remove(void)
}
#ifdef CONFIG_TC
-static int __devinit dec_lance_tc_probe(struct device *dev);
+static int dec_lance_tc_probe(struct device *dev);
static int __exit dec_lance_tc_remove(struct device *dev);
static const struct tc_device_id dec_lance_tc_table[] = {
@@ -1341,7 +1341,7 @@ static struct tc_driver dec_lance_tc_driver = {
},
};
-static int __devinit dec_lance_tc_probe(struct device *dev)
+static int dec_lance_tc_probe(struct device *dev)
{
int status = dec_lance_probe(dev, PMAD_LANCE);
if (!status)
diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c
index c771de71612a..34a485363d5b 100644
--- a/drivers/net/ethernet/amd/depca.c
+++ b/drivers/net/ethernet/amd/depca.c
@@ -338,21 +338,21 @@ static struct eisa_driver depca_eisa_driver = {
.driver = {
.name = depca_string,
.probe = depca_eisa_probe,
- .remove = __devexit_p (depca_device_remove)
+ .remove = depca_device_remove
}
};
#endif
static int depca_isa_probe (struct platform_device *);
-static int __devexit depca_isa_remove(struct platform_device *pdev)
+static int depca_isa_remove(struct platform_device *pdev)
{
return depca_device_remove(&pdev->dev);
}
static struct platform_driver depca_isa_driver = {
.probe = depca_isa_probe,
- .remove = __devexit_p(depca_isa_remove),
+ .remove = depca_isa_remove,
.driver = {
.name = depca_string,
},
@@ -1320,7 +1320,7 @@ static enum depca_type __init depca_shmem_probe (ulong *mem_start)
return adapter;
}
-static int __devinit depca_isa_probe (struct platform_device *device)
+static int depca_isa_probe(struct platform_device *device)
{
struct net_device *dev;
struct depca_private *lp;
@@ -1412,7 +1412,7 @@ static int __init depca_eisa_probe (struct device *device)
}
#endif
-static int __devexit depca_device_remove (struct device *device)
+static int depca_device_remove(struct device *device)
{
struct net_device *dev;
struct depca_private *lp;
diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
index 8baff4e5d964..0c61fd50d882 100644
--- a/drivers/net/ethernet/amd/hplance.c
+++ b/drivers/net/ethernet/amd/hplance.c
@@ -46,11 +46,9 @@ struct hplance_private {
* plus board-specific init, open and close actions.
* Oh, and we need to tell the generic code how to read and write LANCE registers...
*/
-static int __devinit hplance_init_one(struct dio_dev *d,
- const struct dio_device_id *ent);
-static void __devinit hplance_init(struct net_device *dev,
- struct dio_dev *d);
-static void __devexit hplance_remove_one(struct dio_dev *d);
+static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent);
+static void hplance_init(struct net_device *dev, struct dio_dev *d);
+static void hplance_remove_one(struct dio_dev *d);
static void hplance_writerap(void *priv, unsigned short value);
static void hplance_writerdp(void *priv, unsigned short value);
static unsigned short hplance_readrdp(void *priv);
@@ -66,7 +64,7 @@ static struct dio_driver hplance_driver = {
.name = "hplance",
.id_table = hplance_dio_tbl,
.probe = hplance_init_one,
- .remove = __devexit_p(hplance_remove_one),
+ .remove = hplance_remove_one,
};
static const struct net_device_ops hplance_netdev_ops = {
@@ -83,8 +81,7 @@ static const struct net_device_ops hplance_netdev_ops = {
};
/* Find all the HP Lance boards and initialise them... */
-static int __devinit hplance_init_one(struct dio_dev *d,
- const struct dio_device_id *ent)
+static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent)
{
struct net_device *dev;
int err = -ENOMEM;
@@ -118,7 +115,7 @@ static int __devinit hplance_init_one(struct dio_dev *d,
return err;
}
-static void __devexit hplance_remove_one(struct dio_dev *d)
+static void hplance_remove_one(struct dio_dev *d)
{
struct net_device *dev = dio_get_drvdata(d);
@@ -128,7 +125,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d)
}
/* Initialise a single lance board at the given DIO device */
-static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
+static void hplance_init(struct net_device *dev, struct dio_dev *d)
{
unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
struct hplance_private *lp;
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 86b6d8e4e6cd..a227ccdcb9b5 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -1443,7 +1443,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {
/* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */
-static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
+static void pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
{
unsigned int *port, ioaddr;
@@ -1462,7 +1462,7 @@ static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
}
}
-static int __devinit
+static int
pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned long ioaddr;
@@ -1521,7 +1521,7 @@ static const struct net_device_ops pcnet32_netdev_ops = {
* Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
* pdev will be NULL when called from pcnet32_probe_vlbus.
*/
-static int __devinit
+static int
pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
{
struct pcnet32_private *lp;
@@ -2823,7 +2823,7 @@ static int pcnet32_pm_resume(struct pci_dev *pdev)
return 0;
}
-static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
+static void pcnet32_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2844,7 +2844,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
static struct pci_driver pcnet32_driver = {
.name = DRV_NAME,
.probe = pcnet32_probe_pci,
- .remove = __devexit_p(pcnet32_remove_one),
+ .remove = pcnet32_remove_one,
.id_table = pcnet32_pci_tbl,
.suspend = pcnet32_pm_suspend,
.resume = pcnet32_pm_resume,
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index d7a3533d990b..c2d696c88e46 100644
--- a/drivers/net/ethernet/amd/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -1304,9 +1304,9 @@ static const struct net_device_ops sparc_lance_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit sparc_lance_probe_one(struct platform_device *op,
- struct platform_device *ledma,
- struct platform_device *lebuffer)
+static int sparc_lance_probe_one(struct platform_device *op,
+ struct platform_device *ledma,
+ struct platform_device *lebuffer)
{
struct device_node *dp = op->dev.of_node;
static unsigned version_printed;
@@ -1488,7 +1488,7 @@ fail:
return -ENODEV;
}
-static int __devinit sunlance_sbus_probe(struct platform_device *op)
+static int sunlance_sbus_probe(struct platform_device *op)
{
struct platform_device *parent = to_platform_device(op->dev.parent);
struct device_node *parent_dp = parent->dev.of_node;
@@ -1504,7 +1504,7 @@ static int __devinit sunlance_sbus_probe(struct platform_device *op)
return err;
}
-static int __devexit sunlance_sbus_remove(struct platform_device *op)
+static int sunlance_sbus_remove(struct platform_device *op)
{
struct lance_private *lp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = lp->dev;
@@ -1536,7 +1536,7 @@ static struct platform_driver sunlance_sbus_driver = {
.of_match_table = sunlance_sbus_match,
},
.probe = sunlance_sbus_probe,
- .remove = __devexit_p(sunlance_sbus_remove),
+ .remove = sunlance_sbus_remove,
};
module_platform_driver(sunlance_sbus_driver);
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
index 855bdafb1a87..f36bbd6d5085 100644
--- a/drivers/net/ethernet/apple/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -1244,7 +1244,7 @@ static const struct net_device_ops bmac_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
+static int bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
{
int j, rev, ret;
struct bmac_data *bp;
@@ -1602,7 +1602,7 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
}
#endif
-static int __devexit bmac_remove(struct macio_dev *mdev)
+static int bmac_remove(struct macio_dev *mdev)
{
struct net_device *dev = macio_get_drvdata(mdev);
struct bmac_data *bp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
index e1df4b76c885..842fe7684904 100644
--- a/drivers/net/ethernet/apple/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -106,7 +106,7 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
+static int mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
{
struct device_node *mace = macio_get_of_node(mdev);
struct net_device *dev;
@@ -271,7 +271,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
return rc;
}
-static int __devexit mace_remove(struct macio_dev *mdev)
+static int mace_remove(struct macio_dev *mdev)
{
struct net_device *dev = macio_get_drvdata(mdev);
struct mace_data *mp;
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index a92ddee7f665..a206779c68cf 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -195,7 +195,7 @@ static const struct net_device_ops mace_netdev_ops = {
* model of Macintrash has a MACE (AV macintoshes)
*/
-static int __devinit mace_probe(struct platform_device *pdev)
+static int mace_probe(struct platform_device *pdev)
{
int j;
struct mace_data *mp;
@@ -746,7 +746,7 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
MODULE_ALIAS("platform:macmace");
-static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+static int mac_mace_device_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct mace_data *mp = netdev_priv(dev);
@@ -768,7 +768,7 @@ static int __devexit mac_mace_device_remove (struct platform_device *pdev)
static struct platform_driver mac_mace_driver = {
.probe = mace_probe,
- .remove = __devexit_p(mac_mace_device_remove),
+ .remove = mac_mace_device_remove,
.driver = {
.name = mac_mace_string,
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index d19f82f7597a..56d3f697e0c7 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -643,7 +643,7 @@ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* @adapter: board private structure to initialize
*
*/
-static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
+static int atl1c_alloc_queues(struct atl1c_adapter *adapter)
{
return 0;
}
@@ -702,7 +702,7 @@ struct atl1c_platform_patch {
u32 patch_flag;
#define ATL1C_LINK_PATCH 0x1
};
-static const struct atl1c_platform_patch plats[] __devinitconst = {
+static const struct atl1c_platform_patch plats[] = {
{0x2060, 0xC1, 0x1019, 0x8152, 0x1},
{0x2060, 0xC1, 0x1019, 0x2060, 0x1},
{0x2060, 0xC1, 0x1019, 0xE000, 0x1},
@@ -725,7 +725,7 @@ static const struct atl1c_platform_patch plats[] __devinitconst = {
{0},
};
-static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
+static void atl1c_patch_assign(struct atl1c_hw *hw)
{
struct pci_dev *pdev = hw->adapter->pdev;
u32 misc_ctrl;
@@ -764,7 +764,7 @@ static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
*/
-static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
+static int atl1c_sw_init(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -2442,8 +2442,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
*/
-static int __devinit atl1c_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl1c_adapter *adapter;
@@ -2587,7 +2586,7 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
*/
-static void __devexit atl1c_remove(struct pci_dev *pdev)
+static void atl1c_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct atl1c_adapter *adapter = netdev_priv(netdev);
@@ -2697,7 +2696,7 @@ static struct pci_driver atl1c_driver = {
.name = atl1c_driver_name,
.id_table = atl1c_pci_tbl,
.probe = atl1c_probe,
- .remove = __devexit_p(atl1c_remove),
+ .remove = atl1c_remove,
.shutdown = atl1c_shutdown,
.err_handler = &atl1c_err_handler,
.driver.pm = &atl1c_pm_ops,
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index e213da29e73d..e4466a36d106 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -534,7 +534,7 @@ static void atl1e_setup_pcicmd(struct pci_dev *pdev)
* @adapter: board private structure to initialize
*
*/
-static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+static int atl1e_alloc_queues(struct atl1e_adapter *adapter)
{
return 0;
}
@@ -547,7 +547,7 @@ static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
*/
-static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+static int atl1e_sw_init(struct atl1e_adapter *adapter)
{
struct atl1e_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -2235,8 +2235,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
*/
-static int __devinit atl1e_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl1e_adapter *adapter = NULL;
@@ -2387,7 +2386,7 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
*/
-static void __devexit atl1e_remove(struct pci_dev *pdev)
+static void atl1e_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct atl1e_adapter *adapter = netdev_priv(netdev);
@@ -2499,7 +2498,7 @@ static struct pci_driver atl1e_driver = {
.name = atl1e_driver_name,
.id_table = atl1e_pci_tbl,
.probe = atl1e_probe,
- .remove = __devexit_p(atl1e_remove),
+ .remove = atl1e_remove,
/* Power Management Hooks */
#ifdef CONFIG_PM
.suspend = atl1e_suspend,
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
index b5086f1e637f..fa314282c9ad 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
@@ -40,7 +40,7 @@
#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
#define ATL1E_PARAM(x, desc) \
- static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+ static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
static unsigned int num_##x; \
module_param_array_named(x, x, int, &num_##x, 0); \
MODULE_PARM_DESC(x, desc);
@@ -116,7 +116,8 @@ struct atl1e_option {
} arg;
};
-static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter)
+static int atl1e_validate_option(int *value, struct atl1e_option *opt,
+ struct atl1e_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -177,7 +178,7 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt,
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
*/
-void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
+void atl1e_check_options(struct atl1e_adapter *adapter)
{
int bd = adapter->bd_number;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 7bae2ad7a7c0..71b3d7daa21d 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -113,7 +113,7 @@ static const struct ethtool_ops atl1_ethtool_ops;
*
* Default Value: 100 (200us)
*/
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
static unsigned int num_int_mod_timer;
module_param_array_named(int_mod_timer, int_mod_timer, int,
&num_int_mod_timer, 0);
@@ -143,8 +143,8 @@ struct atl1_option {
} arg;
};
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
- struct pci_dev *pdev)
+static int atl1_validate_option(int *value, struct atl1_option *opt,
+ struct pci_dev *pdev)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -204,7 +204,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
*/
-static void __devinit atl1_check_options(struct atl1_adapter *adapter)
+static void atl1_check_options(struct atl1_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
int bd = adapter->bd_number;
@@ -945,7 +945,7 @@ static void atl1_set_mac_addr(struct atl1_hw *hw)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
*/
-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+static int atl1_sw_init(struct atl1_adapter *adapter)
{
struct atl1_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
@@ -2934,8 +2934,7 @@ static const struct net_device_ops atl1_netdev_ops = {
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
*/
-static int __devinit atl1_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl1_adapter *adapter;
@@ -3113,7 +3112,7 @@ err_request_regions:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
*/
-static void __devexit atl1_remove(struct pci_dev *pdev)
+static void atl1_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct atl1_adapter *adapter;
@@ -3146,7 +3145,7 @@ static struct pci_driver atl1_driver = {
.name = ATLX_DRIVER_NAME,
.id_table = atl1_pci_tbl,
.probe = atl1_probe,
- .remove = __devexit_p(atl1_remove),
+ .remove = atl1_remove,
.shutdown = atl1_shutdown,
.driver.pm = ATL1_PM_OPS,
};
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 623dd8635c46..aab83a2d4e07 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -83,7 +83,7 @@ static void atl2_check_options(struct atl2_adapter *adapter);
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
*/
-static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
+static int atl2_sw_init(struct atl2_adapter *adapter)
{
struct atl2_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -1338,8 +1338,7 @@ static const struct net_device_ops atl2_netdev_ops = {
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
*/
-static int __devinit atl2_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl2_adapter *adapter;
@@ -1498,7 +1497,7 @@ err_dma:
*/
/* FIXME: write the original MAC address back in case it was changed from a
* BIOS-set value, as in atl1 -- CHS */
-static void __devexit atl2_remove(struct pci_dev *pdev)
+static void atl2_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct atl2_adapter *adapter = netdev_priv(netdev);
@@ -1705,7 +1704,7 @@ static struct pci_driver atl2_driver = {
.name = atl2_driver_name,
.id_table = atl2_pci_tbl,
.probe = atl2_probe,
- .remove = __devexit_p(atl2_remove),
+ .remove = atl2_remove,
/* Power Management Hooks */
.suspend = atl2_suspend,
#ifdef CONFIG_PM
@@ -2845,12 +2844,12 @@ static void atl2_force_ps(struct atl2_hw *hw)
*/
#define ATL2_PARAM(X, desc) \
- static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
+ static const int X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
MODULE_PARM_DESC(X, desc);
#else
#define ATL2_PARAM(X, desc) \
- static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
+ static int X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
static unsigned int num_##X; \
module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
@@ -2934,7 +2933,7 @@ struct atl2_option {
} arg;
};
-static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
+static int atl2_validate_option(int *value, struct atl2_option *opt)
{
int i;
struct atl2_opt_list *ent;
@@ -2992,7 +2991,7 @@ static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
*/
-static void __devinit atl2_check_options(struct atl2_adapter *adapter)
+static void atl2_check_options(struct atl2_adapter *adapter)
{
int val;
struct atl2_option opt;
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 4bd416b72e65..f55267363f35 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -102,6 +102,7 @@ config TIGON3
depends on PCI
select PHYLIB
select HWMON
+ select PTP_1588_CLOCK
---help---
This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 9786c0e9890e..219f6226fcb1 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2083,7 +2083,7 @@ out:
return err;
}
-static int __devinit b44_get_invariants(struct b44 *bp)
+static int b44_get_invariants(struct b44 *bp)
{
struct ssb_device *sdev = bp->sdev;
int err = 0;
@@ -2141,8 +2141,8 @@ static const struct net_device_ops b44_netdev_ops = {
#endif
};
-static int __devinit b44_init_one(struct ssb_device *sdev,
- const struct ssb_device_id *ent)
+static int b44_init_one(struct ssb_device *sdev,
+ const struct ssb_device_id *ent)
{
struct net_device *dev;
struct b44 *bp;
@@ -2249,7 +2249,7 @@ out:
return err;
}
-static void __devexit b44_remove_one(struct ssb_device *sdev)
+static void b44_remove_one(struct ssb_device *sdev)
{
struct net_device *dev = ssb_get_drvdata(sdev);
@@ -2340,7 +2340,7 @@ static struct ssb_driver b44_ssb_driver = {
.name = DRV_MODULE_NAME,
.id_table = b44_ssb_tbl,
.probe = b44_init_one,
- .remove = __devexit_p(b44_remove_one),
+ .remove = b44_remove_one,
.suspend = b44_suspend,
.resume = b44_resume,
};
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index c7ca7ec065ee..39387d67b722 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1612,7 +1612,7 @@ static const struct net_device_ops bcm_enet_ops = {
/*
* allocate netdevice, request register memory and register device.
*/
-static int __devinit bcm_enet_probe(struct platform_device *pdev)
+static int bcm_enet_probe(struct platform_device *pdev)
{
struct bcm_enet_priv *priv;
struct net_device *dev;
@@ -1830,7 +1830,7 @@ out:
/*
* exit func, stops hardware and unregisters netdevice
*/
-static int __devexit bcm_enet_remove(struct platform_device *pdev)
+static int bcm_enet_remove(struct platform_device *pdev)
{
struct bcm_enet_priv *priv;
struct net_device *dev;
@@ -1877,7 +1877,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
struct platform_driver bcm63xx_enet_driver = {
.probe = bcm_enet_probe,
- .remove = __devexit_p(bcm_enet_remove),
+ .remove = bcm_enet_remove,
.driver = {
.name = "bcm63xx_enet",
.owner = THIS_MODULE,
@@ -1887,7 +1887,7 @@ struct platform_driver bcm63xx_enet_driver = {
/*
* reserve & remap memory space shared between all macs
*/
-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
+static int bcm_enet_shared_probe(struct platform_device *pdev)
{
struct resource *res;
unsigned int iomem_size;
@@ -1908,7 +1908,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
+static int bcm_enet_shared_remove(struct platform_device *pdev)
{
struct resource *res;
@@ -1924,7 +1924,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
*/
struct platform_driver bcm63xx_enet_shared_driver = {
.probe = bcm_enet_shared_probe,
- .remove = __devexit_p(bcm_enet_shared_remove),
+ .remove = bcm_enet_shared_remove,
.driver = {
.name = "bcm63xx_enet_shared",
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index d4310700c7a7..a1adfaf87f49 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -71,7 +71,7 @@
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (5*HZ)
-static char version[] __devinitdata =
+static char version[] =
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
@@ -106,7 +106,7 @@ typedef enum {
/* indexed by board_t, above */
static struct {
char *name;
-} board_info[] __devinitdata = {
+} board_info[] = {
{ "Broadcom NetXtreme II BCM5706 1000Base-T" },
{ "HP NC370T Multifunction Gigabit Server Adapter" },
{ "HP NC370i Multifunction Gigabit Server Adapter" },
@@ -260,10 +260,10 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
* needs to be skipped.
*/
diff = txr->tx_prod - txr->tx_cons;
- if (unlikely(diff >= TX_DESC_CNT)) {
+ if (unlikely(diff >= BNX2_TX_DESC_CNT)) {
diff &= 0xffff;
- if (diff == TX_DESC_CNT)
- diff = MAX_TX_DESC_CNT;
+ if (diff == BNX2_TX_DESC_CNT)
+ diff = BNX2_MAX_TX_DESC_CNT;
}
return bp->tx_ring_size - diff;
}
@@ -274,8 +274,8 @@ bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
u32 val;
spin_lock_bh(&bp->indirect_lock);
- REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
- val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
+ BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW);
spin_unlock_bh(&bp->indirect_lock);
return val;
}
@@ -284,8 +284,8 @@ static void
bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
{
spin_lock_bh(&bp->indirect_lock);
- REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
- REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+ BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
spin_unlock_bh(&bp->indirect_lock);
}
@@ -306,21 +306,21 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
{
offset += cid_addr;
spin_lock_bh(&bp->indirect_lock);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
int i;
- REG_WR(bp, BNX2_CTX_CTX_DATA, val);
- REG_WR(bp, BNX2_CTX_CTX_CTRL,
- offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
+ BNX2_WR(bp, BNX2_CTX_CTX_DATA, val);
+ BNX2_WR(bp, BNX2_CTX_CTX_CTRL,
+ offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
for (i = 0; i < 5; i++) {
- val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
+ val = BNX2_RD(bp, BNX2_CTX_CTX_CTRL);
if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
break;
udelay(5);
}
} else {
- REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
- REG_WR(bp, BNX2_CTX_DATA, val);
+ BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset);
+ BNX2_WR(bp, BNX2_CTX_DATA, val);
}
spin_unlock_bh(&bp->indirect_lock);
}
@@ -434,7 +434,6 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
return cp;
}
-EXPORT_SYMBOL(bnx2_cnic_probe);
static void
bnx2_cnic_stop(struct bnx2 *bp)
@@ -494,11 +493,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
int i, ret;
if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
- REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
- REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
udelay(40);
}
@@ -506,16 +505,16 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
val1 = (bp->phy_addr << 21) | (reg << 16) |
BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
BNX2_EMAC_MDIO_COMM_START_BUSY;
- REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
for (i = 0; i < 50; i++) {
udelay(10);
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
udelay(5);
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
val1 &= BNX2_EMAC_MDIO_COMM_DATA;
break;
@@ -532,11 +531,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
}
if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
- REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
- REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
udelay(40);
}
@@ -551,11 +550,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
int i, ret;
if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
- REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
- REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
udelay(40);
}
@@ -563,12 +562,12 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
val1 = (bp->phy_addr << 21) | (reg << 16) | val |
BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
- REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
for (i = 0; i < 50; i++) {
udelay(10);
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
udelay(5);
break;
@@ -581,11 +580,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
ret = 0;
if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
- val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
- REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
- REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
udelay(40);
}
@@ -601,10 +600,10 @@ bnx2_disable_int(struct bnx2 *bp)
for (i = 0; i < bp->irq_nvecs; i++) {
bnapi = &bp->bnx2_napi[i];
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
}
- REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+ BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
}
static void
@@ -616,16 +615,16 @@ bnx2_enable_int(struct bnx2 *bp)
for (i = 0; i < bp->irq_nvecs; i++) {
bnapi = &bp->bnx2_napi[i];
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
- bnapi->last_status_idx);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bnapi->last_status_idx);
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bnapi->last_status_idx);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bnapi->last_status_idx);
}
- REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
+ BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
}
static void
@@ -824,7 +823,7 @@ bnx2_free_mem(struct bnx2 *bp)
for (i = 0; i < bp->ctx_pages; i++) {
if (bp->ctx_blk[i]) {
- dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE,
+ dma_free_coherent(&bp->pdev->dev, BNX2_PAGE_SIZE,
bp->ctx_blk[i],
bp->ctx_blk_mapping[i]);
bp->ctx_blk[i] = NULL;
@@ -887,13 +886,13 @@ bnx2_alloc_mem(struct bnx2 *bp)
bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+ bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE;
if (bp->ctx_pages == 0)
bp->ctx_pages = 1;
for (i = 0; i < bp->ctx_pages; i++) {
bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev,
- BCM_PAGE_SIZE,
+ BNX2_PAGE_SIZE,
&bp->ctx_blk_mapping[i],
GFP_KERNEL);
if (bp->ctx_blk[i] == NULL)
@@ -1034,7 +1033,7 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp)
}
if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
- (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+ (BNX2_CHIP(bp) == BNX2_CHIP_5708)) {
u32 val;
bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
@@ -1294,14 +1293,14 @@ bnx2_set_mac_link(struct bnx2 *bp)
{
u32 val;
- REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
+ BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
if (bp->link_up && (bp->line_speed == SPEED_1000) &&
(bp->duplex == DUPLEX_HALF)) {
- REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
+ BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
}
/* Configure the EMAC mode register. */
- val = REG_RD(bp, BNX2_EMAC_MODE);
+ val = BNX2_RD(bp, BNX2_EMAC_MODE);
val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
@@ -1310,7 +1309,7 @@ bnx2_set_mac_link(struct bnx2 *bp)
if (bp->link_up) {
switch (bp->line_speed) {
case SPEED_10:
- if (CHIP_NUM(bp) != CHIP_NUM_5706) {
+ if (BNX2_CHIP(bp) != BNX2_CHIP_5706) {
val |= BNX2_EMAC_MODE_PORT_MII_10M;
break;
}
@@ -1333,25 +1332,25 @@ bnx2_set_mac_link(struct bnx2 *bp)
/* Set the MAC to operate in the appropriate duplex mode. */
if (bp->duplex == DUPLEX_HALF)
val |= BNX2_EMAC_MODE_HALF_DUPLEX;
- REG_WR(bp, BNX2_EMAC_MODE, val);
+ BNX2_WR(bp, BNX2_EMAC_MODE, val);
/* Enable/disable rx PAUSE. */
bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
if (bp->flow_ctrl & FLOW_CTRL_RX)
bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
- REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
+ BNX2_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
/* Enable/disable tx PAUSE. */
- val = REG_RD(bp, BNX2_EMAC_TX_MODE);
+ val = BNX2_RD(bp, BNX2_EMAC_TX_MODE);
val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
if (bp->flow_ctrl & FLOW_CTRL_TX)
val |= BNX2_EMAC_TX_MODE_FLOW_EN;
- REG_WR(bp, BNX2_EMAC_TX_MODE, val);
+ BNX2_WR(bp, BNX2_EMAC_TX_MODE, val);
/* Acknowledge the interrupt. */
- REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+ BNX2_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
bnx2_init_all_rx_contexts(bp);
}
@@ -1360,7 +1359,7 @@ static void
bnx2_enable_bmsr1(struct bnx2 *bp)
{
if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
- (CHIP_NUM(bp) == CHIP_NUM_5709))
+ (BNX2_CHIP(bp) == BNX2_CHIP_5709))
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
MII_BNX2_BLK_ADDR_GP_STATUS);
}
@@ -1369,7 +1368,7 @@ static void
bnx2_disable_bmsr1(struct bnx2 *bp)
{
if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
- (CHIP_NUM(bp) == CHIP_NUM_5709))
+ (BNX2_CHIP(bp) == BNX2_CHIP_5709))
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
}
@@ -1386,7 +1385,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp)
if (bp->autoneg & AUTONEG_SPEED)
bp->advertising |= ADVERTISED_2500baseX_Full;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
bnx2_read_phy(bp, bp->mii_up1, &up1);
@@ -1396,7 +1395,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp)
ret = 0;
}
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
@@ -1412,7 +1411,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp)
if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
return 0;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
bnx2_read_phy(bp, bp->mii_up1, &up1);
@@ -1422,7 +1421,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp)
ret = 1;
}
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
@@ -1438,7 +1437,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
return;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
u32 val;
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
@@ -1454,7 +1453,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
- } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
if (!err)
bmcr |= BCM5708S_BMCR_FORCE_2500;
@@ -1482,7 +1481,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp)
if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
return;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
u32 val;
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
@@ -1496,7 +1495,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp)
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
- } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
if (!err)
bmcr &= ~BCM5708S_BMCR_FORCE_2500;
@@ -1547,14 +1546,14 @@ bnx2_set_link(struct bnx2 *bp)
bnx2_disable_bmsr1(bp);
if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
- (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ (BNX2_CHIP(bp) == BNX2_CHIP_5706)) {
u32 val, an_dbg;
if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) {
bnx2_5706s_force_link_dn(bp, 0);
bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN;
}
- val = REG_RD(bp, BNX2_EMAC_STATUS);
+ val = BNX2_RD(bp, BNX2_EMAC_STATUS);
bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
@@ -1571,11 +1570,11 @@ bnx2_set_link(struct bnx2 *bp)
bp->link_up = 1;
if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
- if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
bnx2_5706s_linkup(bp);
- else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ else if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
bnx2_5708s_linkup(bp);
- else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ else if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_5709s_linkup(bp);
}
else {
@@ -1757,7 +1756,7 @@ __acquires(&bp->phy_lock)
new_bmcr = bmcr & ~BMCR_ANENABLE;
new_bmcr |= BMCR_SPEED1000;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
if (bp->req_line_speed == SPEED_2500)
bnx2_enable_forced_2g5(bp);
else if (bp->req_line_speed == SPEED_1000) {
@@ -1765,7 +1764,7 @@ __acquires(&bp->phy_lock)
new_bmcr &= ~0x2000;
}
- } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
if (bp->req_line_speed == SPEED_2500)
new_bmcr |= BCM5708S_BMCR_FORCE_2500;
else
@@ -1942,8 +1941,8 @@ bnx2_send_heart_beat(struct bnx2 *bp)
spin_lock(&bp->indirect_lock);
msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
- REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
- REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
+ BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
+ BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
spin_unlock(&bp->indirect_lock);
}
@@ -2230,9 +2229,9 @@ bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
bnx2_write_phy(bp, BCM5708S_UP1, val);
}
- if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1)) {
/* increase tx signal amplitude */
bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
BCM5708S_BLK_ADDR_TX_MISC);
@@ -2268,8 +2267,8 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
- if (CHIP_NUM(bp) == CHIP_NUM_5706)
- REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
+ BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
if (bp->dev->mtu > 1500) {
u32 val;
@@ -2368,7 +2367,7 @@ __acquires(&bp->phy_lock)
bp->mii_adv = MII_ADVERTISE;
bp->mii_lpa = MII_LPA;
- REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+ BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
goto setup_phy;
@@ -2379,11 +2378,11 @@ __acquires(&bp->phy_lock)
bp->phy_id |= val & 0xffff;
if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
- if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
rc = bnx2_init_5706s_phy(bp, reset_phy);
- else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ else if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
rc = bnx2_init_5708s_phy(bp, reset_phy);
- else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ else if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
rc = bnx2_init_5709s_phy(bp, reset_phy);
}
else {
@@ -2402,10 +2401,10 @@ bnx2_set_mac_loopback(struct bnx2 *bp)
{
u32 mac_mode;
- mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+ mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE);
mac_mode &= ~BNX2_EMAC_MODE_PORT;
mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK;
- REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+ BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode);
bp->link_up = 1;
return 0;
}
@@ -2431,13 +2430,13 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
msleep(100);
}
- mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+ mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE);
mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
BNX2_EMAC_MODE_25G_MODE);
mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
- REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+ BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode);
bp->link_up = 1;
return 0;
}
@@ -2449,7 +2448,7 @@ bnx2_dump_mcp_state(struct bnx2 *bp)
u32 mcp_p0, mcp_p1;
netdev_err(dev, "<--- start MCP states dump --->\n");
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
mcp_p0 = BNX2_MCP_STATE_P0;
mcp_p1 = BNX2_MCP_STATE_P1;
} else {
@@ -2538,10 +2537,10 @@ bnx2_init_5709_context(struct bnx2 *bp)
u32 val;
val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
- val |= (BCM_PAGE_BITS - 8) << 16;
- REG_WR(bp, BNX2_CTX_COMMAND, val);
+ val |= (BNX2_PAGE_BITS - 8) << 16;
+ BNX2_WR(bp, BNX2_CTX_COMMAND, val);
for (i = 0; i < 10; i++) {
- val = REG_RD(bp, BNX2_CTX_COMMAND);
+ val = BNX2_RD(bp, BNX2_CTX_COMMAND);
if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
break;
udelay(2);
@@ -2553,20 +2552,20 @@ bnx2_init_5709_context(struct bnx2 *bp)
int j;
if (bp->ctx_blk[i])
- memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE);
+ memset(bp->ctx_blk[i], 0, BNX2_PAGE_SIZE);
else
return -ENOMEM;
- REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
- (bp->ctx_blk_mapping[i] & 0xffffffff) |
- BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
- REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
- (u64) bp->ctx_blk_mapping[i] >> 32);
- REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
- BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
+ BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
+ (bp->ctx_blk_mapping[i] & 0xffffffff) |
+ BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
+ BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
+ (u64) bp->ctx_blk_mapping[i] >> 32);
+ BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
+ BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
for (j = 0; j < 10; j++) {
- val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
+ val = BNX2_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
break;
udelay(5);
@@ -2591,7 +2590,7 @@ bnx2_init_context(struct bnx2 *bp)
vcid--;
- if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
u32 new_vcid;
vcid_addr = GET_PCID_ADDR(vcid);
@@ -2612,8 +2611,8 @@ bnx2_init_context(struct bnx2 *bp)
vcid_addr += (i << PHY_CTX_SHIFT);
pcid_addr += (i << PHY_CTX_SHIFT);
- REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
- REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ BNX2_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ BNX2_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
/* Zero out the context. */
for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
@@ -2633,7 +2632,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
if (good_mbuf == NULL)
return -ENOMEM;
- REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
good_mbuf_cnt = 0;
@@ -2678,21 +2677,21 @@ bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
val = (mac_addr[0] << 8) | mac_addr[1];
- REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
+ BNX2_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
(mac_addr[4] << 8) | mac_addr[5];
- REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
+ BNX2_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
}
static inline int
bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
{
dma_addr_t mapping;
- struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
- struct rx_bd *rxbd =
- &rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
+ struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index];
+ struct bnx2_rx_bd *rxbd =
+ &rxr->rx_pg_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)];
struct page *page = alloc_page(gfp);
if (!page)
@@ -2714,7 +2713,7 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gf
static void
bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
{
- struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
+ struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index];
struct page *page = rx_pg->page;
if (!page)
@@ -2731,9 +2730,10 @@ static inline int
bnx2_alloc_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
{
u8 *data;
- struct sw_bd *rx_buf = &rxr->rx_buf_ring[index];
+ struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[index];
dma_addr_t mapping;
- struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
+ struct bnx2_rx_bd *rxbd =
+ &rxr->rx_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)];
data = kmalloc(bp->rx_buf_size, gfp);
if (!data)
@@ -2770,9 +2770,9 @@ bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
old_link_state = sblk->status_attn_bits_ack & event;
if (new_link_state != old_link_state) {
if (new_link_state)
- REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
+ BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
else
- REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
+ BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
} else
is_set = 0;
@@ -2802,7 +2802,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
barrier();
cons = *bnapi->hw_tx_cons_ptr;
barrier();
- if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
+ if (unlikely((cons & BNX2_MAX_TX_DESC_CNT) == BNX2_MAX_TX_DESC_CNT))
cons++;
return cons;
}
@@ -2823,11 +2823,11 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
sw_cons = txr->tx_cons;
while (sw_cons != hw_cons) {
- struct sw_tx_bd *tx_buf;
+ struct bnx2_sw_tx_bd *tx_buf;
struct sk_buff *skb;
int i, last;
- sw_ring_cons = TX_RING_IDX(sw_cons);
+ sw_ring_cons = BNX2_TX_RING_IDX(sw_cons);
tx_buf = &txr->tx_buf_ring[sw_ring_cons];
skb = tx_buf->skb;
@@ -2841,7 +2841,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
last_idx = sw_cons + tx_buf->nr_frags + 1;
last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
- if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
+ if (unlikely(last_ring_idx >= BNX2_MAX_TX_DESC_CNT)) {
last_idx++;
}
if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) {
@@ -2856,17 +2856,18 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
last = tx_buf->nr_frags;
for (i = 0; i < last; i++) {
- sw_cons = NEXT_TX_BD(sw_cons);
+ struct bnx2_sw_tx_bd *tx_buf;
+ sw_cons = BNX2_NEXT_TX_BD(sw_cons);
+
+ tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(sw_cons)];
dma_unmap_page(&bp->pdev->dev,
- dma_unmap_addr(
- &txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
- mapping),
+ dma_unmap_addr(tx_buf, mapping),
skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_TODEVICE);
}
- sw_cons = NEXT_TX_BD(sw_cons);
+ sw_cons = BNX2_NEXT_TX_BD(sw_cons);
tx_bytes += skb->len;
dev_kfree_skb(skb);
@@ -2905,8 +2906,8 @@ static void
bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
struct sk_buff *skb, int count)
{
- struct sw_pg *cons_rx_pg, *prod_rx_pg;
- struct rx_bd *cons_bd, *prod_bd;
+ struct bnx2_sw_pg *cons_rx_pg, *prod_rx_pg;
+ struct bnx2_rx_bd *cons_bd, *prod_bd;
int i;
u16 hw_prod, prod;
u16 cons = rxr->rx_pg_cons;
@@ -2933,12 +2934,14 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
hw_prod = rxr->rx_pg_prod;
for (i = 0; i < count; i++) {
- prod = RX_PG_RING_IDX(hw_prod);
+ prod = BNX2_RX_PG_RING_IDX(hw_prod);
prod_rx_pg = &rxr->rx_pg_ring[prod];
cons_rx_pg = &rxr->rx_pg_ring[cons];
- cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
- prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ cons_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(cons)]
+ [BNX2_RX_IDX(cons)];
+ prod_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(prod)]
+ [BNX2_RX_IDX(prod)];
if (prod != cons) {
prod_rx_pg->page = cons_rx_pg->page;
@@ -2950,8 +2953,8 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
}
- cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
- hw_prod = NEXT_RX_BD(hw_prod);
+ cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(cons));
+ hw_prod = BNX2_NEXT_RX_BD(hw_prod);
}
rxr->rx_pg_prod = hw_prod;
rxr->rx_pg_cons = cons;
@@ -2961,8 +2964,8 @@ static inline void
bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
u8 *data, u16 cons, u16 prod)
{
- struct sw_bd *cons_rx_buf, *prod_rx_buf;
- struct rx_bd *cons_bd, *prod_bd;
+ struct bnx2_sw_bd *cons_rx_buf, *prod_rx_buf;
+ struct bnx2_rx_bd *cons_bd, *prod_bd;
cons_rx_buf = &rxr->rx_buf_ring[cons];
prod_rx_buf = &rxr->rx_buf_ring[prod];
@@ -2981,8 +2984,8 @@ bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
dma_unmap_addr_set(prod_rx_buf, mapping,
dma_unmap_addr(cons_rx_buf, mapping));
- cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
- prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ cons_bd = &rxr->rx_desc_ring[BNX2_RX_RING(cons)][BNX2_RX_IDX(cons)];
+ prod_bd = &rxr->rx_desc_ring[BNX2_RX_RING(prod)][BNX2_RX_IDX(prod)];
prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
}
@@ -3022,7 +3025,7 @@ error:
return skb;
} else {
unsigned int i, frag_len, frag_size, pages;
- struct sw_pg *rx_pg;
+ struct bnx2_sw_pg *rx_pg;
u16 pg_cons = rxr->rx_pg_cons;
u16 pg_prod = rxr->rx_pg_prod;
@@ -3065,7 +3068,7 @@ error:
rx_pg->page = NULL;
err = bnx2_alloc_rx_page(bp, rxr,
- RX_PG_RING_IDX(pg_prod),
+ BNX2_RX_PG_RING_IDX(pg_prod),
GFP_ATOMIC);
if (unlikely(err)) {
rxr->rx_pg_cons = pg_cons;
@@ -3083,8 +3086,8 @@ error:
skb->truesize += PAGE_SIZE;
skb->len += frag_len;
- pg_prod = NEXT_RX_BD(pg_prod);
- pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
+ pg_prod = BNX2_NEXT_RX_BD(pg_prod);
+ pg_cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(pg_cons));
}
rxr->rx_pg_prod = pg_prod;
rxr->rx_pg_cons = pg_cons;
@@ -3101,7 +3104,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
barrier();
cons = *bnapi->hw_rx_cons_ptr;
barrier();
- if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
+ if (unlikely((cons & BNX2_MAX_RX_DESC_CNT) == BNX2_MAX_RX_DESC_CNT))
cons++;
return cons;
}
@@ -3125,13 +3128,14 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
while (sw_cons != hw_cons) {
unsigned int len, hdr_len;
u32 status;
- struct sw_bd *rx_buf, *next_rx_buf;
+ struct bnx2_sw_bd *rx_buf, *next_rx_buf;
struct sk_buff *skb;
dma_addr_t dma_addr;
u8 *data;
+ u16 next_ring_idx;
- sw_ring_cons = RX_RING_IDX(sw_cons);
- sw_ring_prod = RX_RING_IDX(sw_prod);
+ sw_ring_cons = BNX2_RX_RING_IDX(sw_cons);
+ sw_ring_prod = BNX2_RX_RING_IDX(sw_prod);
rx_buf = &rxr->rx_buf_ring[sw_ring_cons];
data = rx_buf->data;
@@ -3146,8 +3150,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
PCI_DMA_FROMDEVICE);
- next_rx_buf =
- &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+ next_ring_idx = BNX2_RX_RING_IDX(BNX2_NEXT_RX_BD(sw_cons));
+ next_rx_buf = &rxr->rx_buf_ring[next_ring_idx];
prefetch(get_l2_fhdr(next_rx_buf->data));
len = rx_hdr->l2_fhdr_pkt_len;
@@ -3239,8 +3243,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
rx_pkt++;
next_rx:
- sw_cons = NEXT_RX_BD(sw_cons);
- sw_prod = NEXT_RX_BD(sw_prod);
+ sw_cons = BNX2_NEXT_RX_BD(sw_cons);
+ sw_prod = BNX2_NEXT_RX_BD(sw_prod);
if ((rx_pkt == budget))
break;
@@ -3255,11 +3259,11 @@ next_rx:
rxr->rx_prod = sw_prod;
if (pg_ring_used)
- REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
+ BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
- REG_WR16(bp, rxr->rx_bidx_addr, sw_prod);
+ BNX2_WR16(bp, rxr->rx_bidx_addr, sw_prod);
- REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
+ BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
mmiowb();
@@ -3277,7 +3281,7 @@ bnx2_msi(int irq, void *dev_instance)
struct bnx2 *bp = bnapi->bp;
prefetch(bnapi->status_blk.msi);
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
@@ -3321,18 +3325,18 @@ bnx2_interrupt(int irq, void *dev_instance)
* the status block write.
*/
if ((sblk->status_idx == bnapi->last_status_idx) &&
- (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
+ (BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS) &
BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
return IRQ_NONE;
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
/* Read back to deassert IRQ immediately to avoid too many
* spurious interrupts.
*/
- REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+ BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
/* Return here if interrupt is shared and is disabled. */
if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3388,14 +3392,14 @@ bnx2_chk_missed_msi(struct bnx2 *bp)
u32 msi_ctrl;
if (bnx2_has_work(bnapi)) {
- msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL);
+ msi_ctrl = BNX2_RD(bp, BNX2_PCICFG_MSI_CONTROL);
if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE))
return;
if (bnapi->last_status_idx == bp->idle_chk_status_idx) {
- REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
- ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
- REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
+ BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
+ ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
+ BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
bnx2_msi(bp->irq_tbl[0].vector, bnapi);
}
}
@@ -3434,9 +3438,9 @@ static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
/* This is needed to take care of transient status
* during link changes.
*/
- REG_WR(bp, BNX2_HC_COMMAND,
- bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
- REG_RD(bp, BNX2_HC_COMMAND);
+ BNX2_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ BNX2_RD(bp, BNX2_HC_COMMAND);
}
}
@@ -3473,9 +3477,9 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget)
if (likely(!bnx2_has_fast_work(bnapi))) {
napi_complete(napi);
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bnapi->last_status_idx);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bnapi->last_status_idx);
break;
}
}
@@ -3511,19 +3515,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
if (likely(!bnx2_has_work(bnapi))) {
napi_complete(napi);
if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bnapi->last_status_idx);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bnapi->last_status_idx);
break;
}
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
- bnapi->last_status_idx);
-
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bnapi->last_status_idx);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bnapi->last_status_idx);
+
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bnapi->last_status_idx);
break;
}
}
@@ -3561,8 +3565,8 @@ bnx2_set_rx_mode(struct net_device *dev)
}
else if (dev->flags & IFF_ALLMULTI) {
for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
- REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
- 0xffffffff);
+ BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
}
sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
}
@@ -3584,8 +3588,8 @@ bnx2_set_rx_mode(struct net_device *dev)
}
for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
- REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
- mc_filter[i]);
+ BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ mc_filter[i]);
}
sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
@@ -3610,12 +3614,12 @@ bnx2_set_rx_mode(struct net_device *dev)
if (rx_mode != bp->rx_mode) {
bp->rx_mode = rx_mode;
- REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
+ BNX2_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
}
- REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
- REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
- REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
spin_unlock_bh(&bp->phy_lock);
}
@@ -3663,10 +3667,10 @@ static int bnx2_request_uncached_firmware(struct bnx2 *bp)
const struct bnx2_rv2p_fw_file *rv2p_fw;
int rc;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
mips_fw_file = FW_MIPS_FILE_09;
- if ((CHIP_ID(bp) == CHIP_ID_5709_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5709_A1))
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A1))
rv2p_fw_file = FW_RV2P_FILE_09_Ax;
else
rv2p_fw_file = FW_RV2P_FILE_09;
@@ -3756,13 +3760,13 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
}
for (i = 0; i < rv2p_code_len; i += 8) {
- REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
+ BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
rv2p_code++;
- REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
+ BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
rv2p_code++;
val = (i / 8) | cmd;
- REG_WR(bp, addr, val);
+ BNX2_WR(bp, addr, val);
}
rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
@@ -3772,22 +3776,22 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
loc = be32_to_cpu(fw_entry->fixup[i]);
if (loc && ((loc * 4) < rv2p_code_len)) {
code = be32_to_cpu(*(rv2p_code + loc - 1));
- REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
+ BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
code = be32_to_cpu(*(rv2p_code + loc));
code = rv2p_fw_fixup(rv2p_proc, i, loc, code);
- REG_WR(bp, BNX2_RV2P_INSTR_LOW, code);
+ BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, code);
val = (loc / 2) | cmd;
- REG_WR(bp, addr, val);
+ BNX2_WR(bp, addr, val);
}
}
/* Reset the processor, un-stall is done later. */
if (rv2p_proc == RV2P_PROC1) {
- REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
+ BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
}
else {
- REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
+ BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
}
return 0;
@@ -3924,14 +3928,14 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
/* delay required during transition out of D3hot */
msleep(20);
- val = REG_RD(bp, BNX2_EMAC_MODE);
+ val = BNX2_RD(bp, BNX2_EMAC_MODE);
val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
val &= ~BNX2_EMAC_MODE_MPKT;
- REG_WR(bp, BNX2_EMAC_MODE, val);
+ BNX2_WR(bp, BNX2_EMAC_MODE, val);
- val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val = BNX2_RD(bp, BNX2_RPM_CONFIG);
val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
- REG_WR(bp, BNX2_RPM_CONFIG, val);
+ BNX2_WR(bp, BNX2_RPM_CONFIG, val);
break;
}
case PCI_D3hot: {
@@ -3963,7 +3967,7 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
- val = REG_RD(bp, BNX2_EMAC_MODE);
+ val = BNX2_RD(bp, BNX2_EMAC_MODE);
/* Enable port mode. */
val &= ~BNX2_EMAC_MODE_PORT;
@@ -3978,32 +3982,32 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
val |= BNX2_EMAC_MODE_25G_MODE;
}
- REG_WR(bp, BNX2_EMAC_MODE, val);
+ BNX2_WR(bp, BNX2_EMAC_MODE, val);
/* receive all multicast */
for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
- REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
- 0xffffffff);
+ BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
}
- REG_WR(bp, BNX2_EMAC_RX_MODE,
- BNX2_EMAC_RX_MODE_SORT_MODE);
+ BNX2_WR(bp, BNX2_EMAC_RX_MODE,
+ BNX2_EMAC_RX_MODE_SORT_MODE);
val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
BNX2_RPM_SORT_USER0_MC_EN;
- REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
- REG_WR(bp, BNX2_RPM_SORT_USER0, val);
- REG_WR(bp, BNX2_RPM_SORT_USER0, val |
- BNX2_RPM_SORT_USER0_ENA);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, val);
+ BNX2_WR(bp, BNX2_RPM_SORT_USER0, val |
+ BNX2_RPM_SORT_USER0_ENA);
/* Need to enable EMAC and RPM for WOL. */
- REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
- BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
- BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
- BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
+ BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
+ BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
+ BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
- val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val = BNX2_RD(bp, BNX2_RPM_CONFIG);
val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
- REG_WR(bp, BNX2_RPM_CONFIG, val);
+ BNX2_WR(bp, BNX2_RPM_CONFIG, val);
wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
}
@@ -4016,8 +4020,8 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
1, 0);
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
- if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)) {
if (bp->wol)
pmcsr |= 3;
@@ -4050,9 +4054,9 @@ bnx2_acquire_nvram_lock(struct bnx2 *bp)
int j;
/* Request access to the flash interface. */
- REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
+ BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
- val = REG_RD(bp, BNX2_NVM_SW_ARB);
+ val = BNX2_RD(bp, BNX2_NVM_SW_ARB);
if (val & BNX2_NVM_SW_ARB_ARB_ARB2)
break;
@@ -4072,10 +4076,10 @@ bnx2_release_nvram_lock(struct bnx2 *bp)
u32 val;
/* Relinquish nvram interface. */
- REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
+ BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
- val = REG_RD(bp, BNX2_NVM_SW_ARB);
+ val = BNX2_RD(bp, BNX2_NVM_SW_ARB);
if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2))
break;
@@ -4094,20 +4098,20 @@ bnx2_enable_nvram_write(struct bnx2 *bp)
{
u32 val;
- val = REG_RD(bp, BNX2_MISC_CFG);
- REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
+ val = BNX2_RD(bp, BNX2_MISC_CFG);
+ BNX2_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
if (bp->flash_info->flags & BNX2_NV_WREN) {
int j;
- REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
- REG_WR(bp, BNX2_NVM_COMMAND,
- BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+ BNX2_WR(bp, BNX2_NVM_COMMAND,
+ BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
udelay(5);
- val = REG_RD(bp, BNX2_NVM_COMMAND);
+ val = BNX2_RD(bp, BNX2_NVM_COMMAND);
if (val & BNX2_NVM_COMMAND_DONE)
break;
}
@@ -4123,8 +4127,8 @@ bnx2_disable_nvram_write(struct bnx2 *bp)
{
u32 val;
- val = REG_RD(bp, BNX2_MISC_CFG);
- REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
+ val = BNX2_RD(bp, BNX2_MISC_CFG);
+ BNX2_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
}
@@ -4133,10 +4137,10 @@ bnx2_enable_nvram_access(struct bnx2 *bp)
{
u32 val;
- val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE);
/* Enable both bits, even on read. */
- REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
- val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
+ BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
}
static void
@@ -4144,9 +4148,9 @@ bnx2_disable_nvram_access(struct bnx2 *bp)
{
u32 val;
- val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE);
/* Disable both bits, even after read. */
- REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE,
val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
BNX2_NVM_ACCESS_ENABLE_WR_EN));
}
@@ -4166,13 +4170,13 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
BNX2_NVM_COMMAND_DOIT;
/* Need to clear DONE bit separately. */
- REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
/* Address of the NVRAM to read from. */
- REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+ BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
/* Issue an erase command. */
- REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
/* Wait for completion. */
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
@@ -4180,7 +4184,7 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
udelay(5);
- val = REG_RD(bp, BNX2_NVM_COMMAND);
+ val = BNX2_RD(bp, BNX2_NVM_COMMAND);
if (val & BNX2_NVM_COMMAND_DONE)
break;
}
@@ -4208,13 +4212,13 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
}
/* Need to clear DONE bit separately. */
- REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
/* Address of the NVRAM to read from. */
- REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+ BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
/* Issue a read command. */
- REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
/* Wait for completion. */
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
@@ -4222,9 +4226,9 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
udelay(5);
- val = REG_RD(bp, BNX2_NVM_COMMAND);
+ val = BNX2_RD(bp, BNX2_NVM_COMMAND);
if (val & BNX2_NVM_COMMAND_DONE) {
- __be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ));
+ __be32 v = cpu_to_be32(BNX2_RD(bp, BNX2_NVM_READ));
memcpy(ret_val, &v, 4);
break;
}
@@ -4254,24 +4258,24 @@ bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags)
}
/* Need to clear DONE bit separately. */
- REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
memcpy(&val32, val, 4);
/* Write the data. */
- REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
+ BNX2_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
/* Address of the NVRAM to write to. */
- REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+ BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
/* Issue the write command. */
- REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+ BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
/* Wait for completion. */
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
udelay(5);
- if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
+ if (BNX2_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
break;
}
if (j >= NVRAM_TIMEOUT_COUNT)
@@ -4287,13 +4291,13 @@ bnx2_init_nvram(struct bnx2 *bp)
int j, entry_count, rc = 0;
const struct flash_spec *flash;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
bp->flash_info = &flash_5709;
goto get_flash_size;
}
/* Determine the selected interface. */
- val = REG_RD(bp, BNX2_NVM_CFG1);
+ val = BNX2_RD(bp, BNX2_NVM_CFG1);
entry_count = ARRAY_SIZE(flash_table);
@@ -4332,10 +4336,10 @@ bnx2_init_nvram(struct bnx2 *bp)
bnx2_enable_nvram_access(bp);
/* Reconfigure the flash interface */
- REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
- REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
- REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
- REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
+ BNX2_WR(bp, BNX2_NVM_CFG1, flash->config1);
+ BNX2_WR(bp, BNX2_NVM_CFG2, flash->config2);
+ BNX2_WR(bp, BNX2_NVM_CFG3, flash->config3);
+ BNX2_WR(bp, BNX2_NVM_WRITE1, flash->write1);
/* Disable access to flash interface */
bnx2_disable_nvram_access(bp);
@@ -4696,10 +4700,10 @@ bnx2_init_fw_cap(struct bnx2 *bp)
static void
bnx2_setup_msix_tbl(struct bnx2 *bp)
{
- REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
+ BNX2_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
- REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
- REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
+ BNX2_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
+ BNX2_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
}
static int
@@ -4711,24 +4715,24 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
/* Wait for the current PCI transaction to complete before
* issuing a reset. */
- if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
- (CHIP_NUM(bp) == CHIP_NUM_5708)) {
- REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
- BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
- BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
- BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
- BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
- val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+ if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) ||
+ (BNX2_CHIP(bp) == BNX2_CHIP_5708)) {
+ BNX2_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+ BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+ val = BNX2_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
udelay(5);
} else { /* 5709 */
- val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+ val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
- REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
- val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+ BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+ val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
for (i = 0; i < 100; i++) {
msleep(1);
- val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
+ val = BNX2_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
break;
}
@@ -4744,17 +4748,17 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
/* Do a dummy read to force the chip to complete all current transaction
* before we issue a reset. */
- val = REG_RD(bp, BNX2_MISC_ID);
+ val = BNX2_RD(bp, BNX2_MISC_ID);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
- REG_RD(bp, BNX2_MISC_COMMAND);
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+ BNX2_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
+ BNX2_RD(bp, BNX2_MISC_COMMAND);
udelay(5);
val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
- REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+ BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
} else {
val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
@@ -4762,19 +4766,19 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
/* Chip reset. */
- REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+ BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
/* Reading back any register after chip reset will hang the
* bus on 5706 A0 and A1. The msleep below provides plenty
* of margin for write posting.
*/
- if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A1))
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1))
msleep(20);
/* Reset takes approximate 30 usec */
for (i = 0; i < 10; i++) {
- val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+ val = BNX2_RD(bp, BNX2_PCICFG_MISC_CONFIG);
if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
break;
@@ -4789,7 +4793,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
}
/* Make sure byte swapping is properly configured. */
- val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
+ val = BNX2_RD(bp, BNX2_PCI_SWAP_DIAG0);
if (val != 0x01020304) {
pr_err("Chip not in correct endian mode\n");
return -ENODEV;
@@ -4808,10 +4812,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
bnx2_set_default_remote_link(bp);
spin_unlock_bh(&bp->phy_lock);
- if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
/* Adjust the voltage regular to two steps lower. The default
* of this register is 0x0000000e. */
- REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
+ BNX2_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
/* Remove bad rbuf memory from the free pool. */
rc = bnx2_alloc_bad_rbuf(bp);
@@ -4820,7 +4824,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
if (bp->flags & BNX2_FLAG_USING_MSIX) {
bnx2_setup_msix_tbl(bp);
/* Prevent MSIX table reads and write from timing out */
- REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
+ BNX2_WR(bp, BNX2_MISC_ECO_HW_CTL,
BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
}
@@ -4834,7 +4838,7 @@ bnx2_init_chip(struct bnx2 *bp)
int rc, i;
/* Make sure the interrupt is not active. */
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+ BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
BNX2_DMA_CONFIG_DATA_WORD_SWAP |
@@ -4850,16 +4854,17 @@ bnx2_init_chip(struct bnx2 *bp)
if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133))
val |= (1 << 23);
- if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
- (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX))
+ if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) &&
+ (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0) &&
+ !(bp->flags & BNX2_FLAG_PCIX))
val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
- REG_WR(bp, BNX2_DMA_CONFIG, val);
+ BNX2_WR(bp, BNX2_DMA_CONFIG, val);
- if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
- val = REG_RD(bp, BNX2_TDMA_CONFIG);
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
+ val = BNX2_RD(bp, BNX2_TDMA_CONFIG);
val |= BNX2_TDMA_CONFIG_ONE_DMA;
- REG_WR(bp, BNX2_TDMA_CONFIG, val);
+ BNX2_WR(bp, BNX2_TDMA_CONFIG, val);
}
if (bp->flags & BNX2_FLAG_PCIX) {
@@ -4871,14 +4876,14 @@ bnx2_init_chip(struct bnx2 *bp)
val16 & ~PCI_X_CMD_ERO);
}
- REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
- BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
- BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
- BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
+ BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
/* Initialize context mapping and zero out the quick contexts. The
* context block must have already been enabled. */
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
rc = bnx2_init_5709_context(bp);
if (rc)
return rc;
@@ -4892,29 +4897,29 @@ bnx2_init_chip(struct bnx2 *bp)
bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
- val = REG_RD(bp, BNX2_MQ_CONFIG);
+ val = BNX2_RD(bp, BNX2_MQ_CONFIG);
val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
- if (CHIP_REV(bp) == CHIP_REV_Ax)
+ if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax)
val |= BNX2_MQ_CONFIG_HALT_DIS;
}
- REG_WR(bp, BNX2_MQ_CONFIG, val);
+ BNX2_WR(bp, BNX2_MQ_CONFIG, val);
val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
- REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
- REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
+ BNX2_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
+ BNX2_WR(bp, BNX2_MQ_KNL_WIND_END, val);
- val = (BCM_PAGE_BITS - 8) << 24;
- REG_WR(bp, BNX2_RV2P_CONFIG, val);
+ val = (BNX2_PAGE_BITS - 8) << 24;
+ BNX2_WR(bp, BNX2_RV2P_CONFIG, val);
/* Configure page size. */
- val = REG_RD(bp, BNX2_TBDR_CONFIG);
+ val = BNX2_RD(bp, BNX2_TBDR_CONFIG);
val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
- val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
- REG_WR(bp, BNX2_TBDR_CONFIG, val);
+ val |= (BNX2_PAGE_BITS - 8) << 24 | 0x40;
+ BNX2_WR(bp, BNX2_TBDR_CONFIG, val);
val = bp->mac_addr[0] +
(bp->mac_addr[1] << 8) +
@@ -4922,14 +4927,14 @@ bnx2_init_chip(struct bnx2 *bp)
bp->mac_addr[3] +
(bp->mac_addr[4] << 8) +
(bp->mac_addr[5] << 16);
- REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
+ BNX2_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
/* Program the MTU. Also include 4 bytes for CRC32. */
mtu = bp->dev->mtu;
val = mtu + ETH_HLEN + ETH_FCS_LEN;
if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
- REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+ BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
if (mtu < 1500)
mtu = 1500;
@@ -4947,43 +4952,43 @@ bnx2_init_chip(struct bnx2 *bp)
bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
/* Set up how to generate a link change interrupt. */
- REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+ BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
- REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
- (u64) bp->status_blk_mapping & 0xffffffff);
- REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
+ BNX2_WR(bp, BNX2_HC_STATUS_ADDR_L,
+ (u64) bp->status_blk_mapping & 0xffffffff);
+ BNX2_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
- REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
- (u64) bp->stats_blk_mapping & 0xffffffff);
- REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
- (u64) bp->stats_blk_mapping >> 32);
+ BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
+ (u64) bp->stats_blk_mapping & 0xffffffff);
+ BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
+ (u64) bp->stats_blk_mapping >> 32);
- REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
- (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
+ BNX2_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
+ (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
- REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
- (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
+ BNX2_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
+ (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
- REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
- (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
+ BNX2_WR(bp, BNX2_HC_COMP_PROD_TRIP,
+ (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
- REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
+ BNX2_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
- REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
+ BNX2_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
- REG_WR(bp, BNX2_HC_COM_TICKS,
- (bp->com_ticks_int << 16) | bp->com_ticks);
+ BNX2_WR(bp, BNX2_HC_COM_TICKS,
+ (bp->com_ticks_int << 16) | bp->com_ticks);
- REG_WR(bp, BNX2_HC_CMD_TICKS,
- (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
+ BNX2_WR(bp, BNX2_HC_CMD_TICKS,
+ (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
if (bp->flags & BNX2_FLAG_BROKEN_STATS)
- REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
+ BNX2_WR(bp, BNX2_HC_STATS_TICKS, 0);
else
- REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
- REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
+ BNX2_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
+ BNX2_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
- if (CHIP_ID(bp) == CHIP_ID_5706_A1)
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)
val = BNX2_HC_CONFIG_COLLECT_STATS;
else {
val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
@@ -4991,8 +4996,8 @@ bnx2_init_chip(struct bnx2 *bp)
}
if (bp->flags & BNX2_FLAG_USING_MSIX) {
- REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
- BNX2_HC_MSIX_BIT_VECTOR_VAL);
+ BNX2_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
+ BNX2_HC_MSIX_BIT_VECTOR_VAL);
val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
}
@@ -5000,7 +5005,7 @@ bnx2_init_chip(struct bnx2 *bp)
if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM;
- REG_WR(bp, BNX2_HC_CONFIG, val);
+ BNX2_WR(bp, BNX2_HC_CONFIG, val);
if (bp->rx_ticks < 25)
bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
@@ -5011,48 +5016,48 @@ bnx2_init_chip(struct bnx2 *bp)
u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
BNX2_HC_SB_CONFIG_1;
- REG_WR(bp, base,
+ BNX2_WR(bp, base,
BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
BNX2_HC_SB_CONFIG_1_RX_TMR_MODE |
BNX2_HC_SB_CONFIG_1_ONE_SHOT);
- REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
+ BNX2_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
(bp->tx_quick_cons_trip_int << 16) |
bp->tx_quick_cons_trip);
- REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
+ BNX2_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
(bp->tx_ticks_int << 16) | bp->tx_ticks);
- REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
- (bp->rx_quick_cons_trip_int << 16) |
+ BNX2_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
+ (bp->rx_quick_cons_trip_int << 16) |
bp->rx_quick_cons_trip);
- REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
+ BNX2_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
(bp->rx_ticks_int << 16) | bp->rx_ticks);
}
/* Clear internal stats counters. */
- REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
+ BNX2_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
- REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
+ BNX2_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
/* Initialize the receive filter. */
bnx2_set_rx_mode(bp->dev);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+ val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
- REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+ BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
}
rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
1, 0);
- REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
- REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
+ BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
+ BNX2_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
udelay(20);
- bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+ bp->hc_cmd = BNX2_RD(bp, BNX2_HC_COMMAND);
return rc;
}
@@ -5086,7 +5091,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
u32 val, offset0, offset1, offset2, offset3;
u32 cid_addr = GET_CID_ADDR(cid);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
offset0 = BNX2_L2CTX_TYPE_XI;
offset1 = BNX2_L2CTX_CMD_TYPE_XI;
offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
@@ -5113,7 +5118,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
static void
bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
{
- struct tx_bd *txbd;
+ struct bnx2_tx_bd *txbd;
u32 cid = TX_CID;
struct bnx2_napi *bnapi;
struct bnx2_tx_ring_info *txr;
@@ -5128,7 +5133,7 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
bp->tx_wake_thresh = bp->tx_ring_size / 2;
- txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT];
+ txbd = &txr->tx_desc_ring[BNX2_MAX_TX_DESC_CNT];
txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32;
txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff;
@@ -5143,17 +5148,17 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
}
static void
-bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
- int num_rings)
+bnx2_init_rxbd_rings(struct bnx2_rx_bd *rx_ring[], dma_addr_t dma[],
+ u32 buf_size, int num_rings)
{
int i;
- struct rx_bd *rxbd;
+ struct bnx2_rx_bd *rxbd;
for (i = 0; i < num_rings; i++) {
int j;
rxbd = &rx_ring[i][0];
- for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
+ for (j = 0; j < BNX2_MAX_RX_DESC_CNT; j++, rxbd++) {
rxbd->rx_bd_len = buf_size;
rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
}
@@ -5187,9 +5192,9 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
bnx2_init_rx_context(bp, cid);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
- REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+ val = BNX2_RD(bp, BNX2_MQ_MAP_L2_5);
+ BNX2_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
}
bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
@@ -5208,8 +5213,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff;
bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
+ BNX2_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
}
val = (u64) rxr->rx_desc_mapping[0] >> 32;
@@ -5225,8 +5230,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
ring_num, i, bp->rx_pg_ring_size);
break;
}
- prod = NEXT_RX_BD(prod);
- ring_prod = RX_PG_RING_IDX(prod);
+ prod = BNX2_NEXT_RX_BD(prod);
+ ring_prod = BNX2_RX_PG_RING_IDX(prod);
}
rxr->rx_pg_prod = prod;
@@ -5237,8 +5242,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
ring_num, i, bp->rx_ring_size);
break;
}
- prod = NEXT_RX_BD(prod);
- ring_prod = RX_RING_IDX(prod);
+ prod = BNX2_NEXT_RX_BD(prod);
+ ring_prod = BNX2_RX_RING_IDX(prod);
}
rxr->rx_prod = prod;
@@ -5246,10 +5251,10 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ;
rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX;
- REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
- REG_WR16(bp, rxr->rx_bidx_addr, prod);
+ BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
+ BNX2_WR16(bp, rxr->rx_bidx_addr, prod);
- REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
+ BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
}
static void
@@ -5260,15 +5265,15 @@ bnx2_init_all_rings(struct bnx2 *bp)
bnx2_clear_ring_states(bp);
- REG_WR(bp, BNX2_TSCH_TSS_CFG, 0);
+ BNX2_WR(bp, BNX2_TSCH_TSS_CFG, 0);
for (i = 0; i < bp->num_tx_rings; i++)
bnx2_init_tx_ring(bp, i);
if (bp->num_tx_rings > 1)
- REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
- (TX_TSS_CID << 7));
+ BNX2_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
+ (TX_TSS_CID << 7));
- REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
+ BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0);
for (i = 0; i < bp->num_rx_rings; i++)
@@ -5282,8 +5287,8 @@ bnx2_init_all_rings(struct bnx2 *bp)
tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
if ((i % 8) == 7) {
- REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
- REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
+ BNX2_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
+ BNX2_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
BNX2_RLUP_RSS_COMMAND_WRITE |
BNX2_RLUP_RSS_COMMAND_HASH_MASK);
@@ -5294,7 +5299,7 @@ bnx2_init_all_rings(struct bnx2 *bp)
val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI;
- REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
+ BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
}
}
@@ -5303,8 +5308,8 @@ static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
{
u32 max, num_rings = 1;
- while (ring_size > MAX_RX_DESC_CNT) {
- ring_size -= MAX_RX_DESC_CNT;
+ while (ring_size > BNX2_MAX_RX_DESC_CNT) {
+ ring_size -= BNX2_MAX_RX_DESC_CNT;
num_rings++;
}
/* round to next power of 2 */
@@ -5337,13 +5342,14 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
jumbo_size = size * pages;
- if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT)
- jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT;
+ if (jumbo_size > BNX2_MAX_TOTAL_RX_PG_DESC_CNT)
+ jumbo_size = BNX2_MAX_TOTAL_RX_PG_DESC_CNT;
bp->rx_pg_ring_size = jumbo_size;
bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
- MAX_RX_PG_RINGS);
- bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
+ BNX2_MAX_RX_PG_RINGS);
+ bp->rx_max_pg_ring_idx =
+ (bp->rx_max_pg_ring * BNX2_RX_DESC_CNT) - 1;
rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET;
bp->rx_copy_thresh = 0;
}
@@ -5354,8 +5360,8 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET;
bp->rx_ring_size = size;
- bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
- bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
+ bp->rx_max_ring = bnx2_find_max_ring(size, BNX2_MAX_RX_RINGS);
+ bp->rx_max_ring_idx = (bp->rx_max_ring * BNX2_RX_DESC_CNT) - 1;
}
static void
@@ -5371,13 +5377,13 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
if (txr->tx_buf_ring == NULL)
continue;
- for (j = 0; j < TX_DESC_CNT; ) {
- struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
+ for (j = 0; j < BNX2_TX_DESC_CNT; ) {
+ struct bnx2_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
struct sk_buff *skb = tx_buf->skb;
int k, last;
if (skb == NULL) {
- j = NEXT_TX_BD(j);
+ j = BNX2_NEXT_TX_BD(j);
continue;
}
@@ -5389,9 +5395,9 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
tx_buf->skb = NULL;
last = tx_buf->nr_frags;
- j = NEXT_TX_BD(j);
- for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) {
- tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
+ j = BNX2_NEXT_TX_BD(j);
+ for (k = 0; k < last; k++, j = BNX2_NEXT_TX_BD(j)) {
+ tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(j)];
dma_unmap_page(&bp->pdev->dev,
dma_unmap_addr(tx_buf, mapping),
skb_frag_size(&skb_shinfo(skb)->frags[k]),
@@ -5417,7 +5423,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
return;
for (j = 0; j < bp->rx_max_ring_idx; j++) {
- struct sw_bd *rx_buf = &rxr->rx_buf_ring[j];
+ struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[j];
u8 *data = rx_buf->data;
if (data == NULL)
@@ -5615,7 +5621,7 @@ bnx2_test_registers(struct bnx2 *bp)
ret = 0;
is_5709 = 0;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
is_5709 = 1;
for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
@@ -5714,7 +5720,7 @@ bnx2_test_memory(struct bnx2 *bp)
};
struct mem_entry *mem_tbl;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
mem_tbl = mem_tbl_5709;
else
mem_tbl = mem_tbl_5706;
@@ -5741,8 +5747,8 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
unsigned char *packet;
u16 rx_start_idx, rx_idx;
dma_addr_t map;
- struct tx_bd *txbd;
- struct sw_bd *rx_buf;
+ struct bnx2_tx_bd *txbd;
+ struct bnx2_sw_bd *rx_buf;
struct l2_fhdr *rx_hdr;
int ret = -ENODEV;
struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
@@ -5784,17 +5790,17 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
return -EIO;
}
- REG_WR(bp, BNX2_HC_COMMAND,
- bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ BNX2_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
- REG_RD(bp, BNX2_HC_COMMAND);
+ BNX2_RD(bp, BNX2_HC_COMMAND);
udelay(5);
rx_start_idx = bnx2_get_hw_rx_cons(bnapi);
num_pkts = 0;
- txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)];
+ txbd = &txr->tx_desc_ring[BNX2_TX_RING_IDX(txr->tx_prod)];
txbd->tx_bd_haddr_hi = (u64) map >> 32;
txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
@@ -5802,18 +5808,18 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
num_pkts++;
- txr->tx_prod = NEXT_TX_BD(txr->tx_prod);
+ txr->tx_prod = BNX2_NEXT_TX_BD(txr->tx_prod);
txr->tx_prod_bseq += pkt_size;
- REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
- REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
+ BNX2_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
+ BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
udelay(100);
- REG_WR(bp, BNX2_HC_COMMAND,
- bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ BNX2_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
- REG_RD(bp, BNX2_HC_COMMAND);
+ BNX2_RD(bp, BNX2_HC_COMMAND);
udelay(5);
@@ -5962,14 +5968,14 @@ bnx2_test_intr(struct bnx2 *bp)
if (!netif_running(bp->dev))
return -ENODEV;
- status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
+ status_idx = BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
/* This register is not touched during run-time. */
- REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
- REG_RD(bp, BNX2_HC_COMMAND);
+ BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
+ BNX2_RD(bp, BNX2_HC_COMMAND);
for (i = 0; i < 10; i++) {
- if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
+ if ((BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
status_idx) {
break;
@@ -6132,11 +6138,11 @@ bnx2_timer(unsigned long data)
/* workaround occasional corrupted counters */
if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks)
- REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
- BNX2_HC_COMMAND_STATS_NOW);
+ BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
+ BNX2_HC_COMMAND_STATS_NOW);
if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
- if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
bnx2_5706_serdes_timer(bp);
else
bnx2_5708_serdes_timer(bp);
@@ -6205,13 +6211,13 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
const int len = sizeof(bp->irq_tbl[0].name);
bnx2_setup_msix_tbl(bp);
- REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
- REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
- REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
+ BNX2_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
+ BNX2_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
+ BNX2_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
/* Need to flush the previous three writes to ensure MSI-X
* is setup properly */
- REG_RD(bp, BNX2_PCI_MSIX_CONTROL);
+ BNX2_RD(bp, BNX2_PCI_MSIX_CONTROL);
for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
msix_ent[i].entry = i;
@@ -6274,7 +6280,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
!(bp->flags & BNX2_FLAG_USING_MSIX)) {
if (pci_enable_msi(bp->pdev) == 0) {
bp->flags |= BNX2_FLAG_USING_MSI;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
bp->flags |= BNX2_FLAG_ONE_SHOT_MSI;
bp->irq_tbl[0].handler = bnx2_msi_1shot;
} else
@@ -6464,22 +6470,22 @@ bnx2_dump_ftq(struct bnx2 *bp)
netdev_err(dev, "<--- end FTQ dump --->\n");
netdev_err(dev, "<--- start TBDC dump --->\n");
netdev_err(dev, "TBDC free cnt: %ld\n",
- REG_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT);
+ BNX2_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT);
netdev_err(dev, "LINE CID BIDX CMD VALIDS\n");
for (i = 0; i < 0x20; i++) {
int j = 0;
- REG_WR(bp, BNX2_TBDC_BD_ADDR, i);
- REG_WR(bp, BNX2_TBDC_CAM_OPCODE,
- BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ);
- REG_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB);
- while ((REG_RD(bp, BNX2_TBDC_COMMAND) &
+ BNX2_WR(bp, BNX2_TBDC_BD_ADDR, i);
+ BNX2_WR(bp, BNX2_TBDC_CAM_OPCODE,
+ BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ);
+ BNX2_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB);
+ while ((BNX2_RD(bp, BNX2_TBDC_COMMAND) &
BNX2_TBDC_COMMAND_CMD_REG_ARB) && j < 100)
j++;
- cid = REG_RD(bp, BNX2_TBDC_CID);
- bdidx = REG_RD(bp, BNX2_TBDC_BIDX);
- valid = REG_RD(bp, BNX2_TBDC_CAM_OPCODE);
+ cid = BNX2_RD(bp, BNX2_TBDC_CID);
+ bdidx = BNX2_RD(bp, BNX2_TBDC_BIDX);
+ valid = BNX2_RD(bp, BNX2_TBDC_CAM_OPCODE);
netdev_err(dev, "%02x %06x %04lx %02x [%x]\n",
i, cid, bdidx & BNX2_TBDC_BDIDX_BDIDX,
bdidx >> 24, (valid >> 8) & 0x0ff);
@@ -6500,15 +6506,15 @@ bnx2_dump_state(struct bnx2 *bp)
pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2);
netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2);
netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n",
- REG_RD(bp, BNX2_EMAC_TX_STATUS),
- REG_RD(bp, BNX2_EMAC_RX_STATUS));
+ BNX2_RD(bp, BNX2_EMAC_TX_STATUS),
+ BNX2_RD(bp, BNX2_EMAC_RX_STATUS));
netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
- REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
+ BNX2_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
- REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
+ BNX2_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
if (bp->flags & BNX2_FLAG_USING_MSIX)
netdev_err(dev, "DEBUG: PBA[%08x]\n",
- REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
+ BNX2_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
}
static void
@@ -6533,8 +6539,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
dma_addr_t mapping;
- struct tx_bd *txbd;
- struct sw_tx_bd *tx_buf;
+ struct bnx2_tx_bd *txbd;
+ struct bnx2_sw_tx_bd *tx_buf;
u32 len, vlan_tag_flags, last_frag, mss;
u16 prod, ring_prod;
int i;
@@ -6557,7 +6563,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
len = skb_headlen(skb);
prod = txr->tx_prod;
- ring_prod = TX_RING_IDX(prod);
+ ring_prod = BNX2_TX_RING_IDX(prod);
vlan_tag_flags = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -6627,8 +6633,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
for (i = 0; i < last_frag; i++) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- prod = NEXT_TX_BD(prod);
- ring_prod = TX_RING_IDX(prod);
+ prod = BNX2_NEXT_TX_BD(prod);
+ ring_prod = BNX2_TX_RING_IDX(prod);
txbd = &txr->tx_desc_ring[ring_prod];
len = skb_frag_size(frag);
@@ -6652,11 +6658,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(txq, skb->len);
- prod = NEXT_TX_BD(prod);
+ prod = BNX2_NEXT_TX_BD(prod);
txr->tx_prod_bseq += skb->len;
- REG_WR16(bp, txr->tx_bidx_addr, prod);
- REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
+ BNX2_WR16(bp, txr->tx_bidx_addr, prod);
+ BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
mmiowb();
@@ -6682,7 +6688,7 @@ dma_error:
/* start back at beginning and unmap skb */
prod = txr->tx_prod;
- ring_prod = TX_RING_IDX(prod);
+ ring_prod = BNX2_TX_RING_IDX(prod);
tx_buf = &txr->tx_buf_ring[ring_prod];
tx_buf->skb = NULL;
dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
@@ -6690,8 +6696,8 @@ dma_error:
/* unmap remaining mapped pages */
for (i = 0; i < last_frag; i++) {
- prod = NEXT_TX_BD(prod);
- ring_prod = TX_RING_IDX(prod);
+ prod = BNX2_NEXT_TX_BD(prod);
+ ring_prod = BNX2_TX_RING_IDX(prod);
tx_buf = &txr->tx_buf_ring[ring_prod];
dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
skb_frag_size(&skb_shinfo(skb)->frags[i]),
@@ -6810,8 +6816,8 @@ bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) +
GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions);
- if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
- (CHIP_ID(bp) == CHIP_ID_5708_A0))
+ if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0))
net_stats->tx_carrier_errors = 0;
else {
net_stats->tx_carrier_errors =
@@ -7030,7 +7036,7 @@ bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
offset = reg_boundaries[0];
p += offset;
while (offset < BNX2_REGDUMP_LEN) {
- *p++ = REG_RD(bp, offset);
+ *p++ = BNX2_RD(bp, offset);
offset += 4;
if (offset == reg_boundaries[i + 1]) {
offset = reg_boundaries[i + 2];
@@ -7254,13 +7260,13 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
{
struct bnx2 *bp = netdev_priv(dev);
- ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
- ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
+ ering->rx_max_pending = BNX2_MAX_TOTAL_RX_DESC_CNT;
+ ering->rx_jumbo_max_pending = BNX2_MAX_TOTAL_RX_PG_DESC_CNT;
ering->rx_pending = bp->rx_ring_size;
ering->rx_jumbo_pending = bp->rx_pg_ring_size;
- ering->tx_max_pending = MAX_TX_DESC_CNT;
+ ering->tx_max_pending = BNX2_MAX_TX_DESC_CNT;
ering->tx_pending = bp->tx_ring_size;
}
@@ -7326,8 +7332,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
struct bnx2 *bp = netdev_priv(dev);
int rc;
- if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
- (ering->tx_pending > MAX_TX_DESC_CNT) ||
+ if ((ering->rx_pending > BNX2_MAX_TOTAL_RX_DESC_CNT) ||
+ (ering->tx_pending > BNX2_MAX_TX_DESC_CNT) ||
(ering->tx_pending <= MAX_SKB_FRAGS)) {
return -EINVAL;
@@ -7614,10 +7620,10 @@ bnx2_get_ethtool_stats(struct net_device *dev,
return;
}
- if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A1) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A2) ||
- (CHIP_ID(bp) == CHIP_ID_5708_A0))
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A2) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0))
stats_len_arr = bnx2_5706_stats_len_arr;
else
stats_len_arr = bnx2_5708_stats_len_arr;
@@ -7655,26 +7661,26 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
case ETHTOOL_ID_ACTIVE:
bnx2_set_power_state(bp, PCI_D0);
- bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
- REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
+ bp->leds_save = BNX2_RD(bp, BNX2_MISC_CFG);
+ BNX2_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
return 1; /* cycle on/off once per second */
case ETHTOOL_ID_ON:
- REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
- BNX2_EMAC_LED_1000MB_OVERRIDE |
- BNX2_EMAC_LED_100MB_OVERRIDE |
- BNX2_EMAC_LED_10MB_OVERRIDE |
- BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
- BNX2_EMAC_LED_TRAFFIC);
+ BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
+ BNX2_EMAC_LED_1000MB_OVERRIDE |
+ BNX2_EMAC_LED_100MB_OVERRIDE |
+ BNX2_EMAC_LED_10MB_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC);
break;
case ETHTOOL_ID_OFF:
- REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
+ BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
break;
case ETHTOOL_ID_INACTIVE:
- REG_WR(bp, BNX2_EMAC_LED, 0);
- REG_WR(bp, BNX2_MISC_CFG, bp->leds_save);
+ BNX2_WR(bp, BNX2_EMAC_LED, 0);
+ BNX2_WR(bp, BNX2_MISC_CFG, bp->leds_save);
if (!netif_running(dev))
bnx2_set_power_state(bp, PCI_D3hot);
@@ -7896,10 +7902,10 @@ poll_bnx2(struct net_device *dev)
}
#endif
-static void __devinit
+static void
bnx2_get_5709_media(struct bnx2 *bp)
{
- u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
+ u32 val = BNX2_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
u32 strap;
@@ -7934,18 +7940,18 @@ bnx2_get_5709_media(struct bnx2 *bp)
}
}
-static void __devinit
+static void
bnx2_get_pci_speed(struct bnx2 *bp)
{
u32 reg;
- reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+ reg = BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS);
if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
u32 clkreg;
bp->flags |= BNX2_FLAG_PCIX;
- clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+ clkreg = BNX2_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
switch (clkreg) {
@@ -7986,7 +7992,7 @@ bnx2_get_pci_speed(struct bnx2 *bp)
}
-static void __devinit
+static void
bnx2_read_vpd_fw_ver(struct bnx2 *bp)
{
int rc, i, j;
@@ -8054,7 +8060,7 @@ vpd_done:
kfree(data);
}
-static int __devinit
+static int
bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
{
struct bnx2 *bp;
@@ -8131,20 +8137,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
* Rely on CPU to do target byte swapping on big endian systems
* The chip's target access swapping will not swap all accesses
*/
- REG_WR(bp, BNX2_PCICFG_MISC_CONFIG,
- BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
- BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+ BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG,
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
- bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+ bp->chip_id = BNX2_RD(bp, BNX2_MISC_ID);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
if (!pci_is_pcie(pdev)) {
dev_err(&pdev->dev, "Not PCIE, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
bp->flags |= BNX2_FLAG_PCIE;
- if (CHIP_REV(bp) == CHIP_REV_Ax)
+ if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax)
bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
/* AER (Advanced Error Reporting) hooks */
@@ -8163,18 +8169,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->flags |= BNX2_FLAG_BROKEN_STATS;
}
- if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709 &&
+ BNX2_CHIP_REV(bp) != BNX2_CHIP_REV_Ax) {
if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
bp->flags |= BNX2_FLAG_MSIX_CAP;
}
- if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
+ if (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0 &&
+ BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A1) {
if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
bp->flags |= BNX2_FLAG_MSI_CAP;
}
/* 5708 cannot support DMA addresses > 40-bit. */
- if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
persist_dma_mask = dma_mask = DMA_BIT_MASK(40);
else
persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
@@ -8197,12 +8205,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bnx2_get_pci_speed(bp);
/* 5706A0 may falsely detect SERR and PERR. */
- if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
- reg = REG_RD(bp, PCI_COMMAND);
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
+ reg = BNX2_RD(bp, PCI_COMMAND);
reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
- REG_WR(bp, PCI_COMMAND, reg);
- }
- else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
+ BNX2_WR(bp, PCI_COMMAND, reg);
+ } else if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) &&
!(bp->flags & BNX2_FLAG_PCIX)) {
dev_err(&pdev->dev,
@@ -8299,7 +8306,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->mac_addr[4] = (u8) (reg >> 8);
bp->mac_addr[5] = (u8) reg;
- bp->tx_ring_size = MAX_TX_DESC_CNT;
+ bp->tx_ring_size = BNX2_MAX_TX_DESC_CNT;
bnx2_set_rx_ring_size(bp, 255);
bp->tx_quick_cons_trip_int = 2;
@@ -8319,9 +8326,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->phy_addr = 1;
/* Disable WOL support if we are running on a SERDES chip. */
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
bnx2_get_5709_media(bp);
- else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
+ else if (BNX2_CHIP_BOND(bp) & BNX2_CHIP_BOND_SERDES_BIT)
bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
bp->phy_port = PORT_TP;
@@ -8332,7 +8339,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->flags |= BNX2_FLAG_NO_WOL;
bp->wol = 0;
}
- if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706) {
/* Don't do parallel detect on this board because of
* some board problems. The link will not go down
* if we do parallel detect.
@@ -8345,25 +8352,25 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE;
}
- } else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
- CHIP_NUM(bp) == CHIP_NUM_5708)
+ } else if (BNX2_CHIP(bp) == BNX2_CHIP_5706 ||
+ BNX2_CHIP(bp) == BNX2_CHIP_5708)
bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX;
- else if (CHIP_NUM(bp) == CHIP_NUM_5709 &&
- (CHIP_REV(bp) == CHIP_REV_Ax ||
- CHIP_REV(bp) == CHIP_REV_Bx))
+ else if (BNX2_CHIP(bp) == BNX2_CHIP_5709 &&
+ (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax ||
+ BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Bx))
bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC;
bnx2_init_fw_cap(bp);
- if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B1) ||
- !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
+ if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) ||
+ (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1) ||
+ !(BNX2_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
bp->flags |= BNX2_FLAG_NO_WOL;
bp->wol = 0;
}
- if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
bp->tx_quick_cons_trip_int =
bp->tx_quick_cons_trip;
bp->tx_ticks_int = bp->tx_ticks;
@@ -8385,7 +8392,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
* AMD believes this incompatibility is unique to the 5706, and
* prefers to locally disable MSI rather than globally disabling it.
*/
- if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5706 && disable_msi == 0) {
struct pci_dev *amd_8132 = NULL;
while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
@@ -8414,6 +8421,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->cnic_eth_dev.max_iscsi_conn =
(bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
+ bp->cnic_probe = bnx2_cnic_probe;
#endif
pci_save_state(pdev);
@@ -8439,7 +8447,7 @@ err_out:
return rc;
}
-static char * __devinit
+static char *
bnx2_bus_string(struct bnx2 *bp, char *str)
{
char *s = str;
@@ -8505,7 +8513,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
#endif
};
-static int __devinit
+static int
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int version_printed = 0;
@@ -8541,7 +8549,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_TSO | NETIF_F_TSO_ECN |
NETIF_F_RXHASH | NETIF_F_RXCSUM;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
dev->vlan_features = dev->hw_features;
@@ -8556,8 +8564,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, "
"node addr %pM\n", board_info[ent->driver_data].name,
- ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
- ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ ((BNX2_CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+ ((BNX2_CHIP_ID(bp) & 0x0ff0) >> 4),
bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0),
pdev->irq, dev->dev_addr);
@@ -8573,7 +8581,7 @@ err_free:
return rc;
}
-static void __devexit
+static void
bnx2_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -8752,7 +8760,7 @@ static struct pci_driver bnx2_pci_driver = {
.name = DRV_MODULE_NAME,
.id_table = bnx2_pci_tbl,
.probe = bnx2_init_one,
- .remove = __devexit_p(bnx2_remove_one),
+ .remove = bnx2_remove_one,
.suspend = bnx2_suspend,
.resume = bnx2_resume,
.err_handler = &bnx2_err_handler,
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index af6451dec295..172efbecfea2 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -20,7 +20,7 @@
/*
* tx_bd definition
*/
-struct tx_bd {
+struct bnx2_tx_bd {
u32 tx_bd_haddr_hi;
u32 tx_bd_haddr_lo;
u32 tx_bd_mss_nbytes;
@@ -48,7 +48,7 @@ struct tx_bd {
/*
* rx_bd definition
*/
-struct rx_bd {
+struct bnx2_rx_bd {
u32 rx_bd_haddr_hi;
u32 rx_bd_haddr_lo;
u32 rx_bd_len;
@@ -6538,37 +6538,38 @@ struct l2_fhdr {
/* Use CPU native page size up to 16K for the ring sizes. */
#if (PAGE_SHIFT > 14)
-#define BCM_PAGE_BITS 14
+#define BNX2_PAGE_BITS 14
#else
-#define BCM_PAGE_BITS PAGE_SHIFT
+#define BNX2_PAGE_BITS PAGE_SHIFT
#endif
-#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS)
+#define BNX2_PAGE_SIZE (1 << BNX2_PAGE_BITS)
-#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+#define BNX2_TX_DESC_CNT (BNX2_PAGE_SIZE / sizeof(struct bnx2_tx_bd))
+#define BNX2_MAX_TX_DESC_CNT (BNX2_TX_DESC_CNT - 1)
-#define MAX_RX_RINGS 8
-#define MAX_RX_PG_RINGS 32
-#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
-#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
-#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
+#define BNX2_MAX_RX_RINGS 8
+#define BNX2_MAX_RX_PG_RINGS 32
+#define BNX2_RX_DESC_CNT (BNX2_PAGE_SIZE / sizeof(struct bnx2_rx_bd))
+#define BNX2_MAX_RX_DESC_CNT (BNX2_RX_DESC_CNT - 1)
+#define BNX2_MAX_TOTAL_RX_DESC_CNT (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_RINGS)
+#define BNX2_MAX_TOTAL_RX_PG_DESC_CNT \
+ (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_PG_RINGS)
-#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
- (MAX_TX_DESC_CNT - 1)) ? \
+#define BNX2_NEXT_TX_BD(x) (((x) & (BNX2_MAX_TX_DESC_CNT - 1)) == \
+ (BNX2_MAX_TX_DESC_CNT - 1)) ? \
(x) + 2 : (x) + 1
-#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+#define BNX2_TX_RING_IDX(x) ((x) & BNX2_MAX_TX_DESC_CNT)
-#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \
- (MAX_RX_DESC_CNT - 1)) ? \
+#define BNX2_NEXT_RX_BD(x) (((x) & (BNX2_MAX_RX_DESC_CNT - 1)) == \
+ (BNX2_MAX_RX_DESC_CNT - 1)) ? \
(x) + 2 : (x) + 1
-#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
-#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
+#define BNX2_RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+#define BNX2_RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
-#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
+#define BNX2_RX_RING(x) (((x) & ~BNX2_MAX_RX_DESC_CNT) >> (BNX2_PAGE_BITS - 4))
+#define BNX2_RX_IDX(x) ((x) & BNX2_MAX_RX_DESC_CNT)
/* Context size. */
#define CTX_SHIFT 7
@@ -6609,7 +6610,7 @@ struct l2_fhdr {
* RX ring buffer contains pointer to kmalloc() data only,
* skb are built only after Hardware filled the frame.
*/
-struct sw_bd {
+struct bnx2_sw_bd {
u8 *data;
DEFINE_DMA_UNMAP_ADDR(mapping);
};
@@ -6623,23 +6624,23 @@ static inline struct l2_fhdr *get_l2_fhdr(u8 *data)
}
-struct sw_pg {
+struct bnx2_sw_pg {
struct page *page;
DEFINE_DMA_UNMAP_ADDR(mapping);
};
-struct sw_tx_bd {
+struct bnx2_sw_tx_bd {
struct sk_buff *skb;
DEFINE_DMA_UNMAP_ADDR(mapping);
unsigned short is_gso;
unsigned short nr_frags;
};
-#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
-#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
-#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
-#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT)
-#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
+#define SW_RXBD_RING_SIZE (sizeof(struct bnx2_sw_bd) * BNX2_RX_DESC_CNT)
+#define SW_RXPG_RING_SIZE (sizeof(struct bnx2_sw_pg) * BNX2_RX_DESC_CNT)
+#define RXBD_RING_SIZE (sizeof(struct bnx2_rx_bd) * BNX2_RX_DESC_CNT)
+#define SW_TXBD_RING_SIZE (sizeof(struct bnx2_sw_tx_bd) * BNX2_TX_DESC_CNT)
+#define TXBD_RING_SIZE (sizeof(struct bnx2_tx_bd) * BNX2_TX_DESC_CNT)
/* Buffered flash (Atmel: AT45DB011B) specific information */
#define SEEPROM_PAGE_BITS 2
@@ -6720,8 +6721,8 @@ struct bnx2_tx_ring_info {
u32 tx_bidx_addr;
u32 tx_bseq_addr;
- struct tx_bd *tx_desc_ring;
- struct sw_tx_bd *tx_buf_ring;
+ struct bnx2_tx_bd *tx_desc_ring;
+ struct bnx2_sw_tx_bd *tx_buf_ring;
u16 tx_cons;
u16 hw_tx_cons;
@@ -6741,13 +6742,13 @@ struct bnx2_rx_ring_info {
u16 rx_pg_prod;
u16 rx_pg_cons;
- struct sw_bd *rx_buf_ring;
- struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
- struct sw_pg *rx_pg_ring;
- struct rx_bd *rx_pg_desc_ring[MAX_RX_PG_RINGS];
+ struct bnx2_sw_bd *rx_buf_ring;
+ struct bnx2_rx_bd *rx_desc_ring[BNX2_MAX_RX_RINGS];
+ struct bnx2_sw_pg *rx_pg_ring;
+ struct bnx2_rx_bd *rx_pg_desc_ring[BNX2_MAX_RX_PG_RINGS];
- dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
- dma_addr_t rx_pg_desc_mapping[MAX_RX_PG_RINGS];
+ dma_addr_t rx_desc_mapping[BNX2_MAX_RX_RINGS];
+ dma_addr_t rx_pg_desc_mapping[BNX2_MAX_RX_PG_RINGS];
};
struct bnx2_napi {
@@ -6853,33 +6854,31 @@ struct bnx2 {
u32 chip_id;
/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
-#define CHIP_NUM_5706 0x57060000
-#define CHIP_NUM_5708 0x57080000
-#define CHIP_NUM_5709 0x57090000
-
-#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
-#define CHIP_REV_Ax 0x00000000
-#define CHIP_REV_Bx 0x00001000
-#define CHIP_REV_Cx 0x00002000
-
-#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
-#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f)
-
-#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
-#define CHIP_ID_5706_A0 0x57060000
-#define CHIP_ID_5706_A1 0x57060010
-#define CHIP_ID_5706_A2 0x57060020
-#define CHIP_ID_5708_A0 0x57080000
-#define CHIP_ID_5708_B0 0x57081000
-#define CHIP_ID_5708_B1 0x57081010
-#define CHIP_ID_5709_A0 0x57090000
-#define CHIP_ID_5709_A1 0x57090010
-
-#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
+#define BNX2_CHIP(bp) (((bp)->chip_id) & 0xffff0000)
+#define BNX2_CHIP_5706 0x57060000
+#define BNX2_CHIP_5708 0x57080000
+#define BNX2_CHIP_5709 0x57090000
+
+#define BNX2_CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
+#define BNX2_CHIP_REV_Ax 0x00000000
+#define BNX2_CHIP_REV_Bx 0x00001000
+#define BNX2_CHIP_REV_Cx 0x00002000
+
+#define BNX2_CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
+#define BNX2_CHIP_BOND(bp) (((bp)->chip_id) & 0x0000000f)
+
+#define BNX2_CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
+#define BNX2_CHIP_ID_5706_A0 0x57060000
+#define BNX2_CHIP_ID_5706_A1 0x57060010
+#define BNX2_CHIP_ID_5706_A2 0x57060020
+#define BNX2_CHIP_ID_5708_A0 0x57080000
+#define BNX2_CHIP_ID_5708_B0 0x57081000
+#define BNX2_CHIP_ID_5708_B1 0x57081010
+#define BNX2_CHIP_ID_5709_A0 0x57090000
+#define BNX2_CHIP_ID_5709_A1 0x57090010
/* A serdes chip will have the first bit of the bond id set. */
-#define CHIP_BOND_ID_SERDES_BIT 0x01
+#define BNX2_CHIP_BOND_SERDES_BIT 0x01
u32 phy_addr;
u32 phy_id;
@@ -6985,19 +6984,20 @@ struct bnx2 {
#ifdef BCM_CNIC
struct mutex cnic_lock;
struct cnic_eth_dev cnic_eth_dev;
+ struct cnic_eth_dev *(*cnic_probe)(struct net_device *);
#endif
const struct firmware *mips_firmware;
const struct firmware *rv2p_firmware;
};
-#define REG_RD(bp, offset) \
+#define BNX2_RD(bp, offset) \
readl(bp->regview + offset)
-#define REG_WR(bp, offset, val) \
+#define BNX2_WR(bp, offset, val) \
writel(val, bp->regview + offset)
-#define REG_WR16(bp, offset, val) \
+#define BNX2_WR16(bp, offset, val) \
writew(val, bp->regview + offset)
struct cpu_reg {
@@ -7052,7 +7052,7 @@ struct bnx2_rv2p_fw_file {
#define RV2P_P1_FIXUP_PAGE_SIZE_IDX 0
#define RV2P_BD_PAGE_SIZE_MSK 0xffff
-#define RV2P_BD_PAGE_SIZE ((BCM_PAGE_SIZE / 16) - 1)
+#define RV2P_BD_PAGE_SIZE ((BNX2_PAGE_SIZE / 16) - 1)
#define RV2P_PROC1 0
#define RV2P_PROC2 1
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 72897c47b8c8..e8d4db10c8f3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -34,25 +34,16 @@
#include "bnx2x_hsi.h"
-#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
-#define BCM_CNIC 1
#include "../cnic_if.h"
-#endif
-#ifdef BCM_CNIC
-#define BNX2X_MIN_MSIX_VEC_CNT 3
-#define BNX2X_MSIX_VEC_FP_START 2
-#else
-#define BNX2X_MIN_MSIX_VEC_CNT 2
-#define BNX2X_MSIX_VEC_FP_START 1
-#endif
+
+#define BNX2X_MIN_MSIX_VEC_CNT(bp) ((bp)->min_msix_vec_cnt)
#include <linux/mdio.h>
#include "bnx2x_reg.h"
#include "bnx2x_fw_defs.h"
#include "bnx2x_mfw_req.h"
-#include "bnx2x_hsi.h"
#include "bnx2x_link.h"
#include "bnx2x_sp.h"
#include "bnx2x_dcb.h"
@@ -256,15 +247,10 @@ enum {
/* FCoE L2 */
#define BNX2X_FCOE_ETH_CID(bp) (BNX2X_CNIC_START_ETH_CID(bp) + 1)
-/** Additional rings budgeting */
-#ifdef BCM_CNIC
-#define CNIC_PRESENT 1
-#define FCOE_PRESENT 1
-#else
-#define CNIC_PRESENT 0
-#define FCOE_PRESENT 0
-#endif /* BCM_CNIC */
-#define NON_ETH_CONTEXT_USE (FCOE_PRESENT)
+#define CNIC_SUPPORT(bp) ((bp)->cnic_support)
+#define CNIC_ENABLED(bp) ((bp)->cnic_enabled)
+#define CNIC_LOADED(bp) ((bp)->cnic_loaded)
+#define FCOE_INIT(bp) ((bp)->fcoe_init)
#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -297,9 +283,7 @@ enum {
OOO_TXQ_IDX_OFFSET,
};
#define MAX_ETH_TXQ_IDX(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos)
-#ifdef BCM_CNIC
#define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET)
-#endif
/* fast path */
/*
@@ -505,7 +489,7 @@ struct bnx2x_fastpath {
u32 ustorm_rx_prods_offset;
u32 rx_buf_size;
-
+ u32 rx_frag_size; /* 0 if kmalloced(), or rx_buf_size + NET_SKB_PAD */
dma_addr_t status_blk_mapping;
enum bnx2x_tpa_mode_t mode;
@@ -585,15 +569,9 @@ struct bnx2x_fastpath {
->var)
-#define IS_ETH_FP(fp) (fp->index < \
- BNX2X_NUM_ETH_QUEUES(fp->bp))
-#ifdef BCM_CNIC
-#define IS_FCOE_FP(fp) (fp->index == FCOE_IDX(fp->bp))
-#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp))
-#else
-#define IS_FCOE_FP(fp) false
-#define IS_FCOE_IDX(idx) false
-#endif
+#define IS_ETH_FP(fp) ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp))
+#define IS_FCOE_FP(fp) ((fp)->index == FCOE_IDX((fp)->bp))
+#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp))
/* MC hsi */
@@ -886,6 +864,18 @@ struct bnx2x_common {
(CHIP_REV(bp) == CHIP_REV_Bx))
#define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \
(CHIP_REV(bp) == CHIP_REV_Ax))
+/* This define is used in two main places:
+ * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher
+ * to nic-only mode or to offload mode. Offload mode is configured if either the
+ * chip is E1x (where MIC_MODE register is not applicable), or if cnic already
+ * registered for this port (which means that the user wants storage services).
+ * 2. During cnic-related load, to know if offload mode is already configured in
+ * the HW or needs to be configrued.
+ * Since the transition from nic-mode to offload-mode in HW causes traffic
+ * coruption, nic-mode is configured only in ports on which storage services
+ * where never requested.
+ */
+#define CONFIGURE_NIC_MODE(bp) (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp))
int flash_size;
#define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */
@@ -925,6 +915,7 @@ struct bnx2x_common {
#define BNX2X_IGU_STAS_MSG_VF_CNT 64
#define BNX2X_IGU_STAS_MSG_PF_CNT 4
+#define MAX_IGU_ATTN_ACK_TO 100
/* end of common */
/* port */
@@ -946,7 +937,6 @@ struct bnx2x_port {
/* used to synchronize phy accesses */
struct mutex phy_mutex;
- int need_hw_lock;
u32 port_stx;
@@ -1003,18 +993,15 @@ union cdu_context {
#define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */
#define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
-#ifdef BCM_CNIC
#define CNIC_ISCSI_CID_MAX 256
#define CNIC_FCOE_CID_MAX 2048
#define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
#define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
-#endif
#define QM_ILT_PAGE_SZ_HW 0
#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
#define QM_CID_ROUND 1024
-#ifdef BCM_CNIC
/* TM (timers) host DB constants */
#define TM_ILT_PAGE_SZ_HW 0
#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
@@ -1032,8 +1019,6 @@ union cdu_context {
#define SRC_T2_SZ SRC_ILT_SZ
#define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
-#endif
-
#define MAX_DMAE_C 8
/* DMA memory not used in fastpath */
@@ -1201,6 +1186,7 @@ struct bnx2x_prev_path_list {
u8 slot;
u8 path;
struct list_head list;
+ u8 undi;
};
struct bnx2x_sp_objs {
@@ -1227,7 +1213,6 @@ struct bnx2x {
struct bnx2x_sp_objs *sp_objs;
struct bnx2x_fp_stats *fp_stats;
struct bnx2x_fp_txdata *bnx2x_txq;
- int bnx2x_txq_size;
void __iomem *regview;
void __iomem *doorbells;
u16 db_size;
@@ -1350,6 +1335,16 @@ struct bnx2x {
#define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG)
#define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG)
+ u8 cnic_support;
+ bool cnic_enabled;
+ bool cnic_loaded;
+ struct cnic_eth_dev *(*cnic_probe)(struct net_device *);
+
+ /* Flag that indicates that we can start looking for FCoE L2 queue
+ * completions in the default status block.
+ */
+ bool fcoe_init;
+
int pm_cap;
int mrrs;
@@ -1420,6 +1415,8 @@ struct bnx2x {
#define BNX2X_MAX_COS 3
#define BNX2X_MAX_TX_COS 2
int num_queues;
+ uint num_ethernet_queues;
+ uint num_cnic_queues;
int num_napi_queues;
int disable_tpa;
@@ -1433,6 +1430,7 @@ struct bnx2x {
u8 igu_dsb_id;
u8 igu_base_sb;
u8 igu_sb_cnt;
+ u8 min_msix_vec_cnt;
dma_addr_t def_status_blk_mapping;
@@ -1478,26 +1476,23 @@ struct bnx2x {
* Maximum supported number of RSS queues: number of IGU SBs minus one that goes
* to CNIC.
*/
-#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_PRESENT)
+#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_SUPPORT(bp))
/*
* Maximum CID count that might be required by the bnx2x:
* Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI
*/
#define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \
- + NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+ + 2 * CNIC_SUPPORT(bp))
#define BNX2X_L2_MAX_CID(bp) (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \
- + NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+ + 2 * CNIC_SUPPORT(bp))
#define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
ILT_PAGE_CIDS))
int qm_cid_count;
- int dropless_fc;
+ bool dropless_fc;
-#ifdef BCM_CNIC
- u32 cnic_flags;
-#define BNX2X_CNIC_FLAG_MAC_SET 1
void *t2;
dma_addr_t t2_mapping;
struct cnic_ops __rcu *cnic_ops;
@@ -1518,7 +1513,6 @@ struct bnx2x {
/* Start index of the "special" (CNIC related) L2 cleints */
u8 cnic_base_cl_id;
-#endif
int dmae_ready;
/* used to synchronize dmae accesses */
@@ -1647,9 +1641,9 @@ struct bnx2x {
/* Tx queues may be less or equal to Rx queues */
extern int num_queues;
#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
+#define BNX2X_NUM_ETH_QUEUES(bp) ((bp)->num_ethernet_queues)
#define BNX2X_NUM_NON_CNIC_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - \
- NON_ETH_CONTEXT_USE)
+ (bp)->num_cnic_queues)
#define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp)
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
@@ -1689,6 +1683,13 @@ struct bnx2x_func_init_params {
u16 spq_prod; /* valid iff FUNC_FLG_SPQ */
};
+#define for_each_cnic_queue(bp, var) \
+ for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+ (var)++) \
+ if (skip_queue(bp, var)) \
+ continue; \
+ else
+
#define for_each_eth_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
@@ -1702,6 +1703,22 @@ struct bnx2x_func_init_params {
else
/* Skip forwarding FP */
+#define for_each_valid_rx_queue(bp, var) \
+ for ((var) = 0; \
+ (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \
+ BNX2X_NUM_ETH_QUEUES(bp)); \
+ (var)++) \
+ if (skip_rx_queue(bp, var)) \
+ continue; \
+ else
+
+#define for_each_rx_queue_cnic(bp, var) \
+ for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+ (var)++) \
+ if (skip_rx_queue(bp, var)) \
+ continue; \
+ else
+
#define for_each_rx_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_rx_queue(bp, var)) \
@@ -1709,6 +1726,22 @@ struct bnx2x_func_init_params {
else
/* Skip OOO FP */
+#define for_each_valid_tx_queue(bp, var) \
+ for ((var) = 0; \
+ (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \
+ BNX2X_NUM_ETH_QUEUES(bp)); \
+ (var)++) \
+ if (skip_tx_queue(bp, var)) \
+ continue; \
+ else
+
+#define for_each_tx_queue_cnic(bp, var) \
+ for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+ (var)++) \
+ if (skip_tx_queue(bp, var)) \
+ continue; \
+ else
+
#define for_each_tx_queue(bp, var) \
for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
if (skip_tx_queue(bp, var)) \
@@ -2179,7 +2212,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
#define BNX2X_MF_SD_PROTOCOL(bp) \
((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK)
-#ifdef BCM_CNIC
#define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \
(BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI)
@@ -2196,9 +2228,12 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
#define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \
(BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \
BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)))
-#else
-#define IS_MF_FCOE_AFEX(bp) false
-#endif
+enum {
+ SWITCH_UPDATE,
+ AFEX_UPDATE,
+};
+
+#define NUM_MACS 8
#endif /* bnx2x.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 4833b6a9031c..a2998bea5d4b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -552,6 +552,23 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return 0;
}
+static void bnx2x_frag_free(const struct bnx2x_fastpath *fp, void *data)
+{
+ if (fp->rx_frag_size)
+ put_page(virt_to_head_page(data));
+ else
+ kfree(data);
+}
+
+static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp)
+{
+ if (fp->rx_frag_size)
+ return netdev_alloc_frag(fp->rx_frag_size);
+
+ return kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
+}
+
+
static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct bnx2x_agg_info *tpa_info,
u16 pages,
@@ -574,15 +591,14 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
goto drop;
/* Try to allocate the new data */
- new_data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
-
+ new_data = bnx2x_frag_alloc(fp);
/* Unmap skb in the pool anyway, as we are going to change
pool entry status to BNX2X_TPA_STOP even if new skb allocation
fails. */
dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
if (likely(new_data))
- skb = build_skb(data, 0);
+ skb = build_skb(data, fp->rx_frag_size);
if (likely(skb)) {
#ifdef BNX2X_STOP_ON_ERROR
@@ -619,7 +635,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return;
}
- kfree(new_data);
+ bnx2x_frag_free(fp, new_data);
drop:
/* drop the packet and keep the buffer in the bin */
DP(NETIF_MSG_RX_STATUS,
@@ -635,7 +651,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
dma_addr_t mapping;
- data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
+ data = bnx2x_frag_alloc(fp);
if (unlikely(data == NULL))
return -ENOMEM;
@@ -643,7 +659,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
fp->rx_buf_size,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
- kfree(data);
+ bnx2x_frag_free(fp, data);
BNX2X_ERR("Can't map rx data\n");
return -ENOMEM;
}
@@ -845,9 +861,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size,
DMA_FROM_DEVICE);
- skb = build_skb(data, 0);
+ skb = build_skb(data, fp->rx_frag_size);
if (unlikely(!skb)) {
- kfree(data);
+ bnx2x_frag_free(fp, data);
bnx2x_fp_qstats(bp, fp)->
rx_skb_alloc_failed++;
goto next_rx;
@@ -948,14 +964,12 @@ void bnx2x_acquire_phy_lock(struct bnx2x *bp)
{
mutex_lock(&bp->port.phy_mutex);
- if (bp->port.need_hw_lock)
- bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
}
void bnx2x_release_phy_lock(struct bnx2x *bp)
{
- if (bp->port.need_hw_lock)
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
mutex_unlock(&bp->port.phy_mutex);
}
@@ -1147,11 +1161,30 @@ static void bnx2x_free_tpa_pool(struct bnx2x *bp,
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(first_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
- kfree(data);
+ bnx2x_frag_free(fp, data);
first_buf->data = NULL;
}
}
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp)
+{
+ int j;
+
+ for_each_rx_queue_cnic(bp, j) {
+ struct bnx2x_fastpath *fp = &bp->fp[j];
+
+ fp->rx_bd_cons = 0;
+
+ /* Activate BD ring */
+ /* Warning!
+ * this will generate an interrupt (to the TSTORM)
+ * must only be done after chip is initialized
+ */
+ bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
+ fp->rx_sge_prod);
+ }
+}
+
void bnx2x_init_rx_rings(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
@@ -1159,7 +1192,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
int i, j;
/* Allocate TPA resources */
- for_each_rx_queue(bp, j) {
+ for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
DP(NETIF_MSG_IFUP,
@@ -1173,8 +1206,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
struct sw_rx_bd *first_buf =
&tpa_info->first_buf;
- first_buf->data = kmalloc(fp->rx_buf_size + NET_SKB_PAD,
- GFP_ATOMIC);
+ first_buf->data = bnx2x_frag_alloc(fp);
if (!first_buf->data) {
BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n",
j);
@@ -1217,7 +1249,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
}
}
- for_each_rx_queue(bp, j) {
+ for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
fp->rx_bd_cons = 0;
@@ -1244,29 +1276,45 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
}
}
-static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
{
- int i;
u8 cos;
+ struct bnx2x *bp = fp->bp;
- for_each_tx_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
- for_each_cos_in_tx_queue(fp, cos) {
- struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
- unsigned pkts_compl = 0, bytes_compl = 0;
+ for_each_cos_in_tx_queue(fp, cos) {
+ struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
+ unsigned pkts_compl = 0, bytes_compl = 0;
- u16 sw_prod = txdata->tx_pkt_prod;
- u16 sw_cons = txdata->tx_pkt_cons;
+ u16 sw_prod = txdata->tx_pkt_prod;
+ u16 sw_cons = txdata->tx_pkt_cons;
- while (sw_cons != sw_prod) {
- bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
- &pkts_compl, &bytes_compl);
- sw_cons++;
- }
- netdev_tx_reset_queue(
- netdev_get_tx_queue(bp->dev,
- txdata->txq_index));
+ while (sw_cons != sw_prod) {
+ bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
+ &pkts_compl, &bytes_compl);
+ sw_cons++;
}
+
+ netdev_tx_reset_queue(
+ netdev_get_tx_queue(bp->dev,
+ txdata->txq_index));
+ }
+}
+
+static void bnx2x_free_tx_skbs_cnic(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_tx_queue_cnic(bp, i) {
+ bnx2x_free_tx_skbs_queue(&bp->fp[i]);
+ }
+}
+
+static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_eth_queue(bp, i) {
+ bnx2x_free_tx_skbs_queue(&bp->fp[i]);
}
}
@@ -1290,7 +1338,16 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
fp->rx_buf_size, DMA_FROM_DEVICE);
rx_buf->data = NULL;
- kfree(data);
+ bnx2x_frag_free(fp, data);
+ }
+}
+
+static void bnx2x_free_rx_skbs_cnic(struct bnx2x *bp)
+{
+ int j;
+
+ for_each_rx_queue_cnic(bp, j) {
+ bnx2x_free_rx_bds(&bp->fp[j]);
}
}
@@ -1298,7 +1355,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
{
int j;
- for_each_rx_queue(bp, j) {
+ for_each_eth_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
bnx2x_free_rx_bds(fp);
@@ -1308,6 +1365,12 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
}
}
+void bnx2x_free_skbs_cnic(struct bnx2x *bp)
+{
+ bnx2x_free_tx_skbs_cnic(bp);
+ bnx2x_free_rx_skbs_cnic(bp);
+}
+
void bnx2x_free_skbs(struct bnx2x *bp)
{
bnx2x_free_tx_skbs(bp);
@@ -1347,11 +1410,12 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
bp->msix_table[offset].vector);
offset++;
-#ifdef BCM_CNIC
- if (nvecs == offset)
- return;
- offset++;
-#endif
+
+ if (CNIC_SUPPORT(bp)) {
+ if (nvecs == offset)
+ return;
+ offset++;
+ }
for_each_eth_queue(bp, i) {
if (nvecs == offset)
@@ -1368,7 +1432,7 @@ void bnx2x_free_irq(struct bnx2x *bp)
if (bp->flags & USING_MSIX_FLAG &&
!(bp->flags & USING_SINGLE_MSIX_FLAG))
bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
- CNIC_PRESENT + 1);
+ CNIC_SUPPORT(bp) + 1);
else
free_irq(bp->dev->irq, bp->dev);
}
@@ -1382,12 +1446,14 @@ int bnx2x_enable_msix(struct bnx2x *bp)
bp->msix_table[0].entry);
msix_vec++;
-#ifdef BCM_CNIC
- bp->msix_table[msix_vec].entry = msix_vec;
- BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
- bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
- msix_vec++;
-#endif
+ /* Cnic requires an msix vector for itself */
+ if (CNIC_SUPPORT(bp)) {
+ bp->msix_table[msix_vec].entry = msix_vec;
+ BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
+ msix_vec, bp->msix_table[msix_vec].entry);
+ msix_vec++;
+ }
+
/* We need separate vectors for ETH queues only (not FCoE) */
for_each_eth_queue(bp, i) {
bp->msix_table[msix_vec].entry = msix_vec;
@@ -1396,7 +1462,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
msix_vec++;
}
- req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
+ req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1;
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
@@ -1404,7 +1470,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
* reconfigure number of tx/rx queues according to available
* MSI-X vectors
*/
- if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
+ if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
/* how less vectors we will have? */
int diff = req_cnt - rc;
@@ -1419,7 +1485,8 @@ int bnx2x_enable_msix(struct bnx2x *bp)
/*
* decrease number of queues by number of unallocated entries
*/
- bp->num_queues -= diff;
+ bp->num_ethernet_queues -= diff;
+ bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("New queue configuration set: %d\n",
bp->num_queues);
@@ -1435,6 +1502,9 @@ int bnx2x_enable_msix(struct bnx2x *bp)
BNX2X_DEV_INFO("Using single MSI-X vector\n");
bp->flags |= USING_SINGLE_MSIX_FLAG;
+ BNX2X_DEV_INFO("set number of queues to 1\n");
+ bp->num_ethernet_queues = 1;
+ bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
} else if (rc < 0) {
BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
goto no_msix;
@@ -1464,9 +1534,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
return -EBUSY;
}
-#ifdef BCM_CNIC
- offset++;
-#endif
+ if (CNIC_SUPPORT(bp))
+ offset++;
+
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@@ -1485,7 +1555,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
}
i = BNX2X_NUM_ETH_QUEUES(bp);
- offset = 1 + CNIC_PRESENT;
+ offset = 1 + CNIC_SUPPORT(bp);
netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n",
bp->msix_table[0].vector,
0, bp->msix_table[offset].vector,
@@ -1556,19 +1626,35 @@ static int bnx2x_setup_irqs(struct bnx2x *bp)
return 0;
}
+static void bnx2x_napi_enable_cnic(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_rx_queue_cnic(bp, i)
+ napi_enable(&bnx2x_fp(bp, i, napi));
+}
+
static void bnx2x_napi_enable(struct bnx2x *bp)
{
int i;
- for_each_rx_queue(bp, i)
+ for_each_eth_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
+static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_rx_queue_cnic(bp, i)
+ napi_disable(&bnx2x_fp(bp, i, napi));
+}
+
static void bnx2x_napi_disable(struct bnx2x *bp)
{
int i;
- for_each_rx_queue(bp, i)
+ for_each_eth_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
@@ -1576,6 +1662,8 @@ void bnx2x_netif_start(struct bnx2x *bp)
{
if (netif_running(bp->dev)) {
bnx2x_napi_enable(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_napi_enable_cnic(bp);
bnx2x_int_enable(bp);
if (bp->state == BNX2X_STATE_OPEN)
netif_tx_wake_all_queues(bp->dev);
@@ -1586,14 +1674,15 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{
bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_napi_disable_cnic(bp);
}
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
{
struct bnx2x *bp = netdev_priv(dev);
-#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
+ if (CNIC_LOADED(bp) && !NO_FCOE(bp)) {
struct ethhdr *hdr = (struct ethhdr *)skb->data;
u16 ether_type = ntohs(hdr->h_proto);
@@ -1609,7 +1698,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
return bnx2x_fcoe_tx(bp, txq_index);
}
-#endif
+
/* select a non-FCoE queue */
return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
}
@@ -1618,15 +1707,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
void bnx2x_set_num_queues(struct bnx2x *bp)
{
/* RSS queues */
- bp->num_queues = bnx2x_calc_num_queues(bp);
+ bp->num_ethernet_queues = bnx2x_calc_num_queues(bp);
-#ifdef BCM_CNIC
/* override in STORAGE SD modes */
if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))
- bp->num_queues = 1;
-#endif
+ bp->num_ethernet_queues = 1;
+
/* Add special queues */
- bp->num_queues += NON_ETH_CONTEXT_USE;
+ bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */
+ bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
}
@@ -1653,20 +1742,18 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
* bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
* will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
*/
-static int bnx2x_set_real_num_queues(struct bnx2x *bp)
+static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)
{
int rc, tx, rx;
tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos;
- rx = BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE;
+ rx = BNX2X_NUM_ETH_QUEUES(bp);
/* account for fcoe queue */
-#ifdef BCM_CNIC
- if (!NO_FCOE(bp)) {
- rx += FCOE_PRESENT;
- tx += FCOE_PRESENT;
+ if (include_cnic && !NO_FCOE(bp)) {
+ rx++;
+ tx++;
}
-#endif
rc = netif_set_real_num_tx_queues(bp->dev, tx);
if (rc) {
@@ -1710,6 +1797,10 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
mtu +
BNX2X_FW_RX_ALIGN_END;
/* Note : rx_buf_size doesnt take into account NET_SKB_PAD */
+ if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE)
+ fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD;
+ else
+ fp->rx_frag_size = 0;
}
}
@@ -1859,14 +1950,26 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
(bp)->state = BNX2X_STATE_ERROR; \
goto label; \
} while (0)
-#else
+
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+ do { \
+ bp->cnic_loaded = false; \
+ goto label; \
+ } while (0)
+#else /*BNX2X_STOP_ON_ERROR*/
#define LOAD_ERROR_EXIT(bp, label) \
do { \
(bp)->state = BNX2X_STATE_ERROR; \
(bp)->panic = 1; \
return -EBUSY; \
} while (0)
-#endif
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+ do { \
+ bp->cnic_loaded = false; \
+ (bp)->panic = 1; \
+ return -EBUSY; \
+ } while (0)
+#endif /*BNX2X_STOP_ON_ERROR*/
bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
{
@@ -1959,10 +2062,8 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
fp->max_cos = 1;
/* Init txdata pointers */
-#ifdef BCM_CNIC
if (IS_FCOE_FP(fp))
fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)];
-#endif
if (IS_ETH_FP(fp))
for_each_cos_in_tx_queue(fp, cos)
fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
@@ -1980,11 +2081,95 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
else if (bp->flags & GRO_ENABLE_FLAG)
fp->mode = TPA_MODE_GRO;
-#ifdef BCM_CNIC
/* We don't want TPA on an FCoE L2 ring */
if (IS_FCOE_FP(fp))
fp->disable_tpa = 1;
-#endif
+}
+
+int bnx2x_load_cnic(struct bnx2x *bp)
+{
+ int i, rc, port = BP_PORT(bp);
+
+ DP(NETIF_MSG_IFUP, "Starting CNIC-related load\n");
+
+ mutex_init(&bp->cnic_mutex);
+
+ rc = bnx2x_alloc_mem_cnic(bp);
+ if (rc) {
+ BNX2X_ERR("Unable to allocate bp memory for cnic\n");
+ LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+ }
+
+ rc = bnx2x_alloc_fp_mem_cnic(bp);
+ if (rc) {
+ BNX2X_ERR("Unable to allocate memory for cnic fps\n");
+ LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+ }
+
+ /* Update the number of queues with the cnic queues */
+ rc = bnx2x_set_real_num_queues(bp, 1);
+ if (rc) {
+ BNX2X_ERR("Unable to set real_num_queues including cnic\n");
+ LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+ }
+
+ /* Add all CNIC NAPI objects */
+ bnx2x_add_all_napi_cnic(bp);
+ DP(NETIF_MSG_IFUP, "cnic napi added\n");
+ bnx2x_napi_enable_cnic(bp);
+
+ rc = bnx2x_init_hw_func_cnic(bp);
+ if (rc)
+ LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic1);
+
+ bnx2x_nic_init_cnic(bp);
+
+ /* Enable Timer scan */
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
+
+ for_each_cnic_queue(bp, i) {
+ rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
+ if (rc) {
+ BNX2X_ERR("Queue setup failed\n");
+ LOAD_ERROR_EXIT(bp, load_error_cnic2);
+ }
+ }
+
+ /* Initialize Rx filter. */
+ netif_addr_lock_bh(bp->dev);
+ bnx2x_set_rx_mode(bp->dev);
+ netif_addr_unlock_bh(bp->dev);
+
+ /* re-read iscsi info */
+ bnx2x_get_iscsi_info(bp);
+ bnx2x_setup_cnic_irq_info(bp);
+ bnx2x_setup_cnic_info(bp);
+ bp->cnic_loaded = true;
+ if (bp->state == BNX2X_STATE_OPEN)
+ bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
+
+
+ DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
+
+ return 0;
+
+#ifndef BNX2X_STOP_ON_ERROR
+load_error_cnic2:
+ /* Disable Timer scan */
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+
+load_error_cnic1:
+ bnx2x_napi_disable_cnic(bp);
+ /* Update the number of queues without the cnic queues */
+ rc = bnx2x_set_real_num_queues(bp, 0);
+ if (rc)
+ BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
+load_error_cnic0:
+ BNX2X_ERR("CNIC-related load failed\n");
+ bnx2x_free_fp_mem_cnic(bp);
+ bnx2x_free_mem_cnic(bp);
+ return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
}
@@ -1995,6 +2180,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
u32 load_code;
int i, rc;
+ DP(NETIF_MSG_IFUP, "Starting NIC load\n");
+ DP(NETIF_MSG_IFUP,
+ "CNIC is %s\n", CNIC_ENABLED(bp) ? "enabled" : "disabled");
+
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic)) {
BNX2X_ERR("Can't load NIC when there is panic\n");
@@ -2022,9 +2211,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
for_each_queue(bp, i)
bnx2x_bz_fp(bp, i);
- memset(bp->bnx2x_txq, 0, bp->bnx2x_txq_size *
- sizeof(struct bnx2x_fp_txdata));
+ memset(bp->bnx2x_txq, 0, (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS +
+ bp->num_cnic_queues) *
+ sizeof(struct bnx2x_fp_txdata));
+ bp->fcoe_init = false;
/* Set the receive queues buffer size */
bnx2x_set_rx_buf_size(bp);
@@ -2034,9 +2225,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* As long as bnx2x_alloc_mem() may possibly update
* bp->num_queues, bnx2x_set_real_num_queues() should always
- * come after it.
+ * come after it. At this stage cnic queues are not counted.
*/
- rc = bnx2x_set_real_num_queues(bp);
+ rc = bnx2x_set_real_num_queues(bp, 0);
if (rc) {
BNX2X_ERR("Unable to set real_num_queues\n");
LOAD_ERROR_EXIT(bp, load_error0);
@@ -2050,6 +2241,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Add all NAPI objects */
bnx2x_add_all_napi(bp);
+ DP(NETIF_MSG_IFUP, "napi added\n");
bnx2x_napi_enable(bp);
/* set pf load just before approaching the MCP */
@@ -2073,7 +2265,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
DRV_PULSE_SEQ_MASK);
BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
- load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
+ DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
@@ -2191,23 +2384,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
LOAD_ERROR_EXIT(bp, load_error3);
}
-#ifdef BCM_CNIC
- /* Enable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
-#endif
-
- for_each_nondefault_queue(bp, i) {
+ for_each_nondefault_eth_queue(bp, i) {
rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
if (rc) {
BNX2X_ERR("Queue setup failed\n");
- LOAD_ERROR_EXIT(bp, load_error4);
+ LOAD_ERROR_EXIT(bp, load_error3);
}
}
rc = bnx2x_init_rss_pf(bp);
if (rc) {
BNX2X_ERR("PF RSS init failed\n");
- LOAD_ERROR_EXIT(bp, load_error4);
+ LOAD_ERROR_EXIT(bp, load_error3);
}
/* Now when Clients are configured we are ready to work */
@@ -2217,7 +2405,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_set_eth_mac(bp, true);
if (rc) {
BNX2X_ERR("Setting Ethernet MAC failed\n");
- LOAD_ERROR_EXIT(bp, load_error4);
+ LOAD_ERROR_EXIT(bp, load_error3);
}
if (bp->pending_max) {
@@ -2227,6 +2415,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
+ bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_BOOT_FROM_SAN;
/* Start fast path */
@@ -2257,21 +2446,15 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
}
if (bp->port.pmf)
- bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_DCB_CONFIGURED, 0);
+ bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_PORT_MASK, 0);
else
bnx2x__link_status_update(bp);
/* start the timer */
mod_timer(&bp->timer, jiffies + bp->current_interval);
-#ifdef BCM_CNIC
- /* re-read iscsi info */
- bnx2x_get_iscsi_info(bp);
- bnx2x_setup_cnic_irq_info(bp);
- bnx2x_setup_cnic_info(bp);
- if (bp->state == BNX2X_STATE_OPEN)
- bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
-#endif
+ if (CNIC_ENABLED(bp))
+ bnx2x_load_cnic(bp);
/* mark driver is loaded in shmem2 */
if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
@@ -2293,14 +2476,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG))
bnx2x_dcbx_init(bp, false);
+ DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n");
+
return 0;
#ifndef BNX2X_STOP_ON_ERROR
-load_error4:
-#ifdef BCM_CNIC
- /* Disable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-#endif
load_error3:
bnx2x_int_disable_sync(bp, 1);
@@ -2338,6 +2518,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
int i;
bool global = false;
+ DP(NETIF_MSG_IFUP, "Starting NIC unload\n");
+
/* mark driver is unloaded in shmem2 */
if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
u32 val;
@@ -2373,14 +2555,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
smp_mb();
+ if (CNIC_LOADED(bp))
+ bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
/* Stop Tx */
bnx2x_tx_disable(bp);
netdev_reset_tc(bp->dev);
-#ifdef BCM_CNIC
- bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
-
bp->rx_mode = BNX2X_RX_MODE_NONE;
del_timer_sync(&bp->timer);
@@ -2414,7 +2595,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
bnx2x_netif_stop(bp, 1);
/* Delete all NAPI objects */
bnx2x_del_all_napi(bp);
-
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
/* Release IRQs */
bnx2x_free_irq(bp);
@@ -2435,12 +2617,19 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_free_skbs_cnic(bp);
for_each_rx_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
+ if (CNIC_LOADED(bp)) {
+ bnx2x_free_fp_mem_cnic(bp);
+ bnx2x_free_mem_cnic(bp);
+ }
bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED;
+ bp->cnic_loaded = false;
/* Check if there are pending parity attentions. If there are - set
* RECOVERY_IN_PROGRESS.
@@ -2460,6 +2649,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp);
+ DP(NETIF_MSG_IFUP, "Ending NIC unload\n");
+
return 0;
}
@@ -2550,7 +2741,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
/* Fall out from the NAPI loop if needed */
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-#ifdef BCM_CNIC
+
/* No need to update SB for FCoE L2 ring as long as
* it's connected to the default SB and the SB
* has been updated when NAPI was scheduled.
@@ -2559,8 +2750,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
napi_complete(napi);
break;
}
-#endif
-
bnx2x_update_fpsb_idx(fp);
/* bnx2x_has_rx_work() reads the status block,
* thus we need to ensure that status block indices
@@ -2940,7 +3129,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
txq_index = skb_get_queue_mapping(skb);
txq = netdev_get_tx_queue(dev, txq_index);
- BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
+ BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + (CNIC_LOADED(bp) ? 1 : 0));
txdata = &bp->bnx2x_txq[txq_index];
@@ -2958,11 +3147,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
BDS_PER_TX_PKT +
NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) {
/* Handle special storage cases separately */
- if (txdata->tx_ring_size != 0) {
- BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
+ if (txdata->tx_ring_size == 0) {
+ struct bnx2x_eth_q_stats *q_stats =
+ bnx2x_fp_qstats(bp, txdata->parent_fp);
+ q_stats->driver_filtered_tx_pkt++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++;
netif_tx_stop_queue(txq);
- }
+ BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
return NETDEV_TX_BUSY;
}
@@ -3339,13 +3533,11 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
return -EINVAL;
}
-#ifdef BCM_CNIC
if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) &&
!is_zero_ether_addr(addr->sa_data)) {
BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n");
return -EINVAL;
}
-#endif
if (netif_running(dev)) {
rc = bnx2x_set_eth_mac(bp, false);
@@ -3369,13 +3561,11 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
u8 cos;
/* Common */
-#ifdef BCM_CNIC
+
if (IS_FCOE_IDX(fp_index)) {
memset(sb, 0, sizeof(union host_hc_status_block));
fp->status_blk_mapping = 0;
-
} else {
-#endif
/* status blocks */
if (!CHIP_IS_E1x(bp))
BNX2X_PCI_FREE(sb->e2_sb,
@@ -3387,9 +3577,8 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
bnx2x_fp(bp, fp_index,
status_blk_mapping),
sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
}
-#endif
+
/* Rx */
if (!skip_rx_queue(bp, fp_index)) {
bnx2x_free_rx_bds(fp);
@@ -3431,10 +3620,17 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
/* end of fastpath */
}
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
+{
+ int i;
+ for_each_cnic_queue(bp, i)
+ bnx2x_free_fp_mem_at(bp, i);
+}
+
void bnx2x_free_fp_mem(struct bnx2x *bp)
{
int i;
- for_each_queue(bp, i)
+ for_each_eth_queue(bp, i)
bnx2x_free_fp_mem_at(bp, i);
}
@@ -3519,14 +3715,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
u8 cos;
int rx_ring_size = 0;
-#ifdef BCM_CNIC
if (!bp->rx_ring_size &&
(IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
rx_ring_size = MIN_RX_SIZE_NONTPA;
bp->rx_ring_size = rx_ring_size;
- } else
-#endif
- if (!bp->rx_ring_size) {
+ } else if (!bp->rx_ring_size) {
rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
if (CHIP_IS_E3(bp)) {
@@ -3550,9 +3743,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
/* Common */
sb = &bnx2x_fp(bp, index, status_blk);
-#ifdef BCM_CNIC
+
if (!IS_FCOE_IDX(index)) {
-#endif
/* status blocks */
if (!CHIP_IS_E1x(bp))
BNX2X_PCI_ALLOC(sb->e2_sb,
@@ -3562,9 +3754,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
BNX2X_PCI_ALLOC(sb->e1x_sb,
&bnx2x_fp(bp, index, status_blk_mapping),
sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
}
-#endif
/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
* set shortcuts for it.
@@ -3641,31 +3831,31 @@ alloc_mem_err:
return 0;
}
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
+{
+ if (!NO_FCOE(bp))
+ /* FCoE */
+ if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
+ /* we will fail load process instead of mark
+ * NO_FCOE_FLAG
+ */
+ return -ENOMEM;
+
+ return 0;
+}
+
int bnx2x_alloc_fp_mem(struct bnx2x *bp)
{
int i;
- /**
- * 1. Allocate FP for leading - fatal if error
- * 2. {CNIC} Allocate FCoE FP - fatal if error
- * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
- * 4. Allocate RSS - fix number of queues if error
+ /* 1. Allocate FP for leading - fatal if error
+ * 2. Allocate RSS - fix number of queues if error
*/
/* leading */
if (bnx2x_alloc_fp_mem_at(bp, 0))
return -ENOMEM;
-#ifdef BCM_CNIC
- if (!NO_FCOE(bp))
- /* FCoE */
- if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
- /* we will fail load process instead of mark
- * NO_FCOE_FLAG
- */
- return -ENOMEM;
-#endif
-
/* RSS */
for_each_nondefault_eth_queue(bp, i)
if (bnx2x_alloc_fp_mem_at(bp, i))
@@ -3676,17 +3866,17 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
WARN_ON(delta < 0);
-#ifdef BCM_CNIC
- /**
- * move non eth FPs next to last eth FP
- * must be done in that order
- * FCOE_IDX < FWD_IDX < OOO_IDX
- */
+ if (CNIC_SUPPORT(bp))
+ /* move non eth FPs next to last eth FP
+ * must be done in that order
+ * FCOE_IDX < FWD_IDX < OOO_IDX
+ */
- /* move FCoE fp even NO_FCOE_FLAG is on */
- bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
-#endif
- bp->num_queues -= delta;
+ /* move FCoE fp even NO_FCOE_FLAG is on */
+ bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
+ bp->num_ethernet_queues -= delta;
+ bp->num_queues = bp->num_ethernet_queues +
+ bp->num_cnic_queues;
BNX2X_ERR("Adjusted num of queues from %d to %d\n",
bp->num_queues + delta, bp->num_queues);
}
@@ -3705,13 +3895,13 @@ void bnx2x_free_mem_bp(struct bnx2x *bp)
kfree(bp->ilt);
}
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
+int bnx2x_alloc_mem_bp(struct bnx2x *bp)
{
struct bnx2x_fastpath *fp;
struct msix_entry *tbl;
struct bnx2x_ilt *ilt;
int msix_table_size = 0;
- int fp_array_size;
+ int fp_array_size, txq_array_size;
int i;
/*
@@ -3721,7 +3911,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
msix_table_size = bp->igu_sb_cnt + 1;
/* fp array: RSS plus CNIC related L2 queues */
- fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE;
+ fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
BNX2X_DEV_INFO("fp_array_size %d", fp_array_size);
fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL);
@@ -3750,12 +3940,12 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
goto alloc_err;
/* Allocate memory for the transmission queues array */
- bp->bnx2x_txq_size = BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS;
-#ifdef BCM_CNIC
- bp->bnx2x_txq_size++;
-#endif
- bp->bnx2x_txq = kcalloc(bp->bnx2x_txq_size,
- sizeof(struct bnx2x_fp_txdata), GFP_KERNEL);
+ txq_array_size =
+ BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + CNIC_SUPPORT(bp);
+ BNX2X_DEV_INFO("txq_array_size %d", txq_array_size);
+
+ bp->bnx2x_txq = kcalloc(txq_array_size, sizeof(struct bnx2x_fp_txdata),
+ GFP_KERNEL);
if (!bp->bnx2x_txq)
goto alloc_err;
@@ -3838,7 +4028,7 @@ int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
return LINK_CONFIG_IDX(sel_phy_idx);
}
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
{
struct bnx2x *bp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 9c5ea6c5b4c7..0991534f61da 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -144,7 +144,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
* @bp: driver handle
* @load_mode: current mode
*/
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
+int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
/**
* bnx2x_link_set - configure hw according to link parameters structure.
@@ -238,7 +238,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
* @dev_instance: private instance
*/
irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
-#ifdef BCM_CNIC
/**
* bnx2x_cnic_notify - send command to cnic driver
@@ -262,8 +261,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
*/
void bnx2x_setup_cnic_info(struct bnx2x *bp);
-#endif
-
/**
* bnx2x_int_enable - enable HW interrupts.
*
@@ -283,7 +280,7 @@ void bnx2x_int_enable(struct bnx2x *bp);
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
/**
- * bnx2x_nic_init - init driver internals.
+ * bnx2x_nic_init_cnic - init driver internals for cnic.
*
* @bp: driver handle
* @load_code: COMMON, PORT or FUNCTION
@@ -293,9 +290,26 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
* - status blocks
* - etc.
*/
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+void bnx2x_nic_init_cnic(struct bnx2x *bp);
/**
+ * bnx2x_nic_init - init driver internals.
+ *
+ * @bp: driver handle
+ *
+ * Initializes:
+ * - rings
+ * - status blocks
+ * - etc.
+ */
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+/**
+ * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic.
+ *
+ * @bp: driver handle
+ */
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp);
+/**
* bnx2x_alloc_mem - allocate driver's memory.
*
* @bp: driver handle
@@ -303,6 +317,12 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
int bnx2x_alloc_mem(struct bnx2x *bp);
/**
+ * bnx2x_free_mem_cnic - release driver's memory for cnic.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_free_mem_cnic(struct bnx2x *bp);
+/**
* bnx2x_free_mem - release driver's memory.
*
* @bp: driver handle
@@ -407,6 +427,7 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
void bnx2x_set_reset_in_progress(struct bnx2x *bp);
void bnx2x_set_reset_global(struct bnx2x *bp);
void bnx2x_disable_close_the_gate(struct bnx2x *bp);
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
/**
* bnx2x_sp_event - handle ramrods completion.
@@ -424,6 +445,14 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
void bnx2x_ilt_set_info(struct bnx2x *bp);
/**
+ * bnx2x_ilt_set_cnic_info - prepare ILT configurations for SRC
+ * and TM.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_ilt_set_info_cnic(struct bnx2x *bp);
+
+/**
* bnx2x_dcbx_init - initialize dcbx protocol.
*
* @bp: driver handle
@@ -491,12 +520,17 @@ int bnx2x_resume(struct pci_dev *pdev);
/* Release IRQ vectors */
void bnx2x_free_irq(struct bnx2x *bp);
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
void bnx2x_free_fp_mem(struct bnx2x *bp);
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
int bnx2x_alloc_fp_mem(struct bnx2x *bp);
void bnx2x_init_rx_rings(struct bnx2x *bp);
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp);
+void bnx2x_free_skbs_cnic(struct bnx2x *bp);
void bnx2x_free_skbs(struct bnx2x *bp);
void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
void bnx2x_netif_start(struct bnx2x *bp);
+int bnx2x_load_cnic(struct bnx2x *bp);
/**
* bnx2x_enable_msix - set msix configuration.
@@ -529,7 +563,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget);
*
* @bp: driver handle
*/
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
+int bnx2x_alloc_mem_bp(struct bnx2x *bp);
/**
* bnx2x_free_mem_bp - release memories outsize main driver structure
@@ -547,7 +581,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
*/
int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
/**
* bnx2x_fcoe_get_wwn - return the requested WWN value for this port
*
@@ -793,23 +827,39 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
sge->addr_lo = 0;
}
-static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
{
int i;
- bp->num_napi_queues = bp->num_queues;
+ /* Add NAPI objects */
+ for_each_rx_queue_cnic(bp, i)
+ netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+ bnx2x_poll, BNX2X_NAPI_WEIGHT);
+}
+
+static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+{
+ int i;
/* Add NAPI objects */
- for_each_rx_queue(bp, i)
+ for_each_eth_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, BNX2X_NAPI_WEIGHT);
}
+static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_rx_queue_cnic(bp, i)
+ netif_napi_del(&bnx2x_fp(bp, i, napi));
+}
+
static inline void bnx2x_del_all_napi(struct bnx2x *bp)
{
int i;
- for_each_rx_queue(bp, i)
+ for_each_eth_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
}
@@ -979,11 +1029,9 @@ static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
{
struct bnx2x *bp = fp->bp;
if (!CHIP_IS_E1x(bp)) {
-#ifdef BCM_CNIC
/* there are special statistics counters for FCoE 136..140 */
if (IS_FCOE_FP(fp))
return bp->cnic_base_cl_id + (bp->pf_num >> 1);
-#endif
return fp->cl_id;
}
return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x;
@@ -1102,7 +1150,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
txdata->cid, txdata->txq_index);
}
-#ifdef BCM_CNIC
static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
{
return bp->cnic_base_cl_id + cl_idx +
@@ -1162,7 +1209,6 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
fp->igu_sb_id);
}
-#endif
static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
struct bnx2x_fp_txdata *txdata)
@@ -1280,7 +1326,7 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
*/
return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
}
-#ifdef BCM_CNIC
+
/**
* bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
*
@@ -1288,7 +1334,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
*
*/
void bnx2x_get_iscsi_info(struct bnx2x *bp);
-#endif
/**
* bnx2x_link_sync_notify - send notification to other functions.
@@ -1340,13 +1385,11 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
{
- if (is_valid_ether_addr(addr))
+ if (is_valid_ether_addr(addr) ||
+ (is_zero_ether_addr(addr) &&
+ (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))))
return true;
-#ifdef BCM_CNIC
- if (is_zero_ether_addr(addr) &&
- (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))
- return true;
-#endif
+
return false;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index 2245c3895409..10bc093d2ca4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -413,8 +413,11 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
{
+ int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+ GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+ 1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
if (bp->dcbx_port_params.pfc.enabled &&
- !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+ (!(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) || mfw_configured))
/*
* 1. Fills up common PFC structures if required
* 2. Configure NIG, MAC and BRB via the elink
@@ -552,10 +555,13 @@ static void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
{
+ int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+ GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+ 1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
if (!bp->dcbx_port_params.ets.enabled ||
- (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+ ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured))
return;
if (CHIP_IS_E3B0(bp))
@@ -1802,11 +1808,14 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
u8 cos = 0, pri = 0;
struct priority_cos *tt2cos;
u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+ int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+ GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+ 1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
/* to disable DCB - the structure must be zeroed */
- if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
+ if ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured)
return;
/*shortcut*/
@@ -1895,6 +1904,11 @@ static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
struct bnx2x *bp = netdev_priv(netdev);
DP(BNX2X_MSG_DCB, "state = %s\n", state ? "on" : "off");
+ if (state && ((bp->dcbx_enabled == BNX2X_DCBX_ENABLED_OFF) ||
+ (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_INVALID))) {
+ DP(BNX2X_MSG_DCB, "Can not set dcbx to enabled while it is disabled in nvm\n");
+ return 1;
+ }
bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
return 0;
}
@@ -1908,10 +1922,10 @@ static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
/* first the HW mac address */
memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
-#ifdef BCM_CNIC
- /* second SAN address */
- memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
-#endif
+ if (CNIC_LOADED(bp))
+ /* second SAN address */
+ memcpy(perm_addr+netdev->addr_len, bp->fip_mac,
+ netdev->addr_len);
}
static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
@@ -2038,10 +2052,13 @@ static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
return;
- bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
- if (setting)
+ if (setting) {
+ bp->dcbx_config_params.admin_pfc_bitmap |= (1 << prio);
bp->dcbx_config_params.admin_pfc_tx_enable = 1;
+ } else {
+ bp->dcbx_config_params.admin_pfc_bitmap &= ~(1 << prio);
+ }
}
static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
@@ -2073,8 +2090,12 @@ static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
"Handling parity error recovery. Try again later\n");
return 1;
}
- if (netif_running(bp->dev))
+ if (netif_running(bp->dev)) {
+ bnx2x_update_drv_flags(bp,
+ 1 << DRV_FLAGS_DCB_MFW_CONFIGURED,
+ 1);
bnx2x_dcbx_init(bp, true);
+ }
DP(BNX2X_MSG_DCB, "set_dcbx_params done (%d)\n", rc);
if (rc)
return 1;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 6e5bdd1a31d9..277f17e3c8f8 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -62,7 +62,9 @@ static const struct {
8, "[%s]: tpa_aggregations" },
{ Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
8, "[%s]: tpa_aggregated_frames"},
- { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"}
+ { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"},
+ { Q_STATS_OFFSET32(driver_filtered_tx_pkt),
+ 4, "[%s]: driver_filtered_tx_pkt" }
};
#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -177,6 +179,8 @@ static const struct {
4, STATS_FLAGS_FUNC, "recoverable_errors" },
{ STATS_OFFSET32(unrecoverable_error),
4, STATS_FLAGS_FUNC, "unrecoverable_errors" },
+ { STATS_OFFSET32(driver_filtered_tx_pkt),
+ 4, STATS_FLAGS_FUNC, "driver_filtered_tx_pkt" },
{ STATS_OFFSET32(eee_tx_lpi),
4, STATS_FLAGS_PORT, "Tx LPI entry count"}
};
@@ -227,18 +231,14 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->advertising &= ~(ADVERTISED_10000baseT_Full);
}
- if ((bp->state == BNX2X_STATE_OPEN) && (bp->link_vars.link_up)) {
- if (!(bp->flags & MF_FUNC_DIS)) {
- ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
+ if ((bp->state == BNX2X_STATE_OPEN) && bp->link_vars.link_up &&
+ !(bp->flags & MF_FUNC_DIS)) {
cmd->duplex = bp->link_vars.duplex;
- } else {
- ethtool_cmd_speed_set(
- cmd, bp->link_params.req_line_speed[cfg_idx]);
- cmd->duplex = bp->link_params.req_duplex[cfg_idx];
- }
if (IS_MF(bp) && !BP_NOMCP(bp))
ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
+ else
+ ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
} else {
cmd->duplex = DUPLEX_UNKNOWN;
ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
@@ -2660,20 +2660,25 @@ static int bnx2x_set_phys_id(struct net_device *dev,
return 1; /* cycle on/off once per second */
case ETHTOOL_ID_ON:
+ bnx2x_acquire_phy_lock(bp);
bnx2x_set_led(&bp->link_params, &bp->link_vars,
LED_MODE_ON, SPEED_1000);
+ bnx2x_release_phy_lock(bp);
break;
case ETHTOOL_ID_OFF:
+ bnx2x_acquire_phy_lock(bp);
bnx2x_set_led(&bp->link_params, &bp->link_vars,
LED_MODE_FRONT_PANEL_OFF, 0);
-
+ bnx2x_release_phy_lock(bp);
break;
case ETHTOOL_ID_INACTIVE:
+ bnx2x_acquire_phy_lock(bp);
bnx2x_set_led(&bp->link_params, &bp->link_vars,
LED_MODE_OPER,
bp->link_vars.line_speed);
+ bnx2x_release_phy_lock(bp);
}
return 0;
@@ -2901,7 +2906,9 @@ static void bnx2x_get_channels(struct net_device *dev,
static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
{
bnx2x_disable_msi(bp);
- BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE;
+ bp->num_ethernet_queues = num_rss;
+ bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
+ BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
bnx2x_set_int_mode(bp);
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 620fe939ecfd..60a83ad10370 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -23,6 +23,11 @@
(IRO[159].base + ((funcId) * IRO[159].m1))
#define CSTORM_FUNC_EN_OFFSET(funcId) \
(IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hcIndex, sbId) \
+ (IRO[139].base + ((hcIndex) * IRO[139].m1) + ((sbId) * IRO[139].m2))
+#define CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hcIndex, sbId) \
+ (IRO[138].base + (((hcIndex)>>2) * IRO[138].m1) + (((hcIndex)&3) \
+ * IRO[138].m2) + ((sbId) * IRO[138].m3))
#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
(IRO[316].base + ((pfId) * IRO[316].m1))
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 18704929e642..3369a50ac6b4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -500,7 +500,15 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u32 e3_cmn_pin_cfg1; /* 0x170 */
#define PORT_HW_CFG_E3_OVER_CURRENT_MASK 0x000000FF
#define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT 0
- u32 reserved0[7]; /* 0x174 */
+
+ /* pause on host ring */
+ u32 generic_features; /* 0x174 */
+ #define PORT_HW_CFG_PAUSE_ON_HOST_RING_MASK 0x00000001
+ #define PORT_HW_CFG_PAUSE_ON_HOST_RING_SHIFT 0
+ #define PORT_HW_CFG_PAUSE_ON_HOST_RING_DISABLED 0x00000000
+ #define PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED 0x00000001
+
+ u32 reserved0[6]; /* 0x178 */
u32 aeu_int_mask; /* 0x190 */
@@ -695,6 +703,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE 0x00000e00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722 0x00000f00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616 0x00001000
+ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84834 0x00001100
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
@@ -751,6 +760,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE 0x00000e00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722 0x00000f00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616 0x00001000
+ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834 0x00001100
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
@@ -1246,6 +1256,7 @@ struct drv_func_mb {
#define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED 0xa2000000
#define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED 0x00070002
#define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014
+ #define REQ_BC_VER_4_MT_SUPPORTED 0x00070201
#define REQ_BC_VER_4_PFC_STATS_SUPPORTED 0x00070201
#define REQ_BC_VER_4_FCOE_FEATURES 0x00070209
@@ -1515,12 +1526,13 @@ enum mf_cfg_afex_vlan_mode {
/* This structure is not applicable and should not be accessed on 57711 */
struct func_ext_cfg {
u32 func_cfg;
- #define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF
+ #define MACP_FUNC_CFG_FLAGS_MASK 0x0000007F
#define MACP_FUNC_CFG_FLAGS_SHIFT 0
#define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001
#define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002
#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004
#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008
+ #define MACP_FUNC_CFG_PAUSE_ON_HOST_RING 0x00000080
u32 iscsi_mac_addr_upper;
u32 iscsi_mac_addr_lower;
@@ -2085,8 +2097,13 @@ struct shmem2_region {
/* generic flags controlled by the driver */
u32 drv_flags;
- #define DRV_FLAGS_DCB_CONFIGURED 0x1
+ #define DRV_FLAGS_DCB_CONFIGURED 0x0
+ #define DRV_FLAGS_DCB_CONFIGURATION_ABORTED 0x1
+ #define DRV_FLAGS_DCB_MFW_CONFIGURED 0x2
+ #define DRV_FLAGS_PORT_MASK ((1 << DRV_FLAGS_DCB_CONFIGURED) | \
+ (1 << DRV_FLAGS_DCB_CONFIGURATION_ABORTED) | \
+ (1 << DRV_FLAGS_DCB_MFW_CONFIGURED))
/* pointer to extended dev_info shared data copied from nvm image */
u32 extended_dev_info_shared_addr;
u32 ncsi_oem_data_addr;
@@ -2159,6 +2176,16 @@ struct shmem2_region {
#define SHMEM_EEE_TIME_OUTPUT_BIT 0x80000000
u32 sizeof_port_stats;
+
+ /* Link Flap Avoidance */
+ u32 lfa_host_addr[PORT_MAX];
+ u32 reserved1;
+
+ u32 reserved2; /* Offset 0x148 */
+ u32 reserved3; /* Offset 0x14C */
+ u32 reserved4; /* Offset 0x150 */
+ u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */
+ #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0)
};
@@ -4845,9 +4872,17 @@ struct vif_list_event_data {
__le32 reserved2;
};
-/*
- * union for all event ring message types
- */
+/* function update event data */
+struct function_update_event_data {
+ u8 echo;
+ u8 reserved;
+ __le16 reserved0;
+ __le32 reserved1;
+ __le32 reserved2;
+};
+
+
+/* union for all event ring message types */
union event_data {
struct vf_pf_event_data vf_pf_event;
struct eth_event_data eth_event;
@@ -4855,6 +4890,7 @@ union event_data {
struct vf_flr_event_data vf_flr_event;
struct malicious_vf_event_data malicious_vf_event;
struct vif_list_event_data vif_list_event;
+ struct function_update_event_data function_update_event;
};
@@ -4984,8 +5020,10 @@ struct function_update_data {
u8 allowed_priorities;
u8 network_cos_mode;
u8 lb_mode_en;
- u8 reserved0;
- __le32 reserved1;
+ u8 tx_switch_suspend_change_flg;
+ u8 tx_switch_suspend;
+ u8 echo;
+ __le16 reserved1;
};
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
index fe66d902dc62..d755acfe7a40 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
@@ -648,15 +648,25 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
return rc;
}
+static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop)
+{
+ int rc = 0;
+
+ if (CONFIGURE_NIC_MODE(bp))
+ rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
+ if (!rc)
+ rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
+
+ return rc;
+}
+
static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
{
int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
if (!rc)
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
- if (!rc)
+ if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
- if (!rc)
- rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
return rc;
}
@@ -781,12 +791,19 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
}
+static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop)
+{
+ if (CONFIGURE_NIC_MODE(bp))
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+}
+
static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
{
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
- bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
- bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+ if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
}
static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
@@ -890,7 +907,6 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
/****************************************************************************
* SRC initializations
****************************************************************************/
-#ifdef BCM_CNIC
/* called during init func stage */
static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
dma_addr_t t2_mapping, int src_cid_count)
@@ -915,5 +931,4 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
U64_HI((u64)t2_mapping +
(src_cid_count-1) * sizeof(struct src_ent)));
}
-#endif
#endif /* BNX2X_INIT_OPS_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index f6cfdc6cf20f..09096b43a6e9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -121,6 +121,7 @@
#define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
#define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
#define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
+#define GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2
#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -253,6 +254,12 @@ static int bnx2x_check_lfa(struct link_params *params)
if (!(link_status & LINK_STATUS_LINK_UP))
return LFA_LINK_DOWN;
+ /* if loaded after BOOT from SAN, don't flap the link in any case and
+ * rely on link set by preboot driver
+ */
+ if (params->feature_config_flags & FEATURE_CONFIG_BOOT_FROM_SAN)
+ return 0;
+
/* Verify that loopback mode is not set */
if (params->loopback_mode)
return LFA_LOOPBACK_ENABLED;
@@ -1440,30 +1447,47 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
/******************************************************************/
/* MAC/PBF section */
/******************************************************************/
-static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id,
+ u32 emac_base)
{
- u32 mode, emac_base;
+ u32 new_mode, cur_mode;
+ u32 clc_cnt;
/* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
+ cur_mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
- if (CHIP_IS_E2(bp))
- emac_base = GRCBASE_EMAC0;
- else
- emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
- mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
- mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
- EMAC_MDIO_MODE_CLOCK_CNT);
if (USES_WARPCORE(bp))
- mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+ clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
else
- mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+ clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
- mode |= (EMAC_MDIO_MODE_CLAUSE_45);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+ if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) &&
+ (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
+ return;
+ new_mode = cur_mode &
+ ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+ new_mode |= clc_cnt;
+ new_mode |= (EMAC_MDIO_MODE_CLAUSE_45);
+
+ DP(NETIF_MSG_LINK, "Changing emac_mode from 0x%x to 0x%x\n",
+ cur_mode, new_mode);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode);
udelay(40);
}
+
+static void bnx2x_set_mdio_emac_per_phy(struct bnx2x *bp,
+ struct link_params *params)
+{
+ u8 phy_index;
+ /* Set mdio clock per phy */
+ for (phy_index = INT_PHY; phy_index < params->num_phys;
+ phy_index++)
+ bnx2x_set_mdio_clk(bp, params->chip_id,
+ params->phy[phy_index].mdio_ctrl);
+}
+
static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
{
u32 port4mode_ovwr_val;
@@ -1508,7 +1532,8 @@ static void bnx2x_emac_init(struct link_params *params,
}
timeout--;
} while (val & EMAC_MODE_RESET);
- bnx2x_set_mdio_clk(bp, params->chip_id, port);
+
+ bnx2x_set_mdio_emac_per_phy(bp, params);
/* Set mac address */
val = ((params->mac_addr[0] << 8) |
params->mac_addr[1]);
@@ -1664,7 +1689,10 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
* ports of the path
*/
- if ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) &&
+ if (((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) ||
+ (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) ||
+ (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE)) &&
+ is_port4mode &&
(REG_RD(bp, MISC_REG_RESET_REG_2) &
MISC_REGISTERS_RESET_REG_2_XMAC)) {
DP(NETIF_MSG_LINK,
@@ -1760,6 +1788,18 @@ static int bnx2x_xmac_enable(struct link_params *params,
*/
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
+ /* When XMAC is in XLGMII mode, disable sending idles for fault
+ * detection.
+ */
+ if (!(params->phy[INT_PHY].flags & FLAGS_TX_ERROR_CHECK)) {
+ REG_WR(bp, xmac_base + XMAC_REG_RX_LSS_CTRL,
+ (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE |
+ XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE));
+ REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
+ REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
+ XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
+ XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
+ }
/* Set Max packet size */
REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
@@ -1780,6 +1820,12 @@ static int bnx2x_xmac_enable(struct link_params *params,
/* Enable TX and RX */
val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
+ /* Set MAC in XLGMII mode for dual-mode */
+ if ((vars->line_speed == SPEED_20000) &&
+ (params->phy[INT_PHY].supported &
+ SUPPORTED_20000baseKR2_Full))
+ val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB;
+
/* Check loopback mode */
if (lb)
val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
@@ -2096,6 +2142,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
port_mb[params->port].link_status), link_status);
}
+static void bnx2x_update_link_attr(struct link_params *params, u32 link_attr)
+{
+ struct bnx2x *bp = params->bp;
+
+ if (SHMEM2_HAS(bp, link_attr_sync))
+ REG_WR(bp, params->shmem2_base +
+ offsetof(struct shmem2_region,
+ link_attr_sync[params->port]), link_attr);
+}
+
static void bnx2x_update_pfc_nig(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *nig_params)
@@ -2126,7 +2182,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
if (CHIP_IS_E3(bp))
ppp_enable = 0;
else
- ppp_enable = 1;
+ ppp_enable = 1;
xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
xcm_out_en = 0;
@@ -2247,7 +2303,6 @@ int bnx2x_update_pfc(struct link_params *params,
return bnx2x_status;
}
-
static int bnx2x_bmac1_enable(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
@@ -2651,6 +2706,13 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
u32 val;
u16 i;
int rc = 0;
+ u32 chip_id;
+ if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+ chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+ ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+ bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+ }
+
if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
EMAC_MDIO_STATUS_10MB);
@@ -2719,6 +2781,13 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
u32 tmp;
u8 i;
int rc = 0;
+ u32 chip_id;
+ if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+ chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+ ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+ bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+ }
+
if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
EMAC_MDIO_STATUS_10MB);
@@ -3147,6 +3216,15 @@ static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
}
+static void bnx2x_cl45_read_and_write(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 and_val)
+{
+ u16 val;
+ bnx2x_cl45_read(bp, phy, devad, reg, &val);
+ bnx2x_cl45_write(bp, phy, devad, reg, val & and_val);
+}
+
int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
u8 devad, u16 reg, u16 *ret_val)
{
@@ -3551,6 +3629,44 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
* init configuration, and set/clear SGMII flag. Internal
* phy init is done purely in phy_init stage.
*/
+static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 i;
+ static struct bnx2x_reg_set reg_set[] = {
+ /* Step 1 - Program the TX/RX alignment markers */
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537},
+ /* Step 2 - Configure the NP registers */
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620}
+ };
+ DP(NETIF_MSG_LINK, "Enabling 20G-KR2\n");
+
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6));
+
+ for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+ bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+ reg_set[i].val);
+
+ /* Start KR2 work-around timer which handles BCM8073 link-parner */
+ vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
+ bnx2x_update_link_attr(params, vars->link_attr_sync);
+}
static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
struct link_params *params)
@@ -3564,6 +3680,21 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
}
+static void bnx2x_warpcore_restart_AN_KR(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ /* Restart autoneg on the leading lane only */
+ struct bnx2x *bp = params->bp;
+ u16 lane = bnx2x_get_warpcore_lane(phy, params);
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, lane);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+
+ /* Restore AER */
+ bnx2x_set_aer_mmd(params, phy);
+}
+
static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars) {
@@ -3576,7 +3707,9 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
/* Disable Autoneg: re-enable it after adv is done. */
- {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0}
+ {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0},
+ {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0},
};
DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
/* Set to default registers that may be overriden by 10G force */
@@ -3585,11 +3718,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
reg_set[i].val);
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
- cl72_ctrl &= 0xf8ff;
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+ cl72_ctrl &= 0x08ff;
cl72_ctrl |= 0x3800;
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
/* Check adding advertisement for 1G KX */
if (((vars->line_speed == SPEED_AUTO_NEG) &&
@@ -3624,6 +3757,16 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
(0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
(0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+ /* Configure the next lane if dual mode */
+ if (phy->flags & FLAGS_WC_DUAL_MODE)
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
+ ((0x02 <<
+ MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ (0x06 <<
+ MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+ (0x09 <<
+ MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
0x03f0);
@@ -3670,10 +3813,26 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
- /* Enable Autoneg */
- bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
- MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
+ (phy->req_line_speed == SPEED_20000)) {
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, lane);
+
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane),
+ (1<<11));
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
+ bnx2x_set_aer_mmd(params, phy);
+
+ bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+ }
+
+ /* Enable Autoneg: only on the main lane */
+ bnx2x_warpcore_restart_AN_KR(phy, params);
}
static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
@@ -3692,9 +3851,7 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
/* Leave cl72 training enable, needed for KR */
- {MDIO_PMA_DEVAD,
- MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
- 0x2}
+ {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}
};
for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
@@ -3764,27 +3921,21 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
/* Disable 100FX Enable and Auto-Detect */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_FX100_CTRL1, &val);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_FX100_CTRL1, 0xFFFA);
/* Disable 100FX Idle detect */
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_FX100_CTRL3, 0x0080);
/* Set Block address to Remote PHY & Clear forced_speed[5] */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_DIGITAL4_MISC3, &val);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F);
/* Turn off auto-detect & fiber mode */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
- (val & 0xFFEE));
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+ 0xFFEE);
/* Set filter_force_link, disable_false_link and parallel_detect */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -3846,22 +3997,65 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
/* Release tx_fifo_reset */
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3,
+ 0xFFFE);
+ /* Release rxSeqStart */
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF);
+}
+
+static void bnx2x_warpcore_set_20G_force_KR2(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u16 val;
+ struct bnx2x *bp = params->bp;
+ /* Set global registers, so set AER lane to 0 */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+
+ /* Disable sequencer */
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13));
+
+ bnx2x_set_aer_mmd(params, phy);
+
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1));
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CTRL, 0);
+ /* Turn off CL73 */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+ MDIO_WC_REG_CL73_USERB0_CTRL, &val);
+ val &= ~(1<<5);
+ val |= (1<<6);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+ MDIO_WC_REG_CL73_USERB0_CTRL, val);
+
+ /* Set 20G KR2 force speed */
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
+
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL4_MISC3, (1<<7));
- /* Release rxSeqStart */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val);
+ val &= ~(3<<14);
+ val |= (1<<15);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
-}
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
-static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
- struct bnx2x_phy *phy)
-{
- DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+ /* Enable sequencer (over lane 0) */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13));
+
+ bnx2x_set_aer_mmd(params, phy);
}
static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
@@ -3931,20 +4125,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
u16 val16, digctrl_kx1, digctrl_kx2;
/* Clear XFI clock comp in non-10G single lane mode. */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_RX66_CONTROL, &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, ~(3<<13));
bnx2x_warpcore_set_lpi_passthrough(phy, params);
if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) {
/* SGMII Autoneg */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
- val16 | 0x1000);
+ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+ 0x1000);
DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
} else {
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4086,7 +4276,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
(cfg_pin > PIN_CFG_GPIO3_P1)) {
DP(NETIF_MSG_LINK,
- "ERROR: Invalid cfg pin %x for module detect indication\n",
+ "No cfg pin %x for module detect indication\n",
cfg_pin);
return -EINVAL;
}
@@ -4097,7 +4287,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
*gpio_num = MISC_REGISTERS_GPIO_3;
*gpio_port = port;
}
- DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+
return 0;
}
@@ -4120,7 +4310,7 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
return 0;
}
static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
- struct link_params *params)
+ struct link_params *params)
{
u16 gp2_status_reg0, lane;
struct bnx2x *bp = params->bp;
@@ -4134,8 +4324,8 @@ static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
}
static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u32 serdes_net_if;
@@ -4163,7 +4353,7 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
case PORT_HW_CFG_NET_SERDES_IF_KR:
/* Do we get link yet? */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
- &gp_status1);
+ &gp_status1);
lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
/*10G KR*/
lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
@@ -4215,6 +4405,27 @@ static void bnx2x_warpcore_config_sfi(struct bnx2x_phy *phy,
}
}
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 tx_en)
+{
+ struct bnx2x *bp = params->bp;
+ u32 cfg_pin;
+ u8 port = params->port;
+
+ cfg_pin = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+ PORT_HW_CFG_E3_TX_LASER_MASK;
+ /* Set the !tx_en since this pin is DISABLE_TX_LASER */
+ DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+
+ /* For 20G, the expected pin to be used is 3 pins after the current */
+ bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+ bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
+
static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
@@ -4275,9 +4486,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
break;
case PORT_HW_CFG_NET_SERDES_IF_SFI:
- /* Issue Module detection */
+ /* Issue Module detection if module is plugged, or
+ * enabled transmitter to avoid current leakage in case
+ * no module is connected
+ */
if (bnx2x_is_sfp_module_plugged(phy, params))
bnx2x_sfp_module_detection(phy, params);
+ else
+ bnx2x_sfp_e3_set_transmitter(params, phy, 1);
bnx2x_warpcore_config_sfi(phy, params);
break;
@@ -4293,16 +4509,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
bnx2x_sfp_module_detection(phy, params);
break;
-
case PORT_HW_CFG_NET_SERDES_IF_KR2:
- if (vars->line_speed != SPEED_20000) {
- DP(NETIF_MSG_LINK, "Speed not supported yet\n");
- return;
+ if (!params->loopback_mode) {
+ bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+ } else {
+ DP(NETIF_MSG_LINK, "Setting KR 20G-Force\n");
+ bnx2x_warpcore_set_20G_force_KR2(phy, params);
}
- DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
- bnx2x_warpcore_set_20G_KR2(bp, phy);
break;
-
default:
DP(NETIF_MSG_LINK,
"Unsupported Serdes Net Interface 0x%x\n",
@@ -4316,68 +4530,35 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Exit config init\n");
}
-static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
- struct bnx2x_phy *phy,
- u8 tx_en)
-{
- struct bnx2x *bp = params->bp;
- u32 cfg_pin;
- u8 port = params->port;
-
- cfg_pin = REG_RD(bp, params->shmem_base +
- offsetof(struct shmem_region,
- dev_info.port_hw_config[port].e3_sfp_ctrl)) &
- PORT_HW_CFG_TX_LASER_MASK;
- /* Set the !tx_en since this pin is DISABLE_TX_LASER */
- DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
- /* For 20G, the expected pin to be used is 3 pins after the current */
-
- bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
- if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
- bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
-}
-
static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 val16, lane;
bnx2x_sfp_e3_set_transmitter(params, phy, 0);
- bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+ bnx2x_set_mdio_emac_per_phy(bp, params);
bnx2x_set_aer_mmd(params, phy);
/* Global register */
bnx2x_warpcore_reset_lane(bp, phy, 1);
/* Clear loopback settings (if any) */
/* 10G & 20G */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
- 0xBFFF);
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF);
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe);
/* Update those 1-copy registers */
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, 0);
/* Enable 1G MDIO (1-copy) */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
- &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
- val16 & ~0x10);
-
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_XGXSBLK1_LANECTRL2,
- val16 & 0xff00);
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+ ~0x10);
+ bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00);
lane = bnx2x_get_warpcore_lane(phy, params);
/* Disable CL36 PCS Tx */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4413,8 +4594,9 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
params->loopback_mode, phy->req_line_speed);
- if (phy->req_line_speed < SPEED_10000) {
- /* 10/100/1000 */
+ if (phy->req_line_speed < SPEED_10000 ||
+ phy->supported & SUPPORTED_20000baseKR2_Full) {
+ /* 10/100/1000/20G-KR2 */
/* Update those 1-copy registers */
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
@@ -4427,18 +4609,20 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
lane = bnx2x_get_warpcore_lane(phy, params);
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+ val16 |= (1<<lane);
+ if (phy->flags & FLAGS_WC_DUAL_MODE)
+ val16 |= (2<<lane);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_XGXSBLK1_LANECTRL2,
- val16 | (1<<lane));
+ MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+ val16);
/* Switch back to 4-copy registers */
bnx2x_set_aer_mmd(params, phy);
} else {
- /* 10G & 20G */
+ /* 10G / 20G-DXGXS */
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
0x4000);
-
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
}
@@ -4603,6 +4787,10 @@ void bnx2x_link_status_update(struct link_params *params,
params->feature_config_flags &=
~FEATURE_CONFIG_PFC_ENABLED;
+ if (SHMEM2_HAS(bp, link_attr_sync))
+ vars->link_attr_sync = SHMEM2_RD(bp,
+ link_attr_sync[params->port]);
+
DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
@@ -5332,6 +5520,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
vars->link_status |= LINK_10GTFD;
break;
case GP_STATUS_20G_DXGXS:
+ case GP_STATUS_20G_KR2:
vars->line_speed = SPEED_20000;
vars->link_status |= LINK_20GTFD;
break;
@@ -5439,7 +5628,15 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
int rc = 0;
lane = bnx2x_get_warpcore_lane(phy, params);
/* Read gp_status */
- if (phy->req_line_speed > SPEED_10000) {
+ if ((params->loopback_mode) &&
+ (phy->flags & FLAGS_WC_DUAL_MODE)) {
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+ link_up &= 0x1;
+ } else if ((phy->req_line_speed > SPEED_10000) &&
+ (phy->supported & SUPPORTED_20000baseMLD2_Full)) {
u16 temp_link_up;
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
1, &temp_link_up);
@@ -5452,12 +5649,22 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
bnx2x_ext_phy_resolve_fc(phy, params, vars);
} else {
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+ MDIO_WC_REG_GP2_STATUS_GP_2_1,
+ &gp_status1);
DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
- /* Check for either KR or generic link up. */
- gp_status1 = ((gp_status1 >> 8) & 0xf) |
- ((gp_status1 >> 12) & 0xf);
- link_up = gp_status1 & (1 << lane);
+ /* Check for either KR, 1G, or AN up. */
+ link_up = ((gp_status1 >> 8) |
+ (gp_status1 >> 12) |
+ (gp_status1)) &
+ (1 << lane);
+ if (phy->supported & SUPPORTED_20000baseKR2_Full) {
+ u16 an_link;
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_STATUS, &an_link);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_STATUS, &an_link);
+ link_up |= (an_link & (1<<2));
+ }
if (link_up && SINGLE_MEDIA_DIRECT(params)) {
u16 pd, gp_status4;
if (phy->req_line_speed == SPEED_AUTO_NEG) {
@@ -5522,7 +5729,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
if ((lane & 1) == 0)
gp_speed <<= 8;
gp_speed &= 0x3f00;
-
+ link_up = !!link_up;
rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
duplex);
@@ -6683,7 +6890,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
} else if (prev_line_speed != vars->line_speed) {
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
0);
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
}
@@ -6753,7 +6960,7 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
{
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
}
@@ -6894,7 +7101,7 @@ static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
} while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
((fw_msgout & 0xff) != 0x03 && (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
@@ -7604,13 +7811,12 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
return 0;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
return -EINVAL;
}
static void bnx2x_warpcore_power_module(struct link_params *params,
- struct bnx2x_phy *phy,
u8 power)
{
u32 pin_cfg;
@@ -7652,10 +7858,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
addr32 = addr & (~0x3);
do {
if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
- bnx2x_warpcore_power_module(params, phy, 0);
+ bnx2x_warpcore_power_module(params, 0);
/* Note that 100us are not enough here */
usleep_range(1000, 2000);
- bnx2x_warpcore_power_module(params, phy, 1);
+ bnx2x_warpcore_power_module(params, 1);
}
rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
data_array);
@@ -7715,7 +7921,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
/* Wait appropriate time for two-wire command to finish before
* polling the status register
*/
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
/* Wait up to 500us for command complete status */
for (i = 0; i < 100; i++) {
@@ -7751,7 +7957,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
return 0;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
return -EINVAL;
@@ -7786,9 +7992,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u32 sync_offset = 0, phy_idx, media_types;
- u8 val[2], check_limiting_mode = 0;
+ u8 gport, val[2], check_limiting_mode = 0;
*edc_mode = EDC_MODE_LIMITING;
-
phy->media_type = ETH_PHY_UNSPECIFIED;
/* First check for copper cable */
if (bnx2x_read_sfp_module_eeprom(phy,
@@ -7843,8 +8048,15 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
SFP_EEPROM_COMP_CODE_LR_MASK |
SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
DP(NETIF_MSG_LINK, "1G Optic module detected\n");
+ gport = params->port;
phy->media_type = ETH_PHY_SFP_1G_FIBER;
phy->req_line_speed = SPEED_1000;
+ if (!CHIP_IS_E1x(bp))
+ gport = BP_PATH(bp) + (params->port << 1);
+ netdev_err(bp->dev, "Warning: Link speed was forced to 1000Mbps."
+ " Current SFP module in port %d is not"
+ " compliant with 10G Ethernet\n",
+ gport);
} else {
int idx, cfg_idx = 0;
DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -8241,7 +8453,7 @@ static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
struct link_params *params)
{
struct bnx2x *bp = params->bp;
- bnx2x_warpcore_power_module(params, phy, 0);
+ bnx2x_warpcore_power_module(params, 0);
/* Put Warpcore in low power mode */
REG_WR(bp, MISC_REG_WC0_RESET, 0x0c0e);
@@ -8264,7 +8476,7 @@ static void bnx2x_power_sfp_module(struct link_params *params,
bnx2x_8727_power_module(params->bp, phy, power);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- bnx2x_warpcore_power_module(params, phy, power);
+ bnx2x_warpcore_power_module(params, power);
break;
default:
break;
@@ -8337,7 +8549,8 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].config));
-
+ /* Enabled transmitter by default */
+ bnx2x_sfp_set_transmitter(params, phy, 1);
DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
params->port);
/* Power up module */
@@ -8370,14 +8583,12 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
*/
bnx2x_set_limiting_mode(params, phy, edc_mode);
- /* Enable transmit for this module if the module is approved, or
- * if unapproved modules should also enable the Tx laser
+ /* Disable transmit for this module if the module is not approved, and
+ * laser needs to be disabled.
*/
- if (rc == 0 ||
- (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
- bnx2x_sfp_set_transmitter(params, phy, 1);
- else
+ if ((rc) &&
+ ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER))
bnx2x_sfp_set_transmitter(params, phy, 0);
return rc;
@@ -8389,11 +8600,13 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
struct bnx2x_phy *phy;
u32 gpio_val;
u8 gpio_num, gpio_port;
- if (CHIP_IS_E3(bp))
+ if (CHIP_IS_E3(bp)) {
phy = &params->phy[INT_PHY];
- else
+ /* Always enable TX laser,will be disabled in case of fault */
+ bnx2x_sfp_set_transmitter(params, phy, 1);
+ } else {
phy = &params->phy[EXT_PHY1];
-
+ }
if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
params->port, &gpio_num, &gpio_port) ==
-EINVAL) {
@@ -8409,7 +8622,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
/* Call the handling function in case module is detected */
if (gpio_val == 0) {
- bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+ bnx2x_set_mdio_emac_per_phy(bp, params);
bnx2x_set_aer_mmd(params, phy);
bnx2x_power_sfp_module(params, phy, 1);
@@ -8438,10 +8651,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
}
} else {
- u32 val = REG_RD(bp, params->shmem_base +
- offsetof(struct shmem_region, dev_info.
- port_feature_config[params->port].
- config));
bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
gpio_port);
@@ -8449,10 +8658,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
* Disable transmit for this module
*/
phy->media_type = ETH_PHY_NOT_PRESENT;
- if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
- CHIP_IS_E3(bp))
- bnx2x_sfp_set_transmitter(params, phy, 0);
}
}
@@ -9192,6 +9397,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
+ bnx2x_8727_power_module(params->bp, phy, 0);
return 0;
}
} /* Over current check */
@@ -9296,20 +9502,28 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
struct bnx2x *bp,
u8 port)
{
- u16 val, fw_ver1, fw_ver2, cnt;
+ u16 val, fw_ver2, cnt, i;
+ static struct bnx2x_reg_set reg_set[] = {
+ {MDIO_PMA_DEVAD, 0xA819, 0x0014},
+ {MDIO_PMA_DEVAD, 0xA81A, 0xc200},
+ {MDIO_PMA_DEVAD, 0xA81B, 0x0000},
+ {MDIO_PMA_DEVAD, 0xA81C, 0x0300},
+ {MDIO_PMA_DEVAD, 0xA817, 0x0009}
+ };
+ u16 fw_ver1;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+ (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
phy->ver_addr);
} else {
/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
/* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+ for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set);
+ i++)
+ bnx2x_cl45_write(bp, phy, reg_set[i].devad,
+ reg_set[i].reg, reg_set[i].val);
for (cnt = 0; cnt < 100; cnt++) {
bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
@@ -9357,8 +9571,16 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
static void bnx2x_848xx_set_led(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
- u16 val, offset;
-
+ u16 val, offset, i;
+ static struct bnx2x_reg_set reg_set[] = {
+ {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
+ {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
+ {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
+ {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
+ {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
+ MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
+ {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
+ };
/* PHYC_CTL_LED_CTL */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
@@ -9370,49 +9592,20 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LINK_SIGNAL, val);
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED1_MASK,
- 0x80);
-
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED2_MASK,
- 0x18);
-
- /* Select activity source by Tx and Rx, as suggested by PHY AE */
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_MASK,
- 0x0006);
-
- /* Select the closest activity blink rate to that in 10/100/1000 */
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_BLINK,
- 0);
-
- /* Configure the blink rate to ~15.9 Hz */
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
- MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ);
+ for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+ bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+ reg_set[i].val);
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+ (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
else
offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
- bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, offset, &val);
- val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
- bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD, offset, val);
-
- /* 'Interrupt Mask' */
- bnx2x_cl45_write(bp, phy,
- MDIO_AN_DEVAD,
- 0xFFFB, 0xFFFD);
+ /* stretch_en for LED3*/
+ bnx2x_cl45_read_or_write(bp, phy,
+ MDIO_PMA_DEVAD, offset,
+ MDIO_PMA_REG_84823_LED3_STRETCH_EN);
}
static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
@@ -9422,7 +9615,8 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
switch (action) {
case PHY_INIT:
- if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+ (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
}
@@ -9443,7 +9637,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
+ u16 autoneg_val, an_1000_val, an_10_100_val;
bnx2x_848xx_specific_func(phy, params, PHY_INIT);
bnx2x_cl45_write(bp, phy,
@@ -9542,11 +9736,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
if (phy->req_duplex == DUPLEX_FULL)
autoneg_val |= (1<<8);
- /* Always write this if this is not 84833.
- * For 84833, write it only when it's a forced speed.
+ /* Always write this if this is not 84833/4.
+ * For 84833/4, write it only when it's a forced speed.
*/
- if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
- ((autoneg_val & (1<<12)) == 0))
+ if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+ (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) ||
+ ((autoneg_val & (1<<12)) == 0))
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
@@ -9558,14 +9753,11 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Advertising 10G\n");
/* Restart autoneg for 10G*/
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
- &an_10g_val);
- bnx2x_cl45_write(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
- an_10g_val | 0x1000);
+ bnx2x_cl45_read_or_write(
+ bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+ 0x1000);
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
0x3200);
@@ -9598,9 +9790,8 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
#define PHY84833_CMDHDLR_WAIT 300
#define PHY84833_CMDHDLR_MAX_ARGS 5
static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
- struct link_params *params,
- u16 fw_cmd,
- u16 cmd_args[], int argc)
+ struct link_params *params, u16 fw_cmd,
+ u16 cmd_args[], int argc)
{
int idx;
u16 val;
@@ -9614,7 +9805,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
MDIO_84833_CMD_HDLR_STATUS, &val);
if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
break;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
if (idx >= PHY84833_CMDHDLR_WAIT) {
DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
@@ -9635,7 +9826,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
break;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
if ((idx >= PHY84833_CMDHDLR_WAIT) ||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
@@ -9654,7 +9845,6 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
return 0;
}
-
static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
@@ -9802,11 +9992,11 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
u8 port, initialize = 1;
u16 val;
- u32 actual_phy_selection, cms_enable;
+ u32 actual_phy_selection;
u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
int rc = 0;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
if (!(CHIP_IS_E1x(bp)))
port = BP_PATH(bp);
@@ -9828,7 +10018,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
/* Wait for GPHY to come out of reset */
msleep(50);
- if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+ (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
/* BCM84823 requires that XGXS links up first @ 10G for normal
* behavior.
*/
@@ -9884,7 +10075,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
params->multi_phy_config, val);
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+ (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
bnx2x_84833_pair_swap_cfg(phy, params, vars);
/* Keep AutogrEEEn disabled. */
@@ -9904,7 +10096,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
/* 84833 PHY has a better feature and doesn't need to support this. */
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
- cms_enable = REG_RD(bp, params->shmem_base +
+ u32 cms_enable = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region,
dev_info.port_hw_config[params->port].default_cfg)) &
PORT_HW_CFG_ENABLE_CMS_MASK;
@@ -9933,7 +10125,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
return rc;
}
- if ((params->req_duplex[actual_phy_selection] == DUPLEX_FULL) &&
+ if ((phy->req_duplex == DUPLEX_FULL) &&
(params->eee_mode & EEE_MODE_ADV_LPI) &&
(bnx2x_eee_calc_timer(params) ||
!(params->eee_mode & EEE_MODE_ENABLE_LPI)))
@@ -9948,15 +10140,13 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
}
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+ (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
/* Bring PHY out of super isolate mode as the final step. */
- bnx2x_cl45_read(bp, phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
- val &= ~MDIO_84833_SUPER_ISOLATE;
- bnx2x_cl45_write(bp, phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+ bnx2x_cl45_read_and_write(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1,
+ (u16)~MDIO_84833_SUPER_ISOLATE);
}
return rc;
}
@@ -10090,7 +10280,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
return link_up;
}
-
static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
int status = 0;
@@ -10962,7 +11151,7 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
/* STATIC PHY DECLARATION */
/******************************************************************/
-static struct bnx2x_phy phy_null = {
+static const struct bnx2x_phy phy_null = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
.addr = 0,
.def_md_devad = 0,
@@ -10988,7 +11177,7 @@ static struct bnx2x_phy phy_null = {
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_serdes = {
+static const struct bnx2x_phy phy_serdes = {
.type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
.def_md_devad = 0,
@@ -11023,7 +11212,7 @@ static struct bnx2x_phy phy_serdes = {
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_xgxs = {
+static const struct bnx2x_phy phy_xgxs = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
.def_md_devad = 0,
@@ -11058,12 +11247,11 @@ static struct bnx2x_phy phy_xgxs = {
.set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
};
-static struct bnx2x_phy phy_warpcore = {
+static const struct bnx2x_phy phy_warpcore = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
.def_md_devad = 0,
- .flags = (FLAGS_HW_LOCK_REQUIRED |
- FLAGS_TX_ERROR_CHECK),
+ .flags = FLAGS_TX_ERROR_CHECK,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11097,7 +11285,7 @@ static struct bnx2x_phy phy_warpcore = {
};
-static struct bnx2x_phy phy_7101 = {
+static const struct bnx2x_phy phy_7101 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
.addr = 0xff,
.def_md_devad = 0,
@@ -11126,11 +11314,11 @@ static struct bnx2x_phy phy_7101 = {
.set_link_led = (set_link_led_t)bnx2x_7101_set_link_led,
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_8073 = {
+static const struct bnx2x_phy phy_8073 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
.addr = 0xff,
.def_md_devad = 0,
- .flags = FLAGS_HW_LOCK_REQUIRED,
+ .flags = 0,
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11157,7 +11345,7 @@ static struct bnx2x_phy phy_8073 = {
.set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)bnx2x_8073_specific_func
};
-static struct bnx2x_phy phy_8705 = {
+static const struct bnx2x_phy phy_8705 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
.addr = 0xff,
.def_md_devad = 0,
@@ -11185,7 +11373,7 @@ static struct bnx2x_phy phy_8705 = {
.set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_8706 = {
+static const struct bnx2x_phy phy_8706 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
.addr = 0xff,
.def_md_devad = 0,
@@ -11215,12 +11403,11 @@ static struct bnx2x_phy phy_8706 = {
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_8726 = {
+static const struct bnx2x_phy phy_8726 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
.addr = 0xff,
.def_md_devad = 0,
- .flags = (FLAGS_HW_LOCK_REQUIRED |
- FLAGS_INIT_XGXS_FIRST |
+ .flags = (FLAGS_INIT_XGXS_FIRST |
FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
@@ -11248,7 +11435,7 @@ static struct bnx2x_phy phy_8726 = {
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_8727 = {
+static const struct bnx2x_phy phy_8727 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
.addr = 0xff,
.def_md_devad = 0,
@@ -11278,7 +11465,7 @@ static struct bnx2x_phy phy_8727 = {
.set_link_led = (set_link_led_t)bnx2x_8727_set_link_led,
.phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
};
-static struct bnx2x_phy phy_8481 = {
+static const struct bnx2x_phy phy_8481 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
.addr = 0xff,
.def_md_devad = 0,
@@ -11314,7 +11501,7 @@ static struct bnx2x_phy phy_8481 = {
.phy_specific_func = (phy_specific_func_t)NULL
};
-static struct bnx2x_phy phy_84823 = {
+static const struct bnx2x_phy phy_84823 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
.addr = 0xff,
.def_md_devad = 0,
@@ -11351,7 +11538,7 @@ static struct bnx2x_phy phy_84823 = {
.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
};
-static struct bnx2x_phy phy_84833 = {
+static const struct bnx2x_phy phy_84833 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
.addr = 0xff,
.def_md_devad = 0,
@@ -11386,7 +11573,41 @@ static struct bnx2x_phy phy_84833 = {
.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
};
-static struct bnx2x_phy phy_54618se = {
+static const struct bnx2x_phy phy_84834 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834,
+ .addr = 0xff,
+ .def_md_devad = 0,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_REARM_LATCH_SIGNAL,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_848x3_config_init,
+ .read_status = (read_status_t)bnx2x_848xx_read_status,
+ .link_reset = (link_reset_t)bnx2x_848x3_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
+ .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy,
+ .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
+};
+
+static const struct bnx2x_phy phy_54618se = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
.addr = 0xff,
.def_md_devad = 0,
@@ -11564,9 +11785,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
phy->media_type = ETH_PHY_KR;
phy->flags |= FLAGS_WC_DUAL_MODE;
phy->supported &= (SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_Autoneg |
SUPPORTED_FIBRE |
SUPPORTED_Pause |
SUPPORTED_Asym_Pause);
+ phy->flags &= ~FLAGS_TX_ERROR_CHECK;
break;
default:
DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
@@ -11665,6 +11888,9 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
*phy = phy_84833;
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+ *phy = phy_84834;
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
*phy = phy_54618se;
@@ -11721,9 +11947,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
}
phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
- if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+ if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+ (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) &&
(phy->ver_addr)) {
- /* Remove 100Mb link supported for BCM84833 when phy fw
+ /* Remove 100Mb link supported for BCM84833/4 when phy fw
* version lower than or equal to 1.39
*/
u32 raw_ver = REG_RD(bp, phy->ver_addr);
@@ -11733,12 +11960,6 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
SUPPORTED_100baseT_Full);
}
- /* In case mdc/mdio_access of the external phy is different than the
- * mdc/mdio access of the XGXS, a HW lock must be taken in each access
- * to prevent one port interfere with another port's CL45 operations.
- */
- if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
- phy->flags |= FLAGS_HW_LOCK_REQUIRED;
DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
phy_type, port, phy_index);
DP(NETIF_MSG_LINK, " addr=0x%x, mdio_ctl=0x%x\n",
@@ -11863,7 +12084,6 @@ u32 bnx2x_phy_selection(struct link_params *params)
return return_cfg;
}
-
int bnx2x_phy_probe(struct link_params *params)
{
u8 phy_index, actual_phy_idx;
@@ -11907,6 +12127,10 @@ int bnx2x_phy_probe(struct link_params *params)
FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
phy->flags &= ~FLAGS_TX_ERROR_CHECK;
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_MT_SUPPORT))
+ phy->flags |= FLAGS_MDC_MDIO_WA_G;
+
sync_offset = params->shmem_base +
offsetof(struct shmem_region,
dev_info.port_hw_config[params->port].media_type);
@@ -11934,8 +12158,8 @@ int bnx2x_phy_probe(struct link_params *params)
return 0;
}
-void bnx2x_init_bmac_loopback(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_bmac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
vars->link_up = 1;
@@ -11954,8 +12178,8 @@ void bnx2x_init_bmac_loopback(struct link_params *params,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
-void bnx2x_init_emac_loopback(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_emac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
vars->link_up = 1;
@@ -11973,8 +12197,8 @@ void bnx2x_init_emac_loopback(struct link_params *params,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
-void bnx2x_init_xmac_loopback(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_xmac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
vars->link_up = 1;
@@ -11999,8 +12223,8 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
-void bnx2x_init_umac_loopback(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_umac_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
vars->link_up = 1;
@@ -12014,17 +12238,21 @@ void bnx2x_init_umac_loopback(struct link_params *params,
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
-void bnx2x_init_xgxs_loopback(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_xgxs_loopback(struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- vars->link_up = 1;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->duplex = DUPLEX_FULL;
+ struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
+ vars->link_up = 1;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->duplex = DUPLEX_FULL;
if (params->req_line_speed[0] == SPEED_1000)
- vars->line_speed = SPEED_1000;
+ vars->line_speed = SPEED_1000;
+ else if ((params->req_line_speed[0] == SPEED_20000) ||
+ (int_phy->flags & FLAGS_WC_DUAL_MODE))
+ vars->line_speed = SPEED_20000;
else
- vars->line_speed = SPEED_10000;
+ vars->line_speed = SPEED_10000;
if (!USES_WARPCORE(bp))
bnx2x_xgxs_deassert(params);
@@ -12044,34 +12272,30 @@ void bnx2x_init_xgxs_loopback(struct link_params *params,
bnx2x_bmac_enable(params, vars, 0, 1);
}
- if (params->loopback_mode == LOOPBACK_XGXS) {
- /* set 10G XGXS loopback */
- params->phy[INT_PHY].config_loopback(
- &params->phy[INT_PHY],
- params);
-
- } else {
- /* set external phy loopback */
- u8 phy_index;
- for (phy_index = EXT_PHY1;
- phy_index < params->num_phys; phy_index++) {
- if (params->phy[phy_index].config_loopback)
- params->phy[phy_index].config_loopback(
- &params->phy[phy_index],
- params);
- }
- }
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+ if (params->loopback_mode == LOOPBACK_XGXS) {
+ /* Set 10G XGXS loopback */
+ int_phy->config_loopback(int_phy, params);
+ } else {
+ /* Set external phy loopback */
+ u8 phy_index;
+ for (phy_index = EXT_PHY1;
+ phy_index < params->num_phys; phy_index++)
+ if (params->phy[phy_index].config_loopback)
+ params->phy[phy_index].config_loopback(
+ &params->phy[phy_index],
+ params);
+ }
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
}
-static void bnx2x_set_rx_filter(struct link_params *params, u8 en)
+void bnx2x_set_rx_filter(struct link_params *params, u8 en)
{
struct bnx2x *bp = params->bp;
u8 val = en * 0x1F;
- /* Open the gate between the NIG to the BRB */
+ /* Open / close the gate between the NIG and the BRB */
if (!CHIP_IS_E1x(bp))
val |= en * 0x20;
REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + params->port*4, val);
@@ -12345,7 +12569,7 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
* Hold it as vars low
*/
/* Clear link led */
- bnx2x_set_mdio_clk(bp, params->chip_id, port);
+ bnx2x_set_mdio_emac_per_phy(bp, params);
bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
if (reset_ext_phy) {
@@ -12696,7 +12920,7 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
/* Initiate PHY reset*/
bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
port);
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
port);
@@ -12784,7 +13008,8 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
}
static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
- struct bnx2x_phy *phy)
+ struct bnx2x_phy *phy,
+ u8 port)
{
u16 val, cnt;
/* Wait for FW completing its initialization. */
@@ -12794,7 +13019,7 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
MDIO_PMA_REG_CTRL, &val);
if (!(val & (1<<15)))
break;
- usleep_range(1000, 2000);
+ usleep_range(1000, 2000);
}
if (cnt >= 1500) {
DP(NETIF_MSG_LINK, "84833 reset timeout\n");
@@ -12811,26 +13036,28 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
/* Save spirom version */
- bnx2x_save_848xx_spirom_version(phy, bp, PORT_0);
+ bnx2x_save_848xx_spirom_version(phy, bp, port);
return 0;
}
int bnx2x_pre_init_phy(struct bnx2x *bp,
u32 shmem_base,
u32 shmem2_base,
- u32 chip_id)
+ u32 chip_id,
+ u8 port)
{
int rc = 0;
struct bnx2x_phy phy;
- bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
- PORT_0, &phy)) {
+ port, &phy) != 0) {
DP(NETIF_MSG_LINK, "populate_phy failed\n");
return -EINVAL;
}
+ bnx2x_set_mdio_clk(bp, chip_id, phy.mdio_ctrl);
switch (phy.type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
- rc = bnx2x_84833_pre_init_phy(bp, &phy);
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+ rc = bnx2x_84833_pre_init_phy(bp, &phy, port);
break;
default:
break;
@@ -12867,6 +13094,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
/* GPIO3's are linked, and so both need to be toggled
* to obtain required 2us pulse.
*/
@@ -12898,8 +13126,9 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
u32 phy_ver, val;
u8 phy_index = 0;
u32 ext_phy_type, ext_phy_config;
- bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
- bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
+
+ bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC0);
+ bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC1);
DP(NETIF_MSG_LINK, "Begin common phy init\n");
if (CHIP_IS_E3(bp)) {
/* Enable EPIO */
@@ -12960,6 +13189,7 @@ static void bnx2x_check_over_curr(struct link_params *params,
" error.\n",
params->port);
vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+ bnx2x_warpcore_power_module(params, 0);
}
} else
vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
@@ -13139,6 +13369,108 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
}
}
}
+static void bnx2x_disable_kr2(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_phy *phy)
+{
+ struct bnx2x *bp = params->bp;
+ int i;
+ static struct bnx2x_reg_set reg_set[] = {
+ /* Step 1 - Program the TX/RX alignment markers */
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+ };
+ DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+ for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+ bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+ reg_set[i].val);
+ vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+ bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+ /* Restart AN on leading lane */
+ bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_kr2_recovery(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_phy *phy)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "KR2 recovery\n");
+ bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+ bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_check_kr2_wa(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_phy *phy)
+{
+ struct bnx2x *bp = params->bp;
+ u16 base_page, next_page, not_kr2_device, lane;
+ int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
+
+ if (!sigdet) {
+ if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+ bnx2x_kr2_recovery(params, vars, phy);
+ return;
+ }
+
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, lane);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &base_page);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG2, &next_page);
+ bnx2x_set_aer_mmd(params, phy);
+
+ /* CL73 has not begun yet */
+ if (base_page == 0) {
+ if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+ bnx2x_kr2_recovery(params, vars, phy);
+ return;
+ }
+
+ /* In case NP bit is not set in the BasePage, or it is set,
+ * but only KX is advertised, declare this link partner as non-KR2
+ * device.
+ */
+ not_kr2_device = (((base_page & 0x8000) == 0) ||
+ (((base_page & 0x8000) &&
+ ((next_page & 0xe0) == 0x2))));
+
+ /* In case KR2 is already disabled, check if we need to re-enable it */
+ if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+ if (!not_kr2_device) {
+ DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
+ next_page);
+ bnx2x_kr2_recovery(params, vars, phy);
+ }
+ return;
+ }
+ /* KR2 is enabled, but not KR2 device */
+ if (not_kr2_device) {
+ /* Disable KR2 on both lanes */
+ DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
+ bnx2x_disable_kr2(params, vars, phy);
+ return;
+ }
+}
+
void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
{
u16 phy_idx;
@@ -13156,6 +13488,9 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
if (CHIP_IS_E3(bp)) {
struct bnx2x_phy *phy = &params->phy[INT_PHY];
bnx2x_set_aer_mmd(params, phy);
+ if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
+ (phy->speed_cap_mask & SPEED_20000))
+ bnx2x_check_kr2_wa(params, vars, phy);
bnx2x_check_over_curr(params, vars);
if (vars->rx_tx_asic_rst)
bnx2x_warpcore_config_runtime(phy, params, vars);
@@ -13176,27 +13511,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
bnx2x_update_mng(params, vars->link_status);
}
}
-
- }
-
-}
-
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
-{
- u8 phy_index;
- struct bnx2x_phy phy;
- for (phy_index = INT_PHY; phy_index < MAX_PHYS;
- phy_index++) {
- if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
- 0, &phy) != 0) {
- DP(NETIF_MSG_LINK, "populate phy failed\n");
- return 0;
- }
-
- if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
- return 1;
}
- return 0;
}
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 9165b89a4b19..ee6e7ec85457 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -139,8 +139,6 @@ struct bnx2x_phy {
u8 addr;
u8 def_md_devad;
u16 flags;
- /* Require HW lock */
-#define FLAGS_HW_LOCK_REQUIRED (1<<0)
/* No Over-Current detection */
#define FLAGS_NOC (1<<1)
/* Fan failure detection required */
@@ -156,6 +154,7 @@ struct bnx2x_phy {
#define FLAGS_MDC_MDIO_WA_B0 (1<<10)
#define FLAGS_TX_ERROR_CHECK (1<<12)
#define FLAGS_EEE (1<<13)
+#define FLAGS_MDC_MDIO_WA_G (1<<15)
/* preemphasis values for the rx side */
u16 rx_preemphasis[4];
@@ -267,6 +266,9 @@ struct link_params {
#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
#define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11)
+#define FEATURE_CONFIG_MT_SUPPORT (1<<13)
+#define FEATURE_CONFIG_BOOT_FROM_SAN (1<<14)
+
/* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS];
@@ -347,6 +349,8 @@ struct link_vars {
u8 rx_tx_asic_rst;
u8 turn_to_run_wc_rt;
u16 rsrv2;
+ /* The same definitions as the shmem2 parameter */
+ u32 link_attr_sync;
};
/***********************************************************/
@@ -418,10 +422,6 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
void bnx2x_hw_reset_phy(struct link_params *params);
-/* Checks if HW lock is required for this phy/board type */
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
- u32 shmem2_base);
-
/* Check swap bit and adjust PHY order */
u32 bnx2x_phy_selection(struct link_params *params);
@@ -432,7 +432,8 @@ int bnx2x_phy_probe(struct link_params *params);
u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
u32 shmem2_base, u8 port);
-
+/* Open / close the gate between the NIG and the BRB */
+void bnx2x_set_rx_filter(struct link_params *params, u8 en);
/* DCBX structs */
@@ -459,9 +460,6 @@ struct bnx2x_nig_brb_pfc_port_params {
u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
u32 llfc_high_priority_classes;
u32 llfc_low_priority_classes;
- /* BRB */
- u32 cos0_pauseable;
- u32 cos1_pauseable;
};
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 01611b33a93d..940ef859dc60 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -79,7 +79,7 @@
/* Time in jiffies before concluding the transmitter is hung */
#define TX_TIMEOUT (5*HZ)
-static char version[] __devinitdata =
+static char version[] =
"Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -149,7 +149,7 @@ enum bnx2x_board_type {
/* indexed by board_type, above */
static struct {
char *name;
-} board_info[] __devinitdata = {
+} board_info[] = {
{ "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
{ "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
{ "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
@@ -791,10 +791,9 @@ void bnx2x_panic_dump(struct bnx2x *bp)
/* host sb data */
-#ifdef BCM_CNIC
if (IS_FCOE_FP(fp))
continue;
-#endif
+
BNX2X_ERR(" run indexes (");
for (j = 0; j < HC_SB_MAX_SM; j++)
pr_cont("0x%x%s",
@@ -859,7 +858,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
#ifdef BNX2X_STOP_ON_ERROR
/* Rings */
/* Rx */
- for_each_rx_queue(bp, i) {
+ for_each_valid_rx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
@@ -893,7 +892,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
}
/* Tx */
- for_each_tx_queue(bp, i) {
+ for_each_valid_tx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
for_each_cos_in_tx_queue(fp, cos) {
struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
@@ -1483,7 +1482,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
BNX2X_ERR("BUG! proper val not read from IGU!\n");
}
-void bnx2x_int_disable(struct bnx2x *bp)
+static void bnx2x_int_disable(struct bnx2x *bp)
{
if (bp->common.int_block == INT_BLOCK_HC)
bnx2x_hc_int_disable(bp);
@@ -1504,9 +1503,8 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
if (msix) {
synchronize_irq(bp->msix_table[0].vector);
offset = 1;
-#ifdef BCM_CNIC
- offset++;
-#endif
+ if (CNIC_SUPPORT(bp))
+ offset++;
for_each_eth_queue(bp, i)
synchronize_irq(bp->msix_table[offset++].vector);
} else
@@ -1588,9 +1586,8 @@ static bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
}
-#ifdef BCM_CNIC
static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
-#endif
+
void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
{
@@ -1720,7 +1717,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- mask = 0x2 << (fp->index + CNIC_PRESENT);
+ mask = 0x2 << (fp->index + CNIC_SUPPORT(bp));
if (status & mask) {
/* Handle Rx or Tx according to SB id */
prefetch(fp->rx_cons_sb);
@@ -1732,22 +1729,23 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
}
}
-#ifdef BCM_CNIC
- mask = 0x2;
- if (status & (mask | 0x1)) {
- struct cnic_ops *c_ops = NULL;
+ if (CNIC_SUPPORT(bp)) {
+ mask = 0x2;
+ if (status & (mask | 0x1)) {
+ struct cnic_ops *c_ops = NULL;
- if (likely(bp->state == BNX2X_STATE_OPEN)) {
- rcu_read_lock();
- c_ops = rcu_dereference(bp->cnic_ops);
- if (c_ops)
- c_ops->cnic_handler(bp->cnic_data, NULL);
- rcu_read_unlock();
- }
+ if (likely(bp->state == BNX2X_STATE_OPEN)) {
+ rcu_read_lock();
+ c_ops = rcu_dereference(bp->cnic_ops);
+ if (c_ops)
+ c_ops->cnic_handler(bp->cnic_data,
+ NULL);
+ rcu_read_unlock();
+ }
- status &= ~mask;
+ status &= ~mask;
+ }
}
-#endif
if (unlikely(status & 0x1)) {
queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
@@ -2034,40 +2032,39 @@ int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
return 0;
}
-static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
+static int bnx2x_set_spio(struct bnx2x *bp, int spio, u32 mode)
{
- u32 spio_mask = (1 << spio_num);
u32 spio_reg;
- if ((spio_num < MISC_REGISTERS_SPIO_4) ||
- (spio_num > MISC_REGISTERS_SPIO_7)) {
- BNX2X_ERR("Invalid SPIO %d\n", spio_num);
+ /* Only 2 SPIOs are configurable */
+ if ((spio != MISC_SPIO_SPIO4) && (spio != MISC_SPIO_SPIO5)) {
+ BNX2X_ERR("Invalid SPIO 0x%x\n", spio);
return -EINVAL;
}
bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
/* read SPIO and mask except the float bits */
- spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT);
+ spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_SPIO_FLOAT);
switch (mode) {
- case MISC_REGISTERS_SPIO_OUTPUT_LOW:
- DP(NETIF_MSG_HW, "Set SPIO %d -> output low\n", spio_num);
+ case MISC_SPIO_OUTPUT_LOW:
+ DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output low\n", spio);
/* clear FLOAT and set CLR */
- spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
- spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_CLR_POS);
+ spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS);
+ spio_reg |= (spio << MISC_SPIO_CLR_POS);
break;
- case MISC_REGISTERS_SPIO_OUTPUT_HIGH:
- DP(NETIF_MSG_HW, "Set SPIO %d -> output high\n", spio_num);
+ case MISC_SPIO_OUTPUT_HIGH:
+ DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output high\n", spio);
/* clear FLOAT and set SET */
- spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
- spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_SET_POS);
+ spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS);
+ spio_reg |= (spio << MISC_SPIO_SET_POS);
break;
- case MISC_REGISTERS_SPIO_INPUT_HI_Z:
- DP(NETIF_MSG_HW, "Set SPIO %d -> input\n", spio_num);
+ case MISC_SPIO_INPUT_HI_Z:
+ DP(NETIF_MSG_HW, "Set SPIO 0x%x -> input\n", spio);
/* set FLOAT */
- spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
+ spio_reg |= (spio << MISC_SPIO_FLOAT_POS);
break;
default:
@@ -2106,22 +2103,25 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp)
}
}
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
+static void bnx2x_set_requested_fc(struct bnx2x *bp)
{
- if (!BP_NOMCP(bp)) {
- u8 rc;
- int cfx_idx = bnx2x_get_link_cfg_idx(bp);
- u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
- /*
- * Initialize link parameters structure variables
- * It is recommended to turn off RX FC for jumbo frames
- * for better performance
- */
- if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
- bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
- else
- bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
+ /* Initialize link parameters structure variables
+ * It is recommended to turn off RX FC for jumbo frames
+ * for better performance
+ */
+ if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
+ bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
+ else
+ bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
+}
+int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
+{
+ int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
+ u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
+
+ if (!BP_NOMCP(bp)) {
+ bnx2x_set_requested_fc(bp);
bnx2x_acquire_phy_lock(bp);
if (load_mode == LOAD_DIAG) {
@@ -2150,11 +2150,11 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
bnx2x_calc_fc_adv(bp);
- if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
+ if (bp->link_vars.link_up) {
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
bnx2x_link_report(bp);
- } else
- queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+ }
+ queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
return rc;
}
@@ -3075,11 +3075,13 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
{
-#ifdef BCM_CNIC
struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
struct fcoe_stats_info *fcoe_stat =
&bp->slowpath->drv_info_to_mcp.fcoe_stat;
+ if (!CNIC_LOADED(bp))
+ return;
+
memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT,
bp->fip_mac, ETH_ALEN);
@@ -3162,16 +3164,17 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
/* ask L5 driver to add data to the struct */
bnx2x_cnic_notify(bp, CNIC_CTL_FCOE_STATS_GET_CMD);
-#endif
}
static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
{
-#ifdef BCM_CNIC
struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
struct iscsi_stats_info *iscsi_stat =
&bp->slowpath->drv_info_to_mcp.iscsi_stat;
+ if (!CNIC_LOADED(bp))
+ return;
+
memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT,
bp->cnic_eth_dev.iscsi_mac, ETH_ALEN);
@@ -3180,7 +3183,6 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
/* ask L5 driver to add data to the struct */
bnx2x_cnic_notify(bp, CNIC_CTL_ISCSI_STATS_GET_CMD);
-#endif
}
/* called due to MCP event (on pmf):
@@ -3589,6 +3591,21 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
/* now set back the mask */
if (asserted & ATTN_NIG_FOR_FUNC) {
+ /* Verify that IGU ack through BAR was written before restoring
+ * NIG mask. This loop should exit after 2-3 iterations max.
+ */
+ if (bp->common.int_block != INT_BLOCK_HC) {
+ u32 cnt = 0, igu_acked;
+ do {
+ igu_acked = REG_RD(bp,
+ IGU_REG_ATTENTION_ACK_BITS);
+ } while (((igu_acked & ATTN_NIG_FOR_FUNC) == 0) &&
+ (++cnt < MAX_IGU_ATTN_ACK_TO));
+ if (!igu_acked)
+ DP(NETIF_MSG_HW,
+ "Failed to verify IGU ack on time\n");
+ barrier();
+ }
REG_WR(bp, nig_int_mask_addr, nig_mask);
bnx2x_release_phy_lock(bp);
}
@@ -4572,7 +4589,6 @@ static void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
mmiowb(); /* keep prod updates ordered */
}
-#ifdef BCM_CNIC
static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
union event_ring_elem *elem)
{
@@ -4594,7 +4610,6 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
bnx2x_cnic_cfc_comp(bp, cid, err);
return 0;
}
-#endif
static void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
{
@@ -4635,11 +4650,9 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
case BNX2X_FILTER_MAC_PENDING:
DP(BNX2X_MSG_SP, "Got SETUP_MAC completions\n");
-#ifdef BCM_CNIC
- if (cid == BNX2X_ISCSI_ETH_CID(bp))
+ if (CNIC_LOADED(bp) && (cid == BNX2X_ISCSI_ETH_CID(bp)))
vlan_mac_obj = &bp->iscsi_l2_mac_obj;
else
-#endif
vlan_mac_obj = &bp->sp_objs[cid].mac_obj;
break;
@@ -4665,9 +4678,7 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
}
-#ifdef BCM_CNIC
static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
-#endif
static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
{
@@ -4678,14 +4689,12 @@ static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
/* Send rx_mode command again if was requested */
if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
bnx2x_set_storm_rx_mode(bp);
-#ifdef BCM_CNIC
else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
&bp->sp_state))
bnx2x_set_iscsi_eth_rx_mode(bp, true);
else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
&bp->sp_state))
bnx2x_set_iscsi_eth_rx_mode(bp, false);
-#endif
netif_addr_unlock_bh(bp->dev);
}
@@ -4747,7 +4756,6 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
q);
}
-#ifdef BCM_CNIC
if (!NO_FCOE(bp)) {
fp = &bp->fp[FCOE_IDX(bp)];
queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
@@ -4770,22 +4778,16 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
bnx2x_link_report(bp);
bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
}
-#else
- /* If no FCoE ring - ACK MCP now */
- bnx2x_link_report(bp);
- bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
-#endif /* BCM_CNIC */
}
static struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
struct bnx2x *bp, u32 cid)
{
DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
-#ifdef BCM_CNIC
- if (cid == BNX2X_FCOE_ETH_CID(bp))
+
+ if (CNIC_LOADED(bp) && (cid == BNX2X_FCOE_ETH_CID(bp)))
return &bnx2x_fcoe_sp_obj(bp, q_obj);
else
-#endif
return &bp->sp_objs[CID_TO_FP(cid, bp)].q_obj;
}
@@ -4793,6 +4795,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
{
u16 hw_cons, sw_cons, sw_prod;
union event_ring_elem *elem;
+ u8 echo;
u32 cid;
u8 opcode;
int spqe_cnt = 0;
@@ -4847,10 +4850,11 @@ static void bnx2x_eq_int(struct bnx2x *bp)
*/
DP(BNX2X_MSG_SP,
"got delete ramrod for MULTI[%d]\n", cid);
-#ifdef BCM_CNIC
- if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
+
+ if (CNIC_LOADED(bp) &&
+ !bnx2x_cnic_handle_cfc_del(bp, cid, elem))
goto next_spqe;
-#endif
+
q_obj = bnx2x_cid_to_q_obj(bp, cid);
if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
@@ -4875,21 +4879,34 @@ static void bnx2x_eq_int(struct bnx2x *bp)
break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe;
+
case EVENT_RING_OPCODE_FUNCTION_UPDATE:
- DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
- "AFEX: ramrod completed FUNCTION_UPDATE\n");
- f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_AFEX_UPDATE);
+ echo = elem->message.data.function_update_event.echo;
+ if (echo == SWITCH_UPDATE) {
+ DP(BNX2X_MSG_SP | NETIF_MSG_IFUP,
+ "got FUNC_SWITCH_UPDATE ramrod\n");
+ if (f_obj->complete_cmd(
+ bp, f_obj, BNX2X_F_CMD_SWITCH_UPDATE))
+ break;
- /* We will perform the Queues update from sp_rtnl task
- * as all Queue SP operations should run under
- * rtnl_lock.
- */
- smp_mb__before_clear_bit();
- set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
- &bp->sp_rtnl_state);
- smp_mb__after_clear_bit();
+ } else {
+ DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
+ "AFEX: ramrod completed FUNCTION_UPDATE\n");
+ f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_AFEX_UPDATE);
+
+ /* We will perform the Queues update from
+ * sp_rtnl task as all Queue SP operations
+ * should run under rtnl_lock.
+ */
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
+ &bp->sp_rtnl_state);
+ smp_mb__after_clear_bit();
+
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
+ }
- schedule_delayed_work(&bp->sp_rtnl_task, 0);
goto next_spqe;
case EVENT_RING_OPCODE_AFEX_VIF_LISTS:
@@ -4999,11 +5016,10 @@ static void bnx2x_sp_task(struct work_struct *work)
/* SP events: STAT_QUERY and others */
if (status & BNX2X_DEF_SB_IDX) {
-#ifdef BCM_CNIC
struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
- if ((!NO_FCOE(bp)) &&
- (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+ if (FCOE_INIT(bp) &&
+ (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
/*
* Prevent local bottom-halves from running as
* we are going to change the local NAPI list.
@@ -5012,7 +5028,7 @@ static void bnx2x_sp_task(struct work_struct *work)
napi_schedule(&bnx2x_fcoe(bp, napi));
local_bh_enable();
}
-#endif
+
/* Handle EQ completions */
bnx2x_eq_int(bp);
@@ -5050,8 +5066,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
return IRQ_HANDLED;
#endif
-#ifdef BCM_CNIC
- {
+ if (CNIC_LOADED(bp)) {
struct cnic_ops *c_ops;
rcu_read_lock();
@@ -5060,7 +5075,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
c_ops->cnic_handler(bp->cnic_data, NULL);
rcu_read_unlock();
}
-#endif
+
queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
return IRQ_HANDLED;
@@ -5498,12 +5513,10 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
unsigned long rx_mode_flags = 0, ramrod_flags = 0;
unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
-#ifdef BCM_CNIC
if (!NO_FCOE(bp))
/* Configure rx_mode of FCoE Queue */
__set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
-#endif
switch (bp->rx_mode) {
case BNX2X_RX_MODE_NONE:
@@ -5624,12 +5637,12 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
{
- return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
+ return fp->bp->igu_base_sb + fp->index + CNIC_SUPPORT(fp->bp);
}
static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
{
- return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
+ return fp->bp->base_fw_ndsb + fp->index + CNIC_SUPPORT(fp->bp);
}
static u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
@@ -5720,23 +5733,25 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
txdata->tx_pkt = 0;
}
+static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_tx_queue_cnic(bp, i)
+ bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]);
+}
static void bnx2x_init_tx_rings(struct bnx2x *bp)
{
int i;
u8 cos;
- for_each_tx_queue(bp, i)
+ for_each_eth_queue(bp, i)
for_each_cos_in_tx_queue(&bp->fp[i], cos)
bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]);
}
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+void bnx2x_nic_init_cnic(struct bnx2x *bp)
{
- int i;
-
- for_each_eth_queue(bp, i)
- bnx2x_init_eth_fp(bp, i);
-#ifdef BCM_CNIC
if (!NO_FCOE(bp))
bnx2x_init_fcoe_fp(bp);
@@ -5744,8 +5759,22 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
BNX2X_VF_ID_INVALID, false,
bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
-#endif
+ /* ensure status block indices were read */
+ rmb();
+ bnx2x_init_rx_rings_cnic(bp);
+ bnx2x_init_tx_rings_cnic(bp);
+
+ /* flush all */
+ mb();
+ mmiowb();
+}
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+{
+ int i;
+
+ for_each_eth_queue(bp, i)
+ bnx2x_init_eth_fp(bp, i);
/* Initialize MOD_ABS interrupts */
bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
bp->common.shmem_base, bp->common.shmem2_base,
@@ -6031,10 +6060,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
msleep(50);
bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-#ifndef BCM_CNIC
- /* set NIC mode */
- REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
+ if (!CNIC_SUPPORT(bp))
+ /* set NIC mode */
+ REG_WR(bp, PRS_REG_NIC_MODE, 1);
/* Enable inputs of parser neighbor blocks */
REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff);
@@ -6049,6 +6077,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
{
+ u32 val;
+
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
if (!CHIP_IS_E1x(bp))
REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
@@ -6082,17 +6112,14 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
- if (CHIP_REV_IS_FPGA(bp))
- REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
- else if (!CHIP_IS_E1x(bp))
- REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
- (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
- | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
- | PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN
- | PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED
- | PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED));
- else
- REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
+ val = PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT |
+ PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF |
+ PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN;
+ if (!CHIP_IS_E1x(bp))
+ val |= PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED |
+ PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED;
+ REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, val);
+
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
@@ -6185,18 +6212,16 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
return;
/* Fan failure is indicated by SPIO 5 */
- bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
- MISC_REGISTERS_SPIO_INPUT_HI_Z);
+ bnx2x_set_spio(bp, MISC_SPIO_SPIO5, MISC_SPIO_INPUT_HI_Z);
/* set to active low mode */
val = REG_RD(bp, MISC_REG_SPIO_INT);
- val |= ((1 << MISC_REGISTERS_SPIO_5) <<
- MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
+ val |= (MISC_SPIO_SPIO5 << MISC_SPIO_INT_OLD_SET_POS);
REG_WR(bp, MISC_REG_SPIO_INT, val);
/* enable interrupt to signal the IGU */
val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
- val |= (1 << MISC_REGISTERS_SPIO_5);
+ val |= MISC_SPIO_SPIO5;
REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
}
@@ -6256,6 +6281,10 @@ void bnx2x_pf_disable(struct bnx2x *bp)
static void bnx2x__common_init_phy(struct bnx2x *bp)
{
u32 shmem_base[2], shmem2_base[2];
+ /* Avoid common init in case MFW supports LFA */
+ if (SHMEM2_RD(bp, size) >
+ (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+ return;
shmem_base[0] = bp->common.shmem_base;
shmem2_base[0] = bp->common.shmem2_base;
if (!CHIP_IS_E1x(bp)) {
@@ -6522,9 +6551,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
REG_WR(bp, QM_REG_SOFT_RESET, 1);
REG_WR(bp, QM_REG_SOFT_RESET, 0);
-#ifdef BCM_CNIC
- bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
-#endif
+ if (CNIC_SUPPORT(bp))
+ bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
@@ -6611,18 +6639,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
-#ifdef BCM_CNIC
- REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
- REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
- REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
- REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
- REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
- REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
- REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
- REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
- REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
- REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
-#endif
+ if (CNIC_SUPPORT(bp)) {
+ REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
+ REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
+ REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
+ REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
+ REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
+ REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
+ REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
+ REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
+ REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
+ REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
+ }
REG_WR(bp, SRC_REG_SOFT_RST, 0);
if (sizeof(union cdu_context) != 1024)
@@ -6786,11 +6814,11 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
/* QM cid (connection) count */
bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
-#ifdef BCM_CNIC
- bnx2x_init_block(bp, BLOCK_TM, init_phase);
- REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
- REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
-#endif
+ if (CNIC_SUPPORT(bp)) {
+ bnx2x_init_block(bp, BLOCK_TM, init_phase);
+ REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
+ REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
+ }
bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
@@ -6877,9 +6905,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
}
-#ifdef BCM_CNIC
- bnx2x_init_block(bp, BLOCK_SRC, init_phase);
-#endif
+ if (CNIC_SUPPORT(bp))
+ bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+
bnx2x_init_block(bp, BLOCK_CDU, init_phase);
bnx2x_init_block(bp, BLOCK_CFC, init_phase);
@@ -6955,7 +6983,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
/* If SPIO5 is set to generate interrupts, enable it for this port */
val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
- if (val & (1 << MISC_REGISTERS_SPIO_5)) {
+ if (val & MISC_SPIO_SPIO5) {
u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
val = REG_RD(bp, reg_addr);
@@ -7040,6 +7068,130 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
bnx2x_ilt_wr(bp, i, 0);
}
+
+static void bnx2x_init_searcher(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
+ /* T1 hash bits value determines the T1 number of entries */
+ REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
+}
+
+static inline int bnx2x_func_switch_update(struct bnx2x *bp, int suspend)
+{
+ int rc;
+ struct bnx2x_func_state_params func_params = {NULL};
+ struct bnx2x_func_switch_update_params *switch_update_params =
+ &func_params.params.switch_update;
+
+ /* Prepare parameters for function state transitions */
+ __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+ __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
+
+ /* Function parameters */
+ switch_update_params->suspend = suspend;
+
+ rc = bnx2x_func_state_change(bp, &func_params);
+
+ return rc;
+}
+
+static int bnx2x_reset_nic_mode(struct bnx2x *bp)
+{
+ int rc, i, port = BP_PORT(bp);
+ int vlan_en = 0, mac_en[NUM_MACS];
+
+
+ /* Close input from network */
+ if (bp->mf_mode == SINGLE_FUNCTION) {
+ bnx2x_set_rx_filter(&bp->link_params, 0);
+ } else {
+ vlan_en = REG_RD(bp, port ? NIG_REG_LLH1_FUNC_EN :
+ NIG_REG_LLH0_FUNC_EN);
+ REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+ NIG_REG_LLH0_FUNC_EN, 0);
+ for (i = 0; i < NUM_MACS; i++) {
+ mac_en[i] = REG_RD(bp, port ?
+ (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+ 4 * i) :
+ (NIG_REG_LLH0_FUNC_MEM_ENABLE +
+ 4 * i));
+ REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+ 4 * i) :
+ (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i), 0);
+ }
+ }
+
+ /* Close BMC to host */
+ REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+ NIG_REG_P1_TX_MNG_HOST_ENABLE, 0);
+
+ /* Suspend Tx switching to the PF. Completion of this ramrod
+ * further guarantees that all the packets of that PF / child
+ * VFs in BRB were processed by the Parser, so it is safe to
+ * change the NIC_MODE register.
+ */
+ rc = bnx2x_func_switch_update(bp, 1);
+ if (rc) {
+ BNX2X_ERR("Can't suspend tx-switching!\n");
+ return rc;
+ }
+
+ /* Change NIC_MODE register */
+ REG_WR(bp, PRS_REG_NIC_MODE, 0);
+
+ /* Open input from network */
+ if (bp->mf_mode == SINGLE_FUNCTION) {
+ bnx2x_set_rx_filter(&bp->link_params, 1);
+ } else {
+ REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+ NIG_REG_LLH0_FUNC_EN, vlan_en);
+ for (i = 0; i < NUM_MACS; i++) {
+ REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+ 4 * i) :
+ (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i),
+ mac_en[i]);
+ }
+ }
+
+ /* Enable BMC to host */
+ REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+ NIG_REG_P1_TX_MNG_HOST_ENABLE, 1);
+
+ /* Resume Tx switching to the PF */
+ rc = bnx2x_func_switch_update(bp, 0);
+ if (rc) {
+ BNX2X_ERR("Can't resume tx-switching!\n");
+ return rc;
+ }
+
+ DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+ return 0;
+}
+
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp)
+{
+ int rc;
+
+ bnx2x_ilt_init_op_cnic(bp, INITOP_SET);
+
+ if (CONFIGURE_NIC_MODE(bp)) {
+ /* Configrue searcher as part of function hw init */
+ bnx2x_init_searcher(bp);
+
+ /* Reset NIC mode */
+ rc = bnx2x_reset_nic_mode(bp);
+ if (rc)
+ BNX2X_ERR("Can't change NIC mode!\n");
+ return rc;
+ }
+
+ return 0;
+}
+
static int bnx2x_init_hw_func(struct bnx2x *bp)
{
int port = BP_PORT(bp);
@@ -7082,17 +7234,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
}
bnx2x_ilt_init_op(bp, INITOP_SET);
-#ifdef BCM_CNIC
- bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
-
- /* T1 hash bits value determines the T1 number of entries */
- REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
-#endif
+ if (!CONFIGURE_NIC_MODE(bp)) {
+ bnx2x_init_searcher(bp);
+ REG_WR(bp, PRS_REG_NIC_MODE, 0);
+ DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+ } else {
+ /* Set NIC mode */
+ REG_WR(bp, PRS_REG_NIC_MODE, 1);
+ DP(NETIF_MSG_IFUP, "NIC MODE configrued\n");
-#ifndef BCM_CNIC
- /* set NIC mode */
- REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif /* BCM_CNIC */
+ }
if (!CHIP_IS_E1x(bp)) {
u32 pf_conf = IGU_PF_CONF_FUNC_EN;
@@ -7343,6 +7494,20 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
}
+void bnx2x_free_mem_cnic(struct bnx2x *bp)
+{
+ bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE);
+
+ if (!CHIP_IS_E1x(bp))
+ BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e2));
+ else
+ BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e1x));
+
+ BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
+}
+
void bnx2x_free_mem(struct bnx2x *bp)
{
int i;
@@ -7367,17 +7532,6 @@ void bnx2x_free_mem(struct bnx2x *bp)
BNX2X_FREE(bp->ilt->lines);
-#ifdef BCM_CNIC
- if (!CHIP_IS_E1x(bp))
- BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
- sizeof(struct host_hc_status_block_e2));
- else
- BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
- sizeof(struct host_hc_status_block_e1x));
-
- BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
-#endif
-
BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
@@ -7445,24 +7599,44 @@ alloc_mem_err:
return -ENOMEM;
}
-
-int bnx2x_alloc_mem(struct bnx2x *bp)
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
{
- int i, allocated, context_size;
-
-#ifdef BCM_CNIC
if (!CHIP_IS_E1x(bp))
/* size = the status block + ramrod buffers */
BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
sizeof(struct host_hc_status_block_e2));
else
- BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
- sizeof(struct host_hc_status_block_e1x));
+ BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb,
+ &bp->cnic_sb_mapping,
+ sizeof(struct
+ host_hc_status_block_e1x));
- /* allocate searcher T2 table */
- BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
-#endif
+ if (CONFIGURE_NIC_MODE(bp))
+ /* allocate searcher T2 table, as it wan't allocated before */
+ BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+
+ /* write address to which L5 should insert its values */
+ bp->cnic_eth_dev.addr_drv_info_to_mcp =
+ &bp->slowpath->drv_info_to_mcp;
+ if (bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_ALLOC))
+ goto alloc_mem_err;
+
+ return 0;
+
+alloc_mem_err:
+ bnx2x_free_mem_cnic(bp);
+ BNX2X_ERR("Can't allocate memory\n");
+ return -ENOMEM;
+}
+
+int bnx2x_alloc_mem(struct bnx2x *bp)
+{
+ int i, allocated, context_size;
+
+ if (!CONFIGURE_NIC_MODE(bp))
+ /* allocate searcher T2 table */
+ BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
sizeof(struct host_sp_status_block));
@@ -7470,11 +7644,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
-#ifdef BCM_CNIC
- /* write address to which L5 should insert its values */
- bp->cnic_eth_dev.addr_drv_info_to_mcp = &bp->slowpath->drv_info_to_mcp;
-#endif
-
/* Allocated memory for FW statistics */
if (bnx2x_alloc_fw_stats_mem(bp))
goto alloc_mem_err;
@@ -7596,14 +7765,12 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
{
unsigned long ramrod_flags = 0;
-#ifdef BCM_CNIC
if (is_zero_ether_addr(bp->dev->dev_addr) &&
(IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
DP(NETIF_MSG_IFUP | NETIF_MSG_IFDOWN,
"Ignoring Zero MAC for STORAGE SD mode\n");
return 0;
}
-#endif
DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
@@ -7632,7 +7799,8 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
bnx2x_enable_msi(bp);
/* falling through... */
case INT_MODE_INTx:
- bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+ bp->num_ethernet_queues = 1;
+ bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("set number of queues to 1\n");
break;
default:
@@ -7644,9 +7812,10 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
bp->flags & USING_SINGLE_MSIX_FLAG) {
/* failed to enable multiple MSI-X */
BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
- bp->num_queues, 1 + NON_ETH_CONTEXT_USE);
+ bp->num_queues,
+ 1 + bp->num_cnic_queues);
- bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+ bp->num_queues = 1 + bp->num_cnic_queues;
/* Try to enable MSI */
if (!(bp->flags & USING_SINGLE_MSIX_FLAG) &&
@@ -7679,9 +7848,9 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
ilt_client->flags = ILT_CLIENT_SKIP_MEM;
ilt_client->start = line;
line += bnx2x_cid_ilt_lines(bp);
-#ifdef BCM_CNIC
- line += CNIC_ILT_LINES;
-#endif
+
+ if (CNIC_SUPPORT(bp))
+ line += CNIC_ILT_LINES;
ilt_client->end = line - 1;
DP(NETIF_MSG_IFUP, "ilt client[CDU]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
@@ -7714,49 +7883,43 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
ilog2(ilt_client->page_size >> 12));
}
- /* SRC */
- ilt_client = &ilt->clients[ILT_CLIENT_SRC];
-#ifdef BCM_CNIC
- ilt_client->client_num = ILT_CLIENT_SRC;
- ilt_client->page_size = SRC_ILT_PAGE_SZ;
- ilt_client->flags = 0;
- ilt_client->start = line;
- line += SRC_ILT_LINES;
- ilt_client->end = line - 1;
- DP(NETIF_MSG_IFUP,
- "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
- ilt_client->start,
- ilt_client->end,
- ilt_client->page_size,
- ilt_client->flags,
- ilog2(ilt_client->page_size >> 12));
+ if (CNIC_SUPPORT(bp)) {
+ /* SRC */
+ ilt_client = &ilt->clients[ILT_CLIENT_SRC];
+ ilt_client->client_num = ILT_CLIENT_SRC;
+ ilt_client->page_size = SRC_ILT_PAGE_SZ;
+ ilt_client->flags = 0;
+ ilt_client->start = line;
+ line += SRC_ILT_LINES;
+ ilt_client->end = line - 1;
-#else
- ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
+ DP(NETIF_MSG_IFUP,
+ "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
- /* TM */
- ilt_client = &ilt->clients[ILT_CLIENT_TM];
-#ifdef BCM_CNIC
- ilt_client->client_num = ILT_CLIENT_TM;
- ilt_client->page_size = TM_ILT_PAGE_SZ;
- ilt_client->flags = 0;
- ilt_client->start = line;
- line += TM_ILT_LINES;
- ilt_client->end = line - 1;
+ /* TM */
+ ilt_client = &ilt->clients[ILT_CLIENT_TM];
+ ilt_client->client_num = ILT_CLIENT_TM;
+ ilt_client->page_size = TM_ILT_PAGE_SZ;
+ ilt_client->flags = 0;
+ ilt_client->start = line;
+ line += TM_ILT_LINES;
+ ilt_client->end = line - 1;
- DP(NETIF_MSG_IFUP,
- "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
- ilt_client->start,
- ilt_client->end,
- ilt_client->page_size,
- ilt_client->flags,
- ilog2(ilt_client->page_size >> 12));
+ DP(NETIF_MSG_IFUP,
+ "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
+ }
-#else
- ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
BUG_ON(line > ILT_MAX_LINES);
}
@@ -7823,7 +7986,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
}
}
-int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct bnx2x_queue_state_params *q_params,
struct bnx2x_queue_setup_tx_only_params *tx_only_params,
int tx_index, bool leading)
@@ -7924,6 +8087,9 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* Set the command */
q_params.cmd = BNX2X_Q_CMD_SETUP;
+ if (IS_FCOE_FP(fp))
+ bp->fcoe_init = true;
+
/* Change the state to SETUP */
rc = bnx2x_queue_state_change(bp, &q_params);
if (rc) {
@@ -8037,12 +8203,12 @@ static void bnx2x_reset_func(struct bnx2x *bp)
SB_DISABLED);
}
-#ifdef BCM_CNIC
- /* CNIC SB */
- REG_WR8(bp, BAR_CSTRORM_INTMEM +
- CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
- SB_DISABLED);
-#endif
+ if (CNIC_LOADED(bp))
+ /* CNIC SB */
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET
+ (bnx2x_cnic_fw_sb_id(bp)), SB_DISABLED);
+
/* SP SB */
REG_WR8(bp, BAR_CSTRORM_INTMEM +
CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
@@ -8061,19 +8227,19 @@ static void bnx2x_reset_func(struct bnx2x *bp)
REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
}
-#ifdef BCM_CNIC
- /* Disable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
- /*
- * Wait for at least 10ms and up to 2 second for the timers scan to
- * complete
- */
- for (i = 0; i < 200; i++) {
- msleep(10);
- if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
- break;
+ if (CNIC_LOADED(bp)) {
+ /* Disable Timer scan */
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+ /*
+ * Wait for at least 10ms and up to 2 second for the timers
+ * scan to complete
+ */
+ for (i = 0; i < 200; i++) {
+ msleep(10);
+ if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
+ break;
+ }
}
-#endif
/* Clear ILT */
bnx2x_clear_func_ilt(bp, func);
@@ -8409,13 +8575,24 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
/* Close multi and leading connections
* Completions for ramrods are collected in a synchronous way
*/
- for_each_queue(bp, i)
+ for_each_eth_queue(bp, i)
if (bnx2x_stop_queue(bp, i))
#ifdef BNX2X_STOP_ON_ERROR
return;
#else
goto unload_error;
#endif
+
+ if (CNIC_LOADED(bp)) {
+ for_each_cnic_queue(bp, i)
+ if (bnx2x_stop_queue(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#else
+ goto unload_error;
+#endif
+ }
+
/* If SP settings didn't get completed so far - something
* very wrong has happen.
*/
@@ -8437,6 +8614,8 @@ unload_error:
bnx2x_netif_stop(bp, 1);
/* Delete all NAPI objects */
bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
/* Release IRQs */
bnx2x_free_irq(bp);
@@ -8558,7 +8737,8 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val)
/* Get shmem offset */
shmem = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
- validity_offset = offsetof(struct shmem_region, validity_map[0]);
+ validity_offset =
+ offsetof(struct shmem_region, validity_map[BP_PORT(bp)]);
/* Clear validity map flags */
if (shmem > 0)
@@ -8651,7 +8831,11 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
- /* Don't reset the following blocks */
+ /* Don't reset the following blocks.
+ * Important: per port blocks (such as EMAC, BMAC, UMAC) can't be
+ * reset, as in 4 port device they might still be owned
+ * by the MCP (there is only one leader per path).
+ */
not_reset_mask1 =
MISC_REGISTERS_RESET_REG_1_RST_HC |
MISC_REGISTERS_RESET_REG_1_RST_PXPV |
@@ -8667,19 +8851,19 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
MISC_REGISTERS_RESET_REG_2_RST_ATC |
- MISC_REGISTERS_RESET_REG_2_PGLC;
+ MISC_REGISTERS_RESET_REG_2_PGLC |
+ MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
+ MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
+ MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
+ MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
+ MISC_REGISTERS_RESET_REG_2_UMAC0 |
+ MISC_REGISTERS_RESET_REG_2_UMAC1;
/*
* Keep the following blocks in reset:
* - all xxMACs are handled by the bnx2x_link code.
*/
stay_reset2 =
- MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
- MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
- MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
- MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
- MISC_REGISTERS_RESET_REG_2_UMAC0 |
- MISC_REGISTERS_RESET_REG_2_UMAC1 |
MISC_REGISTERS_RESET_REG_2_XMAC |
MISC_REGISTERS_RESET_REG_2_XMAC_SOFT;
@@ -8769,6 +8953,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
int cnt = 1000;
u32 val = 0;
u32 sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2;
+ u32 tags_63_32 = 0;
/* Empty the Tetris buffer, wait for 1s */
@@ -8778,10 +8963,14 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
port_is_idle_0 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_0);
port_is_idle_1 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_1);
pgl_exp_rom2 = REG_RD(bp, PXP2_REG_PGL_EXP_ROM2);
+ if (CHIP_IS_E3(bp))
+ tags_63_32 = REG_RD(bp, PGLUE_B_REG_TAGS_63_32);
+
if ((sr_cnt == 0x7e) && (blk_cnt == 0xa0) &&
((port_is_idle_0 & 0x1) == 0x1) &&
((port_is_idle_1 & 0x1) == 0x1) &&
- (pgl_exp_rom2 == 0xffffffff))
+ (pgl_exp_rom2 == 0xffffffff) &&
+ (!CHIP_IS_E3(bp) || (tags_63_32 == 0xffffffff)))
break;
usleep_range(1000, 1000);
} while (cnt-- > 0);
@@ -8838,9 +9027,6 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
/* TBD: Add resetting the NO_MCP mode DB here */
- /* PXP */
- bnx2x_pxp_prep(bp);
-
/* Open the gates #2, #3 and #4 */
bnx2x_set_234_gates(bp, false);
@@ -8850,7 +9036,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
return 0;
}
-int bnx2x_leader_reset(struct bnx2x *bp)
+static int bnx2x_leader_reset(struct bnx2x *bp)
{
int rc = 0;
bool global = bnx2x_reset_is_global(bp);
@@ -9234,7 +9420,7 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
bnx2x_undi_int_disable_e1h(bp);
}
-static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
{
u32 val, base_addr, offset, mask, reset_reg;
bool mac_stopped = false;
@@ -9301,8 +9487,7 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
-static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
- u8 inc)
+static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
{
u16 rcq, bd;
u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
@@ -9317,7 +9502,7 @@ static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
port, bd, rcq);
}
-static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
+static int bnx2x_prev_mcp_done(struct bnx2x *bp)
{
u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE,
DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET);
@@ -9329,7 +9514,21 @@ static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
return 0;
}
-static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
+static struct bnx2x_prev_path_list *
+ bnx2x_prev_path_get_entry(struct bnx2x *bp)
+{
+ struct bnx2x_prev_path_list *tmp_list;
+
+ list_for_each_entry(tmp_list, &bnx2x_prev_list, list)
+ if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
+ bp->pdev->bus->number == tmp_list->bus &&
+ BP_PATH(bp) == tmp_list->path)
+ return tmp_list;
+
+ return NULL;
+}
+
+static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
{
struct bnx2x_prev_path_list *tmp_list;
int rc = false;
@@ -9353,7 +9552,7 @@ static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
return rc;
}
-static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
+static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
{
struct bnx2x_prev_path_list *tmp_list;
int rc;
@@ -9367,6 +9566,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
tmp_list->bus = bp->pdev->bus->number;
tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
tmp_list->path = BP_PATH(bp);
+ tmp_list->undi = after_undi ? (1 << BP_PORT(bp)) : 0;
rc = down_interruptible(&bnx2x_prev_sem);
if (rc) {
@@ -9382,7 +9582,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
return rc;
}
-static int __devinit bnx2x_do_flr(struct bnx2x *bp)
+static int bnx2x_do_flr(struct bnx2x *bp)
{
int i;
u16 status;
@@ -9422,7 +9622,7 @@ clear:
return 0;
}
-static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+static int bnx2x_prev_unload_uncommon(struct bnx2x *bp)
{
int rc;
@@ -9460,9 +9660,10 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
return rc;
}
-static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
+static int bnx2x_prev_unload_common(struct bnx2x *bp)
{
u32 reset_reg, tmp_reg = 0, rc;
+ bool prev_undi = false;
/* It is possible a previous function received 'common' answer,
* but hasn't loaded yet, therefore creating a scenario of
* multiple functions receiving 'common' on the same path.
@@ -9477,7 +9678,6 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
/* Reset should be performed after BRB is emptied */
if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
u32 timer_count = 1000;
- bool prev_undi = false;
/* Close the MAC Rx to prevent BRB from filling up */
bnx2x_prev_unload_close_mac(bp);
@@ -9527,7 +9727,7 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
/* No packets are in the pipeline, path is ready for reset */
bnx2x_reset_common(bp);
- rc = bnx2x_prev_mark_path(bp);
+ rc = bnx2x_prev_mark_path(bp, prev_undi);
if (rc) {
bnx2x_prev_mcp_done(bp);
return rc;
@@ -9543,7 +9743,7 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
* to clear the interrupt which detected this from the pglueb and the was done
* bit
*/
-static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
+static void bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
{
if (!CHIP_IS_E1x(bp)) {
u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
@@ -9555,10 +9755,11 @@ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
}
}
-static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
+static int bnx2x_prev_unload(struct bnx2x *bp)
{
int time_counter = 10;
u32 rc, fw, hw_lock_reg, hw_lock_val;
+ struct bnx2x_prev_path_list *prev_list;
BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
/* clear hw from errors which may have resulted from an interrupted
@@ -9617,12 +9818,18 @@ static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
rc = -EBUSY;
}
+ /* Mark function if its port was used to boot from SAN */
+ prev_list = bnx2x_prev_path_get_entry(bp);
+ if (prev_list && (prev_list->undi & (1 << BP_PORT(bp))))
+ bp->link_params.feature_config_flags |=
+ FEATURE_CONFIG_BOOT_FROM_SAN;
+
BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
return rc;
}
-static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
{
u32 val, val2, val3, val4, id, boot_mode;
u16 pmc;
@@ -9701,6 +9908,14 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->link_params.shmem_base = bp->common.shmem_base;
bp->link_params.shmem2_base = bp->common.shmem2_base;
+ if (SHMEM2_RD(bp, size) >
+ (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+ bp->link_params.lfa_base =
+ REG_RD(bp, bp->common.shmem2_base +
+ (u32)offsetof(struct shmem2_region,
+ lfa_host_addr[BP_PORT(bp)]));
+ else
+ bp->link_params.lfa_base = 0;
BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n",
bp->common.shmem_base, bp->common.shmem2_base);
@@ -9748,6 +9963,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->link_params.feature_config_flags |=
(val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_MT_SUPPORTED) ?
+ FEATURE_CONFIG_MT_SUPPORT : 0;
+
bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ?
BC_SUPPORTS_PFC_STATS : 0;
@@ -9792,7 +10012,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
#define IGU_FID(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
#define IGU_VEC(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
-static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
+static int bnx2x_get_igu_cam_info(struct bnx2x *bp)
{
int pfid = BP_FUNC(bp);
int igu_sb_id;
@@ -9809,7 +10029,7 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
bp->igu_dsb_id = E1HVN_MAX * FP_SB_MAX_E1x +
(CHIP_MODE_IS_4_PORT(bp) ? pfid : vn);
- return;
+ return 0;
}
/* IGU in normal mode - read CAM */
@@ -9843,12 +10063,15 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);
#endif
- if (igu_sb_cnt == 0)
+ if (igu_sb_cnt == 0) {
BNX2X_ERR("CAM configuration error\n");
+ return -EINVAL;
+ }
+
+ return 0;
}
-static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
- u32 switch_cfg)
+static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
{
int cfg_size = 0, idx, port = BP_PORT(bp);
@@ -9946,7 +10169,7 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
bp->port.supported[1]);
}
-static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
+static void bnx2x_link_settings_requested(struct bnx2x *bp)
{
u32 link_config, idx, cfg_size = 0;
bp->port.advertising[0] = 0;
@@ -10115,11 +10338,13 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
bp->link_params.req_flow_ctrl[idx] = (link_config &
PORT_FEATURE_FLOW_CONTROL_MASK);
- if ((bp->link_params.req_flow_ctrl[idx] ==
- BNX2X_FLOW_CTRL_AUTO) &&
- !(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
- bp->link_params.req_flow_ctrl[idx] =
- BNX2X_FLOW_CTRL_NONE;
+ if (bp->link_params.req_flow_ctrl[idx] ==
+ BNX2X_FLOW_CTRL_AUTO) {
+ if (!(bp->port.supported[idx] & SUPPORTED_Autoneg))
+ bp->link_params.req_flow_ctrl[idx] =
+ BNX2X_FLOW_CTRL_NONE;
+ else
+ bnx2x_set_requested_fc(bp);
}
BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x advertising 0x%x\n",
@@ -10130,7 +10355,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
}
}
-static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
+static void bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
{
mac_hi = cpu_to_be16(mac_hi);
mac_lo = cpu_to_be32(mac_lo);
@@ -10138,7 +10363,7 @@ static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo));
}
-static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_port_hwinfo(struct bnx2x *bp)
{
int port = BP_PORT(bp);
u32 config;
@@ -10199,17 +10424,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->mdio.prtad =
XGXS_EXT_PHY_ADDR(ext_phy_config);
- /*
- * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
- * In MF mode, it is set to cover self test cases
- */
- if (IS_MF(bp))
- bp->port.need_hw_lock = 1;
- else
- bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
- bp->common.shmem_base,
- bp->common.shmem2_base);
-
/* Configure link feature according to nvram value */
eee_mode = (((SHMEM_RD(bp, dev_info.
port_feature_config[port].eee_power_mode)) &
@@ -10227,12 +10441,15 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
void bnx2x_get_iscsi_info(struct bnx2x *bp)
{
u32 no_flags = NO_ISCSI_FLAG;
-#ifdef BCM_CNIC
int port = BP_PORT(bp);
-
u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
drv_lic_key[port].max_iscsi_conn);
+ if (!CNIC_SUPPORT(bp)) {
+ bp->flags |= no_flags;
+ return;
+ }
+
/* Get the number of maximum allowed iSCSI connections */
bp->cnic_eth_dev.max_iscsi_conn =
(max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
@@ -10247,13 +10464,10 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp)
*/
if (!bp->cnic_eth_dev.max_iscsi_conn)
bp->flags |= no_flags;
-#else
- bp->flags |= no_flags;
-#endif
+
}
-#ifdef BCM_CNIC
-static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
+static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
{
/* Port info */
bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
@@ -10267,16 +10481,18 @@ static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower);
}
-#endif
-static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
+static void bnx2x_get_fcoe_info(struct bnx2x *bp)
{
-#ifdef BCM_CNIC
int port = BP_PORT(bp);
int func = BP_ABS_FUNC(bp);
-
u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
drv_lic_key[port].max_fcoe_conn);
+ if (!CNIC_SUPPORT(bp)) {
+ bp->flags |= NO_FCOE_FLAG;
+ return;
+ }
+
/* Get the number of maximum allowed FCoE connections */
bp->cnic_eth_dev.max_fcoe_conn =
(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
@@ -10311,8 +10527,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))
bnx2x_get_ext_wwn_info(bp, func);
- } else if (IS_MF_FCOE_SD(bp))
+ } else if (IS_MF_FCOE_SD(bp) && !CHIP_IS_E1x(bp)) {
bnx2x_get_ext_wwn_info(bp, func);
+ }
BNX2X_DEV_INFO("max_fcoe_conn 0x%x\n", bp->cnic_eth_dev.max_fcoe_conn);
@@ -10322,12 +10539,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
*/
if (!bp->cnic_eth_dev.max_fcoe_conn)
bp->flags |= NO_FCOE_FLAG;
-#else
- bp->flags |= NO_FCOE_FLAG;
-#endif
}
-static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+static void bnx2x_get_cnic_info(struct bnx2x *bp)
{
/*
* iSCSI may be dynamically disabled but reading
@@ -10338,143 +10552,162 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
bnx2x_get_fcoe_info(bp);
}
-static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
{
u32 val, val2;
int func = BP_ABS_FUNC(bp);
int port = BP_PORT(bp);
-#ifdef BCM_CNIC
u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
u8 *fip_mac = bp->fip_mac;
-#endif
- /* Zero primary MAC configuration */
- memset(bp->dev->dev_addr, 0, ETH_ALEN);
-
- if (BP_NOMCP(bp)) {
- BNX2X_ERROR("warning: random MAC workaround active\n");
- eth_hw_addr_random(bp->dev);
- } else if (IS_MF(bp)) {
- val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
- val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
- if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
- (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
- bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
- /*
- * iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+ if (IS_MF(bp)) {
+ /* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
* FCoE MAC then the appropriate feature should be disabled.
- *
- * In non SD mode features configuration comes from
- * struct func_ext_config.
+ * In non SD mode features configuration comes from struct
+ * func_ext_config.
*/
- if (!IS_MF_SD(bp)) {
+ if (!IS_MF_SD(bp) && !CHIP_IS_E1x(bp)) {
u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
val2 = MF_CFG_RD(bp, func_ext_config[func].
- iscsi_mac_addr_upper);
+ iscsi_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
- iscsi_mac_addr_lower);
+ iscsi_mac_addr_lower);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
- BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
- iscsi_mac);
- } else
+ BNX2X_DEV_INFO
+ ("Read iSCSI MAC: %pM\n", iscsi_mac);
+ } else {
bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+ }
if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
val2 = MF_CFG_RD(bp, func_ext_config[func].
- fcoe_mac_addr_upper);
+ fcoe_mac_addr_upper);
val = MF_CFG_RD(bp, func_ext_config[func].
- fcoe_mac_addr_lower);
+ fcoe_mac_addr_lower);
bnx2x_set_mac_buf(fip_mac, val, val2);
- BNX2X_DEV_INFO("Read FCoE L2 MAC: %pM\n",
- fip_mac);
-
- } else
+ BNX2X_DEV_INFO
+ ("Read FCoE L2 MAC: %pM\n", fip_mac);
+ } else {
bp->flags |= NO_FCOE_FLAG;
+ }
bp->mf_ext_config = cfg;
} else { /* SD MODE */
- if (IS_MF_STORAGE_SD(bp)) {
- if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
- /* use primary mac as iscsi mac */
- memcpy(iscsi_mac, bp->dev->dev_addr,
- ETH_ALEN);
-
- BNX2X_DEV_INFO("SD ISCSI MODE\n");
- BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
- iscsi_mac);
- } else { /* FCoE */
- memcpy(fip_mac, bp->dev->dev_addr,
- ETH_ALEN);
- BNX2X_DEV_INFO("SD FCoE MODE\n");
- BNX2X_DEV_INFO("Read FIP MAC: %pM\n",
- fip_mac);
- }
- /* Zero primary MAC configuration */
- memset(bp->dev->dev_addr, 0, ETH_ALEN);
+ if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
+ /* use primary mac as iscsi mac */
+ memcpy(iscsi_mac, bp->dev->dev_addr, ETH_ALEN);
+
+ BNX2X_DEV_INFO("SD ISCSI MODE\n");
+ BNX2X_DEV_INFO
+ ("Read iSCSI MAC: %pM\n", iscsi_mac);
+ } else if (BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) {
+ /* use primary mac as fip mac */
+ memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+ BNX2X_DEV_INFO("SD FCoE MODE\n");
+ BNX2X_DEV_INFO
+ ("Read FIP MAC: %pM\n", fip_mac);
}
}
+ if (IS_MF_STORAGE_SD(bp))
+ /* Zero primary MAC configuration */
+ memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
if (IS_MF_FCOE_AFEX(bp))
/* use FIP MAC as primary MAC */
memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN);
-#endif
} else {
- /* in SF read MACs from port configuration */
- val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
- val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
- bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
- iscsi_mac_upper);
+ iscsi_mac_upper);
val = SHMEM_RD(bp, dev_info.port_hw_config[port].
- iscsi_mac_lower);
+ iscsi_mac_lower);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
- fcoe_fip_mac_upper);
+ fcoe_fip_mac_upper);
val = SHMEM_RD(bp, dev_info.port_hw_config[port].
- fcoe_fip_mac_lower);
+ fcoe_fip_mac_lower);
bnx2x_set_mac_buf(fip_mac, val, val2);
-#endif
}
- memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
- memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
-
-#ifdef BCM_CNIC
- /* Disable iSCSI if MAC configuration is
- * invalid.
- */
+ /* Disable iSCSI OOO if MAC configuration is invalid. */
if (!is_valid_ether_addr(iscsi_mac)) {
- bp->flags |= NO_ISCSI_FLAG;
+ bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
memset(iscsi_mac, 0, ETH_ALEN);
}
- /* Disable FCoE if MAC configuration is
- * invalid.
- */
+ /* Disable FCoE if MAC configuration is invalid. */
if (!is_valid_ether_addr(fip_mac)) {
bp->flags |= NO_FCOE_FLAG;
memset(bp->fip_mac, 0, ETH_ALEN);
}
-#endif
+}
+
+static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+{
+ u32 val, val2;
+ int func = BP_ABS_FUNC(bp);
+ int port = BP_PORT(bp);
+
+ /* Zero primary MAC configuration */
+ memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
+ if (BP_NOMCP(bp)) {
+ BNX2X_ERROR("warning: random MAC workaround active\n");
+ eth_hw_addr_random(bp->dev);
+ } else if (IS_MF(bp)) {
+ val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+ val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
+ if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+ (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
+ bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+ if (CNIC_SUPPORT(bp))
+ bnx2x_get_cnic_mac_hwinfo(bp);
+ } else {
+ /* in SF read MACs from port configuration */
+ val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
+ val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
+ bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+ if (CNIC_SUPPORT(bp))
+ bnx2x_get_cnic_mac_hwinfo(bp);
+ }
+
+ memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
+ memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
dev_err(&bp->pdev->dev,
"bad Ethernet MAC address configuration: %pM\n"
"change it manually before bringing up the appropriate network interface\n",
bp->dev->dev_addr);
+}
+static bool bnx2x_get_dropless_info(struct bnx2x *bp)
+{
+ int tmp;
+ u32 cfg;
+ if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
+ /* Take function: tmp = func */
+ tmp = BP_ABS_FUNC(bp);
+ cfg = MF_CFG_RD(bp, func_ext_config[tmp].func_cfg);
+ cfg = !!(cfg & MACP_FUNC_CFG_PAUSE_ON_HOST_RING);
+ } else {
+ /* Take port: tmp = port */
+ tmp = BP_PORT(bp);
+ cfg = SHMEM_RD(bp,
+ dev_info.port_hw_config[tmp].generic_features);
+ cfg = !!(cfg & PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED);
+ }
+ return cfg;
}
-static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
+static int bnx2x_get_hwinfo(struct bnx2x *bp)
{
int /*abs*/func = BP_ABS_FUNC(bp);
int vn;
@@ -10516,6 +10749,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
dev_err(&bp->pdev->dev,
"FORCING Normal Mode failed!!!\n");
+ bnx2x_release_hw_lock(bp,
+ HW_LOCK_RESOURCE_RESET);
return -EPERM;
}
}
@@ -10526,9 +10761,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
} else
BNX2X_DEV_INFO("IGU Normal Mode\n");
- bnx2x_get_igu_cam_info(bp);
-
+ rc = bnx2x_get_igu_cam_info(bp);
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+ if (rc)
+ return rc;
}
/*
@@ -10697,7 +10933,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
return rc;
}
-static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp)
+static void bnx2x_read_fwinfo(struct bnx2x *bp)
{
int cnt, i, block_end, rodi;
char vpd_start[BNX2X_VPD_LEN+1];
@@ -10782,7 +11018,7 @@ out_not_found:
return;
}
-static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+static void bnx2x_set_modes_bitmap(struct bnx2x *bp)
{
u32 flags = 0;
@@ -10832,7 +11068,7 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
INIT_MODE_FLAGS(bp) = flags;
}
-static int __devinit bnx2x_init_bp(struct bnx2x *bp)
+static int bnx2x_init_bp(struct bnx2x *bp)
{
int func;
int rc;
@@ -10840,9 +11076,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
spin_lock_init(&bp->stats_lock);
-#ifdef BCM_CNIC
- mutex_init(&bp->cnic_mutex);
-#endif
+
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
@@ -10880,10 +11114,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n");
bp->disable_tpa = disable_tpa;
-
-#ifdef BCM_CNIC
bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp);
-#endif
/* Set TPA flags */
if (bp->disable_tpa) {
@@ -10897,7 +11128,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
if (CHIP_IS_E1(bp))
bp->dropless_fc = 0;
else
- bp->dropless_fc = dropless_fc;
+ bp->dropless_fc = dropless_fc | bnx2x_get_dropless_info(bp);
bp->mrrs = mrrs;
@@ -10914,15 +11145,20 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2x_timer;
- bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
- bnx2x_dcbx_init_params(bp);
+ if (SHMEM2_HAS(bp, dcbx_lldp_params_offset) &&
+ SHMEM2_HAS(bp, dcbx_lldp_dcbx_stat_offset) &&
+ SHMEM2_RD(bp, dcbx_lldp_params_offset) &&
+ SHMEM2_RD(bp, dcbx_lldp_dcbx_stat_offset)) {
+ bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
+ bnx2x_dcbx_init_params(bp);
+ } else {
+ bnx2x_dcbx_set_state(bp, false, BNX2X_DCBX_ENABLED_OFF);
+ }
-#ifdef BCM_CNIC
if (CHIP_IS_E1x(bp))
bp->cnic_base_cl_id = FP_SB_MAX_E1x;
else
bp->cnic_base_cl_id = FP_SB_MAX_E2;
-#endif
/* multiple tx priority */
if (CHIP_IS_E1x(bp))
@@ -10932,6 +11168,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
if (CHIP_IS_E3B0(bp))
bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
+ /* We need at least one default status block for slow-path events,
+ * second status block for the L2 queue, and a third status block for
+ * CNIC if supproted.
+ */
+ if (CNIC_SUPPORT(bp))
+ bp->min_msix_vec_cnt = 3;
+ else
+ bp->min_msix_vec_cnt = 2;
+ BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
+
return rc;
}
@@ -11168,11 +11414,9 @@ void bnx2x_set_rx_mode(struct net_device *dev)
}
bp->rx_mode = rx_mode;
-#ifdef BCM_CNIC
/* handle ISCSI SD mode */
if (IS_MF_ISCSI_SD(bp))
bp->rx_mode = BNX2X_RX_MODE_NONE;
-#endif
/* Schedule the rx_mode command */
if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
@@ -11284,7 +11528,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
#endif
.ndo_setup_tc = bnx2x_setup_tc,
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
.ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn,
#endif
};
@@ -11307,9 +11551,8 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
return 0;
}
-static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
- struct net_device *dev,
- unsigned long board_type)
+static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
+ unsigned long board_type)
{
struct bnx2x *bp;
int rc;
@@ -11346,6 +11589,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
goto err_out_disable;
}
+ pci_read_config_dword(pdev, PCICFG_REVISION_ID_OFFSET, &pci_cfg_dword);
+ if ((pci_cfg_dword & PCICFG_REVESION_ID_MASK) ==
+ PCICFG_REVESION_ID_ERROR_VAL) {
+ pr_err("PCI device error, probably due to fan failure, aborting\n");
+ rc = -ENODEV;
+ goto err_out_disable;
+ }
+
if (atomic_read(&pdev->enable_cnt) == 1) {
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) {
@@ -11481,8 +11732,7 @@ err_out:
return rc;
}
-static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
- int *width, int *speed)
+static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed)
{
u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
@@ -11750,9 +12000,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
{
int cid_count = BNX2X_L2_MAX_CID(bp);
-#ifdef BCM_CNIC
- cid_count += CNIC_CID_MAX;
-#endif
+ if (CNIC_SUPPORT(bp))
+ cid_count += CNIC_CID_MAX;
return roundup(cid_count, QM_CID_ROUND);
}
@@ -11762,7 +12011,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
* @dev: pci device
*
*/
-static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
+ int cnic_cnt)
{
int pos;
u16 control;
@@ -11774,7 +12024,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
* one fast path queue: one FP queue + SB for CNIC
*/
if (!pos)
- return 1 + CNIC_PRESENT;
+ return 1 + cnic_cnt;
/*
* The value in the PCI configuration space is the index of the last
@@ -11786,14 +12036,16 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
return control & PCI_MSIX_FLAGS_QSIZE;
}
-static int __devinit bnx2x_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *);
+
+static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev = NULL;
struct bnx2x *bp;
int pcie_width, pcie_speed;
int rc, max_non_def_sbs;
int rx_count, tx_count, rss_count, doorbell_size;
+ int cnic_cnt;
/*
* An estimated maximum supported CoS number according to the chip
* version.
@@ -11837,21 +12089,22 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
return -ENODEV;
}
- max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
+ cnic_cnt = 1;
+ max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
WARN_ON(!max_non_def_sbs);
/* Maximum number of RSS queues: one IGU SB goes to CNIC */
- rss_count = max_non_def_sbs - CNIC_PRESENT;
+ rss_count = max_non_def_sbs - cnic_cnt;
/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
- rx_count = rss_count + FCOE_PRESENT;
+ rx_count = rss_count + cnic_cnt;
/*
* Maximum number of netdev Tx queues:
* Maximum TSS queues * Maximum supported number of CoS + FCoE L2
*/
- tx_count = rss_count * max_cos_est + FCOE_PRESENT;
+ tx_count = rss_count * max_cos_est + cnic_cnt;
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
@@ -11862,6 +12115,9 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
bp->igu_sb_cnt = max_non_def_sbs;
bp->msg_enable = debug;
+ bp->cnic_support = cnic_cnt;
+ bp->cnic_probe = bnx2x_cnic_probe;
+
pci_set_drvdata(pdev, dev);
rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
@@ -11870,6 +12126,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
return rc;
}
+ BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off");
BNX2X_DEV_INFO("max_non_def_sbs %d\n", max_non_def_sbs);
BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n",
@@ -11902,10 +12159,10 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
/* calc qm_cid_count */
bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
-#ifdef BCM_CNIC
- /* disable FCOE L2 queue for E1x */
+ /* disable FCOE L2 queue for E1x*/
if (CHIP_IS_E1x(bp))
bp->flags |= NO_FCOE_FLAG;
+
/* disable FCOE for 57840 device, until FW supports it */
switch (ent->driver_data) {
case BCM57840_O:
@@ -11915,8 +12172,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
case BCM57840_MF:
bp->flags |= NO_FCOE_FLAG;
}
-#endif
-
/* Set bp->num_queues for MSI-X mode*/
bnx2x_set_num_queues(bp);
@@ -11932,14 +12187,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
goto init_one_exit;
}
-#ifdef BCM_CNIC
+
if (!NO_FCOE(bp)) {
/* Add storage MAC address */
rtnl_lock();
dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
rtnl_unlock();
}
-#endif
bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
@@ -11973,7 +12227,7 @@ init_one_exit:
return rc;
}
-static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
+static void bnx2x_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2x *bp;
@@ -11984,14 +12238,12 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
}
bp = netdev_priv(dev);
-#ifdef BCM_CNIC
/* Delete storage MAC address */
if (!NO_FCOE(bp)) {
rtnl_lock();
dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
rtnl_unlock();
}
-#endif
#ifdef BCM_DCBNL
/* Delete app tlvs from dcbnl */
@@ -12039,15 +12291,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bp->rx_mode = BNX2X_RX_MODE_NONE;
-#ifdef BCM_CNIC
- bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
+ if (CNIC_LOADED(bp))
+ bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
/* Stop Tx */
bnx2x_tx_disable(bp);
bnx2x_netif_stop(bp, 0);
/* Delete all NAPI objects */
bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
del_timer_sync(&bp->timer);
@@ -12188,7 +12442,7 @@ static struct pci_driver bnx2x_pci_driver = {
.name = DRV_MODULE_NAME,
.id_table = bnx2x_pci_tbl,
.probe = bnx2x_init_one,
- .remove = __devexit_p(bnx2x_remove_one),
+ .remove = bnx2x_remove_one,
.suspend = bnx2x_suspend,
.resume = bnx2x_resume,
.err_handler = &bnx2x_err_handler,
@@ -12238,7 +12492,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp)
module_init(bnx2x_init);
module_exit(bnx2x_cleanup);
-#ifdef BCM_CNIC
/**
* bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
*
@@ -12691,12 +12944,31 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
{
struct bnx2x *bp = netdev_priv(dev);
struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ int rc;
+
+ DP(NETIF_MSG_IFUP, "Register_cnic called\n");
if (ops == NULL) {
BNX2X_ERR("NULL ops received\n");
return -EINVAL;
}
+ if (!CNIC_SUPPORT(bp)) {
+ BNX2X_ERR("Can't register CNIC when not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (!CNIC_LOADED(bp)) {
+ rc = bnx2x_load_cnic(bp);
+ if (rc) {
+ BNX2X_ERR("CNIC-related load failed\n");
+ return rc;
+ }
+
+ }
+
+ bp->cnic_enabled = true;
+
bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!bp->cnic_kwq)
return -ENOMEM;
@@ -12786,7 +13058,5 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
cp->starting_cid);
return cp;
}
-EXPORT_SYMBOL(bnx2x_cnic_probe);
-#endif /* BCM_CNIC */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index 1b1999d34c71..bc2f65b32649 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -2107,6 +2107,7 @@
#define NIG_REG_LLH1_ERROR_MASK 0x10090
/* [RW 8] event id for llh1 */
#define NIG_REG_LLH1_EVENT_ID 0x10088
+#define NIG_REG_LLH1_FUNC_EN 0x16104
#define NIG_REG_LLH1_FUNC_MEM 0x161c0
#define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160
#define NIG_REG_LLH1_FUNC_MEM_SIZE 16
@@ -2302,6 +2303,15 @@
* set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
* accommodate the 9 input clients to ETS arbiter. */
#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ * When MCP-to-host paths for both ports 0 and 1 are disabled - the arbiter
+ * for BRB LB interface is bypassed and PBF LB traffic is always selected to
+ * send to BRB LB.
+ */
+#define NIG_REG_P0_TX_MNG_HOST_ENABLE 0x182f4
#define NIG_REG_P1_HWPFC_ENABLE 0x181d0
#define NIG_REG_P1_MAC_IN_EN 0x185c0
/* [RW 1] Output enable for TX MAC interface */
@@ -2418,6 +2428,12 @@
#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4
/* [R 1] TX FIFO for transmitting data to MAC is empty. */
#define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ */
+#define NIG_REG_P1_TX_MNG_HOST_ENABLE 0x182f8
/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
forwarded to the host. */
#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8
@@ -5482,6 +5498,7 @@
#define XMAC_CTRL_REG_RX_EN (0x1<<1)
#define XMAC_CTRL_REG_SOFT_RESET (0x1<<6)
#define XMAC_CTRL_REG_TX_EN (0x1<<0)
+#define XMAC_CTRL_REG_XLGMII_ALIGN_ENB (0x1<<7)
#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18)
#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17)
#define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON (0x1<<1)
@@ -5502,11 +5519,14 @@
#define XMAC_REG_PAUSE_CTRL 0x68
#define XMAC_REG_PFC_CTRL 0x70
#define XMAC_REG_PFC_CTRL_HI 0x74
+#define XMAC_REG_RX_LSS_CTRL 0x50
#define XMAC_REG_RX_LSS_STATUS 0x58
/* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
* CRC in strip mode */
#define XMAC_REG_RX_MAX_SIZE 0x40
#define XMAC_REG_TX_CTRL 0x20
+#define XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE (0x1<<0)
+#define XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE (0x1<<1)
/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
header pointer. */
@@ -5922,6 +5942,16 @@
#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1
#define MISC_REGISTERS_SPIO_OUTPUT_LOW 0
#define MISC_REGISTERS_SPIO_SET_POS 8
+#define MISC_SPIO_CLR_POS 16
+#define MISC_SPIO_FLOAT (0xffL<<24)
+#define MISC_SPIO_FLOAT_POS 24
+#define MISC_SPIO_INPUT_HI_Z 2
+#define MISC_SPIO_INT_OLD_SET_POS 16
+#define MISC_SPIO_OUTPUT_HIGH 1
+#define MISC_SPIO_OUTPUT_LOW 0
+#define MISC_SPIO_SET_POS 8
+#define MISC_SPIO_SPIO4 0x10
+#define MISC_SPIO_SPIO5 0x20
#define HW_LOCK_MAX_RESOURCE_VALUE 31
#define HW_LOCK_RESOURCE_DCBX_ADMIN_MIB 13
#define HW_LOCK_RESOURCE_DRV_FLAGS 10
@@ -6130,7 +6160,9 @@
#define PCICFG_COMMAND_INT_DISABLE (1<<10)
#define PCICFG_COMMAND_RESERVED (0x1f<<11)
#define PCICFG_STATUS_OFFSET 0x06
-#define PCICFG_REVESION_ID_OFFSET 0x08
+#define PCICFG_REVISION_ID_OFFSET 0x08
+#define PCICFG_REVESION_ID_MASK 0xff
+#define PCICFG_REVESION_ID_ERROR_VAL 0xff
#define PCICFG_CACHE_LINE_SIZE 0x0c
#define PCICFG_LATENCY_TIMER 0x0d
#define PCICFG_BAR_1_LOW 0x10
@@ -6672,6 +6704,7 @@
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 0x1B00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 0x1E00
#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 0x1F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2 0x3900
#define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130
@@ -7046,7 +7079,8 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2 0x12
#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY 0x4000
#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ 0x8000
-#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150 0x96
+#define MDIO_WC_REG_PCS_STATUS2 0x0021
+#define MDIO_WC_REG_PMD_KR_CONTROL 0x0096
#define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000
#define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e
#define MDIO_WC_REG_XGXSBLK1_DESKEW 0x8010
@@ -7078,6 +7112,7 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_PAR_DET_10G_STATUS 0x8130
#define MDIO_WC_REG_PAR_DET_10G_CTRL 0x8131
#define MDIO_WC_REG_XGXS_X2_CONTROL2 0x8141
+#define MDIO_WC_REG_XGXS_X2_CONTROL3 0x8142
#define MDIO_WC_REG_XGXS_RX_LN_SWAP1 0x816B
#define MDIO_WC_REG_XGXS_TX_LN_SWAP1 0x8169
#define MDIO_WC_REG_GP2_STATUS_GP_2_0 0x81d0
@@ -7112,6 +7147,7 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET 0x0a
#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK 0x7c00
#define MDIO_WC_REG_TX_FIR_TAP_ENABLE 0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP 0x82e2
#define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL 0x82e3
#define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL 0x82e6
#define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL 0x82e7
@@ -7129,9 +7165,16 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_DIGITAL4_MISC5 0x833e
#define MDIO_WC_REG_DIGITAL5_MISC6 0x8345
#define MDIO_WC_REG_DIGITAL5_MISC7 0x8349
+#define MDIO_WC_REG_DIGITAL5_LINK_STATUS 0x834d
#define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e
#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350
#define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368
+#define MDIO_WC_REG_CL73_USERB0_CTRL 0x8370
+#define MDIO_WC_REG_CL73_USERB0_USTAT 0x8371
+#define MDIO_WC_REG_CL73_BAM_CTRL1 0x8372
+#define MDIO_WC_REG_CL73_BAM_CTRL2 0x8373
+#define MDIO_WC_REG_CL73_BAM_CTRL3 0x8374
+#define MDIO_WC_REG_CL73_BAM_CODE_FIELD 0x837b
#define MDIO_WC_REG_EEE_COMBO_CONTROL0 0x8390
#define MDIO_WC_REG_TX66_CONTROL 0x83b0
#define MDIO_WC_REG_RX66_CONTROL 0x83c0
@@ -7145,7 +7188,17 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_RX66_SCW3_MASK 0x83c9
#define MDIO_WC_REG_FX100_CTRL1 0x8400
#define MDIO_WC_REG_FX100_CTRL3 0x8402
-
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL5 0x8436
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL6 0x8437
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL7 0x8438
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL9 0x8439
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL10 0x843a
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL11 0x843b
+#define MDIO_WC_REG_ETA_CL73_OUI1 0x8453
+#define MDIO_WC_REG_ETA_CL73_OUI2 0x8454
+#define MDIO_WC_REG_ETA_CL73_OUI3 0x8455
+#define MDIO_WC_REG_ETA_CL73_LD_BAM_CODE 0x8456
+#define MDIO_WC_REG_ETA_CL73_LD_UD_CODE 0x8457
#define MDIO_WC_REG_MICROBLK_CMD 0xffc2
#define MDIO_WC_REG_MICROBLK_DL_STATUS 0xffc5
#define MDIO_WC_REG_MICROBLK_CMD3 0xffcc
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 614981c02264..09b625e0fdaa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -4318,7 +4318,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
if (o->next_tx_only >= o->max_cos)
/* >= becuase tx only must always be smaller than cos since the
- * primary connection suports COS 0
+ * primary connection supports COS 0
*/
BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
o->next_tx_only, o->max_cos);
@@ -5350,12 +5350,24 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
(!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
next_state = BNX2X_F_STATE_STARTED;
+
+ /* Switch_update ramrod can be sent in either started or
+ * tx_stopped state, and it doesn't change the state.
+ */
+ else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+ (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+ next_state = BNX2X_F_STATE_STARTED;
+
else if (cmd == BNX2X_F_CMD_TX_STOP)
next_state = BNX2X_F_STATE_TX_STOPPED;
break;
case BNX2X_F_STATE_TX_STOPPED:
- if (cmd == BNX2X_F_CMD_TX_START)
+ if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+ (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+ next_state = BNX2X_F_STATE_TX_STOPPED;
+
+ else if (cmd == BNX2X_F_CMD_TX_START)
next_state = BNX2X_F_STATE_STARTED;
break;
@@ -5637,6 +5649,28 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
U64_LO(data_mapping), NONE_CONNECTION_TYPE);
}
+static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct function_update_data *rdata =
+ (struct function_update_data *)o->rdata;
+ dma_addr_t data_mapping = o->rdata_mapping;
+ struct bnx2x_func_switch_update_params *switch_update_params =
+ &params->params.switch_update;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data with provided parameters */
+ rdata->tx_switch_suspend_change_flg = 1;
+ rdata->tx_switch_suspend = switch_update_params->suspend;
+ rdata->echo = SWITCH_UPDATE;
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
@@ -5657,6 +5691,7 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
cpu_to_le16(afex_update_params->afex_default_vlan);
rdata->allowed_priorities_change_flg = 1;
rdata->allowed_priorities = afex_update_params->allowed_priorities;
+ rdata->echo = AFEX_UPDATE;
/* No need for an explicit memory barrier here as long we would
* need to ensure the ordering of writing to the SPQ element
@@ -5773,6 +5808,8 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
return bnx2x_func_send_tx_stop(bp, params);
case BNX2X_F_CMD_TX_START:
return bnx2x_func_send_tx_start(bp, params);
+ case BNX2X_F_CMD_SWITCH_UPDATE:
+ return bnx2x_func_send_switch_update(bp, params);
default:
BNX2X_ERR("Unknown command: %d\n", params->cmd);
return -EINVAL;
@@ -5818,16 +5855,30 @@ int bnx2x_func_state_change(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
struct bnx2x_func_sp_obj *o = params->f_obj;
- int rc;
+ int rc, cnt = 300;
enum bnx2x_func_cmd cmd = params->cmd;
unsigned long *pending = &o->pending;
mutex_lock(&o->one_pending_mutex);
/* Check that the requested transition is legal */
- if (o->check_transition(bp, o, params)) {
+ rc = o->check_transition(bp, o, params);
+ if ((rc == -EBUSY) &&
+ (test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
+ while ((rc == -EBUSY) && (--cnt > 0)) {
+ mutex_unlock(&o->one_pending_mutex);
+ msleep(10);
+ mutex_lock(&o->one_pending_mutex);
+ rc = o->check_transition(bp, o, params);
+ }
+ if (rc == -EBUSY) {
+ mutex_unlock(&o->one_pending_mutex);
+ BNX2X_ERR("timeout waiting for previous ramrod completion\n");
+ return rc;
+ }
+ } else if (rc) {
mutex_unlock(&o->one_pending_mutex);
- return -EINVAL;
+ return rc;
}
/* Set "pending" bit */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index acf2fe4ca608..adbd91b1bdfc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -40,6 +40,12 @@ enum {
* pending commands list.
*/
RAMROD_CONT,
+ /* If there is another pending ramrod, wait until it finishes and
+ * re-try to submit this one. This flag can be set only in sleepable
+ * context, and should not be set from the context that completes the
+ * ramrods as deadlock will occur.
+ */
+ RAMROD_RETRY,
};
typedef enum {
@@ -1061,6 +1067,7 @@ enum bnx2x_func_cmd {
BNX2X_F_CMD_AFEX_VIFLISTS,
BNX2X_F_CMD_TX_STOP,
BNX2X_F_CMD_TX_START,
+ BNX2X_F_CMD_SWITCH_UPDATE,
BNX2X_F_CMD_MAX,
};
@@ -1103,6 +1110,10 @@ struct bnx2x_func_start_params {
u8 network_cos_mode;
};
+struct bnx2x_func_switch_update_params {
+ u8 suspend;
+};
+
struct bnx2x_func_afex_update_params {
u16 vif_id;
u16 afex_default_vlan;
@@ -1136,6 +1147,7 @@ struct bnx2x_func_state_params {
struct bnx2x_func_hw_init_params hw_init;
struct bnx2x_func_hw_reset_params hw_reset;
struct bnx2x_func_start_params start;
+ struct bnx2x_func_switch_update_params switch_update;
struct bnx2x_func_afex_update_params afex_update;
struct bnx2x_func_afex_viflists_params afex_viflists;
struct bnx2x_func_tx_start_params tx_start;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 348ed02d3c69..89ec0667140a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1149,6 +1149,7 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
UPDATE_ESTAT_QSTAT(rx_err_discard_pkt);
UPDATE_ESTAT_QSTAT(rx_skb_alloc_failed);
UPDATE_ESTAT_QSTAT(hw_csum_err);
+ UPDATE_ESTAT_QSTAT(driver_filtered_tx_pkt);
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
index 24b8e505b60c..b4d7b26c7fe7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
@@ -203,6 +203,7 @@ struct bnx2x_eth_stats {
/* Recovery */
u32 recoverable_error;
u32 unrecoverable_error;
+ u32 driver_filtered_tx_pkt;
/* src: Clear-on-Read register; Will not survive PMF Migration */
u32 eee_tx_lpi;
};
@@ -264,6 +265,7 @@ struct bnx2x_eth_q_stats {
u32 total_tpa_aggregated_frames_lo;
u32 total_tpa_bytes_hi;
u32 total_tpa_bytes_lo;
+ u32 driver_filtered_tx_pkt;
};
struct bnx2x_eth_stats_old {
@@ -315,6 +317,7 @@ struct bnx2x_eth_q_stats_old {
u32 rx_err_discard_pkt_old;
u32 rx_skb_alloc_failed_old;
u32 hw_csum_err_old;
+ u32 driver_filtered_tx_pkt_old;
};
struct bnx2x_net_stats_old {
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index cc8434fd606e..df8c30d1a52c 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -40,8 +40,10 @@
#include <net/ip6_checksum.h>
#include <scsi/iscsi_if.h>
+#define BCM_CNIC 1
#include "cnic_if.h"
#include "bnx2.h"
+#include "bnx2x/bnx2x.h"
#include "bnx2x/bnx2x_reg.h"
#include "bnx2x/bnx2x_fw_defs.h"
#include "bnx2x/bnx2x_hsi.h"
@@ -51,10 +53,10 @@
#include "cnic.h"
#include "cnic_defs.h"
-#define DRV_MODULE_NAME "cnic"
+#define CNIC_MODULE_NAME "cnic"
-static char version[] __devinitdata =
- "Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+static char version[] =
+ "Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
"Chen (zongxi@broadcom.com");
@@ -724,7 +726,7 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
for (i = 0; i < dma->num_pages; i++) {
if (dma->pg_arr[i]) {
- dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE,
+ dma_free_coherent(&dev->pcidev->dev, BNX2_PAGE_SIZE,
dma->pg_arr[i], dma->pg_map_arr[i]);
dma->pg_arr[i] = NULL;
}
@@ -783,7 +785,7 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
for (i = 0; i < pages; i++) {
dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev,
- BCM_PAGE_SIZE,
+ BNX2_PAGE_SIZE,
&dma->pg_map_arr[i],
GFP_ATOMIC);
if (dma->pg_arr[i] == NULL)
@@ -792,8 +794,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
if (!use_pg_tbl)
return 0;
- dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) &
- ~(BCM_PAGE_SIZE - 1);
+ dma->pgtbl_size = ((pages * 8) + BNX2_PAGE_SIZE - 1) &
+ ~(BNX2_PAGE_SIZE - 1);
dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size,
&dma->pgtbl_map, GFP_ATOMIC);
if (dma->pgtbl == NULL)
@@ -895,11 +897,11 @@ static int cnic_alloc_context(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(cp) == BNX2_CHIP_5709) {
int i, k, arr_size;
- cp->ctx_blk_size = BCM_PAGE_SIZE;
- cp->cids_per_blk = BCM_PAGE_SIZE / 128;
+ cp->ctx_blk_size = BNX2_PAGE_SIZE;
+ cp->cids_per_blk = BNX2_PAGE_SIZE / 128;
arr_size = BNX2_MAX_CID / cp->cids_per_blk *
sizeof(struct cnic_ctx);
cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL);
@@ -931,7 +933,7 @@ static int cnic_alloc_context(struct cnic_dev *dev)
for (i = 0; i < cp->ctx_blks; i++) {
cp->ctx_arr[i].ctx =
dma_alloc_coherent(&dev->pcidev->dev,
- BCM_PAGE_SIZE,
+ BNX2_PAGE_SIZE,
&cp->ctx_arr[i].mapping,
GFP_KERNEL);
if (cp->ctx_arr[i].ctx == NULL)
@@ -1011,7 +1013,7 @@ static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages)
if (udev->l2_ring)
return 0;
- udev->l2_ring_size = pages * BCM_PAGE_SIZE;
+ udev->l2_ring_size = pages * BNX2_PAGE_SIZE;
udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
&udev->l2_ring_map,
GFP_KERNEL | __GFP_COMP);
@@ -1234,8 +1236,6 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
int i, j, n, ret, pages;
struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
- cp->iro_arr = ethdev->iro_arr;
-
cp->max_cid_space = MAX_ISCSI_TBL_SZ;
cp->iscsi_start_cid = start_cid;
cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
@@ -1430,6 +1430,7 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type,
static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
int hq_bds, pages;
u32 pfid = cp->pfid;
@@ -1512,6 +1513,7 @@ static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 pfid = cp->pfid;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
@@ -2048,6 +2050,7 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 pfid = cp->pfid;
u8 *mac = dev->mac_addr;
@@ -2084,6 +2087,7 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
u16 tstorm_flags = 0;
@@ -2103,6 +2107,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
u32 num, int *work)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct l4_kwq_connect_req1 *kwqe1 =
(struct l4_kwq_connect_req1 *) wqes[0];
struct l4_kwq_connect_req3 *kwqe3;
@@ -2898,7 +2903,7 @@ static int cnic_l2_completion(struct cnic_local *cp)
u16 hw_cons, sw_cons;
struct cnic_uio_dev *udev = cp->udev;
union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
- (udev->l2_ring + (2 * BCM_PAGE_SIZE));
+ (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
u32 cmd;
int comp = 0;
@@ -3853,12 +3858,17 @@ static int cnic_cm_abort(struct cnic_sock *csk)
return cnic_cm_abort_req(csk);
/* Getting here means that we haven't started connect, or
- * connect was not successful.
+ * connect was not successful, or it has been reset by the target.
*/
cp->close_conn(csk, opcode);
- if (csk->state != opcode)
+ if (csk->state != opcode) {
+ /* Wait for remote reset sequence to complete */
+ while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+ msleep(1);
+
return -EALREADY;
+ }
return 0;
}
@@ -3872,6 +3882,10 @@ static int cnic_cm_close(struct cnic_sock *csk)
csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP;
return cnic_cm_close_req(csk);
} else {
+ /* Wait for remote reset sequence to complete */
+ while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+ msleep(1);
+
return -EALREADY;
}
return 0;
@@ -4200,6 +4214,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 pfid = cp->pfid;
u32 port = CNIC_PORT(cp);
@@ -4349,7 +4364,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
int ret = 0, i;
u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0;
- if (CHIP_NUM(cp) != CHIP_NUM_5709)
+ if (BNX2_CHIP(cp) != BNX2_CHIP_5709)
return 0;
for (i = 0; i < cp->ctx_blks; i++) {
@@ -4357,7 +4372,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk;
u32 val;
- memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE);
+ memset(cp->ctx_arr[i].ctx, 0, BNX2_PAGE_SIZE);
CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0,
(cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit);
@@ -4499,7 +4514,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
u32 cid_addr, tx_cid, sb_id;
u32 val, offset0, offset1, offset2, offset3;
int i;
- struct tx_bd *txbd;
+ struct bnx2_tx_bd *txbd;
dma_addr_t buf_map, ring_map = udev->l2_ring_map;
struct status_block *s_blk = cp->status_blk.gen;
@@ -4517,7 +4532,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
cp->tx_cons = *cp->tx_cons_ptr;
cid_addr = GET_CID_ADDR(tx_cid);
- if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+ if (BNX2_CHIP(cp) == BNX2_CHIP_5709) {
u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40;
for (i = 0; i < PHY_CTX_SIZE; i += 4)
@@ -4545,7 +4560,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
txbd = udev->l2_ring;
buf_map = udev->l2_buf_map;
- for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
+ for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i++, txbd++) {
txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
}
@@ -4565,7 +4580,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
struct cnic_uio_dev *udev = cp->udev;
u32 cid_addr, sb_id, val, coal_reg, coal_val;
int i;
- struct rx_bd *rxbd;
+ struct bnx2_rx_bd *rxbd;
struct status_block *s_blk = cp->status_blk.gen;
dma_addr_t ring_map = udev->l2_ring_map;
@@ -4601,8 +4616,8 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
- rxbd = udev->l2_ring + BCM_PAGE_SIZE;
- for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+ rxbd = udev->l2_ring + BNX2_PAGE_SIZE;
+ for (i = 0; i < BNX2_MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
int n = (i % cp->l2_rx_ring_size) + 1;
@@ -4612,11 +4627,11 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
}
- val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
+ val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
rxbd->rx_bd_haddr_hi = val;
- val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+ val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
rxbd->rx_bd_haddr_lo = val;
@@ -4662,7 +4677,7 @@ static void cnic_set_bnx2_mac(struct cnic_dev *dev)
CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val);
val = 4 | BNX2_RPM_SORT_USER2_BC_EN;
- if (CHIP_NUM(cp) != CHIP_NUM_5709)
+ if (BNX2_CHIP(cp) != BNX2_CHIP_5709)
val |= BNX2_RPM_SORT_USER2_PROM_VLAN;
CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0);
@@ -4682,10 +4697,10 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
val = CNIC_RD(dev, BNX2_MQ_CONFIG);
val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
- if (BCM_PAGE_BITS > 12)
+ if (BNX2_PAGE_BITS > 12)
val |= (12 - 8) << 4;
else
- val |= (BCM_PAGE_BITS - 8) << 4;
+ val |= (BNX2_PAGE_BITS - 8) << 4;
CNIC_WR(dev, BNX2_MQ_CONFIG, val);
@@ -4708,20 +4723,20 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
cp->kwq_con_idx = 0;
set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags);
- if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708)
+ if (BNX2_CHIP(cp) == BNX2_CHIP_5706 || BNX2_CHIP(cp) == BNX2_CHIP_5708)
cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15;
else
cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index;
/* Initialize the kernel work queue context. */
val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
- (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+ (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val);
- val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
+ val = (BNX2_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
- val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
+ val = ((BNX2_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
@@ -4741,13 +4756,13 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
/* Initialize the kernel complete queue context. */
val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
- (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+ (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val);
- val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
+ val = (BNX2_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
- val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
+ val = ((BNX2_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32);
@@ -4843,6 +4858,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
u16 sb_id, u8 sb_index,
u8 disable)
{
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 addr = BAR_CSTRORM_INTMEM +
CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
@@ -4860,6 +4876,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u8 sb_id = cp->status_blk_num;
CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
@@ -4886,10 +4903,10 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
u32 cli = cp->ethdev->iscsi_l2_client_id;
u32 val;
- memset(txbd, 0, BCM_PAGE_SIZE);
+ memset(txbd, 0, BNX2_PAGE_SIZE);
buf_map = udev->l2_buf_map;
- for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) {
+ for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i += 3, txbd += 3) {
struct eth_tx_start_bd *start_bd = &txbd->start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x =
&((txbd + 1)->parse_bd_e1x);
@@ -4908,9 +4925,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
pbd_e2->parsing_data = (UNICAST_ADDRESS <<
- ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
+ ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
else
- pbd_e1x->global_data = (UNICAST_ADDRESS <<
+ pbd_e1x->global_data = (UNICAST_ADDRESS <<
ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT);
}
@@ -4945,9 +4962,9 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
struct cnic_local *cp = dev->cnic_priv;
struct cnic_uio_dev *udev = cp->udev;
struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
- BCM_PAGE_SIZE);
+ BNX2_PAGE_SIZE);
struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
- (udev->l2_ring + (2 * BCM_PAGE_SIZE));
+ (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int i;
u32 cli = cp->ethdev->iscsi_l2_client_id;
@@ -4971,20 +4988,20 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
}
- val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
+ val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
rxbd->addr_hi = cpu_to_le32(val);
data->rx.bd_page_base.hi = cpu_to_le32(val);
- val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+ val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
rxbd->addr_lo = cpu_to_le32(val);
data->rx.bd_page_base.lo = cpu_to_le32(val);
rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
- val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
+ val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) >> 32;
rxcqe->addr_hi = cpu_to_le32(val);
data->rx.cqe_page_base.hi = cpu_to_le32(val);
- val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
+ val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) & 0xffffffff;
rxcqe->addr_lo = cpu_to_le32(val);
data->rx.cqe_page_base.lo = cpu_to_le32(val);
@@ -5009,6 +5026,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 pfid = cp->pfid;
cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
@@ -5047,37 +5065,17 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_eth_dev *ethdev = cp->ethdev;
- int func = CNIC_FUNC(cp), ret;
+ int func, ret;
u32 pfid;
dev->stats_addr = ethdev->addr_drv_info_to_mcp;
- cp->port_mode = CHIP_PORT_MODE_NONE;
-
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
- u32 val;
+ cp->port_mode = bp->common.chip_port_mode;
+ cp->pfid = bp->pfid;
+ cp->func = bp->pf_num;
- pci_read_config_dword(dev->pcidev, PCICFG_ME_REGISTER, &val);
- cp->func = (u8) ((val & ME_REG_ABS_PF_NUM) >>
- ME_REG_ABS_PF_NUM_SHIFT);
- func = CNIC_FUNC(cp);
-
- val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
- if (!(val & 1))
- val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN);
- else
- val = (val >> 1) & 1;
-
- if (val) {
- cp->port_mode = CHIP_4_PORT_MODE;
- cp->pfid = func >> 1;
- } else {
- cp->port_mode = CHIP_2_PORT_MODE;
- cp->pfid = func & 0x6;
- }
- } else {
- cp->pfid = func;
- }
+ func = CNIC_FUNC(cp);
pfid = cp->pfid;
ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
@@ -5144,6 +5142,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
static void cnic_init_rings(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_uio_dev *udev = cp->udev;
if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
@@ -5249,8 +5248,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
msleep(10);
}
clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
- rx_ring = udev->l2_ring + BCM_PAGE_SIZE;
- memset(rx_ring, 0, BCM_PAGE_SIZE);
+ rx_ring = udev->l2_ring + BNX2_PAGE_SIZE;
+ memset(rx_ring, 0, BNX2_PAGE_SIZE);
}
static int cnic_register_netdev(struct cnic_dev *dev)
@@ -5344,8 +5343,28 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
+ u32 hc_index = HC_INDEX_ISCSI_EQ_CONS;
+ u32 sb_id = cp->status_blk_num;
+ u32 idx_off, syn_off;
cnic_free_irq(dev);
+
+ if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ idx_off = offsetof(struct hc_status_block_e2, index_values) +
+ (hc_index * sizeof(u16));
+
+ syn_off = CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hc_index, sb_id);
+ } else {
+ idx_off = offsetof(struct hc_status_block_e1x, index_values) +
+ (hc_index * sizeof(u16));
+
+ syn_off = CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hc_index, sb_id);
+ }
+ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + syn_off, 0);
+ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(sb_id) +
+ idx_off, 0);
+
*cp->kcq1.hw_prod_idx_ptr = 0;
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
@@ -5431,14 +5450,12 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
struct pci_dev *pdev;
struct cnic_dev *cdev;
struct cnic_local *cp;
+ struct bnx2 *bp = netdev_priv(dev);
struct cnic_eth_dev *ethdev = NULL;
- struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
- probe = symbol_get(bnx2_cnic_probe);
- if (probe) {
- ethdev = (*probe)(dev);
- symbol_put(bnx2_cnic_probe);
- }
+ if (bp->cnic_probe)
+ ethdev = (bp->cnic_probe)(dev);
+
if (!ethdev)
return NULL;
@@ -5493,14 +5510,12 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
struct pci_dev *pdev;
struct cnic_dev *cdev;
struct cnic_local *cp;
+ struct bnx2x *bp = netdev_priv(dev);
struct cnic_eth_dev *ethdev = NULL;
- struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
- probe = symbol_get(bnx2x_cnic_probe);
- if (probe) {
- ethdev = (*probe)(dev);
- symbol_put(bnx2x_cnic_probe);
- }
+ if (bp->cnic_probe)
+ ethdev = bp->cnic_probe(dev);
+
if (!ethdev)
return NULL;
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 148604c3fa0c..62c670619ae6 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -80,18 +80,18 @@
#define CNIC_LOCAL_PORT_MAX 61024
#define CNIC_LOCAL_PORT_RANGE (CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
-#define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
-#define KCQE_CNT (BCM_PAGE_SIZE / sizeof(struct kcqe))
+#define KWQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kwqe))
+#define KCQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kcqe))
#define MAX_KWQE_CNT (KWQE_CNT - 1)
#define MAX_KCQE_CNT (KCQE_CNT - 1)
#define MAX_KWQ_IDX ((KWQ_PAGE_CNT * KWQE_CNT) - 1)
#define MAX_KCQ_IDX ((KCQ_PAGE_CNT * KCQE_CNT) - 1)
-#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BNX2_PAGE_BITS - 5))
#define KWQ_IDX(x) ((x) & MAX_KWQE_CNT)
-#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BNX2_PAGE_BITS - 5))
#define KCQ_IDX(x) ((x) & MAX_KCQE_CNT)
#define BNX2X_NEXT_KCQE(x) (((x) & (MAX_KCQE_CNT - 1)) == \
@@ -186,14 +186,6 @@ struct kcq_info {
u16 (*hw_idx)(u16);
};
-struct iro {
- u32 base;
- u16 m1;
- u16 m2;
- u16 m3;
- u16 size;
-};
-
struct cnic_uio_dev {
struct uio_info cnic_uinfo;
u32 uio_dev;
@@ -241,9 +233,6 @@ struct cnic_local {
u16 rx_cons;
u16 tx_cons;
- const struct iro *iro_arr;
-#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
-
struct cnic_dma kwq_info;
struct kwqe **kwq;
@@ -316,9 +305,6 @@ struct cnic_local {
int func;
u32 pfid;
u8 port_mode;
-#define CHIP_4_PORT_MODE 0
-#define CHIP_2_PORT_MODE 1
-#define CHIP_PORT_MODE_NONE 2
u32 shmem_base;
@@ -420,11 +406,11 @@ struct bnx2x_bd_chain_next {
BNX2X_CHIP_IS_57840(x))
#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
-#define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id)
-
-#define BNX2X_RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
+#define BNX2X_RX_DESC_CNT (BNX2_PAGE_SIZE / \
+ sizeof(struct eth_rx_bd))
#define BNX2X_MAX_RX_DESC_CNT (BNX2X_RX_DESC_CNT - 2)
-#define BNX2X_RCQ_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
+#define BNX2X_RCQ_DESC_CNT (BNX2_PAGE_SIZE / \
+ sizeof(union eth_rx_cqe))
#define BNX2X_MAX_RCQ_DESC_CNT (BNX2X_RCQ_DESC_CNT - 1)
#define BNX2X_NEXT_RCQE(x) (((x) & BNX2X_MAX_RCQ_DESC_CNT) == \
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 865095aad1f6..2a35436f9095 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -14,8 +14,8 @@
#include "bnx2x/bnx2x_mfw_req.h"
-#define CNIC_MODULE_VERSION "2.5.14"
-#define CNIC_MODULE_RELDATE "Sep 30, 2012"
+#define CNIC_MODULE_VERSION "2.5.16"
+#define CNIC_MODULE_RELDATE "Dec 05, 2012"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
@@ -353,7 +353,4 @@ extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
extern int cnic_unregister_driver(int ulp_type);
-extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev);
-extern struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
-
#endif
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index 49e7a258da8a..3a1c8a3cf7c9 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2586,7 +2586,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget)
}
-static int __devinit sbmac_probe(struct platform_device *pldev)
+static int sbmac_probe(struct platform_device *pldev)
{
struct net_device *dev;
struct sbmac_softc *sc;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index a8800ac10df9..78ea90c40e19 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -54,6 +54,9 @@
#include <asm/byteorder.h>
#include <linux/uaccess.h>
+#include <uapi/linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+
#ifdef CONFIG_SPARC
#include <asm/idprom.h>
#include <asm/prom.h>
@@ -90,10 +93,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 125
+#define TG3_MIN_NUM 128
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "September 26, 2012"
+#define DRV_MODULE_RELDATE "December 03, 2012"
#define RESET_KIND_SHUTDOWN 0
#define RESET_KIND_INIT 1
@@ -211,7 +214,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define FIRMWARE_TG3TSO "tigon/tg3_tso.bin"
#define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin"
-static char version[] __devinitdata =
+static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
@@ -226,6 +229,9 @@ static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */
module_param(tg3_debug, int, 0);
MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
+#define TG3_DRV_DATA_FLAG_10_100_ONLY 0x0001
+#define TG3_DRV_DATA_FLAG_5705_10_100 0x0002
+
static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
@@ -245,20 +251,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+ TG3_DRV_DATA_FLAG_5705_10_100},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+ TG3_DRV_DATA_FLAG_5705_10_100},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+ TG3_DRV_DATA_FLAG_5705_10_100},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
@@ -266,8 +280,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M,
+ PCI_VENDOR_ID_LENOVO,
+ TG3PCI_SUBDEVICE_ID_LENOVO_5787M),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -286,18 +305,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+ PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+ PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
+ .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
@@ -398,19 +427,27 @@ static const struct {
};
#define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys)
+#define TG3_NVRAM_TEST 0
+#define TG3_LINK_TEST 1
+#define TG3_REGISTER_TEST 2
+#define TG3_MEMORY_TEST 3
+#define TG3_MAC_LOOPB_TEST 4
+#define TG3_PHY_LOOPB_TEST 5
+#define TG3_EXT_LOOPB_TEST 6
+#define TG3_INTERRUPT_TEST 7
static const struct {
const char string[ETH_GSTRING_LEN];
} ethtool_test_keys[] = {
- { "nvram test (online) " },
- { "link test (online) " },
- { "register test (offline)" },
- { "memory test (offline)" },
- { "mac loopback test (offline)" },
- { "phy loopback test (offline)" },
- { "ext loopback test (offline)" },
- { "interrupt test (offline)" },
+ [TG3_NVRAM_TEST] = { "nvram test (online) " },
+ [TG3_LINK_TEST] = { "link test (online) " },
+ [TG3_REGISTER_TEST] = { "register test (offline)" },
+ [TG3_MEMORY_TEST] = { "memory test (offline)" },
+ [TG3_MAC_LOOPB_TEST] = { "mac loopback test (offline)" },
+ [TG3_PHY_LOOPB_TEST] = { "phy loopback test (offline)" },
+ [TG3_EXT_LOOPB_TEST] = { "ext loopback test (offline)" },
+ [TG3_INTERRUPT_TEST] = { "interrupt test (offline)" },
};
#define TG3_NUM_TEST ARRAY_SIZE(ethtool_test_keys)
@@ -2447,6 +2484,18 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
return err;
}
+static void tg3_carrier_on(struct tg3 *tp)
+{
+ netif_carrier_on(tp->dev);
+ tp->link_up = true;
+}
+
+static void tg3_carrier_off(struct tg3 *tp)
+{
+ netif_carrier_off(tp->dev);
+ tp->link_up = false;
+}
+
/* This will reset the tigon3 PHY if there is no valid
* link unless the FORCE argument is non-zero.
*/
@@ -2465,8 +2514,8 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err != 0)
return -EBUSY;
- if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
- netif_carrier_off(tp->dev);
+ if (netif_running(tp->dev) && tp->link_up) {
+ tg3_carrier_off(tp);
tg3_link_report(tp);
}
@@ -4160,6 +4209,24 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
return true;
}
+static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
+{
+ if (curr_link_up != tp->link_up) {
+ if (curr_link_up) {
+ tg3_carrier_on(tp);
+ } else {
+ tg3_carrier_off(tp);
+ if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+ tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+ }
+
+ tg3_link_report(tp);
+ return true;
+ }
+
+ return false;
+}
+
static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
{
int current_link_up;
@@ -4192,7 +4259,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
- netif_carrier_ok(tp->dev)) {
+ tp->link_up) {
tg3_readphy(tp, MII_BMSR, &bmsr);
if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
!(bmsr & BMSR_LSTATUS))
@@ -4434,13 +4501,7 @@ relink:
PCI_EXP_LNKCTL_CLKREQ_EN);
}
- if (current_link_up != netif_carrier_ok(tp->dev)) {
- if (current_link_up)
- netif_carrier_on(tp->dev);
- else
- netif_carrier_off(tp->dev);
- tg3_link_report(tp);
- }
+ tg3_test_and_report_link_chg(tp, current_link_up);
return 0;
}
@@ -5080,7 +5141,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
orig_active_duplex = tp->link_config.active_duplex;
if (!tg3_flag(tp, HW_AUTONEG) &&
- netif_carrier_ok(tp->dev) &&
+ tp->link_up &&
tg3_flag(tp, INIT_COMPLETE)) {
mac_status = tr32(MAC_STATUS);
mac_status &= (MAC_STATUS_PCS_SYNCED |
@@ -5158,13 +5219,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
LED_CTRL_TRAFFIC_OVERRIDE));
}
- if (current_link_up != netif_carrier_ok(tp->dev)) {
- if (current_link_up)
- netif_carrier_on(tp->dev);
- else
- netif_carrier_off(tp->dev);
- tg3_link_report(tp);
- } else {
+ if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
u32 now_pause_cfg = tp->link_config.active_flowctrl;
if (orig_pause_cfg != now_pause_cfg ||
orig_active_speed != tp->link_config.active_speed ||
@@ -5257,7 +5312,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
new_bmcr |= BMCR_SPEED1000;
/* Force a linkdown */
- if (netif_carrier_ok(tp->dev)) {
+ if (tp->link_up) {
u32 adv;
err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
@@ -5269,7 +5324,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
BMCR_ANRESTART |
BMCR_ANENABLE);
udelay(10);
- netif_carrier_off(tp->dev);
+ tg3_carrier_off(tp);
}
tg3_writephy(tp, MII_BMCR, new_bmcr);
bmcr = new_bmcr;
@@ -5335,15 +5390,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
tp->link_config.active_speed = current_speed;
tp->link_config.active_duplex = current_duplex;
- if (current_link_up != netif_carrier_ok(tp->dev)) {
- if (current_link_up)
- netif_carrier_on(tp->dev);
- else {
- netif_carrier_off(tp->dev);
- tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
- }
- tg3_link_report(tp);
- }
+ tg3_test_and_report_link_chg(tp, current_link_up);
return err;
}
@@ -5355,7 +5402,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
return;
}
- if (!netif_carrier_ok(tp->dev) &&
+ if (!tp->link_up &&
(tp->link_config.autoneg == AUTONEG_ENABLE)) {
u32 bmcr;
@@ -5385,7 +5432,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT;
}
}
- } else if (netif_carrier_ok(tp->dev) &&
+ } else if (tp->link_up &&
(tp->link_config.autoneg == AUTONEG_ENABLE) &&
(tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
u32 phy2;
@@ -5451,7 +5498,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
(32 << TX_LENGTHS_SLOT_TIME_SHIFT));
if (!tg3_flag(tp, 5705_PLUS)) {
- if (netif_carrier_ok(tp->dev)) {
+ if (tp->link_up) {
tw32(HOSTCC_STAT_COAL_TICKS,
tp->coal.stats_block_coalesce_usecs);
} else {
@@ -5461,7 +5508,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
if (tg3_flag(tp, ASPM_WORKAROUND)) {
val = tr32(PCIE_PWR_MGMT_THRESH);
- if (!netif_carrier_ok(tp->dev))
+ if (!tp->link_up)
val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
tp->pwrmgmt_thresh;
else
@@ -5472,6 +5519,190 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
return err;
}
+/* tp->lock must be held */
+static u64 tg3_refclk_read(struct tg3 *tp)
+{
+ u64 stamp = tr32(TG3_EAV_REF_CLCK_LSB);
+ return stamp | (u64)tr32(TG3_EAV_REF_CLCK_MSB) << 32;
+}
+
+/* tp->lock must be held */
+static void tg3_refclk_write(struct tg3 *tp, u64 newval)
+{
+ tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP);
+ tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff);
+ tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32);
+ tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME);
+}
+
+static inline void tg3_full_lock(struct tg3 *tp, int irq_sync);
+static inline void tg3_full_unlock(struct tg3 *tp);
+static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ if (tp->ptp_clock)
+ info->phc_index = ptp_clock_index(tp->ptp_clock);
+ else
+ info->phc_index = -1;
+
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
+ return 0;
+}
+
+static int tg3_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+ bool neg_adj = false;
+ u32 correction = 0;
+
+ if (ppb < 0) {
+ neg_adj = true;
+ ppb = -ppb;
+ }
+
+ /* Frequency adjustment is performed using hardware with a 24 bit
+ * accumulator and a programmable correction value. On each clk, the
+ * correction value gets added to the accumulator and when it
+ * overflows, the time counter is incremented/decremented.
+ *
+ * So conversion from ppb to correction value is
+ * ppb * (1 << 24) / 1000000000
+ */
+ correction = div_u64((u64)ppb * (1 << 24), 1000000000ULL) &
+ TG3_EAV_REF_CLK_CORRECT_MASK;
+
+ tg3_full_lock(tp, 0);
+
+ if (correction)
+ tw32(TG3_EAV_REF_CLK_CORRECT_CTL,
+ TG3_EAV_REF_CLK_CORRECT_EN |
+ (neg_adj ? TG3_EAV_REF_CLK_CORRECT_NEG : 0) | correction);
+ else
+ tw32(TG3_EAV_REF_CLK_CORRECT_CTL, 0);
+
+ tg3_full_unlock(tp);
+
+ return 0;
+}
+
+static int tg3_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+ tg3_full_lock(tp, 0);
+ tp->ptp_adjust += delta;
+ tg3_full_unlock(tp);
+
+ return 0;
+}
+
+static int tg3_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+ tg3_full_lock(tp, 0);
+ ns = tg3_refclk_read(tp);
+ ns += tp->ptp_adjust;
+ tg3_full_unlock(tp);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+static int tg3_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ u64 ns;
+ struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+ ns = timespec_to_ns(ts);
+
+ tg3_full_lock(tp, 0);
+ tg3_refclk_write(tp, ns);
+ tp->ptp_adjust = 0;
+ tg3_full_unlock(tp);
+
+ return 0;
+}
+
+static int tg3_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static const struct ptp_clock_info tg3_ptp_caps = {
+ .owner = THIS_MODULE,
+ .name = "tg3 clock",
+ .max_adj = 250000000,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .pps = 0,
+ .adjfreq = tg3_ptp_adjfreq,
+ .adjtime = tg3_ptp_adjtime,
+ .gettime = tg3_ptp_gettime,
+ .settime = tg3_ptp_settime,
+ .enable = tg3_ptp_enable,
+};
+
+static void tg3_hwclock_to_timestamp(struct tg3 *tp, u64 hwclock,
+ struct skb_shared_hwtstamps *timestamp)
+{
+ memset(timestamp, 0, sizeof(struct skb_shared_hwtstamps));
+ timestamp->hwtstamp = ns_to_ktime((hwclock & TG3_TSTAMP_MASK) +
+ tp->ptp_adjust);
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_init(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, PTP_CAPABLE))
+ return;
+
+ /* Initialize the hardware clock to the system time. */
+ tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()));
+ tp->ptp_adjust = 0;
+ tp->ptp_info = tg3_ptp_caps;
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_resume(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, PTP_CAPABLE))
+ return;
+
+ tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()) + tp->ptp_adjust);
+ tp->ptp_adjust = 0;
+}
+
+static void tg3_ptp_fini(struct tg3 *tp)
+{
+ if (!tg3_flag(tp, PTP_CAPABLE) || !tp->ptp_clock)
+ return;
+
+ ptp_clock_unregister(tp->ptp_clock);
+ tp->ptp_clock = NULL;
+ tp->ptp_adjust = 0;
+}
+
static inline int tg3_irq_sync(struct tg3 *tp)
{
return tp->irq_sync;
@@ -5652,6 +5883,16 @@ static void tg3_tx(struct tg3_napi *tnapi)
return;
}
+ if (tnapi->tx_ring[sw_idx].len_flags & TXD_FLAG_HWTSTAMP) {
+ struct skb_shared_hwtstamps timestamp;
+ u64 hwclock = tr32(TG3_TX_TSTAMP_LSB);
+ hwclock |= (u64)tr32(TG3_TX_TSTAMP_MSB) << 32;
+
+ tg3_hwclock_to_timestamp(tp, hwclock, &timestamp);
+
+ skb_tstamp_tx(skb, &timestamp);
+ }
+
pci_unmap_single(tp->pdev,
dma_unmap_addr(ri, mapping),
skb_headlen(skb),
@@ -5919,6 +6160,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
dma_addr_t dma_addr;
u32 opaque_key, desc_idx, *post_ptr;
u8 *data;
+ u64 tstamp = 0;
desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@@ -5953,6 +6195,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
ETH_FCS_LEN;
+ if ((desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+ RXD_FLAG_PTPSTAT_PTPV1 ||
+ (desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+ RXD_FLAG_PTPSTAT_PTPV2) {
+ tstamp = tr32(TG3_RX_TSTAMP_LSB);
+ tstamp |= (u64)tr32(TG3_RX_TSTAMP_MSB) << 32;
+ }
+
if (len > TG3_RX_COPY_THRESH(tp)) {
int skb_size;
unsigned int frag_size;
@@ -5996,6 +6246,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
}
skb_put(skb, len);
+ if (tstamp)
+ tg3_hwclock_to_timestamp(tp, tstamp,
+ skb_hwtstamps(skb));
+
if ((tp->dev->features & NETIF_F_RXCSUM) &&
(desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
(((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
@@ -6477,17 +6731,24 @@ static inline void tg3_netif_stop(struct tg3 *tp)
{
tp->dev->trans_start = jiffies; /* prevent tx timeout */
tg3_napi_disable(tp);
+ netif_carrier_off(tp->dev);
netif_tx_disable(tp->dev);
}
+/* tp->lock must be held */
static inline void tg3_netif_start(struct tg3 *tp)
{
+ tg3_ptp_resume(tp);
+
/* NOTE: unconditional netif_tx_wake_all_queues is only
* appropriate so long as all callers are assured to
* have free tx slots (such as after tg3_init_hw)
*/
netif_tx_wake_all_queues(tp->dev);
+ if (tp->link_up)
+ netif_carrier_on(tp->dev);
+
tg3_napi_enable(tp);
tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
tg3_enable_ints(tp);
@@ -7046,6 +7307,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan = vlan_tx_tag_get(skb);
}
+ if ((unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) &&
+ tg3_flag(tp, TX_TSTAMP_EN)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ base_flags |= TXD_FLAG_HWTSTAMP;
+ }
+
len = skb_headlen(skb);
mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
@@ -8386,7 +8653,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
- if (!netif_carrier_ok(tp->dev))
+ if (!tp->link_up)
val = 0;
tw32(HOSTCC_STAT_COAL_TICKS, val);
@@ -8662,14 +8929,14 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp)
if (!tg3_flag(tp, SUPPORT_MSIX))
return;
- if (tp->irq_cnt <= 2) {
+ if (tp->rxq_cnt == 1) {
memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl));
return;
}
/* Validate table against current IRQ count */
for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
- if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1)
+ if (tp->rss_ind_tbl[i] >= tp->rxq_cnt)
break;
}
@@ -8914,9 +9181,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
*/
tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
- tw32(GRC_MODE,
- tp->grc_mode |
- (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+ val = GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP;
+ if (tp->rxptpctl)
+ tw32(TG3_RX_PTP_CTL,
+ tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+ if (tg3_flag(tp, PTP_CAPABLE))
+ val |= GRC_MODE_TIME_SYNC_ENABLE;
+
+ tw32(GRC_MODE, tp->grc_mode | val);
/* Setup the timer prescalar register. Clock is always 66Mhz. */
val = tr32(GRC_MISC_CFG);
@@ -9679,7 +9952,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
{
struct tg3_hw_stats *sp = tp->hw_stats;
- if (!netif_carrier_ok(tp->dev))
+ if (!tp->link_up)
return;
TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS);
@@ -9823,11 +10096,11 @@ static void tg3_timer(unsigned long __opaque)
u32 mac_stat = tr32(MAC_STATUS);
int need_setup = 0;
- if (netif_carrier_ok(tp->dev) &&
+ if (tp->link_up &&
(mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) {
need_setup = 1;
}
- if (!netif_carrier_ok(tp->dev) &&
+ if (!tp->link_up &&
(mac_stat & (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET))) {
need_setup = 1;
@@ -9890,7 +10163,7 @@ restart_timer:
add_timer(&tp->timer);
}
-static void __devinit tg3_timer_init(struct tg3 *tp)
+static void tg3_timer_init(struct tg3 *tp)
{
if (tg3_flag(tp, TAGGED_STATUS) &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
@@ -10316,7 +10589,8 @@ static void tg3_ints_fini(struct tg3 *tp)
tg3_flag_clear(tp, ENABLE_TSS);
}
-static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
+static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
+ bool init)
{
struct net_device *dev = tp->dev;
int i, err;
@@ -10395,6 +10669,12 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
tg3_flag_set(tp, INIT_COMPLETE);
tg3_enable_ints(tp);
+ if (init)
+ tg3_ptp_init(tp);
+ else
+ tg3_ptp_resume(tp);
+
+
tg3_full_unlock(tp);
netif_tx_start_all_queues(dev);
@@ -10429,10 +10709,8 @@ static void tg3_stop(struct tg3 *tp)
{
int i;
- tg3_napi_disable(tp);
tg3_reset_task_cancel(tp);
-
- netif_tx_disable(tp->dev);
+ tg3_netif_stop(tp);
tg3_timer_stop(tp);
@@ -10481,7 +10759,7 @@ static int tg3_open(struct net_device *dev)
}
}
- netif_carrier_off(tp->dev);
+ tg3_carrier_off(tp);
err = tg3_power_up(tp);
if (err)
@@ -10494,11 +10772,19 @@ static int tg3_open(struct net_device *dev)
tg3_full_unlock(tp);
- err = tg3_start(tp, true, true);
+ err = tg3_start(tp, true, true, true);
if (err) {
tg3_frob_aux_power(tp, false);
pci_set_power_state(tp->pdev, PCI_D3hot);
}
+
+ if (tg3_flag(tp, PTP_CAPABLE)) {
+ tp->ptp_clock = ptp_clock_register(&tp->ptp_info,
+ &tp->pdev->dev);
+ if (IS_ERR(tp->ptp_clock))
+ tp->ptp_clock = NULL;
+ }
+
return err;
}
@@ -10506,6 +10792,8 @@ static int tg3_close(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
+ tg3_ptp_fini(tp);
+
tg3_stop(tp);
/* Clear stats across close / open calls */
@@ -10514,7 +10802,7 @@ static int tg3_close(struct net_device *dev)
tg3_power_down(tp);
- netif_carrier_off(tp->dev);
+ tg3_carrier_off(tp);
return 0;
}
@@ -10888,7 +11176,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->advertising |= ADVERTISED_Asym_Pause;
}
}
- if (netif_running(dev) && netif_carrier_ok(dev)) {
+ if (netif_running(dev) && tp->link_up) {
ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
cmd->duplex = tp->link_config.active_duplex;
cmd->lp_advertising = tp->link_config.rmt_adv;
@@ -11406,9 +11694,9 @@ static int tg3_set_channels(struct net_device *dev,
tg3_stop(tp);
- netif_carrier_off(dev);
+ tg3_carrier_off(tp);
- tg3_start(tp, true, false);
+ tg3_start(tp, true, false, false);
return 0;
}
@@ -11755,7 +12043,7 @@ static int tg3_test_link(struct tg3 *tp)
max = TG3_COPPER_TIMEOUT_SEC;
for (i = 0; i < max; i++) {
- if (netif_carrier_ok(tp->dev))
+ if (tp->link_up)
return 0;
if (msleep_interruptible(1000))
@@ -12326,19 +12614,19 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
if (!netif_running(tp->dev)) {
- data[0] = TG3_LOOPBACK_FAILED;
- data[1] = TG3_LOOPBACK_FAILED;
+ data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+ data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
if (do_extlpbk)
- data[2] = TG3_LOOPBACK_FAILED;
+ data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
goto done;
}
err = tg3_reset_hw(tp, 1);
if (err) {
- data[0] = TG3_LOOPBACK_FAILED;
- data[1] = TG3_LOOPBACK_FAILED;
+ data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+ data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
if (do_extlpbk)
- data[2] = TG3_LOOPBACK_FAILED;
+ data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
goto done;
}
@@ -12361,11 +12649,11 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
tg3_mac_loopback(tp, true);
if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
- data[0] |= TG3_STD_LOOPBACK_FAILED;
+ data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
- data[0] |= TG3_JMB_LOOPBACK_FAILED;
+ data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
tg3_mac_loopback(tp, false);
}
@@ -12384,13 +12672,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
}
if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
- data[1] |= TG3_STD_LOOPBACK_FAILED;
+ data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
if (tg3_flag(tp, TSO_CAPABLE) &&
tg3_run_loopback(tp, ETH_FRAME_LEN, true))
- data[1] |= TG3_TSO_LOOPBACK_FAILED;
+ data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED;
if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
- data[1] |= TG3_JMB_LOOPBACK_FAILED;
+ data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
if (do_extlpbk) {
tg3_phy_lpbk_set(tp, 0, true);
@@ -12402,13 +12690,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
mdelay(40);
if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
- data[2] |= TG3_STD_LOOPBACK_FAILED;
+ data[TG3_EXT_LOOPB_TEST] |=
+ TG3_STD_LOOPBACK_FAILED;
if (tg3_flag(tp, TSO_CAPABLE) &&
tg3_run_loopback(tp, ETH_FRAME_LEN, true))
- data[2] |= TG3_TSO_LOOPBACK_FAILED;
+ data[TG3_EXT_LOOPB_TEST] |=
+ TG3_TSO_LOOPBACK_FAILED;
if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
- data[2] |= TG3_JMB_LOOPBACK_FAILED;
+ data[TG3_EXT_LOOPB_TEST] |=
+ TG3_JMB_LOOPBACK_FAILED;
}
/* Re-enable gphy autopowerdown. */
@@ -12416,7 +12707,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
tg3_phy_toggle_apd(tp, true);
}
- err = (data[0] | data[1] | data[2]) ? -EIO : 0;
+ err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] |
+ data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0;
done:
tp->phy_flags |= eee_cap;
@@ -12441,11 +12733,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
if (tg3_test_nvram(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[0] = 1;
+ data[TG3_NVRAM_TEST] = 1;
}
if (!doextlpbk && tg3_test_link(tp)) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[1] = 1;
+ data[TG3_LINK_TEST] = 1;
}
if (etest->flags & ETH_TEST_FL_OFFLINE) {
int err, err2 = 0, irq_sync = 0;
@@ -12457,7 +12749,6 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
}
tg3_full_lock(tp, irq_sync);
-
tg3_halt(tp, RESET_KIND_SUSPEND, 1);
err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
@@ -12471,25 +12762,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
if (tg3_test_registers(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[2] = 1;
+ data[TG3_REGISTER_TEST] = 1;
}
if (tg3_test_memory(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[3] = 1;
+ data[TG3_MEMORY_TEST] = 1;
}
if (doextlpbk)
etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
- if (tg3_test_loopback(tp, &data[4], doextlpbk))
+ if (tg3_test_loopback(tp, data, doextlpbk))
etest->flags |= ETH_TEST_FL_FAILED;
tg3_full_unlock(tp);
if (tg3_test_interrupt(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[7] = 1;
+ data[TG3_INTERRUPT_TEST] = 1;
}
tg3_full_lock(tp, 0);
@@ -12512,6 +12803,96 @@ 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)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ struct hwtstamp_config stmpconf;
+
+ if (!tg3_flag(tp, PTP_CAPABLE))
+ return -EINVAL;
+
+ if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
+ return -EFAULT;
+
+ if (stmpconf.flags)
+ return -EINVAL;
+
+ switch (stmpconf.tx_type) {
+ case HWTSTAMP_TX_ON:
+ tg3_flag_set(tp, TX_TSTAMP_EN);
+ break;
+ case HWTSTAMP_TX_OFF:
+ tg3_flag_clear(tp, TX_TSTAMP_EN);
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (stmpconf.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ tp->rxptpctl = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+ TG3_RX_PTP_CTL_ALL_V1_EVENTS;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+ TG3_RX_PTP_CTL_SYNC_EVNT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+ TG3_RX_PTP_CTL_DELAY_REQ;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+ TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+ TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+ TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+ TG3_RX_PTP_CTL_SYNC_EVNT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+ TG3_RX_PTP_CTL_SYNC_EVNT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+ TG3_RX_PTP_CTL_SYNC_EVNT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+ TG3_RX_PTP_CTL_DELAY_REQ;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+ TG3_RX_PTP_CTL_DELAY_REQ;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+ TG3_RX_PTP_CTL_DELAY_REQ;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (netif_running(dev) && tp->rxptpctl)
+ tw32(TG3_RX_PTP_CTL,
+ tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+ 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);
@@ -12562,6 +12943,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
+ case SIOCSHWTSTAMP:
+ return tg3_hwtstamp_ioctl(dev, ifr, cmd);
+
default:
/* do nothing */
break;
@@ -12663,7 +13047,7 @@ static const struct ethtool_ops tg3_ethtool_ops = {
.set_rxfh_indir = tg3_set_rxfh_indir,
.get_channels = tg3_get_channels,
.set_channels = tg3_set_channels,
- .get_ts_info = ethtool_op_get_ts_info,
+ .get_ts_info = tg3_get_ts_info,
};
static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@ -12779,7 +13163,7 @@ static const struct net_device_ops tg3_netdev_ops = {
#endif
};
-static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
+static void tg3_get_eeprom_size(struct tg3 *tp)
{
u32 cursize, val, magic;
@@ -12813,7 +13197,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
tp->nvram_size = cursize;
}
-static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+static void tg3_get_nvram_size(struct tg3 *tp)
{
u32 val;
@@ -12846,7 +13230,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
tp->nvram_size = TG3_NVRAM_SIZE_512KB;
}
-static void __devinit tg3_get_nvram_info(struct tg3 *tp)
+static void tg3_get_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -12897,7 +13281,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
}
}
-static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
{
switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
case FLASH_5752PAGE_SIZE_256:
@@ -12924,7 +13308,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
}
}
-static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
+static void tg3_get_5752_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -12965,7 +13349,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
}
}
-static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+static void tg3_get_5755_nvram_info(struct tg3 *tp)
{
u32 nvcfg1, protect = 0;
@@ -13021,7 +13405,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
}
}
-static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+static void tg3_get_5787_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -13059,7 +13443,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
}
}
-static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+static void tg3_get_5761_nvram_info(struct tg3 *tp)
{
u32 nvcfg1, protect = 0;
@@ -13134,14 +13518,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
}
}
-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+static void tg3_get_5906_nvram_info(struct tg3 *tp)
{
tp->nvram_jedecnum = JEDEC_ATMEL;
tg3_flag_set(tp, NVRAM_BUFFERED);
tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
}
-static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+static void tg3_get_57780_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -13214,7 +13598,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
}
-static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+static void tg3_get_5717_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
@@ -13292,7 +13676,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
}
-static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+static void tg3_get_5720_nvram_info(struct tg3 *tp)
{
u32 nvcfg1, nvmpinstrp;
@@ -13405,7 +13789,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
}
/* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void __devinit tg3_nvram_init(struct tg3 *tp)
+static void tg3_nvram_init(struct tg3 *tp)
{
tw32_f(GRC_EEPROM_ADDR,
(EEPROM_ADDR_FSM_RESET |
@@ -13475,7 +13859,7 @@ struct subsys_tbl_ent {
u32 phy_id;
};
-static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
/* Broadcom boards. */
{ TG3PCI_SUBVENDOR_ID_BROADCOM,
TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
@@ -13539,7 +13923,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
};
-static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
{
int i;
@@ -13553,7 +13937,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
return NULL;
}
-static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
{
u32 val;
@@ -13753,7 +14137,7 @@ done:
device_set_wakeup_capable(&tp->pdev->dev, false);
}
-static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
{
int i;
u32 val;
@@ -13776,7 +14160,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
* configuration is a 32-bit value that straddles the alignment boundary.
* We do two 32-bit reads and then shift and merge the results.
*/
-static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+static u32 tg3_read_otp_phycfg(struct tg3 *tp)
{
u32 bhalf_otp, thalf_otp;
@@ -13802,7 +14186,7 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
}
-static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+static void tg3_phy_init_link_config(struct tg3 *tp)
{
u32 adv = ADVERTISED_Autoneg;
@@ -13829,7 +14213,7 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
tp->old_link = -1;
}
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static int tg3_phy_probe(struct tg3 *tp)
{
u32 hw_phy_id_1, hw_phy_id_2;
u32 hw_phy_id, hw_phy_id_masked;
@@ -13957,7 +14341,7 @@ skip_phy_reset:
return err;
}
-static void __devinit tg3_read_vpd(struct tg3 *tp)
+static void tg3_read_vpd(struct tg3 *tp)
{
u8 *vpd_data;
unsigned int block_end, rosize, len;
@@ -14026,7 +14410,8 @@ out_not_found:
out_no_vpd:
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
- if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C)
strcpy(tp->board_part_number, "BCM5717");
else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
strcpy(tp->board_part_number, "BCM5718");
@@ -14077,7 +14462,7 @@ nomatch:
}
}
-static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
{
u32 val;
@@ -14090,7 +14475,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
return 1;
}
-static void __devinit tg3_read_bc_ver(struct tg3 *tp)
+static void tg3_read_bc_ver(struct tg3 *tp)
{
u32 val, offset, start, ver_offset;
int i, dst_off;
@@ -14142,7 +14527,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
}
}
-static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
+static void tg3_read_hwsb_ver(struct tg3 *tp)
{
u32 val, major, minor;
@@ -14158,7 +14543,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor);
}
-static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+static void tg3_read_sb_ver(struct tg3 *tp, u32 val)
{
u32 offset, major, minor, build;
@@ -14213,7 +14598,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
}
}
-static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
+static void tg3_read_mgmtfw_ver(struct tg3 *tp)
{
u32 val, offset, start;
int i, vlen;
@@ -14265,7 +14650,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
}
}
-static void __devinit tg3_probe_ncsi(struct tg3 *tp)
+static void tg3_probe_ncsi(struct tg3 *tp)
{
u32 apedata;
@@ -14281,7 +14666,7 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp)
tg3_flag_set(tp, APE_HAS_NCSI);
}
-static void __devinit tg3_read_dash_ver(struct tg3 *tp)
+static void tg3_read_dash_ver(struct tg3 *tp)
{
int vlen;
u32 apedata;
@@ -14304,7 +14689,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
(apedata & APE_FW_VERSION_BLDMSK));
}
-static void __devinit tg3_read_fw_ver(struct tg3 *tp)
+static void tg3_read_fw_ver(struct tg3 *tp)
{
u32 val;
bool vpd_vers = false;
@@ -14357,7 +14742,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
{ },
};
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
+static struct pci_dev *tg3_find_peer(struct tg3 *tp)
{
struct pci_dev *peer;
unsigned int func, devnr = tp->pdev->devfn & ~7;
@@ -14385,7 +14770,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
return peer;
}
-static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
+static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
{
tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
@@ -14397,6 +14782,7 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
tg3_flag_set(tp, CPMU_PRESENT);
if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
@@ -14424,6 +14810,9 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5717_C0)
+ tp->pci_chip_rev_id = CHIPREV_ID_5720_A0;
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
@@ -14462,7 +14851,29 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
tg3_flag_set(tp, 5705_PLUS);
}
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static bool tg3_10_100_only_device(struct tg3 *tp,
+ const struct pci_device_id *ent)
+{
+ u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK;
+
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+ (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+ (tp->phy_flags & TG3_PHYFLG_IS_FET))
+ return true;
+
+ if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100)
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
{
u32 misc_ctrl_reg;
u32 pci_state_reg, grc_misc_cfg;
@@ -15141,22 +15552,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else
tp->mac_mode = 0;
- /* these are limited to 10/100 only */
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
- (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
- tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
- (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
- tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
- tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
- (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
- (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
- tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
- tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
- (tp->phy_flags & TG3_PHYFLG_IS_FET))
+ if (tg3_10_100_only_device(tp, ent))
tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
err = tg3_phy_probe(tp);
@@ -15236,7 +15632,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
#ifdef CONFIG_SPARC
-static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_macaddr_sparc(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
struct pci_dev *pdev = tp->pdev;
@@ -15253,7 +15649,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
return -ENODEV;
}
-static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_default_macaddr_sparc(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
@@ -15263,7 +15659,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
}
#endif
-static int __devinit tg3_get_device_address(struct tg3 *tp)
+static int tg3_get_device_address(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
u32 hi, lo, mac_offset;
@@ -15342,7 +15738,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
#define BOUNDARY_SINGLE_CACHELINE 1
#define BOUNDARY_MULTI_CACHELINE 2
-static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
{
int cacheline_size;
u8 byte;
@@ -15483,7 +15879,8 @@ out:
return val;
}
-static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
+static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
+ int size, int to_device)
{
struct tg3_internal_buffer_desc test_desc;
u32 sram_dma_descs;
@@ -15570,7 +15967,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
{ },
};
-static int __devinit tg3_test_dma(struct tg3 *tp)
+static int tg3_test_dma(struct tg3 *tp)
{
dma_addr_t buf_dma;
u32 *buf, saved_dma_rwctrl;
@@ -15760,7 +16157,7 @@ out_nofree:
return ret;
}
-static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
+static void tg3_init_bufmgr_config(struct tg3 *tp)
{
if (tg3_flag(tp, 57765_PLUS)) {
tp->bufmgr_config.mbuf_read_dma_low_water =
@@ -15816,7 +16213,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
}
-static char * __devinit tg3_phy_string(struct tg3 *tp)
+static char *tg3_phy_string(struct tg3 *tp)
{
switch (tp->phy_id & TG3_PHY_ID_MASK) {
case TG3_PHY_ID_BCM5400: return "5400";
@@ -15847,7 +16244,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
}
}
-static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+static char *tg3_bus_string(struct tg3 *tp, char *str)
{
if (tg3_flag(tp, PCI_EXPRESS)) {
strcpy(str, "PCI Express");
@@ -15883,7 +16280,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
return str;
}
-static void __devinit tg3_init_coal(struct tg3 *tp)
+static void tg3_init_coal(struct tg3 *tp)
{
struct ethtool_coalesce *ec = &tp->coal;
@@ -15914,7 +16311,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
}
}
-static int __devinit tg3_init_one(struct pci_dev *pdev,
+static int tg3_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev;
@@ -16013,6 +16410,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) {
@@ -16034,7 +16432,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
dev->netdev_ops = &tg3_netdev_ops;
dev->irq = pdev->irq;
- err = tg3_get_invariants(tp);
+ err = tg3_get_invariants(tp, ent);
if (err) {
dev_err(&pdev->dev,
"Problem fetching invariants of chip, aborting\n");
@@ -16209,6 +16607,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ tg3_flag_set(tp, PTP_CAPABLE);
+
if (tg3_flag(tp, 5717_PLUS)) {
/* Resume a low-power mode */
tg3_frob_aux_power(tp, false);
@@ -16293,7 +16695,7 @@ err_out_disable_pdev:
return err;
}
-static void __devexit tg3_remove_one(struct pci_dev *pdev)
+static void tg3_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -16534,8 +16936,8 @@ static void tg3_io_resume(struct pci_dev *pdev)
tg3_full_lock(tp, 0);
tg3_flag_set(tp, INIT_COMPLETE);
err = tg3_restart_hw(tp, 1);
- tg3_full_unlock(tp);
if (err) {
+ tg3_full_unlock(tp);
netdev_err(netdev, "Cannot restart hardware after reset.\n");
goto done;
}
@@ -16546,6 +16948,8 @@ static void tg3_io_resume(struct pci_dev *pdev)
tg3_netif_start(tp);
+ tg3_full_unlock(tp);
+
tg3_phy_start(tp);
done:
@@ -16562,7 +16966,7 @@ static struct pci_driver tg3_driver = {
.name = DRV_MODULE_NAME,
.id_table = tg3_pci_tbl,
.probe = tg3_init_one,
- .remove = __devexit_p(tg3_remove_one),
+ .remove = tg3_remove_one,
.err_handler = &tg3_err_handler,
.driver.pm = TG3_PM_OPS,
};
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index d9308c32102e..d330e81f5793 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -44,12 +44,14 @@
#define TG3PCI_DEVICE_TIGON3_5761S 0x1688
#define TG3PCI_DEVICE_TIGON3_5761SE 0x1689
#define TG3PCI_DEVICE_TIGON3_57780 0x1692
+#define TG3PCI_DEVICE_TIGON3_5787M 0x1693
#define TG3PCI_DEVICE_TIGON3_57760 0x1690
#define TG3PCI_DEVICE_TIGON3_57790 0x1694
#define TG3PCI_DEVICE_TIGON3_57788 0x1691
#define TG3PCI_DEVICE_TIGON3_5785_G 0x1699 /* GPHY */
#define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 /* 10/100 only */
#define TG3PCI_DEVICE_TIGON3_5717 0x1655
+#define TG3PCI_DEVICE_TIGON3_5717_C 0x1665
#define TG3PCI_DEVICE_TIGON3_5718 0x1656
#define TG3PCI_DEVICE_TIGON3_57781 0x16b1
#define TG3PCI_DEVICE_TIGON3_57785 0x16b5
@@ -95,6 +97,10 @@
#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2 0x0099
#define TG3PCI_SUBVENDOR_ID_IBM PCI_VENDOR_ID_IBM
#define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2 0x0281
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_A 0x0601
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_B 0x0612
+#define TG3PCI_SUBDEVICE_ID_LENOVO_5787M 0x3056
+
/* 0x30 --> 0x64 unused */
#define TG3PCI_MSI_DATA 0x00000064
/* 0x66 --> 0x68 unused */
@@ -149,6 +155,7 @@
#define CHIPREV_ID_57780_A0 0x57780000
#define CHIPREV_ID_57780_A1 0x57780001
#define CHIPREV_ID_5717_A0 0x05717000
+#define CHIPREV_ID_5717_C0 0x05717200
#define CHIPREV_ID_57765_A0 0x57785000
#define CHIPREV_ID_5719_A0 0x05719000
#define CHIPREV_ID_5720_A0 0x05720000
@@ -765,7 +772,10 @@
#define SG_DIG_MAC_ACK_STATUS 0x00000004
#define SG_DIG_AUTONEG_COMPLETE 0x00000002
#define SG_DIG_AUTONEG_ERROR 0x00000001
-/* 0x5b8 --> 0x600 unused */
+#define TG3_TX_TSTAMP_LSB 0x000005c0
+#define TG3_TX_TSTAMP_MSB 0x000005c4
+#define TG3_TSTAMP_MASK 0x7fffffffffffffff
+/* 0x5c8 --> 0x600 unused */
#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */
#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */
/* 0x624 --> 0x670 unused */
@@ -782,7 +792,36 @@
#define MAC_RSS_HASH_KEY_7 0x0000068c
#define MAC_RSS_HASH_KEY_8 0x00000690
#define MAC_RSS_HASH_KEY_9 0x00000694
-/* 0x698 --> 0x800 unused */
+/* 0x698 --> 0x6b0 unused */
+
+#define TG3_RX_TSTAMP_LSB 0x000006b0
+#define TG3_RX_TSTAMP_MSB 0x000006b4
+/* 0x6b8 --> 0x6c8 unused */
+
+#define TG3_RX_PTP_CTL 0x000006c8
+#define TG3_RX_PTP_CTL_SYNC_EVNT 0x00000001
+#define TG3_RX_PTP_CTL_DELAY_REQ 0x00000002
+#define TG3_RX_PTP_CTL_PDLAY_REQ 0x00000004
+#define TG3_RX_PTP_CTL_PDLAY_RES 0x00000008
+#define TG3_RX_PTP_CTL_ALL_V1_EVENTS (TG3_RX_PTP_CTL_SYNC_EVNT | \
+ TG3_RX_PTP_CTL_DELAY_REQ)
+#define TG3_RX_PTP_CTL_ALL_V2_EVENTS (TG3_RX_PTP_CTL_SYNC_EVNT | \
+ TG3_RX_PTP_CTL_DELAY_REQ | \
+ TG3_RX_PTP_CTL_PDLAY_REQ | \
+ TG3_RX_PTP_CTL_PDLAY_RES)
+#define TG3_RX_PTP_CTL_FOLLOW_UP 0x00000100
+#define TG3_RX_PTP_CTL_DELAY_RES 0x00000200
+#define TG3_RX_PTP_CTL_PDRES_FLW_UP 0x00000400
+#define TG3_RX_PTP_CTL_ANNOUNCE 0x00000800
+#define TG3_RX_PTP_CTL_SIGNALING 0x00001000
+#define TG3_RX_PTP_CTL_MANAGEMENT 0x00002000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN 0x00800000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN 0x01000000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_EN (TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | \
+ TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN)
+#define TG3_RX_PTP_CTL_RX_PTP_V1_EN 0x02000000
+#define TG3_RX_PTP_CTL_HWTS_INTERLOCK 0x04000000
+/* 0x6cc --> 0x800 unused */
#define MAC_TX_STATS_OCTETS 0x00000800
#define MAC_TX_STATS_RESV1 0x00000804
@@ -1662,6 +1701,7 @@
#define GRC_MODE_HOST_STACKUP 0x00010000
#define GRC_MODE_HOST_SENDBDS 0x00020000
#define GRC_MODE_HTX2B_ENABLE 0x00040000
+#define GRC_MODE_TIME_SYNC_ENABLE 0x00080000
#define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000
#define GRC_MODE_NVRAM_WR_ENABLE 0x00200000
#define GRC_MODE_PCIE_TL_SEL 0x00000000
@@ -1764,7 +1804,17 @@
#define GRC_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000
#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */
-/* 0x6c00 --> 0x7000 unused */
+#define TG3_EAV_REF_CLCK_LSB 0x00006900
+#define TG3_EAV_REF_CLCK_MSB 0x00006904
+#define TG3_EAV_REF_CLCK_CTL 0x00006908
+#define TG3_EAV_REF_CLCK_CTL_STOP 0x00000002
+#define TG3_EAV_REF_CLCK_CTL_RESUME 0x00000004
+#define TG3_EAV_REF_CLK_CORRECT_CTL 0x00006928
+#define TG3_EAV_REF_CLK_CORRECT_EN (1 << 31)
+#define TG3_EAV_REF_CLK_CORRECT_NEG (1 << 30)
+
+#define TG3_EAV_REF_CLK_CORRECT_MASK 0xffffff
+/* 0x690c --> 0x7000 unused */
/* NVRAM Control registers */
#define NVRAM_CMD 0x00007000
@@ -2432,6 +2482,7 @@ struct tg3_tx_buffer_desc {
#define TXD_FLAG_IP_FRAG 0x0008
#define TXD_FLAG_JMB_PKT 0x0008
#define TXD_FLAG_IP_FRAG_END 0x0010
+#define TXD_FLAG_HWTSTAMP 0x0020
#define TXD_FLAG_VLAN 0x0040
#define TXD_FLAG_COAL_NOW 0x0080
#define TXD_FLAG_CPU_PRE_DMA 0x0100
@@ -2473,6 +2524,9 @@ struct tg3_rx_buffer_desc {
#define RXD_FLAG_IP_CSUM 0x1000
#define RXD_FLAG_TCPUDP_CSUM 0x2000
#define RXD_FLAG_IS_TCP 0x4000
+#define RXD_FLAG_PTPSTAT_MASK 0x0210
+#define RXD_FLAG_PTPSTAT_PTPV1 0x0010
+#define RXD_FLAG_PTPSTAT_PTPV2 0x0200
u32 ip_tcp_csum;
#define RXD_IPCSUM_MASK 0xffff0000
@@ -2963,9 +3017,11 @@ enum TG3_FLAGS {
TG3_FLAG_USE_JUMBO_BDFLAG,
TG3_FLAG_L1PLLPD_EN,
TG3_FLAG_APE_HAS_NCSI,
+ TG3_FLAG_TX_TSTAMP_EN,
TG3_FLAG_4K_FIFO_LIMIT,
TG3_FLAG_5719_RDMA_BUG,
TG3_FLAG_RESET_TASK_PENDING,
+ TG3_FLAG_PTP_CAPABLE,
TG3_FLAG_5705_PLUS,
TG3_FLAG_IS_5788,
TG3_FLAG_5750_PLUS,
@@ -3034,6 +3090,10 @@ struct tg3 {
u32 coal_now;
u32 msg_enable;
+ struct ptp_clock_info ptp_info;
+ struct ptp_clock *ptp_clock;
+ s64 ptp_adjust;
+
/* begin "tx thread" cacheline section */
void (*write32_tx_mbox) (struct tg3 *, u32,
u32);
@@ -3101,6 +3161,7 @@ struct tg3 {
u32 dma_rwctrl;
u32 coalesce_mode;
u32 pwrmgmt_thresh;
+ u32 rxptpctl;
/* PCI block */
u32 pci_chip_rev_id;
@@ -3262,6 +3323,7 @@ struct tg3 {
#if IS_ENABLED(CONFIG_HWMON)
struct device *hwmon_dev;
#endif
+ bool link_up;
};
#endif /* !(_T3_H) */
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 959c58ef972a..3227fdde521b 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -2273,7 +2273,6 @@ bfa_ioc_get_type(struct bfa_ioc *ioc)
static void
bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
{
- memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
memcpy(serial_num,
(void *)ioc->attr->brcd_serialnum,
BFA_ADAPTER_SERIAL_NUM_LEN);
@@ -2282,7 +2281,6 @@ bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
static void
bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
{
- memset(fw_ver, 0, BFA_VERSION_LEN);
memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
}
@@ -2304,7 +2302,6 @@ bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
static void
bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
{
- memset(optrom_ver, 0, BFA_VERSION_LEN);
memcpy(optrom_ver, ioc->attr->optrom_version,
BFA_VERSION_LEN);
}
@@ -2312,7 +2309,6 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
static void
bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
{
- memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
}
diff --git a/drivers/net/ethernet/brocade/bna/bfi_enet.h b/drivers/net/ethernet/brocade/bna/bfi_enet.h
index eef6e1f8aecc..7d10e335c27d 100644
--- a/drivers/net/ethernet/brocade/bna/bfi_enet.h
+++ b/drivers/net/ethernet/brocade/bna/bfi_enet.h
@@ -787,6 +787,7 @@ struct bfi_enet_stats_bpc {
/* MAC Rx Statistics */
struct bfi_enet_stats_mac {
+ u64 stats_clr_cnt; /* times this stats cleared */
u64 frame_64; /* both rx and tx counter */
u64 frame_65_127; /* both rx and tx counter */
u64 frame_128_255; /* both rx and tx counter */
diff --git a/drivers/net/ethernet/brocade/bna/bna.h b/drivers/net/ethernet/brocade/bna/bna.h
index ede532b4e9db..25dae757e9c4 100644
--- a/drivers/net/ethernet/brocade/bna/bna.h
+++ b/drivers/net/ethernet/brocade/bna/bna.h
@@ -138,6 +138,8 @@ do { \
#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth) \
((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1))
+#define BNA_QE_INDX_INC(_idx, _q_depth) BNA_QE_INDX_ADD(_idx, 1, _q_depth)
+
#define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth) \
(((_updated_idx) - (_old_idx)) & ((_q_depth) - 1))
diff --git a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
index b8c4e21fbf4c..af3f7bb0b3b8 100644
--- a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
+++ b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
@@ -46,7 +46,8 @@
#define BFI_MAX_INTERPKT_COUNT 0xFF
#define BFI_MAX_INTERPKT_TIMEO 0xF /* in 0.5us units */
#define BFI_TX_COALESCING_TIMEO 20 /* 20 * 5 = 100us */
-#define BFI_TX_INTERPKT_COUNT 32
+#define BFI_TX_INTERPKT_COUNT 12 /* Pkt Cnt = 12 */
+#define BFI_TX_INTERPKT_TIMEO 15 /* 15 * 0.5 = 7.5us */
#define BFI_RX_COALESCING_TIMEO 12 /* 12 * 5 = 60us */
#define BFI_RX_INTERPKT_COUNT 6 /* Pkt Cnt = 6 */
#define BFI_RX_INTERPKT_TIMEO 3 /* 3 * 0.5 = 1.5us */
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
index 71144b396e02..ea6f4a036401 100644
--- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
+++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
@@ -1355,6 +1355,8 @@ bfa_fsm_state_decl(bna_rx, stopped,
struct bna_rx, enum bna_rx_event);
bfa_fsm_state_decl(bna_rx, start_wait,
struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, start_stop_wait,
+ struct bna_rx, enum bna_rx_event);
bfa_fsm_state_decl(bna_rx, rxf_start_wait,
struct bna_rx, enum bna_rx_event);
bfa_fsm_state_decl(bna_rx, started,
@@ -1432,7 +1434,7 @@ static void bna_rx_sm_start_wait(struct bna_rx *rx,
{
switch (event) {
case RX_E_STOP:
- bfa_fsm_set_state(rx, bna_rx_sm_stop_wait);
+ bfa_fsm_set_state(rx, bna_rx_sm_start_stop_wait);
break;
case RX_E_FAIL:
@@ -1488,6 +1490,29 @@ bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
}
+static void
+bna_rx_sm_start_stop_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_start_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_FAIL:
+ case RX_E_STOPPED:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ break;
+
+ case RX_E_STARTED:
+ bna_rx_enet_stop(rx);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
void
bna_rx_sm_started_entry(struct bna_rx *rx)
{
@@ -1908,6 +1933,9 @@ bna_rxq_qpt_setup(struct bna_rxq *rxq,
struct bna_mem_descr *swqpt_mem,
struct bna_mem_descr *page_mem)
{
+ u8 *kva;
+ u64 dma;
+ struct bna_dma_addr bna_dma;
int i;
rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
@@ -1917,13 +1945,21 @@ bna_rxq_qpt_setup(struct bna_rxq *rxq,
rxq->qpt.page_size = page_size;
rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
+ rxq->rcb->sw_q = page_mem->kva;
+
+ kva = page_mem->kva;
+ BNA_GET_DMA_ADDR(&page_mem->dma, dma);
for (i = 0; i < rxq->qpt.page_count; i++) {
- rxq->rcb->sw_qpt[i] = page_mem[i].kva;
+ rxq->rcb->sw_qpt[i] = kva;
+ kva += PAGE_SIZE;
+
+ BNA_SET_DMA_ADDR(dma, &bna_dma);
((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
+ bna_dma.lsb;
((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
+ bna_dma.msb;
+ dma += PAGE_SIZE;
}
}
@@ -1935,6 +1971,9 @@ bna_rxp_cqpt_setup(struct bna_rxp *rxp,
struct bna_mem_descr *swqpt_mem,
struct bna_mem_descr *page_mem)
{
+ u8 *kva;
+ u64 dma;
+ struct bna_dma_addr bna_dma;
int i;
rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
@@ -1944,14 +1983,21 @@ bna_rxp_cqpt_setup(struct bna_rxp *rxp,
rxp->cq.qpt.page_size = page_size;
rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
+ rxp->cq.ccb->sw_q = page_mem->kva;
+
+ kva = page_mem->kva;
+ BNA_GET_DMA_ADDR(&page_mem->dma, dma);
for (i = 0; i < rxp->cq.qpt.page_count; i++) {
- rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
+ rxp->cq.ccb->sw_qpt[i] = kva;
+ kva += PAGE_SIZE;
+ BNA_SET_DMA_ADDR(dma, &bna_dma);
((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
+ bna_dma.lsb;
((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
+ bna_dma.msb;
+ dma += PAGE_SIZE;
}
}
@@ -2250,8 +2296,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = PAGE_SIZE;
- mem_info->num = cpage_count * q_cfg->num_paths;
+ mem_info->len = PAGE_SIZE * cpage_count;
+ mem_info->num = q_cfg->num_paths;
res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
@@ -2268,8 +2314,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = PAGE_SIZE;
- mem_info->num = dpage_count * q_cfg->num_paths;
+ mem_info->len = PAGE_SIZE * dpage_count;
+ mem_info->num = q_cfg->num_paths;
res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
@@ -2286,8 +2332,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = (hpage_count ? PAGE_SIZE : 0);
- mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
+ mem_info->len = PAGE_SIZE * hpage_count;
+ mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
res_info[BNA_RX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info;
@@ -2332,7 +2378,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
struct bna_mem_descr *dsqpt_mem;
struct bna_mem_descr *hpage_mem;
struct bna_mem_descr *dpage_mem;
- int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0;
+ int i;
int dpage_count, hpage_count, rcb_idx;
if (!bna_rx_res_check(rx_mod, rx_cfg))
@@ -2352,14 +2398,14 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
- page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
+ page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.len /
+ PAGE_SIZE;
- dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
+ dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.len /
+ PAGE_SIZE;
- hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
+ hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.len /
+ PAGE_SIZE;
rx = bna_rx_get(rx_mod, rx_cfg->rx_type);
rx->bna = bna;
@@ -2446,10 +2492,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
q0->rx_packets_with_error = q0->rxbuf_alloc_failed = 0;
bna_rxq_qpt_setup(q0, rxp, dpage_count, PAGE_SIZE,
- &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
- q0->rcb->page_idx = dpage_idx;
- q0->rcb->page_count = dpage_count;
- dpage_idx += dpage_count;
+ &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[i]);
if (rx->rcb_setup_cbfn)
rx->rcb_setup_cbfn(bnad, q0->rcb);
@@ -2475,10 +2518,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
bna_rxq_qpt_setup(q1, rxp, hpage_count, PAGE_SIZE,
&hqpt_mem[i], &hsqpt_mem[i],
- &hpage_mem[hpage_idx]);
- q1->rcb->page_idx = hpage_idx;
- q1->rcb->page_count = hpage_count;
- hpage_idx += hpage_count;
+ &hpage_mem[i]);
if (rx->rcb_setup_cbfn)
rx->rcb_setup_cbfn(bnad, q1->rcb);
@@ -2510,10 +2550,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
rxp->cq.ccb->id = i;
bna_rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
- &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
- rxp->cq.ccb->page_idx = cpage_idx;
- rxp->cq.ccb->page_count = page_count;
- cpage_idx += page_count;
+ &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[i]);
if (rx->ccb_setup_cbfn)
rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
@@ -3230,6 +3267,9 @@ bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
struct bna_mem_descr *swqpt_mem,
struct bna_mem_descr *page_mem)
{
+ u8 *kva;
+ u64 dma;
+ struct bna_dma_addr bna_dma;
int i;
txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
@@ -3239,14 +3279,21 @@ bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
txq->qpt.page_size = page_size;
txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
+ txq->tcb->sw_q = page_mem->kva;
+
+ kva = page_mem->kva;
+ BNA_GET_DMA_ADDR(&page_mem->dma, dma);
for (i = 0; i < page_count; i++) {
- txq->tcb->sw_qpt[i] = page_mem[i].kva;
+ txq->tcb->sw_qpt[i] = kva;
+ kva += PAGE_SIZE;
+ BNA_SET_DMA_ADDR(dma, &bna_dma);
((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
+ bna_dma.lsb;
((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
+ bna_dma.msb;
+ dma += PAGE_SIZE;
}
}
@@ -3430,8 +3477,8 @@ bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = PAGE_SIZE;
- mem_info->num = num_txq * page_count;
+ mem_info->len = PAGE_SIZE * page_count;
+ mem_info->num = num_txq;
res_info[BNA_TX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
mem_info = &res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info;
@@ -3457,14 +3504,11 @@ bna_tx_create(struct bna *bna, struct bnad *bnad,
struct bna_txq *txq;
struct list_head *qe;
int page_count;
- int page_size;
- int page_idx;
int i;
intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
- page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
- tx_cfg->num_txq;
- page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
+ page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len) /
+ PAGE_SIZE;
/**
* Get resources
@@ -3529,7 +3573,6 @@ bna_tx_create(struct bna *bna, struct bnad *bnad,
/* TxQ */
i = 0;
- page_idx = 0;
list_for_each(qe, &tx->txq_q) {
txq = (struct bna_txq *)qe;
txq->tcb = (struct bna_tcb *)
@@ -3551,7 +3594,7 @@ bna_tx_create(struct bna *bna, struct bnad *bnad,
if (intr_info->intr_type == BNA_INTR_T_INTX)
txq->ib.intr_vector = (1 << txq->ib.intr_vector);
txq->ib.coalescing_timeo = tx_cfg->coalescing_timeo;
- txq->ib.interpkt_timeo = 0; /* Not used */
+ txq->ib.interpkt_timeo = BFI_TX_INTERPKT_TIMEO;
txq->ib.interpkt_count = BFI_TX_INTERPKT_COUNT;
/* TCB */
@@ -3569,14 +3612,11 @@ bna_tx_create(struct bna *bna, struct bnad *bnad,
txq->tcb->id = i;
/* QPT, SWQPT, Pages */
- bna_txq_qpt_setup(txq, page_count, page_size,
+ bna_txq_qpt_setup(txq, page_count, PAGE_SIZE,
&res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
&res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
&res_info[BNA_TX_RES_MEM_T_PAGE].
- res_u.mem_info.mdl[page_idx]);
- txq->tcb->page_idx = page_idx;
- txq->tcb->page_count = page_count;
- page_idx += page_count;
+ res_u.mem_info.mdl[i]);
/* Callback to bnad for setting up TCB */
if (tx->tcb_setup_cbfn)
diff --git a/drivers/net/ethernet/brocade/bna/bna_types.h b/drivers/net/ethernet/brocade/bna/bna_types.h
index d3eb8bddfb2a..dc50f7836b6d 100644
--- a/drivers/net/ethernet/brocade/bna/bna_types.h
+++ b/drivers/net/ethernet/brocade/bna/bna_types.h
@@ -430,6 +430,7 @@ struct bna_ib {
struct bna_tcb {
/* Fast path */
void **sw_qpt;
+ void *sw_q;
void *unmap_q;
u32 producer_index;
u32 consumer_index;
@@ -437,8 +438,6 @@ struct bna_tcb {
u32 q_depth;
void __iomem *q_dbell;
struct bna_ib_dbell *i_dbell;
- int page_idx;
- int page_count;
/* Control path */
struct bna_txq *txq;
struct bnad *bnad;
@@ -563,13 +562,12 @@ struct bna_tx_mod {
struct bna_rcb {
/* Fast path */
void **sw_qpt;
+ void *sw_q;
void *unmap_q;
u32 producer_index;
u32 consumer_index;
u32 q_depth;
void __iomem *q_dbell;
- int page_idx;
- int page_count;
/* Control path */
struct bna_rxq *rxq;
struct bna_ccb *ccb;
@@ -626,6 +624,7 @@ struct bna_pkt_rate {
struct bna_ccb {
/* Fast path */
void **sw_qpt;
+ void *sw_q;
u32 producer_index;
volatile u32 *hw_producer_index;
u32 q_depth;
@@ -633,8 +632,6 @@ struct bna_ccb {
struct bna_rcb *rcb[2];
void *ctrl; /* For bnad */
struct bna_pkt_rate pkt_rate;
- int page_idx;
- int page_count;
/* Control path */
struct bna_cq *cq;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index ce1eac529470..7cce42dc2f20 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -61,23 +61,17 @@ static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/*
* Local MACROS
*/
-#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2)
-
-#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth)
-
#define BNAD_GET_MBOX_IRQ(_bnad) \
(((_bnad)->cfg_flags & BNAD_CF_MSIX) ? \
((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \
((_bnad)->pcidev->irq))
-#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth) \
+#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _size) \
do { \
(_res_info)->res_type = BNA_RES_T_MEM; \
(_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA; \
(_res_info)->res_u.mem_info.num = (_num); \
- (_res_info)->res_u.mem_info.len = \
- sizeof(struct bnad_unmap_q) + \
- (sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \
+ (_res_info)->res_u.mem_info.len = (_size); \
} while (0)
static void
@@ -103,48 +97,58 @@ bnad_remove_from_list(struct bnad *bnad)
static void
bnad_cq_cleanup(struct bnad *bnad, struct bna_ccb *ccb)
{
- struct bna_cq_entry *cmpl, *next_cmpl;
- unsigned int wi_range, wis = 0, ccb_prod = 0;
+ struct bna_cq_entry *cmpl;
int i;
- BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl,
- wi_range);
-
for (i = 0; i < ccb->q_depth; i++) {
- wis++;
- if (likely(--wi_range))
- next_cmpl = cmpl + 1;
- else {
- BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth);
- wis = 0;
- BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt,
- next_cmpl, wi_range);
- }
+ cmpl = &((struct bna_cq_entry *)ccb->sw_q)[i];
cmpl->valid = 0;
- cmpl = next_cmpl;
}
}
+/* Tx Datapath functions */
+
+
+/* Caller should ensure that the entry at unmap_q[index] is valid */
static u32
-bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
- u32 index, u32 depth, struct sk_buff *skb, u32 frag)
+bnad_tx_buff_unmap(struct bnad *bnad,
+ struct bnad_tx_unmap *unmap_q,
+ u32 q_depth, u32 index)
{
- int j;
- array[index].skb = NULL;
-
- dma_unmap_single(pdev, dma_unmap_addr(&array[index], dma_addr),
- skb_headlen(skb), DMA_TO_DEVICE);
- dma_unmap_addr_set(&array[index], dma_addr, 0);
- BNA_QE_INDX_ADD(index, 1, depth);
+ struct bnad_tx_unmap *unmap;
+ struct sk_buff *skb;
+ int vector, nvecs;
+
+ unmap = &unmap_q[index];
+ nvecs = unmap->nvecs;
+
+ skb = unmap->skb;
+ unmap->skb = NULL;
+ unmap->nvecs = 0;
+ dma_unmap_single(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vectors[0], dma_addr),
+ skb_headlen(skb), DMA_TO_DEVICE);
+ dma_unmap_addr_set(&unmap->vectors[0], dma_addr, 0);
+ nvecs--;
+
+ vector = 0;
+ while (nvecs) {
+ vector++;
+ if (vector == BFI_TX_MAX_VECTORS_PER_WI) {
+ vector = 0;
+ BNA_QE_INDX_INC(index, q_depth);
+ unmap = &unmap_q[index];
+ }
- for (j = 0; j < frag; j++) {
- dma_unmap_page(pdev, dma_unmap_addr(&array[index], dma_addr),
- skb_frag_size(&skb_shinfo(skb)->frags[j]),
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&array[index], dma_addr, 0);
- BNA_QE_INDX_ADD(index, 1, depth);
+ dma_unmap_page(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vectors[vector], dma_addr),
+ skb_shinfo(skb)->frags[nvecs].size, DMA_TO_DEVICE);
+ dma_unmap_addr_set(&unmap->vectors[vector], dma_addr, 0);
+ nvecs--;
}
+ BNA_QE_INDX_INC(index, q_depth);
+
return index;
}
@@ -154,80 +158,64 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
* so DMA unmap & freeing is fine.
*/
static void
-bnad_txq_cleanup(struct bnad *bnad,
- struct bna_tcb *tcb)
+bnad_txq_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
{
- u32 unmap_cons;
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
- struct bnad_skb_unmap *unmap_array;
- struct sk_buff *skb = NULL;
- int q;
-
- unmap_array = unmap_q->unmap_array;
+ struct bnad_tx_unmap *unmap_q = tcb->unmap_q;
+ struct sk_buff *skb;
+ int i;
- for (q = 0; q < unmap_q->q_depth; q++) {
- skb = unmap_array[q].skb;
+ for (i = 0; i < tcb->q_depth; i++) {
+ skb = unmap_q[i].skb;
if (!skb)
continue;
-
- unmap_cons = q;
- unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array,
- unmap_cons, unmap_q->q_depth, skb,
- skb_shinfo(skb)->nr_frags);
+ bnad_tx_buff_unmap(bnad, unmap_q, tcb->q_depth, i);
dev_kfree_skb_any(skb);
}
}
-/* Data Path Handlers */
-
/*
* bnad_txcmpl_process : Frees the Tx bufs on Tx completion
* Can be called in a) Interrupt context
* b) Sending context
*/
static u32
-bnad_txcmpl_process(struct bnad *bnad,
- struct bna_tcb *tcb)
+bnad_txcmpl_process(struct bnad *bnad, struct bna_tcb *tcb)
{
- u32 unmap_cons, sent_packets = 0, sent_bytes = 0;
- u16 wis, updated_hw_cons;
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
- struct bnad_skb_unmap *unmap_array;
- struct sk_buff *skb;
+ u32 sent_packets = 0, sent_bytes = 0;
+ u32 wis, unmap_wis, hw_cons, cons, q_depth;
+ struct bnad_tx_unmap *unmap_q = tcb->unmap_q;
+ struct bnad_tx_unmap *unmap;
+ struct sk_buff *skb;
/* Just return if TX is stopped */
if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
return 0;
- updated_hw_cons = *(tcb->hw_consumer_index);
-
- wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index,
- updated_hw_cons, tcb->q_depth);
+ hw_cons = *(tcb->hw_consumer_index);
+ cons = tcb->consumer_index;
+ q_depth = tcb->q_depth;
+ wis = BNA_Q_INDEX_CHANGE(cons, hw_cons, q_depth);
BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth)));
- unmap_array = unmap_q->unmap_array;
- unmap_cons = unmap_q->consumer_index;
-
- prefetch(&unmap_array[unmap_cons + 1]);
while (wis) {
- skb = unmap_array[unmap_cons].skb;
+ unmap = &unmap_q[cons];
+
+ skb = unmap->skb;
sent_packets++;
sent_bytes += skb->len;
- wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
- unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array,
- unmap_cons, unmap_q->q_depth, skb,
- skb_shinfo(skb)->nr_frags);
+ unmap_wis = BNA_TXQ_WI_NEEDED(unmap->nvecs);
+ wis -= unmap_wis;
+ cons = bnad_tx_buff_unmap(bnad, unmap_q, q_depth, cons);
dev_kfree_skb_any(skb);
}
/* Update consumer pointers. */
- tcb->consumer_index = updated_hw_cons;
- unmap_q->consumer_index = unmap_cons;
+ tcb->consumer_index = hw_cons;
tcb->txq->tx_packets += sent_packets;
tcb->txq->tx_bytes += sent_bytes;
@@ -278,133 +266,306 @@ bnad_msix_tx(int irq, void *data)
return IRQ_HANDLED;
}
-static void
-bnad_rcb_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
+static inline void
+bnad_rxq_alloc_uninit(struct bnad *bnad, struct bna_rcb *rcb)
{
- struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+
+ unmap_q->reuse_pi = -1;
+ unmap_q->alloc_order = -1;
+ unmap_q->map_size = 0;
+ unmap_q->type = BNAD_RXBUF_NONE;
+}
+
+/* Default is page-based allocation. Multi-buffer support - TBD */
+static int
+bnad_rxq_alloc_init(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+ int mtu, order;
+
+ bnad_rxq_alloc_uninit(bnad, rcb);
+
+ mtu = bna_enet_mtu_get(&bnad->bna.enet);
+ order = get_order(mtu);
+
+ if (bna_is_small_rxq(rcb->id)) {
+ unmap_q->alloc_order = 0;
+ unmap_q->map_size = rcb->rxq->buffer_size;
+ } else {
+ unmap_q->alloc_order = order;
+ unmap_q->map_size =
+ (rcb->rxq->buffer_size > 2048) ?
+ PAGE_SIZE << order : 2048;
+ }
+
+ BUG_ON(((PAGE_SIZE << order) % unmap_q->map_size));
+
+ unmap_q->type = BNAD_RXBUF_PAGE;
+
+ return 0;
+}
+
+static inline void
+bnad_rxq_cleanup_page(struct bnad *bnad, struct bnad_rx_unmap *unmap)
+{
+ if (!unmap->page)
+ return;
+
+ dma_unmap_page(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vector, dma_addr),
+ unmap->vector.len, DMA_FROM_DEVICE);
+ put_page(unmap->page);
+ unmap->page = NULL;
+ dma_unmap_addr_set(&unmap->vector, dma_addr, 0);
+ unmap->vector.len = 0;
+}
- rcb->producer_index = 0;
- rcb->consumer_index = 0;
+static inline void
+bnad_rxq_cleanup_skb(struct bnad *bnad, struct bnad_rx_unmap *unmap)
+{
+ if (!unmap->skb)
+ return;
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
+ dma_unmap_single(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vector, dma_addr),
+ unmap->vector.len, DMA_FROM_DEVICE);
+ dev_kfree_skb_any(unmap->skb);
+ unmap->skb = NULL;
+ dma_unmap_addr_set(&unmap->vector, dma_addr, 0);
+ unmap->vector.len = 0;
}
static void
bnad_rxq_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
{
- struct bnad_unmap_q *unmap_q;
- struct bnad_skb_unmap *unmap_array;
- struct sk_buff *skb;
- int unmap_cons;
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+ int i;
- unmap_q = rcb->unmap_q;
- unmap_array = unmap_q->unmap_array;
- for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
- skb = unmap_array[unmap_cons].skb;
- if (!skb)
- continue;
- unmap_array[unmap_cons].skb = NULL;
- dma_unmap_single(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr),
- rcb->rxq->buffer_size,
- DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
+ for (i = 0; i < rcb->q_depth; i++) {
+ struct bnad_rx_unmap *unmap = &unmap_q->unmap[i];
+
+ if (BNAD_RXBUF_IS_PAGE(unmap_q->type))
+ bnad_rxq_cleanup_page(bnad, unmap);
+ else
+ bnad_rxq_cleanup_skb(bnad, unmap);
}
- bnad_rcb_cleanup(bnad, rcb);
+ bnad_rxq_alloc_uninit(bnad, rcb);
}
-static void
-bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb)
+static u32
+bnad_rxq_refill_page(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc)
{
- u16 to_alloc, alloced, unmap_prod, wi_range;
- struct bnad_unmap_q *unmap_q = rcb->unmap_q;
- struct bnad_skb_unmap *unmap_array;
+ u32 alloced, prod, q_depth;
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+ struct bnad_rx_unmap *unmap, *prev;
struct bna_rxq_entry *rxent;
- struct sk_buff *skb;
+ struct page *page;
+ u32 page_offset, alloc_size;
dma_addr_t dma_addr;
+ prod = rcb->producer_index;
+ q_depth = rcb->q_depth;
+
+ alloc_size = PAGE_SIZE << unmap_q->alloc_order;
alloced = 0;
- to_alloc =
- BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth);
- unmap_array = unmap_q->unmap_array;
- unmap_prod = unmap_q->producer_index;
+ while (nalloc--) {
+ unmap = &unmap_q->unmap[prod];
- BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
+ if (unmap_q->reuse_pi < 0) {
+ page = alloc_pages(GFP_ATOMIC | __GFP_COMP,
+ unmap_q->alloc_order);
+ page_offset = 0;
+ } else {
+ prev = &unmap_q->unmap[unmap_q->reuse_pi];
+ page = prev->page;
+ page_offset = prev->page_offset + unmap_q->map_size;
+ get_page(page);
+ }
+
+ if (unlikely(!page)) {
+ BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
+ rcb->rxq->rxbuf_alloc_failed++;
+ goto finishing;
+ }
+
+ dma_addr = dma_map_page(&bnad->pcidev->dev, page, page_offset,
+ unmap_q->map_size, DMA_FROM_DEVICE);
+
+ unmap->page = page;
+ unmap->page_offset = page_offset;
+ dma_unmap_addr_set(&unmap->vector, dma_addr, dma_addr);
+ unmap->vector.len = unmap_q->map_size;
+ page_offset += unmap_q->map_size;
+
+ if (page_offset < alloc_size)
+ unmap_q->reuse_pi = prod;
+ else
+ unmap_q->reuse_pi = -1;
+
+ rxent = &((struct bna_rxq_entry *)rcb->sw_q)[prod];
+ BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
+ BNA_QE_INDX_INC(prod, q_depth);
+ alloced++;
+ }
+
+finishing:
+ if (likely(alloced)) {
+ rcb->producer_index = prod;
+ smp_mb();
+ if (likely(test_bit(BNAD_RXQ_POST_OK, &rcb->flags)))
+ bna_rxq_prod_indx_doorbell(rcb);
+ }
+
+ return alloced;
+}
+
+static u32
+bnad_rxq_refill_skb(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc)
+{
+ u32 alloced, prod, q_depth, buff_sz;
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+ struct bnad_rx_unmap *unmap;
+ struct bna_rxq_entry *rxent;
+ struct sk_buff *skb;
+ dma_addr_t dma_addr;
+
+ buff_sz = rcb->rxq->buffer_size;
+ prod = rcb->producer_index;
+ q_depth = rcb->q_depth;
+
+ alloced = 0;
+ while (nalloc--) {
+ unmap = &unmap_q->unmap[prod];
+
+ skb = netdev_alloc_skb_ip_align(bnad->netdev, buff_sz);
- while (to_alloc--) {
- if (!wi_range)
- BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
- wi_range);
- skb = netdev_alloc_skb_ip_align(bnad->netdev,
- rcb->rxq->buffer_size);
if (unlikely(!skb)) {
BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
rcb->rxq->rxbuf_alloc_failed++;
goto finishing;
}
- unmap_array[unmap_prod].skb = skb;
dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
- rcb->rxq->buffer_size,
- DMA_FROM_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
- dma_addr);
- BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
- BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ buff_sz, DMA_FROM_DEVICE);
+
+ unmap->skb = skb;
+ dma_unmap_addr_set(&unmap->vector, dma_addr, dma_addr);
+ unmap->vector.len = buff_sz;
- rxent++;
- wi_range--;
+ rxent = &((struct bna_rxq_entry *)rcb->sw_q)[prod];
+ BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
+ BNA_QE_INDX_INC(prod, q_depth);
alloced++;
}
finishing:
if (likely(alloced)) {
- unmap_q->producer_index = unmap_prod;
- rcb->producer_index = unmap_prod;
+ rcb->producer_index = prod;
smp_mb();
if (likely(test_bit(BNAD_RXQ_POST_OK, &rcb->flags)))
bna_rxq_prod_indx_doorbell(rcb);
}
+
+ return alloced;
}
static inline void
-bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb)
{
- struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+ struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q;
+ u32 to_alloc;
- if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
- if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
- >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_rxq_post(bnad, rcb);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+ to_alloc = BNA_QE_FREE_CNT(rcb, rcb->q_depth);
+ if (!(to_alloc >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT))
+ return;
+
+ if (BNAD_RXBUF_IS_PAGE(unmap_q->type))
+ bnad_rxq_refill_page(bnad, rcb, to_alloc);
+ else
+ bnad_rxq_refill_skb(bnad, rcb, to_alloc);
+}
+
+#define flags_cksum_prot_mask (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \
+ BNA_CQ_EF_IPV6 | \
+ BNA_CQ_EF_TCP | BNA_CQ_EF_UDP | \
+ BNA_CQ_EF_L4_CKSUM_OK)
+
+#define flags_tcp4 (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \
+ BNA_CQ_EF_TCP | BNA_CQ_EF_L4_CKSUM_OK)
+#define flags_tcp6 (BNA_CQ_EF_IPV6 | \
+ BNA_CQ_EF_TCP | BNA_CQ_EF_L4_CKSUM_OK)
+#define flags_udp4 (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \
+ BNA_CQ_EF_UDP | BNA_CQ_EF_L4_CKSUM_OK)
+#define flags_udp6 (BNA_CQ_EF_IPV6 | \
+ BNA_CQ_EF_UDP | BNA_CQ_EF_L4_CKSUM_OK)
+
+static inline struct sk_buff *
+bnad_cq_prepare_skb(struct bnad_rx_ctrl *rx_ctrl,
+ struct bnad_rx_unmap_q *unmap_q,
+ struct bnad_rx_unmap *unmap,
+ u32 length, u32 flags)
+{
+ struct bnad *bnad = rx_ctrl->bnad;
+ struct sk_buff *skb;
+
+ if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) {
+ skb = napi_get_frags(&rx_ctrl->napi);
+ if (unlikely(!skb))
+ return NULL;
+
+ dma_unmap_page(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vector, dma_addr),
+ unmap->vector.len, DMA_FROM_DEVICE);
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+ unmap->page, unmap->page_offset, length);
+ skb->len += length;
+ skb->data_len += length;
+ skb->truesize += length;
+
+ unmap->page = NULL;
+ unmap->vector.len = 0;
+
+ return skb;
}
+
+ skb = unmap->skb;
+ BUG_ON(!skb);
+
+ dma_unmap_single(&bnad->pcidev->dev,
+ dma_unmap_addr(&unmap->vector, dma_addr),
+ unmap->vector.len, DMA_FROM_DEVICE);
+
+ skb_put(skb, length);
+
+ skb->protocol = eth_type_trans(skb, bnad->netdev);
+
+ unmap->skb = NULL;
+ unmap->vector.len = 0;
+ return skb;
}
static u32
bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
{
- struct bna_cq_entry *cmpl, *next_cmpl;
+ struct bna_cq_entry *cq, *cmpl;
struct bna_rcb *rcb = NULL;
- unsigned int wi_range, packets = 0, wis = 0;
- struct bnad_unmap_q *unmap_q;
- struct bnad_skb_unmap *unmap_array;
+ struct bnad_rx_unmap_q *unmap_q;
+ struct bnad_rx_unmap *unmap;
struct sk_buff *skb;
- u32 flags, unmap_cons;
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
- struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
-
- if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
- return 0;
+ struct bnad_rx_ctrl *rx_ctrl = ccb->ctrl;
+ u32 packets = 0, length = 0, flags, masked_flags;
prefetch(bnad->netdev);
- BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
- wi_range);
- BUG_ON(!(wi_range <= ccb->q_depth));
- while (cmpl->valid && packets < budget) {
+
+ cq = ccb->sw_q;
+ cmpl = &cq[ccb->producer_index];
+
+ while (cmpl->valid && (packets < budget)) {
packets++;
+ flags = ntohl(cmpl->flags);
+ length = ntohs(cmpl->length);
BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
if (bna_is_small_rxq(cmpl->rxq_id))
@@ -413,83 +574,63 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
rcb = ccb->rcb[0];
unmap_q = rcb->unmap_q;
- unmap_array = unmap_q->unmap_array;
- unmap_cons = unmap_q->consumer_index;
-
- skb = unmap_array[unmap_cons].skb;
- BUG_ON(!(skb));
- unmap_array[unmap_cons].skb = NULL;
- dma_unmap_single(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr),
- rcb->rxq->buffer_size,
- DMA_FROM_DEVICE);
- BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
-
- /* Should be more efficient ? Performance ? */
- BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
-
- wis++;
- if (likely(--wi_range))
- next_cmpl = cmpl + 1;
- else {
- BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
- wis = 0;
- BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt,
- next_cmpl, wi_range);
- BUG_ON(!(wi_range <= ccb->q_depth));
- }
- prefetch(next_cmpl);
+ unmap = &unmap_q->unmap[rcb->consumer_index];
+
+ if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR |
+ BNA_CQ_EF_FCS_ERROR |
+ BNA_CQ_EF_TOO_LONG))) {
+ if (BNAD_RXBUF_IS_PAGE(unmap_q->type))
+ bnad_rxq_cleanup_page(bnad, unmap);
+ else
+ bnad_rxq_cleanup_skb(bnad, unmap);
- flags = ntohl(cmpl->flags);
- if (unlikely
- (flags &
- (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR |
- BNA_CQ_EF_TOO_LONG))) {
- dev_kfree_skb_any(skb);
rcb->rxq->rx_packets_with_error++;
goto next;
}
- skb_put(skb, ntohs(cmpl->length));
+ skb = bnad_cq_prepare_skb(ccb->ctrl, unmap_q, unmap,
+ length, flags);
+
+ if (unlikely(!skb))
+ break;
+
+ masked_flags = flags & flags_cksum_prot_mask;
+
if (likely
((bnad->netdev->features & NETIF_F_RXCSUM) &&
- (((flags & BNA_CQ_EF_IPV4) &&
- (flags & BNA_CQ_EF_L3_CKSUM_OK)) ||
- (flags & BNA_CQ_EF_IPV6)) &&
- (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) &&
- (flags & BNA_CQ_EF_L4_CKSUM_OK)))
+ ((masked_flags == flags_tcp4) ||
+ (masked_flags == flags_udp4) ||
+ (masked_flags == flags_tcp6) ||
+ (masked_flags == flags_udp6))))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb_checksum_none_assert(skb);
rcb->rxq->rx_packets++;
- rcb->rxq->rx_bytes += skb->len;
- skb->protocol = eth_type_trans(skb, bnad->netdev);
+ rcb->rxq->rx_bytes += length;
if (flags & BNA_CQ_EF_VLAN)
__vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag));
- if (skb->ip_summed == CHECKSUM_UNNECESSARY)
- napi_gro_receive(&rx_ctrl->napi, skb);
+ if (BNAD_RXBUF_IS_PAGE(unmap_q->type))
+ napi_gro_frags(&rx_ctrl->napi);
else
netif_receive_skb(skb);
next:
cmpl->valid = 0;
- cmpl = next_cmpl;
+ BNA_QE_INDX_INC(rcb->consumer_index, rcb->q_depth);
+ BNA_QE_INDX_INC(ccb->producer_index, ccb->q_depth);
+ cmpl = &cq[ccb->producer_index];
}
- BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
-
+ napi_gro_flush(&rx_ctrl->napi, false);
if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
bna_ib_ack_disable_irq(ccb->i_dbell, packets);
- bnad_refill_rxq(bnad, ccb->rcb[0]);
+ bnad_rxq_post(bnad, ccb->rcb[0]);
if (ccb->rcb[1])
- bnad_refill_rxq(bnad, ccb->rcb[1]);
-
- clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+ bnad_rxq_post(bnad, ccb->rcb[1]);
return packets;
}
@@ -764,12 +905,9 @@ bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
{
struct bnad_tx_info *tx_info =
(struct bnad_tx_info *)tcb->txq->tx->priv;
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+ tcb->priv = tcb;
tx_info->tcb[tcb->id] = tcb;
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
- unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
}
static void
@@ -783,16 +921,6 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
}
static void
-bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
-{
- struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
- unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH;
-}
-
-static void
bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bnad_rx_info *rx_info =
@@ -878,10 +1006,9 @@ bnad_tx_cleanup(struct delayed_work *work)
struct bnad_tx_info *tx_info =
container_of(work, struct bnad_tx_info, tx_cleanup_work);
struct bnad *bnad = NULL;
- struct bnad_unmap_q *unmap_q;
struct bna_tcb *tcb;
unsigned long flags;
- uint32_t i, pending = 0;
+ u32 i, pending = 0;
for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
tcb = tx_info->tcb[i];
@@ -897,10 +1024,6 @@ bnad_tx_cleanup(struct delayed_work *work)
bnad_txq_cleanup(bnad, tcb);
- unmap_q = tcb->unmap_q;
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
-
smp_mb__before_clear_bit();
clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
}
@@ -916,7 +1039,6 @@ bnad_tx_cleanup(struct delayed_work *work)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
-
static void
bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
{
@@ -965,7 +1087,7 @@ bnad_rx_cleanup(void *work)
struct bnad_rx_ctrl *rx_ctrl;
struct bnad *bnad = NULL;
unsigned long flags;
- uint32_t i;
+ u32 i;
for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
rx_ctrl = &rx_info->rx_ctrl[i];
@@ -1022,9 +1144,7 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
struct bna_ccb *ccb;
struct bna_rcb *rcb;
struct bnad_rx_ctrl *rx_ctrl;
- struct bnad_unmap_q *unmap_q;
- int i;
- int j;
+ int i, j;
for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
rx_ctrl = &rx_info->rx_ctrl[i];
@@ -1039,19 +1159,10 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!rcb)
continue;
+ bnad_rxq_alloc_init(bnad, rcb);
set_bit(BNAD_RXQ_STARTED, &rcb->flags);
set_bit(BNAD_RXQ_POST_OK, &rcb->flags);
- unmap_q = rcb->unmap_q;
-
- /* Now allocate & post buffers for this RCB */
- /* !!Allocation in callback context */
- if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
- if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
- >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_rxq_post(bnad, rcb);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
- }
+ bnad_rxq_post(bnad, rcb);
}
}
}
@@ -1775,10 +1886,9 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Fill Unmap Q memory requirements */
- BNAD_FILL_UNMAPQ_MEM_REQ(
- &res_info[BNA_TX_RES_MEM_T_UNMAPQ],
- bnad->num_txq_per_tx,
- BNAD_TX_UNMAPQ_DEPTH);
+ BNAD_FILL_UNMAPQ_MEM_REQ(&res_info[BNA_TX_RES_MEM_T_UNMAPQ],
+ bnad->num_txq_per_tx, (sizeof(struct bnad_tx_unmap) *
+ bnad->txq_depth));
/* Allocate resources */
err = bnad_tx_res_alloc(bnad, res_info, tx_id);
@@ -1916,7 +2026,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
&res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
static const struct bna_rx_event_cbfn rx_cbfn = {
- .rcb_setup_cbfn = bnad_cb_rcb_setup,
+ .rcb_setup_cbfn = NULL,
.rcb_destroy_cbfn = NULL,
.ccb_setup_cbfn = bnad_cb_ccb_setup,
.ccb_destroy_cbfn = bnad_cb_ccb_destroy,
@@ -1938,11 +2048,12 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Fill Unmap Q memory requirements */
- BNAD_FILL_UNMAPQ_MEM_REQ(
- &res_info[BNA_RX_RES_MEM_T_UNMAPQ],
+ BNAD_FILL_UNMAPQ_MEM_REQ(&res_info[BNA_RX_RES_MEM_T_UNMAPQ],
rx_config->num_paths +
- ((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 :
- rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH);
+ ((rx_config->rxp_type == BNA_RXP_SINGLE) ?
+ 0 : rx_config->num_paths),
+ ((bnad->rxq_depth * sizeof(struct bnad_rx_unmap)) +
+ sizeof(struct bnad_rx_unmap_q)));
/* Allocate resource */
err = bnad_rx_res_alloc(bnad, res_info, rx_id);
@@ -2523,125 +2634,34 @@ bnad_stop(struct net_device *netdev)
}
/* TX */
-/*
- * bnad_start_xmit : Netdev entry point for Transmit
- * Called under lock held by net_device
- */
-static netdev_tx_t
-bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+/* Returns 0 for success */
+static int
+bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb,
+ struct sk_buff *skb, struct bna_txq_entry *txqent)
{
- struct bnad *bnad = netdev_priv(netdev);
- u32 txq_id = 0;
- struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
-
- u16 txq_prod, vlan_tag = 0;
- u32 unmap_prod, wis, wis_used, wi_range;
- u32 vectors, vect_id, i, acked;
- int err;
- unsigned int len;
- u32 gso_size;
-
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
- dma_addr_t dma_addr;
- struct bna_txq_entry *txqent;
- u16 flags;
-
- if (unlikely(skb->len <= ETH_HLEN)) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, tx_skb_too_short);
- return NETDEV_TX_OK;
- }
- if (unlikely(skb_headlen(skb) > BFI_TX_MAX_DATA_PER_VECTOR)) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, tx_skb_headlen_too_long);
- return NETDEV_TX_OK;
- }
- if (unlikely(skb_headlen(skb) == 0)) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero);
- return NETDEV_TX_OK;
- }
-
- /*
- * Takes care of the Tx that is scheduled between clearing the flag
- * and the netif_tx_stop_all_queues() call.
- */
- if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, tx_skb_stopping);
- return NETDEV_TX_OK;
- }
-
- vectors = 1 + skb_shinfo(skb)->nr_frags;
- if (unlikely(vectors > BFI_TX_MAX_VECTORS_PER_PKT)) {
- dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, tx_skb_max_vectors);
- return NETDEV_TX_OK;
- }
- wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
- acked = 0;
- if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
- vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
- if ((u16) (*tcb->hw_consumer_index) !=
- tcb->consumer_index &&
- !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
- acked = bnad_txcmpl_process(bnad, tcb);
- if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
- bna_ib_ack(tcb->i_dbell, acked);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
- } else {
- netif_stop_queue(netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_stop);
- }
-
- smp_mb();
- /*
- * Check again to deal with race condition between
- * netif_stop_queue here, and netif_wake_queue in
- * interrupt handler which is not inside netif tx lock.
- */
- if (likely
- (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
- vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
- BNAD_UPDATE_CTR(bnad, netif_queue_stop);
- return NETDEV_TX_BUSY;
- } else {
- netif_wake_queue(netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
- }
- }
-
- unmap_prod = unmap_q->producer_index;
- flags = 0;
-
- txq_prod = tcb->producer_index;
- BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
- txqent->hdr.wi.reserved = 0;
- txqent->hdr.wi.num_vectors = vectors;
+ u16 flags = 0;
+ u32 gso_size;
+ u16 vlan_tag = 0;
if (vlan_tx_tag_present(skb)) {
- vlan_tag = (u16) vlan_tx_tag_get(skb);
+ vlan_tag = (u16)vlan_tx_tag_get(skb);
flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
}
if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
- vlan_tag =
- (tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
+ vlan_tag = ((tcb->priority & 0x7) << VLAN_PRIO_SHIFT)
+ | (vlan_tag & 0x1fff);
flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
}
-
txqent->hdr.wi.vlan_tag = htons(vlan_tag);
if (skb_is_gso(skb)) {
gso_size = skb_shinfo(skb)->gso_size;
-
- if (unlikely(gso_size > netdev->mtu)) {
- dev_kfree_skb(skb);
+ if (unlikely(gso_size > bnad->netdev->mtu)) {
BNAD_UPDATE_CTR(bnad, tx_skb_mss_too_long);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
if (unlikely((gso_size + skb_transport_offset(skb) +
- tcp_hdrlen(skb)) >= skb->len)) {
+ tcp_hdrlen(skb)) >= skb->len)) {
txqent->hdr.wi.opcode =
__constant_htons(BNA_TXQ_WI_SEND);
txqent->hdr.wi.lso_mss = 0;
@@ -2652,25 +2672,22 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
txqent->hdr.wi.lso_mss = htons(gso_size);
}
- err = bnad_tso_prepare(bnad, skb);
- if (unlikely(err)) {
- dev_kfree_skb(skb);
+ if (bnad_tso_prepare(bnad, skb)) {
BNAD_UPDATE_CTR(bnad, tx_skb_tso_prepare);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
+
flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
txqent->hdr.wi.l4_hdr_size_n_offset =
- htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
- (tcp_hdrlen(skb) >> 2,
- skb_transport_offset(skb)));
- } else {
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET(
+ tcp_hdrlen(skb) >> 2, skb_transport_offset(skb)));
+ } else {
txqent->hdr.wi.opcode = __constant_htons(BNA_TXQ_WI_SEND);
txqent->hdr.wi.lso_mss = 0;
- if (unlikely(skb->len > (netdev->mtu + ETH_HLEN))) {
- dev_kfree_skb(skb);
+ if (unlikely(skb->len > (bnad->netdev->mtu + ETH_HLEN))) {
BNAD_UPDATE_CTR(bnad, tx_skb_non_tso_too_long);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -2678,11 +2695,13 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if (skb->protocol == __constant_htons(ETH_P_IP))
proto = ip_hdr(skb)->protocol;
+#ifdef NETIF_F_IPV6_CSUM
else if (skb->protocol ==
__constant_htons(ETH_P_IPV6)) {
/* nexthdr may not be TCP immediately. */
proto = ipv6_hdr(skb)->nexthdr;
}
+#endif
if (proto == IPPROTO_TCP) {
flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
txqent->hdr.wi.l4_hdr_size_n_offset =
@@ -2692,12 +2711,11 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
if (unlikely(skb_headlen(skb) <
- skb_transport_offset(skb) + tcp_hdrlen(skb))) {
- dev_kfree_skb(skb);
+ skb_transport_offset(skb) +
+ tcp_hdrlen(skb))) {
BNAD_UPDATE_CTR(bnad, tx_skb_tcp_hdr);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
-
} else if (proto == IPPROTO_UDP) {
flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
txqent->hdr.wi.l4_hdr_size_n_offset =
@@ -2706,51 +2724,149 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
BNAD_UPDATE_CTR(bnad, udpcsum_offload);
if (unlikely(skb_headlen(skb) <
- skb_transport_offset(skb) +
+ skb_transport_offset(skb) +
sizeof(struct udphdr))) {
- dev_kfree_skb(skb);
BNAD_UPDATE_CTR(bnad, tx_skb_udp_hdr);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
} else {
- dev_kfree_skb(skb);
+
BNAD_UPDATE_CTR(bnad, tx_skb_csum_err);
- return NETDEV_TX_OK;
+ return -EINVAL;
}
- } else {
+ } else
txqent->hdr.wi.l4_hdr_size_n_offset = 0;
- }
}
txqent->hdr.wi.flags = htons(flags);
-
txqent->hdr.wi.frame_length = htonl(skb->len);
- unmap_q->unmap_array[unmap_prod].skb = skb;
+ return 0;
+}
+
+/*
+ * bnad_start_xmit : Netdev entry point for Transmit
+ * Called under lock held by net_device
+ */
+static netdev_tx_t
+bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ u32 txq_id = 0;
+ struct bna_tcb *tcb = NULL;
+ struct bnad_tx_unmap *unmap_q, *unmap, *head_unmap;
+ u32 prod, q_depth, vect_id;
+ u32 wis, vectors, len;
+ int i;
+ dma_addr_t dma_addr;
+ struct bna_txq_entry *txqent;
+
len = skb_headlen(skb);
- txqent->vector[0].length = htons(len);
- dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
- dma_addr);
- BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr);
- BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ /* Sanity checks for the skb */
- vect_id = 0;
- wis_used = 1;
+ if (unlikely(skb->len <= ETH_HLEN)) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_too_short);
+ return NETDEV_TX_OK;
+ }
+ if (unlikely(len > BFI_TX_MAX_DATA_PER_VECTOR)) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero);
+ return NETDEV_TX_OK;
+ }
+ if (unlikely(len == 0)) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero);
+ return NETDEV_TX_OK;
+ }
+
+ tcb = bnad->tx_info[0].tcb[txq_id];
+ q_depth = tcb->q_depth;
+ prod = tcb->producer_index;
+
+ unmap_q = tcb->unmap_q;
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ /*
+ * Takes care of the Tx that is scheduled between clearing the flag
+ * and the netif_tx_stop_all_queues() call.
+ */
+ if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_stopping);
+ return NETDEV_TX_OK;
+ }
+
+ vectors = 1 + skb_shinfo(skb)->nr_frags;
+ wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
+
+ if (unlikely(vectors > BFI_TX_MAX_VECTORS_PER_PKT)) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_max_vectors);
+ return NETDEV_TX_OK;
+ }
+
+ /* Check for available TxQ resources */
+ if (unlikely(wis > BNA_QE_FREE_CNT(tcb, q_depth))) {
+ if ((*tcb->hw_consumer_index != tcb->consumer_index) &&
+ !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
+ u32 sent;
+ sent = bnad_txcmpl_process(bnad, tcb);
+ if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+ bna_ib_ack(tcb->i_dbell, sent);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ } else {
+ netif_stop_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ }
+
+ smp_mb();
+ /*
+ * Check again to deal with race condition between
+ * netif_stop_queue here, and netif_wake_queue in
+ * interrupt handler which is not inside netif tx lock.
+ */
+ if (likely(wis > BNA_QE_FREE_CNT(tcb, q_depth))) {
+ BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ return NETDEV_TX_BUSY;
+ } else {
+ netif_wake_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+ }
+
+ txqent = &((struct bna_txq_entry *)tcb->sw_q)[prod];
+ head_unmap = &unmap_q[prod];
+
+ /* Program the opcode, flags, frame_len, num_vectors in WI */
+ if (bnad_txq_wi_prepare(bnad, tcb, skb, txqent)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ txqent->hdr.wi.reserved = 0;
+ txqent->hdr.wi.num_vectors = vectors;
+
+ head_unmap->skb = skb;
+ head_unmap->nvecs = 0;
+
+ /* Program the vectors */
+ unmap = head_unmap;
+ dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
+ len, DMA_TO_DEVICE);
+ BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr);
+ txqent->vector[0].length = htons(len);
+ dma_unmap_addr_set(&unmap->vectors[0], dma_addr, dma_addr);
+ head_unmap->nvecs++;
+
+ for (i = 0, vect_id = 0; i < vectors - 1; i++) {
const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
u16 size = skb_frag_size(frag);
if (unlikely(size == 0)) {
- unmap_prod = unmap_q->producer_index;
-
- unmap_prod = bnad_pci_unmap_skb(&bnad->pcidev->dev,
- unmap_q->unmap_array,
- unmap_prod, unmap_q->q_depth, skb,
- i);
+ /* Undo the changes starting at tcb->producer_index */
+ bnad_tx_buff_unmap(bnad, unmap_q, q_depth,
+ tcb->producer_index);
dev_kfree_skb(skb);
BNAD_UPDATE_CTR(bnad, tx_skb_frag_zero);
return NETDEV_TX_OK;
@@ -2758,47 +2874,35 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
len += size;
- if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
+ vect_id++;
+ if (vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
vect_id = 0;
- if (--wi_range)
- txqent++;
- else {
- BNA_QE_INDX_ADD(txq_prod, wis_used,
- tcb->q_depth);
- wis_used = 0;
- BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
- txqent, wi_range);
- }
- wis_used++;
+ BNA_QE_INDX_INC(prod, q_depth);
+ txqent = &((struct bna_txq_entry *)tcb->sw_q)[prod];
txqent->hdr.wi_ext.opcode =
__constant_htons(BNA_TXQ_WI_EXTENSION);
+ unmap = &unmap_q[prod];
}
- BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
- txqent->vector[vect_id].length = htons(size);
dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag,
0, size, DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
- dma_addr);
BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
- BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ txqent->vector[vect_id].length = htons(size);
+ dma_unmap_addr_set(&unmap->vectors[vect_id], dma_addr,
+ dma_addr);
+ head_unmap->nvecs++;
}
if (unlikely(len != skb->len)) {
- unmap_prod = unmap_q->producer_index;
-
- unmap_prod = bnad_pci_unmap_skb(&bnad->pcidev->dev,
- unmap_q->unmap_array, unmap_prod,
- unmap_q->q_depth, skb,
- skb_shinfo(skb)->nr_frags);
+ /* Undo the changes starting at tcb->producer_index */
+ bnad_tx_buff_unmap(bnad, unmap_q, q_depth, tcb->producer_index);
dev_kfree_skb(skb);
BNAD_UPDATE_CTR(bnad, tx_skb_len_mismatch);
return NETDEV_TX_OK;
}
- unmap_q->producer_index = unmap_prod;
- BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth);
- tcb->producer_index = txq_prod;
+ BNA_QE_INDX_INC(prod, q_depth);
+ tcb->producer_index = prod;
smp_mb();
@@ -3226,7 +3330,7 @@ bnad_pci_uninit(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static int __devinit
+static int
bnad_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pcidev_id)
{
@@ -3320,7 +3424,6 @@ bnad_pci_probe(struct pci_dev *pdev,
if (err)
goto res_free;
-
/* Set up timers */
setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout,
((unsigned long)bnad));
@@ -3426,7 +3529,7 @@ unlock_mutex:
return err;
}
-static void __devexit
+static void
bnad_pci_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3490,7 +3593,7 @@ static struct pci_driver bnad_pci_driver = {
.name = BNAD_NAME,
.id_table = bnad_pci_id_table,
.probe = bnad_pci_probe,
- .remove = __devexit_p(bnad_pci_remove),
+ .remove = bnad_pci_remove,
};
static int __init
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index d78339224751..c1d0bc059bfd 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -71,7 +71,7 @@ struct bnad_rx_ctrl {
#define BNAD_NAME "bna"
#define BNAD_NAME_LEN 64
-#define BNAD_VERSION "3.0.23.0"
+#define BNAD_VERSION "3.1.2.1"
#define BNAD_MAILBOX_MSIX_INDEX 0
#define BNAD_MAILBOX_MSIX_VECTORS 1
@@ -83,12 +83,9 @@ struct bnad_rx_ctrl {
#define BNAD_IOCETH_TIMEOUT 10000
-#define BNAD_MAX_Q_DEPTH 0x10000
-#define BNAD_MIN_Q_DEPTH 0x200
-
-#define BNAD_MAX_RXQ_DEPTH (BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq)
-/* keeping MAX TX and RX Q depth equal */
-#define BNAD_MAX_TXQ_DEPTH BNAD_MAX_RXQ_DEPTH
+#define BNAD_MIN_Q_DEPTH 512
+#define BNAD_MAX_RXQ_DEPTH 2048
+#define BNAD_MAX_TXQ_DEPTH 2048
#define BNAD_JUMBO_MTU 9000
@@ -101,9 +98,8 @@ struct bnad_rx_ctrl {
#define BNAD_TXQ_TX_STARTED 1
/* Bit positions for rcb->flags */
-#define BNAD_RXQ_REFILL 0
-#define BNAD_RXQ_STARTED 1
-#define BNAD_RXQ_POST_OK 2
+#define BNAD_RXQ_STARTED 0
+#define BNAD_RXQ_POST_OK 1
/* Resource limits */
#define BNAD_NUM_TXQ (bnad->num_tx * bnad->num_txq_per_tx)
@@ -221,18 +217,43 @@ struct bnad_rx_info {
struct work_struct rx_cleanup_work;
} ____cacheline_aligned;
-/* Unmap queues for Tx / Rx cleanup */
-struct bnad_skb_unmap {
+struct bnad_tx_vector {
+ DEFINE_DMA_UNMAP_ADDR(dma_addr);
+};
+
+struct bnad_tx_unmap {
struct sk_buff *skb;
+ u32 nvecs;
+ struct bnad_tx_vector vectors[BFI_TX_MAX_VECTORS_PER_WI];
+};
+
+struct bnad_rx_vector {
DEFINE_DMA_UNMAP_ADDR(dma_addr);
+ u32 len;
+};
+
+struct bnad_rx_unmap {
+ struct page *page;
+ u32 page_offset;
+ struct sk_buff *skb;
+ struct bnad_rx_vector vector;
};
-struct bnad_unmap_q {
- u32 producer_index;
- u32 consumer_index;
- u32 q_depth;
- /* This should be the last one */
- struct bnad_skb_unmap unmap_array[1];
+enum bnad_rxbuf_type {
+ BNAD_RXBUF_NONE = 0,
+ BNAD_RXBUF_SKB = 1,
+ BNAD_RXBUF_PAGE = 2,
+ BNAD_RXBUF_MULTI = 3
+};
+
+#define BNAD_RXBUF_IS_PAGE(_type) ((_type) == BNAD_RXBUF_PAGE)
+
+struct bnad_rx_unmap_q {
+ int reuse_pi;
+ int alloc_order;
+ u32 map_size;
+ enum bnad_rxbuf_type type;
+ struct bnad_rx_unmap unmap[0];
};
/* Bit mask values for bnad->cfg_flags */
@@ -252,11 +273,6 @@ struct bnad_unmap_q {
#define BNAD_RF_STATS_TIMER_RUNNING 5
#define BNAD_RF_TX_PRIO_SET 6
-
-/* Define for Fast Path flags */
-/* Defined as bit positions */
-#define BNAD_FP_IN_RX_PATH 0
-
struct bnad {
struct net_device *netdev;
u32 id;
@@ -284,8 +300,8 @@ struct bnad {
u8 tx_coalescing_timeo;
u8 rx_coalescing_timeo;
- struct bna_rx_config rx_config[BNAD_MAX_RX];
- struct bna_tx_config tx_config[BNAD_MAX_TX];
+ struct bna_rx_config rx_config[BNAD_MAX_RX] ____cacheline_aligned;
+ struct bna_tx_config tx_config[BNAD_MAX_TX] ____cacheline_aligned;
void __iomem *bar0; /* BAR0 address */
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 40e1e84f4984..455b5a2e59d4 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -102,6 +102,7 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"rx_unmap_q_alloc_failed",
"rxbuf_alloc_failed",
+ "mac_stats_clr_cnt",
"mac_frame_64",
"mac_frame_65_127",
"mac_frame_128_255",
diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h
index 32e8f178ab76..14ca9317c915 100644
--- a/drivers/net/ethernet/brocade/bna/cna.h
+++ b/drivers/net/ethernet/brocade/bna/cna.h
@@ -37,8 +37,8 @@
extern char bfa_version[];
-#define CNA_FW_FILE_CT "ctfw.bin"
-#define CNA_FW_FILE_CT2 "ct2fw.bin"
+#define CNA_FW_FILE_CT "ctfw-3.1.0.0.bin"
+#define CNA_FW_FILE_CT2 "ct2fw-3.1.0.0.bin"
#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */
#pragma pack(1)
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index db931916da08..ceb0de0cf62c 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -2,13 +2,10 @@
# Atmel device configuration
#
-config HAVE_NET_MACB
- bool
-
config NET_CADENCE
bool "Cadence devices"
+ depends on HAS_IOMEM
default y
- depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
Make sure you know the name of your card. Read the Ethernet-HOWTO,
@@ -25,16 +22,14 @@ if NET_CADENCE
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
- depends on ARM && ARCH_AT91RM9200
select NET_CORE
- select MII
+ select MACB
---help---
If you wish to compile a kernel for the AT91RM9200 and enable
ethernet support, then you should always answer Y to this.
config MACB
tristate "Cadence MACB/GEM support"
- depends on HAVE_NET_MACB
select PHYLIB
---help---
The Cadence MACB ethernet interface is found on many Atmel AT32 and
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 35fc6edbacf8..3becdb2deb46 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -6,11 +6,6 @@
* Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
* Initial version by Rick Bronson 01/11/2003
*
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- * (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.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
@@ -20,7 +15,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -31,956 +25,248 @@
#include <linux/clk.h>
#include <linux/gfp.h>
#include <linux/phy.h>
-#include <linux/platform_data/atmel.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <asm/gpio.h>
-
-#include "at91_ether.h"
-
-#define DRV_NAME "at91_ether"
-#define DRV_VERSION "1.0"
-
-#define LINK_POLL_INTERVAL (HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
-{
- return __raw_readl(lp->emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
-{
- __raw_writel(value, lp->emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- * protected by a spinlock.
- */
-static void enable_mdi(struct at91_private *lp)
-{
- unsigned long ctl;
-
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(struct at91_private *lp)
-{
- unsigned long ctl;
-
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(struct at91_private *lp)
-{
- unsigned long timeout = jiffies + 2;
-
- while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
- if (time_after(jiffies, timeout)) {
- printk("at91_ether: MIO timeout\n");
- break;
- }
- cpu_relax();
- }
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
-{
- at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
- | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
- /* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait(lp);
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
- at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
- | ((phy_addr & 0x1f) << 23) | (address << 18));
-
- /* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait(lp);
-
- *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int bmsr, bmcr, lpa, mac_cfg;
- unsigned int speed, duplex;
-
- if (!mii_link_ok(&lp->mii)) { /* no link */
- netif_carrier_off(dev);
- if (!silent)
- printk(KERN_INFO "%s: Link down.\n", dev->name);
- return;
- }
-
- /* Link up, or auto-negotiation still in progress */
- read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
- read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
- if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
- if (!(bmsr & BMSR_ANEGCOMPLETE))
- return; /* Do nothing - another interrupt generated when negotiation complete */
-
- read_phy(lp, lp->phy_address, MII_LPA, &lpa);
- if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
- else speed = SPEED_10;
- if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
- else duplex = DUPLEX_HALF;
- } else {
- speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
- duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
- }
-
- /* Update the MAC */
- mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
- if (speed == SPEED_100) {
- if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
- mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
- else /* 100 Half Duplex */
- mac_cfg |= AT91_EMAC_SPD;
- } else {
- if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
- mac_cfg |= AT91_EMAC_FD;
- else {} /* 10 Half Duplex */
- }
- at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
-
- if (!silent)
- printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
- netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
- unsigned int phy;
-
- /*
- * This hander is triggered on both edges, but the PHY chips expect
- * level-triggering. We therefore have to check if the PHY actually has
- * an IRQ pending.
- */
- enable_mdi(lp);
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_LXT971A_ID) {
- read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
- if (!(phy & (1 << 2)))
- goto done;
- }
- else if (lp->phy_type == MII_BCM5221_ID) {
- read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_KS8721_ID) {
- read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
- read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
- else if (lp->phy_type == MII_DP83848_ID) {
- read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
- if (!(phy & (1 << 7)))
- goto done;
- }
-
- update_linkspeed(dev, 0);
-
-done:
- disable_mdi(lp);
-
- return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int dsintr, irq_number;
- int status;
-
- if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
- /*
- * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
- * or board does not have it connected.
- */
- mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
- return;
- }
-
- irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
- status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
- if (status) {
- printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
- return;
- }
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
- write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
- write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- dsintr = (1 << 15) | ( 1 << 14);
- write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- dsintr = (1 << 10) | ( 1 << 8);
- write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr | 0x500; /* set bits 8, 10 */
- write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr | 0x3c; /* set bits 2..5 */
- write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
- read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr | 0x3; /* set bits 0,1 */
- write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
- }
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int dsintr;
- unsigned int irq_number;
-
- if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
- del_timer_sync(&lp->check_timer);
- return;
- }
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr | 0xf00; /* set bits 8..11 */
- write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
- write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
- dsintr = ~(1 << 14);
- write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
- dsintr = ~((1 << 10) | (1 << 8));
- write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr & ~0x500; /* clear bits 8, 10 */
- write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr & ~0x3; /* clear bits 0, 1 */
- write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
- read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr & ~0x3c; /* clear bits 2..5 */
- write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
- }
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
- free_irq(irq_number, dev); /* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int bmcr;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- /* Perform PHY reset */
- write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
-
- /* Wait until PHY reset is complete */
- do {
- read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
- } while (!(bmcr & BMCR_RESET));
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
-
- enable_mdi(lp);
- update_linkspeed(dev, 1);
- disable_mdi(lp);
-
- mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/*
- * Perform any PHY-specific initialization.
- */
-static void __init initialize_phy(struct at91_private *lp)
-{
- unsigned int val;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
- if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
- lp->phy_media = PORT_FIBRE;
- } else if (machine_is_csb337()) {
- /* mix link activity status into LED2 link state */
- write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
- } else if (machine_is_ecbat91())
- write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-}
-
-/* ......................... ADDRESS MANAGEMENT ........................ */
-
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- * happen to access the Ethernet while it's booting. Some versions of
- * U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- * MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- * continues to do so, for bug-compatibility).
- */
-
-static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
-{
- char addr[6];
-
- if (machine_is_csb337()) {
- addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */
- addr[4] = (lo & 0xff00) >> 8;
- addr[3] = (lo & 0xff0000) >> 16;
- addr[2] = (lo & 0xff000000) >> 24;
- addr[1] = (hi & 0xff);
- addr[0] = (hi & 0xff00) >> 8;
- }
- else {
- addr[0] = (lo & 0xff);
- addr[1] = (lo & 0xff00) >> 8;
- addr[2] = (lo & 0xff0000) >> 16;
- addr[3] = (lo & 0xff000000) >> 24;
- addr[4] = (hi & 0xff);
- addr[5] = (hi & 0xff00) >> 8;
- }
-
- if (is_valid_ether_addr(addr)) {
- memcpy(dev->dev_addr, &addr, 6);
- return 1;
- }
- return 0;
-}
-
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void __init get_mac_address(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
-
- /* Check Specific-Address 1 */
- if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
- return;
- /* Check Specific-Address 2 */
- if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
- return;
- /* Check Specific-Address 3 */
- if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
- return;
- /* Check Specific-Address 4 */
- if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
- return;
-
- printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
-
- at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
- at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-
- at91_emac_write(lp, AT91_EMAC_SA2L, 0);
- at91_emac_write(lp, AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int set_mac_address(struct net_device *dev, void* addr)
-{
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
- update_mac_address(dev);
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
- printk("%s: Setting MAC address to %pM\n", dev->name,
- dev->dev_addr);
+#include "macb.h"
- return 0;
-}
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
- if (addr[bitnr / 8] & (1 << (bitnr % 8)))
- return 1;
- return 0;
-}
+/* 1518 rounded up */
+#define MAX_RBUFF_SZ 0x600
+/* max number of receive buffers */
+#define MAX_RX_DESCR 9
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- * register enable the reception of hash matched frames. The destination address is
- * reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- * unicast indicator, and da[47] represents the most significant bit of the last byte
- * received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- * matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- * the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- * hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- * multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
- int i, j, bitval;
- int hash_index = 0;
-
- for (j = 0; j < 6; j++) {
- for (i = 0, bitval = 0; i < 8; i++)
- bitval ^= hash_bit_value(i*6 + j, addr);
-
- hash_index |= (bitval << j);
- }
-
- return hash_index;
-}
-
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-static void at91ether_sethashtable(struct net_device *dev)
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
- struct netdev_hw_addr *ha;
- unsigned long mc_filter[2];
- unsigned int bitnr;
-
- mc_filter[0] = mc_filter[1] = 0;
-
- netdev_for_each_mc_addr(ha, dev) {
- bitnr = hash_get_index(ha->addr);
- mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
- }
-
- at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
- at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
-}
+ struct macb *lp = netdev_priv(dev);
+ dma_addr_t addr;
+ u32 ctl;
+ int i;
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned long cfg;
-
- cfg = at91_emac_read(lp, AT91_EMAC_CFG);
-
- if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
- cfg |= AT91_EMAC_CAF;
- else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */
- cfg &= ~AT91_EMAC_CAF;
-
- if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
- at91_emac_write(lp, AT91_EMAC_HSH, -1);
- at91_emac_write(lp, AT91_EMAC_HSL, -1);
- cfg |= AT91_EMAC_MTI;
- } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
- at91ether_sethashtable(dev);
- cfg |= AT91_EMAC_MTI;
- } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
- at91_emac_write(lp, AT91_EMAC_HSH, 0);
- at91_emac_write(lp, AT91_EMAC_HSL, 0);
- cfg &= ~AT91_EMAC_MTI;
+ lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
+ MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+ &lp->rx_ring_dma, GFP_KERNEL);
+ if (!lp->rx_ring) {
+ netdev_err(dev, "unable to alloc rx ring DMA buffer\n");
+ return -ENOMEM;
}
- at91_emac_write(lp, AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int value;
-
- read_phy(lp, phy_id, location, &value);
- return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
- struct at91_private *lp = netdev_priv(dev);
-
- write_phy(lp, phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
+ lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
+ MAX_RX_DESCR * MAX_RBUFF_SZ,
+ &lp->rx_buffers_dma, GFP_KERNEL);
+ if (!lp->rx_buffers) {
+ netdev_err(dev, "unable to alloc rx data DMA buffer\n");
- ret = mii_ethtool_gset(&lp->mii, cmd);
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
- cmd->supported = SUPPORTED_FIBRE;
- cmd->port = PORT_FIBRE;
+ dma_free_coherent(&lp->pdev->dev,
+ MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+ lp->rx_ring, lp->rx_ring_dma);
+ lp->rx_ring = NULL;
+ return -ENOMEM;
}
- return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- ret = mii_ethtool_sset(&lp->mii, cmd);
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
-
- ret = mii_nway_restart(&lp->mii);
-
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
- strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
- .get_settings = at91ether_get_settings,
- .set_settings = at91ether_set_settings,
- .get_drvinfo = at91ether_get_drvinfo,
- .nway_reset = at91ether_nwayreset,
- .get_link = ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int res;
-
- if (!netif_running(dev))
- return -EINVAL;
-
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
- res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- struct recv_desc_bufs *dlist, *dlist_phys;
- int i;
- unsigned long ctl;
-
- dlist = lp->dlist;
- dlist_phys = lp->dlist_phys;
-
+ addr = lp->rx_buffers_dma;
for (i = 0; i < MAX_RX_DESCR; i++) {
- dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
- dlist->descriptors[i].size = 0;
+ lp->rx_ring[i].addr = addr;
+ lp->rx_ring[i].ctrl = 0;
+ addr += MAX_RBUFF_SZ;
}
/* Set the Wrap bit on the last descriptor */
- dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+ lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
/* Reset buffer index */
- lp->rxBuffIndex = 0;
+ lp->rx_tail = 0;
/* Program address of descriptor list in Rx Buffer Queue register */
- at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+ macb_writel(lp, RBQP, lp->rx_ring_dma);
/* Enable Receive and Transmit */
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+ ctl = macb_readl(lp, NCR);
+ macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+
+ return 0;
}
-/*
- * Open the ethernet interface
- */
+/* Open the ethernet interface */
static int at91ether_open(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
- unsigned long ctl;
-
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EADDRNOTAVAIL;
-
- clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */
+ struct macb *lp = netdev_priv(dev);
+ u32 ctl;
+ int ret;
/* Clear internal statistics */
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+ ctl = macb_readl(lp, NCR);
+ macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
- /* Update the MAC address (incase user has changed it) */
- update_mac_address(dev);
+ macb_set_hwaddr(lp);
- /* Enable PHY interrupt */
- enable_phyirq(dev);
+ ret = at91ether_start(dev);
+ if (ret)
+ return ret;
/* Enable MAC interrupts */
- at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
- update_linkspeed(dev, 0);
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- at91ether_start(dev);
+ macb_writel(lp, IER, MACB_BIT(RCOMP) |
+ MACB_BIT(RXUBR) |
+ MACB_BIT(ISR_TUND) |
+ MACB_BIT(ISR_RLE) |
+ MACB_BIT(TCOMP) |
+ MACB_BIT(ISR_ROVR) |
+ MACB_BIT(HRESP));
+
+ /* schedule a link state check */
+ phy_start(lp->phy_dev);
+
netif_start_queue(dev);
+
return 0;
}
-/*
- * Close the interface
- */
+/* Close the interface */
static int at91ether_close(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
- unsigned long ctl;
+ struct macb *lp = netdev_priv(dev);
+ u32 ctl;
/* Disable Receiver and Transmitter */
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
- /* Disable PHY interrupt */
- disable_phyirq(dev);
+ ctl = macb_readl(lp, NCR);
+ macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
/* Disable MAC interrupts */
- at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
+ macb_writel(lp, IDR, MACB_BIT(RCOMP) |
+ MACB_BIT(RXUBR) |
+ MACB_BIT(ISR_TUND) |
+ MACB_BIT(ISR_RLE) |
+ MACB_BIT(TCOMP) |
+ MACB_BIT(ISR_ROVR) |
+ MACB_BIT(HRESP));
netif_stop_queue(dev);
- clk_disable(lp->ether_clk); /* Disable Peripheral clock */
+ dma_free_coherent(&lp->pdev->dev,
+ MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+ lp->rx_ring, lp->rx_ring_dma);
+ lp->rx_ring = NULL;
+
+ dma_free_coherent(&lp->pdev->dev,
+ MAX_RX_DESCR * MAX_RBUFF_SZ,
+ lp->rx_buffers, lp->rx_buffers_dma);
+ lp->rx_buffers = NULL;
return 0;
}
-/*
- * Transmit packet.
- */
+/* Transmit packet */
static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
+ struct macb *lp = netdev_priv(dev);
- if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+ if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
netif_stop_queue(dev);
/* Store packet information (to free when Tx completed) */
lp->skb = skb;
lp->skb_length = skb->len;
- lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- dev->stats.tx_bytes += skb->len;
+ lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
+ DMA_TO_DEVICE);
/* Set address of the data in the Transmit Address register */
- at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
+ macb_writel(lp, TAR, lp->skb_physaddr);
/* Set length of the packet in the Transmit Control register */
- at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
+ macb_writel(lp, TCR, skb->len);
} else {
- printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
- return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
- on this skb, he also reports -ENETDOWN and printk's, so either
- we free and return(0) or don't free and return 1 */
+ netdev_err(dev, "%s called, but device is busy!\n", __func__);
+ return NETDEV_TX_BUSY;
}
return NETDEV_TX_OK;
}
-/*
- * Update the current statistics from the internal statistics registers.
- */
-static struct net_device_stats *at91ether_stats(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ale, lenerr, seqe, lcol, ecol;
-
- if (netif_running(dev)) {
- dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK); /* Good frames received */
- ale = at91_emac_read(lp, AT91_EMAC_ALE);
- dev->stats.rx_frame_errors += ale; /* Alignment errors */
- lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
- dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
- seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
- dev->stats.rx_crc_errors += seqe; /* CRC error */
- dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
- dev->stats.rx_errors += (ale + lenerr + seqe
- + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
-
- dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA); /* Frames successfully transmitted */
- dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */
- dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE); /* Carrier Sense errors */
- dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
-
- lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
- ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
- dev->stats.tx_window_errors += lcol; /* Late collisions */
- dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
-
- dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
- }
- return &dev->stats;
-}
-
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
+/* Extract received frame from buffer descriptors and sent to upper layers.
* (Called from interrupt context)
*/
static void at91ether_rx(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
- struct recv_desc_bufs *dlist;
+ struct macb *lp = netdev_priv(dev);
unsigned char *p_recv;
struct sk_buff *skb;
unsigned int pktlen;
- dlist = lp->dlist;
- while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
- p_recv = dlist->recv_buf[lp->rxBuffIndex];
- pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
+ while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+ p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ;
+ pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
skb = netdev_alloc_skb(dev, pktlen + 2);
- if (skb != NULL) {
+ if (skb) {
skb_reserve(skb, 2);
memcpy(skb_put(skb, pktlen), p_recv, pktlen);
skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_bytes += pktlen;
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pktlen;
netif_rx(skb);
+ } else {
+ lp->stats.rx_dropped++;
+ netdev_notice(dev, "Memory squeeze, dropping packet.\n");
}
- else {
- dev->stats.rx_dropped += 1;
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- }
- if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
- dev->stats.multicast++;
+ if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+ lp->stats.multicast++;
+
+ /* reset ownership bit */
+ lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
- dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
- if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
- lp->rxBuffIndex = 0;
+ /* wrap after last buffer */
+ if (lp->rx_tail == MAX_RX_DESCR - 1)
+ lp->rx_tail = 0;
else
- lp->rxBuffIndex++;
+ lp->rx_tail++;
}
}
-/*
- * MAC interrupt handler
- */
+/* MAC interrupt handler */
static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
- unsigned long intstatus, ctl;
+ struct net_device *dev = dev_id;
+ struct macb *lp = netdev_priv(dev);
+ u32 intstatus, ctl;
/* MAC Interrupt Status register indicates what interrupts are pending.
- It is automatically cleared once read. */
- intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
+ * It is automatically cleared once read.
+ */
+ intstatus = macb_readl(lp, ISR);
- if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
+ /* Receive complete */
+ if (intstatus & MACB_BIT(RCOMP))
at91ether_rx(dev);
- if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
- /* The TCOM bit is set even if the transmission failed. */
- if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
- dev->stats.tx_errors += 1;
+ /* Transmit complete */
+ if (intstatus & MACB_BIT(TCOMP)) {
+ /* The TCOM bit is set even if the transmission failed */
+ if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
+ lp->stats.tx_errors++;
if (lp->skb) {
dev_kfree_skb_irq(lp->skb);
lp->skb = NULL;
dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += lp->skb_length;
}
netif_wake_queue(dev);
}
- /* Work-around for Errata #11 */
- if (intstatus & AT91_EMAC_RBNA) {
- ctl = at91_emac_read(lp, AT91_EMAC_CTL);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
- at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+ /* Work-around for EMAC Errata section 41.3.1 */
+ if (intstatus & MACB_BIT(RXUBR)) {
+ ctl = macb_readl(lp, NCR);
+ macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+ macb_writel(lp, NCR, ctl | MACB_BIT(RE));
}
- if (intstatus & AT91_EMAC_ROVR)
- printk("%s: ROVR error\n", dev->name);
+ if (intstatus & MACB_BIT(ISR_ROVR))
+ netdev_err(dev, "ROVR error\n");
return IRQ_HANDLED;
}
@@ -1000,10 +286,10 @@ static const struct net_device_ops at91ether_netdev_ops = {
.ndo_open = at91ether_open,
.ndo_stop = at91ether_close,
.ndo_start_xmit = at91ether_start_xmit,
- .ndo_get_stats = at91ether_stats,
- .ndo_set_rx_mode = at91ether_set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
- .ndo_do_ioctl = at91ether_ioctl,
+ .ndo_get_stats = macb_get_stats,
+ .ndo_set_rx_mode = macb_set_rx_mode,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_do_ioctl = macb_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1011,237 +297,195 @@ static const struct net_device_ops at91ether_netdev_ops = {
#endif
};
-/*
- * Detect the PHY type, and its address.
- */
-static int __init at91ether_phy_detect(struct at91_private *lp)
+#if defined(CONFIG_OF)
+static const struct of_device_id at91ether_dt_ids[] = {
+ { .compatible = "cdns,at91rm9200-emac" },
+ { .compatible = "cdns,emac" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91ether_dt_ids);
+
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
{
- unsigned int phyid1, phyid2;
- unsigned long phy_id;
- unsigned short phy_address = 0;
-
- while (phy_address < PHY_MAX_ADDR) {
- /* Read the PHY ID registers */
- enable_mdi(lp);
- read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
- read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
- disable_mdi(lp);
-
- phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
- switch (phy_id) {
- case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
- case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
- case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
- case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
- case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
- case MII_DP83847_ID: /* National Semiconductor DP83847: */
- case MII_DP83848_ID: /* National Semiconductor DP83848: */
- case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
- case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
- case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
- case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
- /* store detected values */
- lp->phy_type = phy_id; /* Type of PHY connected */
- lp->phy_address = phy_address; /* MDI address of PHY */
- return 1;
- }
+ struct device_node *np = pdev->dev.of_node;
- phy_address++;
- }
+ if (np)
+ return of_get_phy_mode(np);
- return 0; /* not detected */
+ return -ENODEV;
}
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+ struct device_node *np = bp->pdev->dev.of_node;
-/*
- * Detect MAC & PHY and perform ethernet interface initialization
- */
+ if (np) {
+ const char *mac = of_get_mac_address(np);
+ if (mac) {
+ memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+#else
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
+{
+ return -ENODEV;
+}
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+ return -ENODEV;
+}
+#endif
+
+/* Detect MAC & PHY and perform ethernet interface initialization */
static int __init at91ether_probe(struct platform_device *pdev)
{
struct macb_platform_data *board_data = pdev->dev.platform_data;
struct resource *regs;
struct net_device *dev;
- struct at91_private *lp;
+ struct phy_device *phydev;
+ struct pinctrl *pinctrl;
+ struct macb *lp;
int res;
+ u32 reg;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs)
return -ENOENT;
- dev = alloc_etherdev(sizeof(struct at91_private));
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ res = PTR_ERR(pinctrl);
+ if (res == -EPROBE_DEFER)
+ return res;
+
+ dev_warn(&pdev->dev, "No pinctrl provided\n");
+ }
+
+ dev = alloc_etherdev(sizeof(struct macb));
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- lp->board_data = *board_data;
+ lp->pdev = pdev;
+ lp->dev = dev;
spin_lock_init(&lp->lock);
- dev->base_addr = regs->start; /* physical base address */
- lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
- if (!lp->emac_base) {
+ /* physical base address */
+ dev->base_addr = regs->start;
+ lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+ if (!lp->regs) {
res = -ENOMEM;
goto err_free_dev;
}
/* Clock */
- lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
- if (IS_ERR(lp->ether_clk)) {
- res = PTR_ERR(lp->ether_clk);
- goto err_ioumap;
+ lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+ if (IS_ERR(lp->pclk)) {
+ res = PTR_ERR(lp->pclk);
+ goto err_free_dev;
}
- clk_enable(lp->ether_clk);
+ clk_enable(lp->pclk);
/* Install the interrupt handler */
dev->irq = platform_get_irq(pdev, 0);
- if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
- res = -EBUSY;
+ res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
+ if (res)
goto err_disable_clock;
- }
-
- /* Allocate memory for DMA Receive descriptors */
- lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
- if (lp->dlist == NULL) {
- res = -ENOMEM;
- goto err_free_irq;
- }
ether_setup(dev);
dev->netdev_ops = &at91ether_netdev_ops;
- dev->ethtool_ops = &at91ether_ethtool_ops;
+ dev->ethtool_ops = &macb_ethtool_ops;
platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
- get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
- update_mac_address(dev); /* Program ethernet address into MAC */
-
- at91_emac_write(lp, AT91_EMAC_CTL, 0);
+ res = at91ether_get_hwaddr_dt(lp);
+ if (res < 0)
+ macb_get_hwaddr(lp);
- if (board_data->is_rmii)
- at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
- else
- at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
- /* Detect PHY */
- if (!at91ether_phy_detect(lp)) {
- printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
- res = -ENODEV;
- goto err_free_dmamem;
+ res = at91ether_get_phy_mode_dt(pdev);
+ if (res < 0) {
+ if (board_data && board_data->is_rmii)
+ lp->phy_interface = PHY_INTERFACE_MODE_RMII;
+ else
+ lp->phy_interface = PHY_INTERFACE_MODE_MII;
+ } else {
+ lp->phy_interface = res;
}
- initialize_phy(lp);
+ macb_writel(lp, NCR, 0);
+
+ reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
+ if (lp->phy_interface == PHY_INTERFACE_MODE_RMII)
+ reg |= MACB_BIT(RM9200_RMII);
- lp->mii.dev = dev; /* Support for ethtool */
- lp->mii.mdio_read = mdio_read;
- lp->mii.mdio_write = mdio_write;
- lp->mii.phy_id = lp->phy_address;
- lp->mii.phy_id_mask = 0x1f;
- lp->mii.reg_num_mask = 0x1f;
+ macb_writel(lp, NCFGR, reg);
/* Register the network interface */
res = register_netdev(dev);
if (res)
- goto err_free_dmamem;
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
- enable_mdi(lp);
- update_linkspeed(dev, 0);
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
- netif_carrier_off(dev); /* will be enabled in open() */
-
- /* If board has no PHY IRQ, use a timer to poll the PHY */
- if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
- gpio_request(board_data->phy_irq_pin, "ethernet_phy");
- } else {
- /* If board has no PHY IRQ, use a timer to poll the PHY */
- init_timer(&lp->check_timer);
- lp->check_timer.data = (unsigned long)dev;
- lp->check_timer.function = at91ether_check_link;
- }
+ goto err_disable_clock;
+
+ if (macb_mii_init(lp) != 0)
+ goto err_out_unregister_netdev;
+
+ /* will be enabled in open() */
+ netif_carrier_off(dev);
+
+ phydev = lp->phy_dev;
+ netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ phydev->drv->name, dev_name(&phydev->dev),
+ phydev->irq);
/* Display ethernet banner */
- printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
- dev->name, (uint) dev->base_addr, dev->irq,
- at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
- at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
- dev->dev_addr);
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
- printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
- else if (lp->phy_type == MII_LXT971A_ID)
- printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
- else if (lp->phy_type == MII_RTL8201_ID)
- printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
- else if (lp->phy_type == MII_BCM5221_ID)
- printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
- else if (lp->phy_type == MII_DP83847_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
- else if (lp->phy_type == MII_DP83848_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
- else if (lp->phy_type == MII_AC101L_ID)
- printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
- else if (lp->phy_type == MII_KS8721_ID)
- printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
- else if (lp->phy_type == MII_T78Q21x3_ID)
- printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
- else if (lp->phy_type == MII_LAN83C185_ID)
- printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
- clk_disable(lp->ether_clk); /* Disable Peripheral clock */
+ netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n",
+ dev->base_addr, dev->irq, dev->dev_addr);
return 0;
-
-err_free_dmamem:
- platform_set_drvdata(pdev, NULL);
- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-err_free_irq:
- free_irq(dev->irq, dev);
+err_out_unregister_netdev:
+ unregister_netdev(dev);
err_disable_clock:
- clk_disable(lp->ether_clk);
- clk_put(lp->ether_clk);
-err_ioumap:
- iounmap(lp->emac_base);
+ clk_disable(lp->pclk);
err_free_dev:
free_netdev(dev);
return res;
}
-static int __devexit at91ether_remove(struct platform_device *pdev)
+static int at91ether_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(dev);
+ struct macb *lp = netdev_priv(dev);
- if (gpio_is_valid(lp->board_data.phy_irq_pin))
- gpio_free(lp->board_data.phy_irq_pin);
+ if (lp->phy_dev)
+ phy_disconnect(lp->phy_dev);
+ mdiobus_unregister(lp->mii_bus);
+ kfree(lp->mii_bus->irq);
+ mdiobus_free(lp->mii_bus);
unregister_netdev(dev);
- free_irq(dev->irq, dev);
- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
- clk_put(lp->ether_clk);
-
- platform_set_drvdata(pdev, NULL);
+ clk_disable(lp->pclk);
free_netdev(dev);
+ platform_set_drvdata(pdev, NULL);
+
return 0;
}
#ifdef CONFIG_PM
-
static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
{
struct net_device *net_dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(net_dev);
+ struct macb *lp = netdev_priv(net_dev);
if (netif_running(net_dev)) {
- if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
- int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
- disable_irq(phy_irq);
- }
-
netif_stop_queue(net_dev);
netif_device_detach(net_dev);
- clk_disable(lp->ether_clk);
+ clk_disable(lp->pclk);
}
return 0;
}
@@ -1249,34 +493,29 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
static int at91ether_resume(struct platform_device *pdev)
{
struct net_device *net_dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(net_dev);
+ struct macb *lp = netdev_priv(net_dev);
if (netif_running(net_dev)) {
- clk_enable(lp->ether_clk);
+ clk_enable(lp->pclk);
netif_device_attach(net_dev);
netif_start_queue(net_dev);
-
- if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
- int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
- enable_irq(phy_irq);
- }
}
return 0;
}
-
#else
#define at91ether_suspend NULL
#define at91ether_resume NULL
#endif
static struct platform_driver at91ether_driver = {
- .remove = __devexit_p(at91ether_remove),
+ .remove = at91ether_remove,
.suspend = at91ether_suspend,
.resume = at91ether_resume,
.driver = {
- .name = DRV_NAME,
+ .name = "at91_ether",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91ether_dt_ids),
},
};
@@ -1296,4 +535,4 @@ module_exit(at91ether_exit)
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:at91_ether");
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
deleted file mode 100644
index 0ef6328fa7f8..000000000000
--- a/drivers/net/ethernet/cadence/at91_ether.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- * Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * 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 AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID 0x0181b880
-#define MII_DM9161A_ID 0x0181b8a0
-#define MII_DSCR_REG 16
-#define MII_DSCSR_REG 17
-#define MII_DSINTR_REG 21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID 0x001378E0
-#define MII_ISINTE_REG 18
-#define MII_ISINTS_REG 19
-#define MII_LEDCTRL_REG 20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID 0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID 0x004061e0
-#define MII_BCMINTR_REG 26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID 0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID 0x20005c90
-#define MII_DPPHYSTS_REG 16
-#define MII_DPMICR_REG 17
-#define MII_DPMISR_REG 18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID 0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID 0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID 0x000e7230
-#define MII_T78Q21INT_REG 17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID 0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
-#define MAX_RX_DESCR 9 /* max number of receive buffers */
-
-#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
-#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
-
-#define EMAC_BROADCAST 0x80000000 /* broadcast address */
-#define EMAC_MULTICAST 0x40000000 /* multicast address */
-#define EMAC_UNICAST 0x20000000 /* unicast address */
-
-struct rbf_t
-{
- unsigned int addr;
- unsigned long size;
-};
-
-struct recv_desc_bufs
-{
- struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
- char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
-};
-
-struct at91_private
-{
- struct mii_if_info mii; /* ethtool support */
- struct macb_platform_data board_data; /* board-specific
- * configuration (shared with
- * macb for common data */
- void __iomem *emac_base; /* base register address */
- struct clk *ether_clk; /* clock */
-
- /* PHY */
- unsigned long phy_type; /* type of PHY (PHY_ID) */
- spinlock_t lock; /* lock for MDI interface */
- short phy_media; /* media interface type */
- unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */
- struct timer_list check_timer; /* Poll link status */
-
- /* Transmit */
- struct sk_buff *skb; /* holds skb until xmit interrupt completes */
- dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
- int skb_length; /* saved skb length for pci_unmap_single */
-
- /* Receive */
- int rxBuffIndex; /* index into receive descriptor list */
- struct recv_desc_bufs *dlist; /* descriptor list address */
- struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
-};
-
-#endif
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 033064b7b576..a9b0830fb39d 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -14,8 +14,10 @@
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/circ_buf.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -26,37 +28,74 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
#include "macb.h"
#define RX_BUFFER_SIZE 128
-#define RX_RING_SIZE 512
-#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE)
+#define RX_RING_SIZE 512 /* must be power of 2 */
+#define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
-/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
-#define RX_OFFSET 2
+#define TX_RING_SIZE 128 /* must be power of 2 */
+#define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-#define TX_RING_SIZE 128
-#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)
-#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
+/* level of occupied TX descriptors under which we wake up TX process */
+#define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4)
-#define TX_RING_GAP(bp) \
- (TX_RING_SIZE - (bp)->tx_pending)
-#define TX_BUFFS_AVAIL(bp) \
- (((bp)->tx_tail <= (bp)->tx_head) ? \
- (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \
- (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
-#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1))
+#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
+ | MACB_BIT(ISR_ROVR))
+#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \
+ | MACB_BIT(ISR_RLE) \
+ | MACB_BIT(TXERR))
+#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
-#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1))
+/*
+ * Graceful stop timeouts in us. We should allow up to
+ * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
+ */
+#define MACB_HALT_TIMEOUT 1230
-/* minimum number of free TX descriptors before waking up TX process */
-#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4)
+/* Ring buffer accessors */
+static unsigned int macb_tx_ring_wrap(unsigned int index)
+{
+ return index & (TX_RING_SIZE - 1);
+}
-#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
- | MACB_BIT(ISR_ROVR))
+static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
+{
+ return &bp->tx_ring[macb_tx_ring_wrap(index)];
+}
-static void __macb_set_hwaddr(struct macb *bp)
+static struct macb_tx_skb *macb_tx_skb(struct macb *bp, unsigned int index)
+{
+ return &bp->tx_skb[macb_tx_ring_wrap(index)];
+}
+
+static dma_addr_t macb_tx_dma(struct macb *bp, unsigned int index)
+{
+ dma_addr_t offset;
+
+ offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+
+ return bp->tx_ring_dma + offset;
+}
+
+static unsigned int macb_rx_ring_wrap(unsigned int index)
+{
+ return index & (RX_RING_SIZE - 1);
+}
+
+static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
+{
+ return &bp->rx_ring[macb_rx_ring_wrap(index)];
+}
+
+static void *macb_rx_buffer(struct macb *bp, unsigned int index)
+{
+ return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
+}
+
+void macb_set_hwaddr(struct macb *bp)
{
u32 bottom;
u16 top;
@@ -65,31 +104,58 @@ static void __macb_set_hwaddr(struct macb *bp)
macb_or_gem_writel(bp, SA1B, bottom);
top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
macb_or_gem_writel(bp, SA1T, top);
+
+ /* Clear unused address register sets */
+ macb_or_gem_writel(bp, SA2B, 0);
+ macb_or_gem_writel(bp, SA2T, 0);
+ macb_or_gem_writel(bp, SA3B, 0);
+ macb_or_gem_writel(bp, SA3T, 0);
+ macb_or_gem_writel(bp, SA4B, 0);
+ macb_or_gem_writel(bp, SA4T, 0);
}
+EXPORT_SYMBOL_GPL(macb_set_hwaddr);
-static void __init macb_get_hwaddr(struct macb *bp)
+void macb_get_hwaddr(struct macb *bp)
{
+ struct macb_platform_data *pdata;
u32 bottom;
u16 top;
u8 addr[6];
+ int i;
- bottom = macb_or_gem_readl(bp, SA1B);
- top = macb_or_gem_readl(bp, SA1T);
+ pdata = bp->pdev->dev.platform_data;
- addr[0] = bottom & 0xff;
- addr[1] = (bottom >> 8) & 0xff;
- addr[2] = (bottom >> 16) & 0xff;
- addr[3] = (bottom >> 24) & 0xff;
- addr[4] = top & 0xff;
- addr[5] = (top >> 8) & 0xff;
+ /* Check all 4 address register for vaild address */
+ for (i = 0; i < 4; i++) {
+ bottom = macb_or_gem_readl(bp, SA1B + i * 8);
+ top = macb_or_gem_readl(bp, SA1T + i * 8);
+
+ if (pdata && pdata->rev_eth_addr) {
+ addr[5] = bottom & 0xff;
+ addr[4] = (bottom >> 8) & 0xff;
+ addr[3] = (bottom >> 16) & 0xff;
+ addr[2] = (bottom >> 24) & 0xff;
+ addr[1] = top & 0xff;
+ addr[0] = (top & 0xff00) >> 8;
+ } else {
+ addr[0] = bottom & 0xff;
+ addr[1] = (bottom >> 8) & 0xff;
+ addr[2] = (bottom >> 16) & 0xff;
+ addr[3] = (bottom >> 24) & 0xff;
+ addr[4] = top & 0xff;
+ addr[5] = (top >> 8) & 0xff;
+ }
- if (is_valid_ether_addr(addr)) {
- memcpy(bp->dev->dev_addr, addr, sizeof(addr));
- } else {
- netdev_info(bp->dev, "invalid hw address, using random\n");
- eth_hw_addr_random(bp->dev);
+ if (is_valid_ether_addr(addr)) {
+ memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+ return;
+ }
}
+
+ netdev_info(bp->dev, "invalid hw address, using random\n");
+ eth_hw_addr_random(bp->dev);
}
+EXPORT_SYMBOL_GPL(macb_get_hwaddr);
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
@@ -152,13 +218,17 @@ static void macb_handle_link_change(struct net_device *dev)
reg = macb_readl(bp, NCFGR);
reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+ if (macb_is_gem(bp))
+ reg &= ~GEM_BIT(GBE);
if (phydev->duplex)
reg |= MACB_BIT(FD);
if (phydev->speed == SPEED_100)
reg |= MACB_BIT(SPD);
+ if (phydev->speed == SPEED_1000)
+ reg |= GEM_BIT(GBE);
- macb_writel(bp, NCFGR, reg);
+ macb_or_gem_writel(bp, NCFGR, reg);
bp->speed = phydev->speed;
bp->duplex = phydev->duplex;
@@ -196,7 +266,9 @@ static void macb_handle_link_change(struct net_device *dev)
static int macb_mii_probe(struct net_device *dev)
{
struct macb *bp = netdev_priv(dev);
+ struct macb_platform_data *pdata;
struct phy_device *phydev;
+ int phy_irq;
int ret;
phydev = phy_find_first(bp->mii_bus);
@@ -205,7 +277,14 @@ static int macb_mii_probe(struct net_device *dev)
return -1;
}
- /* TODO : add pin_irq */
+ pdata = dev_get_platdata(&bp->pdev->dev);
+ if (pdata && gpio_is_valid(pdata->phy_irq_pin)) {
+ ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, "phy int");
+ if (!ret) {
+ phy_irq = gpio_to_irq(pdata->phy_irq_pin);
+ phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
+ }
+ }
/* attach the mac to the phy */
ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
@@ -216,7 +295,10 @@ static int macb_mii_probe(struct net_device *dev)
}
/* mask with MAC supported features */
- phydev->supported &= PHY_BASIC_FEATURES;
+ if (macb_is_gem(bp))
+ phydev->supported &= PHY_GBIT_FEATURES;
+ else
+ phydev->supported &= PHY_BASIC_FEATURES;
phydev->advertising = phydev->supported;
@@ -228,7 +310,7 @@ static int macb_mii_probe(struct net_device *dev)
return 0;
}
-static int macb_mii_init(struct macb *bp)
+int macb_mii_init(struct macb *bp)
{
struct macb_platform_data *pdata;
int err = -ENXIO, i;
@@ -284,6 +366,7 @@ err_out_free_mdiobus:
err_out:
return err;
}
+EXPORT_SYMBOL_GPL(macb_mii_init);
static void macb_update_stats(struct macb *bp)
{
@@ -297,93 +380,148 @@ static void macb_update_stats(struct macb *bp)
*p += __raw_readl(reg);
}
-static void macb_tx(struct macb *bp)
+static int macb_halt_tx(struct macb *bp)
{
- unsigned int tail;
- unsigned int head;
- u32 status;
+ unsigned long halt_time, timeout;
+ u32 status;
- status = macb_readl(bp, TSR);
- macb_writel(bp, TSR, status);
+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT));
- netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
+ timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT);
+ do {
+ halt_time = jiffies;
+ status = macb_readl(bp, TSR);
+ if (!(status & MACB_BIT(TGO)))
+ return 0;
- if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
- int i;
- netdev_err(bp->dev, "TX %s, resetting buffers\n",
- status & MACB_BIT(UND) ?
- "underrun" : "retry limit exceeded");
+ usleep_range(10, 250);
+ } while (time_before(halt_time, timeout));
- /* Transfer ongoing, disable transmitter, to avoid confusion */
- if (status & MACB_BIT(TGO))
- macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));
+ return -ETIMEDOUT;
+}
- head = bp->tx_head;
+static void macb_tx_error_task(struct work_struct *work)
+{
+ struct macb *bp = container_of(work, struct macb, tx_error_task);
+ struct macb_tx_skb *tx_skb;
+ struct sk_buff *skb;
+ unsigned int tail;
- /*Mark all the buffer as used to avoid sending a lost buffer*/
- for (i = 0; i < TX_RING_SIZE; i++)
- bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ netdev_vdbg(bp->dev, "macb_tx_error_task: t = %u, h = %u\n",
+ bp->tx_tail, bp->tx_head);
- /* Add wrap bit */
- bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+ /* Make sure nobody is trying to queue up new packets */
+ netif_stop_queue(bp->dev);
- /* free transmit buffer in upper layer*/
- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
- struct ring_info *rp = &bp->tx_skb[tail];
- struct sk_buff *skb = rp->skb;
+ /*
+ * Stop transmission now
+ * (in case we have just queued new packets)
+ */
+ if (macb_halt_tx(bp))
+ /* Just complain for now, reinitializing TX path can be good */
+ netdev_err(bp->dev, "BUG: halt tx timed out\n");
- BUG_ON(skb == NULL);
+ /* No need for the lock here as nobody will interrupt us anymore */
- rmb();
+ /*
+ * Treat frames in TX queue including the ones that caused the error.
+ * Free transmit buffers in upper layer.
+ */
+ for (tail = bp->tx_tail; tail != bp->tx_head; tail++) {
+ struct macb_dma_desc *desc;
+ u32 ctrl;
+
+ desc = macb_tx_desc(bp, tail);
+ ctrl = desc->ctrl;
+ tx_skb = macb_tx_skb(bp, tail);
+ skb = tx_skb->skb;
+
+ if (ctrl & MACB_BIT(TX_USED)) {
+ netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
+ macb_tx_ring_wrap(tail), skb->data);
+ bp->stats.tx_packets++;
+ bp->stats.tx_bytes += skb->len;
+ } else {
+ /*
+ * "Buffers exhausted mid-frame" errors may only happen
+ * if the driver is buggy, so complain loudly about those.
+ * Statistics are updated by hardware.
+ */
+ if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
+ netdev_err(bp->dev,
+ "BUG: TX buffers exhausted mid-frame\n");
- dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
- DMA_TO_DEVICE);
- rp->skb = NULL;
- dev_kfree_skb_irq(skb);
+ desc->ctrl = ctrl | MACB_BIT(TX_USED);
}
- bp->tx_head = bp->tx_tail = 0;
-
- /* Enable the transmitter again */
- if (status & MACB_BIT(TGO))
- macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
+ DMA_TO_DEVICE);
+ tx_skb->skb = NULL;
+ dev_kfree_skb(skb);
}
- if (!(status & MACB_BIT(COMP)))
- /*
- * This may happen when a buffer becomes complete
- * between reading the ISR and scanning the
- * descriptors. Nothing to worry about.
- */
- return;
+ /* Make descriptor updates visible to hardware */
+ wmb();
+
+ /* Reinitialize the TX desc queue */
+ macb_writel(bp, TBQP, bp->tx_ring_dma);
+ /* Make TX ring reflect state of hardware */
+ bp->tx_head = bp->tx_tail = 0;
+
+ /* Now we are ready to start transmission again */
+ netif_wake_queue(bp->dev);
+
+ /* Housework before enabling TX IRQ */
+ macb_writel(bp, TSR, macb_readl(bp, TSR));
+ macb_writel(bp, IER, MACB_TX_INT_FLAGS);
+}
+
+static void macb_tx_interrupt(struct macb *bp)
+{
+ unsigned int tail;
+ unsigned int head;
+ u32 status;
+
+ status = macb_readl(bp, TSR);
+ macb_writel(bp, TSR, status);
+
+ netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
+ (unsigned long)status);
head = bp->tx_head;
- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
- struct ring_info *rp = &bp->tx_skb[tail];
- struct sk_buff *skb = rp->skb;
- u32 bufstat;
+ for (tail = bp->tx_tail; tail != head; tail++) {
+ struct macb_tx_skb *tx_skb;
+ struct sk_buff *skb;
+ struct macb_dma_desc *desc;
+ u32 ctrl;
- BUG_ON(skb == NULL);
+ desc = macb_tx_desc(bp, tail);
+ /* Make hw descriptor updates visible to CPU */
rmb();
- bufstat = bp->tx_ring[tail].ctrl;
- if (!(bufstat & MACB_BIT(TX_USED)))
+ ctrl = desc->ctrl;
+
+ if (!(ctrl & MACB_BIT(TX_USED)))
break;
- netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n",
- tail, skb->data);
- dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
+ tx_skb = macb_tx_skb(bp, tail);
+ skb = tx_skb->skb;
+
+ netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
+ macb_tx_ring_wrap(tail), skb->data);
+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
DMA_TO_DEVICE);
bp->stats.tx_packets++;
bp->stats.tx_bytes += skb->len;
- rp->skb = NULL;
+ tx_skb->skb = NULL;
dev_kfree_skb_irq(skb);
}
bp->tx_tail = tail;
- if (netif_queue_stopped(bp->dev) &&
- TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
+ if (netif_queue_stopped(bp->dev)
+ && CIRC_CNT(bp->tx_head, bp->tx_tail,
+ TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
netif_wake_queue(bp->dev);
}
@@ -392,31 +530,48 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
{
unsigned int len;
unsigned int frag;
- unsigned int offset = 0;
+ unsigned int offset;
struct sk_buff *skb;
+ struct macb_dma_desc *desc;
- len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
+ desc = macb_rx_desc(bp, last_frag);
+ len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
- netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
- first_frag, last_frag, len);
+ netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
+ macb_rx_ring_wrap(first_frag),
+ macb_rx_ring_wrap(last_frag), len);
- skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
+ /*
+ * The ethernet header starts NET_IP_ALIGN bytes into the
+ * first buffer. Since the header is 14 bytes, this makes the
+ * payload word-aligned.
+ *
+ * Instead of calling skb_reserve(NET_IP_ALIGN), we just copy
+ * the two padding bytes into the skb so that we avoid hitting
+ * the slowpath in memcpy(), and pull them off afterwards.
+ */
+ skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN);
if (!skb) {
bp->stats.rx_dropped++;
- for (frag = first_frag; ; frag = NEXT_RX(frag)) {
- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+ for (frag = first_frag; ; frag++) {
+ desc = macb_rx_desc(bp, frag);
+ desc->addr &= ~MACB_BIT(RX_USED);
if (frag == last_frag)
break;
}
+
+ /* Make descriptor updates visible to hardware */
wmb();
+
return 1;
}
- skb_reserve(skb, RX_OFFSET);
+ offset = 0;
+ len += NET_IP_ALIGN;
skb_checksum_none_assert(skb);
skb_put(skb, len);
- for (frag = first_frag; ; frag = NEXT_RX(frag)) {
+ for (frag = first_frag; ; frag++) {
unsigned int frag_len = RX_BUFFER_SIZE;
if (offset + frag_len > len) {
@@ -424,22 +579,24 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
frag_len = len - offset;
}
skb_copy_to_linear_data_offset(skb, offset,
- (bp->rx_buffers +
- (RX_BUFFER_SIZE * frag)),
- frag_len);
+ macb_rx_buffer(bp, frag), frag_len);
offset += RX_BUFFER_SIZE;
- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
- wmb();
+ desc = macb_rx_desc(bp, frag);
+ desc->addr &= ~MACB_BIT(RX_USED);
if (frag == last_frag)
break;
}
+ /* Make descriptor updates visible to hardware */
+ wmb();
+
+ __skb_pull(skb, NET_IP_ALIGN);
skb->protocol = eth_type_trans(skb, bp->dev);
bp->stats.rx_packets++;
- bp->stats.rx_bytes += len;
- netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n",
+ bp->stats.rx_bytes += skb->len;
+ netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
skb->len, skb->csum);
netif_receive_skb(skb);
@@ -452,8 +609,12 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
{
unsigned int frag;
- for (frag = begin; frag != end; frag = NEXT_RX(frag))
- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+ for (frag = begin; frag != end; frag++) {
+ struct macb_dma_desc *desc = macb_rx_desc(bp, frag);
+ desc->addr &= ~MACB_BIT(RX_USED);
+ }
+
+ /* Make descriptor updates visible to hardware */
wmb();
/*
@@ -466,15 +627,18 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
static int macb_rx(struct macb *bp, int budget)
{
int received = 0;
- unsigned int tail = bp->rx_tail;
+ unsigned int tail;
int first_frag = -1;
- for (; budget > 0; tail = NEXT_RX(tail)) {
+ for (tail = bp->rx_tail; budget > 0; tail++) {
+ struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
u32 addr, ctrl;
+ /* Make hw descriptor updates visible to CPU */
rmb();
- addr = bp->rx_ring[tail].addr;
- ctrl = bp->rx_ring[tail].ctrl;
+
+ addr = desc->addr;
+ ctrl = desc->ctrl;
if (!(addr & MACB_BIT(RX_USED)))
break;
@@ -517,7 +681,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
work_done = 0;
- netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n",
+ netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n",
(unsigned long)status, budget);
work_done = macb_rx(bp, budget);
@@ -552,10 +716,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
while (status) {
/* close possible race with dev_close */
if (unlikely(!netif_running(dev))) {
- macb_writel(bp, IDR, ~0UL);
+ macb_writel(bp, IDR, -1);
break;
}
+ netdev_vdbg(bp->dev, "isr = 0x%08lx\n", (unsigned long)status);
+
if (status & MACB_RX_INT_FLAGS) {
/*
* There's no point taking any more interrupts
@@ -567,14 +733,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
if (napi_schedule_prep(&bp->napi)) {
- netdev_dbg(bp->dev, "scheduling RX softirq\n");
+ netdev_vdbg(bp->dev, "scheduling RX softirq\n");
__napi_schedule(&bp->napi);
}
}
- if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
- MACB_BIT(ISR_RLE)))
- macb_tx(bp);
+ if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
+ macb_writel(bp, IDR, MACB_TX_INT_FLAGS);
+ schedule_work(&bp->tx_error_task);
+ break;
+ }
+
+ if (status & MACB_BIT(TCOMP))
+ macb_tx_interrupt(bp);
/*
* Link change detection isn't possible with RMII, so we'll
@@ -626,11 +797,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct macb *bp = netdev_priv(dev);
dma_addr_t mapping;
unsigned int len, entry;
+ struct macb_dma_desc *desc;
+ struct macb_tx_skb *tx_skb;
u32 ctrl;
unsigned long flags;
-#ifdef DEBUG
- netdev_dbg(bp->dev,
+#if defined(DEBUG) && defined(VERBOSE_DEBUG)
+ netdev_vdbg(bp->dev,
"start_xmit: len %u head %p data %p tail %p end %p\n",
skb->len, skb->head, skb->data,
skb_tail_pointer(skb), skb_end_pointer(skb));
@@ -642,7 +815,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&bp->lock, flags);
/* This is a hard error, log it. */
- if (TX_BUFFS_AVAIL(bp) < 1) {
+ if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
netif_stop_queue(dev);
spin_unlock_irqrestore(&bp->lock, flags);
netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
@@ -651,13 +824,16 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- entry = bp->tx_head;
- netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry);
+ entry = macb_tx_ring_wrap(bp->tx_head);
+ bp->tx_head++;
+ netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
mapping = dma_map_single(&bp->pdev->dev, skb->data,
len, DMA_TO_DEVICE);
- bp->tx_skb[entry].skb = skb;
- bp->tx_skb[entry].mapping = mapping;
- netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
+
+ tx_skb = &bp->tx_skb[entry];
+ tx_skb->skb = skb;
+ tx_skb->mapping = mapping;
+ netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
skb->data, (unsigned long)mapping);
ctrl = MACB_BF(TX_FRMLEN, len);
@@ -665,18 +841,18 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (entry == (TX_RING_SIZE - 1))
ctrl |= MACB_BIT(TX_WRAP);
- bp->tx_ring[entry].addr = mapping;
- bp->tx_ring[entry].ctrl = ctrl;
- wmb();
+ desc = &bp->tx_ring[entry];
+ desc->addr = mapping;
+ desc->ctrl = ctrl;
- entry = NEXT_TX(entry);
- bp->tx_head = entry;
+ /* Make newly initialized descriptor visible to hardware */
+ wmb();
skb_tx_timestamp(skb);
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
- if (TX_BUFFS_AVAIL(bp) < 1)
+ if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1)
netif_stop_queue(dev);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -712,7 +888,7 @@ static int macb_alloc_consistent(struct macb *bp)
{
int size;
- size = TX_RING_SIZE * sizeof(struct ring_info);
+ size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
bp->tx_skb = kmalloc(size, GFP_KERNEL);
if (!bp->tx_skb)
goto out_err;
@@ -775,9 +951,6 @@ static void macb_init_rings(struct macb *bp)
static void macb_reset_hw(struct macb *bp)
{
- /* Make sure we have the write buffer for ourselves */
- wmb();
-
/*
* Disable RX and TX (XXX: Should we halt the transmission
* more gracefully?)
@@ -788,11 +961,11 @@ static void macb_reset_hw(struct macb *bp)
macb_writel(bp, NCR, MACB_BIT(CLRSTAT));
/* Clear all status flags */
- macb_writel(bp, TSR, ~0UL);
- macb_writel(bp, RSR, ~0UL);
+ macb_writel(bp, TSR, -1);
+ macb_writel(bp, RSR, -1);
/* Disable all interrupts */
- macb_writel(bp, IDR, ~0UL);
+ macb_writel(bp, IDR, -1);
macb_readl(bp, ISR);
}
@@ -860,8 +1033,12 @@ static u32 macb_dbw(struct macb *bp)
}
/*
- * Configure the receive DMA engine to use the correct receive buffer size.
- * This is a configurable parameter for GEM.
+ * Configure the receive DMA engine
+ * - use the correct receive buffer size
+ * - set the possibility to use INCR16 bursts
+ * (if not supported by FIFO, it will fallback to default)
+ * - set both rx/tx packet buffers to full memory size
+ * These are configurable parameters for GEM.
*/
static void macb_configure_dma(struct macb *bp)
{
@@ -870,6 +1047,8 @@ static void macb_configure_dma(struct macb *bp)
if (macb_is_gem(bp)) {
dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
+ dmacfg |= GEM_BF(FBLDO, 16);
+ dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
gem_writel(bp, DMACFG, dmacfg);
}
}
@@ -879,9 +1058,10 @@ static void macb_init_hw(struct macb *bp)
u32 config;
macb_reset_hw(bp);
- __macb_set_hwaddr(bp);
+ macb_set_hwaddr(bp);
config = macb_mdc_clk_div(bp);
+ config |= MACB_BF(RBOF, NET_IP_ALIGN); /* Make eth data aligned */
config |= MACB_BIT(PAE); /* PAuse Enable */
config |= MACB_BIT(DRFCS); /* Discard Rx FCS */
config |= MACB_BIT(BIG); /* Receive oversized frames */
@@ -891,6 +1071,8 @@ static void macb_init_hw(struct macb *bp)
config |= MACB_BIT(NBC); /* No BroadCast */
config |= macb_dbw(bp);
macb_writel(bp, NCFGR, config);
+ bp->speed = SPEED_10;
+ bp->duplex = DUPLEX_HALF;
macb_configure_dma(bp);
@@ -902,13 +1084,8 @@ static void macb_init_hw(struct macb *bp)
macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
/* Enable interrupts */
- macb_writel(bp, IER, (MACB_BIT(RCOMP)
- | MACB_BIT(RXUBR)
- | MACB_BIT(ISR_TUND)
- | MACB_BIT(ISR_RLE)
- | MACB_BIT(TXERR)
- | MACB_BIT(TCOMP)
- | MACB_BIT(ISR_ROVR)
+ macb_writel(bp, IER, (MACB_RX_INT_FLAGS
+ | MACB_TX_INT_FLAGS
| MACB_BIT(HRESP)));
}
@@ -996,7 +1173,7 @@ static void macb_sethashtable(struct net_device *dev)
/*
* Enable/Disable promiscuous and multicast modes.
*/
-static void macb_set_rx_mode(struct net_device *dev)
+void macb_set_rx_mode(struct net_device *dev)
{
unsigned long cfg;
struct macb *bp = netdev_priv(dev);
@@ -1028,6 +1205,7 @@ static void macb_set_rx_mode(struct net_device *dev)
macb_writel(bp, NCFGR, cfg);
}
+EXPORT_SYMBOL_GPL(macb_set_rx_mode);
static int macb_open(struct net_device *dev)
{
@@ -1043,9 +1221,6 @@ static int macb_open(struct net_device *dev)
if (!bp->phy_dev)
return -EAGAIN;
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EADDRNOTAVAIL;
-
err = macb_alloc_consistent(bp);
if (err) {
netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
@@ -1135,7 +1310,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
return nstat;
}
-static struct net_device_stats *macb_get_stats(struct net_device *dev)
+struct net_device_stats *macb_get_stats(struct net_device *dev)
{
struct macb *bp = netdev_priv(dev);
struct net_device_stats *nstat = &bp->stats;
@@ -1181,6 +1356,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
return nstat;
}
+EXPORT_SYMBOL_GPL(macb_get_stats);
static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
@@ -1204,25 +1380,55 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return phy_ethtool_sset(phydev, cmd);
}
-static void macb_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
+static int macb_get_regs_len(struct net_device *netdev)
+{
+ return MACB_GREGS_NBR * sizeof(u32);
+}
+
+static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
{
struct macb *bp = netdev_priv(dev);
+ unsigned int tail, head;
+ u32 *regs_buff = p;
+
+ regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
+ | MACB_GREGS_VERSION;
+
+ tail = macb_tx_ring_wrap(bp->tx_tail);
+ head = macb_tx_ring_wrap(bp->tx_head);
+
+ regs_buff[0] = macb_readl(bp, NCR);
+ regs_buff[1] = macb_or_gem_readl(bp, NCFGR);
+ regs_buff[2] = macb_readl(bp, NSR);
+ regs_buff[3] = macb_readl(bp, TSR);
+ regs_buff[4] = macb_readl(bp, RBQP);
+ regs_buff[5] = macb_readl(bp, TBQP);
+ regs_buff[6] = macb_readl(bp, RSR);
+ regs_buff[7] = macb_readl(bp, IMR);
- strcpy(info->driver, bp->pdev->dev.driver->name);
- strcpy(info->version, "$Revision: 1.14 $");
- strcpy(info->bus_info, dev_name(&bp->pdev->dev));
+ regs_buff[8] = tail;
+ regs_buff[9] = head;
+ regs_buff[10] = macb_tx_dma(bp, tail);
+ regs_buff[11] = macb_tx_dma(bp, head);
+
+ if (macb_is_gem(bp)) {
+ regs_buff[12] = gem_readl(bp, USRIO);
+ regs_buff[13] = gem_readl(bp, DMACFG);
+ }
}
-static const struct ethtool_ops macb_ethtool_ops = {
+const struct ethtool_ops macb_ethtool_ops = {
.get_settings = macb_get_settings,
.set_settings = macb_set_settings,
- .get_drvinfo = macb_get_drvinfo,
+ .get_regs_len = macb_get_regs_len,
+ .get_regs = macb_get_regs,
.get_link = ethtool_op_get_link,
.get_ts_info = ethtool_op_get_ts_info,
};
+EXPORT_SYMBOL_GPL(macb_ethtool_ops);
-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct macb *bp = netdev_priv(dev);
struct phy_device *phydev = bp->phy_dev;
@@ -1235,6 +1441,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return phy_mii_ioctl(phydev, rq, cmd);
}
+EXPORT_SYMBOL_GPL(macb_ioctl);
static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
@@ -1263,7 +1470,7 @@ static const struct of_device_id macb_dt_ids[] = {
MODULE_DEVICE_TABLE(of, macb_dt_ids);
-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
+static int macb_get_phy_mode_dt(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1273,7 +1480,7 @@ static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
return -ENODEV;
}
-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
+static int macb_get_hwaddr_dt(struct macb *bp)
{
struct device_node *np = bp->pdev->dev.of_node;
if (np) {
@@ -1287,11 +1494,11 @@ static int __devinit macb_get_hwaddr_dt(struct macb *bp)
return -ENODEV;
}
#else
-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
+static int macb_get_phy_mode_dt(struct platform_device *pdev)
{
return -ENODEV;
}
-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
+static int macb_get_hwaddr_dt(struct macb *bp)
{
return -ENODEV;
}
@@ -1306,6 +1513,7 @@ static int __init macb_probe(struct platform_device *pdev)
struct phy_device *phydev;
u32 config;
int err = -ENXIO;
+ struct pinctrl *pinctrl;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
@@ -1313,6 +1521,15 @@ static int __init macb_probe(struct platform_device *pdev)
goto err_out;
}
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ err = PTR_ERR(pinctrl);
+ if (err == -EPROBE_DEFER)
+ goto err_out;
+
+ dev_warn(&pdev->dev, "No pinctrl provided\n");
+ }
+
err = -ENOMEM;
dev = alloc_etherdev(sizeof(*bp));
if (!dev)
@@ -1328,6 +1545,7 @@ static int __init macb_probe(struct platform_device *pdev)
bp->dev = dev;
spin_lock_init(&bp->lock);
+ INIT_WORK(&bp->tx_error_task, macb_tx_error_task);
bp->pclk = clk_get(&pdev->dev, "pclk");
if (IS_ERR(bp->pclk)) {
@@ -1384,7 +1602,9 @@ static int __init macb_probe(struct platform_device *pdev)
bp->phy_interface = err;
}
- if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
+ if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
+ macb_or_gem_writel(bp, USRIO, GEM_BIT(RGMII));
+ else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
#if defined(CONFIG_ARCH_AT91)
macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
MACB_BIT(CLKEN)));
@@ -1398,8 +1618,6 @@ static int __init macb_probe(struct platform_device *pdev)
macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
#endif
- bp->tx_pending = DEF_TX_RING_PENDING;
-
err = register_netdev(dev);
if (err) {
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 335e288f5314..570908b93578 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -10,10 +10,15 @@
#ifndef _MACB_H
#define _MACB_H
+#define MACB_GREGS_NBR 16
+#define MACB_GREGS_VERSION 1
+
/* MACB register offsets */
#define MACB_NCR 0x0000
#define MACB_NCFGR 0x0004
#define MACB_NSR 0x0008
+#define MACB_TAR 0x000c /* AT91RM9200 only */
+#define MACB_TCR 0x0010 /* AT91RM9200 only */
#define MACB_TSR 0x0014
#define MACB_RBQP 0x0018
#define MACB_TBQP 0x001c
@@ -69,6 +74,12 @@
#define GEM_HRT 0x0084
#define GEM_SA1B 0x0088
#define GEM_SA1T 0x008C
+#define GEM_SA2B 0x0090
+#define GEM_SA2T 0x0094
+#define GEM_SA3B 0x0098
+#define GEM_SA3T 0x009C
+#define GEM_SA4B 0x00A0
+#define GEM_SA4T 0x00A4
#define GEM_OTX 0x0100
#define GEM_DCFG1 0x0280
#define GEM_DCFG2 0x0284
@@ -133,6 +144,8 @@
#define MACB_RTY_SIZE 1
#define MACB_PAE_OFFSET 13
#define MACB_PAE_SIZE 1
+#define MACB_RM9200_RMII_OFFSET 13 /* AT91RM9200 only */
+#define MACB_RM9200_RMII_SIZE 1 /* AT91RM9200 only */
#define MACB_RBOF_OFFSET 14
#define MACB_RBOF_SIZE 2
#define MACB_RLCE_OFFSET 16
@@ -145,6 +158,8 @@
#define MACB_IRXFCS_SIZE 1
/* GEM specific NCFGR bitfields. */
+#define GEM_GBE_OFFSET 10
+#define GEM_GBE_SIZE 1
#define GEM_CLK_OFFSET 18
#define GEM_CLK_SIZE 3
#define GEM_DBW_OFFSET 21
@@ -156,8 +171,19 @@
#define GEM_DBW128 2
/* Bitfields in DMACFG. */
+#define GEM_FBLDO_OFFSET 0
+#define GEM_FBLDO_SIZE 5
+#define GEM_RXBMS_OFFSET 8
+#define GEM_RXBMS_SIZE 2
+#define GEM_TXPBMS_OFFSET 10
+#define GEM_TXPBMS_SIZE 1
+#define GEM_TXCOEN_OFFSET 11
+#define GEM_TXCOEN_SIZE 1
#define GEM_RXBS_OFFSET 16
#define GEM_RXBS_SIZE 8
+#define GEM_DDRP_OFFSET 24
+#define GEM_DDRP_SIZE 1
+
/* Bitfields in NSR */
#define MACB_NSR_LINK_OFFSET 0
@@ -178,6 +204,8 @@
#define MACB_TGO_SIZE 1
#define MACB_BEX_OFFSET 4
#define MACB_BEX_SIZE 1
+#define MACB_RM9200_BNQ_OFFSET 4 /* AT91RM9200 only */
+#define MACB_RM9200_BNQ_SIZE 1 /* AT91RM9200 only */
#define MACB_COMP_OFFSET 5
#define MACB_COMP_SIZE 1
#define MACB_UND_OFFSET 6
@@ -246,6 +274,8 @@
/* Bitfields in USRIO (AT91) */
#define MACB_RMII_OFFSET 0
#define MACB_RMII_SIZE 1
+#define GEM_RGMII_OFFSET 0 /* GEM gigabit mode */
+#define GEM_RGMII_SIZE 1
#define MACB_CLKEN_OFFSET 1
#define MACB_CLKEN_SIZE 1
@@ -352,7 +382,12 @@
__v; \
})
-struct dma_desc {
+/**
+ * struct macb_dma_desc - Hardware DMA descriptor
+ * @addr: DMA address of data buffer
+ * @ctrl: Control and status bits
+ */
+struct macb_dma_desc {
u32 addr;
u32 ctrl;
};
@@ -417,7 +452,12 @@ struct dma_desc {
#define MACB_TX_USED_OFFSET 31
#define MACB_TX_USED_SIZE 1
-struct ring_info {
+/**
+ * struct macb_tx_skb - data about an skb which is being transmitted
+ * @skb: skb currently being transmitted
+ * @mapping: DMA address of the skb's data buffer
+ */
+struct macb_tx_skb {
struct sk_buff *skb;
dma_addr_t mapping;
};
@@ -502,12 +542,12 @@ struct macb {
void __iomem *regs;
unsigned int rx_tail;
- struct dma_desc *rx_ring;
+ struct macb_dma_desc *rx_ring;
void *rx_buffers;
unsigned int tx_head, tx_tail;
- struct dma_desc *tx_ring;
- struct ring_info *tx_skb;
+ struct macb_dma_desc *tx_ring;
+ struct macb_tx_skb *tx_skb;
spinlock_t lock;
struct platform_device *pdev;
@@ -515,6 +555,7 @@ struct macb {
struct clk *hclk;
struct net_device *dev;
struct napi_struct napi;
+ struct work_struct tx_error_task;
struct net_device_stats stats;
union {
struct macb_stats macb;
@@ -525,8 +566,6 @@ struct macb {
dma_addr_t tx_ring_dma;
dma_addr_t rx_buffers_dma;
- unsigned int rx_pending, tx_pending;
-
struct mii_bus *mii_bus;
struct phy_device *phy_dev;
unsigned int link;
@@ -534,8 +573,22 @@ struct macb {
unsigned int duplex;
phy_interface_t phy_interface;
+
+ /* AT91RM9200 transmit */
+ struct sk_buff *skb; /* holds skb until xmit interrupt completes */
+ dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
+ int skb_length; /* saved skb length for pci_unmap_single */
};
+extern const struct ethtool_ops macb_ethtool_ops;
+
+int macb_mii_init(struct macb *bp);
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+struct net_device_stats *macb_get_stats(struct net_device *dev);
+void macb_set_rx_mode(struct net_device *dev);
+void macb_set_hwaddr(struct macb *bp);
+void macb_get_hwaddr(struct macb *bp);
+
static inline bool macb_is_gem(struct macb *bp)
{
return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 16814b34d4b6..b407043ce9b0 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -191,6 +191,7 @@
#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */
#define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */
#define DMA_CONTROL_DFF 0x01000000 /* Disable flush of rx frames */
+#define DMA_CONTROL_OSF 0x00000004 /* Operate on 2nd tx frame */
/* DMA Normal interrupt */
#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */
@@ -210,7 +211,7 @@
#define DMA_INTR_ENA_TIE 0x00000001 /* Transmit Interrupt */
#define DMA_INTR_NORMAL (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
- DMA_INTR_ENA_TUE)
+ DMA_INTR_ENA_TUE | DMA_INTR_ENA_TIE)
#define DMA_INTR_ABNORMAL (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \
@@ -373,6 +374,7 @@ struct xgmac_priv {
struct sk_buff **tx_skbuff;
unsigned int tx_head;
unsigned int tx_tail;
+ int tx_irq_cnt;
void __iomem *base;
unsigned int dma_buf_sz;
@@ -663,6 +665,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
{
struct xgmac_dma_desc *p;
dma_addr_t paddr;
+ int bufsz = priv->dev->mtu + ETH_HLEN + ETH_FCS_LEN;
while (dma_ring_space(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ) > 1) {
int entry = priv->rx_head;
@@ -671,13 +674,13 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
p = priv->dma_rx + entry;
if (priv->rx_skbuff[entry] == NULL) {
- skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+ skb = netdev_alloc_skb_ip_align(priv->dev, bufsz);
if (unlikely(skb == NULL))
break;
priv->rx_skbuff[entry] = skb;
paddr = dma_map_single(priv->device, skb->data,
- priv->dma_buf_sz, DMA_FROM_DEVICE);
+ bufsz, DMA_FROM_DEVICE);
desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
}
@@ -701,10 +704,10 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev)
unsigned int bfsize;
/* Set the Buffer size according to the MTU;
- * indeed, in case of jumbo we need to bump-up the buffer sizes.
+ * The total buffer size including any IP offset must be a multiple
+ * of 8 bytes.
*/
- bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN + 64,
- 64);
+ bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN, 8);
netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize);
@@ -845,9 +848,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv)
static void xgmac_tx_complete(struct xgmac_priv *priv)
{
int i;
- void __iomem *ioaddr = priv->base;
-
- writel(DMA_STATUS_TU | DMA_STATUS_NIS, ioaddr + XGMAC_DMA_STATUS);
while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) {
unsigned int entry = priv->tx_tail;
@@ -888,7 +888,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
}
if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
- TX_THRESH)
+ MAX_SKB_FRAGS)
netif_wake_queue(priv->dev);
}
@@ -965,8 +965,7 @@ static int xgmac_hw_init(struct net_device *dev)
ctrl |= XGMAC_CONTROL_IPC;
writel(ctrl, ioaddr + XGMAC_CONTROL);
- value = DMA_CONTROL_DFF;
- writel(value, ioaddr + XGMAC_DMA_CONTROL);
+ writel(DMA_CONTROL_OSF, ioaddr + XGMAC_DMA_CONTROL);
/* Set the HW DMA mode and the COE */
writel(XGMAC_OMR_TSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA |
@@ -1060,19 +1059,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
struct xgmac_priv *priv = netdev_priv(dev);
unsigned int entry;
int i;
+ u32 irq_flag;
int nfrags = skb_shinfo(skb)->nr_frags;
struct xgmac_dma_desc *desc, *first;
unsigned int desc_flags;
unsigned int len;
dma_addr_t paddr;
- if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
- (nfrags + 1)) {
- writel(DMA_INTR_DEFAULT_MASK | DMA_INTR_ENA_TIE,
- priv->base + XGMAC_DMA_INTR_ENA);
- netif_stop_queue(dev);
- return NETDEV_TX_BUSY;
- }
+ priv->tx_irq_cnt = (priv->tx_irq_cnt + 1) & (DMA_TX_RING_SZ/4 - 1);
+ irq_flag = priv->tx_irq_cnt ? 0 : TXDESC_INTERRUPT;
desc_flags = (skb->ip_summed == CHECKSUM_PARTIAL) ?
TXDESC_CSUM_ALL : 0;
@@ -1113,9 +1108,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
/* Interrupt on completition only for the latest segment */
if (desc != first)
desc_set_tx_owner(desc, desc_flags |
- TXDESC_LAST_SEG | TXDESC_INTERRUPT);
+ TXDESC_LAST_SEG | irq_flag);
else
- desc_flags |= TXDESC_LAST_SEG | TXDESC_INTERRUPT;
+ desc_flags |= TXDESC_LAST_SEG | irq_flag;
/* Set owner on first desc last to avoid race condition */
wmb();
@@ -1124,6 +1119,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
writel(1, priv->base + XGMAC_DMA_TX_POLL);
+ if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
+ MAX_SKB_FRAGS)
+ netif_stop_queue(dev);
return NETDEV_TX_OK;
}
@@ -1139,9 +1137,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
struct sk_buff *skb;
int frame_len;
- writel(DMA_STATUS_RI | DMA_STATUS_NIS,
- priv->base + XGMAC_DMA_STATUS);
-
entry = priv->rx_tail;
p = priv->dma_rx + entry;
if (desc_get_owner(p))
@@ -1180,8 +1175,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
xgmac_rx_refill(priv);
- writel(1, priv->base + XGMAC_DMA_RX_POLL);
-
return count;
}
@@ -1205,7 +1198,7 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(napi);
- writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
+ __raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
}
return work_done;
}
@@ -1350,7 +1343,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
struct xgmac_priv *priv = netdev_priv(dev);
void __iomem *ioaddr = priv->base;
- intr_status = readl(ioaddr + XGMAC_INT_STAT);
+ intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
if (intr_status & XGMAC_INT_STAT_PMT) {
netdev_dbg(priv->dev, "received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT */
@@ -1368,9 +1361,9 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
struct xgmac_extra_stats *x = &priv->xstats;
/* read the status register (CSR5) */
- intr_status = readl(priv->base + XGMAC_DMA_STATUS);
- intr_status &= readl(priv->base + XGMAC_DMA_INTR_ENA);
- writel(intr_status, priv->base + XGMAC_DMA_STATUS);
+ intr_status = __raw_readl(priv->base + XGMAC_DMA_STATUS);
+ intr_status &= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
+ __raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
/* It displays the DMA process states (CSR5 register) */
/* ABNORMAL interrupts */
@@ -1405,8 +1398,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
}
/* TX/RX NORMAL interrupts */
- if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU)) {
- writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
+ if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
+ __raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
napi_schedule(&priv->napi);
}
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index 2de50f95798f..d40c994a4f6a 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_CHELSIO
bool "Chelsio devices"
default y
- depends on PCI || INET
+ depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 1d17c92f2dda..c8fdeaae56c0 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -974,8 +974,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
#endif
};
-static int __devinit init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int version_printed;
@@ -1332,7 +1331,7 @@ static inline void t1_sw_reset(struct pci_dev *pdev)
pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
}
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct adapter *adapter = dev->ml_priv;
@@ -1361,7 +1360,7 @@ static struct pci_driver driver = {
.name = DRV_NAME,
.id_table = t1_pci_tbl,
.probe = init_one,
- .remove = __devexit_p(remove_one),
+ .remove = remove_one,
};
static int __init t1_init_module(void)
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 47a84359d4e4..d84872e88171 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -367,18 +367,6 @@ void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port,
#endif /* 0 */
-
-/*
- * get_clock() implements a ns clock (see ktime_get)
- */
-static inline ktime_t get_clock(void)
-{
- struct timespec ts;
-
- ktime_get_ts(&ts);
- return timespec_to_ktime(ts);
-}
-
/*
* tx_sched_init() allocates resources and does basic initialization.
*/
@@ -411,7 +399,7 @@ static int tx_sched_init(struct sge *sge)
static inline int sched_update_avail(struct sge *sge)
{
struct sched *s = sge->tx_sched;
- ktime_t now = get_clock();
+ ktime_t now = ktime_get();
unsigned int i;
long long delta_time_ns;
@@ -2071,8 +2059,7 @@ static void espibug_workaround(unsigned long data)
/*
* Creates a t1_sge structure and returns suggested resource parameters.
*/
-struct sge * __devinit t1_sge_create(struct adapter *adapter,
- struct sge_params *p)
+struct sge *t1_sge_create(struct adapter *adapter, struct sge_params *p)
{
struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);
int i;
diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c
index 8a43c7e19701..e0a03a31e7c4 100644
--- a/drivers/net/ethernet/chelsio/cxgb/subr.c
+++ b/drivers/net/ethernet/chelsio/cxgb/subr.c
@@ -892,8 +892,8 @@ static void power_sequence_xpak(adapter_t* adapter)
}
}
-int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
- struct adapter_params *p)
+int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ struct adapter_params *p)
{
p->chip_version = bi->chip_term;
p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
@@ -992,7 +992,7 @@ out_err:
/*
* Determine a card's PCI mode.
*/
-static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
+static void get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
{
static const unsigned short speed_map[] = { 33, 66, 100, 133 };
u32 pci_mode;
@@ -1028,8 +1028,8 @@ void t1_free_sw_modules(adapter_t *adapter)
t1_espi_destroy(adapter->espi);
}
-static void __devinit init_link_config(struct link_config *lc,
- const struct board_info *bi)
+static void init_link_config(struct link_config *lc,
+ const struct board_info *bi)
{
lc->supported = bi->caps;
lc->requested_speed = lc->speed = SPEED_INVALID;
@@ -1049,8 +1049,7 @@ static void __devinit init_link_config(struct link_config *lc,
* Allocate and initialize the data structures that hold the SW state of
* the Terminator HW modules.
*/
-int __devinit t1_init_sw_modules(adapter_t *adapter,
- const struct board_info *bi)
+int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi)
{
unsigned int i;
diff --git a/drivers/net/ethernet/chelsio/cxgb/tp.c b/drivers/net/ethernet/chelsio/cxgb/tp.c
index 8bed4a59e65f..b146acabf982 100644
--- a/drivers/net/ethernet/chelsio/cxgb/tp.c
+++ b/drivers/net/ethernet/chelsio/cxgb/tp.c
@@ -55,7 +55,7 @@ void t1_tp_destroy(struct petp *tp)
kfree(tp);
}
-struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p)
+struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p)
{
struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h
index df01b6343241..8c82248ce416 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/common.h
@@ -42,10 +42,9 @@
#include <linux/mdio.h>
#include "version.h"
-#define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_WARN(adap, fmt, ...) dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_ALERT(adap, fmt, ...) \
- dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__)
+#define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_WARN(adap, fmt, ...) dev_warn(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_ALERT(adap, fmt, ...) dev_alert(&adap->pdev->dev, fmt, ##__VA_ARGS__)
/*
* More powerful macro that selectively prints messages based on msg_enable.
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 9c9f3260344a..f15ee326d5c1 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3078,7 +3078,7 @@ static void set_nqsets(struct adapter *adap)
}
}
-static int __devinit cxgb_enable_msix(struct adapter *adap)
+static int cxgb_enable_msix(struct adapter *adap)
{
struct msix_entry entries[SGE_QSETS + 1];
int vectors;
@@ -3108,8 +3108,7 @@ static int __devinit cxgb_enable_msix(struct adapter *adap)
return err;
}
-static void __devinit print_port_info(struct adapter *adap,
- const struct adapter_info *ai)
+static void print_port_info(struct adapter *adap, const struct adapter_info *ai)
{
static const char *pci_variant[] = {
"PCI", "PCI-X", "PCI-X ECC", "PCI-X 266", "PCI Express"
@@ -3165,7 +3164,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
#endif
};
-static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
+static void cxgb3_init_iscsi_mac(struct net_device *dev)
{
struct port_info *pi = netdev_priv(dev);
@@ -3176,8 +3175,7 @@ static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
-static int __devinit init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int version_printed;
@@ -3381,7 +3379,7 @@ out:
return err;
}
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
{
struct adapter *adapter = pci_get_drvdata(pdev);
@@ -3425,7 +3423,7 @@ static struct pci_driver driver = {
.name = DRV_NAME,
.id_table = cxgb3_pci_tbl,
.probe = init_one,
- .remove = __devexit_p(remove_one),
+ .remove = remove_one,
.err_handler = &t3_err_handler,
};
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index 2dbbcbb450d3..942dace361d2 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
@@ -1382,7 +1382,7 @@ static inline int adap2type(struct adapter *adapter)
return type;
}
-void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
+void cxgb3_adapter_ofld(struct adapter *adapter)
{
struct t3cdev *tdev = &adapter->tdev;
@@ -1396,7 +1396,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
register_tdev(tdev);
}
-void __devexit cxgb3_adapter_unofld(struct adapter *adapter)
+void cxgb3_adapter_unofld(struct adapter *adapter)
{
struct t3cdev *tdev = &adapter->tdev;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
index aef45d3113ba..3dee68612c9e 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
@@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap)
G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
log2_width = fls(adap->params.pci.width) - 1;
acklat = ack_lat[log2_width][pldsize];
- if (val & 1) /* check LOsEnable */
+ if (val & PCI_EXP_LNKCTL_ASPM_L0S) /* check LOsEnable */
acklat += fst_trn_tx * 4;
rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 0df1284df497..130dd9d5b493 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2148,8 +2148,8 @@ static const struct file_operations mem_debugfs_fops = {
.llseek = default_llseek,
};
-static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
- unsigned int idx, unsigned int size_mb)
+static void add_debugfs_mem(struct adapter *adap, const char *name,
+ unsigned int idx, unsigned int size_mb)
{
struct dentry *de;
@@ -2159,7 +2159,7 @@ static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
de->d_inode->i_size = size_mb << 20;
}
-static int __devinit setup_debugfs(struct adapter *adap)
+static int setup_debugfs(struct adapter *adap)
{
int i;
@@ -4173,7 +4173,7 @@ static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
* of ports we found and the number of available CPUs. Most settings can be
* modified by the admin prior to actual use.
*/
-static void __devinit cfg_queues(struct adapter *adap)
+static void cfg_queues(struct adapter *adap)
{
struct sge *s = &adap->sge;
int i, q10g = 0, n10g = 0, qidx = 0;
@@ -4257,7 +4257,7 @@ static void __devinit cfg_queues(struct adapter *adap)
* Reduce the number of Ethernet queues across all ports to at most n.
* n provides at least one queue per port.
*/
-static void __devinit reduce_ethqs(struct adapter *adap, int n)
+static void reduce_ethqs(struct adapter *adap, int n)
{
int i;
struct port_info *pi;
@@ -4284,7 +4284,7 @@ static void __devinit reduce_ethqs(struct adapter *adap, int n)
/* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
#define EXTRA_VECS 2
-static int __devinit enable_msix(struct adapter *adap)
+static int enable_msix(struct adapter *adap)
{
int ofld_need = 0;
int i, err, want, need;
@@ -4333,7 +4333,7 @@ static int __devinit enable_msix(struct adapter *adap)
#undef EXTRA_VECS
-static int __devinit init_rss(struct adapter *adap)
+static int init_rss(struct adapter *adap)
{
unsigned int i, j;
@@ -4349,7 +4349,7 @@ static int __devinit init_rss(struct adapter *adap)
return 0;
}
-static void __devinit print_port_info(const struct net_device *dev)
+static void print_port_info(const struct net_device *dev)
{
static const char *base[] = {
"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
@@ -4386,7 +4386,7 @@ static void __devinit print_port_info(const struct net_device *dev)
adap->params.vpd.sn, adap->params.vpd.ec);
}
-static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
+static void enable_pcie_relaxed_ordering(struct pci_dev *dev)
{
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
}
@@ -4419,8 +4419,7 @@ static void free_some_resources(struct adapter *adapter)
#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
-static int __devinit init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int func, i, err;
struct port_info *pi;
@@ -4640,7 +4639,7 @@ sriov:
return err;
}
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
{
struct adapter *adapter = pci_get_drvdata(pdev);
@@ -4680,7 +4679,7 @@ static struct pci_driver cxgb4_driver = {
.name = KBUILD_MODNAME,
.id_table = cxgb4_pci_tbl,
.probe = init_one,
- .remove = __devexit_p(remove_one),
+ .remove = remove_one,
.err_handler = &cxgb4_eeh,
};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 730ae2cfa49e..45f2bea2e929 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -2003,7 +2003,7 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
*
* Initialize the congestion control parameters.
*/
-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
+static void init_cong_ctrl(unsigned short *a, unsigned short *b)
{
a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
a[9] = 2;
@@ -3440,8 +3440,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
return 0;
}
-static void __devinit get_pci_mode(struct adapter *adapter,
- struct pci_params *p)
+static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
{
u16 val;
@@ -3460,8 +3459,7 @@ static void __devinit get_pci_mode(struct adapter *adapter,
* Initializes the SW state maintained for each link, including the link's
* capabilities and default speed/flow-control/autonegotiation settings.
*/
-static void __devinit init_link_config(struct link_config *lc,
- unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int caps)
{
lc->supported = caps;
lc->requested_speed = 0;
@@ -3485,7 +3483,7 @@ int t4_wait_dev_ready(struct adapter *adap)
return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
}
-static int __devinit get_flash_params(struct adapter *adap)
+static int get_flash_params(struct adapter *adap)
{
int ret;
u32 info;
@@ -3521,7 +3519,7 @@ static int __devinit get_flash_params(struct adapter *adap)
* values for some adapter tunables, take PHYs out of reset, and
* initialize the MDIO interface.
*/
-int __devinit t4_prep_adapter(struct adapter *adapter)
+int t4_prep_adapter(struct adapter *adapter)
{
int ret;
@@ -3549,7 +3547,7 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
return 0;
}
-int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
+int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
{
u8 addr[6];
int ret, i, j = 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 9dad56101e23..0188df705719 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2023,7 +2023,7 @@ static struct cxgb4vf_debugfs_entry debugfs_files[] = {
* Set up out /sys/kernel/debug/cxgb4vf sub-nodes. We assume that the
* directory (debugfs_root) has already been set up.
*/
-static int __devinit setup_debugfs(struct adapter *adapter)
+static int setup_debugfs(struct adapter *adapter)
{
int i;
@@ -2064,7 +2064,7 @@ static void cleanup_debugfs(struct adapter *adapter)
* adapter parameters we're going to be using and initialize basic adapter
* hardware support.
*/
-static int __devinit adap_init0(struct adapter *adapter)
+static int adap_init0(struct adapter *adapter)
{
struct vf_resources *vfres = &adapter->params.vfres;
struct sge_params *sge_params = &adapter->params.sge;
@@ -2266,7 +2266,7 @@ static inline void init_rspq(struct sge_rspq *rspq, u8 timer_idx,
* be modified by the admin via ethtool and cxgbtool prior to the adapter
* being brought up for the first time.
*/
-static void __devinit cfg_queues(struct adapter *adapter)
+static void cfg_queues(struct adapter *adapter)
{
struct sge *s = &adapter->sge;
int q10g, n10g, qidx, pidx, qs;
@@ -2361,7 +2361,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
* Reduce the number of Ethernet queues across all ports to at most n.
* n provides at least one queue per port.
*/
-static void __devinit reduce_ethqs(struct adapter *adapter, int n)
+static void reduce_ethqs(struct adapter *adapter, int n)
{
int i;
struct port_info *pi;
@@ -2400,7 +2400,7 @@ static void __devinit reduce_ethqs(struct adapter *adapter, int n)
* for our "extras". Note that this process may lower the maximum number of
* allowed Queue Sets ...
*/
-static int __devinit enable_msix(struct adapter *adapter)
+static int enable_msix(struct adapter *adapter)
{
int i, err, want, need;
struct msix_entry entries[MSIX_ENTRIES];
@@ -2462,8 +2462,8 @@ static const struct net_device_ops cxgb4vf_netdev_ops = {
* state needed to manage the device. This routine is called "init_one" in
* the PF Driver ...
*/
-static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int cxgb4vf_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int version_printed;
@@ -2769,7 +2769,7 @@ err_disable_device:
* "probe" routine and quiesce the device (disable interrupts, etc.). (Note
* that this is called "remove_one" in the PF Driver.)
*/
-static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
+static void cxgb4vf_pci_remove(struct pci_dev *pdev)
{
struct adapter *adapter = pci_get_drvdata(pdev);
@@ -2835,7 +2835,7 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
* "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
* delivery.
*/
-static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
+static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
{
struct adapter *adapter;
int pidx;
@@ -2905,8 +2905,8 @@ static struct pci_driver cxgb4vf_driver = {
.name = KBUILD_MODNAME,
.id_table = cxgb4vf_pci_tbl,
.probe = cxgb4vf_pci_probe,
- .remove = __devexit_p(cxgb4vf_pci_remove),
- .shutdown = __devexit_p(cxgb4vf_pci_shutdown),
+ .remove = cxgb4vf_pci_remove,
+ .shutdown = cxgb4vf_pci_shutdown,
};
/*
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index a65c80aed1f2..283f9d0d37fd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -232,8 +232,8 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
}
-int __devinit t4vf_wait_dev_ready(struct adapter *);
-int __devinit t4vf_port_init(struct adapter *, int);
+int t4vf_wait_dev_ready(struct adapter *);
+int t4vf_port_init(struct adapter *, int);
int t4vf_fw_reset(struct adapter *);
int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index fe3fd3dad6f7..7127c7b9efde 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -46,7 +46,7 @@
* returning a value other than all 1's). Return an error if it doesn't
* become ready ...
*/
-int __devinit t4vf_wait_dev_ready(struct adapter *adapter)
+int t4vf_wait_dev_ready(struct adapter *adapter)
{
const u32 whoami = T4VF_PL_BASE_ADDR + PL_VF_WHOAMI;
const u32 notready1 = 0xffffffff;
@@ -253,8 +253,7 @@ static int hash_mac_addr(const u8 *addr)
* Initializes the SW state maintained for each link, including the link's
* capabilities and default speed/flow-control/autonegotiation settings.
*/
-static void __devinit init_link_config(struct link_config *lc,
- unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int caps)
{
lc->supported = caps;
lc->requested_speed = 0;
@@ -275,7 +274,7 @@ static void __devinit init_link_config(struct link_config *lc,
* @adapter: the adapter
* @pidx: the adapter port index
*/
-int __devinit t4vf_port_init(struct adapter *adapter, int pidx)
+int t4vf_port_init(struct adapter *adapter, int pidx)
{
struct port_info *pi = adap2pinfo(adapter, pidx);
struct fw_vi_cmd vi_cmd, vi_rpl;
diff --git a/drivers/net/ethernet/cisco/Kconfig b/drivers/net/ethernet/cisco/Kconfig
index 94606f7ee13a..1c7b884e3371 100644
--- a/drivers/net/ethernet/cisco/Kconfig
+++ b/drivers/net/ethernet/cisco/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_CISCO
bool "Cisco devices"
default y
- depends on PCI && INET
+ depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/cisco/enic/Kconfig b/drivers/net/ethernet/cisco/enic/Kconfig
index 9cc706a6cffd..b63f8d8a4261 100644
--- a/drivers/net/ethernet/cisco/enic/Kconfig
+++ b/drivers/net/ethernet/cisco/enic/Kconfig
@@ -4,6 +4,6 @@
config ENIC
tristate "Cisco VIC Ethernet NIC Support"
- depends on PCI && INET
+ depends on PCI
---help---
This enables the support for the Cisco VIC Ethernet card.
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index ad1468b3ab91..64866ff1aea0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2275,8 +2275,7 @@ static void enic_iounmap(struct enic *enic)
iounmap(enic->bar[i].vaddr);
}
-static int __devinit enic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
struct net_device *netdev;
@@ -2552,7 +2551,7 @@ err_out_free_netdev:
return err;
}
-static void __devexit enic_remove(struct pci_dev *pdev)
+static void enic_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -2584,7 +2583,7 @@ static struct pci_driver enic_driver = {
.name = DRV_NAME,
.id_table = enic_id_table,
.probe = enic_probe,
- .remove = __devexit_p(enic_remove),
+ .remove = enic_remove,
};
static int __init enic_init_module(void)
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 36499d5edd95..c73472c369cd 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -193,35 +193,35 @@ iow(board_info_t * db, int reg, int value)
static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
{
- writesb(reg, data, count);
+ iowrite8_rep(reg, data, count);
}
static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
{
- writesw(reg, data, (count+1) >> 1);
+ iowrite16_rep(reg, data, (count+1) >> 1);
}
static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
{
- writesl(reg, data, (count+3) >> 2);
+ iowrite32_rep(reg, data, (count+3) >> 2);
}
/* input block from chip to memory */
static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
{
- readsb(reg, data, count);
+ ioread8_rep(reg, data, count);
}
static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
{
- readsw(reg, data, (count+1) >> 1);
+ ioread16_rep(reg, data, (count+1) >> 1);
}
static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
{
- readsl(reg, data, (count+3) >> 2);
+ ioread32_rep(reg, data, (count+3) >> 2);
}
/* dump block from chip to null */
@@ -1359,7 +1359,7 @@ static const struct net_device_ops dm9000_netdev_ops = {
/*
* Search DM9000 board, allocate space and register it
*/
-static int __devinit
+static int
dm9000_probe(struct platform_device *pdev)
{
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
@@ -1661,7 +1661,7 @@ static const struct dev_pm_ops dm9000_drv_pm_ops = {
.resume = dm9000_drv_resume,
};
-static int __devexit
+static int
dm9000_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1683,7 +1683,7 @@ static struct platform_driver dm9000_driver = {
.pm = &dm9000_drv_pm_ops,
},
.probe = dm9000_probe,
- .remove = __devexit_p(dm9000_drv_remove),
+ .remove = dm9000_drv_remove,
};
static int __init
diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c
index 17ae8c619680..9f992b95eddc 100644
--- a/drivers/net/ethernet/dec/ewrk3.c
+++ b/drivers/net/ethernet/dec/ewrk3.c
@@ -1910,9 +1910,8 @@ static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];
static int ndevs;
static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
-/* '21' below should really be 'MAX_NUM_EWRK3S' */
module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_array(irq, byte, NULL, 0);
MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 77335853ac36..eaab73cf27ca 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1700,7 +1700,7 @@ static const struct ethtool_ops de_ethtool_ops = {
.get_regs = de_get_regs,
};
-static void __devinit de21040_get_mac_address (struct de_private *de)
+static void de21040_get_mac_address(struct de_private *de)
{
unsigned i;
@@ -1721,7 +1721,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
}
}
-static void __devinit de21040_get_media_info(struct de_private *de)
+static void de21040_get_media_info(struct de_private *de)
{
unsigned int i;
@@ -1748,7 +1748,8 @@ static void __devinit de21040_get_media_info(struct de_private *de)
}
/* Note: this routine returns extra data bits for size detection. */
-static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len)
+static unsigned tulip_read_eeprom(void __iomem *regs, int location,
+ int addr_len)
{
int i;
unsigned retval = 0;
@@ -1783,7 +1784,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in
return retval;
}
-static void __devinit de21041_get_srom_info (struct de_private *de)
+static void de21041_get_srom_info(struct de_private *de)
{
unsigned i, sa_offset = 0, ofs;
u8 ee_data[DE_EEPROM_SIZE + 6] = {};
@@ -1961,8 +1962,7 @@ static const struct net_device_ops de_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit de_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int de_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct de_private *de;
@@ -2099,7 +2099,7 @@ err_out_free:
return rc;
}
-static void __devexit de_remove_one (struct pci_dev *pdev)
+static void de_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct de_private *de = netdev_priv(dev);
@@ -2184,7 +2184,7 @@ static struct pci_driver de_driver = {
.name = DRV_NAME,
.id_table = de_pci_tbl,
.probe = de_init_one,
- .remove = __devexit_p(de_remove_one),
+ .remove = de_remove_one,
#ifdef CONFIG_PM
.suspend = de_suspend,
.resume = de_resume,
diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index f879e9224846..4c830030fb06 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -479,7 +479,7 @@
#include "de4x5.h"
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
#define c_char const char
@@ -1092,7 +1092,7 @@ static const struct net_device_ops de4x5_netdev_ops = {
};
-static int __devinit
+static int
de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
{
char name[DE4X5_NAME_LENGTH + 1];
@@ -2077,7 +2077,7 @@ static int __init de4x5_eisa_probe (struct device *gendev)
return status;
}
-static int __devexit de4x5_eisa_remove (struct device *device)
+static int de4x5_eisa_remove(struct device *device)
{
struct net_device *dev;
u_long iobase;
@@ -2104,7 +2104,7 @@ static struct eisa_driver de4x5_eisa_driver = {
.driver = {
.name = "de4x5",
.probe = de4x5_eisa_probe,
- .remove = __devexit_p (de4x5_eisa_remove),
+ .remove = de4x5_eisa_remove,
}
};
MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
@@ -2118,7 +2118,7 @@ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
** For single port cards this is a time waster...
*/
-static void __devinit
+static void
srom_search(struct net_device *dev, struct pci_dev *pdev)
{
u_char pb;
@@ -2192,8 +2192,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
** kernels use the V0.535[n] drivers.
*/
-static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int de4x5_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
u_char pb, pbus = 0, dev_num, dnum = 0, timer;
u_short vendor, status;
@@ -2314,7 +2314,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
return error;
}
-static void __devexit de4x5_pci_remove (struct pci_dev *pdev)
+static void de4x5_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev;
u_long iobase;
@@ -2344,7 +2344,7 @@ static struct pci_driver de4x5_pci_driver = {
.name = "de4x5",
.id_table = de4x5_pci_tbl,
.probe = de4x5_pci_probe,
- .remove = __devexit_p (de4x5_pci_remove),
+ .remove = de4x5_pci_remove,
};
#endif
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index d23755ea9bc7..83139307861c 100644
--- a/drivers/net/ethernet/dec/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -291,8 +291,8 @@ enum dmfe_CR6_bits {
};
/* Global variable declaration ----------------------------- */
-static int __devinitdata printed_version;
-static const char version[] __devinitconst =
+static int printed_version;
+static const char version[] =
"Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
static int dmfe_debug;
@@ -367,8 +367,7 @@ static const struct net_device_ops netdev_ops = {
* Search DM910X board ,allocate space and register it
*/
-static int __devinit dmfe_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int dmfe_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct dmfe_board_info *db; /* board information structure */
struct net_device *dev;
@@ -531,7 +530,7 @@ err_out_free:
}
-static void __devexit dmfe_remove_one (struct pci_dev *pdev)
+static void dmfe_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct dmfe_board_info *db = netdev_priv(dev);
@@ -2187,7 +2186,7 @@ static struct pci_driver dmfe_driver = {
.name = "dmfe",
.id_table = dmfe_pci_tbl,
.probe = dmfe_init_one,
- .remove = __devexit_p(dmfe_remove_one),
+ .remove = dmfe_remove_one,
.suspend = dmfe_suspend,
.resume = dmfe_resume
};
diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
index 44f7e8e82d85..df5a892fb49c 100644
--- a/drivers/net/ethernet/dec/tulip/eeprom.c
+++ b/drivers/net/ethernet/dec/tulip/eeprom.c
@@ -26,7 +26,7 @@
*/
/* Known cards that have old-style EEPROMs. */
-static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
+static struct eeprom_fixup eeprom_fixups[] = {
{"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
{"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
@@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
{NULL}};
-static const char *const block_name[] __devinitconst = {
+static const char *const block_name[] = {
"21140 non-MII",
"21140 MII PHY",
"21142 Serial PHY",
@@ -102,7 +102,7 @@ static const char *const block_name[] __devinitconst = {
* #ifdef __hppa__ should completely optimize this function away for
* non-parisc hardware.
*/
-static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
+static void tulip_build_fake_mediatable(struct tulip_private *tp)
{
#ifdef CONFIG_GSC
if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
@@ -140,7 +140,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
#endif
}
-void __devinit tulip_parse_eeprom(struct net_device *dev)
+void tulip_parse_eeprom(struct net_device *dev)
{
/*
dev is not registered at this point, so logging messages can't
@@ -339,7 +339,7 @@ subsequent_board:
#define EE_READ_CMD (6)
/* Note: this routine returns extra data bits for size detection. */
-int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
+int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
{
int i;
unsigned retval = 0;
diff --git a/drivers/net/ethernet/dec/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c
index ae937c6749e7..93a4afaa09f1 100644
--- a/drivers/net/ethernet/dec/tulip/media.c
+++ b/drivers/net/ethernet/dec/tulip/media.c
@@ -447,7 +447,7 @@ int tulip_check_duplex(struct net_device *dev)
return 0;
}
-void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
+void tulip_find_mii(struct net_device *dev, int board_idx)
{
struct tulip_private *tp = netdev_priv(dev);
int phyn, phy_idx = 0;
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 885700a19978..1e9443d9fb57 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -37,7 +37,7 @@
#include <asm/prom.h>
#endif
-static char version[] __devinitdata =
+static char version[] =
"Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
/* A few user-configurable values. */
@@ -1191,8 +1191,7 @@ static void set_rx_mode(struct net_device *dev)
}
#ifdef CONFIG_TULIP_MWI
-static void __devinit tulip_mwi_config (struct pci_dev *pdev,
- struct net_device *dev)
+static void tulip_mwi_config(struct pci_dev *pdev, struct net_device *dev)
{
struct tulip_private *tp = netdev_priv(dev);
u8 cache;
@@ -1301,8 +1300,7 @@ DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
{ },
};
-static int __devinit tulip_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct tulip_private *tp;
/* See note below on the multiport cards. */
@@ -1927,7 +1925,7 @@ static int tulip_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
-static void __devexit tulip_remove_one (struct pci_dev *pdev)
+static void tulip_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct tulip_private *tp;
@@ -1974,7 +1972,7 @@ static struct pci_driver tulip_driver = {
.name = DRV_NAME,
.id_table = tulip_pci_tbl,
.probe = tulip_init_one,
- .remove = __devexit_p(tulip_remove_one),
+ .remove = tulip_remove_one,
#ifdef CONFIG_PM
.suspend = tulip_suspend,
.resume = tulip_resume,
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index 75d45f8a37dc..93845afe1cea 100644
--- a/drivers/net/ethernet/dec/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -204,8 +204,8 @@ enum uli526x_CR6_bits {
};
/* Global variable declaration ----------------------------- */
-static int __devinitdata printed_version;
-static const char version[] __devinitconst =
+static int printed_version;
+static const char version[] =
"ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
static int uli526x_debug;
@@ -281,8 +281,8 @@ static const struct net_device_ops netdev_ops = {
* Search ULI526X board, allocate space and register it
*/
-static int __devinit uli526x_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int uli526x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct uli526x_board_info *db; /* board information structure */
struct net_device *dev;
@@ -436,7 +436,7 @@ err_out_free:
}
-static void __devexit uli526x_remove_one (struct pci_dev *pdev)
+static void uli526x_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct uli526x_board_info *db = netdev_priv(dev);
@@ -1788,7 +1788,7 @@ static struct pci_driver uli526x_driver = {
.name = "uli526x",
.id_table = uli526x_pci_tbl,
.probe = uli526x_init_one,
- .remove = __devexit_p(uli526x_remove_one),
+ .remove = uli526x_remove_one,
.suspend = uli526x_suspend,
.resume = uli526x_resume,
};
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 7c1ec4d7920b..c7b04ecf5b49 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -236,7 +236,7 @@ struct pci_id_info {
int drv_flags; /* Driver use, intended as capability flags. */
};
-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
+static const struct pci_id_info pci_id_tbl[] = {
{ /* Sometime a Level-One switch card. */
"Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII},
{ "Winbond W89c840", CanHaveMII | HasBrokenTx},
@@ -358,8 +358,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit w840_probe1 (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int w840_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct netdev_private *np;
@@ -1532,7 +1531,7 @@ static int netdev_close(struct net_device *dev)
return 0;
}
-static void __devexit w840_remove1 (struct pci_dev *pdev)
+static void w840_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -1647,7 +1646,7 @@ static struct pci_driver w840_driver = {
.name = DRV_NAME,
.id_table = w840_pci_tbl,
.probe = w840_probe1,
- .remove = __devexit_p(w840_remove1),
+ .remove = w840_remove1,
#ifdef CONFIG_PM
.suspend = w840_suspend,
.resume = w840_resume,
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 138bf83bc98e..88feced9a629 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -148,7 +148,7 @@ static struct pci_driver xircom_ops = {
.name = "xircom_cb",
.id_table = xircom_pci_table,
.probe = xircom_probe,
- .remove = __devexit_p(xircom_remove),
+ .remove = xircom_remove,
};
@@ -190,7 +190,7 @@ static const struct net_device_ops netdev_ops = {
first two packets that get send, and pump hates that.
*/
-static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *d = &pdev->dev;
struct net_device *dev = NULL;
@@ -312,7 +312,7 @@ err_disable:
Interrupts and such are already stopped in the "ifconfig ethX down"
code.
*/
-static void __devexit xircom_remove(struct pci_dev *pdev)
+static void xircom_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct xircom_private *card = netdev_priv(dev);
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index a059f0c27e28..1d342d37915c 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -23,7 +23,7 @@
#define dr16(reg) ioread16(ioaddr + (reg))
#define dr8(reg) ioread8(ioaddr + (reg))
-static char version[] __devinitdata =
+static char version[] =
KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
#define MAX_UNITS 8
static int mtu[MAX_UNITS];
@@ -110,7 +110,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_change_mtu = change_mtu,
};
-static int __devinit
+static int
rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
@@ -1727,7 +1727,7 @@ rio_close (struct net_device *dev)
return 0;
}
-static void __devexit
+static void
rio_remove1 (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
@@ -1755,24 +1755,10 @@ static struct pci_driver rio_driver = {
.name = "dl2k",
.id_table = rio_pci_tbl,
.probe = rio_probe1,
- .remove = __devexit_p(rio_remove1),
+ .remove = rio_remove1,
};
-static int __init
-rio_init (void)
-{
- return pci_register_driver(&rio_driver);
-}
-
-static void __exit
-rio_exit (void)
-{
- pci_unregister_driver (&rio_driver);
-}
-
-module_init (rio_init);
-module_exit (rio_exit);
-
+module_pci_driver(rio_driver);
/*
Compile command:
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 3b83588e51f6..28fc11b2f1ea 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -102,7 +102,7 @@ static char *media[MAX_UNITS];
#include <linux/mii.h>
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
" Written by Donald Becker\n";
@@ -218,7 +218,7 @@ enum {
struct pci_id_info {
const char *name;
};
-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
+static const struct pci_id_info pci_id_tbl[] = {
{"D-Link DFE-550TX FAST Ethernet Adapter"},
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
{"D-Link DFE-580TX 4 port Server Adapter"},
@@ -259,6 +259,7 @@ enum alta_offsets {
EECtrl = 0x36,
FlashAddr = 0x40,
FlashData = 0x44,
+ WakeEvent = 0x45,
TxStatus = 0x46,
TxFrameId = 0x47,
DownCounter = 0x18,
@@ -333,6 +334,14 @@ enum mac_ctrl1_bits {
RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000,
};
+/* Bits in WakeEvent register. */
+enum wake_event_bits {
+ WakePktEnable = 0x01,
+ MagicPktEnable = 0x02,
+ LinkEventEnable = 0x04,
+ WolEnable = 0x80,
+};
+
/* The Rx and Tx buffer descriptors. */
/* Note that using only 32 bit fields simplifies conversion to big-endian
architectures. */
@@ -392,6 +401,7 @@ struct netdev_private {
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int an_enable:1;
unsigned int speed;
+ unsigned int wol_enabled:1; /* Wake on LAN enabled */
struct tasklet_struct rx_tasklet;
struct tasklet_struct tx_tasklet;
int budget;
@@ -472,8 +482,8 @@ static const struct net_device_ops netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit sundance_probe1 (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int sundance_probe1(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
struct netdev_private *np;
@@ -701,7 +711,7 @@ static int change_mtu(struct net_device *dev, int new_mtu)
#define eeprom_delay(ee_addr) ioread32(ee_addr)
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
-static int __devinit eeprom_read(void __iomem *ioaddr, int location)
+static int eeprom_read(void __iomem *ioaddr, int location)
{
int boguscnt = 10000; /* Typical 1900 ticks. */
iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl);
@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev)
unsigned long flags;
int i;
- /* Do we need to reset the chip??? */
+ sundance_reset(dev, 0x00ff << 16);
i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (i)
@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev)
iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
+ /* Disable Wol */
+ iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent);
+ np->wol_enabled = 0;
+
if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
"MAC Control %x, %4.4x %4.4x.\n",
@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev,
data[i++] = np->xstats.rx_mcasts;
}
+#ifdef CONFIG_PM
+
+static void sundance_get_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->base;
+ u8 wol_bits;
+
+ wol->wolopts = 0;
+
+ wol->supported = (WAKE_PHY | WAKE_MAGIC);
+ if (!np->wol_enabled)
+ return;
+
+ wol_bits = ioread8(ioaddr + WakeEvent);
+ if (wol_bits & MagicPktEnable)
+ wol->wolopts |= WAKE_MAGIC;
+ if (wol_bits & LinkEventEnable)
+ wol->wolopts |= WAKE_PHY;
+}
+
+static int sundance_set_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->base;
+ u8 wol_bits;
+
+ if (!device_can_wakeup(&np->pci_dev->dev))
+ return -EOPNOTSUPP;
+
+ np->wol_enabled = !!(wol->wolopts);
+ wol_bits = ioread8(ioaddr + WakeEvent);
+ wol_bits &= ~(WakePktEnable | MagicPktEnable |
+ LinkEventEnable | WolEnable);
+
+ if (np->wol_enabled) {
+ if (wol->wolopts & WAKE_MAGIC)
+ wol_bits |= (MagicPktEnable | WolEnable);
+ if (wol->wolopts & WAKE_PHY)
+ wol_bits |= (LinkEventEnable | WolEnable);
+ }
+ iowrite8(wol_bits, ioaddr + WakeEvent);
+
+ device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled);
+
+ return 0;
+}
+#else
+#define sundance_get_wol NULL
+#define sundance_set_wol NULL
+#endif /* CONFIG_PM */
+
static const struct ethtool_ops ethtool_ops = {
.begin = check_if_running,
.get_drvinfo = get_drvinfo,
@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = {
.set_settings = set_settings,
.nway_reset = nway_reset,
.get_link = get_link,
+ .get_wol = sundance_get_wol,
+ .set_wol = sundance_set_wol,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
.get_strings = get_strings,
@@ -1844,7 +1914,7 @@ static int netdev_close(struct net_device *dev)
return 0;
}
-static void __devexit sundance_remove1 (struct pci_dev *pdev)
+static void sundance_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev)
static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->base;
if (!netif_running(dev))
return 0;
@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
netif_device_detach(dev);
pci_save_state(pci_dev);
+ if (np->wol_enabled) {
+ iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
+ iowrite16(RxEnable, ioaddr + MACCtrl1);
+ }
+ pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state),
+ np->wol_enabled);
pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
return 0;
@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev)
pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
+ pci_enable_wake(pci_dev, PCI_D0, 0);
err = netdev_open(dev);
if (err) {
@@ -1910,7 +1989,7 @@ static struct pci_driver sundance_driver = {
.name = DRV_NAME,
.id_table = sundance_pci_tbl,
.probe = sundance_probe1,
- .remove = __devexit_p(sundance_remove1),
+ .remove = sundance_remove1,
#ifdef CONFIG_PM
.suspend = sundance_suspend,
.resume = sundance_resume,
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 290b26f868c9..2c177b329c8b 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -72,7 +72,7 @@ static void __dnet_set_hwaddr(struct dnet *bp)
dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
}
-static void __devinit dnet_get_hwaddr(struct dnet *bp)
+static void dnet_get_hwaddr(struct dnet *bp)
{
u16 tmp;
u8 addr[6];
@@ -664,9 +664,6 @@ static int dnet_open(struct net_device *dev)
if (!bp->phy_dev)
return -EAGAIN;
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EADDRNOTAVAIL;
-
napi_enable(&bp->napi);
dnet_init_hw(bp);
@@ -829,7 +826,7 @@ static const struct net_device_ops dnet_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit dnet_probe(struct platform_device *pdev)
+static int dnet_probe(struct platform_device *pdev)
{
struct resource *res;
struct net_device *dev;
@@ -945,7 +942,7 @@ err_out:
return err;
}
-static int __devexit dnet_remove(struct platform_device *pdev)
+static int dnet_remove(struct platform_device *pdev)
{
struct net_device *dev;
@@ -971,7 +968,7 @@ static int __devexit dnet_remove(struct platform_device *pdev)
static struct platform_driver dnet_driver = {
.probe = dnet_probe,
- .remove = __devexit_p(dnet_remove),
+ .remove = dnet_remove,
.driver = {
.name = "dnet",
},
diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig
index 7a28a6433944..1b8d638c6cb1 100644
--- a/drivers/net/ethernet/emulex/Kconfig
+++ b/drivers/net/ethernet/emulex/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_EMULEX
bool "Emulex devices"
default y
- depends on PCI && INET
+ depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig
index 804db04a2bd0..231129dd1764 100644
--- a/drivers/net/ethernet/emulex/benet/Kconfig
+++ b/drivers/net/ethernet/emulex/benet/Kconfig
@@ -1,6 +1,6 @@
config BE2NET
tristate "ServerEngines' 10Gbps NIC - BladeEngine"
- depends on PCI && INET
+ depends on PCI
---help---
This driver implements the NIC functionality for ServerEngines'
10Gbps network adapter - BladeEngine.
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index cf4c05bdf5fe..abf26c7c1d19 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -34,7 +34,7 @@
#include "be_hw.h"
#include "be_roce.h"
-#define DRV_VER "4.4.31.0u"
+#define DRV_VER "4.4.161.0u"
#define DRV_NAME "be2net"
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
@@ -53,6 +53,7 @@
#define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */
#define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */
#define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */
+#define OC_DEVICE_ID6 0x728 /* Device id for VF in SkyHawk */
#define OC_SUBSYS_DEVICE_ID1 0xE602
#define OC_SUBSYS_DEVICE_ID2 0xE642
#define OC_SUBSYS_DEVICE_ID3 0xE612
@@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev)
case BE_DEVICE_ID2:
return BE3_NAME;
case OC_DEVICE_ID5:
+ case OC_DEVICE_ID6:
return OC_NAME_SH;
default:
return BE_NAME;
@@ -346,7 +348,6 @@ struct be_adapter {
struct pci_dev *pdev;
struct net_device *netdev;
- u8 __iomem *csr;
u8 __iomem *db; /* Door Bell */
struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
@@ -374,11 +375,8 @@ struct be_adapter {
struct be_rx_obj rx_obj[MAX_RX_QS];
u32 big_page_size; /* Compounded page size shared by rx wrbs */
- u8 eq_next_idx;
struct be_drv_stats drv_stats;
-
u16 vlans_added;
- u16 max_vlans; /* Number of vlans supported */
u8 vlan_tag[VLAN_N_VID];
u8 vlan_prio_bmap; /* Available Priority BitMap */
u16 recommended_prio; /* Recommended Priority */
@@ -391,6 +389,7 @@ struct be_adapter {
struct delayed_work func_recovery_work;
u32 flags;
+ u32 cmd_privileges;
/* Ethtool knobs and info */
char fw_ver[FW_VER_LEN];
int if_handle; /* Used to configure filtering */
@@ -408,10 +407,8 @@ struct be_adapter {
u32 rx_fc; /* Rx flow control */
u32 tx_fc; /* Tx flow control */
bool stats_cmd_sent;
- u8 generation; /* BladeEngine ASIC generation */
u32 if_type;
struct {
- u8 __iomem *base; /* Door Bell */
u32 size;
u32 total_size;
u64 io_addr;
@@ -434,10 +431,18 @@ struct be_adapter {
struct phy_info phy;
u8 wol_cap;
bool wol;
- u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
u32 uc_macs; /* Count of secondary UC MAC programmed */
u32 msg_enable;
int be_get_temp_freq;
+ u16 max_mcast_mac;
+ u16 max_tx_queues;
+ u16 max_rss_queues;
+ u16 max_rx_queues;
+ u16 max_pmac_cnt;
+ u16 max_vlans;
+ u16 max_event_queues;
+ u32 if_cap_flags;
+ u8 pf_number;
};
#define be_physfn(adapter) (!adapter->virtfn)
@@ -448,21 +453,25 @@ struct be_adapter {
for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
i++, vf_cfg++)
-/* BladeEngine Generation numbers */
-#define BE_GEN2 2
-#define BE_GEN3 3
-
#define ON 1
#define OFF 0
-#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \
- (adapter->pdev->device == OC_DEVICE_ID4))
-#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5)
+#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3 || \
+ adapter->pdev->device == OC_DEVICE_ID4)
+
+#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5 || \
+ adapter->pdev->device == OC_DEVICE_ID6)
+
+#define BE3_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID2 || \
+ adapter->pdev->device == OC_DEVICE_ID2)
+#define BE2_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID1 || \
+ adapter->pdev->device == OC_DEVICE_ID1)
-#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
- adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
- (adapter->function_mode & RDMA_ENABLED))
+#define BEx_chip(adapter) (BE3_chip(adapter) || BE2_chip(adapter))
+
+#define be_roce_supported(adapter) (skyhawk_chip(adapter) && \
+ (adapter->function_mode & RDMA_ENABLED))
extern const struct ethtool_ops be_ethtool_ops;
@@ -637,12 +646,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
}
}
-static inline bool be_type_2_3(struct be_adapter *adapter)
-{
- return (adapter->if_type == SLI_INTF_TYPE_2 ||
- adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
-}
-
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index af60bb26e330..f2875aa47661 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -19,6 +19,55 @@
#include "be.h"
#include "be_cmds.h"
+static struct be_cmd_priv_map cmd_priv_map[] = {
+ {
+ OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+ CMD_SUBSYSTEM_ETH,
+ BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+ BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+ },
+ {
+ OPCODE_COMMON_GET_FLOW_CONTROL,
+ CMD_SUBSYSTEM_COMMON,
+ BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
+ BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+ },
+ {
+ OPCODE_COMMON_SET_FLOW_CONTROL,
+ CMD_SUBSYSTEM_COMMON,
+ BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+ BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+ },
+ {
+ OPCODE_ETH_GET_PPORT_STATS,
+ CMD_SUBSYSTEM_ETH,
+ BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+ BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+ },
+ {
+ OPCODE_COMMON_GET_PHY_DETAILS,
+ CMD_SUBSYSTEM_COMMON,
+ BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+ BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+ }
+};
+
+static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode,
+ u8 subsystem)
+{
+ int i;
+ int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
+ u32 cmd_privileges = adapter->cmd_privileges;
+
+ for (i = 0; i < num_entries; i++)
+ if (opcode == cmd_priv_map[i].opcode &&
+ subsystem == cmd_priv_map[i].subsystem)
+ if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
+ return false;
+
+ return true;
+}
+
static inline void *embedded_payload(struct be_mcc_wrb *wrb)
{
return wrb->payload.embedded_payload;
@@ -419,14 +468,13 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
{
u32 sem;
+ u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH :
+ SLIPORT_SEMAPHORE_OFFSET_BE;
- if (lancer_chip(adapter))
- sem = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
- else
- sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
+ pci_read_config_dword(adapter->pdev, reg, &sem);
+ *stage = sem & POST_STAGE_MASK;
- *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
- if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
+ if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK)
return -1;
else
return 0;
@@ -452,10 +500,33 @@ int lancer_wait_ready(struct be_adapter *adapter)
return status;
}
+static bool lancer_provisioning_error(struct be_adapter *adapter)
+{
+ u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
+ sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+ if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
+ sliport_err1 = ioread32(adapter->db +
+ SLIPORT_ERROR1_OFFSET);
+ sliport_err2 = ioread32(adapter->db +
+ SLIPORT_ERROR2_OFFSET);
+
+ if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 &&
+ sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2)
+ return true;
+ }
+ return false;
+}
+
int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
{
int status;
u32 sliport_status, err, reset_needed;
+ bool resource_error;
+
+ resource_error = lancer_provisioning_error(adapter);
+ if (resource_error)
+ return -1;
+
status = lancer_wait_ready(adapter);
if (!status) {
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
@@ -477,6 +548,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
status = -1;
}
}
+ /* Stop error recovery if error is not recoverable.
+ * No resource error is temporary errors and will go away
+ * when PF provisions resources.
+ */
+ resource_error = lancer_provisioning_error(adapter);
+ if (status == -1 && !resource_error)
+ adapter->eeh_error = true;
+
return status;
}
@@ -601,6 +680,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
struct be_queue_info *mccq = &adapter->mcc_obj.q;
struct be_mcc_wrb *wrb;
+ if (!mccq->created)
+ return NULL;
+
if (atomic_read(&mccq->used) >= mccq->len) {
dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
return NULL;
@@ -1155,8 +1237,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
req->id = cpu_to_le16(q->id);
status = be_mbox_notify_wait(adapter);
- if (!status)
- q->created = false;
+ q->created = false;
mutex_unlock(&adapter->mbox_lock);
return status;
@@ -1183,8 +1264,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
req->id = cpu_to_le16(q->id);
status = be_mcc_notify_wait(adapter);
- if (!status)
- q->created = false;
+ q->created = false;
err:
spin_unlock_bh(&adapter->mcc_lock);
@@ -1281,7 +1361,8 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd);
- if (adapter->generation == BE_GEN3)
+ /* version 1 of the cmd is not supported only by BE2 */
+ if (!BE2_chip(adapter))
hdr->version = 1;
be_mcc_notify(adapter);
@@ -1301,6 +1382,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
struct lancer_cmd_req_pport_stats *req;
int status = 0;
+ if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
+ CMD_SUBSYSTEM_ETH))
+ return -EPERM;
+
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
@@ -1367,7 +1452,8 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
- if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
+ /* version 1 of the cmd is not supported only by BE2 */
+ if (!BE2_chip(adapter))
req->hdr.version = 1;
req->hdr.domain = dom;
@@ -1658,9 +1744,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
/* Reset mcast promisc mode if already set by setting mask
* and not setting flags field
*/
- if (!lancer_chip(adapter) || be_physfn(adapter))
- req->if_flags_mask |=
- cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+ req->if_flags_mask |=
+ cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
+ adapter->if_cap_flags);
req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
netdev_for_each_mc_addr(ha, adapter->netdev)
@@ -1680,6 +1766,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
struct be_cmd_req_set_flow_control *req;
int status;
+ if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
+ CMD_SUBSYSTEM_COMMON))
+ return -EPERM;
+
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
@@ -1709,6 +1799,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
struct be_cmd_req_get_flow_control *req;
int status;
+ if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
+ CMD_SUBSYSTEM_COMMON))
+ return -EPERM;
+
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
@@ -2067,7 +2161,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
int offset)
{
struct be_mcc_wrb *wrb;
- struct be_cmd_write_flashrom *req;
+ struct be_cmd_read_flash_crc *req;
int status;
spin_lock_bh(&adapter->mcc_lock);
@@ -2080,7 +2174,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
req = embedded_payload(wrb);
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
+ OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
+ wrb, NULL);
req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
@@ -2089,7 +2184,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
status = be_mcc_notify_wait(adapter);
if (!status)
- memcpy(flashed_crc, req->params.data_buf, 4);
+ memcpy(flashed_crc, req->crc, 4);
err:
spin_unlock_bh(&adapter->mcc_lock);
@@ -2275,6 +2370,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
struct be_dma_mem cmd;
int status;
+ if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
+ CMD_SUBSYSTEM_COMMON))
+ return -EPERM;
+
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
@@ -2434,6 +2533,42 @@ err:
return status;
}
+/* Get privilege(s) for a function */
+int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
+ u32 domain)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_fn_privileges *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
+ wrb, NULL);
+
+ req->hdr.domain = domain;
+
+ status = be_mcc_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_get_fn_privileges *resp =
+ embedded_payload(wrb);
+ *privilege = le32_to_cpu(resp->privilege_mask);
+ }
+
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
/* Uses synchronous MCCQ */
int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
bool *pmac_id_active, u32 *pmac_id, u8 domain)
@@ -2651,6 +2786,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
int payload_len = sizeof(*req);
struct be_dma_mem cmd;
+ if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+ CMD_SUBSYSTEM_ETH))
+ return -EPERM;
+
memset(&cmd, 0, sizeof(struct be_dma_mem));
cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
@@ -2792,6 +2931,240 @@ err:
return status;
}
+static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+ u32 max_buf_size)
+{
+ struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf;
+ int i;
+
+ for (i = 0; i < desc_count; i++) {
+ desc->desc_len = RESOURCE_DESC_SIZE;
+ if (((void *)desc + desc->desc_len) >
+ (void *)(buf + max_buf_size)) {
+ desc = NULL;
+ break;
+ }
+
+ if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID)
+ break;
+
+ desc = (void *)desc + desc->desc_len;
+ }
+
+ if (!desc || i == MAX_RESOURCE_DESC)
+ return NULL;
+
+ return desc;
+}
+
+/* Uses Mbox */
+int be_cmd_get_func_config(struct be_adapter *adapter)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_func_config *req;
+ int status;
+ struct be_dma_mem cmd;
+
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
+ cmd.size = sizeof(struct be_cmd_resp_get_func_config);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+ &cmd.dma);
+ if (!cmd.va) {
+ dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+ return -ENOMEM;
+ }
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd.va;
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_FUNC_CONFIG,
+ cmd.size, wrb, &cmd);
+
+ status = be_mbox_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_get_func_config *resp = cmd.va;
+ u32 desc_count = le32_to_cpu(resp->desc_count);
+ struct be_nic_resource_desc *desc;
+
+ desc = be_get_nic_desc(resp->func_param, desc_count,
+ sizeof(resp->func_param));
+ if (!desc) {
+ status = -EINVAL;
+ goto err;
+ }
+
+ adapter->pf_number = desc->pf_num;
+ adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count);
+ adapter->max_vlans = le16_to_cpu(desc->vlan_count);
+ adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
+ adapter->max_tx_queues = le16_to_cpu(desc->txq_count);
+ adapter->max_rss_queues = le16_to_cpu(desc->rssq_count);
+ adapter->max_rx_queues = le16_to_cpu(desc->rq_count);
+
+ adapter->max_event_queues = le16_to_cpu(desc->eq_count);
+ adapter->if_cap_flags = le32_to_cpu(desc->cap_flags);
+ }
+err:
+ mutex_unlock(&adapter->mbox_lock);
+ pci_free_consistent(adapter->pdev, cmd.size,
+ cmd.va, cmd.dma);
+ return status;
+}
+
+ /* Uses sync mcc */
+int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+ u8 domain)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_profile_config *req;
+ int status;
+ struct be_dma_mem cmd;
+
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
+ cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+ &cmd.dma);
+ if (!cmd.va) {
+ dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd.va;
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_PROFILE_CONFIG,
+ cmd.size, wrb, &cmd);
+
+ req->type = ACTIVE_PROFILE_TYPE;
+ req->hdr.domain = domain;
+
+ status = be_mcc_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_get_profile_config *resp = cmd.va;
+ u32 desc_count = le32_to_cpu(resp->desc_count);
+ struct be_nic_resource_desc *desc;
+
+ desc = be_get_nic_desc(resp->func_param, desc_count,
+ sizeof(resp->func_param));
+
+ if (!desc) {
+ status = -EINVAL;
+ goto err;
+ }
+ *cap_flags = le32_to_cpu(desc->cap_flags);
+ }
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ pci_free_consistent(adapter->pdev, cmd.size,
+ cmd.va, cmd.dma);
+ return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+ u8 domain)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_set_profile_config *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
+ wrb, NULL);
+
+ req->hdr.domain = domain;
+ req->desc_count = cpu_to_le32(1);
+
+ req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID;
+ req->nic_desc.desc_len = RESOURCE_DESC_SIZE;
+ req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
+ req->nic_desc.pf_num = adapter->pf_number;
+ req->nic_desc.vf_num = domain;
+
+ /* Mark fields invalid */
+ req->nic_desc.unicast_mac_count = 0xFFFF;
+ req->nic_desc.mcc_count = 0xFFFF;
+ req->nic_desc.vlan_count = 0xFFFF;
+ req->nic_desc.mcast_mac_count = 0xFFFF;
+ req->nic_desc.txq_count = 0xFFFF;
+ req->nic_desc.rq_count = 0xFFFF;
+ req->nic_desc.rssq_count = 0xFFFF;
+ req->nic_desc.lro_count = 0xFFFF;
+ req->nic_desc.cq_count = 0xFFFF;
+ req->nic_desc.toe_conn_count = 0xFFFF;
+ req->nic_desc.eq_count = 0xFFFF;
+ req->nic_desc.link_param = 0xFF;
+ req->nic_desc.bw_min = 0xFFFFFFFF;
+ req->nic_desc.acpi_params = 0xFF;
+ req->nic_desc.wol_param = 0x0F;
+
+ /* Change BW */
+ req->nic_desc.bw_min = cpu_to_le32(bps);
+ req->nic_desc.bw_max = cpu_to_le32(bps);
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_enable_disable_vf *req;
+ int status;
+
+ if (!lancer_chip(adapter))
+ return 0;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
+ wrb, NULL);
+
+ req->hdr.domain = domain;
+ req->enable = 1;
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
{
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 0936e21e3cff..d6552e19ffee 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -196,9 +196,14 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_MAC_LIST 147
#define OPCODE_COMMON_SET_MAC_LIST 148
#define OPCODE_COMMON_GET_HSW_CONFIG 152
+#define OPCODE_COMMON_GET_FUNC_CONFIG 160
+#define OPCODE_COMMON_GET_PROFILE_CONFIG 164
+#define OPCODE_COMMON_SET_PROFILE_CONFIG 165
#define OPCODE_COMMON_SET_HSW_CONFIG 153
+#define OPCODE_COMMON_GET_FN_PRIVILEGES 170
#define OPCODE_COMMON_READ_OBJECT 171
#define OPCODE_COMMON_WRITE_OBJECT 172
+#define OPCODE_COMMON_ENABLE_DISABLE_VF 196
#define OPCODE_ETH_RSS_CONFIG 1
#define OPCODE_ETH_ACPI_CONFIG 2
@@ -1151,14 +1156,22 @@ struct flashrom_params {
u32 op_type;
u32 data_buf_size;
u32 offset;
- u8 data_buf[4];
};
struct be_cmd_write_flashrom {
struct be_cmd_req_hdr hdr;
struct flashrom_params params;
-};
+ u8 data_buf[32768];
+ u8 rsvd[4];
+} __packed;
+/* cmd to read flash crc */
+struct be_cmd_read_flash_crc {
+ struct be_cmd_req_hdr hdr;
+ struct flashrom_params params;
+ u8 crc[4];
+ u8 rsvd[4];
+};
/**************** Lancer Firmware Flash ************/
struct amap_lancer_write_obj_context {
u8 write_length[24];
@@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap {
u8 rsvd[212];
};
+/*********************** Function Privileges ***********************/
+enum {
+ BE_PRIV_DEFAULT = 0x1,
+ BE_PRIV_LNKQUERY = 0x2,
+ BE_PRIV_LNKSTATS = 0x4,
+ BE_PRIV_LNKMGMT = 0x8,
+ BE_PRIV_LNKDIAG = 0x10,
+ BE_PRIV_UTILQUERY = 0x20,
+ BE_PRIV_FILTMGMT = 0x40,
+ BE_PRIV_IFACEMGMT = 0x80,
+ BE_PRIV_VHADM = 0x100,
+ BE_PRIV_DEVCFG = 0x200,
+ BE_PRIV_DEVSEC = 0x400
+};
+#define MAX_PRIVILEGES (BE_PRIV_VHADM | BE_PRIV_DEVCFG | \
+ BE_PRIV_DEVSEC)
+#define MIN_PRIVILEGES BE_PRIV_DEFAULT
+
+struct be_cmd_priv_map {
+ u8 opcode;
+ u8 subsystem;
+ u32 priv_mask;
+};
+
+struct be_cmd_req_get_fn_privileges {
+ struct be_cmd_req_hdr hdr;
+ u32 rsvd;
+};
+
+struct be_cmd_resp_get_fn_privileges {
+ struct be_cmd_resp_hdr hdr;
+ u32 privilege_mask;
+};
+
+
/******************** GET/SET_MACLIST **************************/
#define BE_MAX_MAC 64
struct be_cmd_req_get_mac_list {
@@ -1608,33 +1656,6 @@ struct be_cmd_resp_get_stats_v1 {
struct be_hw_stats_v1 hw_stats;
};
-static inline void *hw_stats_from_cmd(struct be_adapter *adapter)
-{
- if (adapter->generation == BE_GEN3) {
- struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
-
- return &cmd->hw_stats;
- } else {
- struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
-
- return &cmd->hw_stats;
- }
-}
-
-static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
-{
- if (adapter->generation == BE_GEN3) {
- struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
- return &hw_stats->erx;
- } else {
- struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
- return &hw_stats->erx;
- }
-}
-
-
/************** get fat capabilites *******************/
#define MAX_MODULES 27
#define MAX_MODES 4
@@ -1684,6 +1705,96 @@ struct be_cmd_req_set_ext_fat_caps {
struct be_fat_conf_params set_params;
};
+#define RESOURCE_DESC_SIZE 72
+#define NIC_RESOURCE_DESC_TYPE_ID 0x41
+#define MAX_RESOURCE_DESC 4
+
+/* QOS unit number */
+#define QUN 4
+/* Immediate */
+#define IMM 6
+/* No save */
+#define NOSV 7
+
+struct be_nic_resource_desc {
+ u8 desc_type;
+ u8 desc_len;
+ u8 rsvd1;
+ u8 flags;
+ u8 vf_num;
+ u8 rsvd2;
+ u8 pf_num;
+ u8 rsvd3;
+ u16 unicast_mac_count;
+ u8 rsvd4[6];
+ u16 mcc_count;
+ u16 vlan_count;
+ u16 mcast_mac_count;
+ u16 txq_count;
+ u16 rq_count;
+ u16 rssq_count;
+ u16 lro_count;
+ u16 cq_count;
+ u16 toe_conn_count;
+ u16 eq_count;
+ u32 rsvd5;
+ u32 cap_flags;
+ u8 link_param;
+ u8 rsvd6[3];
+ u32 bw_min;
+ u32 bw_max;
+ u8 acpi_params;
+ u8 wol_param;
+ u16 rsvd7;
+ u32 rsvd8[3];
+};
+
+struct be_cmd_req_get_func_config {
+ struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_get_func_config {
+ struct be_cmd_req_hdr hdr;
+ u32 desc_count;
+ u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+#define ACTIVE_PROFILE_TYPE 0x2
+struct be_cmd_req_get_profile_config {
+ struct be_cmd_req_hdr hdr;
+ u8 rsvd;
+ u8 type;
+ u16 rsvd1;
+};
+
+struct be_cmd_resp_get_profile_config {
+ struct be_cmd_req_hdr hdr;
+ u32 desc_count;
+ u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+struct be_cmd_req_set_profile_config {
+ struct be_cmd_req_hdr hdr;
+ u32 rsvd;
+ u32 desc_count;
+ struct be_nic_resource_desc nic_desc;
+};
+
+struct be_cmd_resp_set_profile_config {
+ struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_enable_disable_vf {
+ struct be_cmd_req_hdr hdr;
+ u8 enable;
+ u8 rsvd[3];
+};
+
+static inline bool check_privilege(struct be_adapter *adapter, u32 flags)
+{
+ return flags & adapter->cmd_privileges ? true : false;
+}
+
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_fw_wait_ready(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1780,6 +1891,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
extern int be_cmd_req_native_mode(struct be_adapter *adapter);
extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
+extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
+ u32 *privilege, u32 domain);
extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
bool *pmac_id_active, u32 *pmac_id,
u8 domain);
@@ -1798,4 +1911,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
extern int lancer_wait_ready(struct be_adapter *adapter);
extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+extern int be_cmd_get_func_config(struct be_adapter *adapter);
+extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+ u8 domain);
+extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+ u8 domain);
+extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 8e6fb0ba6aa9..00454a10f88d 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev)
struct be_adapter *adapter = netdev_priv(netdev);
u32 log_size = 0;
+ if (!check_privilege(adapter, MAX_PRIVILEGES))
+ return 0;
+
if (be_physfn(adapter)) {
if (lancer_chip(adapter))
log_size = lancer_cmd_get_file_len(adapter,
@@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
u8 link_status;
u16 link_speed = 0;
int status;
+ u32 auto_speeds;
+ u32 fixed_speeds;
+ u32 dac_cable_len;
+ u16 interface_type;
if (adapter->phy.link_speed < 0) {
status = be_cmd_link_status_query(adapter, &link_speed,
@@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ethtool_cmd_speed_set(ecmd, link_speed);
status = be_cmd_get_phy_info(adapter);
- if (status)
- return status;
-
- ecmd->supported =
- convert_to_et_setting(adapter->phy.interface_type,
- adapter->phy.auto_speeds_supported |
- adapter->phy.fixed_speeds_supported);
- ecmd->advertising =
- convert_to_et_setting(adapter->phy.interface_type,
- adapter->phy.auto_speeds_supported);
-
- ecmd->port = be_get_port_type(adapter->phy.interface_type,
- adapter->phy.dac_cable_len);
-
- if (adapter->phy.auto_speeds_supported) {
- ecmd->supported |= SUPPORTED_Autoneg;
- ecmd->autoneg = AUTONEG_ENABLE;
- ecmd->advertising |= ADVERTISED_Autoneg;
- }
+ if (!status) {
+ interface_type = adapter->phy.interface_type;
+ auto_speeds = adapter->phy.auto_speeds_supported;
+ fixed_speeds = adapter->phy.fixed_speeds_supported;
+ dac_cable_len = adapter->phy.dac_cable_len;
+
+ ecmd->supported =
+ convert_to_et_setting(interface_type,
+ auto_speeds |
+ fixed_speeds);
+ ecmd->advertising =
+ convert_to_et_setting(interface_type,
+ auto_speeds);
+
+ ecmd->port = be_get_port_type(interface_type,
+ dac_cable_len);
+
+ if (adapter->phy.auto_speeds_supported) {
+ ecmd->supported |= SUPPORTED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ }
- if (be_pause_supported(adapter)) {
ecmd->supported |= SUPPORTED_Pause;
- ecmd->advertising |= ADVERTISED_Pause;
- }
-
- switch (adapter->phy.interface_type) {
- case PHY_TYPE_KR_10GB:
- case PHY_TYPE_KX4_10GB:
- ecmd->transceiver = XCVR_INTERNAL;
- break;
- default:
- ecmd->transceiver = XCVR_EXTERNAL;
- break;
+ if (be_pause_supported(adapter))
+ ecmd->advertising |= ADVERTISED_Pause;
+
+ switch (adapter->phy.interface_type) {
+ case PHY_TYPE_KR_10GB:
+ case PHY_TYPE_KX4_10GB:
+ ecmd->transceiver = XCVR_INTERNAL;
+ break;
+ default:
+ ecmd->transceiver = XCVR_EXTERNAL;
+ break;
+ }
+ } else {
+ ecmd->port = PORT_OTHER;
+ ecmd->autoneg = AUTONEG_DISABLE;
+ ecmd->transceiver = XCVR_DUMMY1;
}
/* Save for future use */
@@ -787,6 +801,10 @@ static int
be_get_eeprom_len(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (!check_privilege(adapter, MAX_PRIVILEGES))
+ return 0;
+
if (lancer_chip(adapter)) {
if (be_physfn(adapter))
return lancer_cmd_get_file_len(adapter,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index b755f7061dce..541d4530d5bf 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -31,12 +31,12 @@
#define MPU_EP_CONTROL 0
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET 0xac
-#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET 0x400
-#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK 0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT 31
+/********** MPU semphore: used for SH & BE *************/
+#define SLIPORT_SEMAPHORE_OFFSET_BE 0x7c
+#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94
+#define POST_STAGE_MASK 0x0000FFFF
+#define POST_ERR_MASK 0x1
+#define POST_ERR_SHIFT 31
/* MPU semphore POST stage values */
#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */
@@ -59,6 +59,9 @@
#define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002
#define PHYSDEV_CONTROL_INP_MASK 0x40000000
+#define SLIPORT_ERROR_NO_RESOURCE1 0x2
+#define SLIPORT_ERROR_NO_RESOURCE2 0x9
+
/********* Memory BAR register ************/
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -102,11 +105,6 @@
#define SLI_INTF_TYPE_2 2
#define SLI_INTF_TYPE_3 3
-/* SLI family */
-#define BE_SLI_FAMILY 0x0
-#define LANCER_A0_SLI_FAMILY 0xA
-#define SKYHAWK_SLI_FAMILY 0x2
-
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
#define CEV_ISR_SIZE 4
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index d1b6cc587639..f95612b907ae 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)},
+ { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)},
{ 0 }
};
MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
int status = 0;
u8 current_mac[ETH_ALEN];
u32 pmac_id = adapter->pmac_id[0];
+ bool active_mac = true;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- status = be_cmd_mac_addr_query(adapter, current_mac, false,
- adapter->if_handle, 0);
+ /* For BE VF, MAC address is already activated by PF.
+ * Hence only operation left is updating netdev->devaddr.
+ * Update it if user is passing the same MAC which was used
+ * during configuring VF MAC from PF(Hypervisor).
+ */
+ if (!lancer_chip(adapter) && !be_physfn(adapter)) {
+ status = be_cmd_mac_addr_query(adapter, current_mac,
+ false, adapter->if_handle, 0);
+ if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
+ goto done;
+ else
+ goto err;
+ }
+
+ if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
+ goto done;
+
+ /* For Lancer check if any MAC is active.
+ * If active, get its mac id.
+ */
+ if (lancer_chip(adapter) && !be_physfn(adapter))
+ be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
+ &pmac_id, 0);
+
+ status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+ adapter->if_handle,
+ &adapter->pmac_id[0], 0);
+
if (status)
goto err;
- if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) {
- status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
- adapter->if_handle, &adapter->pmac_id[0], 0);
- if (status)
- goto err;
-
- be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0);
- }
+ if (active_mac)
+ be_cmd_pmac_del(adapter, adapter->if_handle,
+ pmac_id, 0);
+done:
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
return 0;
err:
@@ -261,7 +285,35 @@ err:
return status;
}
-static void populate_be2_stats(struct be_adapter *adapter)
+/* BE2 supports only v0 cmd */
+static void *hw_stats_from_cmd(struct be_adapter *adapter)
+{
+ if (BE2_chip(adapter)) {
+ struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
+
+ return &cmd->hw_stats;
+ } else {
+ struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
+
+ return &cmd->hw_stats;
+ }
+}
+
+/* BE2 supports only v0 cmd */
+static void *be_erx_stats_from_cmd(struct be_adapter *adapter)
+{
+ if (BE2_chip(adapter)) {
+ struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
+
+ return &hw_stats->erx;
+ } else {
+ struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
+
+ return &hw_stats->erx;
+ }
+}
+
+static void populate_be_v0_stats(struct be_adapter *adapter)
{
struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -310,7 +362,7 @@ static void populate_be2_stats(struct be_adapter *adapter)
adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
}
-static void populate_be3_stats(struct be_adapter *adapter)
+static void populate_be_v1_stats(struct be_adapter *adapter)
{
struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -412,28 +464,25 @@ void be_parse_stats(struct be_adapter *adapter)
struct be_rx_obj *rxo;
int i;
- if (adapter->generation == BE_GEN3) {
- if (lancer_chip(adapter))
- populate_lancer_stats(adapter);
- else
- populate_be3_stats(adapter);
+ if (lancer_chip(adapter)) {
+ populate_lancer_stats(adapter);
} else {
- populate_be2_stats(adapter);
- }
-
- if (lancer_chip(adapter))
- goto done;
+ if (BE2_chip(adapter))
+ populate_be_v0_stats(adapter);
+ else
+ /* for BE3 and Skyhawk */
+ populate_be_v1_stats(adapter);
- /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
- for_all_rx_queues(adapter, rxo, i) {
- /* below erx HW counter can actually wrap around after
- * 65535. Driver accumulates a 32-bit value
- */
- accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
- (u16)erx->rx_drops_no_fragments[rxo->q.id]);
+ /* as erx_v1 is longer than v0, ok to use v1 for v0 access */
+ for_all_rx_queues(adapter, rxo, i) {
+ /* below erx HW counter can actually wrap around after
+ * 65535. Driver accumulates a 32-bit value
+ */
+ accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
+ (u16)erx->rx_drops_no_fragments \
+ [rxo->q.id]);
+ }
}
-done:
- return;
}
static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
@@ -597,16 +646,6 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
hdr, skb_shinfo(skb)->gso_size);
if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
- if (lancer_chip(adapter) && adapter->sli_family ==
- LANCER_A0_SLI_FAMILY) {
- AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
- if (is_tcp_pkt(skb))
- AMAP_SET_BITS(struct amap_eth_hdr_wrb,
- tcpcs, hdr, 1);
- else if (is_udp_pkt(skb))
- AMAP_SET_BITS(struct amap_eth_hdr_wrb,
- udpcs, hdr, 1);
- }
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (is_tcp_pkt(skb))
AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
@@ -856,11 +895,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
struct be_adapter *adapter = netdev_priv(netdev);
int status = 0;
- if (!be_physfn(adapter)) {
+ if (!lancer_chip(adapter) && !be_physfn(adapter)) {
status = -EINVAL;
goto ret;
}
+ /* Packets with VID 0 are always received by Lancer by default */
+ if (lancer_chip(adapter) && vid == 0)
+ goto ret;
+
adapter->vlan_tag[vid] = 1;
if (adapter->vlans_added <= (adapter->max_vlans + 1))
status = be_vid_config(adapter);
@@ -878,11 +921,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid)
struct be_adapter *adapter = netdev_priv(netdev);
int status = 0;
- if (!be_physfn(adapter)) {
+ if (!lancer_chip(adapter) && !be_physfn(adapter)) {
status = -EINVAL;
goto ret;
}
+ /* Packets with VID 0 are always received by Lancer by default */
+ if (lancer_chip(adapter) && vid == 0)
+ goto ret;
+
adapter->vlan_tag[vid] = 0;
if (adapter->vlans_added <= adapter->max_vlans)
status = be_vid_config(adapter);
@@ -917,7 +964,7 @@ static void be_set_rx_mode(struct net_device *netdev)
/* Enable multicast promisc if num configured exceeds what we support */
if (netdev->flags & IFF_ALLMULTI ||
- netdev_mc_count(netdev) > BE_MAX_MC) {
+ netdev_mc_count(netdev) > adapter->max_mcast_mac) {
be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
goto done;
}
@@ -962,6 +1009,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
struct be_adapter *adapter = netdev_priv(netdev);
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
int status;
+ bool active_mac = false;
+ u32 pmac_id;
+ u8 old_mac[ETH_ALEN];
if (!sriov_enabled(adapter))
return -EPERM;
@@ -970,6 +1020,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
return -EINVAL;
if (lancer_chip(adapter)) {
+ status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
+ &pmac_id, vf + 1);
+ if (!status && active_mac)
+ be_cmd_pmac_del(adapter, vf_cfg->if_handle,
+ pmac_id, vf + 1);
+
status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
} else {
status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
@@ -1062,7 +1118,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return -EINVAL;
}
- status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
+ if (lancer_chip(adapter))
+ status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1);
+ else
+ status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
if (status)
dev_err(&adapter->pdev->dev,
@@ -1616,24 +1675,6 @@ static inline int events_get(struct be_eq_obj *eqo)
return num;
}
-static int event_handle(struct be_eq_obj *eqo)
-{
- bool rearm = false;
- int num = events_get(eqo);
-
- /* Deal with any spurious interrupts that come without events */
- if (!num)
- rearm = true;
-
- if (num || msix_enabled(eqo->adapter))
- be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
-
- if (num)
- napi_schedule(&eqo->napi);
-
- return num;
-}
-
/* Leaves the EQ is disarmed state */
static void be_eq_clean(struct be_eq_obj *eqo)
{
@@ -1837,12 +1878,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
static int be_num_txqs_want(struct be_adapter *adapter)
{
- if (sriov_want(adapter) || be_is_mc(adapter) ||
- lancer_chip(adapter) || !be_physfn(adapter) ||
- adapter->generation == BE_GEN2)
+ if ((!lancer_chip(adapter) && sriov_want(adapter)) ||
+ be_is_mc(adapter) ||
+ (!lancer_chip(adapter) && !be_physfn(adapter)) ||
+ BE2_chip(adapter))
return 1;
else
- return MAX_TX_QS;
+ return adapter->max_tx_queues;
}
static int be_tx_cqs_create(struct be_adapter *adapter)
@@ -1954,22 +1996,31 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
static irqreturn_t be_intx(int irq, void *dev)
{
- struct be_adapter *adapter = dev;
- int num_evts;
+ struct be_eq_obj *eqo = dev;
+ struct be_adapter *adapter = eqo->adapter;
+ int num_evts = 0;
- /* With INTx only one EQ is used */
- num_evts = event_handle(&adapter->eq_obj[0]);
- if (num_evts)
- return IRQ_HANDLED;
- else
- return IRQ_NONE;
+ /* On Lancer, clear-intr bit of the EQ DB does not work.
+ * INTx is de-asserted only on notifying num evts.
+ */
+ if (lancer_chip(adapter))
+ num_evts = events_get(eqo);
+
+ /* The EQ-notify may not de-assert INTx rightaway, causing
+ * the ISR to be invoked again. So, return HANDLED even when
+ * num_evts is zero.
+ */
+ be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
+ napi_schedule(&eqo->napi);
+ return IRQ_HANDLED;
}
static irqreturn_t be_msix(int irq, void *dev)
{
struct be_eq_obj *eqo = dev;
- event_handle(eqo);
+ be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+ napi_schedule(&eqo->napi);
return IRQ_HANDLED;
}
@@ -2065,9 +2116,11 @@ int be_poll(struct napi_struct *napi, int budget)
{
struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi);
struct be_adapter *adapter = eqo->adapter;
- int max_work = 0, work, i;
+ int max_work = 0, work, i, num_evts;
bool tx_done;
+ num_evts = events_get(eqo);
+
/* Process all TXQs serviced by this EQ */
for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) {
tx_done = be_process_tx(adapter, &adapter->tx_obj[i],
@@ -2090,10 +2143,10 @@ int be_poll(struct napi_struct *napi, int budget)
if (max_work < budget) {
napi_complete(napi);
- be_eq_notify(adapter, eqo->q.id, true, false, 0);
+ be_eq_notify(adapter, eqo->q.id, true, false, num_evts);
} else {
/* As we'll continue in polling mode, count and clear events */
- be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo));
+ be_eq_notify(adapter, eqo->q.id, false, false, num_evts);
}
return max_work;
}
@@ -2177,9 +2230,11 @@ static void be_msix_disable(struct be_adapter *adapter)
static uint be_num_rss_want(struct be_adapter *adapter)
{
u32 num = 0;
+
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !sriov_want(adapter) && be_physfn(adapter)) {
- num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+ (lancer_chip(adapter) ||
+ (!sriov_want(adapter) && be_physfn(adapter)))) {
+ num = adapter->max_rss_queues;
num = min_t(u32, num, (u32)netif_get_num_default_rss_queues());
}
return num;
@@ -2277,10 +2332,10 @@ static int be_irq_register(struct be_adapter *adapter)
return status;
}
- /* INTx */
+ /* INTx: only the first EQ is used */
netdev->irq = adapter->pdev->irq;
status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name,
- adapter);
+ &adapter->eq_obj[0]);
if (status) {
dev_err(&adapter->pdev->dev,
"INTx request IRQ failed - err %d\n", status);
@@ -2302,7 +2357,7 @@ static void be_irq_unregister(struct be_adapter *adapter)
/* INTx */
if (!msix_enabled(adapter)) {
- free_irq(netdev->irq, adapter);
+ free_irq(netdev->irq, &adapter->eq_obj[0]);
goto done;
}
@@ -2579,10 +2634,30 @@ static int be_clear(struct be_adapter *adapter)
be_tx_queues_destroy(adapter);
be_evt_queues_destroy(adapter);
+ kfree(adapter->pmac_id);
+ adapter->pmac_id = NULL;
+
be_msix_disable(adapter);
return 0;
}
+static void be_get_vf_if_cap_flags(struct be_adapter *adapter,
+ u32 *cap_flags, u8 domain)
+{
+ bool profile_present = false;
+ int status;
+
+ if (lancer_chip(adapter)) {
+ status = be_cmd_get_profile_config(adapter, cap_flags, domain);
+ if (!status)
+ profile_present = true;
+ }
+
+ if (!profile_present)
+ *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_MULTICAST;
+}
+
static int be_vf_setup_init(struct be_adapter *adapter)
{
struct be_vf_cfg *vf_cfg;
@@ -2634,9 +2709,13 @@ static int be_vf_setup(struct be_adapter *adapter)
if (status)
goto err;
- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
- BE_IF_FLAGS_MULTICAST;
for_all_vfs(adapter, vf_cfg, vf) {
+ be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1);
+
+ en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+ BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_MULTICAST);
+
status = be_cmd_if_create(adapter, cap_flags, en_flags,
&vf_cfg->if_handle, vf + 1);
if (status)
@@ -2661,6 +2740,8 @@ static int be_vf_setup(struct be_adapter *adapter)
if (status)
goto err;
vf_cfg->def_vid = def_vlan;
+
+ be_cmd_enable_vf(adapter, vf + 1);
}
return 0;
err:
@@ -2674,7 +2755,10 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->if_handle = -1;
adapter->be3_native = false;
adapter->promiscuous = false;
- adapter->eq_next_idx = 0;
+ if (be_physfn(adapter))
+ adapter->cmd_privileges = MAX_PRIVILEGES;
+ else
+ adapter->cmd_privileges = MIN_PRIVILEGES;
}
static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
@@ -2712,12 +2796,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
return status;
}
+static void be_get_resources(struct be_adapter *adapter)
+{
+ int status;
+ bool profile_present = false;
+
+ if (lancer_chip(adapter)) {
+ status = be_cmd_get_func_config(adapter);
+
+ if (!status)
+ profile_present = true;
+ }
+
+ if (profile_present) {
+ /* Sanity fixes for Lancer */
+ adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt,
+ BE_UC_PMAC_COUNT);
+ adapter->max_vlans = min_t(u16, adapter->max_vlans,
+ BE_NUM_VLANS_SUPPORTED);
+ adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac,
+ BE_MAX_MC);
+ adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues,
+ MAX_TX_QS);
+ adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues,
+ BE3_MAX_RSS_QS);
+ adapter->max_event_queues = min_t(u16,
+ adapter->max_event_queues,
+ BE3_MAX_RSS_QS);
+
+ if (adapter->max_rss_queues &&
+ adapter->max_rss_queues == adapter->max_rx_queues)
+ adapter->max_rss_queues -= 1;
+
+ if (adapter->max_event_queues < adapter->max_rss_queues)
+ adapter->max_rss_queues = adapter->max_event_queues;
+
+ } else {
+ if (be_physfn(adapter))
+ adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
+ else
+ adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
+
+ if (adapter->function_mode & FLEX10_MODE)
+ adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+ else
+ adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
+
+ adapter->max_mcast_mac = BE_MAX_MC;
+ adapter->max_tx_queues = MAX_TX_QS;
+ adapter->max_rss_queues = (adapter->be3_native) ?
+ BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+ adapter->max_event_queues = BE3_MAX_RSS_QS;
+
+ adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED |
+ BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_MULTICAST |
+ BE_IF_FLAGS_PASS_L3L4_ERRORS |
+ BE_IF_FLAGS_MCAST_PROMISCUOUS |
+ BE_IF_FLAGS_VLAN_PROMISCUOUS |
+ BE_IF_FLAGS_PROMISCUOUS;
+
+ if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
+ adapter->if_cap_flags |= BE_IF_FLAGS_RSS;
+ }
+}
+
/* Routine to query per function resource limits */
static int be_get_config(struct be_adapter *adapter)
{
- int pos;
+ int pos, status;
u16 dev_num_vfs;
+ status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+ &adapter->function_mode,
+ &adapter->function_caps);
+ if (status)
+ goto err;
+
+ be_get_resources(adapter);
+
+ /* primary mac needs 1 pmac entry */
+ adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!adapter->pmac_id) {
+ status = -ENOMEM;
+ goto err;
+ }
+
pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
if (pos) {
pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
@@ -2726,13 +2891,14 @@ static int be_get_config(struct be_adapter *adapter)
dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS);
adapter->dev_num_vfs = dev_num_vfs;
}
- return 0;
+err:
+ return status;
}
static int be_setup(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
- u32 cap_flags, en_flags;
+ u32 en_flags;
u32 tx_fc, rx_fc;
int status;
u8 mac[ETH_ALEN];
@@ -2740,9 +2906,12 @@ static int be_setup(struct be_adapter *adapter)
be_setup_init(adapter);
- be_get_config(adapter);
+ if (!lancer_chip(adapter))
+ be_cmd_req_native_mode(adapter);
- be_cmd_req_native_mode(adapter);
+ status = be_get_config(adapter);
+ if (status)
+ goto err;
be_msix_enable(adapter);
@@ -2762,24 +2931,22 @@ static int be_setup(struct be_adapter *adapter)
if (status)
goto err;
+ be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0);
+ /* In UMC mode FW does not return right privileges.
+ * Override with correct privilege equivalent to PF.
+ */
+ if (be_is_mc(adapter))
+ adapter->cmd_privileges = MAX_PRIVILEGES;
+
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
- cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
- BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS;
- if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
- cap_flags |= BE_IF_FLAGS_RSS;
+ if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
en_flags |= BE_IF_FLAGS_RSS;
- }
- if (lancer_chip(adapter) && !be_physfn(adapter)) {
- en_flags = BE_IF_FLAGS_UNTAGGED |
- BE_IF_FLAGS_BROADCAST |
- BE_IF_FLAGS_MULTICAST;
- cap_flags = en_flags;
- }
+ en_flags = en_flags & adapter->if_cap_flags;
- status = be_cmd_if_create(adapter, cap_flags, en_flags,
+ status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags,
&adapter->if_handle, 0);
if (status != 0)
goto err;
@@ -2827,8 +2994,8 @@ static int be_setup(struct be_adapter *adapter)
dev_warn(dev, "device doesn't support SRIOV\n");
}
- be_cmd_get_phy_info(adapter);
- if (be_pause_supported(adapter))
+ status = be_cmd_get_phy_info(adapter);
+ if (!status && be_pause_supported(adapter))
adapter->phy.fc_autoneg = 1;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -2846,8 +3013,10 @@ static void be_netpoll(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
- for_all_evt_queues(adapter, eqo, i)
- event_handle(eqo);
+ for_all_evt_queues(adapter, eqo, i) {
+ be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+ napi_schedule(&eqo->napi);
+ }
return;
}
@@ -2895,7 +3064,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter,
int i = 0, img_type = 0;
struct flash_section_info_g2 *fsec_g2 = NULL;
- if (adapter->generation != BE_GEN3)
+ if (BE2_chip(adapter))
fsec_g2 = (struct flash_section_info_g2 *)fsec;
for (i = 0; i < MAX_FLASH_COMP; i++) {
@@ -2928,7 +3097,49 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
return NULL;
}
-static int be_flash_data(struct be_adapter *adapter,
+static int be_flash(struct be_adapter *adapter, const u8 *img,
+ struct be_dma_mem *flash_cmd, int optype, int img_size)
+{
+ u32 total_bytes = 0, flash_op, num_bytes = 0;
+ int status = 0;
+ struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+ total_bytes = img_size;
+ while (total_bytes) {
+ num_bytes = min_t(u32, 32*1024, total_bytes);
+
+ total_bytes -= num_bytes;
+
+ if (!total_bytes) {
+ if (optype == OPTYPE_PHY_FW)
+ flash_op = FLASHROM_OPER_PHY_FLASH;
+ else
+ flash_op = FLASHROM_OPER_FLASH;
+ } else {
+ if (optype == OPTYPE_PHY_FW)
+ flash_op = FLASHROM_OPER_PHY_SAVE;
+ else
+ flash_op = FLASHROM_OPER_SAVE;
+ }
+
+ memcpy(req->data_buf, img, num_bytes);
+ img += num_bytes;
+ status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
+ flash_op, num_bytes);
+ if (status) {
+ if (status == ILLEGAL_IOCTL_REQ &&
+ optype == OPTYPE_PHY_FW)
+ break;
+ dev_err(&adapter->pdev->dev,
+ "cmd to write to flash rom failed.\n");
+ return status;
+ }
+ }
+ return 0;
+}
+
+/* For BE2 and BE3 */
+static int be_flash_BEx(struct be_adapter *adapter,
const struct firmware *fw,
struct be_dma_mem *flash_cmd,
int num_of_images)
@@ -2936,12 +3147,9 @@ static int be_flash_data(struct be_adapter *adapter,
{
int status = 0, i, filehdr_size = 0;
int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
- u32 total_bytes = 0, flash_op;
- int num_bytes;
const u8 *p = fw->data;
- struct be_cmd_write_flashrom *req = flash_cmd->va;
const struct flash_comp *pflashcomp;
- int num_comp, hdr_size;
+ int num_comp, redboot;
struct flash_section_info *fsec = NULL;
struct flash_comp gen3_flash_types[] = {
@@ -2986,7 +3194,7 @@ static int be_flash_data(struct be_adapter *adapter,
FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
};
- if (adapter->generation == BE_GEN3) {
+ if (BE3_chip(adapter)) {
pflashcomp = gen3_flash_types;
filehdr_size = sizeof(struct flash_file_hdr_g3);
num_comp = ARRAY_SIZE(gen3_flash_types);
@@ -2995,6 +3203,7 @@ static int be_flash_data(struct be_adapter *adapter,
filehdr_size = sizeof(struct flash_file_hdr_g2);
num_comp = ARRAY_SIZE(gen2_flash_types);
}
+
/* Get flash section info*/
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
if (!fsec) {
@@ -3010,70 +3219,105 @@ static int be_flash_data(struct be_adapter *adapter,
memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
continue;
- if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
- if (!phy_flashing_required(adapter))
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW &&
+ !phy_flashing_required(adapter))
continue;
- }
-
- hdr_size = filehdr_size +
- (num_of_images * sizeof(struct image_hdr));
- if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
- (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
- pflashcomp[i].size, hdr_size)))
- continue;
+ if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
+ redboot = be_flash_redboot(adapter, fw->data,
+ pflashcomp[i].offset, pflashcomp[i].size,
+ filehdr_size + img_hdrs_size);
+ if (!redboot)
+ continue;
+ }
- /* Flash the component */
p = fw->data;
p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
if (p + pflashcomp[i].size > fw->data + fw->size)
return -1;
- total_bytes = pflashcomp[i].size;
- while (total_bytes) {
- if (total_bytes > 32*1024)
- num_bytes = 32*1024;
- else
- num_bytes = total_bytes;
- total_bytes -= num_bytes;
- if (!total_bytes) {
- if (pflashcomp[i].optype == OPTYPE_PHY_FW)
- flash_op = FLASHROM_OPER_PHY_FLASH;
- else
- flash_op = FLASHROM_OPER_FLASH;
- } else {
- if (pflashcomp[i].optype == OPTYPE_PHY_FW)
- flash_op = FLASHROM_OPER_PHY_SAVE;
- else
- flash_op = FLASHROM_OPER_SAVE;
- }
- memcpy(req->params.data_buf, p, num_bytes);
- p += num_bytes;
- status = be_cmd_write_flashrom(adapter, flash_cmd,
- pflashcomp[i].optype, flash_op, num_bytes);
- if (status) {
- if ((status == ILLEGAL_IOCTL_REQ) &&
- (pflashcomp[i].optype ==
- OPTYPE_PHY_FW))
- break;
- dev_err(&adapter->pdev->dev,
- "cmd to write to flash rom failed.\n");
- return -1;
- }
+
+ status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
+ pflashcomp[i].size);
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "Flashing section type %d failed.\n",
+ pflashcomp[i].img_type);
+ return status;
}
}
return 0;
}
-static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
+static int be_flash_skyhawk(struct be_adapter *adapter,
+ const struct firmware *fw,
+ struct be_dma_mem *flash_cmd, int num_of_images)
{
- if (fhdr == NULL)
- return 0;
- if (fhdr->build[0] == '3')
- return BE_GEN3;
- else if (fhdr->build[0] == '2')
- return BE_GEN2;
- else
- return 0;
+ int status = 0, i, filehdr_size = 0;
+ int img_offset, img_size, img_optype, redboot;
+ int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+ const u8 *p = fw->data;
+ struct flash_section_info *fsec = NULL;
+
+ filehdr_size = sizeof(struct flash_file_hdr_g3);
+ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+ if (!fsec) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid Cookie. UFI corrupted ?\n");
+ return -1;
+ }
+
+ for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
+ img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
+ img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size);
+
+ switch (le32_to_cpu(fsec->fsec_entry[i].type)) {
+ case IMAGE_FIRMWARE_iSCSI:
+ img_optype = OPTYPE_ISCSI_ACTIVE;
+ break;
+ case IMAGE_BOOT_CODE:
+ img_optype = OPTYPE_REDBOOT;
+ break;
+ case IMAGE_OPTION_ROM_ISCSI:
+ img_optype = OPTYPE_BIOS;
+ break;
+ case IMAGE_OPTION_ROM_PXE:
+ img_optype = OPTYPE_PXE_BIOS;
+ break;
+ case IMAGE_OPTION_ROM_FCoE:
+ img_optype = OPTYPE_FCOE_BIOS;
+ break;
+ case IMAGE_FIRMWARE_BACKUP_iSCSI:
+ img_optype = OPTYPE_ISCSI_BACKUP;
+ break;
+ case IMAGE_NCSI:
+ img_optype = OPTYPE_NCSI_FW;
+ break;
+ default:
+ continue;
+ }
+
+ if (img_optype == OPTYPE_REDBOOT) {
+ redboot = be_flash_redboot(adapter, fw->data,
+ img_offset, img_size,
+ filehdr_size + img_hdrs_size);
+ if (!redboot)
+ continue;
+ }
+
+ p = fw->data;
+ p += filehdr_size + img_offset + img_hdrs_size;
+ if (p + img_size > fw->data + fw->size)
+ return -1;
+
+ status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "Flashing section type %d failed.\n",
+ fsec->fsec_entry[i].type);
+ return status;
+ }
+ }
+ return 0;
}
static int lancer_wait_idle(struct be_adapter *adapter)
@@ -3207,6 +3451,28 @@ lancer_fw_exit:
return status;
}
+#define UFI_TYPE2 2
+#define UFI_TYPE3 3
+#define UFI_TYPE4 4
+static int be_get_ufi_type(struct be_adapter *adapter,
+ struct flash_file_hdr_g2 *fhdr)
+{
+ if (fhdr == NULL)
+ goto be_get_ufi_exit;
+
+ if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
+ return UFI_TYPE4;
+ else if (BE3_chip(adapter) && fhdr->build[0] == '3')
+ return UFI_TYPE3;
+ else if (BE2_chip(adapter) && fhdr->build[0] == '2')
+ return UFI_TYPE2;
+
+be_get_ufi_exit:
+ dev_err(&adapter->pdev->dev,
+ "UFI and Interface are not compatible for flashing\n");
+ return -1;
+}
+
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
{
struct flash_file_hdr_g2 *fhdr;
@@ -3214,12 +3480,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
struct image_hdr *img_hdr_ptr = NULL;
struct be_dma_mem flash_cmd;
const u8 *p;
- int status = 0, i = 0, num_imgs = 0;
-
- p = fw->data;
- fhdr = (struct flash_file_hdr_g2 *) p;
+ int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
- flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+ flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
&flash_cmd.dma, GFP_KERNEL);
if (!flash_cmd.va) {
@@ -3229,27 +3492,32 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
goto be_fw_exit;
}
- if ((adapter->generation == BE_GEN3) &&
- (get_ufigen_type(fhdr) == BE_GEN3)) {
- fhdr3 = (struct flash_file_hdr_g3 *) fw->data;
- num_imgs = le32_to_cpu(fhdr3->num_imgs);
- for (i = 0; i < num_imgs; i++) {
- img_hdr_ptr = (struct image_hdr *) (fw->data +
- (sizeof(struct flash_file_hdr_g3) +
- i * sizeof(struct image_hdr)));
- if (le32_to_cpu(img_hdr_ptr->imageid) == 1)
- status = be_flash_data(adapter, fw, &flash_cmd,
- num_imgs);
+ p = fw->data;
+ fhdr = (struct flash_file_hdr_g2 *)p;
+
+ ufi_type = be_get_ufi_type(adapter, fhdr);
+
+ fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+ num_imgs = le32_to_cpu(fhdr3->num_imgs);
+ for (i = 0; i < num_imgs; i++) {
+ img_hdr_ptr = (struct image_hdr *)(fw->data +
+ (sizeof(struct flash_file_hdr_g3) +
+ i * sizeof(struct image_hdr)));
+ if (le32_to_cpu(img_hdr_ptr->imageid) == 1) {
+ if (ufi_type == UFI_TYPE4)
+ status = be_flash_skyhawk(adapter, fw,
+ &flash_cmd, num_imgs);
+ else if (ufi_type == UFI_TYPE3)
+ status = be_flash_BEx(adapter, fw, &flash_cmd,
+ num_imgs);
}
- } else if ((adapter->generation == BE_GEN2) &&
- (get_ufigen_type(fhdr) == BE_GEN2)) {
- status = be_flash_data(adapter, fw, &flash_cmd, 0);
- } else {
- dev_err(&adapter->pdev->dev,
- "UFI and Interface are not compatible for flashing\n");
- status = -1;
}
+ if (ufi_type == UFI_TYPE2)
+ status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
+ else if (ufi_type == -1)
+ status = -1;
+
dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
flash_cmd.dma);
if (status) {
@@ -3344,80 +3612,47 @@ static void be_netdev_init(struct net_device *netdev)
static void be_unmap_pci_bars(struct be_adapter *adapter)
{
- if (adapter->csr)
- iounmap(adapter->csr);
if (adapter->db)
- iounmap(adapter->db);
- if (adapter->roce_db.base)
- pci_iounmap(adapter->pdev, adapter->roce_db.base);
+ pci_iounmap(adapter->pdev, adapter->db);
}
-static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+static int db_bar(struct be_adapter *adapter)
{
- struct pci_dev *pdev = adapter->pdev;
- u8 __iomem *addr;
-
- addr = pci_iomap(pdev, 2, 0);
- if (addr == NULL)
- return -ENOMEM;
+ if (lancer_chip(adapter) || !be_physfn(adapter))
+ return 0;
+ else
+ return 4;
+}
- adapter->roce_db.base = addr;
- adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
- adapter->roce_db.size = 8192;
- adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+static int be_roce_map_pci_bars(struct be_adapter *adapter)
+{
+ if (skyhawk_chip(adapter)) {
+ adapter->roce_db.size = 4096;
+ adapter->roce_db.io_addr = pci_resource_start(adapter->pdev,
+ db_bar(adapter));
+ adapter->roce_db.total_size = pci_resource_len(adapter->pdev,
+ db_bar(adapter));
+ }
return 0;
}
static int be_map_pci_bars(struct be_adapter *adapter)
{
u8 __iomem *addr;
- int db_reg;
+ u32 sli_intf;
- if (lancer_chip(adapter)) {
- if (be_type_2_3(adapter)) {
- addr = ioremap_nocache(
- pci_resource_start(adapter->pdev, 0),
- pci_resource_len(adapter->pdev, 0));
- if (addr == NULL)
- return -ENOMEM;
- adapter->db = addr;
- }
- if (adapter->if_type == SLI_INTF_TYPE_3) {
- if (lancer_roce_map_pci_bars(adapter))
- goto pci_map_err;
- }
- return 0;
- }
-
- if (be_physfn(adapter)) {
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
- pci_resource_len(adapter->pdev, 2));
- if (addr == NULL)
- return -ENOMEM;
- adapter->csr = addr;
- }
+ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+ SLI_INTF_IF_TYPE_SHIFT;
- if (adapter->generation == BE_GEN2) {
- db_reg = 4;
- } else {
- if (be_physfn(adapter))
- db_reg = 4;
- else
- db_reg = 0;
- }
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg),
- pci_resource_len(adapter->pdev, db_reg));
+ addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
if (addr == NULL)
goto pci_map_err;
adapter->db = addr;
- if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
- adapter->roce_db.size = 4096;
- adapter->roce_db.io_addr =
- pci_resource_start(adapter->pdev, db_reg);
- adapter->roce_db.total_size =
- pci_resource_len(adapter->pdev, db_reg);
- }
+
+ be_roce_map_pci_bars(adapter);
return 0;
+
pci_map_err:
be_unmap_pci_bars(adapter);
return -ENOMEM;
@@ -3437,7 +3672,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
if (mem->va)
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
mem->dma);
- kfree(adapter->pmac_id);
}
static int be_ctrl_init(struct be_adapter *adapter)
@@ -3445,8 +3679,14 @@ static int be_ctrl_init(struct be_adapter *adapter)
struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
struct be_dma_mem *rx_filter = &adapter->rx_filter;
+ u32 sli_intf;
int status;
+ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >>
+ SLI_INTF_FAMILY_SHIFT;
+ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
+
status = be_map_pci_bars(adapter);
if (status)
goto done;
@@ -3473,13 +3713,6 @@ static int be_ctrl_init(struct be_adapter *adapter)
goto free_mbox;
}
memset(rx_filter->va, 0, rx_filter->size);
-
- /* primary mac needs 1 pmac entry */
- adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
- sizeof(*adapter->pmac_id), GFP_KERNEL);
- if (!adapter->pmac_id)
- return -ENOMEM;
-
mutex_init(&adapter->mbox_lock);
spin_lock_init(&adapter->mcc_lock);
spin_lock_init(&adapter->mcc_cq_lock);
@@ -3512,14 +3745,14 @@ static int be_stats_init(struct be_adapter *adapter)
{
struct be_dma_mem *cmd = &adapter->stats_cmd;
- if (adapter->generation == BE_GEN2) {
+ if (lancer_chip(adapter))
+ cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
+ else if (BE2_chip(adapter))
cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
- } else {
- if (lancer_chip(adapter))
- cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
- else
- cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
- }
+ else
+ /* BE3 and Skyhawk */
+ cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
+
cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
GFP_KERNEL);
if (cmd->va == NULL)
@@ -3528,7 +3761,7 @@ static int be_stats_init(struct be_adapter *adapter)
return 0;
}
-static void __devexit be_remove(struct pci_dev *pdev)
+static void be_remove(struct pci_dev *pdev)
{
struct be_adapter *adapter = pci_get_drvdata(pdev);
@@ -3573,6 +3806,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
u32 level = 0;
int j;
+ if (lancer_chip(adapter))
+ return 0;
+
memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
@@ -3598,26 +3834,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
err:
return level;
}
+
static int be_get_initial_config(struct be_adapter *adapter)
{
int status;
u32 level;
- status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
- &adapter->function_mode, &adapter->function_caps);
- if (status)
- return status;
-
- if (adapter->function_mode & FLEX10_MODE)
- adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
- else
- adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
-
- if (be_physfn(adapter))
- adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
- else
- adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
-
status = be_cmd_get_cntl_attributes(adapter);
if (status)
return status;
@@ -3642,55 +3864,6 @@ static int be_get_initial_config(struct be_adapter *adapter)
return 0;
}
-static int be_dev_type_check(struct be_adapter *adapter)
-{
- struct pci_dev *pdev = adapter->pdev;
- u32 sli_intf = 0, if_type;
-
- switch (pdev->device) {
- case BE_DEVICE_ID1:
- case OC_DEVICE_ID1:
- adapter->generation = BE_GEN2;
- break;
- case BE_DEVICE_ID2:
- case OC_DEVICE_ID2:
- adapter->generation = BE_GEN3;
- break;
- case OC_DEVICE_ID3:
- case OC_DEVICE_ID4:
- pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
- adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
- SLI_INTF_IF_TYPE_SHIFT;
- if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
- SLI_INTF_IF_TYPE_SHIFT;
- if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
- !be_type_2_3(adapter)) {
- dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
- return -EINVAL;
- }
- adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
- SLI_INTF_FAMILY_SHIFT);
- adapter->generation = BE_GEN3;
- break;
- case OC_DEVICE_ID5:
- pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
- if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
- dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
- return -EINVAL;
- }
- adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
- SLI_INTF_FAMILY_SHIFT);
- adapter->generation = BE_GEN3;
- break;
- default:
- adapter->generation = 0;
- }
-
- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
- adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
- return 0;
-}
-
static int lancer_recover_func(struct be_adapter *adapter)
{
int status;
@@ -3721,8 +3894,9 @@ static int lancer_recover_func(struct be_adapter *adapter)
"Adapter SLIPORT recovery succeeded\n");
return 0;
err:
- dev_err(&adapter->pdev->dev,
- "Adapter SLIPORT recovery failed\n");
+ if (adapter->eeh_error)
+ dev_err(&adapter->pdev->dev,
+ "Adapter SLIPORT recovery failed\n");
return status;
}
@@ -3820,8 +3994,7 @@ static inline char *func_name(struct be_adapter *adapter)
return be_physfn(adapter) ? "PF" : "VF";
}
-static int __devinit be_probe(struct pci_dev *pdev,
- const struct pci_device_id *pdev_id)
+static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
{
int status = 0;
struct be_adapter *adapter;
@@ -3845,11 +4018,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
adapter = netdev_priv(netdev);
adapter->pdev = pdev;
pci_set_drvdata(pdev, adapter);
-
- status = be_dev_type_check(adapter);
- if (status)
- goto free_netdev;
-
adapter->netdev = netdev;
SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -4023,9 +4191,6 @@ static void be_shutdown(struct pci_dev *pdev)
netif_device_detach(adapter->netdev);
- if (adapter->wol)
- be_setup_wol(adapter, true);
-
be_cmd_reset_function(adapter);
pci_disable_device(pdev);
@@ -4061,9 +4226,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
/* The error could cause the FW to trigger a flash debug dump.
* Resetting the card while flash dump is in progress
- * can cause it not to recover; wait for it to finish
+ * can cause it not to recover; wait for it to finish.
+ * Wait only for first function as it is needed only once per
+ * adapter.
*/
- ssleep(30);
+ if (pdev->devfn == 0)
+ ssleep(30);
+
return PCI_ERS_RESULT_NEED_RESET;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index deecc44b3617..55d32aa0a093 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -47,10 +47,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter)
dev_info.dpp_unmapped_len = 0;
}
dev_info.pdev = adapter->pdev;
- if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
- dev_info.db = adapter->db;
- else
- dev_info.db = adapter->roce_db.base;
+ dev_info.db = adapter->db;
dev_info.unmapped_db = adapter->roce_db.io_addr;
dev_info.db_page_size = adapter->roce_db.size;
dev_info.db_total_size = adapter->roce_db.total_size;
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 94b7bfcdb24e..8db1c06008de 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -665,7 +665,7 @@ static void ethoc_mdio_poll(struct net_device *dev)
{
}
-static int __devinit ethoc_mdio_probe(struct net_device *dev)
+static int ethoc_mdio_probe(struct net_device *dev)
{
struct ethoc *priv = netdev_priv(dev);
struct phy_device *phy;
@@ -905,7 +905,7 @@ static const struct net_device_ops ethoc_netdev_ops = {
* ethoc_probe - initialize OpenCores ethernet MAC
* pdev: platform device
*/
-static int __devinit ethoc_probe(struct platform_device *pdev)
+static int ethoc_probe(struct platform_device *pdev)
{
struct net_device *netdev = NULL;
struct resource *res = NULL;
@@ -1143,7 +1143,7 @@ out:
* ethoc_remove - shutdown OpenCores ethernet MAC
* @pdev: platform device
*/
-static int __devexit ethoc_remove(struct platform_device *pdev)
+static int ethoc_remove(struct platform_device *pdev)
{
struct net_device *netdev = platform_get_drvdata(pdev);
struct ethoc *priv = netdev_priv(netdev);
@@ -1190,7 +1190,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match);
static struct platform_driver ethoc_driver = {
.probe = ethoc_probe,
- .remove = __devexit_p(ethoc_remove),
+ .remove = ethoc_remove,
.suspend = ethoc_suspend,
.resume = ethoc_resume,
.driver = {
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index 0e4a0ac86aa8..c706b7a9397e 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#include <asm/byteorder.h>
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
@@ -150,7 +150,7 @@ struct chip_info {
int flags;
};
-static const struct chip_info skel_netdrv_tbl[] __devinitconst = {
+static const struct chip_info skel_netdrv_tbl[] = {
{ "100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
{ "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR },
{ "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
@@ -477,8 +477,8 @@ static const struct net_device_ops netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit fealnx_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int fealnx_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct netdev_private *np;
int i, option, err, irq;
@@ -684,7 +684,7 @@ err_out_res:
}
-static void __devexit fealnx_remove_one(struct pci_dev *pdev)
+static void fealnx_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -1950,7 +1950,7 @@ static struct pci_driver fealnx_driver = {
.name = "fealnx",
.id_table = fealnx_pci_tbl,
.probe = fealnx_init_one,
- .remove = __devexit_p(fealnx_remove_one),
+ .remove = fealnx_remove_one,
};
static int __init fealnx_init(void)
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index feff51664dcf..5ba6e1cbd346 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -92,4 +92,13 @@ config GIANFAR
This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
and MPC86xx family of chips, and the FEC on the 8540.
+config FEC_PTP
+ bool "PTP Hardware Clock (PHC)"
+ depends on FEC && ARCH_MXC
+ select PTP_1588_CLOCK
+ default y if SOC_IMX6Q
+ --help---
+ Say Y here if you want to use PTP Hardware Clock (PHC) in the
+ driver. Only the basic clock operations have been implemented.
+
endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 3d1839afff65..d4d19b3d00ae 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -3,6 +3,7 @@
#
obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_PTP) += fec_ptp.o
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index fffd20528b5d..0704bcab178a 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -140,21 +140,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#endif
#endif /* CONFIG_M5272 */
-/* The number of Tx and Rx buffers. These are allocated from the page
- * pool. The code may assume these are power of two, so it it best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter. We just use
- * the skbuffer directly.
- */
-#define FEC_ENET_RX_PAGES 8
-#define FEC_ENET_RX_FRSIZE 2048
-#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
-#define FEC_ENET_TX_FRSIZE 2048
-#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE 16 /* Must be power of two */
-#define TX_RING_MOD_MASK 15 /* for this to work */
-
#if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
#error "FEC: descriptor ring size constants too large"
#endif
@@ -179,9 +164,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#define PKT_MINBUF_SIZE 64
#define PKT_MAXBLR_SIZE 1520
-/* This device has up to three irqs on some platforms */
-#define FEC_IRQ_NUM 3
-
/*
* The 5270/5271/5280/5282/532x RX control register also contains maximum frame
* size bits. Other FEC hardware does not, so we need to take that into
@@ -194,61 +176,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#define OPT_FRAME_SIZE 0
#endif
-/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors. The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller. The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions. The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct fec_enet_private {
- /* Hardware registers of the FEC device */
- void __iomem *hwp;
-
- struct net_device *netdev;
-
- struct clk *clk_ipg;
- struct clk *clk_ahb;
-
- /* The saved address of a sent-in-place packet/buffer, for skfree(). */
- unsigned char *tx_bounce[TX_RING_SIZE];
- struct sk_buff* tx_skbuff[TX_RING_SIZE];
- struct sk_buff* rx_skbuff[RX_RING_SIZE];
- ushort skb_cur;
- ushort skb_dirty;
-
- /* CPM dual port RAM relative addresses */
- dma_addr_t bd_dma;
- /* Address of Rx and Tx buffers */
- struct bufdesc *rx_bd_base;
- struct bufdesc *tx_bd_base;
- /* The next free ring entry */
- struct bufdesc *cur_rx, *cur_tx;
- /* The ring entries to be free()ed */
- struct bufdesc *dirty_tx;
-
- uint tx_full;
- /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
- spinlock_t hw_lock;
-
- struct platform_device *pdev;
-
- int opened;
- int dev_id;
-
- /* Phylib and MDIO interface */
- struct mii_bus *mii_bus;
- struct phy_device *phy_dev;
- int mii_timeout;
- uint phy_speed;
- phy_interface_t phy_interface;
- int link;
- int full_duplex;
- struct completion mdio_done;
- int irq[FEC_IRQ_NUM];
-};
-
/* FEC MII MMFR bits definition */
#define FEC_MMFR_ST (1 << 30)
#define FEC_MMFR_OP_READ (2 << 28)
@@ -353,6 +280,17 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
| BD_ENET_TX_LAST | BD_ENET_TX_TC);
bdp->cbd_sc = status;
+#ifdef CONFIG_FEC_PTP
+ bdp->cbd_bdu = 0;
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+ fep->hwts_tx_en)) {
+ bdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ } else {
+
+ bdp->cbd_esc = BD_ENET_TX_INT;
+ }
+#endif
/* Trigger transmission start */
writel(0, fep->hwp + FEC_X_DES_ACTIVE);
@@ -510,10 +448,17 @@ fec_restart(struct net_device *ndev, int duplex)
writel(1 << 8, fep->hwp + FEC_X_WMRK);
}
+#ifdef CONFIG_FEC_PTP
+ ecntl |= (1 << 4);
+#endif
+
/* And last, enable the transmit and receive processing */
writel(ecntl, fep->hwp + FEC_ECNTRL);
writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+#ifdef CONFIG_FEC_PTP
+ fec_ptp_start_cyclecounter(ndev);
+#endif
/* Enable interrupts we wish to service */
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
@@ -599,6 +544,19 @@ fec_enet_tx(struct net_device *ndev)
ndev->stats.tx_packets++;
}
+#ifdef CONFIG_FEC_PTP
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+ struct skb_shared_hwtstamps shhwtstamps;
+ unsigned long flags;
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ shhwtstamps.hwtstamp = ns_to_ktime(
+ timecounter_cyc2time(&fep->tc, bdp->ts));
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+#endif
if (status & BD_ENET_TX_READY)
printk("HEY! Enet xmit interrupt and TX_READY.\n");
@@ -725,6 +683,21 @@ fec_enet_rx(struct net_device *ndev)
skb_put(skb, pkt_len - 4); /* Make room */
skb_copy_to_linear_data(skb, data, pkt_len - 4);
skb->protocol = eth_type_trans(skb, ndev);
+#ifdef CONFIG_FEC_PTP
+ /* Get receive timestamp from the skb */
+ if (fep->hwts_rx_en) {
+ struct skb_shared_hwtstamps *shhwtstamps =
+ skb_hwtstamps(skb);
+ unsigned long flags;
+
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ shhwtstamps->hwtstamp = ns_to_ktime(
+ timecounter_cyc2time(&fep->tc, bdp->ts));
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+ }
+#endif
if (!skb_defer_rx_timestamp(skb))
netif_rx(skb);
}
@@ -739,6 +712,12 @@ rx_processing_done:
status |= BD_ENET_RX_EMPTY;
bdp->cbd_sc = status;
+#ifdef CONFIG_FEC_PTP
+ bdp->cbd_esc = BD_ENET_RX_INT;
+ bdp->cbd_prot = 0;
+ bdp->cbd_bdu = 0;
+#endif
+
/* Update BD pointer to next entry */
if (status & BD_ENET_RX_WRAP)
bdp = fep->rx_bd_base;
@@ -1178,6 +1157,10 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
if (!phydev)
return -ENODEV;
+#ifdef CONFIG_FEC_PTP
+ if (cmd == SIOCSHWTSTAMP)
+ return fec_ptp_ioctl(ndev, rq, cmd);
+#endif
return phy_mii_ioctl(phydev, rq, cmd);
}
@@ -1224,6 +1207,9 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
bdp->cbd_sc = BD_ENET_RX_EMPTY;
+#ifdef CONFIG_FEC_PTP
+ bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
bdp++;
}
@@ -1237,6 +1223,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp->cbd_sc = 0;
bdp->cbd_bufaddr = 0;
+
+#ifdef CONFIG_FEC_PTP
+ bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
bdp++;
}
@@ -1494,7 +1484,7 @@ static int fec_enet_init(struct net_device *ndev)
}
#ifdef CONFIG_OF
-static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
+static int fec_get_phy_mode_dt(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1504,7 +1494,7 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
return -ENODEV;
}
-static void __devinit fec_reset_phy(struct platform_device *pdev)
+static void fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
int msec = 1;
@@ -1543,7 +1533,7 @@ static inline void fec_reset_phy(struct platform_device *pdev)
}
#endif /* CONFIG_OF */
-static int __devinit
+static int
fec_probe(struct platform_device *pdev)
{
struct fec_enet_private *fep;
@@ -1638,9 +1628,19 @@ fec_probe(struct platform_device *pdev)
goto failed_clk;
}
+#ifdef CONFIG_FEC_PTP
+ fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
+ if (IS_ERR(fep->clk_ptp)) {
+ ret = PTR_ERR(fep->clk_ptp);
+ goto failed_clk;
+ }
+#endif
+
clk_prepare_enable(fep->clk_ahb);
clk_prepare_enable(fep->clk_ipg);
-
+#ifdef CONFIG_FEC_PTP
+ clk_prepare_enable(fep->clk_ptp);
+#endif
reg_phy = devm_regulator_get(&pdev->dev, "phy");
if (!IS_ERR(reg_phy)) {
ret = regulator_enable(reg_phy);
@@ -1668,6 +1668,10 @@ fec_probe(struct platform_device *pdev)
if (ret)
goto failed_register;
+#ifdef CONFIG_FEC_PTP
+ fec_ptp_init(ndev, pdev);
+#endif
+
return 0;
failed_register:
@@ -1677,6 +1681,9 @@ failed_init:
failed_regulator:
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
+#ifdef CONFIG_FEC_PTP
+ clk_disable_unprepare(fep->clk_ptp);
+#endif
failed_pin:
failed_clk:
for (i = 0; i < FEC_IRQ_NUM; i++) {
@@ -1694,7 +1701,7 @@ failed_alloc_etherdev:
return ret;
}
-static int __devexit
+static int
fec_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1709,6 +1716,12 @@ fec_drv_remove(struct platform_device *pdev)
if (irq > 0)
free_irq(irq, ndev);
}
+#ifdef CONFIG_FEC_PTP
+ del_timer_sync(&fep->time_keep);
+ clk_disable_unprepare(fep->clk_ptp);
+ if (fep->ptp_clock)
+ ptp_clock_unregister(fep->ptp_clock);
+#endif
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
iounmap(fep->hwp);
@@ -1777,7 +1790,7 @@ static struct platform_driver fec_driver = {
},
.id_table = fec_devtype,
.probe = fec_probe,
- .remove = __devexit_p(fec_drv_remove),
+ .remove = fec_drv_remove,
};
module_platform_driver(fec_driver);
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 8408c627b195..c5a3bc1475c7 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -13,6 +13,12 @@
#define FEC_H
/****************************************************************************/
+#ifdef CONFIG_FEC_PTP
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+#endif
+
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
@@ -88,6 +94,13 @@ struct bufdesc {
unsigned short cbd_datlen; /* Data length */
unsigned short cbd_sc; /* Control and status info */
unsigned long cbd_bufaddr; /* Buffer address */
+#ifdef CONFIG_FEC_PTP
+ unsigned long cbd_esc;
+ unsigned long cbd_prot;
+ unsigned long cbd_bdu;
+ unsigned long ts;
+ unsigned short res0[4];
+#endif
};
#else
struct bufdesc {
@@ -147,6 +160,112 @@ struct bufdesc {
#define BD_ENET_TX_CSL ((ushort)0x0001)
#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
+/*enhanced buffer desciptor control/status used by Ethernet transmit*/
+#define BD_ENET_TX_INT 0x40000000
+#define BD_ENET_TX_TS 0x20000000
+
+
+/* This device has up to three irqs on some platforms */
+#define FEC_IRQ_NUM 3
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+
+#define FEC_ENET_RX_PAGES 8
+#define FEC_ENET_RX_FRSIZE 2048
+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define FEC_ENET_TX_FRSIZE 2048
+#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+
+#define BD_ENET_RX_INT 0x00800000
+#define BD_ENET_RX_PTP ((ushort)0x0400)
+
+/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fec_enet_private {
+ /* Hardware registers of the FEC device */
+ void __iomem *hwp;
+
+ struct net_device *netdev;
+
+ struct clk *clk_ipg;
+ struct clk *clk_ahb;
+#ifdef CONFIG_FEC_PTP
+ struct clk *clk_ptp;
+#endif
+
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ unsigned char *tx_bounce[TX_RING_SIZE];
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses */
+ dma_addr_t bd_dma;
+ /* Address of Rx and Tx buffers */
+ struct bufdesc *rx_bd_base;
+ struct bufdesc *tx_bd_base;
+ /* The next free ring entry */
+ struct bufdesc *cur_rx, *cur_tx;
+ /* The ring entries to be free()ed */
+ struct bufdesc *dirty_tx;
+
+ uint tx_full;
+ /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
+ spinlock_t hw_lock;
+
+ struct platform_device *pdev;
+
+ int opened;
+ int dev_id;
+
+ /* Phylib and MDIO interface */
+ struct mii_bus *mii_bus;
+ struct phy_device *phy_dev;
+ int mii_timeout;
+ uint phy_speed;
+ phy_interface_t phy_interface;
+ int link;
+ int full_duplex;
+ struct completion mdio_done;
+ int irq[FEC_IRQ_NUM];
+
+#ifdef CONFIG_FEC_PTP
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_caps;
+ unsigned long last_overflow_check;
+ spinlock_t tmreg_lock;
+ struct cyclecounter cc;
+ struct timecounter tc;
+ int rx_hwtstamp_filter;
+ u32 base_incval;
+ u32 cycle_speed;
+ int hwts_rx_en;
+ int hwts_tx_en;
+ struct timer_list time_keep;
+#endif
+
+};
+
+#ifdef CONFIG_FEC_PTP
+void fec_ptp_init(struct net_device *ndev, 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);
+#endif
/****************************************************************************/
#endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 2933d08b036e..817d081d2cd8 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -845,7 +845,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
/* OF Driver */
/* ======================================================================== */
-static int __devinit mpc52xx_fec_probe(struct platform_device *op)
+static int mpc52xx_fec_probe(struct platform_device *op)
{
int rv;
struct net_device *ndev;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
new file mode 100644
index 000000000000..c40526c78c20
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -0,0 +1,383 @@
+/*
+ * Fast Ethernet Controller (ENET) PTP driver for MX6x.
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+
+#include "fec.h"
+
+/* FEC 1588 register bits */
+#define FEC_T_CTRL_SLAVE 0x00002000
+#define FEC_T_CTRL_CAPTURE 0x00000800
+#define FEC_T_CTRL_RESTART 0x00000200
+#define FEC_T_CTRL_PERIOD_RST 0x00000030
+#define FEC_T_CTRL_PERIOD_EN 0x00000010
+#define FEC_T_CTRL_ENABLE 0x00000001
+
+#define FEC_T_INC_MASK 0x0000007f
+#define FEC_T_INC_OFFSET 0
+#define FEC_T_INC_CORR_MASK 0x00007f00
+#define FEC_T_INC_CORR_OFFSET 8
+
+#define FEC_ATIME_CTRL 0x400
+#define FEC_ATIME 0x404
+#define FEC_ATIME_EVT_OFFSET 0x408
+#define FEC_ATIME_EVT_PERIOD 0x40c
+#define FEC_ATIME_CORR 0x410
+#define FEC_ATIME_INC 0x414
+#define FEC_TS_TIMESTAMP 0x418
+
+#define FEC_CC_MULT (1 << 31)
+/**
+ * fec_ptp_read - read raw cycle counter (to be used by time counter)
+ * @cc: the cyclecounter structure
+ *
+ * this function reads the cyclecounter registers and is called by the
+ * cyclecounter structure used to construct a ns counter from the
+ * arbitrary fixed point registers
+ */
+static cycle_t fec_ptp_read(const struct cyclecounter *cc)
+{
+ struct fec_enet_private *fep =
+ container_of(cc, struct fec_enet_private, cc);
+ u32 tempval;
+
+ tempval = readl(fep->hwp + FEC_ATIME_CTRL);
+ tempval |= FEC_T_CTRL_CAPTURE;
+ writel(tempval, fep->hwp + FEC_ATIME_CTRL);
+
+ return readl(fep->hwp + FEC_ATIME);
+}
+
+/**
+ * fec_ptp_start_cyclecounter - create the cycle counter from hw
+ * @ndev: network device
+ *
+ * this function initializes the timecounter and cyclecounter
+ * structures for use in generated a ns counter from the arbitrary
+ * fixed point cycles registers in the hardware.
+ */
+void fec_ptp_start_cyclecounter(struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ unsigned long flags;
+ int inc;
+
+ inc = 1000000000 / clk_get_rate(fep->clk_ptp);
+
+ /* grab the ptp lock */
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+ /* 1ns counter */
+ writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC);
+
+ /* use free running count */
+ writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD);
+
+ writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL);
+
+ memset(&fep->cc, 0, sizeof(fep->cc));
+ fep->cc.read = fec_ptp_read;
+ fep->cc.mask = CLOCKSOURCE_MASK(32);
+ fep->cc.shift = 31;
+ fep->cc.mult = FEC_CC_MULT;
+
+ /* reset the ns time counter */
+ timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
+
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+}
+
+/**
+ * fec_ptp_adjfreq - adjust ptp cycle frequency
+ * @ptp: the ptp clock structure
+ * @ppb: parts per billion adjustment from base
+ *
+ * Adjust the frequency of the ptp cycle counter by the
+ * indicated ppb from the base frequency.
+ *
+ * Because ENET hardware frequency adjust is complex,
+ * using software method to do that.
+ */
+static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ u64 diff;
+ unsigned long flags;
+ int neg_adj = 0;
+ u32 mult = FEC_CC_MULT;
+
+ struct fec_enet_private *fep =
+ container_of(ptp, struct fec_enet_private, ptp_caps);
+
+ if (ppb < 0) {
+ ppb = -ppb;
+ neg_adj = 1;
+ }
+
+ diff = mult;
+ diff *= ppb;
+ diff = div_u64(diff, 1000000000ULL);
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ /*
+ * dummy read to set cycle_last in tc to now.
+ * So use adjusted mult to calculate when next call
+ * timercounter_read.
+ */
+ timecounter_read(&fep->tc);
+
+ fep->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+ return 0;
+}
+
+/**
+ * fec_ptp_adjtime
+ * @ptp: the ptp clock structure
+ * @delta: offset to adjust the cycle counter by
+ *
+ * adjust the timer by resetting the timecounter structure.
+ */
+static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct fec_enet_private *fep =
+ container_of(ptp, struct fec_enet_private, ptp_caps);
+ unsigned long flags;
+ u64 now;
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+ now = timecounter_read(&fep->tc);
+ now += delta;
+
+ /* reset the timecounter */
+ timecounter_init(&fep->tc, &fep->cc, now);
+
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+ return 0;
+}
+
+/**
+ * fec_ptp_gettime
+ * @ptp: the ptp clock structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * read the timecounter and return the correct value on ns,
+ * after converting it into a struct timespec.
+ */
+static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ struct fec_enet_private *adapter =
+ container_of(ptp, struct fec_enet_private, ptp_caps);
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+ ns = timecounter_read(&adapter->tc);
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+/**
+ * fec_ptp_settime
+ * @ptp: the ptp clock structure
+ * @ts: the timespec containing the new time for the cycle counter
+ *
+ * reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ */
+static int fec_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ struct fec_enet_private *fep =
+ container_of(ptp, struct fec_enet_private, ptp_caps);
+
+ u64 ns;
+ unsigned long flags;
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ timecounter_init(&fep->tc, &fep->cc, ns);
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+ return 0;
+}
+
+/**
+ * fec_ptp_enable
+ * @ptp: the ptp clock structure
+ * @rq: the requested feature to change
+ * @on: whether to enable or disable the feature
+ *
+ */
+static int fec_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * fec_ptp_hwtstamp_ioctl - control hardware time stamping
+ * @ndev: pointer to net_device
+ * @ifreq: ioctl data
+ * @cmd: particular ioctl requested
+ */
+int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ struct hwtstamp_config config;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ fep->hwts_tx_en = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ fep->hwts_tx_en = 1;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ if (fep->hwts_rx_en)
+ fep->hwts_rx_en = 0;
+ config.rx_filter = HWTSTAMP_FILTER_NONE;
+ break;
+
+ default:
+ /*
+ * register RXMTRL must be set in order to do V1 packets,
+ * therefore it is not possible to time stamp both V1 Sync and
+ * Delay_Req messages and hardware does not support
+ * timestamping all packets => return error
+ */
+ fep->hwts_rx_en = 1;
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ }
+
+ 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
+ */
+static void fec_time_keep(unsigned long _data)
+{
+ struct fec_enet_private *fep = (struct fec_enet_private *)_data;
+ u64 ns;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ ns = timecounter_read(&fep->tc);
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+ mod_timer(&fep->time_keep, jiffies + HZ);
+}
+
+/**
+ * fec_ptp_init
+ * @ndev: The FEC network adapter
+ *
+ * This function performs the required steps for enabling ptp
+ * support. If ptp support has already been loaded it simply calls the
+ * cyclecounter init routine and exits.
+ */
+
+void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ fep->ptp_caps.owner = THIS_MODULE;
+ snprintf(fep->ptp_caps.name, 16, "fec ptp");
+
+ fep->ptp_caps.max_adj = 250000000;
+ fep->ptp_caps.n_alarm = 0;
+ fep->ptp_caps.n_ext_ts = 0;
+ fep->ptp_caps.n_per_out = 0;
+ fep->ptp_caps.pps = 0;
+ fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
+ fep->ptp_caps.adjtime = fec_ptp_adjtime;
+ fep->ptp_caps.gettime = fec_ptp_gettime;
+ fep->ptp_caps.settime = fec_ptp_settime;
+ fep->ptp_caps.enable = fec_ptp_enable;
+
+ spin_lock_init(&fep->tmreg_lock);
+
+ fec_ptp_start_cyclecounter(ndev);
+
+ init_timer(&fep->time_keep);
+ fep->time_keep.data = (unsigned long)fep;
+ fep->time_keep.function = fec_time_keep;
+ fep->time_keep.expires = jiffies + HZ;
+ add_timer(&fep->time_keep);
+
+ fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
+ if (IS_ERR(fep->ptp_clock)) {
+ fep->ptp_clock = NULL;
+ pr_err("ptp_clock_register failed\n");
+ } else {
+ pr_info("registered PHC device on %s\n", ndev->name);
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 2b7633f766d9..e9879c5af7ba 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1004,7 +1004,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
};
static struct of_device_id fs_enet_match[];
-static int __devinit fs_enet_probe(struct platform_device *ofdev)
+static int fs_enet_probe(struct platform_device *ofdev)
{
const struct of_device_id *match;
struct net_device *ndev;
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
index 151453309401..2bafbd37c247 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
@@ -108,8 +108,7 @@ static struct mdiobb_ops bb_ops = {
.get_mdio_data = mdio_read,
};
-static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
- struct device_node *np)
+static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np)
{
struct resource res;
const u32 *data;
@@ -150,7 +149,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
return 0;
}
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
+static int fs_enet_mdio_probe(struct platform_device *ofdev)
{
struct mii_bus *new_bus;
struct bb_info *bitbang;
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index cdf702a59485..18e8ef203736 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -102,7 +102,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
}
static struct of_device_id fs_enet_mdio_fec_match[];
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
+static int fs_enet_mdio_probe(struct platform_device *ofdev)
{
const struct of_device_id *match;
struct resource res;
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 19ac096cb07b..bffb2edd6858 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -210,7 +210,7 @@ static int gfar_init_bds(struct net_device *ndev)
skb = gfar_new_skb(ndev);
if (!skb) {
netdev_err(ndev, "Can't allocate RX buffers\n");
- goto err_rxalloc_fail;
+ return -ENOMEM;
}
rx_queue->rx_skbuff[j] = skb;
@@ -223,10 +223,6 @@ static int gfar_init_bds(struct net_device *ndev)
}
return 0;
-
-err_rxalloc_fail:
- free_skb_resources(priv);
- return -ENOMEM;
}
static int gfar_alloc_skb_resources(struct net_device *ndev)
@@ -1359,7 +1355,11 @@ static int gfar_restore(struct device *dev)
return 0;
}
- gfar_init_bds(ndev);
+ if (gfar_init_bds(ndev)) {
+ free_skb_resources(priv);
+ return -ENOMEM;
+ }
+
init_registers(ndev);
gfar_set_mac_address(ndev);
gfar_init_mac(ndev);
@@ -1712,6 +1712,7 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue)
tx_queue->tx_skbuff[i] = NULL;
}
kfree(tx_queue->tx_skbuff);
+ tx_queue->tx_skbuff = NULL;
}
static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
@@ -1735,6 +1736,7 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
rxbdp++;
}
kfree(rx_queue->rx_skbuff);
+ rx_queue->rx_skbuff = NULL;
}
/* If there are any tx skbs or rx skbs still around, free them.
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index 1afb5ea2a984..418068b941b1 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -189,7 +189,7 @@ static int xgmac_mdio_reset(struct mii_bus *bus)
return ret;
}
-static int __devinit xgmac_mdio_probe(struct platform_device *pdev)
+static int xgmac_mdio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mii_bus *bus;
@@ -240,7 +240,7 @@ err_ioremap:
return ret;
}
-static int __devexit xgmac_mdio_remove(struct platform_device *pdev)
+static int xgmac_mdio_remove(struct platform_device *pdev)
{
struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
index 3f4391bede81..e3c7c697fc45 100644
--- a/drivers/net/ethernet/hp/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -308,7 +308,7 @@ static void wait(void)
* Read board id and convert to string.
* Effectively same code as decode_eisa_sig
*/
-static __devinit const char *hp100_read_id(int ioaddr)
+static const char *hp100_read_id(int ioaddr)
{
int i;
static char str[HP100_SIG_LEN];
@@ -447,8 +447,8 @@ static const struct net_device_ops hp100_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
- u_char bus, struct pci_dev *pci_dev)
+static int hp100_probe1(struct net_device *dev, int ioaddr, u_char bus,
+ struct pci_dev *pci_dev)
{
int i;
int err = -ENODEV;
@@ -2866,7 +2866,7 @@ static int __init hp100_eisa_probe (struct device *gendev)
return err;
}
-static int __devexit hp100_eisa_remove (struct device *gendev)
+static int hp100_eisa_remove(struct device *gendev)
{
struct net_device *dev = dev_get_drvdata(gendev);
cleanup_dev(dev);
@@ -2878,14 +2878,14 @@ static struct eisa_driver hp100_eisa_driver = {
.driver = {
.name = "hp100",
.probe = hp100_eisa_probe,
- .remove = __devexit_p (hp100_eisa_remove),
+ .remove = hp100_eisa_remove,
}
};
#endif
#ifdef CONFIG_PCI
-static int __devinit hp100_pci_probe (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int hp100_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
int ioaddr;
@@ -2937,7 +2937,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev,
return err;
}
-static void __devexit hp100_pci_remove (struct pci_dev *pdev)
+static void hp100_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2950,7 +2950,7 @@ static struct pci_driver hp100_pci_driver = {
.name = "hp100",
.id_table = hp100_pci_tbl,
.probe = hp100_pci_probe,
- .remove = __devexit_p(hp100_pci_remove),
+ .remove = hp100_pci_remove,
};
#endif
diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index 067db3f13e91..5d353c660068 100644
--- a/drivers/net/ethernet/i825xx/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -72,7 +72,7 @@ static void ether1_timeout(struct net_device *dev);
/* ------------------------------------------------------------------------- */
-static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
+static char version[] = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
#define BUS_16 16
#define BUS_8 8
@@ -250,7 +250,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
} while (thislen);
}
-static int __devinit
+static int
ether1_ramtest(struct net_device *dev, unsigned char byte)
{
unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
@@ -304,7 +304,7 @@ ether1_reset (struct net_device *dev)
return BUS_16;
}
-static int __devinit
+static int
ether1_init_2(struct net_device *dev)
{
int i;
@@ -638,12 +638,6 @@ ether1_txalloc (struct net_device *dev, int size)
static int
ether1_open (struct net_device *dev)
{
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
@@ -972,7 +966,7 @@ ether1_setmulticastlist (struct net_device *dev)
/* ------------------------------------------------------------------------- */
-static void __devinit ether1_banner(void)
+static void ether1_banner(void)
{
static unsigned int version_printed = 0;
@@ -991,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit
+static int
ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
@@ -1052,7 +1046,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit ether1_remove(struct expansion_card *ec)
+static void ether1_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
@@ -1070,7 +1064,7 @@ static const struct ecard_id ether1_ids[] = {
static struct ecard_driver ether1_driver = {
.probe = ether1_probe,
- .remove = __devexit_p(ether1_remove),
+ .remove = ether1_remove,
.id_table = ether1_ids,
.drv = {
.name = "ether1",
diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
index 6eba352c52e0..f42f1b707733 100644
--- a/drivers/net/ethernet/i825xx/lasi_82596.c
+++ b/drivers/net/ethernet/i825xx/lasi_82596.c
@@ -150,7 +150,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
#define LAN_PROM_ADDR 0xF0810000
-static int __devinit
+static int
lan_init_chip(struct parisc_device *dev)
{
struct net_device *netdevice;
@@ -195,7 +195,7 @@ lan_init_chip(struct parisc_device *dev)
return retval;
}
-static int __devexit lan_remove_chip (struct parisc_device *pdev)
+static int lan_remove_chip(struct parisc_device *pdev)
{
struct net_device *dev = parisc_get_drvdata(pdev);
struct i596_private *lp = netdev_priv(dev);
@@ -219,10 +219,10 @@ static struct parisc_driver lan_driver = {
.name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
- .remove = __devexit_p(lan_remove_chip),
+ .remove = lan_remove_chip,
};
-static int __devinit lasi_82596_init(void)
+static int lasi_82596_init(void)
{
printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
return register_parisc_driver(&lan_driver);
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index 3efbd8dbb63d..f045ea4dc514 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1048,7 +1048,7 @@ static const struct net_device_ops i596_netdev_ops = {
#endif
};
-static int __devinit i82596_probe(struct net_device *dev)
+static int i82596_probe(struct net_device *dev)
{
int i;
struct i596_private *lp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
index 6b2a88817473..4ceae9a30274 100644
--- a/drivers/net/ethernet/i825xx/sni_82596.c
+++ b/drivers/net/ethernet/i825xx/sni_82596.c
@@ -75,7 +75,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
}
-static int __devinit sni_82596_probe(struct platform_device *dev)
+static int sni_82596_probe(struct platform_device *dev)
{
struct net_device *netdevice;
struct i596_private *lp;
@@ -147,7 +147,7 @@ probe_failed_free_mpu:
return retval;
}
-static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+static int sni_82596_driver_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct i596_private *lp = netdev_priv(dev);
@@ -163,14 +163,14 @@ static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
static struct platform_driver sni_82596_driver = {
.probe = sni_82596_probe,
- .remove = __devexit_p(sni_82596_driver_remove),
+ .remove = sni_82596_driver_remove,
.driver = {
.name = sni_82596_string,
.owner = THIS_MODULE,
},
};
-static int __devinit sni_82596_init(void)
+static int sni_82596_init(void)
{
printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
return platform_driver_register(&sni_82596_driver);
diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig
index b9773d229192..6529d31595a7 100644
--- a/drivers/net/ethernet/ibm/Kconfig
+++ b/drivers/net/ethernet/ibm/Kconfig
@@ -6,7 +6,7 @@ config NET_VENDOR_IBM
bool "IBM devices"
default y
depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
- (IBMEBUS && INET && SPARSEMEM)
+ (IBMEBUS && SPARSEMEM)
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -33,8 +33,7 @@ source "drivers/net/ethernet/ibm/emac/Kconfig"
config EHEA
tristate "eHEA Ethernet support"
- depends on IBMEBUS && INET && SPARSEMEM
- select INET_LRO
+ depends on IBMEBUS && SPARSEMEM
---help---
This driver supports the IBM pSeries eHEA ethernet adapter.
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index f4d2da0db1b1..19b64de7124b 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -98,10 +98,10 @@ static struct ehea_fw_handle_array ehea_fw_handles;
static struct ehea_bcmc_reg_array ehea_bcmc_regs;
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
- const struct of_device_id *id);
+static int ehea_probe_adapter(struct platform_device *dev,
+ const struct of_device_id *id);
-static int __devexit ehea_remove(struct platform_device *dev);
+static int ehea_remove(struct platform_device *dev);
static struct of_device_id ehea_device_table[] = {
{
@@ -2909,7 +2909,7 @@ static ssize_t ehea_show_port_id(struct device *dev,
static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
NULL);
-static void __devinit logical_port_release(struct device *dev)
+static void logical_port_release(struct device *dev)
{
struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
of_node_put(port->ofdev.dev.of_node);
@@ -3028,7 +3028,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
ehea_set_ethtool_ops(dev);
dev->hw_features = NETIF_F_SG | NETIF_F_TSO
- | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
+ | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
| NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
| NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
@@ -3257,8 +3257,8 @@ static void ehea_remove_device_sysfs(struct platform_device *dev)
device_remove_file(&dev->dev, &dev_attr_remove_port);
}
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
- const struct of_device_id *id)
+static int ehea_probe_adapter(struct platform_device *dev,
+ const struct of_device_id *id)
{
struct ehea_adapter *adapter;
const u64 *adapter_handle;
@@ -3364,7 +3364,7 @@ out:
return ret;
}
-static int __devexit ehea_remove(struct platform_device *dev)
+static int ehea_remove(struct platform_device *dev)
{
struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
int i;
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index a0fe6e3fce61..256bdb8e1994 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -2261,8 +2261,8 @@ struct emac_depentry {
#define EMAC_DEP_PREV_IDX 5
#define EMAC_DEP_COUNT 6
-static int __devinit emac_check_deps(struct emac_instance *dev,
- struct emac_depentry *deps)
+static int emac_check_deps(struct emac_instance *dev,
+ struct emac_depentry *deps)
{
int i, there = 0;
struct device_node *np;
@@ -2314,8 +2314,8 @@ static void emac_put_deps(struct emac_instance *dev)
of_dev_put(dev->tah_dev);
}
-static int __devinit emac_of_bus_notify(struct notifier_block *nb,
- unsigned long action, void *data)
+static int emac_of_bus_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
{
/* We are only intereted in device addition */
if (action == BUS_NOTIFY_BOUND_DRIVER)
@@ -2323,11 +2323,11 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
return 0;
}
-static struct notifier_block emac_of_bus_notifier __devinitdata = {
+static struct notifier_block emac_of_bus_notifier = {
.notifier_call = emac_of_bus_notify
};
-static int __devinit emac_wait_deps(struct emac_instance *dev)
+static int emac_wait_deps(struct emac_instance *dev)
{
struct emac_depentry deps[EMAC_DEP_COUNT];
int i, err;
@@ -2367,8 +2367,8 @@ static int __devinit emac_wait_deps(struct emac_instance *dev)
return err;
}
-static int __devinit emac_read_uint_prop(struct device_node *np, const char *name,
- u32 *val, int fatal)
+static int emac_read_uint_prop(struct device_node *np, const char *name,
+ u32 *val, int fatal)
{
int len;
const u32 *prop = of_get_property(np, name, &len);
@@ -2382,7 +2382,7 @@ static int __devinit emac_read_uint_prop(struct device_node *np, const char *nam
return 0;
}
-static int __devinit emac_init_phy(struct emac_instance *dev)
+static int emac_init_phy(struct emac_instance *dev)
{
struct device_node *np = dev->ofdev->dev.of_node;
struct net_device *ndev = dev->ndev;
@@ -2518,7 +2518,7 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
return 0;
}
-static int __devinit emac_init_config(struct emac_instance *dev)
+static int emac_init_config(struct emac_instance *dev)
{
struct device_node *np = dev->ofdev->dev.of_node;
const void *p;
@@ -2703,7 +2703,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
.ndo_change_mtu = emac_change_mtu,
};
-static int __devinit emac_probe(struct platform_device *ofdev)
+static int emac_probe(struct platform_device *ofdev)
{
struct net_device *ndev;
struct emac_instance *dev;
@@ -2930,7 +2930,7 @@ static int __devinit emac_probe(struct platform_device *ofdev)
return err;
}
-static int __devexit emac_remove(struct platform_device *ofdev)
+static int emac_remove(struct platform_device *ofdev)
{
struct emac_instance *dev = dev_get_drvdata(&ofdev->dev);
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 479e43e2f1ef..50ea12bfb579 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -33,8 +33,7 @@
static int mal_count;
-int __devinit mal_register_commac(struct mal_instance *mal,
- struct mal_commac *commac)
+int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
{
unsigned long flags;
@@ -517,7 +516,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf)
return regs + 1;
}
-static int __devinit mal_probe(struct platform_device *ofdev)
+static int mal_probe(struct platform_device *ofdev)
{
struct mal_instance *mal;
int err = 0, i, bd_size;
@@ -729,7 +728,7 @@ static int __devinit mal_probe(struct platform_device *ofdev)
return err;
}
-static int __devexit mal_remove(struct platform_device *ofdev)
+static int mal_remove(struct platform_device *ofdev)
{
struct mal_instance *mal = dev_get_drvdata(&ofdev->dev);
@@ -738,13 +737,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
/* Synchronize with scheduled polling */
napi_disable(&mal->napi);
- if (!list_empty(&mal->list)) {
+ if (!list_empty(&mal->list))
/* This is *very* bad */
- printk(KERN_EMERG
+ WARN(1, KERN_EMERG
"mal%d: commac list is not empty on remove!\n",
mal->index);
- WARN_ON(1);
- }
dev_set_drvdata(&ofdev->dev, NULL);
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
index d3123282e18e..39251765b55d 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.c
+++ b/drivers/net/ethernet/ibm/emac/rgmii.c
@@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input)
}
}
-int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode)
+int rgmii_attach(struct platform_device *ofdev, int input, int mode)
{
struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
struct rgmii_regs __iomem *p = dev->base;
@@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
}
-static int __devinit rgmii_probe(struct platform_device *ofdev)
+static int rgmii_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct rgmii_instance *dev;
@@ -289,7 +289,7 @@ static int __devinit rgmii_probe(struct platform_device *ofdev)
return rc;
}
-static int __devexit rgmii_remove(struct platform_device *ofdev)
+static int rgmii_remove(struct platform_device *ofdev)
{
struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
index 872912ef518d..795f1393e2b6 100644
--- a/drivers/net/ethernet/ibm/emac/tah.c
+++ b/drivers/net/ethernet/ibm/emac/tah.c
@@ -23,7 +23,7 @@
#include "emac.h"
#include "core.h"
-int __devinit tah_attach(struct platform_device *ofdev, int channel)
+int tah_attach(struct platform_device *ofdev, int channel)
{
struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
@@ -87,7 +87,7 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf)
return regs + 1;
}
-static int __devinit tah_probe(struct platform_device *ofdev)
+static int tah_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct tah_instance *dev;
@@ -135,7 +135,7 @@ static int __devinit tah_probe(struct platform_device *ofdev)
return rc;
}
-static int __devexit tah_remove(struct platform_device *ofdev)
+static int tah_remove(struct platform_device *ofdev)
{
struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
index 415e9b4d5408..f91202f42125 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.c
+++ b/drivers/net/ethernet/ibm/emac/zmii.c
@@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input)
}
}
-int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode)
+int zmii_attach(struct platform_device *ofdev, int input, int *mode)
{
struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
struct zmii_regs __iomem *p = dev->base;
@@ -231,7 +231,7 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
return regs + 1;
}
-static int __devinit zmii_probe(struct platform_device *ofdev)
+static int zmii_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct zmii_instance *dev;
@@ -282,7 +282,7 @@ static int __devinit zmii_probe(struct platform_device *ofdev)
return rc;
}
-static int __devexit zmii_remove(struct platform_device *ofdev)
+static int zmii_remove(struct platform_device *ofdev)
{
struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index b68d28a130e6..f2fdbb79837e 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1324,8 +1324,7 @@ static const struct net_device_ops ibmveth_netdev_ops = {
#endif
};
-static int __devinit ibmveth_probe(struct vio_dev *dev,
- const struct vio_device_id *id)
+static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
{
int rc, i;
struct net_device *netdev;
@@ -1426,7 +1425,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev,
return 0;
}
-static int __devexit ibmveth_remove(struct vio_dev *dev)
+static int ibmveth_remove(struct vio_dev *dev)
{
struct net_device *netdev = dev_get_drvdata(&dev->dev);
struct ibmveth_adapter *adapter = netdev_priv(netdev);
@@ -1593,7 +1592,7 @@ static int ibmveth_resume(struct device *dev)
return 0;
}
-static struct vio_device_id ibmveth_device_table[] __devinitdata = {
+static struct vio_device_id ibmveth_device_table[] = {
{ "network", "IBM,l-lan"},
{ "", "" }
};
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
index 1b563bb959c2..068d78151658 100644
--- a/drivers/net/ethernet/icplus/ipg.c
+++ b/drivers/net/ethernet/icplus/ipg.c
@@ -2167,7 +2167,7 @@ static const struct ethtool_ops ipg_ethtool_ops = {
.nway_reset = ipg_nway_reset,
};
-static void __devexit ipg_remove(struct pci_dev *pdev)
+static void ipg_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct ipg_nic_private *sp = netdev_priv(dev);
@@ -2199,8 +2199,7 @@ static const struct net_device_ops ipg_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit ipg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
unsigned int i = id->driver_data;
struct ipg_nic_private *sp;
@@ -2296,7 +2295,7 @@ static struct pci_driver ipg_pci_driver = {
.name = IPG_DRIVER_NAME,
.id_table = ipg_pci_tbl,
.probe = ipg_probe,
- .remove = __devexit_p(ipg_remove),
+ .remove = ipg_remove,
};
static int __init ipg_init_module(void)
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 0cafe4fe9406..ddee4060948a 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -93,6 +93,7 @@ config E1000E
config IGB
tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on PCI
+ select PTP_1588_CLOCK
---help---
This driver supports Intel(R) 82575/82576 gigabit ethernet family of
adapters. For more information on how to identify your adapter, go
@@ -120,19 +121,6 @@ config IGB_DCA
driver. DCA is a method for warming the CPU cache before data
is used, with the intent of lessening the impact of cache misses.
-config IGB_PTP
- bool "PTP Hardware Clock (PHC)"
- default n
- depends on IGB && EXPERIMENTAL
- select PPS
- select PTP_1588_CLOCK
- ---help---
- Say Y here if you want to use PTP Hardware Clock (PHC) in the
- driver. Only the basic clock operations have been implemented.
-
- Every timestamp and clock read operations must consult the
- overflow counter to form a correct time value.
-
config IGBVF
tristate "Intel(R) 82576 Virtual Function Ethernet support"
depends on PCI
@@ -178,8 +166,9 @@ config IXGB
config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
- depends on PCI && INET
+ depends on PCI
select MDIO
+ select PTP_1588_CLOCK
---help---
This driver supports Intel(R) 10GbE PCI Express family of
adapters. For more information on how to identify your adapter, go
@@ -222,19 +211,6 @@ config IXGBE_DCB
If unsure, say N.
-config IXGBE_PTP
- bool "PTP Clock Support"
- default n
- depends on IXGBE && EXPERIMENTAL
- select PPS
- select PTP_1588_CLOCK
- ---help---
- Say Y here if you want support for 1588 Timestamping with a
- PHC device, using the PTP 1588 Clock support. This is
- required to enable timestamping support for the device.
-
- If unsure, say N.
-
config IXGBEVF
tristate "Intel(R) 82599 Virtual Function Ethernet support"
depends on PCI_MSI
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 29ce9bd27f94..a59f0779e1c3 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2829,8 +2829,7 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_set_features = e100_set_features,
};
-static int __devinit e100_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct nic *nic;
@@ -2981,7 +2980,7 @@ err_out_free_dev:
return err;
}
-static void __devexit e100_remove(struct pci_dev *pdev)
+static void e100_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3167,7 +3166,7 @@ static struct pci_driver e100_driver = {
.name = DRV_NAME,
.id_table = e100_id_table,
.probe = e100_probe,
- .remove = __devexit_p(e100_remove),
+ .remove = e100_remove,
#ifdef CONFIG_PM
/* Power Management hooks */
.suspend = e100_suspend,
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 9089d00f1421..14e30515f6aa 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1671,7 +1671,7 @@ static void e1000_get_wol(struct net_device *netdev,
/* apply any specific unsupported masks here */
switch (hw->device_id) {
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
- /* KSP3 does not suppport UCAST wake-ups */
+ /* KSP3 does not support UCAST wake-ups */
wol->supported &= ~WAKE_UCAST;
if (adapter->wol & E1000_WUFC_EX)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index 3d6839528761..8fedd2451538 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -107,6 +107,7 @@ u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
};
static DEFINE_SPINLOCK(e1000_eeprom_lock);
+static DEFINE_SPINLOCK(e1000_phy_lock);
/**
* e1000_set_phy_type - Set the phy type member in the hw struct.
@@ -2830,19 +2831,25 @@ static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
{
u32 ret_val;
+ unsigned long flags;
e_dbg("e1000_read_phy_reg");
+ spin_lock_irqsave(&e1000_phy_lock, flags);
+
if ((hw->phy_type == e1000_phy_igp) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(u16) reg_addr);
- if (ret_val)
+ if (ret_val) {
+ spin_unlock_irqrestore(&e1000_phy_lock, flags);
return ret_val;
+ }
}
ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
+ spin_unlock_irqrestore(&e1000_phy_lock, flags);
return ret_val;
}
@@ -2965,19 +2972,25 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
{
u32 ret_val;
+ unsigned long flags;
e_dbg("e1000_write_phy_reg");
+ spin_lock_irqsave(&e1000_phy_lock, flags);
+
if ((hw->phy_type == e1000_phy_igp) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(u16) reg_addr);
- if (ret_val)
+ if (ret_val) {
+ spin_unlock_irqrestore(&e1000_phy_lock, flags);
return ret_val;
+ }
}
ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
+ spin_unlock_irqrestore(&e1000_phy_lock, flags);
return ret_val;
}
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 222bfaff4622..294da56b824c 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -111,7 +111,7 @@ void e1000_update_stats(struct e1000_adapter *adapter);
static int e1000_init_module(void);
static void e1000_exit_module(void);
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit e1000_remove(struct pci_dev *pdev);
+static void e1000_remove(struct pci_dev *pdev);
static int e1000_alloc_queues(struct e1000_adapter *adapter);
static int e1000_sw_init(struct e1000_adapter *adapter);
static int e1000_open(struct net_device *netdev);
@@ -202,7 +202,7 @@ static struct pci_driver e1000_driver = {
.name = e1000_driver_name,
.id_table = e1000_pci_tbl,
.probe = e1000_probe,
- .remove = __devexit_p(e1000_remove),
+ .remove = e1000_remove,
#ifdef CONFIG_PM
/* Power Management Hooks */
.suspend = e1000_suspend,
@@ -938,8 +938,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter,
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit e1000_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct e1000_adapter *adapter;
@@ -1273,7 +1272,7 @@ err_pci_reg:
* memory.
**/
-static void __devexit e1000_remove(struct pci_dev *pdev)
+static void e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1309,7 +1308,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
* e1000_init_hw_struct MUST be called before this function
**/
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+static int e1000_sw_init(struct e1000_adapter *adapter)
{
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
@@ -1340,7 +1339,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
* number of queues at compile-time.
**/
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
+static int e1000_alloc_queues(struct e1000_adapter *adapter)
{
adapter->tx_ring = kcalloc(adapter->num_tx_queues,
sizeof(struct e1000_tx_ring), GFP_KERNEL);
diff --git a/drivers/net/ethernet/intel/e1000/e1000_param.c b/drivers/net/ethernet/intel/e1000/e1000_param.c
index 1301eba8b57a..750fc0194f37 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_param.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_param.c
@@ -45,7 +45,7 @@
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
#define E1000_PARAM(X, desc) \
- static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
+ static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
static unsigned int num_##X; \
module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
@@ -205,9 +205,9 @@ struct e1000_option {
} arg;
};
-static int __devinit e1000_validate_option(unsigned int *value,
- const struct e1000_option *opt,
- struct e1000_adapter *adapter)
+static int e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
+ struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -268,7 +268,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter);
* in a variable in the adapter structure.
**/
-void __devinit e1000_check_options(struct e1000_adapter *adapter)
+void e1000_check_options(struct e1000_adapter *adapter)
{
struct e1000_option opt;
int bd = adapter->bd_number;
@@ -534,7 +534,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on fiber adapters
**/
-static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
+static void e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
if (num_Speed > bd) {
@@ -560,7 +560,7 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on copper adapters
**/
-static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
+static void e1000_check_copper_options(struct e1000_adapter *adapter)
{
struct e1000_option opt;
unsigned int speed, dplx, an;
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index 4dd18a1f45d2..e73c2c355993 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -26,8 +26,7 @@
*******************************************************************************/
-/*
- * 80003ES2LAN Gigabit Ethernet Controller (Copper)
+/* 80003ES2LAN Gigabit Ethernet Controller (Copper)
* 80003ES2LAN Gigabit Ethernet Controller (Serdes)
*/
@@ -80,7 +79,8 @@
1 = 50-80M
2 = 80-110M
3 = 110-140M
- 4 = >140M */
+ 4 = >140M
+ */
/* Kumeran Mode Control Register (Page 193, Register 16) */
#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800
@@ -95,8 +95,7 @@
/* In-Band Control Register (Page 194, Register 18) */
#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */
-/*
- * A table for the GG82563 cable length where the range is defined
+/* A table for the GG82563 cable length where the range is defined
* with a lower bound at "index" and the upper bound at
* "index + 5".
*/
@@ -183,8 +182,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
- /*
- * Added to a constant, "size" becomes the left-shift value
+ /* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
@@ -375,8 +373,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
if (!(swfw_sync & (fwmask | swmask)))
break;
- /*
- * Firmware currently using resource (fwmask)
+ /* Firmware currently using resource (fwmask)
* or other software thread using resource (swmask)
*/
e1000e_put_hw_semaphore(hw);
@@ -442,8 +439,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
page_select = GG82563_PHY_PAGE_SELECT;
} else {
- /*
- * Use Alternative Page Select register to access
+ /* Use Alternative Page Select register to access
* registers 30 and 31
*/
page_select = GG82563_PHY_PAGE_SELECT_ALT;
@@ -457,8 +453,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
}
if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
- /*
- * The "ready" bit in the MDIC register may be incorrectly set
+ /* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
@@ -513,8 +508,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
page_select = GG82563_PHY_PAGE_SELECT;
} else {
- /*
- * Use Alternative Page Select register to access
+ /* Use Alternative Page Select register to access
* registers 30 and 31
*/
page_select = GG82563_PHY_PAGE_SELECT_ALT;
@@ -528,8 +522,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
}
if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
- /*
- * The "ready" bit in the MDIC register may be incorrectly set
+ /* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
@@ -618,8 +611,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
u16 phy_data;
bool link;
- /*
- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+ /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
* forced whenever speed and duplex are forced.
*/
ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -657,8 +649,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
return ret_val;
if (!link) {
- /*
- * We didn't get link.
+ /* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = e1000e_phy_reset_dsp(hw);
@@ -677,8 +668,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Resetting the phy means we need to verify the TX_CLK corresponds
+ /* Resetting the phy means we need to verify the TX_CLK corresponds
* to the link speed. 10Mbps -> 2.5MHz, else 25MHz.
*/
phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
@@ -687,8 +677,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
else
phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
- /*
- * In addition, we must re-enable CRS on Tx for both half and full
+ /* In addition, we must re-enable CRS on Tx for both half and full
* duplex.
*/
phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
@@ -766,8 +755,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
s32 ret_val;
u16 kum_reg_data;
- /*
- * Prevent the PCI-E bus from sticking if there is no TLP connection
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000e_disable_pcie_master(hw);
@@ -899,8 +887,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
hw->dev_spec.e80003es2lan.mdic_wa_enable = false;
}
- /*
- * Clear all of the statistics registers (clear on read). It is
+ /* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@@ -945,8 +932,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
reg |= (1 << 28);
ew32(TARC(1), reg);
- /*
- * Disable IPv6 extension header parsing because some malformed
+ /* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
reg = er32(RFCTL);
@@ -979,8 +965,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Options:
+ /* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
* 1 - MDI mode
@@ -1006,8 +991,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
break;
}
- /*
- * Options:
+ /* Options:
* disable_polarity_correction = 0 (default)
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
@@ -1065,8 +1049,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Do not init these registers when the HW is in IAMT mode, since the
+ /* Do not init these registers when the HW is in IAMT mode, since the
* firmware will have already initialized them. We only initialize
* them if the HW is not in IAMT mode.
*/
@@ -1087,8 +1070,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Workaround: Disable padding in Kumeran interface in the MAC
+ /* Workaround: Disable padding in Kumeran interface in the MAC
* and in the PHY to avoid CRC errors.
*/
ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data);
@@ -1121,8 +1103,7 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
ew32(CTRL, ctrl);
- /*
- * Set the mac to wait the maximum time between each
+ /* Set the mac to wait the maximum time between each
* iteration and increase the max iterations when
* polling the phy; this fixes erroneous timeouts at 10Mbps.
*/
@@ -1352,8 +1333,7 @@ static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
{
s32 ret_val = 0;
- /*
- * If there's an alternate MAC address place it in RAR0
+ /* If there's an alternate MAC address place it in RAR0
* so that it will override the Si installed default perm
* address.
*/
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index c98586408005..c77d010d5c59 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -26,8 +26,7 @@
*******************************************************************************/
-/*
- * 82571EB Gigabit Ethernet Controller
+/* 82571EB Gigabit Ethernet Controller
* 82571EB Gigabit Ethernet Controller (Copper)
* 82571EB Gigabit Ethernet Controller (Fiber)
* 82571EB Dual Port Gigabit Mezzanine Adapter
@@ -191,8 +190,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
if (((eecd >> 15) & 0x3) == 0x3) {
nvm->type = e1000_nvm_flash_hw;
nvm->word_size = 2048;
- /*
- * Autonomous Flash update bit must be cleared due
+ /* Autonomous Flash update bit must be cleared due
* to Flash update issue.
*/
eecd &= ~E1000_EECD_AUPDEN;
@@ -204,8 +202,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
nvm->type = e1000_nvm_eeprom_spi;
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
- /*
- * Added to a constant, "size" becomes the left-shift value
+ /* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
@@ -291,8 +288,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
/* FWSM register */
mac->has_fwsm = true;
- /*
- * ARC supported; valid only if manageability features are
+ /* ARC supported; valid only if manageability features are
* enabled.
*/
mac->arc_subsystem_valid = !!(er32(FWSM) &
@@ -314,8 +310,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
break;
}
- /*
- * Ensure that the inter-port SWSM.SMBI lock bit is clear before
+ /* Ensure that the inter-port SWSM.SMBI lock bit is clear before
* first NVM or PHY access. This should be done for single-port
* devices, and for one port only on dual-port devices so that
* for those devices we can still use the SMBI lock to synchronize
@@ -352,11 +347,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
}
- /*
- * Initialize device specific counter of SMBI acquisition
- * timeouts.
- */
- hw->dev_spec.e82571.smb_counter = 0;
+ /* Initialize device specific counter of SMBI acquisition timeouts. */
+ hw->dev_spec.e82571.smb_counter = 0;
return 0;
}
@@ -445,8 +437,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- /*
- * The 82571 firmware may still be configuring the PHY.
+ /* The 82571 firmware may still be configuring the PHY.
* In this case, we cannot access the PHY until the
* configuration is done. So we explicitly set the
* PHY ID.
@@ -492,8 +483,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
s32 fw_timeout = hw->nvm.word_size + 1;
s32 i = 0;
- /*
- * If we have timedout 3 times on trying to acquire
+ /* If we have timedout 3 times on trying to acquire
* the inter-port SMBI semaphore, there is old code
* operating on the other port, and it is not
* releasing SMBI. Modify the number of times that
@@ -787,8 +777,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * If our nvm is an EEPROM, then we're done
+ /* If our nvm is an EEPROM, then we're done
* otherwise, commit the checksum to the flash NVM.
*/
if (hw->nvm.type != e1000_nvm_flash_hw)
@@ -806,8 +795,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
/* Reset the firmware if using STM opcode. */
if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
- /*
- * The enabling of and the actual reset must be done
+ /* The enabling of and the actual reset must be done
* in two write cycles.
*/
ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
@@ -867,8 +855,7 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
u32 i, eewr = 0;
s32 ret_val = 0;
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -957,8 +944,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
} else {
data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
@@ -1002,8 +988,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
u32 ctrl, ctrl_ext, eecd, tctl;
s32 ret_val;
- /*
- * Prevent the PCI-E bus from sticking if there is no TLP connection
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000e_disable_pcie_master(hw);
@@ -1021,8 +1006,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
usleep_range(10000, 20000);
- /*
- * Must acquire the MDIO ownership before MAC reset.
+ /* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset.
*/
switch (hw->mac.type) {
@@ -1067,8 +1051,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
/* We don't want to continue accessing MAC registers. */
return ret_val;
- /*
- * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+ /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
* Need to wait for Phy configuration completion before accessing
* NVM and Phy.
*/
@@ -1076,8 +1059,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- /*
- * REQ and GNT bits need to be cleared when using AUTO_RD
+ /* REQ and GNT bits need to be cleared when using AUTO_RD
* to access the EEPROM.
*/
eecd = er32(EECD);
@@ -1138,8 +1120,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
e_dbg("Initializing the IEEE VLAN\n");
mac->ops.clear_vfta(hw);
- /* Setup the receive address. */
- /*
+ /* Setup the receive address.
* If, however, a locally administered address was assigned to the
* 82571, we must reserve a RAR for it to work around an issue where
* resetting one port will reload the MAC on the other port.
@@ -1183,8 +1164,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
break;
}
- /*
- * Clear all of the statistics registers (clear on read). It is
+ /* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@@ -1281,8 +1261,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(PBA_ECC, reg);
}
- /*
- * Workaround for hardware errata.
+ /* Workaround for hardware errata.
* Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
*/
if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) {
@@ -1291,8 +1270,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(CTRL_EXT, reg);
}
- /*
- * Disable IPv6 extension header parsing because some malformed
+ /* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
if (hw->mac.type <= e1000_82573) {
@@ -1309,8 +1287,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
reg |= (1 << 22);
ew32(GCR, reg);
- /*
- * Workaround for hardware errata.
+ /* Workaround for hardware errata.
* apply workaround for hardware errata documented in errata
* docs Fixes issue where some error prone or unreliable PCIe
* completions are occurring, particularly with ASPM enabled.
@@ -1344,8 +1321,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
case e1000_82574:
case e1000_82583:
if (hw->mng_cookie.vlan_id != 0) {
- /*
- * The VFTA is a 4096b bit-field, each identifying
+ /* The VFTA is a 4096b bit-field, each identifying
* a single VLAN ID. The following operations
* determine which 32b entry (i.e. offset) into the
* array we want to set the VLAN ID (i.e. bit) of
@@ -1362,8 +1338,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
break;
}
for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
- /*
- * If the offset we want to clear is the same offset of the
+ /* If the offset we want to clear is the same offset of the
* manageability VLAN ID, then clear all bits except that of
* the manageability unit.
*/
@@ -1401,8 +1376,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
ctrl = hw->mac.ledctl_mode2;
if (!(E1000_STATUS_LU & er32(STATUS))) {
- /*
- * If no link, then turn LED on by setting the invert bit
+ /* If no link, then turn LED on by setting the invert bit
* for each LED that's "on" (0x0E) in ledctl_mode2.
*/
for (i = 0; i < 4; i++)
@@ -1427,8 +1401,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
u16 receive_errors = 0;
s32 ret_val = 0;
- /*
- * Read PHY Receive Error counter first, if its is max - all F's then
+ /* Read PHY Receive Error counter first, if its is max - all F's then
* read the Base1000T status register If both are max then PHY is hung.
*/
ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
@@ -1458,8 +1431,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
**/
static s32 e1000_setup_link_82571(struct e1000_hw *hw)
{
- /*
- * 82573 does not have a word in the NVM to determine
+ /* 82573 does not have a word in the NVM to determine
* the default flow control setting, so we explicitly
* set it to full.
*/
@@ -1526,8 +1498,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- /*
- * If SerDes loopback mode is entered, there is no form
+ /* If SerDes loopback mode is entered, there is no form
* of reset to take the adapter out of that mode. So we
* have to explicitly take the adapter out of loopback
* mode. This prevents drivers from twiddling their thumbs
@@ -1584,8 +1555,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
switch (mac->serdes_link_state) {
case e1000_serdes_link_autoneg_complete:
if (!(status & E1000_STATUS_LU)) {
- /*
- * We have lost link, retry autoneg before
+ /* We have lost link, retry autoneg before
* reporting link failure
*/
mac->serdes_link_state =
@@ -1598,8 +1568,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
break;
case e1000_serdes_link_forced_up:
- /*
- * If we are receiving /C/ ordered sets, re-enable
+ /* If we are receiving /C/ ordered sets, re-enable
* auto-negotiation in the TXCW register and disable
* forced link in the Device Control register in an
* attempt to auto-negotiate with our link partner.
@@ -1619,8 +1588,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
case e1000_serdes_link_autoneg_progress:
if (rxcw & E1000_RXCW_C) {
- /*
- * We received /C/ ordered sets, meaning the
+ /* We received /C/ ordered sets, meaning the
* link partner has autonegotiated, and we can
* trust the Link Up (LU) status bit.
*/
@@ -1636,8 +1604,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
e_dbg("AN_PROG -> DOWN\n");
}
} else {
- /*
- * The link partner did not autoneg.
+ /* The link partner did not autoneg.
* Force link up and full duplex, and change
* state to forced.
*/
@@ -1660,8 +1627,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
case e1000_serdes_link_down:
default:
- /*
- * The link was down but the receiver has now gained
+ /* The link was down but the receiver has now gained
* valid sync, so lets see if we can bring the link
* up.
*/
@@ -1679,8 +1645,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
mac->serdes_link_state = e1000_serdes_link_down;
e_dbg("ANYSTATE -> DOWN\n");
} else {
- /*
- * Check several times, if SYNCH bit and CONFIG
+ /* Check several times, if SYNCH bit and CONFIG
* bit both are consistently 1 then simply ignore
* the IV bit and restart Autoneg
*/
@@ -1780,8 +1745,7 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
/* If workaround is activated... */
if (state)
- /*
- * Hold a copy of the LAA in RAR[14] This is done so that
+ /* Hold a copy of the LAA in RAR[14] This is done so that
* between the time RAR[0] gets clobbered and the time it
* gets fixed, the actual LAA is in one of the RARs and no
* incoming packets directed to this port are dropped.
@@ -1810,8 +1774,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
if (nvm->type != e1000_nvm_flash_hw)
return 0;
- /*
- * Check bit 4 of word 10h. If it is 0, firmware is done updating
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
* 10h-12h. Checksum may need to be fixed.
*/
ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
@@ -1819,8 +1782,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
return ret_val;
if (!(data & 0x10)) {
- /*
- * Read 0x23 and check bit 15. This bit is a 1
+ /* Read 0x23 and check bit 15. This bit is a 1
* when the checksum has already been fixed. If
* the checksum is still wrong and this bit is a
* 1, we need to return bad checksum. Otherwise,
@@ -1852,8 +1814,7 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
if (hw->mac.type == e1000_82571) {
s32 ret_val = 0;
- /*
- * If there's an alternate MAC address place it in RAR0
+ /* If there's an alternate MAC address place it in RAR0
* so that it will override the Si installed default perm
* address.
*/
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index 76edbc1be33b..02a12b69555f 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -185,8 +185,7 @@
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
-/*
- * Use byte values for the following shift parameters
+/* Use byte values for the following shift parameters
* Usage:
* psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
* E1000_PSRCTL_BSIZE0_MASK) |
@@ -242,8 +241,7 @@
#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
-/*
- * Bit definitions for the Management Data IO (MDIO) and Management Data
+/* Bit definitions for the Management Data IO (MDIO) and Management Data
* Clock (MDC) pins in the Device Control Register.
*/
@@ -424,8 +422,7 @@
#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */
-/*
- * This defines the bits that are set in the Interrupt Mask
+/* This defines the bits that are set in the Interrupt Mask
* Set/Read Register. Each bit is documented below:
* o RXT0 = Receiver Timer Interrupt (ring 0)
* o TXDW = Transmit Descriptor Written Back
@@ -475,8 +472,7 @@
/* 802.1q VLAN Packet Size */
#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
-/* Receive Address */
-/*
+/* Receive Address
* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor.
* Technically, we have 16 spots. However, we reserve one of these spots
@@ -723,8 +719,7 @@
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
#define MAX_PHY_MULTI_PAGE_REG 0xF
-/* Bit definitions for valid PHY IDs. */
-/*
+/* Bit definitions for valid PHY IDs.
* I = Integrated
* E = External
*/
@@ -762,8 +757,7 @@
#define M88E1000_PSCR_AUTO_X_1000T 0x0040
/* Auto crossover enabled all speeds */
#define M88E1000_PSCR_AUTO_X_MODE 0x0060
-/*
- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
+/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
* 0=Normal 10BASE-T Rx Threshold
*/
#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
@@ -779,14 +773,12 @@
#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+/* Number of times we will attempt to autonegotiate before downshifting if we
* are the master
*/
#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+/* Number of times we will attempt to autonegotiate before downshifting if we
* are the slave
*/
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
@@ -808,8 +800,7 @@
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
((reg) & MAX_PHY_REG_ADDRESS))
-/*
- * Bits...
+/* Bits...
* 15-5: page
* 4-0: register offset
*/
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 04668b47a1df..6782a2eea1bc 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -161,8 +161,7 @@ struct e1000_info;
/* Time to wait before putting the device into D3 if there's no link (in ms). */
#define LINK_TIMEOUT 100
-/*
- * Count for polling __E1000_RESET condition every 10-20msec.
+/* Count for polling __E1000_RESET condition every 10-20msec.
* Experimentation has shown the reset can take approximately 210msec.
*/
#define E1000_CHECK_RESET_COUNT 25
@@ -172,8 +171,7 @@ struct e1000_info;
#define BURST_RDTR 0x20
#define BURST_RADV 0x20
-/*
- * in the case of WTHRESH, it appears at least the 82571/2 hardware
+/* in the case of WTHRESH, it appears at least the 82571/2 hardware
* writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
* WTHRESH=4, so a setting of 5 gives the most efficient bus
* utilization but to avoid possible Tx stalls, set it to 1
@@ -214,8 +212,7 @@ struct e1000_ps_page {
u64 dma; /* must be u64 - written to hw */
};
-/*
- * wrappers around a pointer to a socket buffer,
+/* wrappers around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
*/
struct e1000_buffer {
@@ -305,9 +302,7 @@ struct e1000_adapter {
u16 tx_itr;
u16 rx_itr;
- /*
- * Tx
- */
+ /* Tx */
struct e1000_ring *tx_ring /* One per active queue */
____cacheline_aligned_in_smp;
u32 tx_fifo_limit;
@@ -340,9 +335,7 @@ struct e1000_adapter {
u32 tx_fifo_size;
u32 tx_dma_failed;
- /*
- * Rx
- */
+ /* Rx */
bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
int work_to_do) ____cacheline_aligned_in_smp;
void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count,
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index c11ac2756667..f95bc6ee1c22 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -214,7 +214,8 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
mac->autoneg = 0;
/* Make sure dplx is at most 1 bit and lsb of speed is not set
- * for the switch() below to work */
+ * for the switch() below to work
+ */
if ((spd & 1) || (dplx & ~1))
goto err_inval;
@@ -263,8 +264,7 @@ static int e1000_set_settings(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- /*
- * When SoL/IDER sessions are active, autoneg/speed/duplex
+ /* When SoL/IDER sessions are active, autoneg/speed/duplex
* cannot be changed
*/
if (hw->phy.ops.check_reset_block &&
@@ -273,8 +273,7 @@ static int e1000_set_settings(struct net_device *netdev,
return -EINVAL;
}
- /*
- * MDI setting is only allowed when autoneg enabled because
+ /* MDI setting is only allowed when autoneg enabled because
* some hardware doesn't allow MDI setting when speed or
* duplex is forced.
*/
@@ -316,8 +315,7 @@ static int e1000_set_settings(struct net_device *netdev,
/* MDI-X => 2; MDI => 1; Auto => 3 */
if (ecmd->eth_tp_mdix_ctrl) {
- /*
- * fix up the value for auto (3 => 0) as zero is mapped
+ /* fix up the value for auto (3 => 0) as zero is mapped
* internally to auto
*/
if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
@@ -454,8 +452,8 @@ static void e1000_get_regs(struct net_device *netdev,
regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */
/* ethtool doesn't use anything past this point, so all this
- * code is likely legacy junk for apps that may or may not
- * exist */
+ * code is likely legacy junk for apps that may or may not exist
+ */
if (hw->phy.type == e1000_phy_m88) {
e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
regs_buff[13] = (u32)phy_data; /* cable length */
@@ -598,8 +596,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
if (ret_val)
goto out;
- /*
- * Update the checksum over the first part of the EEPROM if needed
+ /* Update the checksum over the first part of the EEPROM if needed
* and flush shadow RAM for applicable controllers
*/
if ((first_word <= NVM_CHECKSUM_REG) ||
@@ -623,8 +620,7 @@ static void e1000_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->version, e1000e_driver_version,
sizeof(drvinfo->version));
- /*
- * EEPROM image version # is reported as firmware version # for
+ /* EEPROM image version # is reported as firmware version # for
* PCI-E controllers
*/
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
@@ -708,8 +704,7 @@ static int e1000_set_ringparam(struct net_device *netdev,
e1000e_down(adapter);
- /*
- * We can't just free everything and then setup again, because the
+ /* We can't just free everything and then setup again, because the
* ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
* structs. First, attempt to allocate new resources...
*/
@@ -813,8 +808,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
u32 mask;
u32 wlock_mac = 0;
- /*
- * The status register is Read Only, so a write should fail.
+ /* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
switch (mac->type) {
@@ -996,8 +990,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
}
if (!shared_int) {
- /*
- * Disable the interrupt to be reported in
+ /* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was posted to the bus, the
@@ -1015,8 +1008,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
}
}
- /*
- * Enable the interrupt to be reported in
+ /* Enable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was not posted to the bus, the
@@ -1034,8 +1026,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
}
if (!shared_int) {
- /*
- * Disable the other interrupts to be reported in
+ /* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
* an interrupt was posted to the bus, the
@@ -1378,8 +1369,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
hw->phy.type == e1000_phy_m88) {
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
} else {
- /*
- * Set the ILOS bit on the fiber Nic if half duplex link is
+ /* Set the ILOS bit on the fiber Nic if half duplex link is
* detected.
*/
if ((er32(STATUS) & E1000_STATUS_FD) == 0)
@@ -1388,8 +1378,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
ew32(CTRL, ctrl_reg);
- /*
- * Disable the receiver on the PHY so when a cable is plugged in, the
+ /* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
if (hw->phy.type == e1000_phy_m88)
@@ -1408,8 +1397,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
/* special requirements for 82571/82572 fiber adapters */
- /*
- * jump through hoops to make sure link is up because serdes
+ /* jump through hoops to make sure link is up because serdes
* link is hardwired up
*/
ctrl |= E1000_CTRL_SLU;
@@ -1429,8 +1417,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
ew32(CTRL, ctrl);
}
- /*
- * special write to serdes control register to enable SerDes analog
+ /* special write to serdes control register to enable SerDes analog
* loopback
*/
#define E1000_SERDES_LB_ON 0x410
@@ -1448,8 +1435,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
u32 ctrlext = er32(CTRL_EXT);
u32 ctrl = er32(CTRL);
- /*
- * save CTRL_EXT to restore later, reuse an empty variable (unused
+ /* save CTRL_EXT to restore later, reuse an empty variable (unused
* on mac_type 80003es2lan)
*/
adapter->tx_fifo_head = ctrlext;
@@ -1585,8 +1571,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
ew32(RDT(0), rx_ring->count - 1);
- /*
- * Calculate the loop count based on the largest descriptor ring
+ /* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
* send/receive pairs during each loop
*/
@@ -1627,8 +1612,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
l++;
if (l == rx_ring->count)
l = 0;
- /*
- * time + 20 msecs (200 msecs on 2.4) is more than
+ /* time + 20 msecs (200 msecs on 2.4) is more than
* enough time to complete the receives, if it's
* exceeded, break and error off
*/
@@ -1649,10 +1633,7 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
{
struct e1000_hw *hw = &adapter->hw;
- /*
- * PHY loopback cannot be performed if SoL/IDER
- * sessions are active
- */
+ /* PHY loopback cannot be performed if SoL/IDER sessions are active */
if (hw->phy.ops.check_reset_block &&
hw->phy.ops.check_reset_block(hw)) {
e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
@@ -1686,8 +1667,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
int i = 0;
hw->mac.serdes_has_link = false;
- /*
- * On some blade server designs, link establishment
+ /* On some blade server designs, link establishment
* could take as long as 2-3 minutes
*/
do {
@@ -1701,8 +1681,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
} else {
hw->mac.ops.check_for_link(hw);
if (hw->mac.autoneg)
- /*
- * On some Phy/switch combinations, link establishment
+ /* On some Phy/switch combinations, link establishment
* can take a few seconds more than expected.
*/
msleep(5000);
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index d37bfd96c987..cf217777586c 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -85,8 +85,7 @@ enum e1e_registers {
E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */
E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */
E1000_PSRCTL = 0x02170, /* Packet Split Receive Control - RW */
-/*
- * Convenience macros
+/* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
@@ -800,8 +799,7 @@ struct e1000_mac_operations {
s32 (*read_mac_addr)(struct e1000_hw *);
};
-/*
- * When to use various PHY register access functions:
+/* When to use various PHY register access functions:
*
* Func Caller
* Function Does Does When to use
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index e3a7b07df629..976336547607 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -26,8 +26,7 @@
*******************************************************************************/
-/*
- * 82562G 10/100 Network Connection
+/* 82562G 10/100 Network Connection
* 82562G-2 10/100 Network Connection
* 82562GT 10/100 Network Connection
* 82562GT-2 10/100 Network Connection
@@ -354,8 +353,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
return true;
}
- /*
- * In case the PHY needs to be in mdio slow mode,
+ /* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
hw->phy.ops.release(hw);
@@ -386,8 +384,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
return ret_val;
}
- /*
- * The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is
* inaccessible and resetting the PHY is not blocked, toggle the
* LANPHYPC Value bit to force the interconnect to PCIe mode.
*/
@@ -396,8 +393,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
if (e1000_phy_is_accessible_pchlan(hw))
break;
- /*
- * Before toggling LANPHYPC, see if PHY is accessible by
+ /* Before toggling LANPHYPC, see if PHY is accessible by
* forcing MAC to SMBus mode first.
*/
mac_reg = er32(CTRL_EXT);
@@ -406,8 +402,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
/* fall-through */
case e1000_pch2lan:
- /*
- * Gate automatic PHY configuration by hardware on
+ /* Gate automatic PHY configuration by hardware on
* non-managed 82579
*/
if ((hw->mac.type == e1000_pch2lan) &&
@@ -474,8 +469,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
hw->phy.ops.release(hw);
- /*
- * Reset the PHY before any access to it. Doing so, ensures
+ /* Reset the PHY before any access to it. Doing so, ensures
* that the PHY is in a known good state before we read/write
* PHY registers. The generic reset is sufficient here,
* because we haven't determined the PHY type yet.
@@ -536,8 +530,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
/* fall-through */
case e1000_pch2lan:
case e1000_pch_lpt:
- /*
- * In case the PHY needs to be in mdio slow mode,
+ /* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
ret_val = e1000_set_mdio_slow_mode_hv(hw);
@@ -593,8 +586,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
- /*
- * We may need to do this twice - once for IGP and if that fails,
+ /* We may need to do this twice - once for IGP and if that fails,
* we'll set BM func pointers and try again
*/
ret_val = e1000e_determine_phy_address(hw);
@@ -679,8 +671,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
gfpreg = er32flash(ICH_FLASH_GFPREG);
- /*
- * sector_X_addr is a "sector"-aligned address (4096 bytes)
+ /* sector_X_addr is a "sector"-aligned address (4096 bytes)
* Add 1 to sector_end_addr since this sector is included in
* the overall size.
*/
@@ -690,8 +681,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* flash_base_addr is byte-aligned */
nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
- /*
- * find total size of the NVM, then cut in half since the total
+ /* find total size of the NVM, then cut in half since the total
* size represents two separate NVM banks.
*/
nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
@@ -788,8 +778,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
- /*
- * Gate automatic PHY configuration by hardware on managed
+ /* Gate automatic PHY configuration by hardware on managed
* 82579 and i217
*/
if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) &&
@@ -840,8 +829,7 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
goto release;
e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability);
- /*
- * EEE is not supported in 100Half, so ignore partner's EEE
+ /* EEE is not supported in 100Half, so ignore partner's EEE
* in 100 ability if full-duplex is not advertised.
*/
e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg);
@@ -869,8 +857,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
bool link;
u16 phy_reg;
- /*
- * We only want to go out to the PHY registers to see if Auto-Neg
+ /* We only want to go out to the PHY registers to see if Auto-Neg
* has completed and/or if our link status has changed. The
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
@@ -878,8 +865,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (!mac->get_link_status)
return 0;
- /*
- * First we want to see if the MII Status Register reports
+ /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
@@ -914,8 +900,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Workaround for PCHx parts in half-duplex:
+ /* Workaround for PCHx parts in half-duplex:
* Set the number of preambles removed from the packet
* when it is passed from the PHY to the MAC to prevent
* the MAC from misinterpreting the packet type.
@@ -932,8 +917,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
break;
}
- /*
- * Check if there was DownShift, must be checked
+ /* Check if there was DownShift, must be checked
* immediately after link-up
*/
e1000e_check_downshift(hw);
@@ -943,22 +927,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * If we are forcing speed/duplex, then we simply return since
+ /* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
if (!mac->autoneg)
return -E1000_ERR_CONFIG;
- /*
- * Auto-Neg is enabled. Auto Speed Detection takes care
+ /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
mac->ops.config_collision_dist(hw);
- /*
- * Configure Flow Control now that Auto-Neg has completed.
+ /* Configure Flow Control now that Auto-Neg has completed.
* First, we need to restore the desired flow control
* settings because we may have had to re-autoneg with a
* different link partner.
@@ -1000,8 +981,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
if (rc)
return rc;
- /*
- * Disable Jumbo Frame support on parts with Intel 10/100 PHY or
+ /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or
* on parts with MACsec enabled in NVM (reflected in CTRL_EXT).
*/
if ((adapter->hw.phy.type == e1000_phy_ife) ||
@@ -1191,8 +1171,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
- /*
- * HW expects these in little endian so we reverse the byte order
+ /* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
rar_low = ((u32)addr[0] |
@@ -1256,8 +1235,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
u32 rar_low, rar_high;
u32 wlock_mac;
- /*
- * HW expects these in little endian so we reverse the byte order
+ /* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
@@ -1277,8 +1255,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
return;
}
- /*
- * The manageability engine (ME) can lock certain SHRAR registers that
+ /* The manageability engine (ME) can lock certain SHRAR registers that
* it is using - those registers are unavailable for use.
*/
if (index < hw->mac.rar_entry_count) {
@@ -1387,8 +1364,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
s32 ret_val = 0;
u16 word_addr, reg_data, reg_addr, phy_page = 0;
- /*
- * Initialize the PHY from the NVM on ICH platforms. This
+ /* Initialize the PHY from the NVM on ICH platforms. This
* is needed due to an issue where the NVM configuration is
* not properly autoloaded after power transitions.
* Therefore, after each PHY reset, we will load the
@@ -1422,8 +1398,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
if (!(data & sw_cfg_mask))
goto release;
- /*
- * Make sure HW does not configure LCD from PHY
+ /* Make sure HW does not configure LCD from PHY
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
@@ -1443,8 +1418,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
if (((hw->mac.type == e1000_pchlan) &&
!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
(hw->mac.type > e1000_pchlan)) {
- /*
- * HW configures the SMBus address and LEDs when the
+ /* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
* When both NVM bits are cleared, SW will configure
* them instead.
@@ -1748,8 +1722,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
}
if (hw->phy.type == e1000_phy_82578) {
- /*
- * Return registers to default by doing a soft reset then
+ /* Return registers to default by doing a soft reset then
* writing 0x3140 to the control register.
*/
if (hw->phy.revision < 2) {
@@ -1769,8 +1742,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Configure the K1 Si workaround during phy reset assuming there is
+ /* Configure the K1 Si workaround during phy reset assuming there is
* link so that it disables K1 if link is in 1Gbps.
*/
ret_val = e1000_k1_gig_workaround_hv(hw, true);
@@ -1853,8 +1825,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
return ret_val;
if (enable) {
- /*
- * Write Rx addresses (rar_entry_count for RAL/H, +4 for
+ /* Write Rx addresses (rar_entry_count for RAL/H, +4 for
* SHRAL/H) and initial CRC values to the MAC
*/
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
@@ -2131,8 +2102,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
udelay(100);
} while ((!data) && --loop);
- /*
- * If basic configuration is incomplete before the above loop
+ /* If basic configuration is incomplete before the above loop
* count reaches 0, loading the configuration from NVM will
* leave the PHY in a bad state possibly resulting in no link.
*/
@@ -2299,8 +2269,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
if (phy->type != e1000_phy_igp_3)
return 0;
- /*
- * Call gig speed drop workaround on LPLU before accessing
+ /* Call gig speed drop workaround on LPLU before accessing
* any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -2319,8 +2288,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
if (phy->type != e1000_phy_igp_3)
return 0;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
@@ -2382,8 +2350,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
if (phy->type != e1000_phy_igp_3)
return 0;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
@@ -2420,8 +2387,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
if (phy->type != e1000_phy_igp_3)
return 0;
- /*
- * Call gig speed drop workaround on LPLU before accessing
+ /* Call gig speed drop workaround on LPLU before accessing
* any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -2589,8 +2555,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
- /*
- * Either we should have a hardware SPI cycle in progress
+ /* Either we should have a hardware SPI cycle in progress
* bit to check against, in order to start a new cycle or
* FDONE bit should be changed in the hardware so that it
* is 1 after hardware reset, which can then be used as an
@@ -2599,8 +2564,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
*/
if (!hsfsts.hsf_status.flcinprog) {
- /*
- * There is no cycle running at present,
+ /* There is no cycle running at present,
* so we can start a cycle.
* Begin by setting Flash Cycle Done.
*/
@@ -2610,8 +2574,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
} else {
s32 i;
- /*
- * Otherwise poll for sometime so the current
+ /* Otherwise poll for sometime so the current
* cycle has a chance to end before giving up.
*/
for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
@@ -2623,8 +2586,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
udelay(1);
}
if (!ret_val) {
- /*
- * Successful in waiting for previous cycle to timeout,
+ /* Successful in waiting for previous cycle to timeout,
* now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
@@ -2753,8 +2715,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
ret_val = e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_READ_COMMAND_TIMEOUT);
- /*
- * Check if FCERR is set to 1, if set to 1, clear it
+ /* Check if FCERR is set to 1, if set to 1, clear it
* and try the whole sequence a few more times, else
* read in (shift in) the Flash Data0, the order is
* least significant byte first msb to lsb
@@ -2767,8 +2728,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
*data = (u16)(flash_data & 0x0000FFFF);
break;
} else {
- /*
- * If we've gotten here, then things are probably
+ /* If we've gotten here, then things are probably
* completely hosed, but if the error condition is
* detected, it won't hurt to give it another try...
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
@@ -2849,8 +2809,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
nvm->ops.acquire(hw);
- /*
- * We're writing to the opposite bank so if we're on bank 1,
+ /* We're writing to the opposite bank so if we're on bank 1,
* write to bank 0 etc. We also need to erase the segment that
* is going to be written
*/
@@ -2875,8 +2834,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
}
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
- /*
- * Determine whether to write the value stored
+ /* Determine whether to write the value stored
* in the other NVM bank or a modified value stored
* in the shadow RAM
*/
@@ -2890,8 +2848,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
break;
}
- /*
- * If the word is 0x13, then make sure the signature bits
+ /* If the word is 0x13, then make sure the signature bits
* (15:14) are 11b until the commit has completed.
* This will allow us to write 10b which indicates the
* signature is valid. We want to do this after the write
@@ -2920,8 +2877,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
break;
}
- /*
- * Don't bother writing the segment valid bits if sector
+ /* Don't bother writing the segment valid bits if sector
* programming failed.
*/
if (ret_val) {
@@ -2930,8 +2886,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
goto release;
}
- /*
- * Finally validate the new segment by setting bit 15:14
+ /* Finally validate the new segment by setting bit 15:14
* to 10b in word 0x13 , this can be done without an
* erase as well since these bits are 11 to start with
* and we need to change bit 14 to 0b
@@ -2948,8 +2903,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto release;
- /*
- * And invalidate the previously valid segment by setting
+ /* And invalidate the previously valid segment by setting
* its signature word (0x13) high_byte to 0b. This can be
* done without an erase because flash erase sets all bits
* to 1's. We can write 1's to 0's without an erase
@@ -2968,8 +2922,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
release:
nvm->ops.release(hw);
- /*
- * Reload the EEPROM, or else modifications will not appear
+ /* Reload the EEPROM, or else modifications will not appear
* until after the next adapter reset.
*/
if (!ret_val) {
@@ -2997,8 +2950,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
s32 ret_val;
u16 data;
- /*
- * Read 0x19 and check bit 6. If this bit is 0, the checksum
+ /* Read 0x19 and check bit 6. If this bit is 0, the checksum
* needs to be fixed. This bit is an indication that the NVM
* was prepared by OEM software and did not calculate the
* checksum...a likely scenario.
@@ -3048,8 +3000,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
pr0.range.wpe = true;
ew32flash(ICH_FLASH_PR0, pr0.regval);
- /*
- * Lock down a subset of GbE Flash Control Registers, e.g.
+ /* Lock down a subset of GbE Flash Control Registers, e.g.
* PR0 to prevent the write-protection from being lifted.
* Once FLOCKDN is set, the registers protected by it cannot
* be written until FLOCKDN is cleared by a hardware reset.
@@ -3109,8 +3060,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
ew32flash(ICH_FLASH_FDATA0, flash_data);
- /*
- * check if FCERR is set to 1 , if set to 1, clear it
+ /* check if FCERR is set to 1 , if set to 1, clear it
* and try the whole sequence a few more times else done
*/
ret_val = e1000_flash_cycle_ich8lan(hw,
@@ -3118,8 +3068,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
if (!ret_val)
break;
- /*
- * If we're here, then things are most likely
+ /* If we're here, then things are most likely
* completely hosed, but if the error condition
* is detected, it won't hurt to give it another
* try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
@@ -3207,8 +3156,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- /*
- * Determine HW Sector size: Read BERASE bits of hw flash status
+ /* Determine HW Sector size: Read BERASE bits of hw flash status
* register
* 00: The Hw sector is 256 bytes, hence we need to erase 16
* consecutive sectors. The start index for the nth Hw sector
@@ -3253,16 +3201,14 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
if (ret_val)
return ret_val;
- /*
- * Write a value 11 (block Erase) in Flash
+ /* Write a value 11 (block Erase) in Flash
* Cycle field in hw flash control
*/
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
- /*
- * Write the last 24 bits of an index within the
+ /* Write the last 24 bits of an index within the
* block into Flash Linear address field in Flash
* Address.
*/
@@ -3274,8 +3220,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
if (!ret_val)
break;
- /*
- * Check if FCERR is set to 1. If 1,
+ /* Check if FCERR is set to 1. If 1,
* clear it and try the whole sequence
* a few more times else Done
*/
@@ -3403,8 +3348,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
ret_val = e1000e_get_bus_info_pcie(hw);
- /*
- * ICH devices are "PCI Express"-ish. They have
+ /* ICH devices are "PCI Express"-ish. They have
* a configuration space, but do not contain
* PCI Express Capability registers, so bus width
* must be hardcoded.
@@ -3429,8 +3373,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
u32 ctrl, reg;
s32 ret_val;
- /*
- * Prevent the PCI-E bus from sticking if there is no TLP connection
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000e_disable_pcie_master(hw);
@@ -3440,8 +3383,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
e_dbg("Masking off all interrupts\n");
ew32(IMC, 0xffffffff);
- /*
- * Disable the Transmit and Receive units. Then delay to allow
+ /* Disable the Transmit and Receive units. Then delay to allow
* any pending transactions to complete before we hit the MAC
* with the global reset.
*/
@@ -3474,15 +3416,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl = er32(CTRL);
if (!hw->phy.ops.check_reset_block(hw)) {
- /*
- * Full-chip reset requires MAC and PHY reset at the same
+ /* Full-chip reset requires MAC and PHY reset at the same
* time to make sure the interface between MAC and the
* external PHY is reset.
*/
ctrl |= E1000_CTRL_PHY_RST;
- /*
- * Gate automatic PHY configuration by hardware on
+ /* Gate automatic PHY configuration by hardware on
* non-managed 82579
*/
if ((hw->mac.type == e1000_pch2lan) &&
@@ -3516,8 +3456,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
return ret_val;
}
- /*
- * For PCH, this write will make sure that any noise
+ /* For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up
* as a bad packet to the DMA engine.
*/
@@ -3569,8 +3508,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
for (i = 0; i < mac->mta_reg_count; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
- /*
- * The 82578 Rx buffer will stall if wakeup is enabled in host and
+ /* The 82578 Rx buffer will stall if wakeup is enabled in host and
* the ME. Disable wakeup by clearing the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
@@ -3600,8 +3538,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
ew32(TXDCTL(1), txdctl);
- /*
- * ICH8 has opposite polarity of no_snoop bits.
+ /* ICH8 has opposite polarity of no_snoop bits.
* By default, we should use snoop behavior.
*/
if (mac->type == e1000_ich8lan)
@@ -3614,8 +3551,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
ew32(CTRL_EXT, ctrl_ext);
- /*
- * Clear all of the statistics registers (clear on read). It is
+ /* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@@ -3676,15 +3612,13 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
ew32(STATUS, reg);
}
- /*
- * work-around descriptor data corruption issue during nfs v2 udp
+ /* work-around descriptor data corruption issue during nfs v2 udp
* traffic, just disable the nfs filtering capability
*/
reg = er32(RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
- /*
- * Disable IPv6 extension header parsing because some malformed
+ /* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
if (hw->mac.type == e1000_ich8lan)
@@ -3709,8 +3643,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
if (hw->phy.ops.check_reset_block(hw))
return 0;
- /*
- * ICH parts do not have a word in the NVM to determine
+ /* ICH parts do not have a word in the NVM to determine
* the default flow control setting, so we explicitly
* set it to full.
*/
@@ -3722,8 +3655,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
hw->fc.requested_mode = e1000_fc_full;
}
- /*
- * Save off the requested flow control mode for use later. Depending
+ /* Save off the requested flow control mode for use later. Depending
* on the link partner's capabilities, we may or may not use this mode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
@@ -3771,8 +3703,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
ew32(CTRL, ctrl);
- /*
- * Set the mac to wait the maximum time between each iteration
+ /* Set the mac to wait the maximum time between each iteration
* and increase the max iterations when polling the phy;
* this fixes erroneous timeouts at 10Mbps.
*/
@@ -3892,8 +3823,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
if (!dev_spec->kmrn_lock_loss_workaround_enabled)
return 0;
- /*
- * Make sure link is up before proceeding. If not just return.
+ /* Make sure link is up before proceeding. If not just return.
* Attempting this while link is negotiating fouled up link
* stability
*/
@@ -3925,8 +3855,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
ew32(PHY_CTRL, phy_ctrl);
- /*
- * Call gig speed drop workaround on Gig disable before accessing
+ /* Call gig speed drop workaround on Gig disable before accessing
* any PHY registers
*/
e1000e_gig_downshift_workaround_ich8lan(hw);
@@ -3983,8 +3912,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
ew32(PHY_CTRL, reg);
- /*
- * Call gig speed drop workaround on Gig disable before
+ /* Call gig speed drop workaround on Gig disable before
* accessing any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -4078,8 +4006,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
goto release;
e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert);
- /*
- * Disable LPLU if both link partners support 100BaseT
+ /* Disable LPLU if both link partners support 100BaseT
* EEE and 100Full is advertised on both ends of the
* link.
*/
@@ -4091,8 +4018,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
E1000_PHY_CTRL_NOND0A_LPLU);
}
- /*
- * For i217 Intel Rapid Start Technology support,
+ /* For i217 Intel Rapid Start Technology support,
* when the system is going into Sx and no manageability engine
* is present, the driver must configure proxy to reset only on
* power good. LPI (Low Power Idle) state must also reset only
@@ -4106,8 +4032,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg);
- /*
- * Set bit enable LPI (EEE) to reset only on
+ /* Set bit enable LPI (EEE) to reset only on
* power good.
*/
e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg);
@@ -4120,8 +4045,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
}
- /*
- * Enable MTA to reset for Intel Rapid Start Technology
+ /* Enable MTA to reset for Intel Rapid Start Technology
* Support
*/
e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
@@ -4175,8 +4099,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
return;
}
- /*
- * For i217 Intel Rapid Start Technology support when the system
+ /* For i217 Intel Rapid Start Technology support when the system
* is transitioning from Sx and no manageability engine is present
* configure SMBus to restore on reset, disable proxy, and enable
* the reset on MTA (Multicast table array).
@@ -4191,8 +4114,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
}
if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
- /*
- * Restore clear on SMB if no manageability engine
+ /* Restore clear on SMB if no manageability engine
* is present
*/
ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
@@ -4298,8 +4220,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
u16 data = (u16)hw->mac.ledctl_mode2;
u32 i, led;
- /*
- * If no link, then turn LED on by setting the invert bit
+ /* If no link, then turn LED on by setting the invert bit
* for each LED that's mode is "link_up" in ledctl_mode2.
*/
if (!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -4329,8 +4250,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
u16 data = (u16)hw->mac.ledctl_mode1;
u32 i, led;
- /*
- * If no link, then turn LED off by clearing the invert bit
+ /* If no link, then turn LED off by clearing the invert bit
* for each LED that's mode is "link_up" in ledctl_mode1.
*/
if (!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -4375,8 +4295,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
} else {
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
- /*
- * When auto config read does not complete, do not
+ /* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c
index a13439928488..54d9dafaf126 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -73,8 +73,7 @@ void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
struct e1000_bus_info *bus = &hw->bus;
u32 reg;
- /*
- * The status register reports the correct function number
+ /* The status register reports the correct function number
* for the device regardless of function swap state.
*/
reg = er32(STATUS);
@@ -210,8 +209,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
return 0;
}
- /*
- * We have a valid alternate MAC address, and we want to treat it the
+ /* We have a valid alternate MAC address, and we want to treat it the
* same as the normal permanent MAC address stored by the HW into the
* RAR. Do this by mapping this address into RAR0.
*/
@@ -233,8 +231,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
- /*
- * HW expects these in little endian so we reverse the byte order
+ /* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
@@ -246,8 +243,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
if (rar_low || rar_high)
rar_high |= E1000_RAH_AV;
- /*
- * Some bridges will combine consecutive 32-bit writes into
+ /* Some bridges will combine consecutive 32-bit writes into
* a single burst write, which will malfunction on some parts.
* The flushes avoid this.
*/
@@ -273,15 +269,13 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
- /*
- * For a mc_filter_type of 0, bit_shift is the number of left-shifts
+ /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
* where 0xFF would still fall within the hash mask.
*/
while (hash_mask >> bit_shift != 0xFF)
bit_shift++;
- /*
- * The portion of the address that is used for the hash table
+ /* The portion of the address that is used for the hash table
* is determined by the mc_filter_type setting.
* The algorithm is such that there is a total of 8 bits of shifting.
* The bit_shift for a mc_filter_type of 0 represents the number of
@@ -423,8 +417,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
s32 ret_val;
bool link;
- /*
- * We only want to go out to the PHY registers to see if Auto-Neg
+ /* We only want to go out to the PHY registers to see if Auto-Neg
* has completed and/or if our link status has changed. The
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
@@ -432,8 +425,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
if (!mac->get_link_status)
return 0;
- /*
- * First we want to see if the MII Status Register reports
+ /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
@@ -446,28 +438,24 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
mac->get_link_status = false;
- /*
- * Check if there was DownShift, must be checked
+ /* Check if there was DownShift, must be checked
* immediately after link-up
*/
e1000e_check_downshift(hw);
- /*
- * If we are forcing speed/duplex, then we simply return since
+ /* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
if (!mac->autoneg)
return -E1000_ERR_CONFIG;
- /*
- * Auto-Neg is enabled. Auto Speed Detection takes care
+ /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
mac->ops.config_collision_dist(hw);
- /*
- * Configure Flow Control now that Auto-Neg has completed.
+ /* Configure Flow Control now that Auto-Neg has completed.
* First, we need to restore the desired flow control
* settings because we may have had to re-autoneg with a
* different link partner.
@@ -498,8 +486,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
status = er32(STATUS);
rxcw = er32(RXCW);
- /*
- * If we don't have link (auto-negotiation failed or link partner
+ /* If we don't have link (auto-negotiation failed or link partner
* cannot auto-negotiate), the cable is plugged in (we have signal),
* and our link partner is not trying to auto-negotiate with us (we
* are receiving idles or data), we need to force link up. We also
@@ -530,8 +517,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
return ret_val;
}
} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
- /*
- * If we are forcing link and we are receiving /C/ ordered
+ /* If we are forcing link and we are receiving /C/ ordered
* sets, re-enable auto-negotiation in the TXCW register
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
@@ -565,8 +551,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
status = er32(STATUS);
rxcw = er32(RXCW);
- /*
- * If we don't have link (auto-negotiation failed or link partner
+ /* If we don't have link (auto-negotiation failed or link partner
* cannot auto-negotiate), and our link partner is not trying to
* auto-negotiate with us (we are receiving idles or data),
* we need to force link up. We also need to give auto-negotiation
@@ -595,8 +580,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
return ret_val;
}
} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
- /*
- * If we are forcing link and we are receiving /C/ ordered
+ /* If we are forcing link and we are receiving /C/ ordered
* sets, re-enable auto-negotiation in the TXCW register
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
@@ -607,8 +591,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
mac->serdes_has_link = true;
} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
- /*
- * If we force link for non-auto-negotiation switch, check
+ /* If we force link for non-auto-negotiation switch, check
* link status based on MAC synchronization for internal
* serdes media type.
*/
@@ -665,8 +648,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
s32 ret_val;
u16 nvm_data;
- /*
- * Read and store word 0x0F of the EEPROM. This word contains bits
+ /* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
* disabling auto-negotiation, and the direction of the
@@ -705,15 +687,13 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
{
s32 ret_val;
- /*
- * In the case of the phy reset being blocked, we already have a link.
+ /* In the case of the phy reset being blocked, we already have a link.
* We do not need to set it up again.
*/
if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
return 0;
- /*
- * If requested flow control is set to default, set flow control
+ /* If requested flow control is set to default, set flow control
* based on the EEPROM flow control settings.
*/
if (hw->fc.requested_mode == e1000_fc_default) {
@@ -722,8 +702,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Save off the requested flow control mode for use later. Depending
+ /* Save off the requested flow control mode for use later. Depending
* on the link partner's capabilities, we may or may not use this mode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
@@ -735,8 +714,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Initialize the flow control address, type, and PAUSE timer
+ /* Initialize the flow control address, type, and PAUSE timer
* registers to their default values. This is done even if flow
* control is disabled, because it does not hurt anything to
* initialize these registers.
@@ -763,8 +741,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
struct e1000_mac_info *mac = &hw->mac;
u32 txcw;
- /*
- * Check for a software override of the flow control settings, and
+ /* Check for a software override of the flow control settings, and
* setup the device accordingly. If auto-negotiation is enabled, then
* software will have to set the "PAUSE" bits to the correct value in
* the Transmit Config Word Register (TXCW) and re-start auto-
@@ -786,8 +763,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
break;
case e1000_fc_rx_pause:
- /*
- * Rx Flow control is enabled and Tx Flow control is disabled
+ /* Rx Flow control is enabled and Tx Flow control is disabled
* by a software over-ride. Since there really isn't a way to
* advertise that we are capable of Rx Pause ONLY, we will
* advertise that we support both symmetric and asymmetric Rx
@@ -797,15 +773,13 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
break;
case e1000_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is disabled,
+ /* Tx Flow control is enabled, and Rx Flow control is disabled,
* by a software over-ride.
*/
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
break;
case e1000_fc_full:
- /*
- * Flow control (both Rx and Tx) is enabled by a software
+ /* Flow control (both Rx and Tx) is enabled by a software
* over-ride.
*/
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
@@ -835,8 +809,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
u32 i, status;
s32 ret_val;
- /*
- * If we have a signal (the cable is plugged in, or assumed true for
+ /* If we have a signal (the cable is plugged in, or assumed true for
* serdes media) then poll for a "Link-Up" indication in the Device
* Status Register. Time-out if a link isn't seen in 500 milliseconds
* seconds (Auto-negotiation should complete in less than 500
@@ -851,8 +824,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
if (i == FIBER_LINK_UP_LIMIT) {
e_dbg("Never got a valid link from auto-neg!!!\n");
mac->autoneg_failed = true;
- /*
- * AutoNeg failed to achieve a link, so we'll call
+ /* AutoNeg failed to achieve a link, so we'll call
* mac->check_for_link. This routine will force the
* link up if we detect a signal. This will allow us to
* communicate with non-autonegotiating link partners.
@@ -894,8 +866,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Since auto-negotiation is enabled, take the link out of reset (the
+ /* Since auto-negotiation is enabled, take the link out of reset (the
* link will be in reset, because we previously reset the chip). This
* will restart auto-negotiation. If auto-negotiation is successful
* then the link-up status bit will be set and the flow control enable
@@ -907,8 +878,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
e1e_flush();
usleep_range(1000, 2000);
- /*
- * For these adapters, the SW definable pin 1 is set when the optics
+ /* For these adapters, the SW definable pin 1 is set when the optics
* detect a signal. If we have a signal, then poll for a "Link-Up"
* indication.
*/
@@ -954,16 +924,14 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
{
u32 fcrtl = 0, fcrth = 0;
- /*
- * Set the flow control receive threshold registers. Normally,
+ /* Set the flow control receive threshold registers. Normally,
* these registers will be set to a default threshold that may be
* adjusted later by the driver's runtime code. However, if the
* ability to transmit pause frames is not enabled, then these
* registers will be set to 0.
*/
if (hw->fc.current_mode & e1000_fc_tx_pause) {
- /*
- * We need to set up the Receive Threshold high and low water
+ /* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of
* XON frames.
*/
@@ -995,8 +963,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
ctrl = er32(CTRL);
- /*
- * Because we didn't get link via the internal auto-negotiation
+ /* Because we didn't get link via the internal auto-negotiation
* mechanism (we either forced link or we got link via PHY
* auto-neg), we have to manually enable/disable transmit an
* receive flow control.
@@ -1057,8 +1024,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
u16 speed, duplex;
- /*
- * Check for the case where we have fiber media and auto-neg failed
+ /* Check for the case where we have fiber media and auto-neg failed
* so we had to force link. In this case, we need to force the
* configuration of the MAC to match the "fc" parameter.
*/
@@ -1076,15 +1042,13 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Check for the case where we have copper media and auto-neg is
+ /* Check for the case where we have copper media and auto-neg is
* enabled. In this case, we need to check and see if Auto-Neg
* has completed, and if so, how the PHY and link partner has
* flow control configured.
*/
if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
- /*
- * Read the MII Status Register and check to see if AutoNeg
+ /* Read the MII Status Register and check to see if AutoNeg
* has completed. We read this twice because this reg has
* some "sticky" (latched) bits.
*/
@@ -1100,8 +1064,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
return ret_val;
}
- /*
- * The AutoNeg process has completed, so we now need to
+ /* The AutoNeg process has completed, so we now need to
* read both the Auto Negotiation Advertisement
* Register (Address 4) and the Auto_Negotiation Base
* Page Ability Register (Address 5) to determine how
@@ -1115,8 +1078,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Two bits in the Auto Negotiation Advertisement Register
+ /* Two bits in the Auto Negotiation Advertisement Register
* (Address 4) and two bits in the Auto Negotiation Base
* Page Ability Register (Address 5) determine flow control
* for both the PHY and the link partner. The following
@@ -1151,8 +1113,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
*/
if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
- /*
- * Now we need to check if the user selected Rx ONLY
+ /* Now we need to check if the user selected Rx ONLY
* of pause frames. In this case, we had to advertise
* FULL flow control because we could not advertise Rx
* ONLY. Hence, we must now check to see if we need to
@@ -1166,8 +1127,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
e_dbg("Flow Control = Rx PAUSE frames only.\n");
}
}
- /*
- * For receiving PAUSE frames ONLY.
+ /* For receiving PAUSE frames ONLY.
*
* LOCAL DEVICE | LINK PARTNER
* PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1181,8 +1141,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
hw->fc.current_mode = e1000_fc_tx_pause;
e_dbg("Flow Control = Tx PAUSE frames only.\n");
}
- /*
- * For transmitting PAUSE frames ONLY.
+ /* For transmitting PAUSE frames ONLY.
*
* LOCAL DEVICE | LINK PARTNER
* PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1196,16 +1155,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
hw->fc.current_mode = e1000_fc_rx_pause;
e_dbg("Flow Control = Rx PAUSE frames only.\n");
} else {
- /*
- * Per the IEEE spec, at this point flow control
+ /* Per the IEEE spec, at this point flow control
* should be disabled.
*/
hw->fc.current_mode = e1000_fc_none;
e_dbg("Flow Control = NONE.\n");
}
- /*
- * Now we need to do one last check... If we auto-
+ /* Now we need to do one last check... If we auto-
* negotiated to HALF DUPLEX, flow control should not be
* enabled per IEEE 802.3 spec.
*/
@@ -1218,8 +1175,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
if (duplex == HALF_DUPLEX)
hw->fc.current_mode = e1000_fc_none;
- /*
- * Now we call a subroutine to actually force the MAC
+ /* Now we call a subroutine to actually force the MAC
* controller to use the correct flow control settings.
*/
ret_val = e1000e_force_mac_fc(hw);
@@ -1520,8 +1476,7 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw)
ledctl_blink = E1000_LEDCTL_LED0_BLINK |
(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
} else {
- /*
- * set the blink bit for each LED that's "on" (0x0E)
+ /* set the blink bit for each LED that's "on" (0x0E)
* in ledctl_mode2
*/
ledctl_blink = hw->mac.ledctl_mode2;
diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c
index bacc950fc684..6dc47beb3adc 100644
--- a/drivers/net/ethernet/intel/e1000e/manage.c
+++ b/drivers/net/ethernet/intel/e1000e/manage.c
@@ -143,8 +143,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
return hw->mac.tx_pkt_filtering;
}
- /*
- * If we can't read from the host interface for whatever
+ /* If we can't read from the host interface for whatever
* reason, disable filtering.
*/
ret_val = e1000_mng_enable_host_if(hw);
@@ -163,8 +162,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
hdr->checksum = 0;
csum = e1000_calculate_checksum((u8 *)hdr,
E1000_MNG_DHCP_COOKIE_LENGTH);
- /*
- * If either the checksums or signature don't match, then
+ /* If either the checksums or signature don't match, then
* the cookie area isn't considered valid, in which case we
* take the safe route of assuming Tx filtering is enabled.
*/
@@ -252,8 +250,7 @@ static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
/* Calculate length in DWORDs */
length >>= 2;
- /*
- * The device driver writes the relevant command block into the
+ /* The device driver writes the relevant command block into the
* ram area.
*/
for (i = 0; i < length; i++) {
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index f444eb0b76d8..fbf75fdca994 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -146,9 +146,11 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
{0, NULL}
};
-/*
+/**
* e1000_regdump - register printout routine
- */
+ * @hw: pointer to the HW structure
+ * @reginfo: pointer to the register info table
+ **/
static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo)
{
int n = 0;
@@ -196,9 +198,10 @@ static void e1000e_dump_ps_pages(struct e1000_adapter *adapter,
}
}
-/*
+/**
* e1000e_dump - Print registers, Tx-ring and Rx-ring
- */
+ * @adapter: board private structure
+ **/
static void e1000e_dump(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -623,8 +626,7 @@ map_skb:
rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
- /*
- * Force memory writes to complete before letting h/w
+ /* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64).
@@ -692,8 +694,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
goto no_buffers;
}
}
- /*
- * Refresh the desc even if buffer_addrs
+ /* Refresh the desc even if buffer_addrs
* didn't change because each write-back
* erases this info.
*/
@@ -726,8 +727,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
- /*
- * Force memory writes to complete before letting h/w
+ /* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64).
@@ -817,7 +817,8 @@ check_page:
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
- * such as IA-64). */
+ * such as IA-64).
+ */
wmb();
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_rdt_wa(rx_ring, i);
@@ -891,8 +892,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
length = le16_to_cpu(rx_desc->wb.upper.length);
- /*
- * !EOP means multiple descriptors were used to store a single
+ /* !EOP means multiple descriptors were used to store a single
* packet, if that's the case we need to toss it. In fact, we
* need to toss every packet with the EOP bit clear and the
* next frame that _does_ have the EOP bit set, as it is by
@@ -933,8 +933,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
total_rx_bytes += length;
total_rx_packets++;
- /*
- * code added for copybreak, this should improve
+ /* code added for copybreak, this should improve
* performance for small packets with large amounts
* of reassembly being done in the stack
*/
@@ -1032,15 +1031,13 @@ static void e1000_print_hw_hang(struct work_struct *work)
if (!adapter->tx_hang_recheck &&
(adapter->flags2 & FLAG2_DMA_BURST)) {
- /*
- * May be block on write-back, flush and detect again
+ /* May be block on write-back, flush and detect again
* flush pending descriptor writebacks to memory
*/
ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
/* execute the writes immediately */
e1e_flush();
- /*
- * Due to rare timing issues, write to TIDV again to ensure
+ /* Due to rare timing issues, write to TIDV again to ensure
* the write is successful
*/
ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
@@ -1169,8 +1166,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
}
if (adapter->detect_tx_hung) {
- /*
- * Detect a transmit hang in hardware, this serializes the
+ /* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i
*/
adapter->detect_tx_hung = false;
@@ -1270,14 +1266,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
skb_put(skb, length);
{
- /*
- * this looks ugly, but it seems compiler issues make
+ /* this looks ugly, but it seems compiler issues make
* it more efficient than reusing j
*/
int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
- /*
- * page alloc/put takes too long and effects small
+ /* page alloc/put takes too long and effects small
* packet throughput, so unsplit small packets and
* save the alloc/put only valid in softirq (napi)
* context to call kmap_*
@@ -1288,8 +1282,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
ps_page = &buffer_info->ps_pages[0];
- /*
- * there is no documentation about how to call
+ /* there is no documentation about how to call
* kmap_atomic, so we can't hold the mapping
* very long
*/
@@ -1486,14 +1479,16 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
skb_shinfo(rxtop)->nr_frags,
buffer_info->page, 0, length);
/* re-use the current skb, we only consumed the
- * page */
+ * page
+ */
buffer_info->skb = skb;
skb = rxtop;
rxtop = NULL;
e1000_consume_page(buffer_info, skb, length);
} else {
/* no chain, got EOP, this buf is the packet
- * copybreak to save the put_page/alloc_page */
+ * copybreak to save the put_page/alloc_page
+ */
if (length <= copybreak &&
skb_tailroom(skb) >= length) {
u8 *vaddr;
@@ -1502,7 +1497,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
length);
kunmap_atomic(vaddr);
/* re-use the page, so don't erase
- * buffer_info->page */
+ * buffer_info->page
+ */
skb_put(skb, length);
} else {
skb_fill_page_desc(skb, 0,
@@ -1656,22 +1652,17 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
struct e1000_hw *hw = &adapter->hw;
u32 icr = er32(ICR);
- /*
- * read ICR disables interrupts using IAM
- */
-
+ /* read ICR disables interrupts using IAM */
if (icr & E1000_ICR_LSC) {
hw->mac.get_link_status = true;
- /*
- * ICH8 workaround-- Call gig speed drop workaround on cable
+ /* ICH8 workaround-- Call gig speed drop workaround on cable
* disconnect (LSC) before accessing any PHY registers
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
schedule_work(&adapter->downshift_task);
- /*
- * 80003ES2LAN workaround-- For packet buffer work-around on
+ /* 80003ES2LAN workaround-- For packet buffer work-around on
* link down event; disable receives here in the ISR and reset
* adapter in watchdog
*/
@@ -1713,31 +1704,27 @@ static irqreturn_t e1000_intr(int irq, void *data)
if (!icr || test_bit(__E1000_DOWN, &adapter->state))
return IRQ_NONE; /* Not our interrupt */
- /*
- * IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
* not set, then the adapter didn't send an interrupt
*/
if (!(icr & E1000_ICR_INT_ASSERTED))
return IRQ_NONE;
- /*
- * Interrupt Auto-Mask...upon reading ICR,
+ /* Interrupt Auto-Mask...upon reading ICR,
* interrupts are masked. No need for the
* IMC write
*/
if (icr & E1000_ICR_LSC) {
hw->mac.get_link_status = true;
- /*
- * ICH8 workaround-- Call gig speed drop workaround on cable
+ /* ICH8 workaround-- Call gig speed drop workaround on cable
* disconnect (LSC) before accessing any PHY registers
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
schedule_work(&adapter->downshift_task);
- /*
- * 80003ES2LAN workaround--
+ /* 80003ES2LAN workaround--
* For packet buffer work-around on link down event;
* disable receives here in the ISR and
* reset adapter in watchdog
@@ -2469,8 +2456,7 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
set_itr_now:
if (new_itr != adapter->itr) {
- /*
- * this attempts to bias the interrupt rate towards Bulk
+ /* this attempts to bias the interrupt rate towards Bulk
* by adding intermediate steps when interrupt rate is
* increasing
*/
@@ -2517,7 +2503,7 @@ void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr)
* e1000_alloc_queues - Allocate memory for all rings
* @adapter: board private structure to initialize
**/
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
+static int e1000_alloc_queues(struct e1000_adapter *adapter)
{
int size = sizeof(struct e1000_ring);
@@ -2740,8 +2726,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
manc = er32(MANC);
- /*
- * enable receiving management packets to the host. this will probably
+ /* enable receiving management packets to the host. this will probably
* generate destination unreachable messages from the host OS, but
* the packets will be handled on SMBUS
*/
@@ -2754,8 +2739,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
break;
case e1000_82574:
case e1000_82583:
- /*
- * Check if IPMI pass-through decision filter already exists;
+ /* Check if IPMI pass-through decision filter already exists;
* if so, enable it.
*/
for (i = 0, j = 0; i < 8; i++) {
@@ -2827,8 +2811,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
u32 txdctl = er32(TXDCTL(0));
txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH |
E1000_TXDCTL_WTHRESH);
- /*
- * set up some performance related parameters to encourage the
+ /* set up some performance related parameters to encourage the
* hardware to use the bus more efficiently in bursts, depends
* on the tx_int_delay to be enabled,
* wthresh = 1 ==> burst write is disabled to avoid Tx stalls
@@ -2845,8 +2828,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
tarc = er32(TARC(0));
- /*
- * set the speed mode bit, we'll clear it if we're not at
+ /* set the speed mode bit, we'll clear it if we're not at
* gigabit link later
*/
#define SPEED_MODE_BIT (1 << 21)
@@ -2967,8 +2949,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
rfctl |= E1000_RFCTL_EXTEN;
ew32(RFCTL, rfctl);
- /*
- * 82571 and greater support packet-split where the protocol
+ /* 82571 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
* placed in pages hanging off of skb_shinfo(skb)->nr_frags.
* In the case of a non-split, skb->data is linearly filled,
@@ -3016,7 +2997,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
/* This is useful for sniffing bad packets. */
if (adapter->netdev->features & NETIF_F_RXALL) {
/* UPE and MPE will be handled by normal PROMISC logic
- * in e1000e_set_rx_mode */
+ * in e1000e_set_rx_mode
+ */
rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
E1000_RCTL_BAM | /* RX All Bcast Pkts */
E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
@@ -3071,8 +3053,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
usleep_range(10000, 20000);
if (adapter->flags2 & FLAG2_DMA_BURST) {
- /*
- * set the writeback threshold (only takes effect if the RDTR
+ /* set the writeback threshold (only takes effect if the RDTR
* is set). set GRAN=1 and write back up to 0x4 worth, and
* enable prefetching of 0x20 Rx descriptors
* granularity = 01
@@ -3083,8 +3064,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE);
ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE);
- /*
- * override the delay timers for enabling bursting, only if
+ /* override the delay timers for enabling bursting, only if
* the value was not set by the user via module options
*/
if (adapter->rx_int_delay == DEFAULT_RDTR)
@@ -3108,8 +3088,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
ew32(CTRL_EXT, ctrl_ext);
e1e_flush();
- /*
- * Setup the HW Rx Head and Tail Descriptor Pointers and
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring
*/
rdba = rx_ring->dma;
@@ -3130,8 +3109,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
ew32(RXCSUM, rxcsum);
if (adapter->hw.mac.type == e1000_pch2lan) {
- /*
- * With jumbo frames, excessive C-state transition
+ /* With jumbo frames, excessive C-state transition
* latencies result in dropped transactions.
*/
if (adapter->netdev->mtu > ETH_DATA_LEN) {
@@ -3216,8 +3194,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev)
if (!netdev_uc_empty(netdev) && rar_entries) {
struct netdev_hw_addr *ha;
- /*
- * write the addresses in reverse order to avoid write
+ /* write the addresses in reverse order to avoid write
* combining
*/
netdev_for_each_uc_addr(ha, netdev) {
@@ -3269,8 +3246,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
if (netdev->flags & IFF_ALLMULTI) {
rctl |= E1000_RCTL_MPE;
} else {
- /*
- * Write addresses to the MTA, if the attempt fails
+ /* Write addresses to the MTA, if the attempt fails
* then we should just turn on promiscuous mode so
* that we can at least receive multicast traffic
*/
@@ -3279,8 +3255,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
rctl |= E1000_RCTL_MPE;
}
e1000e_vlan_filter_enable(adapter);
- /*
- * Write addresses to available RAR registers, if there is not
+ /* Write addresses to available RAR registers, if there is not
* sufficient space to store all the addresses then enable
* unicast promiscuous mode
*/
@@ -3315,8 +3290,7 @@ static void e1000e_setup_rss_hash(struct e1000_adapter *adapter)
for (i = 0; i < 32; i++)
ew32(RETA(i), 0);
- /*
- * Disable raw packet checksumming so that RSS hash is placed in
+ /* Disable raw packet checksumming so that RSS hash is placed in
* descriptor on writeback.
*/
rxcsum = er32(RXCSUM);
@@ -3408,8 +3382,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
ew32(PBA, pba);
if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
- /*
- * To maintain wire speed transmits, the Tx FIFO should be
+ /* To maintain wire speed transmits, the Tx FIFO should be
* large enough to accommodate two full transmit packets,
* rounded up to the next 1KB and expressed in KB. Likewise,
* the Rx FIFO should be large enough to accommodate at least
@@ -3421,8 +3394,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
tx_space = pba >> 16;
/* lower 16 bits has Rx packet buffer allocation size in KB */
pba &= 0xffff;
- /*
- * the Tx fifo also stores 16 bytes of information about the Tx
+ /* the Tx fifo also stores 16 bytes of information about the Tx
* but don't include ethernet FCS because hardware appends it
*/
min_tx_space = (adapter->max_frame_size +
@@ -3435,8 +3407,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
min_rx_space = ALIGN(min_rx_space, 1024);
min_rx_space >>= 10;
- /*
- * If current Tx allocation is less than the min Tx FIFO size,
+ /* If current Tx allocation is less than the min Tx FIFO size,
* and the min Tx FIFO size is less than the current Rx FIFO
* allocation, take space away from current Rx allocation
*/
@@ -3444,8 +3415,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
((min_tx_space - tx_space) < pba)) {
pba -= min_tx_space - tx_space;
- /*
- * if short on Rx space, Rx wins and must trump Tx
+ /* if short on Rx space, Rx wins and must trump Tx
* adjustment
*/
if (pba < min_rx_space)
@@ -3455,8 +3425,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
ew32(PBA, pba);
}
- /*
- * flow control settings
+ /* flow control settings
*
* The high water mark must be low enough to fit one full frame
* (or the size used for early receive) above it in the Rx FIFO.
@@ -3490,8 +3459,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->low_water = fc->high_water - 8;
break;
case e1000_pchlan:
- /*
- * Workaround PCH LOM adapter hangs with certain network
+ /* Workaround PCH LOM adapter hangs with certain network
* loads. If hangs persist, try disabling Tx flow control.
*/
if (adapter->netdev->mtu > ETH_DATA_LEN) {
@@ -3516,8 +3484,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
break;
}
- /*
- * Alignment of Tx data is on an arbitrary byte boundary with the
+ /* Alignment of Tx data is on an arbitrary byte boundary with the
* maximum size per Tx descriptor limited only to the transmit
* allocation of the packet buffer minus 96 bytes with an upper
* limit of 24KB due to receive synchronization limitations.
@@ -3525,8 +3492,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96,
24 << 10);
- /*
- * Disable Adaptive Interrupt Moderation if 2 full packets cannot
+ /* Disable Adaptive Interrupt Moderation if 2 full packets cannot
* fit in receive buffer.
*/
if (adapter->itr_setting & 0x3) {
@@ -3549,8 +3515,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
/* Allow time for pending master requests to run */
mac->ops.reset_hw(hw);
- /*
- * For parts with AMT enabled, let the firmware know
+ /* For parts with AMT enabled, let the firmware know
* that the network interface is in control
*/
if (adapter->flags & FLAG_HAS_AMT)
@@ -3579,8 +3544,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) &&
!(adapter->flags & FLAG_SMART_POWER_DOWN)) {
u16 phy_data = 0;
- /*
- * speed up time to link by disabling smart power down, ignore
+ /* speed up time to link by disabling smart power down, ignore
* the return value of this function because there is nothing
* different we would do if it failed
*/
@@ -3628,8 +3592,7 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
/* execute the writes immediately */
e1e_flush();
- /*
- * due to rare timing issues, write to TIDV/RDTR again to ensure the
+ /* due to rare timing issues, write to TIDV/RDTR again to ensure the
* write is successful
*/
ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
@@ -3647,8 +3610,7 @@ void e1000e_down(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 tctl, rctl;
- /*
- * signal that we're down so the interrupt handler does not
+ /* signal that we're down so the interrupt handler does not
* reschedule our watchdog timer
*/
set_bit(__E1000_DOWN, &adapter->state);
@@ -3691,8 +3653,7 @@ void e1000e_down(struct e1000_adapter *adapter)
if (!pci_channel_offline(adapter->pdev))
e1000e_reset(adapter);
- /*
- * TODO: for power management, we could drop the link and
+ /* TODO: for power management, we could drop the link and
* pci_disable_device here.
*/
}
@@ -3715,7 +3676,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+static int e1000_sw_init(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -3755,8 +3716,7 @@ static irqreturn_t e1000_intr_msi_test(int irq, void *data)
e_dbg("icr is %08X\n", icr);
if (icr & E1000_ICR_RXSEQ) {
adapter->flags &= ~FLAG_MSI_TEST_FAILED;
- /*
- * Force memory writes to complete before acknowledging the
+ /* Force memory writes to complete before acknowledging the
* interrupt is handled.
*/
wmb();
@@ -3786,7 +3746,8 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
e1000e_reset_interrupt_capability(adapter);
/* Assume that the test fails, if it succeeds then the test
- * MSI irq handler will unset this flag */
+ * MSI irq handler will unset this flag
+ */
adapter->flags |= FLAG_MSI_TEST_FAILED;
err = pci_enable_msi(adapter->pdev);
@@ -3800,8 +3761,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
goto msi_test_failed;
}
- /*
- * Force memory writes to complete before enabling and firing an
+ /* Force memory writes to complete before enabling and firing an
* interrupt.
*/
wmb();
@@ -3901,8 +3861,7 @@ static int e1000_open(struct net_device *netdev)
if (err)
goto err_setup_rx;
- /*
- * If AMT is enabled, let the firmware know that the network
+ /* If AMT is enabled, let the firmware know that the network
* interface is now open and reset the part to a known state.
*/
if (adapter->flags & FLAG_HAS_AMT) {
@@ -3923,8 +3882,7 @@ static int e1000_open(struct net_device *netdev)
PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
- /*
- * before we allocate an interrupt, we must be ready to handle it.
+ /* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
* as soon as we call pci_request_irq, so we have to setup our
* clean_rx handler before we do so.
@@ -3935,8 +3893,7 @@ static int e1000_open(struct net_device *netdev)
if (err)
goto err_req_irq;
- /*
- * Work around PCIe errata with MSI interrupts causing some chipsets to
+ /* Work around PCIe errata with MSI interrupts causing some chipsets to
* ignore e1000e MSI messages, which means we need to test our MSI
* interrupt now
*/
@@ -4017,16 +3974,14 @@ static int e1000_close(struct net_device *netdev)
e1000e_free_tx_resources(adapter->tx_ring);
e1000e_free_rx_resources(adapter->rx_ring);
- /*
- * kill manageability vlan ID if supported, but not if a vlan with
+ /* kill manageability vlan ID if supported, but not if a vlan with
* the same ID is registered on the host OS (let 8021q kill it)
*/
if (adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
- /*
- * If AMT is enabled, let the firmware know that the network
+ /* If AMT is enabled, let the firmware know that the network
* interface is now closed
*/
if ((adapter->flags & FLAG_HAS_AMT) &&
@@ -4065,8 +4020,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
/* activate the work around */
e1000e_set_laa_state_82571(&adapter->hw, 1);
- /*
- * Hold a copy of the LAA in RAR[14] This is done so that
+ /* Hold a copy of the LAA in RAR[14] This is done so that
* between the time RAR[0] gets clobbered and the time it
* gets fixed (in e1000_watchdog), the actual LAA is in one
* of the RARs and no incoming packets directed to this port
@@ -4099,10 +4053,13 @@ static void e1000e_update_phy_task(struct work_struct *work)
e1000_get_phy_info(&adapter->hw);
}
-/*
+/**
+ * e1000_update_phy_info - timre call-back to update PHY info
+ * @data: pointer to adapter cast into an unsigned long
+ *
* Need to wait a few seconds after link up to get diagnostic information from
* the phy
- */
+ **/
static void e1000_update_phy_info(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
@@ -4129,8 +4086,7 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
if (ret_val)
return;
- /*
- * A page set is expensive so check if already on desired page.
+ /* A page set is expensive so check if already on desired page.
* If not, set to the page with the PHY status registers.
*/
hw->phy.addr = 1;
@@ -4201,8 +4157,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
- /*
- * Prevent stats update while adapter is being reset, or if the pci
+ /* Prevent stats update while adapter is being reset, or if the pci
* connection is down.
*/
if (adapter->link_speed == 0)
@@ -4270,8 +4225,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
/* Rx Errors */
- /*
- * RLEC on some newer hardware can be incorrect so build
+ /* RLEC on some newer hardware can be incorrect so build
* our own version based on RUC and ROC
*/
netdev->stats.rx_errors = adapter->stats.rxerrc +
@@ -4323,8 +4277,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
if (ret_val)
e_warn("Error reading PHY register\n");
} else {
- /*
- * Do not read PHY registers if link is not up
+ /* Do not read PHY registers if link is not up
* Set values to typical power-on defaults
*/
phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
@@ -4362,8 +4315,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter)
bool link_active = false;
s32 ret_val = 0;
- /*
- * get_link_status is set on LSC (link status) interrupt or
+ /* get_link_status is set on LSC (link status) interrupt or
* Rx sequence error interrupt. get_link_status will stay
* false until the check_for_link establishes link
* for copper adapters ONLY
@@ -4415,8 +4367,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- /*
- * With 82574 controllers, PHY needs to be checked periodically
+ /* With 82574 controllers, PHY needs to be checked periodically
* for hung state and reset, if two calls return true
*/
if (e1000_check_phy_82574(hw))
@@ -4484,8 +4435,7 @@ static void e1000_watchdog_task(struct work_struct *work)
&adapter->link_speed,
&adapter->link_duplex);
e1000_print_link_info(adapter);
- /*
- * On supported PHYs, check for duplex mismatch only
+ /* On supported PHYs, check for duplex mismatch only
* if link has autonegotiated at 10/100 half
*/
if ((hw->phy.type == e1000_phy_igp_3 ||
@@ -4515,8 +4465,7 @@ static void e1000_watchdog_task(struct work_struct *work)
break;
}
- /*
- * workaround: re-program speed mode bit after
+ /* workaround: re-program speed mode bit after
* link-up event
*/
if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) &&
@@ -4527,8 +4476,7 @@ static void e1000_watchdog_task(struct work_struct *work)
ew32(TARC(0), tarc0);
}
- /*
- * disable TSO for pcie and 10/100 speeds, to avoid
+ /* disable TSO for pcie and 10/100 speeds, to avoid
* some hardware issues
*/
if (!(adapter->flags & FLAG_TSO_FORCE)) {
@@ -4549,16 +4497,14 @@ static void e1000_watchdog_task(struct work_struct *work)
}
}
- /*
- * enable transmits in the hardware, need to do this
+ /* enable transmits in the hardware, need to do this
* after setting TARC(0)
*/
tctl = er32(TCTL);
tctl |= E1000_TCTL_EN;
ew32(TCTL, tctl);
- /*
- * Perform any post-link-up configuration before
+ /* Perform any post-link-up configuration before
* reporting link up.
*/
if (phy->ops.cfg_on_link_up)
@@ -4609,8 +4555,7 @@ link_up:
if (!netif_carrier_ok(netdev) &&
(e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
- /*
- * We've lost link, so the controller stops DMA,
+ /* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
* (Do the reset outside of interrupt context).
@@ -4622,8 +4567,7 @@ link_up:
/* Simple mode for Interrupt Throttle Rate (ITR) */
if (adapter->itr_setting == 4) {
- /*
- * Symmetric Tx/Rx gets a reduced ITR=2000;
+ /* Symmetric Tx/Rx gets a reduced ITR=2000;
* Total asymmetrical Tx or Rx gets ITR=8000;
* everyone else is between 2000-8000.
*/
@@ -4648,8 +4592,7 @@ link_up:
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = true;
- /*
- * With 82571 controllers, LAA may be overwritten due to controller
+ /* With 82571 controllers, LAA may be overwritten due to controller
* reset from the other port. Set the appropriate LAA in RAR[0]
*/
if (e1000e_get_laa_state_82571(hw))
@@ -4948,8 +4891,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS));
- /*
- * Force memory writes to complete before letting h/w
+ /* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64).
@@ -4963,8 +4905,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
else
writel(i, tx_ring->tail);
- /*
- * we need this if more than one processor can write to our tail
+ /* we need this if more than one processor can write to our tail
* at a time, it synchronizes IO on IA64/Altix systems
*/
mmiowb();
@@ -5014,15 +4955,13 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
struct e1000_adapter *adapter = tx_ring->adapter;
netif_stop_queue(adapter->netdev);
- /*
- * Herbert's original patch had:
+ /* Herbert's original patch had:
* smp_mb__after_netif_stop_queue();
* but since that doesn't exist yet, just open code it.
*/
smp_mb();
- /*
- * We need to check again in a case another CPU has just
+ /* We need to check again in a case another CPU has just
* made room available.
*/
if (e1000_desc_unused(tx_ring) < size)
@@ -5067,18 +5006,26 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+ /* The minimum packet size with TCTL.PSP set is 17 bytes so
+ * pad skb in order to meet this minimum size requirement
+ */
+ if (unlikely(skb->len < 17)) {
+ if (skb_pad(skb, 17 - skb->len))
+ return NETDEV_TX_OK;
+ skb->len = 17;
+ skb_set_tail_pointer(skb, 17);
+ }
+
mss = skb_shinfo(skb)->gso_size;
if (mss) {
u8 hdr_len;
- /*
- * TSO Workaround for 82571/2/3 Controllers -- if skb->data
+ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
* points to just header, pull a few bytes of payload from
* frags into skb->data
*/
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- /*
- * we do this workaround for ES2LAN, but it is un-necessary,
+ /* we do this workaround for ES2LAN, but it is un-necessary,
* avoiding it could save a lot of cycles
*/
if (skb->data_len && (hdr_len == len)) {
@@ -5109,8 +5056,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (adapter->hw.mac.tx_pkt_filtering)
e1000_transfer_dhcp_info(adapter, skb);
- /*
- * need: count + 2 desc gap to keep tail from touching
+ /* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time
*/
if (e1000_maybe_stop_tx(tx_ring, count + 2))
@@ -5134,8 +5080,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
else if (e1000_tx_csum(tx_ring, skb))
tx_flags |= E1000_TX_FLAGS_CSUM;
- /*
- * Old method was to assume IPv4 packet by default if TSO was enabled.
+ /* Old method was to assume IPv4 packet by default if TSO was enabled.
* 82571 hardware supports TSO capabilities for IPv6 as well...
* no longer assume, we must.
*/
@@ -5222,8 +5167,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
/* Rx Errors */
- /*
- * RLEC on some newer hardware can be incorrect so build
+ /* RLEC on some newer hardware can be incorrect so build
* our own version based on RUC and ROC
*/
stats->rx_errors = adapter->stats.rxerrc +
@@ -5292,8 +5236,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
if (netif_running(netdev))
e1000e_down(adapter);
- /*
- * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size.
* i.e. RXBUFFER_2048 --> size-4096 slab
@@ -5555,8 +5498,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
if (adapter->hw.phy.type == e1000_phy_igp_3)
e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
- /*
- * Release control of h/w to f/w. If f/w is AMT enabled, this
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
*/
e1000e_release_hw_control(adapter);
@@ -5583,8 +5525,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- /*
- * The pci-e switch on some quad port adapters will report a
+ /* The pci-e switch on some quad port adapters will report a
* correctable error when the MAC transitions from D0 to D3. To
* prevent this we need to mask off the correctable errors on the
* downstream port of the pci-e switch.
@@ -5613,8 +5554,7 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
#else
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
- /*
- * Both device and parent should have the same ASPM setting.
+ /* Both device and parent should have the same ASPM setting.
* Disable ASPM in downstream component first and then upstream.
*/
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, state);
@@ -5708,8 +5648,7 @@ static int __e1000_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
- /*
- * If the controller has AMT, do not set DRV_LOAD until the interface
+ /* If the controller has AMT, do not set DRV_LOAD until the interface
* is up. For all other cases, let the f/w know that the h/w is now
* under the control of the driver.
*/
@@ -5837,7 +5776,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data)
return IRQ_HANDLED;
}
-/*
+/**
+ * e1000_netpoll
+ * @netdev: network interface device structure
+ *
* Polling 'interrupt' - used by things like netconsole to send skbs
* without having to re-enable interrupts. It's not called while
* the interrupt routine is executing.
@@ -5962,8 +5904,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
- /*
- * If the controller has AMT, do not set DRV_LOAD until the interface
+ /* If the controller has AMT, do not set DRV_LOAD until the interface
* is up. For all other cases, let the f/w know that the h/w is now
* under the control of the driver.
*/
@@ -6083,8 +6024,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit e1000_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct e1000_adapter *adapter;
@@ -6262,14 +6202,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (e1000e_enable_mng_pass_thru(&adapter->hw))
adapter->flags |= FLAG_MNG_PT_ENABLED;
- /*
- * before reading the NVM, reset the controller to
+ /* before reading the NVM, reset the controller to
* put the device in a known good starting state
*/
adapter->hw.mac.ops.reset_hw(&adapter->hw);
- /*
- * systems with ASPM and others may see the checksum fail on the first
+ /* systems with ASPM and others may see the checksum fail on the first
* attempt. Let's give it a few tries
*/
for (i = 0;; i++) {
@@ -6324,8 +6262,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->rx_ring->count = E1000_DEFAULT_RXD;
adapter->tx_ring->count = E1000_DEFAULT_TXD;
- /*
- * Initial Wake on LAN setting - If APM wake is enabled in
+ /* Initial Wake on LAN setting - If APM wake is enabled in
* the EEPROM, enable the ACPI Magic Packet filter
*/
if (adapter->flags & FLAG_APME_IN_WUC) {
@@ -6349,8 +6286,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (eeprom_data & eeprom_apme_mask)
adapter->eeprom_wol |= E1000_WUFC_MAG;
- /*
- * now that we have the eeprom settings, apply the special cases
+ /* now that we have the eeprom settings, apply the special cases
* where the eeprom may be wrong or the board simply won't support
* wake on lan on a particular port
*/
@@ -6367,8 +6303,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
/* reset the hardware with the new settings */
e1000e_reset(adapter);
- /*
- * If the controller has AMT, do not set DRV_LOAD until the interface
+ /* If the controller has AMT, do not set DRV_LOAD until the interface
* is up. For all other cases, let the f/w know that the h/w is now
* under the control of the driver.
*/
@@ -6425,14 +6360,13 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit e1000_remove(struct pci_dev *pdev)
+static void e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
bool down = test_bit(__E1000_DOWN, &adapter->state);
- /*
- * The timers may be rescheduled, so explicitly disable them
+ /* The timers may be rescheduled, so explicitly disable them
* from being rescheduled.
*/
if (!down)
@@ -6457,8 +6391,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
if (pci_dev_run_wake(pdev))
pm_runtime_get_noresume(&pdev->dev);
- /*
- * Release control of h/w to f/w. If f/w is AMT enabled, this
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
*/
e1000e_release_hw_control(adapter);
@@ -6578,7 +6511,7 @@ static struct pci_driver e1000_driver = {
.name = e1000e_driver_name,
.id_table = e1000_pci_tbl,
.probe = e1000_probe,
- .remove = __devexit_p(e1000_remove),
+ .remove = e1000_remove,
#ifdef CONFIG_PM
.driver = {
.pm = &e1000_pm_ops,
diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c
index a969f1af1b4e..b6468804cb2e 100644
--- a/drivers/net/ethernet/intel/e1000e/nvm.c
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -279,8 +279,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
e1e_flush();
udelay(1);
- /*
- * Read "Status Register" repeatedly until the LSB is cleared.
+ /* Read "Status Register" repeatedly until the LSB is cleared.
* The EEPROM will signal that the command has been completed
* by clearing bit 0 of the internal status register. If it's
* not cleared within 'timeout', then error out.
@@ -321,8 +320,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
u32 i, eerd = 0;
s32 ret_val = 0;
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* too many words for the offset, and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -364,8 +362,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
s32 ret_val;
u16 widx = 0;
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -393,8 +390,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
e1000_standby_nvm(hw);
- /*
- * Some SPI eeproms use the 8th address bit embedded in the
+ /* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
if ((nvm->address_bits == 8) && (offset >= 128))
@@ -461,8 +457,7 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
return ret_val;
}
- /*
- * if nvm_data is not ptr guard the PBA must be in legacy format which
+ /* if nvm_data is not ptr guard the PBA must be in legacy format which
* means pba_ptr is actually our second data word for the PBA number
* and we can decode it into an ascii string
*/
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index dfbfa7fd98c3..89d536dd7ff5 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -32,11 +32,9 @@
#include "e1000.h"
-/*
- * This is the only thing that needs to be changed to adjust the
+/* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage.
*/
-
#define E1000_MAX_NIC 32
#define OPTION_UNSET -1
@@ -49,22 +47,19 @@ module_param(copybreak, uint, 0644);
MODULE_PARM_DESC(copybreak,
"Maximum size of packet that is copied to a new buffer on receive");
-/*
- * All parameters are treated the same, as an integer array of values.
+/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over (plus this helps to avoid typo bugs).
*/
-
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
#define E1000_PARAM(X, desc) \
- static int __devinitdata X[E1000_MAX_NIC+1] \
+ static int X[E1000_MAX_NIC+1] \
= E1000_PARAM_INIT; \
static unsigned int num_##X; \
module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
-/*
- * Transmit Interrupt Delay in units of 1.024 microseconds
+/* Transmit Interrupt Delay in units of 1.024 microseconds
* Tx interrupt delay needs to typically be set to something non-zero
*
* Valid Range: 0-65535
@@ -74,8 +69,7 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
#define MAX_TXDELAY 0xFFFF
#define MIN_TXDELAY 0
-/*
- * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
+/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
*
* Valid Range: 0-65535
*/
@@ -84,8 +78,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
#define MAX_TXABSDELAY 0xFFFF
#define MIN_TXABSDELAY 0
-/*
- * Receive Interrupt Delay in units of 1.024 microseconds
+/* Receive Interrupt Delay in units of 1.024 microseconds
* hardware will likely hang if you set this to anything but zero.
*
* Valid Range: 0-65535
@@ -94,8 +87,7 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
#define MAX_RXDELAY 0xFFFF
#define MIN_RXDELAY 0
-/*
- * Receive Absolute Interrupt Delay in units of 1.024 microseconds
+/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
*
* Valid Range: 0-65535
*/
@@ -103,8 +95,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
#define MAX_RXABSDELAY 0xFFFF
#define MIN_RXABSDELAY 0
-/*
- * Interrupt Throttle Rate (interrupts/sec)
+/* Interrupt Throttle Rate (interrupts/sec)
*
* Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
*/
@@ -113,8 +104,7 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define MAX_ITR 100000
#define MIN_ITR 100
-/*
- * IntMode (Interrupt Mode)
+/* IntMode (Interrupt Mode)
*
* Valid Range: varies depending on kernel configuration & hardware support
*
@@ -132,8 +122,7 @@ E1000_PARAM(IntMode, "Interrupt Mode");
#define MAX_INTMODE 2
#define MIN_INTMODE 0
-/*
- * Enable Smart Power Down of the PHY
+/* Enable Smart Power Down of the PHY
*
* Valid Range: 0, 1
*
@@ -141,8 +130,7 @@ E1000_PARAM(IntMode, "Interrupt Mode");
*/
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
-/*
- * Enable Kumeran Lock Loss workaround
+/* Enable Kumeran Lock Loss workaround
*
* Valid Range: 0, 1
*
@@ -150,8 +138,7 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
*/
E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
-/*
- * Write Protect NVM
+/* Write Protect NVM
*
* Valid Range: 0, 1
*
@@ -159,8 +146,7 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
*/
E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
-/*
- * Enable CRC Stripping
+/* Enable CRC Stripping
*
* Valid Range: 0, 1
*
@@ -186,9 +172,9 @@ struct e1000_option {
} arg;
};
-static int __devinit e1000_validate_option(unsigned int *value,
- const struct e1000_option *opt,
- struct e1000_adapter *adapter)
+static int e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
+ struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -249,7 +235,7 @@ static int __devinit e1000_validate_option(unsigned int *value,
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
**/
-void __devinit e1000e_check_options(struct e1000_adapter *adapter)
+void e1000e_check_options(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
int bd = adapter->bd_number;
@@ -351,8 +337,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- /*
- * Make sure a message is printed for non-special
+ /* Make sure a message is printed for non-special
* values. And in case of an invalid option, display
* warning, use default and go through itr/itr_setting
* adjustment logic below
@@ -361,14 +346,12 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&adapter->itr, &opt, adapter))
adapter->itr = opt.def;
} else {
- /*
- * If no option specified, use default value and go
+ /* If no option specified, use default value and go
* through the logic below to adjust itr/itr_setting
*/
adapter->itr = opt.def;
- /*
- * Make sure a message is printed for non-special
+ /* Make sure a message is printed for non-special
* default values
*/
if (adapter->itr > 4)
@@ -400,8 +383,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
opt.name);
break;
default:
- /*
- * Save the setting, because the dynamic bits
+ /* Save the setting, because the dynamic bits
* change itr.
*
* Clear the lower two bits because
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index fc62a3f3a5be..28b38ff37e84 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -193,8 +193,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
return -E1000_ERR_PARAM;
}
- /*
- * Set up Op-code, Phy Address, and register offset in the MDI
+ /* Set up Op-code, Phy Address, and register offset in the MDI
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
@@ -204,8 +203,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
ew32(MDIC, mdic);
- /*
- * Poll the ready bit to see if the MDI read completed
+ /* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
@@ -225,8 +223,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
}
*data = (u16) mdic;
- /*
- * Allow some time after each MDIC transaction to avoid
+ /* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
@@ -253,8 +250,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
return -E1000_ERR_PARAM;
}
- /*
- * Set up Op-code, Phy Address, and register offset in the MDI
+ /* Set up Op-code, Phy Address, and register offset in the MDI
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
@@ -265,8 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
ew32(MDIC, mdic);
- /*
- * Poll the ready bit to see if the MDI read completed
+ /* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
@@ -285,8 +280,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
return -E1000_ERR_PHY;
}
- /*
- * Allow some time after each MDIC transaction to avoid
+ /* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
@@ -708,8 +702,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
if (ret_val)
return ret_val;
phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
- /*
- * Options:
+ /* Options:
* 0 - Auto (default)
* 1 - MDI mode
* 2 - MDI-X mode
@@ -754,8 +747,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
if (phy->type != e1000_phy_bm)
phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- /*
- * Options:
+ /* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
* 1 - MDI mode
@@ -780,8 +772,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
break;
}
- /*
- * Options:
+ /* Options:
* disable_polarity_correction = 0 (default)
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
@@ -818,8 +809,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
if ((phy->type == e1000_phy_m88) &&
(phy->revision < E1000_REVISION_4) &&
(phy->id != BME1000_E_PHY_ID_R2)) {
- /*
- * Force TX_CLK in the Extended PHY Specific Control Register
+ /* Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock.
*/
ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -899,8 +889,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+ /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
* timeout issues when LFS is enabled.
*/
msleep(100);
@@ -936,8 +925,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
/* set auto-master slave resolution settings */
if (hw->mac.autoneg) {
- /*
- * when autonegotiation advertisement is only 1000Mbps then we
+ /* when autonegotiation advertisement is only 1000Mbps then we
* should disable SmartSpeed and enable Auto MasterSlave
* resolution as hardware default.
*/
@@ -1001,16 +989,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Need to parse both autoneg_advertised and fc and set up
+ /* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
* autoneg_advertised software override. Since we can advertise
* a plethora of combinations, we need to check each bit
* individually.
*/
- /*
- * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ /* First we clear all the 10/100 mb speed bits in the Auto-Neg
* Advertisement Register (Address 4) and the 1000 mb speed bits in
* the 1000Base-T Control Register (Address 9).
*/
@@ -1056,8 +1042,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
}
- /*
- * Check for a software override of the flow control settings, and
+ /* Check for a software override of the flow control settings, and
* setup the PHY advertisement registers accordingly. If
* auto-negotiation is enabled, then software will have to set the
* "PAUSE" bits to the correct value in the Auto-Negotiation
@@ -1076,15 +1061,13 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
*/
switch (hw->fc.current_mode) {
case e1000_fc_none:
- /*
- * Flow control (Rx & Tx) is completely disabled by a
+ /* Flow control (Rx & Tx) is completely disabled by a
* software over-ride.
*/
mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
break;
case e1000_fc_rx_pause:
- /*
- * Rx Flow control is enabled, and Tx Flow control is
+ /* Rx Flow control is enabled, and Tx Flow control is
* disabled, by a software over-ride.
*
* Since there really isn't a way to advertise that we are
@@ -1096,16 +1079,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
break;
case e1000_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is
+ /* Tx Flow control is enabled, and Rx Flow control is
* disabled, by a software over-ride.
*/
mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
break;
case e1000_fc_full:
- /*
- * Flow control (both Rx and Tx) is enabled by a software
+ /* Flow control (both Rx and Tx) is enabled by a software
* over-ride.
*/
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
@@ -1142,14 +1123,12 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
s32 ret_val;
u16 phy_ctrl;
- /*
- * Perform some bounds checking on the autoneg advertisement
+ /* Perform some bounds checking on the autoneg advertisement
* parameter.
*/
phy->autoneg_advertised &= phy->autoneg_mask;
- /*
- * If autoneg_advertised is zero, we assume it was not defaulted
+ /* If autoneg_advertised is zero, we assume it was not defaulted
* by the calling code so we set to advertise full capability.
*/
if (!phy->autoneg_advertised)
@@ -1163,8 +1142,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
}
e_dbg("Restarting Auto-Neg\n");
- /*
- * Restart auto-negotiation by setting the Auto Neg Enable bit and
+ /* Restart auto-negotiation by setting the Auto Neg Enable bit and
* the Auto Neg Restart bit in the PHY control register.
*/
ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
@@ -1176,8 +1154,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Does the user want to wait for Auto-Neg to complete here, or
+ /* Does the user want to wait for Auto-Neg to complete here, or
* check at a later time (for example, callback routine).
*/
if (phy->autoneg_wait_to_complete) {
@@ -1208,16 +1185,14 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
bool link;
if (hw->mac.autoneg) {
- /*
- * Setup autoneg and flow control advertisement and perform
+ /* Setup autoneg and flow control advertisement and perform
* autonegotiation.
*/
ret_val = e1000_copper_link_autoneg(hw);
if (ret_val)
return ret_val;
} else {
- /*
- * PHY will be set to 10H, 10F, 100H or 100F
+ /* PHY will be set to 10H, 10F, 100H or 100F
* depending on user settings.
*/
e_dbg("Forcing Speed and Duplex\n");
@@ -1228,8 +1203,7 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
}
}
- /*
- * Check link status. Wait up to 100 microseconds for link to become
+ /* Check link status. Wait up to 100 microseconds for link to become
* valid.
*/
ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
@@ -1273,8 +1247,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Clear Auto-Crossover to force MDI manually. IGP requires MDI
+ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed and duplex are forced.
*/
ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
@@ -1328,8 +1301,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
u16 phy_data;
bool link;
- /*
- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+ /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
* forced whenever speed and duplex are forced.
*/
ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1370,8 +1342,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
if (hw->phy.type != e1000_phy_m88) {
e_dbg("Link taking longer than expected.\n");
} else {
- /*
- * We didn't get link.
+ /* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
@@ -1398,8 +1369,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Resetting the phy means we need to re-force TX_CLK in the
+ /* Resetting the phy means we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock from
* the reset value of 2.5MHz.
*/
@@ -1408,8 +1378,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * In addition, we must re-enable CRS on Tx for both half and full
+ /* In addition, we must re-enable CRS on Tx for both half and full
* duplex.
*/
ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1573,8 +1542,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
if (ret_val)
return ret_val;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
@@ -1702,8 +1670,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
s32 ret_val;
u16 data, offset, mask;
- /*
- * Polarity is determined based on the speed of
+ /* Polarity is determined based on the speed of
* our connection.
*/
ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
@@ -1715,8 +1682,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
offset = IGP01E1000_PHY_PCS_INIT_REG;
mask = IGP01E1000_PHY_POLARITY_MASK;
} else {
- /*
- * This really only applies to 10Mbps since
+ /* This really only applies to 10Mbps since
* there is no polarity for 100Mbps (always 0).
*/
offset = IGP01E1000_PHY_PORT_STATUS;
@@ -1745,8 +1711,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
s32 ret_val;
u16 phy_data, offset, mask;
- /*
- * Polarity is determined based on the reversal feature being enabled.
+ /* Polarity is determined based on the reversal feature being enabled.
*/
if (phy->polarity_correction) {
offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
@@ -1791,8 +1756,7 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw)
msleep(100);
}
- /*
- * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+ /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
* has completed.
*/
return ret_val;
@@ -1814,15 +1778,13 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
u16 i, phy_status;
for (i = 0; i < iterations; i++) {
- /*
- * Some PHYs require the PHY_STATUS register to be read
+ /* Some PHYs require the PHY_STATUS register to be read
* twice due to the link bit being sticky. No harm doing
* it across the board.
*/
ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
if (ret_val)
- /*
- * If the first read fails, another entity may have
+ /* If the first read fails, another entity may have
* ownership of the resources, wait and try again to
* see if they have relinquished the resources yet.
*/
@@ -1913,8 +1875,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /*
- * Getting bits 15:9, which represent the combination of
+ /* Getting bits 15:9, which represent the combination of
* coarse and fine gain values. The result is a number
* that can be put into the lookup table to obtain the
* approximate cable length.
@@ -2285,15 +2246,13 @@ s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
e1e_wphy(hw, 0x1796, 0x0008);
/* Change cg_icount + enable integbp for channels BCD */
e1e_wphy(hw, 0x1798, 0xD008);
- /*
- * Change cg_icount + enable integbp + change prop_factor_master
+ /* Change cg_icount + enable integbp + change prop_factor_master
* to 8 for channel A
*/
e1e_wphy(hw, 0x1898, 0xD918);
/* Disable AHT in Slave mode on channel A */
e1e_wphy(hw, 0x187A, 0x0800);
- /*
- * Enable LPLU and disable AN to 1000 in non-D0a states,
+ /* Enable LPLU and disable AN to 1000 in non-D0a states,
* Enable SPD+B2B
*/
e1e_wphy(hw, 0x0019, 0x008D);
@@ -2417,8 +2376,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw)
e1000e_get_phy_id(hw);
phy_type = e1000e_get_phy_type_from_id(hw->phy.id);
- /*
- * If phy_type is valid, break - we found our
+ /* If phy_type is valid, break - we found our
* PHY address
*/
if (phy_type != e1000_phy_unknown)
@@ -2478,8 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
if (offset > MAX_PHY_MULTI_PAGE_REG) {
u32 page_shift, page_select;
- /*
- * Page select is register 31 for phy address 1 and 22 for
+ /* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
@@ -2537,8 +2494,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
if (offset > MAX_PHY_MULTI_PAGE_REG) {
u32 page_shift, page_select;
- /*
- * Page select is register 31 for phy address 1 and 22 for
+ /* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
@@ -2683,8 +2639,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
return ret_val;
}
- /*
- * Enable both PHY wakeup mode and Wakeup register page writes.
+ /* Enable both PHY wakeup mode and Wakeup register page writes.
* Prevent a power state change by disabling ME and Host PHY wakeup.
*/
temp = *phy_reg;
@@ -2698,8 +2653,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
return ret_val;
}
- /*
- * Select Host Wakeup Registers page - caller now able to write
+ /* Select Host Wakeup Registers page - caller now able to write
* registers on the Wakeup registers page
*/
return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
@@ -3038,8 +2992,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
if (page == HV_INTC_FC_PAGE_START)
page = 0;
- /*
- * Workaround MDIO accesses being disabled after entering IEEE
+ /* Workaround MDIO accesses being disabled after entering IEEE
* Power Down (when bit 11 of the PHY Control register is set)
*/
if ((hw->phy.type == e1000_phy_82578) &&
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 97c197fd4a8e..624476cfa727 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -34,6 +34,4 @@ obj-$(CONFIG_IGB) += igb.o
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
- e1000_i210.o
-
-igb-$(CONFIG_IGB_PTP) += igb_ptp.o
+ e1000_i210.o igb_ptp.o
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index ca4641e2f748..fdaaf2709d0a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -319,6 +319,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
nvm->ops.acquire = igb_acquire_nvm_i210;
nvm->ops.release = igb_release_nvm_i210;
nvm->ops.read = igb_read_nvm_srrd_i210;
+ nvm->ops.write = igb_write_nvm_srwr_i210;
nvm->ops.valid_led_default = igb_valid_led_default_i210;
break;
case e1000_i211:
@@ -1027,6 +1028,15 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
* continue to check for link.
*/
hw->mac.get_link_status = !hw->mac.serdes_has_link;
+
+ /* Configure Flow Control now that Auto-Neg has completed.
+ * First, we need to restore the desired flow control
+ * settings because we may have had to re-autoneg with a
+ * different link partner.
+ */
+ ret_val = igb_config_fc_after_link_up(hw);
+ if (ret_val)
+ hw_dbg("Error configuring flow control\n");
} else {
ret_val = igb_check_for_copper_link(hw);
}
@@ -1277,12 +1287,20 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
+ u32 phpm_reg;
ctrl = rd32(E1000_CTRL);
ctrl |= E1000_CTRL_SLU;
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
wr32(E1000_CTRL, ctrl);
+ /* Clear Go Link Disconnect bit */
+ if (hw->mac.type >= e1000_82580) {
+ phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT);
+ phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+ wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg);
+ }
+
ret_val = igb_setup_serdes_link_82575(hw);
if (ret_val)
goto out;
@@ -1336,7 +1354,7 @@ out:
**/
static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
{
- u32 ctrl_ext, ctrl_reg, reg;
+ u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
bool pcs_autoneg;
s32 ret_val = E1000_SUCCESS;
u16 data;
@@ -1424,27 +1442,45 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
- /*
- * We force flow control to prevent the CTRL register values from being
- * overwritten by the autonegotiated flow control values
- */
- reg |= E1000_PCS_LCTL_FORCE_FCTRL;
-
if (pcs_autoneg) {
/* Set PCS register for autoneg */
reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+
+ /* Disable force flow control for autoneg */
+ reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
+
+ /* Configure flow control advertisement for autoneg */
+ anadv_reg = rd32(E1000_PCS_ANADV);
+ anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
+ switch (hw->fc.requested_mode) {
+ case e1000_fc_full:
+ case e1000_fc_rx_pause:
+ anadv_reg |= E1000_TXCW_ASM_DIR;
+ anadv_reg |= E1000_TXCW_PAUSE;
+ break;
+ case e1000_fc_tx_pause:
+ anadv_reg |= E1000_TXCW_ASM_DIR;
+ break;
+ default:
+ break;
+ }
+ wr32(E1000_PCS_ANADV, anadv_reg);
+
hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
} else {
/* Set PCS register for forced link */
reg |= E1000_PCS_LCTL_FSD; /* Force Speed */
+ /* Force flow control for forced link */
+ reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+
hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
}
wr32(E1000_PCS_LCTL, reg);
- if (!igb_sgmii_active_82575(hw))
+ if (!pcs_autoneg && !igb_sgmii_active_82575(hw))
igb_force_mac_fc(hw);
return ret_val;
@@ -1918,6 +1954,12 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
hw->dev_spec._82575.global_device_reset = false;
+ /* due to hw errata, global device reset doesn't always
+ * work on 82580
+ */
+ if (hw->mac.type == e1000_82580)
+ global_device_reset = false;
+
/* Get current control state. */
ctrl = rd32(E1000_CTRL);
@@ -2233,19 +2275,16 @@ s32 igb_set_eee_i350(struct e1000_hw *hw)
/* enable or disable per user setting */
if (!(hw->dev_spec._82575.eee_disable)) {
- ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
- E1000_IPCNFG_EEE_100M_AN);
- eeer |= (E1000_EEER_TX_LPI_EN |
- E1000_EEER_RX_LPI_EN |
+ u32 eee_su = rd32(E1000_EEE_SU);
+
+ ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
E1000_EEER_LPI_FC);
- /* keep the LPI clock running before EEE is enabled */
- if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
- u32 eee_su;
- eee_su = rd32(E1000_EEE_SU);
- eee_su &= ~E1000_EEE_SU_LPI_CLK_STP;
- wr32(E1000_EEE_SU, eee_su);
- }
+ /* This bit should not be set in normal operation. */
+ if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
+ hw_dbg("LPI Clock Stop Bit should not be set!\n");
+
} else {
ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index e85c453f5428..44b76b3b6816 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -172,10 +172,13 @@ struct e1000_adv_tx_context_desc {
#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
/* Additional DCA related definitions, note change in position of CPUID */
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index de4b41ec3c40..45dce06eff26 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -431,6 +431,10 @@
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
#define FLOW_CONTROL_TYPE 0x8808
+/* Transmit Config Word */
+#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
+
/* 802.1q VLAN Packet Size */
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
@@ -539,6 +543,9 @@
/* mPHY Near End Digital Loopback Override Bit */
#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10
+#define E1000_PCS_LCTL_FORCE_FCTRL 0x80
+#define E1000_PCS_LSTS_AN_COMPLETE 0x10000
+
/* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
@@ -636,6 +643,7 @@
/* NVM Word Offsets */
#define NVM_COMPAT 0x0003
#define NVM_ID_LED_SETTINGS 0x0004 /* SERDES output amplitude */
+#define NVM_VERSION 0x0005
#define NVM_INIT_CONTROL2_REG 0x000F
#define NVM_INIT_CONTROL3_PORT_B 0x0014
#define NVM_INIT_CONTROL3_PORT_A 0x0024
@@ -653,6 +661,19 @@
#define NVM_LED_1_CFG 0x001C
#define NVM_LED_0_2_CFG 0x001F
+/* NVM version defines */
+#define NVM_ETRACK_WORD 0x0042
+#define NVM_COMB_VER_OFF 0x0083
+#define NVM_COMB_VER_PTR 0x003d
+#define NVM_MAJOR_MASK 0xF000
+#define NVM_MINOR_MASK 0x0FF0
+#define NVM_BUILD_MASK 0x000F
+#define NVM_COMB_VER_MASK 0x00FF
+#define NVM_MAJOR_SHIFT 12
+#define NVM_MINOR_SHIFT 4
+#define NVM_COMB_VER_SHFT 8
+#define NVM_VER_INVALID 0xFFFF
+#define NVM_ETRACK_SHIFT 16
#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
@@ -860,6 +881,7 @@
#define E1000_EEER_FRC_AN 0x10000000 /* Enable EEE in loopback */
#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */
#define E1000_EEE_SU_LPI_CLK_STP 0X00800000 /* EEE LPI Clock Stop */
+#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
/* SerDes Control */
#define E1000_GEN_CTL_READY 0x80000000
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index 77a5f939bc74..fbcdbebb0b5f 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -35,11 +35,42 @@
#include "e1000_hw.h"
#include "e1000_i210.h"
-static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw);
-static void igb_put_hw_semaphore_i210(struct e1000_hw *hw);
-static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw);
+/**
+ * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the HW semaphore to access the PHY or NVM
+ */
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+ s32 ret_val = E1000_SUCCESS;
+ s32 timeout = hw->nvm.word_size + 1;
+ s32 i = 0;
+
+ /* Get the FW semaphore. */
+ for (i = 0; i < timeout; i++) {
+ swsm = rd32(E1000_SWSM);
+ wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
+
+ /* Semaphore acquired if bit latched */
+ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
+ break;
+
+ udelay(50);
+ }
+
+ if (i == timeout) {
+ /* Release semaphores */
+ igb_put_hw_semaphore(hw);
+ hw_dbg("Driver can't access the NVM\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
/**
* igb_acquire_nvm_i210 - Request for access to EEPROM
@@ -68,6 +99,23 @@ void igb_release_nvm_i210(struct e1000_hw *hw)
}
/**
+ * igb_put_hw_semaphore_i210 - Release hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Release hardware semaphore used to access the PHY or NVM
+ */
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+
+ swsm = rd32(E1000_SWSM);
+
+ swsm &= ~E1000_SWSM_SWESMBI;
+
+ wr32(E1000_SWSM, swsm);
+}
+
+/**
* igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
* @hw: pointer to the HW structure
* @mask: specifies which semaphore to acquire
@@ -138,60 +186,6 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
}
/**
- * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
- * @hw: pointer to the HW structure
- *
- * Acquire the HW semaphore to access the PHY or NVM
- **/
-static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
-{
- u32 swsm;
- s32 ret_val = E1000_SUCCESS;
- s32 timeout = hw->nvm.word_size + 1;
- s32 i = 0;
-
- /* Get the FW semaphore. */
- for (i = 0; i < timeout; i++) {
- swsm = rd32(E1000_SWSM);
- wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
-
- /* Semaphore acquired if bit latched */
- if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
- break;
-
- udelay(50);
- }
-
- if (i == timeout) {
- /* Release semaphores */
- igb_put_hw_semaphore(hw);
- hw_dbg("Driver can't access the NVM\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
- }
-
-out:
- return ret_val;
-}
-
-/**
- * igb_put_hw_semaphore_i210 - Release hardware semaphore
- * @hw: pointer to the HW structure
- *
- * Release hardware semaphore used to access the PHY or NVM
- **/
-static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
-{
- u32 swsm;
-
- swsm = rd32(E1000_SWSM);
-
- swsm &= ~E1000_SWSM_SWESMBI;
-
- wr32(E1000_SWSM, swsm);
-}
-
-/**
* igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the Shadow Ram to read
@@ -229,49 +223,6 @@ s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
}
/**
- * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
- * @hw: pointer to the HW structure
- * @offset: offset within the Shadow RAM to be written to
- * @words: number of words to write
- * @data: 16 bit word(s) to be written to the Shadow RAM
- *
- * Writes data to Shadow RAM at offset using EEWR register.
- *
- * If e1000_update_nvm_checksum is not called after this function , the
- * data will not be committed to FLASH and also Shadow RAM will most likely
- * contain an invalid checksum.
- *
- * If error code is returned, data and Shadow RAM may be inconsistent - buffer
- * partially written.
- **/
-s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
-{
- s32 status = E1000_SUCCESS;
- u16 i, count;
-
- /* We cannot hold synchronization semaphores for too long,
- * because of forceful takeover procedure. However it is more efficient
- * to write in bursts than synchronizing access for each word. */
- for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
- count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
- E1000_EERD_EEWR_MAX_COUNT : (words - i);
- if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
- status = igb_write_nvm_srwr(hw, offset, count,
- data + i);
- hw->nvm.ops.release(hw);
- } else {
- status = E1000_ERR_SWFW_SYNC;
- }
-
- if (status != E1000_SUCCESS)
- break;
- }
-
- return status;
-}
-
-/**
* igb_write_nvm_srwr - Write to Shadow Ram using EEWR
* @hw: pointer to the HW structure
* @offset: offset within the Shadow Ram to be written to
@@ -329,6 +280,50 @@ out:
}
/**
+ * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow RAM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ * Writes data to Shadow RAM at offset using EEWR register.
+ *
+ * If e1000_update_nvm_checksum is not called after this function , the
+ * data will not be committed to FLASH and also Shadow RAM will most likely
+ * contain an invalid checksum.
+ *
+ * If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ * partially written.
+ */
+s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u16 i, count;
+
+ /* We cannot hold synchronization semaphores for too long,
+ * because of forceful takeover procedure. However it is more efficient
+ * to write in bursts than synchronizing access for each word.
+ */
+ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+ E1000_EERD_EEWR_MAX_COUNT : (words - i);
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ status = igb_write_nvm_srwr(hw, offset, count,
+ data + i);
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
* igb_read_nvm_i211 - Read NVM wrapper function for I211
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
@@ -350,16 +345,40 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
if (ret_val != E1000_SUCCESS)
hw_dbg("MAC Addr not found in iNVM\n");
break;
- case NVM_ID_LED_SETTINGS:
case NVM_INIT_CTRL_2:
+ ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+ if (ret_val != E1000_SUCCESS) {
+ *data = NVM_INIT_CTRL_2_DEFAULT_I211;
+ ret_val = E1000_SUCCESS;
+ }
+ break;
case NVM_INIT_CTRL_4:
+ ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+ if (ret_val != E1000_SUCCESS) {
+ *data = NVM_INIT_CTRL_4_DEFAULT_I211;
+ ret_val = E1000_SUCCESS;
+ }
+ break;
case NVM_LED_1_CFG:
+ ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+ if (ret_val != E1000_SUCCESS) {
+ *data = NVM_LED_1_CFG_DEFAULT_I211;
+ ret_val = E1000_SUCCESS;
+ }
+ break;
case NVM_LED_0_2_CFG:
igb_read_invm_i211(hw, offset, data);
+ if (ret_val != E1000_SUCCESS) {
+ *data = NVM_LED_0_2_CFG_DEFAULT_I211;
+ ret_val = E1000_SUCCESS;
+ }
break;
- case NVM_COMPAT:
- *data = ID_LED_DEFAULT_I210;
- break;
+ case NVM_ID_LED_SETTINGS:
+ ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+ if (ret_val != E1000_SUCCESS) {
+ *data = ID_LED_RESERVED_FFFF;
+ ret_val = E1000_SUCCESS;
+ }
case NVM_SUB_DEV_ID:
*data = hw->subsystem_device_id;
break;
@@ -423,6 +442,100 @@ s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
}
/**
+ * igb_read_invm_version - Reads iNVM version and image type
+ * @hw: pointer to the HW structure
+ * @invm_ver: version structure for the version read
+ *
+ * Reads iNVM version and image type.
+ **/
+s32 igb_read_invm_version(struct e1000_hw *hw,
+ struct e1000_fw_version *invm_ver) {
+ u32 *record = NULL;
+ u32 *next_record = NULL;
+ u32 i = 0;
+ u32 invm_dword = 0;
+ u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
+ E1000_INVM_RECORD_SIZE_IN_BYTES);
+ u32 buffer[E1000_INVM_SIZE];
+ s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
+ u16 version = 0;
+
+ /* Read iNVM memory */
+ for (i = 0; i < E1000_INVM_SIZE; i++) {
+ invm_dword = rd32(E1000_INVM_DATA_REG(i));
+ buffer[i] = invm_dword;
+ }
+
+ /* Read version number */
+ for (i = 1; i < invm_blocks; i++) {
+ record = &buffer[invm_blocks - i];
+ next_record = &buffer[invm_blocks - i + 1];
+
+ /* Check if we have first version location used */
+ if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
+ version = 0;
+ status = E1000_SUCCESS;
+ break;
+ }
+ /* Check if we have second version location used */
+ else if ((i == 1) &&
+ ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
+ version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+ status = E1000_SUCCESS;
+ break;
+ }
+ /* Check if we have odd version location
+ * used and it is the last one used
+ */
+ else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
+ ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
+ (i != 1))) {
+ version = (*next_record & E1000_INVM_VER_FIELD_TWO)
+ >> 13;
+ status = E1000_SUCCESS;
+ break;
+ }
+ /* Check if we have even version location
+ * used and it is the last one used
+ */
+ else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
+ ((*record & 0x3) == 0)) {
+ version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+ status = E1000_SUCCESS;
+ break;
+ }
+ }
+
+ if (status == E1000_SUCCESS) {
+ invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
+ >> E1000_INVM_MAJOR_SHIFT;
+ invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
+ }
+ /* Read Image Type */
+ for (i = 1; i < invm_blocks; i++) {
+ record = &buffer[invm_blocks - i];
+ next_record = &buffer[invm_blocks - i + 1];
+
+ /* Check if we have image type in first location used */
+ if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
+ invm_ver->invm_img_type = 0;
+ status = E1000_SUCCESS;
+ break;
+ }
+ /* Check if we have image type in first location used */
+ else if ((((*record & 0x3) == 0) &&
+ ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
+ ((((*record & 0x3) != 0) && (i != 1)))) {
+ invm_ver->invm_img_type =
+ (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
+ status = E1000_SUCCESS;
+ break;
+ }
+ }
+ return status;
+}
+
+/**
* igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
* @hw: pointer to the HW structure
*
@@ -519,6 +632,28 @@ out:
}
/**
+ * igb_pool_flash_update_done_i210 - Pool FLUDONE status.
+ * @hw: pointer to the HW structure
+ *
+ */
+static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = -E1000_ERR_NVM;
+ u32 i, reg;
+
+ for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+ reg = rd32(E1000_EECD);
+ if (reg & E1000_EECD_FLUDONE_I210) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ return ret_val;
+}
+
+/**
* igb_update_flash_i210 - Commit EEPROM to the flash
* @hw: pointer to the HW structure
*
@@ -548,28 +683,6 @@ out:
}
/**
- * igb_pool_flash_update_done_i210 - Pool FLUDONE status.
- * @hw: pointer to the HW structure
- *
- **/
-s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
-{
- s32 ret_val = -E1000_ERR_NVM;
- u32 i, reg;
-
- for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
- reg = rd32(E1000_EECD);
- if (reg & E1000_EECD_FLUDONE_I210) {
- ret_val = E1000_SUCCESS;
- break;
- }
- udelay(5);
- }
-
- return ret_val;
-}
-
-/**
* igb_valid_led_default_i210 - Verify a valid default LED config
* @hw: pointer to the HW structure
* @data: pointer to the NVM (EEPROM)
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index 5dc2bd3f50bc..1c89358a99ab 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -43,6 +43,8 @@ extern void igb_release_nvm_i210(struct e1000_hw *hw);
extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
+extern s32 igb_read_invm_version(struct e1000_hw *hw,
+ struct e1000_fw_version *invm_ver);
#define E1000_STM_OPCODE 0xDB00
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
@@ -65,6 +67,15 @@ enum E1000_INVM_STRUCTURE_TYPE {
#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
+#define E1000_INVM_ULT_BYTES_SIZE 8
+#define E1000_INVM_RECORD_SIZE_IN_BYTES 4
+#define E1000_INVM_VER_FIELD_ONE 0x1FF8
+#define E1000_INVM_VER_FIELD_TWO 0x7FE000
+#define E1000_INVM_IMGTYPE_FIELD 0x1F800000
+
+#define E1000_INVM_MAJOR_MASK 0x3F0
+#define E1000_INVM_MINOR_MASK 0xF
+#define E1000_INVM_MAJOR_SHIFT 4
#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
(ID_LED_OFF1_OFF2 << 4) | \
@@ -73,4 +84,10 @@ enum E1000_INVM_STRUCTURE_TYPE {
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_DEF1_DEF2))
+/* NVM offset defaults for i211 device */
+#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243
+#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1
+#define NVM_LED_1_CFG_DEFAULT_I211 0x0184
+#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C
+
#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 819c145ac762..101e6e4da97f 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -839,6 +839,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val = 0;
+ u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
u16 speed, duplex;
@@ -1040,6 +1041,129 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
goto out;
}
}
+ /* Check for the case where we have SerDes media and auto-neg is
+ * enabled. In this case, we need to check and see if Auto-Neg
+ * has completed, and if so, how the PHY and link partner has
+ * flow control configured.
+ */
+ if ((hw->phy.media_type == e1000_media_type_internal_serdes)
+ && mac->autoneg) {
+ /* Read the PCS_LSTS and check to see if AutoNeg
+ * has completed.
+ */
+ pcs_status_reg = rd32(E1000_PCS_LSTAT);
+
+ if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
+ hw_dbg("PCS Auto Neg has not completed.\n");
+ return ret_val;
+ }
+
+ /* The AutoNeg process has completed, so we now need to
+ * read both the Auto Negotiation Advertisement
+ * Register (PCS_ANADV) and the Auto_Negotiation Base
+ * Page Ability Register (PCS_LPAB) to determine how
+ * flow control was negotiated.
+ */
+ pcs_adv_reg = rd32(E1000_PCS_ANADV);
+ pcs_lp_ability_reg = rd32(E1000_PCS_LPAB);
+
+ /* Two bits in the Auto Negotiation Advertisement Register
+ * (PCS_ANADV) and two bits in the Auto Negotiation Base
+ * Page Ability Register (PCS_LPAB) determine flow control
+ * for both the PHY and the link partner. The following
+ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+ * 1999, describes these PAUSE resolution bits and how flow
+ * control is determined based upon these settings.
+ * NOTE: DC = Don't Care
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+ *-------|---------|-------|---------|--------------------
+ * 0 | 0 | DC | DC | e1000_fc_none
+ * 0 | 1 | 0 | DC | e1000_fc_none
+ * 0 | 1 | 1 | 0 | e1000_fc_none
+ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
+ * 1 | 0 | 0 | DC | e1000_fc_none
+ * 1 | DC | 1 | DC | e1000_fc_full
+ * 1 | 1 | 0 | 0 | e1000_fc_none
+ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
+ *
+ * Are both PAUSE bits set to 1? If so, this implies
+ * Symmetric Flow Control is enabled at both ends. The
+ * ASM_DIR bits are irrelevant per the spec.
+ *
+ * For Symmetric Flow Control:
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | DC | 1 | DC | e1000_fc_full
+ *
+ */
+ if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
+ /* Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise Rx
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == e1000_fc_full) {
+ hw->fc.current_mode = e1000_fc_full;
+ hw_dbg("Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = e1000_fc_rx_pause;
+ hw_dbg("Flow Control = Rx PAUSE frames only.\n");
+ }
+ }
+ /* For receiving PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
+ */
+ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+ (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+ hw->fc.current_mode = e1000_fc_tx_pause;
+ hw_dbg("Flow Control = Tx PAUSE frames only.\n");
+ }
+ /* For transmitting PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
+ */
+ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+ !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+ hw->fc.current_mode = e1000_fc_rx_pause;
+ hw_dbg("Flow Control = Rx PAUSE frames only.\n");
+ } else {
+ /* Per the IEEE spec, at this point flow control
+ * should be disabled.
+ */
+ hw->fc.current_mode = e1000_fc_none;
+ hw_dbg("Flow Control = NONE.\n");
+ }
+
+ /* Now we call a subroutine to actually force the MAC
+ * controller to use the correct flow control settings.
+ */
+ pcs_ctrl_reg = rd32(E1000_PCS_LCTL);
+ pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+ wr32(E1000_PCS_LCTL, pcs_ctrl_reg);
+
+ ret_val = igb_force_mac_fc(hw);
+ if (ret_val) {
+ hw_dbg("Error forcing flow control settings\n");
+ return ret_val;
+ }
+ }
out:
return ret_val;
@@ -1391,6 +1515,10 @@ s32 igb_validate_mdi_setting(struct e1000_hw *hw)
{
s32 ret_val = 0;
+ /* All MDI settings are supported on 82580 and newer. */
+ if (hw->mac.type >= e1000_82580)
+ goto out;
+
if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
hw_dbg("Invalid MDI setting detected\n");
hw->phy.mdix = 1;
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index cbddc4e51e30..e2b2c4b9c951 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -33,6 +33,7 @@
#include "e1000_phy.h"
#include "e1000_nvm.h"
#include "e1000_defines.h"
+#include "e1000_i210.h"
/*
* Functions that should not be called directly from drivers but can be used
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index aa5fcdf3f357..fbb7604db364 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -438,7 +438,7 @@ out:
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val;
+ s32 ret_val = -E1000_ERR_NVM;
u16 widx = 0;
/*
@@ -448,22 +448,21 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
hw_dbg("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return ret_val;
}
- ret_val = hw->nvm.ops.acquire(hw);
- if (ret_val)
- goto out;
-
- msleep(10);
-
while (widx < words) {
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
- ret_val = igb_ready_nvm_eeprom(hw);
+ ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto release;
+ return ret_val;
+
+ ret_val = igb_ready_nvm_eeprom(hw);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ return ret_val;
+ }
igb_standby_nvm(hw);
@@ -497,13 +496,10 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
}
}
+ usleep_range(1000, 2000);
+ nvm->ops.release(hw);
}
- msleep(10);
-release:
- hw->nvm.ops.release(hw);
-
-out:
return ret_val;
}
@@ -710,3 +706,74 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw)
out:
return ret_val;
}
+
+/**
+ * igb_get_fw_version - Get firmware version information
+ * @hw: pointer to the HW structure
+ * @fw_vers: pointer to output structure
+ *
+ * unsupported MAC types will return all 0 version structure
+ **/
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
+{
+ u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
+ u16 fw_version;
+
+ memset(fw_vers, 0, sizeof(struct e1000_fw_version));
+
+ switch (hw->mac.type) {
+ case e1000_i211:
+ igb_read_invm_version(hw, fw_vers);
+ return;
+ case e1000_82575:
+ case e1000_82576:
+ case e1000_82580:
+ case e1000_i350:
+ case e1000_i210:
+ break;
+ default:
+ return;
+ }
+ /* basic eeprom version numbers */
+ hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
+ fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT;
+ fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK);
+
+ /* etrack id */
+ hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
+ hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
+ fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl;
+
+ switch (hw->mac.type) {
+ case e1000_i210:
+ case e1000_i350:
+ /* find combo image version */
+ hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
+ if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) {
+
+ hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+ + 1), 1, &comb_verh);
+ hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
+ 1, &comb_verl);
+
+ /* get Option Rom version if it exists and is valid */
+ if ((comb_verh && comb_verl) &&
+ ((comb_verh != NVM_VER_INVALID) &&
+ (comb_verl != NVM_VER_INVALID))) {
+
+ fw_vers->or_valid = true;
+ fw_vers->or_major =
+ comb_verl >> NVM_COMB_VER_SHFT;
+ fw_vers->or_build =
+ ((comb_verl << NVM_COMB_VER_SHFT)
+ | (comb_verh >> NVM_COMB_VER_SHFT));
+ fw_vers->or_patch =
+ comb_verh & NVM_COMB_VER_MASK;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index 825b0228cac0..7012d458c6f7 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -40,4 +40,20 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 igb_validate_nvm_checksum(struct e1000_hw *hw);
s32 igb_update_nvm_checksum(struct e1000_hw *hw);
+struct e1000_fw_version {
+ u32 etrack_id;
+ u16 eep_major;
+ u16 eep_minor;
+
+ u8 invm_major;
+ u8 invm_minor;
+ u8 invm_img_type;
+
+ bool or_valid;
+ u16 or_major;
+ u16 or_build;
+ u16 or_patch;
+};
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers);
+
#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index 3404bc79f4ca..fe76004aca4e 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -1207,20 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
u16 phy_data;
bool link;
- /*
- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
- * forced whenever speed and duplex are forced.
- */
- ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- goto out;
+ /* I210 and I211 devices support Auto-Crossover in forced operation. */
+ if (phy->type != e1000_phy_i210) {
+ /*
+ * Clear Auto-Crossover to force MDI manually. M88E1000
+ * requires MDI forced whenever speed and duplex are forced.
+ */
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ if (ret_val)
+ goto out;
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
- ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- goto out;
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ goto out;
- hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+ hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+ }
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
@@ -1710,6 +1715,26 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
switch (hw->phy.id) {
case I210_I_PHY_ID:
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ return ret_val;
+
+ is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+ break;
case I347AT4_E_PHY_ID:
/* Remember the original page select and set it to 7 */
ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 6ac3299bfcb9..ed282f877d9a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -124,6 +124,7 @@ s32 igb_check_polarity_m88(struct e1000_hw *hw);
#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
+#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
/* Enable flexible speed on link-up */
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 8aad230c0592..17f1686ee411 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -34,16 +34,16 @@
#include "e1000_mac.h"
#include "e1000_82575.h"
-#ifdef CONFIG_IGB_PTP
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IGB_PTP */
#include <linux/bitops.h>
#include <linux/if_vlan.h>
struct igb_adapter;
+#define E1000_PCS_CFG_IGN_SD 1
+
/* Interrupt defines */
#define IGB_START_ITR 648 /* ~6000 ints/sec */
#define IGB_4K_ITR 980
@@ -132,9 +132,10 @@ struct vf_data_storage {
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
/* Supported Rx Buffer Sizes */
-#define IGB_RXBUFFER_256 256
-#define IGB_RXBUFFER_16384 16384
-#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
+#define IGB_RXBUFFER_256 256
+#define IGB_RXBUFFER_2048 2048
+#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
+#define IGB_RX_BUFSZ IGB_RXBUFFER_2048
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define IGB_TX_QUEUE_WAKE 16
@@ -151,11 +152,18 @@ struct vf_data_storage {
#define IGB_MNG_VLAN_NONE -1
-#define IGB_TX_FLAGS_CSUM 0x00000001
-#define IGB_TX_FLAGS_VLAN 0x00000002
-#define IGB_TX_FLAGS_TSO 0x00000004
-#define IGB_TX_FLAGS_IPV4 0x00000008
-#define IGB_TX_FLAGS_TSTAMP 0x00000010
+enum igb_tx_flags {
+ /* cmd_type flags */
+ IGB_TX_FLAGS_VLAN = 0x01,
+ IGB_TX_FLAGS_TSO = 0x02,
+ IGB_TX_FLAGS_TSTAMP = 0x04,
+
+ /* olinfo flags */
+ IGB_TX_FLAGS_IPV4 = 0x10,
+ IGB_TX_FLAGS_CSUM = 0x20,
+};
+
+/* VLAN info */
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
#define IGB_TX_FLAGS_VLAN_SHIFT 16
@@ -174,11 +182,9 @@ struct igb_tx_buffer {
};
struct igb_rx_buffer {
- struct sk_buff *skb;
dma_addr_t dma;
struct page *page;
- dma_addr_t page_dma;
- u32 page_offset;
+ unsigned int page_offset;
};
struct igb_tx_queue_stats {
@@ -205,22 +211,6 @@ struct igb_ring_container {
u8 itr; /* current ITR setting for ring */
};
-struct igb_q_vector {
- struct igb_adapter *adapter; /* backlink */
- int cpu; /* CPU for DCA */
- u32 eims_value; /* EIMS mask value */
-
- struct igb_ring_container rx, tx;
-
- struct napi_struct napi;
-
- u16 itr_val;
- u8 set_itr;
- void __iomem *itr_register;
-
- char name[IFNAMSIZ + 9];
-};
-
struct igb_ring {
struct igb_q_vector *q_vector; /* backlink to q_vector */
struct net_device *netdev; /* back pointer to net_device */
@@ -232,15 +222,17 @@ struct igb_ring {
void *desc; /* descriptor ring memory */
unsigned long flags; /* ring specific flags */
void __iomem *tail; /* pointer to ring tail register */
+ dma_addr_t dma; /* phys address of the ring */
+ unsigned int size; /* length of desc. ring in bytes */
u16 count; /* number of desc. in the ring */
u8 queue_index; /* logical index of the ring*/
u8 reg_idx; /* physical index of the ring */
- u32 size; /* length of desc. ring in bytes */
/* everything past this point are written often */
- u16 next_to_clean ____cacheline_aligned_in_smp;
+ u16 next_to_clean;
u16 next_to_use;
+ u16 next_to_alloc;
union {
/* TX */
@@ -251,12 +243,30 @@ struct igb_ring {
};
/* RX */
struct {
+ struct sk_buff *skb;
struct igb_rx_queue_stats rx_stats;
struct u64_stats_sync rx_syncp;
};
};
- /* Items past this point are only used during ring alloc / free */
- dma_addr_t dma; /* phys address of the ring */
+} ____cacheline_internodealigned_in_smp;
+
+struct igb_q_vector {
+ struct igb_adapter *adapter; /* backlink */
+ int cpu; /* CPU for DCA */
+ u32 eims_value; /* EIMS mask value */
+
+ u16 itr_val;
+ u8 set_itr;
+ void __iomem *itr_register;
+
+ struct igb_ring_container rx, tx;
+
+ struct napi_struct napi;
+ struct rcu_head rcu; /* to avoid race with update stats on free */
+ char name[IFNAMSIZ + 9];
+
+ /* for dynamic allocation of rings associated with this q_vector */
+ struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
};
enum e1000_ring_flags_t {
@@ -362,8 +372,6 @@ struct igb_adapter {
u32 eims_other;
/* to not mess up cache alignment, always add to the bottom */
- u32 eeprom_wol;
-
u16 tx_ring_count;
u16 rx_ring_count;
unsigned int vfs_allocated_count;
@@ -373,7 +381,6 @@ struct igb_adapter {
u32 wvbr;
u32 *shadow_vfta;
-#ifdef CONFIG_IGB_PTP
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
struct delayed_work ptp_overflow_work;
@@ -382,17 +389,19 @@ struct igb_adapter {
spinlock_t tmreg_lock;
struct cyclecounter cc;
struct timecounter tc;
-#endif /* CONFIG_IGB_PTP */
char fw_version[32];
};
-#define IGB_FLAG_HAS_MSI (1 << 0)
-#define IGB_FLAG_DCA_ENABLED (1 << 1)
-#define IGB_FLAG_QUAD_PORT_A (1 << 2)
-#define IGB_FLAG_QUEUE_PAIRS (1 << 3)
-#define IGB_FLAG_DMAC (1 << 4)
-#define IGB_FLAG_PTP (1 << 5)
+#define IGB_FLAG_HAS_MSI (1 << 0)
+#define IGB_FLAG_DCA_ENABLED (1 << 1)
+#define IGB_FLAG_QUAD_PORT_A (1 << 2)
+#define IGB_FLAG_QUEUE_PAIRS (1 << 3)
+#define IGB_FLAG_DMAC (1 << 4)
+#define IGB_FLAG_PTP (1 << 5)
+#define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 6)
+#define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 7)
+#define IGB_FLAG_WOL_SUPPORTED (1 << 8)
/* DMA Coalescing defines */
#define IGB_MIN_TXPBSIZE 20408
@@ -436,18 +445,27 @@ extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
extern void igb_power_up_link(struct igb_adapter *);
extern void igb_set_fw_version(struct igb_adapter *);
-#ifdef CONFIG_IGB_PTP
extern void igb_ptp_init(struct igb_adapter *adapter);
extern void igb_ptp_stop(struct igb_adapter *adapter);
extern void igb_ptp_reset(struct igb_adapter *adapter);
extern void igb_ptp_tx_work(struct work_struct *work);
extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
- union e1000_adv_rx_desc *rx_desc,
+extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
+ struct sk_buff *skb);
+extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+ unsigned char *va,
struct sk_buff *skb);
+static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
+ !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
+ igb_ptp_rx_rgtstamp(q_vector, skb);
+}
+
extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd);
-#endif /* CONFIG_IGB_PTP */
static inline s32 igb_reset_phy(struct e1000_hw *hw)
{
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 2ea012849825..bfe9208c4b18 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -37,6 +37,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/highmem.h>
#include "igb.h"
@@ -1623,6 +1624,20 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter)
reg &= ~E1000_CONNSW_ENRGSRC;
wr32(E1000_CONNSW, reg);
+ /* Unset sigdetect for SERDES loopback on
+ * 82580 and i350 devices.
+ */
+ switch (hw->mac.type) {
+ case e1000_82580:
+ case e1000_i350:
+ reg = rd32(E1000_PCS_CFG0);
+ reg |= E1000_PCS_CFG_IGN_SD;
+ wr32(E1000_PCS_CFG0, reg);
+ break;
+ default:
+ break;
+ }
+
/* Set PCS register for forced speed */
reg = rd32(E1000_PCS_LCTL);
reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/
@@ -1685,16 +1700,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb,
memset(&skb->data[frame_size + 12], 0xAF, 1);
}
-static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer,
+ unsigned int frame_size)
{
- frame_size /= 2;
- if (*(skb->data + 3) == 0xFF) {
- if ((*(skb->data + frame_size + 10) == 0xBE) &&
- (*(skb->data + frame_size + 12) == 0xAF)) {
- return 0;
- }
- }
- return 13;
+ unsigned char *data;
+ bool match = true;
+
+ frame_size >>= 1;
+
+ data = kmap(rx_buffer->page);
+
+ if (data[3] != 0xFF ||
+ data[frame_size + 10] != 0xBE ||
+ data[frame_size + 12] != 0xAF)
+ match = false;
+
+ kunmap(rx_buffer->page);
+
+ return match;
}
static int igb_clean_test_rings(struct igb_ring *rx_ring,
@@ -1704,9 +1727,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc;
struct igb_rx_buffer *rx_buffer_info;
struct igb_tx_buffer *tx_buffer_info;
- struct netdev_queue *txq;
u16 rx_ntc, tx_ntc, count = 0;
- unsigned int total_bytes = 0, total_packets = 0;
/* initialize next to clean and descriptor values */
rx_ntc = rx_ring->next_to_clean;
@@ -1717,21 +1738,24 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
/* check rx buffer */
rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
- /* unmap rx buffer, will be remapped by alloc_rx_buffers */
- dma_unmap_single(rx_ring->dev,
- rx_buffer_info->dma,
- IGB_RX_HDR_LEN,
- DMA_FROM_DEVICE);
- rx_buffer_info->dma = 0;
+ /* sync Rx buffer for CPU read */
+ dma_sync_single_for_cpu(rx_ring->dev,
+ rx_buffer_info->dma,
+ IGB_RX_BUFSZ,
+ DMA_FROM_DEVICE);
/* verify contents of skb */
- if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
+ if (igb_check_lbtest_frame(rx_buffer_info, size))
count++;
+ /* sync Rx buffer for device write */
+ dma_sync_single_for_device(rx_ring->dev,
+ rx_buffer_info->dma,
+ IGB_RX_BUFSZ,
+ DMA_FROM_DEVICE);
+
/* unmap buffer on tx side */
tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
- total_bytes += tx_buffer_info->bytecount;
- total_packets += tx_buffer_info->gso_segs;
igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
/* increment rx/tx next to clean counters */
@@ -1746,8 +1770,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
}
- txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
- netdev_tx_completed_queue(txq, total_packets, total_bytes);
+ netdev_tx_reset_queue(txring_txq(tx_ring));
/* re-map buffers to ring, store next to clean values */
igb_alloc_rx_buffers(rx_ring, count);
@@ -1957,54 +1980,6 @@ static void igb_diag_test(struct net_device *netdev,
msleep_interruptible(4 * 1000);
}
-static int igb_wol_exclusion(struct igb_adapter *adapter,
- struct ethtool_wolinfo *wol)
-{
- struct e1000_hw *hw = &adapter->hw;
- int retval = 1; /* fail by default */
-
- switch (hw->device_id) {
- case E1000_DEV_ID_82575GB_QUAD_COPPER:
- /* WoL not supported */
- wol->supported = 0;
- break;
- case E1000_DEV_ID_82575EB_FIBER_SERDES:
- case E1000_DEV_ID_82576_FIBER:
- case E1000_DEV_ID_82576_SERDES:
- /* Wake events not supported on port B */
- if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) {
- wol->supported = 0;
- break;
- }
- /* return success for non excluded adapter ports */
- retval = 0;
- break;
- case E1000_DEV_ID_82576_QUAD_COPPER:
- case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
- /* quad port adapters only support WoL on port A */
- if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) {
- wol->supported = 0;
- break;
- }
- /* return success for non excluded adapter ports */
- retval = 0;
- break;
- default:
- /* dual port cards only support WoL on port A from now on
- * unless it was enabled in the eeprom for port B
- * so exclude FUNC_1 ports from having WoL enabled */
- if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) &&
- !adapter->eeprom_wol) {
- wol->supported = 0;
- break;
- }
-
- retval = 0;
- }
-
- return retval;
-}
-
static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2014,10 +1989,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
WAKE_PHY;
wol->wolopts = 0;
- /* this function will set ->supported = 0 and return 1 if wol is not
- * supported by this hardware */
- if (igb_wol_exclusion(adapter, wol) ||
- !device_can_wakeup(&adapter->pdev->dev))
+ if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
return;
/* apply any specific unsupported masks here */
@@ -2045,8 +2017,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
- if (igb_wol_exclusion(adapter, wol) ||
- !device_can_wakeup(&adapter->pdev->dev))
+ if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
return wol->wolopts ? -EOPNOTSUPP : 0;
/* these settings will always override what we currently have */
@@ -2301,7 +2272,6 @@ static int igb_get_ts_info(struct net_device *dev,
struct igb_adapter *adapter = netdev_priv(dev);
switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IGB_PTP
case e1000_82576:
case e1000_82580:
case e1000_i350:
@@ -2337,12 +2307,288 @@ static int igb_get_ts_info(struct net_device *dev,
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
return 0;
-#endif /* CONFIG_IGB_PTP */
default:
return -EOPNOTSUPP;
}
}
+static int igb_get_rss_hash_opts(struct igb_adapter *adapter,
+ struct ethtool_rxnfc *cmd)
+{
+ cmd->data = 0;
+
+ /* Report default options for RSS on igb */
+ switch (cmd->flow_type) {
+ case TCP_V4_FLOW:
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case UDP_V4_FLOW:
+ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case IPV4_FLOW:
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case TCP_V6_FLOW:
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case UDP_V6_FLOW:
+ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case IPV6_FLOW:
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct igb_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = adapter->num_rx_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXFH:
+ ret = igb_get_rss_hash_opts(adapter, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \
+ IGB_FLAG_RSS_FIELD_IPV6_UDP)
+static int igb_set_rss_hash_opt(struct igb_adapter *adapter,
+ struct ethtool_rxnfc *nfc)
+{
+ u32 flags = adapter->flags;
+
+ /* RSS does not support anything other than hashing
+ * to queues on src and dst IPs and ports
+ */
+ if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3))
+ return -EINVAL;
+
+ switch (nfc->flow_type) {
+ case TCP_V4_FLOW:
+ case TCP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST) ||
+ !(nfc->data & RXH_L4_B_0_1) ||
+ !(nfc->data & RXH_L4_B_2_3))
+ return -EINVAL;
+ break;
+ case UDP_V4_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST))
+ return -EINVAL;
+ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+ case 0:
+ flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP;
+ break;
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+ flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case UDP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST))
+ return -EINVAL;
+ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+ case 0:
+ flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP;
+ break;
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+ flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST) ||
+ (nfc->data & RXH_L4_B_0_1) ||
+ (nfc->data & RXH_L4_B_2_3))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* if we changed something we need to update flags */
+ if (flags != adapter->flags) {
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mrqc = rd32(E1000_MRQC);
+
+ if ((flags & UDP_RSS_FLAGS) &&
+ !(adapter->flags & UDP_RSS_FLAGS))
+ dev_err(&adapter->pdev->dev,
+ "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
+
+ adapter->flags = flags;
+
+ /* Perform hash on these packet types */
+ mrqc |= E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP;
+
+ mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP |
+ E1000_MRQC_RSS_FIELD_IPV6_UDP);
+
+ if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+ mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+
+ if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+ mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
+ wr32(E1000_MRQC, mrqc);
+ }
+
+ return 0;
+}
+
+static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct igb_adapter *adapter = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXFH:
+ ret = igb_set_rss_hash_opt(adapter, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
+{
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ipcnfg, eeer;
+
+ if ((hw->mac.type < e1000_i350) ||
+ (hw->phy.media_type != e1000_media_type_copper))
+ return -EOPNOTSUPP;
+
+ edata->supported = (SUPPORTED_1000baseT_Full |
+ SUPPORTED_100baseT_Full);
+
+ ipcnfg = rd32(E1000_IPCNFG);
+ eeer = rd32(E1000_EEER);
+
+ /* EEE status on negotiated link */
+ if (ipcnfg & E1000_IPCNFG_EEE_1G_AN)
+ edata->advertised = ADVERTISED_1000baseT_Full;
+
+ if (ipcnfg & E1000_IPCNFG_EEE_100M_AN)
+ edata->advertised |= ADVERTISED_100baseT_Full;
+
+ if (eeer & E1000_EEER_EEE_NEG)
+ edata->eee_active = true;
+
+ edata->eee_enabled = !hw->dev_spec._82575.eee_disable;
+
+ if (eeer & E1000_EEER_TX_LPI_EN)
+ edata->tx_lpi_enabled = true;
+
+ /* Report correct negotiated EEE status for devices that
+ * wrongly report EEE at half-duplex
+ */
+ if (adapter->link_duplex == HALF_DUPLEX) {
+ edata->eee_enabled = false;
+ edata->eee_active = false;
+ edata->tx_lpi_enabled = false;
+ edata->advertised &= ~edata->advertised;
+ }
+
+ return 0;
+}
+
+static int igb_set_eee(struct net_device *netdev,
+ struct ethtool_eee *edata)
+{
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ struct ethtool_eee eee_curr;
+ s32 ret_val;
+
+ if ((hw->mac.type < e1000_i350) ||
+ (hw->phy.media_type != e1000_media_type_copper))
+ return -EOPNOTSUPP;
+
+ ret_val = igb_get_eee(netdev, &eee_curr);
+ if (ret_val)
+ return ret_val;
+
+ if (eee_curr.eee_enabled) {
+ if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
+ dev_err(&adapter->pdev->dev,
+ "Setting EEE tx-lpi is not supported\n");
+ return -EINVAL;
+ }
+
+ /* Tx LPI timer is not implemented currently */
+ if (edata->tx_lpi_timer) {
+ dev_err(&adapter->pdev->dev,
+ "Setting EEE Tx LPI timer is not supported\n");
+ return -EINVAL;
+ }
+
+ if (eee_curr.advertised != edata->advertised) {
+ dev_err(&adapter->pdev->dev,
+ "Setting EEE Advertisement is not supported\n");
+ return -EINVAL;
+ }
+
+ } else if (!edata->eee_enabled) {
+ dev_err(&adapter->pdev->dev,
+ "Setting EEE options are not supported with EEE disabled\n");
+ return -EINVAL;
+ }
+
+ if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
+ hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
+ igb_set_eee_i350(hw);
+
+ /* reset link */
+ if (!netif_running(netdev))
+ igb_reset(adapter);
+ }
+
+ return 0;
+}
+
static int igb_ethtool_begin(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2383,6 +2629,10 @@ static const struct ethtool_ops igb_ethtool_ops = {
.get_coalesce = igb_get_coalesce,
.set_coalesce = igb_set_coalesce,
.get_ts_info = igb_get_ts_info,
+ .get_rxnfc = igb_get_rxnfc,
+ .set_rxnfc = igb_set_rxnfc,
+ .get_eee = igb_get_eee,
+ .set_eee = igb_set_eee,
.begin = igb_ethtool_begin,
.complete = igb_ethtool_complete,
};
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index e1ceb37ef12e..31cfe2ec75df 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -60,8 +60,8 @@
#include "igb.h"
#define MAJ 4
-#define MIN 0
-#define BUILD 1
+#define MIN 1
+#define BUILD 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
@@ -118,10 +118,11 @@ static void igb_free_all_tx_resources(struct igb_adapter *);
static void igb_free_all_rx_resources(struct igb_adapter *);
static void igb_setup_mrqc(struct igb_adapter *);
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit igb_remove(struct pci_dev *pdev);
+static void igb_remove(struct pci_dev *pdev);
static int igb_sw_init(struct igb_adapter *);
static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
+static void igb_configure(struct igb_adapter *);
static void igb_configure_tx(struct igb_adapter *);
static void igb_configure_rx(struct igb_adapter *);
static void igb_clean_all_tx_rings(struct igb_adapter *);
@@ -228,7 +229,7 @@ static struct pci_driver igb_driver = {
.name = igb_driver_name,
.id_table = igb_pci_tbl,
.probe = igb_probe,
- .remove = __devexit_p(igb_remove),
+ .remove = igb_remove,
#ifdef CONFIG_PM
.driver.pm = &igb_pm_ops,
#endif
@@ -534,31 +535,27 @@ rx_ring_summary:
if (staterr & E1000_RXD_STAT_DD) {
/* Descriptor Done */
- pr_info("%s[0x%03X] %016llX %016llX -------"
- "--------- %p%s\n", "RWB", i,
+ pr_info("%s[0x%03X] %016llX %016llX ---------------- %s\n",
+ "RWB", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
- buffer_info->skb, next_desc);
+ next_desc);
} else {
- pr_info("%s[0x%03X] %016llX %016llX %016llX"
- " %p%s\n", "R ", i,
+ pr_info("%s[0x%03X] %016llX %016llX %016llX %s\n",
+ "R ", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)buffer_info->dma,
- buffer_info->skb, next_desc);
+ next_desc);
if (netif_msg_pktdata(adapter) &&
- buffer_info->dma && buffer_info->skb) {
- print_hex_dump(KERN_INFO, "",
- DUMP_PREFIX_ADDRESS,
- 16, 1, buffer_info->skb->data,
- IGB_RX_HDR_LEN, true);
+ buffer_info->dma && buffer_info->page) {
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1,
page_address(buffer_info->page) +
buffer_info->page_offset,
- PAGE_SIZE/2, true);
+ IGB_RX_BUFSZ, true);
}
}
}
@@ -656,80 +653,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
}
}
-static void igb_free_queues(struct igb_adapter *adapter)
-{
- int i;
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- kfree(adapter->tx_ring[i]);
- adapter->tx_ring[i] = NULL;
- }
- for (i = 0; i < adapter->num_rx_queues; i++) {
- kfree(adapter->rx_ring[i]);
- adapter->rx_ring[i] = NULL;
- }
- adapter->num_rx_queues = 0;
- adapter->num_tx_queues = 0;
-}
-
-/**
- * igb_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time.
- **/
-static int igb_alloc_queues(struct igb_adapter *adapter)
-{
- struct igb_ring *ring;
- int i;
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
- if (!ring)
- goto err;
- ring->count = adapter->tx_ring_count;
- ring->queue_index = i;
- ring->dev = &adapter->pdev->dev;
- ring->netdev = adapter->netdev;
- /* For 82575, context index must be unique per ring. */
- if (adapter->hw.mac.type == e1000_82575)
- set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
- adapter->tx_ring[i] = ring;
- }
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
- if (!ring)
- goto err;
- ring->count = adapter->rx_ring_count;
- ring->queue_index = i;
- ring->dev = &adapter->pdev->dev;
- ring->netdev = adapter->netdev;
- /* set flag indicating ring supports SCTP checksum offload */
- if (adapter->hw.mac.type >= e1000_82576)
- set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
-
- /*
- * On i350, i210, and i211, loopback VLAN packets
- * have the tag byte-swapped.
- * */
- if (adapter->hw.mac.type >= e1000_i350)
- set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
-
- adapter->rx_ring[i] = ring;
- }
-
- igb_cache_ring_register(adapter);
-
- return 0;
-
-err:
- igb_free_queues(adapter);
-
- return -ENOMEM;
-}
-
/**
* igb_write_ivar - configure ivar for given MSI-X vector
* @hw: pointer to the HW structure
@@ -909,17 +832,18 @@ static int igb_request_msix(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
- int i, err = 0, vector = 0;
+ int i, err = 0, vector = 0, free_vector = 0;
err = request_irq(adapter->msix_entries[vector].vector,
igb_msix_other, 0, netdev->name, adapter);
if (err)
- goto out;
- vector++;
+ goto err_out;
for (i = 0; i < adapter->num_q_vectors; i++) {
struct igb_q_vector *q_vector = adapter->q_vector[i];
+ vector++;
+
q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
if (q_vector->rx.ring && q_vector->tx.ring)
@@ -938,13 +862,22 @@ static int igb_request_msix(struct igb_adapter *adapter)
igb_msix_ring, 0, q_vector->name,
q_vector);
if (err)
- goto out;
- vector++;
+ goto err_free;
}
igb_configure_msix(adapter);
return 0;
-out:
+
+err_free:
+ /* free already assigned IRQs */
+ free_irq(adapter->msix_entries[free_vector++].vector, adapter);
+
+ vector--;
+ for (i = 0; i < vector; i++) {
+ free_irq(adapter->msix_entries[free_vector++].vector,
+ adapter->q_vector[i]);
+ }
+err_out:
return err;
}
@@ -960,6 +893,35 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
}
/**
+ * igb_free_q_vector - Free memory allocated for specific interrupt vector
+ * @adapter: board private structure to initialize
+ * @v_idx: Index of vector to be freed
+ *
+ * This function frees the memory allocated to the q_vector. In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
+{
+ struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+
+ if (q_vector->tx.ring)
+ adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
+
+ if (q_vector->rx.ring)
+ adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
+
+ adapter->q_vector[v_idx] = NULL;
+ netif_napi_del(&q_vector->napi);
+
+ /*
+ * ixgbe_get_stats64() might access the rings on this vector,
+ * we must wait a grace period before freeing it.
+ */
+ kfree_rcu(q_vector, rcu);
+}
+
+/**
* igb_free_q_vectors - Free memory allocated for interrupt vectors
* @adapter: board private structure to initialize
*
@@ -969,17 +931,14 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
**/
static void igb_free_q_vectors(struct igb_adapter *adapter)
{
- int v_idx;
+ int v_idx = adapter->num_q_vectors;
- for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
- struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
- adapter->q_vector[v_idx] = NULL;
- if (!q_vector)
- continue;
- netif_napi_del(&q_vector->napi);
- kfree(q_vector);
- }
+ adapter->num_tx_queues = 0;
+ adapter->num_rx_queues = 0;
adapter->num_q_vectors = 0;
+
+ while (v_idx--)
+ igb_free_q_vector(adapter, v_idx);
}
/**
@@ -990,7 +949,6 @@ static void igb_free_q_vectors(struct igb_adapter *adapter)
*/
static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
{
- igb_free_queues(adapter);
igb_free_q_vectors(adapter);
igb_reset_interrupt_capability(adapter);
}
@@ -1001,11 +959,14 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
* Attempt to configure interrupts using the best available
* capabilities of the hardware and kernel.
**/
-static int igb_set_interrupt_capability(struct igb_adapter *adapter)
+static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix)
{
int err;
int numvecs, i;
+ if (!msix)
+ goto msi_only;
+
/* Number of supported queues. */
adapter->num_rx_queues = adapter->rss_queues;
if (adapter->vfs_allocated_count)
@@ -1038,7 +999,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
adapter->msix_entries,
numvecs);
if (err == 0)
- goto out;
+ return;
igb_reset_interrupt_capability(adapter);
@@ -1068,105 +1029,183 @@ msi_only:
adapter->num_q_vectors = 1;
if (!pci_enable_msi(adapter->pdev))
adapter->flags |= IGB_FLAG_HAS_MSI;
-out:
- /* Notify the stack of the (possibly) reduced queue counts. */
- rtnl_lock();
- netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
- err = netif_set_real_num_rx_queues(adapter->netdev,
- adapter->num_rx_queues);
- rtnl_unlock();
- return err;
+}
+
+static void igb_add_ring(struct igb_ring *ring,
+ struct igb_ring_container *head)
+{
+ head->ring = ring;
+ head->count++;
}
/**
- * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * igb_alloc_q_vector - Allocate memory for a single interrupt vector
* @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
+ * @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
*
- * We allocate one q_vector per queue interrupt. If allocation fails we
- * return -ENOMEM.
+ * We allocate one q_vector. If allocation fails we return -ENOMEM.
**/
-static int igb_alloc_q_vectors(struct igb_adapter *adapter)
+static int igb_alloc_q_vector(struct igb_adapter *adapter,
+ int v_count, int v_idx,
+ int txr_count, int txr_idx,
+ int rxr_count, int rxr_idx)
{
struct igb_q_vector *q_vector;
- struct e1000_hw *hw = &adapter->hw;
- int v_idx;
+ struct igb_ring *ring;
+ int ring_count, size;
- for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
- q_vector = kzalloc(sizeof(struct igb_q_vector),
- GFP_KERNEL);
- if (!q_vector)
- goto err_out;
- q_vector->adapter = adapter;
- q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
- q_vector->itr_val = IGB_START_ITR;
- netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
- adapter->q_vector[v_idx] = q_vector;
+ /* igb only supports 1 Tx and/or 1 Rx queue per vector */
+ if (txr_count > 1 || rxr_count > 1)
+ return -ENOMEM;
+
+ ring_count = txr_count + rxr_count;
+ size = sizeof(struct igb_q_vector) +
+ (sizeof(struct igb_ring) * ring_count);
+
+ /* allocate q_vector and rings */
+ q_vector = kzalloc(size, GFP_KERNEL);
+ if (!q_vector)
+ return -ENOMEM;
+
+ /* initialize NAPI */
+ netif_napi_add(adapter->netdev, &q_vector->napi,
+ igb_poll, 64);
+
+ /* tie q_vector and adapter together */
+ adapter->q_vector[v_idx] = q_vector;
+ q_vector->adapter = adapter;
+
+ /* initialize work limits */
+ q_vector->tx.work_limit = adapter->tx_work_limit;
+
+ /* initialize ITR configuration */
+ q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0);
+ q_vector->itr_val = IGB_START_ITR;
+
+ /* initialize pointer to rings */
+ ring = q_vector->ring;
+
+ if (txr_count) {
+ /* assign generic ring traits */
+ ring->dev = &adapter->pdev->dev;
+ ring->netdev = adapter->netdev;
+
+ /* configure backlink on ring */
+ ring->q_vector = q_vector;
+
+ /* update q_vector Tx values */
+ igb_add_ring(ring, &q_vector->tx);
+
+ /* For 82575, context index must be unique per ring. */
+ if (adapter->hw.mac.type == e1000_82575)
+ set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
+
+ /* apply Tx specific ring traits */
+ ring->count = adapter->tx_ring_count;
+ ring->queue_index = txr_idx;
+
+ /* assign ring to adapter */
+ adapter->tx_ring[txr_idx] = ring;
+
+ /* push pointer to next ring */
+ ring++;
}
- return 0;
+ if (rxr_count) {
+ /* assign generic ring traits */
+ ring->dev = &adapter->pdev->dev;
+ ring->netdev = adapter->netdev;
-err_out:
- igb_free_q_vectors(adapter);
- return -ENOMEM;
-}
+ /* configure backlink on ring */
+ ring->q_vector = q_vector;
-static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
- int ring_idx, int v_idx)
-{
- struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+ /* update q_vector Rx values */
+ igb_add_ring(ring, &q_vector->rx);
- q_vector->rx.ring = adapter->rx_ring[ring_idx];
- q_vector->rx.ring->q_vector = q_vector;
- q_vector->rx.count++;
- q_vector->itr_val = adapter->rx_itr_setting;
- if (q_vector->itr_val && q_vector->itr_val <= 3)
- q_vector->itr_val = IGB_START_ITR;
-}
+ /* set flag indicating ring supports SCTP checksum offload */
+ if (adapter->hw.mac.type >= e1000_82576)
+ set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
-static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
- int ring_idx, int v_idx)
-{
- struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+ /*
+ * On i350, i210, and i211, loopback VLAN packets
+ * have the tag byte-swapped.
+ * */
+ if (adapter->hw.mac.type >= e1000_i350)
+ set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
- q_vector->tx.ring = adapter->tx_ring[ring_idx];
- q_vector->tx.ring->q_vector = q_vector;
- q_vector->tx.count++;
- q_vector->itr_val = adapter->tx_itr_setting;
- q_vector->tx.work_limit = adapter->tx_work_limit;
- if (q_vector->itr_val && q_vector->itr_val <= 3)
- q_vector->itr_val = IGB_START_ITR;
+ /* apply Rx specific ring traits */
+ ring->count = adapter->rx_ring_count;
+ ring->queue_index = rxr_idx;
+
+ /* assign ring to adapter */
+ adapter->rx_ring[rxr_idx] = ring;
+ }
+
+ return 0;
}
+
/**
- * igb_map_ring_to_vector - maps allocated queues to vectors
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
*
- * This function maps the recently allocated queues to vectors.
+ * We allocate one q_vector per queue interrupt. If allocation fails we
+ * return -ENOMEM.
**/
-static int igb_map_ring_to_vector(struct igb_adapter *adapter)
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
{
- int i;
- int v_idx = 0;
+ int q_vectors = adapter->num_q_vectors;
+ int rxr_remaining = adapter->num_rx_queues;
+ int txr_remaining = adapter->num_tx_queues;
+ int rxr_idx = 0, txr_idx = 0, v_idx = 0;
+ int err;
- if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
- (adapter->num_q_vectors < adapter->num_tx_queues))
- return -ENOMEM;
+ if (q_vectors >= (rxr_remaining + txr_remaining)) {
+ for (; rxr_remaining; v_idx++) {
+ err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+ 0, 0, 1, rxr_idx);
- if (adapter->num_q_vectors >=
- (adapter->num_rx_queues + adapter->num_tx_queues)) {
- for (i = 0; i < adapter->num_rx_queues; i++)
- igb_map_rx_ring_to_vector(adapter, i, v_idx++);
- for (i = 0; i < adapter->num_tx_queues; i++)
- igb_map_tx_ring_to_vector(adapter, i, v_idx++);
- } else {
- for (i = 0; i < adapter->num_rx_queues; i++) {
- if (i < adapter->num_tx_queues)
- igb_map_tx_ring_to_vector(adapter, i, v_idx);
- igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+ if (err)
+ goto err_out;
+
+ /* update counts and index */
+ rxr_remaining--;
+ rxr_idx++;
}
- for (; i < adapter->num_tx_queues; i++)
- igb_map_tx_ring_to_vector(adapter, i, v_idx++);
}
+
+ for (; v_idx < q_vectors; v_idx++) {
+ int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+ int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+ err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+ tqpv, txr_idx, rqpv, rxr_idx);
+
+ if (err)
+ goto err_out;
+
+ /* update counts and index */
+ rxr_remaining -= rqpv;
+ txr_remaining -= tqpv;
+ rxr_idx++;
+ txr_idx++;
+ }
+
return 0;
+
+err_out:
+ adapter->num_tx_queues = 0;
+ adapter->num_rx_queues = 0;
+ adapter->num_q_vectors = 0;
+
+ while (v_idx--)
+ igb_free_q_vector(adapter, v_idx);
+
+ return -ENOMEM;
}
/**
@@ -1174,14 +1213,12 @@ static int igb_map_ring_to_vector(struct igb_adapter *adapter)
*
* This function initializes the interrupts and allocates all of the queues.
**/
-static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
+static int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix)
{
struct pci_dev *pdev = adapter->pdev;
int err;
- err = igb_set_interrupt_capability(adapter);
- if (err)
- return err;
+ igb_set_interrupt_capability(adapter, msix);
err = igb_alloc_q_vectors(adapter);
if (err) {
@@ -1189,24 +1226,10 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
goto err_alloc_q_vectors;
}
- err = igb_alloc_queues(adapter);
- if (err) {
- dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
- goto err_alloc_queues;
- }
-
- err = igb_map_ring_to_vector(adapter);
- if (err) {
- dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
- goto err_map_queues;
- }
-
+ igb_cache_ring_register(adapter);
return 0;
-err_map_queues:
- igb_free_queues(adapter);
-err_alloc_queues:
- igb_free_q_vectors(adapter);
+
err_alloc_q_vectors:
igb_reset_interrupt_capability(adapter);
return err;
@@ -1229,29 +1252,17 @@ static int igb_request_irq(struct igb_adapter *adapter)
if (!err)
goto request_done;
/* fall back to MSI */
- igb_clear_interrupt_scheme(adapter);
- if (!pci_enable_msi(pdev))
- adapter->flags |= IGB_FLAG_HAS_MSI;
igb_free_all_tx_resources(adapter);
igb_free_all_rx_resources(adapter);
- adapter->num_tx_queues = 1;
- adapter->num_rx_queues = 1;
- adapter->num_q_vectors = 1;
- err = igb_alloc_q_vectors(adapter);
- if (err) {
- dev_err(&pdev->dev,
- "Unable to allocate memory for vectors\n");
- goto request_done;
- }
- err = igb_alloc_queues(adapter);
- if (err) {
- dev_err(&pdev->dev,
- "Unable to allocate memory for queues\n");
- igb_free_q_vectors(adapter);
+
+ igb_clear_interrupt_scheme(adapter);
+ err = igb_init_interrupt_scheme(adapter, false);
+ if (err)
goto request_done;
- }
+
igb_setup_all_tx_resources(adapter);
igb_setup_all_rx_resources(adapter);
+ igb_configure(adapter);
}
igb_assign_vector(adapter->q_vector[0], 0);
@@ -1587,8 +1598,7 @@ void igb_reset(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
struct e1000_fc_info *fc = &hw->fc;
- u32 pba = 0, tx_space, min_tx_space, min_rx_space;
- u16 hwm;
+ u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
@@ -1663,7 +1673,7 @@ void igb_reset(struct igb_adapter *adapter)
hwm = min(((pba << 10) * 9 / 10),
((pba << 10) - 2 * adapter->max_frame_size));
- fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */
+ fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */
fc->low_water = fc->high_water - 16;
fc->pause_time = 0xFFFF;
fc->send_xon = 1;
@@ -1706,10 +1716,8 @@ void igb_reset(struct igb_adapter *adapter)
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
-#ifdef CONFIG_IGB_PTP
/* Re-enable PTP, where applicable. */
igb_ptp_reset(adapter);
-#endif /* CONFIG_IGB_PTP */
igb_get_phy_info(hw);
}
@@ -1783,58 +1791,34 @@ static const struct net_device_ops igb_netdev_ops = {
void igb_set_fw_version(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
- u16 major, build, patch, fw_version;
- u32 etrack_id;
-
- hw->nvm.ops.read(hw, 5, 1, &fw_version);
- if (adapter->hw.mac.type != e1000_i211) {
- hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
- hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
- etrack_id = (eeprom_verh << IGB_ETRACK_SHIFT) | eeprom_verl;
-
- /* combo image version needs to be found */
- hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
- if ((comb_offset != 0x0) &&
- (comb_offset != IGB_NVM_VER_INVALID)) {
- hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
- + 1), 1, &comb_verh);
- hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
- 1, &comb_verl);
-
- /* Only display Option Rom if it exists and is valid */
- if ((comb_verh && comb_verl) &&
- ((comb_verh != IGB_NVM_VER_INVALID) &&
- (comb_verl != IGB_NVM_VER_INVALID))) {
- major = comb_verl >> IGB_COMB_VER_SHFT;
- build = (comb_verl << IGB_COMB_VER_SHFT) |
- (comb_verh >> IGB_COMB_VER_SHFT);
- patch = comb_verh & IGB_COMB_VER_MASK;
- snprintf(adapter->fw_version,
- sizeof(adapter->fw_version),
- "%d.%d%d, 0x%08x, %d.%d.%d",
- (fw_version & IGB_MAJOR_MASK) >>
- IGB_MAJOR_SHIFT,
- (fw_version & IGB_MINOR_MASK) >>
- IGB_MINOR_SHIFT,
- (fw_version & IGB_BUILD_MASK),
- etrack_id, major, build, patch);
- goto out;
- }
- }
- snprintf(adapter->fw_version, sizeof(adapter->fw_version),
- "%d.%d%d, 0x%08x",
- (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
- (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
- (fw_version & IGB_BUILD_MASK), etrack_id);
- } else {
+ struct e1000_fw_version fw;
+
+ igb_get_fw_version(hw, &fw);
+
+ switch (hw->mac.type) {
+ case e1000_i211:
snprintf(adapter->fw_version, sizeof(adapter->fw_version),
- "%d.%d%d",
- (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
- (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
- (fw_version & IGB_BUILD_MASK));
+ "%2d.%2d-%d",
+ fw.invm_major, fw.invm_minor, fw.invm_img_type);
+ break;
+
+ default:
+ /* if option is rom valid, display its version too */
+ if (fw.or_valid) {
+ snprintf(adapter->fw_version,
+ sizeof(adapter->fw_version),
+ "%d.%d, 0x%08x, %d.%d.%d",
+ fw.eep_major, fw.eep_minor, fw.etrack_id,
+ fw.or_major, fw.or_build, fw.or_patch);
+ /* no option rom */
+ } else {
+ snprintf(adapter->fw_version,
+ sizeof(adapter->fw_version),
+ "%d.%d, 0x%08x",
+ fw.eep_major, fw.eep_minor, fw.etrack_id);
+ }
+ break;
}
-out:
return;
}
@@ -1849,8 +1833,7 @@ out:
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit igb_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct igb_adapter *adapter;
@@ -1861,7 +1844,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
unsigned long mmio_start, mmio_len;
int err, pci_using_dac;
- u16 eeprom_apme_mask = IGB_EEPROM_APME;
u8 part_str[E1000_PBANUM_LENGTH];
/* Catch broken hardware that put the wrong VF device ID in
@@ -2069,28 +2051,27 @@ static int __devinit igb_probe(struct pci_dev *pdev,
igb_validate_mdi_setting(hw);
- /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
- * enable the ACPI Magic Packet filter
- */
-
+ /* By default, support wake on port A */
if (hw->bus.func == 0)
- hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
- else if (hw->mac.type >= e1000_82580)
+ adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+
+ /* Check the NVM for wake support on non-port A ports */
+ if (hw->mac.type >= e1000_82580)
hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
&eeprom_data);
else if (hw->bus.func == 1)
hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
- if (eeprom_data & eeprom_apme_mask)
- adapter->eeprom_wol |= E1000_WUFC_MAG;
+ if (eeprom_data & IGB_EEPROM_APME)
+ adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
/* now that we have the eeprom settings, apply the special cases where
* the eeprom may be wrong or the board simply won't support wake on
* lan on a particular port */
switch (pdev->device) {
case E1000_DEV_ID_82575GB_QUAD_COPPER:
- adapter->eeprom_wol = 0;
+ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
break;
case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82576_FIBER:
@@ -2098,24 +2079,38 @@ static int __devinit igb_probe(struct pci_dev *pdev,
/* Wake events only supported on port A for dual fiber
* regardless of eeprom setting */
if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1)
- adapter->eeprom_wol = 0;
+ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
break;
case E1000_DEV_ID_82576_QUAD_COPPER:
case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
/* if quad port adapter, disable WoL on all but port A */
if (global_quad_port_a != 0)
- adapter->eeprom_wol = 0;
+ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
else
adapter->flags |= IGB_FLAG_QUAD_PORT_A;
/* Reset for multiple quad port adapters */
if (++global_quad_port_a == 4)
global_quad_port_a = 0;
break;
+ default:
+ /* If the device can't wake, don't set software support */
+ if (!device_can_wakeup(&adapter->pdev->dev))
+ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
}
/* initialize the wol settings based on the eeprom settings */
- adapter->wol = adapter->eeprom_wol;
- device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+ if (adapter->flags & IGB_FLAG_WOL_SUPPORTED)
+ adapter->wol |= E1000_WUFC_MAG;
+
+ /* Some vendors want WoL disabled by default, but still supported */
+ if ((hw->mac.type == e1000_i350) &&
+ (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
+ adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+ adapter->wol = 0;
+ }
+
+ device_set_wakeup_enable(&adapter->pdev->dev,
+ adapter->flags & IGB_FLAG_WOL_SUPPORTED);
/* reset the hardware with the new settings */
igb_reset(adapter);
@@ -2141,10 +2136,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
#endif
-#ifdef CONFIG_IGB_PTP
/* do hw tstamp init after resetting */
igb_ptp_init(adapter);
-#endif /* CONFIG_IGB_PTP */
dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
/* print bus type/speed/width info */
@@ -2212,16 +2205,14 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit igb_remove(struct pci_dev *pdev)
+static void igb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
pm_runtime_get_noresume(&pdev->dev);
-#ifdef CONFIG_IGB_PTP
igb_ptp_stop(adapter);
-#endif /* CONFIG_IGB_PTP */
/*
* The watchdog timer may be rescheduled, so explicitly
@@ -2294,7 +2285,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
* mor expensive time wise to disable SR-IOV than it is to allocate and free
* the memory for the VFs.
**/
-static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+static void igb_probe_vfs(struct igb_adapter *adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
@@ -2355,7 +2346,7 @@ out:
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int __devinit igb_sw_init(struct igb_adapter *adapter)
+static int igb_sw_init(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
@@ -2461,7 +2452,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
GFP_ATOMIC);
/* This call may decrease the number of queues */
- if (igb_init_interrupt_scheme(adapter)) {
+ if (igb_init_interrupt_scheme(adapter, true)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
@@ -2531,6 +2522,17 @@ static int __igb_open(struct net_device *netdev, bool resuming)
if (err)
goto err_req_irq;
+ /* Notify the stack of the actual queue counts. */
+ err = netif_set_real_num_tx_queues(adapter->netdev,
+ adapter->num_tx_queues);
+ if (err)
+ goto err_set_queues;
+
+ err = netif_set_real_num_rx_queues(adapter->netdev,
+ adapter->num_rx_queues);
+ if (err)
+ goto err_set_queues;
+
/* From here on the code is the same as igb_up() */
clear_bit(__IGB_DOWN, &adapter->state);
@@ -2560,6 +2562,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
return 0;
+err_set_queues:
+ igb_free_irq(adapter);
err_req_irq:
igb_release_hw_control(adapter);
igb_power_down_link(adapter);
@@ -2637,10 +2641,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
- tx_ring->desc = dma_alloc_coherent(dev,
- tx_ring->size,
- &tx_ring->dma,
- GFP_KERNEL);
+ tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+ &tx_ring->dma, GFP_KERNEL);
if (!tx_ring->desc)
goto err;
@@ -2777,18 +2779,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
if (!rx_ring->rx_buffer_info)
goto err;
-
/* Round up to nearest 4K */
rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
rx_ring->size = ALIGN(rx_ring->size, 4096);
- rx_ring->desc = dma_alloc_coherent(dev,
- rx_ring->size,
- &rx_ring->dma,
- GFP_KERNEL);
+ rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+ &rx_ring->dma, GFP_KERNEL);
if (!rx_ring->desc)
goto err;
+ rx_ring->next_to_alloc = 0;
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
@@ -2893,18 +2893,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
/* Don't need to set TUOFL or IPOFL, they default to 1 */
wr32(E1000_RXCSUM, rxcsum);
- /*
- * Generate RSS hash based on TCP port numbers and/or
- * IPv4/v6 src and dst addresses since UDP cannot be
- * hashed reliably due to IP fragmentation
- */
+ /* Generate RSS hash based on packet types, TCP/UDP
+ * port numbers and/or IPv4/v6 src and dst addresses
+ */
mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
E1000_MRQC_RSS_FIELD_IPV4_TCP |
E1000_MRQC_RSS_FIELD_IPV6 |
E1000_MRQC_RSS_FIELD_IPV6_TCP |
E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
+ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+ mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+ mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
/* If VMDq is enabled then we set the appropriate mode for that, else
* we default to RSS so that an RSS hash is calculated per packet even
* if we are only using one queue */
@@ -3106,16 +3109,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
/* set descriptor configuration */
srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
- srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#else
- srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#endif
- srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-#ifdef CONFIG_IGB_PTP
+ srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
if (hw->mac.type >= e1000_82580)
srrctl |= E1000_SRRCTL_TIMESTAMP;
-#endif /* CONFIG_IGB_PTP */
/* Only set Drop Enable if we are supporting multiple queues */
if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
srrctl |= E1000_SRRCTL_DROP_EN;
@@ -3305,36 +3302,27 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
unsigned long size;
u16 i;
+ if (rx_ring->skb)
+ dev_kfree_skb(rx_ring->skb);
+ rx_ring->skb = NULL;
+
if (!rx_ring->rx_buffer_info)
return;
/* Free all the Rx ring sk_buffs */
for (i = 0; i < rx_ring->count; i++) {
struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
- if (buffer_info->dma) {
- dma_unmap_single(rx_ring->dev,
- buffer_info->dma,
- IGB_RX_HDR_LEN,
- DMA_FROM_DEVICE);
- buffer_info->dma = 0;
- }
- if (buffer_info->skb) {
- dev_kfree_skb(buffer_info->skb);
- buffer_info->skb = NULL;
- }
- if (buffer_info->page_dma) {
- dma_unmap_page(rx_ring->dev,
- buffer_info->page_dma,
- PAGE_SIZE / 2,
- DMA_FROM_DEVICE);
- buffer_info->page_dma = 0;
- }
- if (buffer_info->page) {
- put_page(buffer_info->page);
- buffer_info->page = NULL;
- buffer_info->page_offset = 0;
- }
+ if (!buffer_info->page)
+ continue;
+
+ dma_unmap_page(rx_ring->dev,
+ buffer_info->dma,
+ PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ __free_page(buffer_info->page);
+
+ buffer_info->page = NULL;
}
size = sizeof(struct igb_rx_buffer) * rx_ring->count;
@@ -3343,6 +3331,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
/* Zero out the descriptor ring */
memset(rx_ring->desc, 0, rx_ring->size);
+ rx_ring->next_to_alloc = 0;
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
}
@@ -4028,6 +4017,9 @@ static int igb_tso(struct igb_ring *tx_ring,
u32 vlan_macip_lens, type_tucmd;
u32 mss_l4len_idx, l4len;
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
if (!skb_is_gso(skb))
return 0;
@@ -4148,26 +4140,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
}
-static __le32 igb_tx_cmd_type(u32 tx_flags)
+#define IGB_SET_FLAG(_input, _flag, _result) \
+ ((_flag <= _result) ? \
+ ((u32)(_input & _flag) * (_result / _flag)) : \
+ ((u32)(_input & _flag) / (_flag / _result)))
+
+static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
{
/* set type for advanced descriptor with frame checksum insertion */
- __le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA |
- E1000_ADVTXD_DCMD_IFCS |
- E1000_ADVTXD_DCMD_DEXT);
+ u32 cmd_type = E1000_ADVTXD_DTYP_DATA |
+ E1000_ADVTXD_DCMD_DEXT |
+ E1000_ADVTXD_DCMD_IFCS;
/* set HW vlan bit if vlan is present */
- if (tx_flags & IGB_TX_FLAGS_VLAN)
- cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE);
+ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN,
+ (E1000_ADVTXD_DCMD_VLE));
+
+ /* set segmentation bits for TSO */
+ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO,
+ (E1000_ADVTXD_DCMD_TSE));
-#ifdef CONFIG_IGB_PTP
/* set timestamp bit if present */
- if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP))
- cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
-#endif /* CONFIG_IGB_PTP */
+ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP,
+ (E1000_ADVTXD_MAC_TSTAMP));
- /* set segmentation bits for TSO */
- if (tx_flags & IGB_TX_FLAGS_TSO)
- cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
+ /* insert frame checksum */
+ cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS);
return cmd_type;
}
@@ -4178,19 +4176,19 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
{
u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
- /* 82575 requires a unique index per ring if any offload is enabled */
- if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) &&
- test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
+ /* 82575 requires a unique index per ring */
+ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
olinfo_status |= tx_ring->reg_idx << 4;
/* insert L4 checksum */
- if (tx_flags & IGB_TX_FLAGS_CSUM) {
- olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+ olinfo_status |= IGB_SET_FLAG(tx_flags,
+ IGB_TX_FLAGS_CSUM,
+ (E1000_TXD_POPTS_TXSM << 8));
- /* insert IPv4 checksum */
- if (tx_flags & IGB_TX_FLAGS_IPV4)
- olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
- }
+ /* insert IPv4 checksum */
+ olinfo_status |= IGB_SET_FLAG(tx_flags,
+ IGB_TX_FLAGS_IPV4,
+ (E1000_TXD_POPTS_IXSM << 8));
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
}
@@ -4209,33 +4207,37 @@ static void igb_tx_map(struct igb_ring *tx_ring,
struct sk_buff *skb = first->skb;
struct igb_tx_buffer *tx_buffer;
union e1000_adv_tx_desc *tx_desc;
+ struct skb_frag_struct *frag;
dma_addr_t dma;
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
- unsigned int data_len = skb->data_len;
- unsigned int size = skb_headlen(skb);
- unsigned int paylen = skb->len - hdr_len;
- __le32 cmd_type;
+ unsigned int data_len, size;
u32 tx_flags = first->tx_flags;
+ u32 cmd_type = igb_tx_cmd_type(skb, tx_flags);
u16 i = tx_ring->next_to_use;
tx_desc = IGB_TX_DESC(tx_ring, i);
- igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen);
- cmd_type = igb_tx_cmd_type(tx_flags);
+ igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len);
+
+ size = skb_headlen(skb);
+ data_len = skb->data_len;
dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
- if (dma_mapping_error(tx_ring->dev, dma))
- goto dma_error;
- /* record length, and DMA address */
- dma_unmap_len_set(first, len, size);
- dma_unmap_addr_set(first, dma, dma);
- tx_desc->read.buffer_addr = cpu_to_le64(dma);
+ tx_buffer = first;
+
+ for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
+ if (dma_mapping_error(tx_ring->dev, dma))
+ goto dma_error;
+
+ /* record length, and DMA address */
+ dma_unmap_len_set(tx_buffer, len, size);
+ dma_unmap_addr_set(tx_buffer, dma, dma);
+
+ tx_desc->read.buffer_addr = cpu_to_le64(dma);
- for (;;) {
while (unlikely(size > IGB_MAX_DATA_PER_TXD)) {
tx_desc->read.cmd_type_len =
- cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD);
+ cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD);
i++;
tx_desc++;
@@ -4243,18 +4245,18 @@ static void igb_tx_map(struct igb_ring *tx_ring,
tx_desc = IGB_TX_DESC(tx_ring, 0);
i = 0;
}
+ tx_desc->read.olinfo_status = 0;
dma += IGB_MAX_DATA_PER_TXD;
size -= IGB_MAX_DATA_PER_TXD;
- tx_desc->read.olinfo_status = 0;
tx_desc->read.buffer_addr = cpu_to_le64(dma);
}
if (likely(!data_len))
break;
- tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
+ tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size);
i++;
tx_desc++;
@@ -4262,32 +4264,22 @@ static void igb_tx_map(struct igb_ring *tx_ring,
tx_desc = IGB_TX_DESC(tx_ring, 0);
i = 0;
}
+ tx_desc->read.olinfo_status = 0;
size = skb_frag_size(frag);
data_len -= size;
dma = skb_frag_dma_map(tx_ring->dev, frag, 0,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(tx_ring->dev, dma))
- goto dma_error;
+ size, DMA_TO_DEVICE);
tx_buffer = &tx_ring->tx_buffer_info[i];
- dma_unmap_len_set(tx_buffer, len, size);
- dma_unmap_addr_set(tx_buffer, dma, dma);
-
- tx_desc->read.olinfo_status = 0;
- tx_desc->read.buffer_addr = cpu_to_le64(dma);
-
- frag++;
}
- netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
-
/* write last descriptor with RS and EOP bits */
- cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
- if (unlikely(skb->no_fcs))
- cmd_type &= ~(cpu_to_le32(E1000_ADVTXD_DCMD_IFCS));
- tx_desc->read.cmd_type_len = cmd_type;
+ cmd_type |= size | IGB_TXD_DCMD;
+ tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+
+ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
/* set the timestamp */
first->time_stamp = jiffies;
@@ -4372,9 +4364,7 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
struct igb_ring *tx_ring)
{
-#ifdef CONFIG_IGB_PTP
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
-#endif /* CONFIG_IGB_PTP */
struct igb_tx_buffer *first;
int tso;
u32 tx_flags = 0;
@@ -4397,7 +4387,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
first->bytecount = skb->len;
first->gso_segs = 1;
-#ifdef CONFIG_IGB_PTP
if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
!(adapter->ptp_tx_skb))) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
@@ -4407,7 +4396,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
if (adapter->hw.mac.type == e1000_82576)
schedule_work(&adapter->ptp_tx_work);
}
-#endif /* CONFIG_IGB_PTP */
if (vlan_tx_tag_present(skb)) {
tx_flags |= IGB_TX_FLAGS_VLAN;
@@ -4467,10 +4455,11 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
* The minimum packet size with TCTL.PSP set is 17 so pad the skb
* in order to meet this minimum size requirement.
*/
- if (skb->len < 17) {
- if (skb_padto(skb, 17))
+ if (unlikely(skb->len < 17)) {
+ if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
+ skb_set_tail_pointer(skb, 17);
}
return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
@@ -4800,7 +4789,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_IGB_PTP
if (icr & E1000_ICR_TS) {
u32 tsicr = rd32(E1000_TSICR);
@@ -4811,7 +4799,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
schedule_work(&adapter->ptp_tx_work);
}
}
-#endif /* CONFIG_IGB_PTP */
wr32(E1000_EIMS, adapter->eims_other);
@@ -4851,45 +4838,63 @@ static irqreturn_t igb_msix_ring(int irq, void *data)
}
#ifdef CONFIG_IGB_DCA
+static void igb_update_tx_dca(struct igb_adapter *adapter,
+ struct igb_ring *tx_ring,
+ int cpu)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 txctrl = dca3_get_tag(tx_ring->dev, cpu);
+
+ if (hw->mac.type != e1000_82575)
+ txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT;
+
+ /*
+ * We can enable relaxed ordering for reads, but not writes when
+ * DCA is enabled. This is due to a known issue in some chipsets
+ * which will cause the DCA tag to be cleared.
+ */
+ txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN |
+ E1000_DCA_TXCTRL_DATA_RRO_EN |
+ E1000_DCA_TXCTRL_DESC_DCA_EN;
+
+ wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl);
+}
+
+static void igb_update_rx_dca(struct igb_adapter *adapter,
+ struct igb_ring *rx_ring,
+ int cpu)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu);
+
+ if (hw->mac.type != e1000_82575)
+ rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT;
+
+ /*
+ * We can enable relaxed ordering for reads, but not writes when
+ * DCA is enabled. This is due to a known issue in some chipsets
+ * which will cause the DCA tag to be cleared.
+ */
+ rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN |
+ E1000_DCA_RXCTRL_DESC_DCA_EN;
+
+ wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl);
+}
+
static void igb_update_dca(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
- struct e1000_hw *hw = &adapter->hw;
int cpu = get_cpu();
if (q_vector->cpu == cpu)
goto out_no_update;
- if (q_vector->tx.ring) {
- int q = q_vector->tx.ring->reg_idx;
- u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
- if (hw->mac.type == e1000_82575) {
- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
- } else {
- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
- E1000_DCA_TXCTRL_CPUID_SHIFT;
- }
- dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
- wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
- }
- if (q_vector->rx.ring) {
- int q = q_vector->rx.ring->reg_idx;
- u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
- if (hw->mac.type == e1000_82575) {
- dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
- dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
- } else {
- dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
- dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
- E1000_DCA_RXCTRL_CPUID_SHIFT;
- }
- dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
- dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
- dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
- wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
- }
+ if (q_vector->tx.ring)
+ igb_update_tx_dca(adapter, q_vector->tx.ring, cpu);
+
+ if (q_vector->rx.ring)
+ igb_update_rx_dca(adapter, q_vector->rx.ring, cpu);
+
q_vector->cpu = cpu;
out_no_update:
put_cpu();
@@ -5545,7 +5550,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_IGB_PTP
if (icr & E1000_ICR_TS) {
u32 tsicr = rd32(E1000_TSICR);
@@ -5556,7 +5560,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
schedule_work(&adapter->ptp_tx_work);
}
}
-#endif /* CONFIG_IGB_PTP */
napi_schedule(&q_vector->napi);
@@ -5599,7 +5602,6 @@ static irqreturn_t igb_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_IGB_PTP
if (icr & E1000_ICR_TS) {
u32 tsicr = rd32(E1000_TSICR);
@@ -5610,7 +5612,6 @@ static irqreturn_t igb_intr(int irq, void *data)
schedule_work(&adapter->ptp_tx_work);
}
}
-#endif /* CONFIG_IGB_PTP */
napi_schedule(&q_vector->napi);
@@ -5840,6 +5841,181 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
return !!budget;
}
+/**
+ * igb_reuse_rx_page - page flip buffer and store it back on the ring
+ * @rx_ring: rx descriptor ring to store buffers on
+ * @old_buff: donor buffer to have page reused
+ *
+ * Synchronizes page for reuse by the adapter
+ **/
+static void igb_reuse_rx_page(struct igb_ring *rx_ring,
+ struct igb_rx_buffer *old_buff)
+{
+ struct igb_rx_buffer *new_buff;
+ u16 nta = rx_ring->next_to_alloc;
+
+ new_buff = &rx_ring->rx_buffer_info[nta];
+
+ /* update, and store next to alloc */
+ nta++;
+ rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
+
+ /* transfer page from old buffer to new buffer */
+ memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer));
+
+ /* sync the buffer for use by the device */
+ dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma,
+ old_buff->page_offset,
+ IGB_RX_BUFSZ,
+ DMA_FROM_DEVICE);
+}
+
+/**
+ * igb_add_rx_frag - Add contents of Rx buffer to sk_buff
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: buffer containing page to add
+ * @rx_desc: descriptor containing length of buffer written by hardware
+ * @skb: sk_buff to place the data into
+ *
+ * This function will add the data contained in rx_buffer->page to the skb.
+ * This is done either through a direct copy if the data in the buffer is
+ * less than the skb header size, otherwise it will just attach the page as
+ * a frag to the skb.
+ *
+ * The function will then update the page offset if necessary and return
+ * true if the buffer can be reused by the adapter.
+ **/
+static bool igb_add_rx_frag(struct igb_ring *rx_ring,
+ struct igb_rx_buffer *rx_buffer,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct page *page = rx_buffer->page;
+ unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+
+ if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) {
+ unsigned char *va = page_address(page) + rx_buffer->page_offset;
+
+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+ igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
+ va += IGB_TS_HDR_LEN;
+ size -= IGB_TS_HDR_LEN;
+ }
+
+ memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
+
+ /* we can reuse buffer as-is, just make sure it is local */
+ if (likely(page_to_nid(page) == numa_node_id()))
+ return true;
+
+ /* this page cannot be reused so discard it */
+ put_page(page);
+ return false;
+ }
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+ rx_buffer->page_offset, size, IGB_RX_BUFSZ);
+
+ /* avoid re-using remote pages */
+ if (unlikely(page_to_nid(page) != numa_node_id()))
+ return false;
+
+#if (PAGE_SIZE < 8192)
+ /* if we are only owner of page we can reuse it */
+ if (unlikely(page_count(page) != 1))
+ return false;
+
+ /* flip page offset to other buffer */
+ rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+
+ /*
+ * since we are the only owner of the page and we need to
+ * increment it, just set the value to 2 in order to avoid
+ * an unnecessary locked operation
+ */
+ atomic_set(&page->_count, 2);
+#else
+ /* move offset up to the next cache line */
+ rx_buffer->page_offset += SKB_DATA_ALIGN(size);
+
+ if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
+ return false;
+
+ /* bump ref count on page before it is given to the stack */
+ get_page(page);
+#endif
+
+ return true;
+}
+
+static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct igb_rx_buffer *rx_buffer;
+ struct page *page;
+
+ rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+
+ /*
+ * This memory barrier is needed to keep us from reading
+ * any other fields out of the rx_desc until we know the
+ * RXD_STAT_DD bit is set
+ */
+ rmb();
+
+ page = rx_buffer->page;
+ prefetchw(page);
+
+ if (likely(!skb)) {
+ void *page_addr = page_address(page) +
+ rx_buffer->page_offset;
+
+ /* prefetch first cache line of first page */
+ prefetch(page_addr);
+#if L1_CACHE_BYTES < 128
+ prefetch(page_addr + L1_CACHE_BYTES);
+#endif
+
+ /* allocate a skb to store the frags */
+ skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+ IGB_RX_HDR_LEN);
+ if (unlikely(!skb)) {
+ rx_ring->rx_stats.alloc_failed++;
+ return NULL;
+ }
+
+ /*
+ * we will be copying header into skb->data in
+ * pskb_may_pull so it is in our interest to prefetch
+ * it now to avoid a possible cache miss
+ */
+ prefetchw(skb->data);
+ }
+
+ /* we are reusing so sync this buffer for CPU use */
+ dma_sync_single_range_for_cpu(rx_ring->dev,
+ rx_buffer->dma,
+ rx_buffer->page_offset,
+ IGB_RX_BUFSZ,
+ DMA_FROM_DEVICE);
+
+ /* pull page into skb */
+ if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) {
+ /* hand second half of page back to the ring */
+ igb_reuse_rx_page(rx_ring, rx_buffer);
+ } else {
+ /* we are not reusing the buffer so unmap it */
+ dma_unmap_page(rx_ring->dev, rx_buffer->dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ }
+
+ /* clear contents of rx_buffer */
+ rx_buffer->page = NULL;
+
+ return skb;
+}
+
static inline void igb_rx_checksum(struct igb_ring *ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -5889,224 +6065,389 @@ static inline void igb_rx_hash(struct igb_ring *ring,
skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}
-static void igb_rx_vlan(struct igb_ring *ring,
- union e1000_adv_rx_desc *rx_desc,
- struct sk_buff *skb)
+/**
+ * igb_is_non_eop - process handling of non-EOP buffers
+ * @rx_ring: Rx ring being processed
+ * @rx_desc: Rx descriptor for current buffer
+ * @skb: current socket buffer containing buffer in progress
+ *
+ * This function updates next to clean. If the buffer is an EOP buffer
+ * this function exits returning false, otherwise it will place the
+ * sk_buff in the next buffer to be chained and return true indicating
+ * that this is in fact a non-EOP buffer.
+ **/
+static bool igb_is_non_eop(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc)
{
- if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
- u16 vid;
- if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
- test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags))
- vid = be16_to_cpu(rx_desc->wb.upper.vlan);
- else
- vid = le16_to_cpu(rx_desc->wb.upper.vlan);
+ u32 ntc = rx_ring->next_to_clean + 1;
- __vlan_hwaccel_put_tag(skb, vid);
- }
+ /* fetch, update, and store next to clean */
+ ntc = (ntc < rx_ring->count) ? ntc : 0;
+ rx_ring->next_to_clean = ntc;
+
+ prefetch(IGB_RX_DESC(rx_ring, ntc));
+
+ if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)))
+ return false;
+
+ return true;
}
-static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc)
-{
- /* HW will not DMA in data larger than the given buffer, even if it
- * parses the (NFS, of course) header to be larger. In that case, it
- * fills the header buffer and spills the rest into the page.
+/**
+ * igb_get_headlen - determine size of header for LRO/GRO
+ * @data: pointer to the start of the headers
+ * @max_len: total length of section to find headers in
+ *
+ * This function is meant to determine the length of headers that will
+ * be recognized by hardware for LRO, and GRO offloads. The main
+ * motivation of doing this is to only perform one pull for IPv4 TCP
+ * packets so that we can do basic things like calculating the gso_size
+ * based on the average data per packet.
+ **/
+static unsigned int igb_get_headlen(unsigned char *data,
+ unsigned int max_len)
+{
+ union {
+ unsigned char *network;
+ /* l2 headers */
+ struct ethhdr *eth;
+ struct vlan_hdr *vlan;
+ /* l3 headers */
+ struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
+ } hdr;
+ __be16 protocol;
+ u8 nexthdr = 0; /* default to not TCP */
+ u8 hlen;
+
+ /* this should never happen, but better safe than sorry */
+ if (max_len < ETH_HLEN)
+ return max_len;
+
+ /* initialize network frame pointer */
+ hdr.network = data;
+
+ /* set first protocol and move network header forward */
+ protocol = hdr.eth->h_proto;
+ hdr.network += ETH_HLEN;
+
+ /* handle any vlan tag if present */
+ if (protocol == __constant_htons(ETH_P_8021Q)) {
+ if ((hdr.network - data) > (max_len - VLAN_HLEN))
+ return max_len;
+
+ protocol = hdr.vlan->h_vlan_encapsulated_proto;
+ hdr.network += VLAN_HLEN;
+ }
+
+ /* handle L3 protocols */
+ if (protocol == __constant_htons(ETH_P_IP)) {
+ if ((hdr.network - data) > (max_len - sizeof(struct iphdr)))
+ return max_len;
+
+ /* access ihl as a u8 to avoid unaligned access on ia64 */
+ hlen = (hdr.network[0] & 0x0F) << 2;
+
+ /* verify hlen meets minimum size requirements */
+ if (hlen < sizeof(struct iphdr))
+ return hdr.network - data;
+
+ /* record next protocol if header is present */
+ if (!hdr.ipv4->frag_off)
+ nexthdr = hdr.ipv4->protocol;
+ } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+ if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+ return max_len;
+
+ /* record next protocol */
+ nexthdr = hdr.ipv6->nexthdr;
+ hlen = sizeof(struct ipv6hdr);
+ } else {
+ return hdr.network - data;
+ }
+
+ /* relocate pointer to start of L4 header */
+ hdr.network += hlen;
+
+ /* finally sort out TCP */
+ if (nexthdr == IPPROTO_TCP) {
+ if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
+ return max_len;
+
+ /* access doff as a u8 to avoid unaligned access on ia64 */
+ hlen = (hdr.network[12] & 0xF0) >> 2;
+
+ /* verify hlen meets minimum size requirements */
+ if (hlen < sizeof(struct tcphdr))
+ return hdr.network - data;
+
+ hdr.network += hlen;
+ } else if (nexthdr == IPPROTO_UDP) {
+ if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+ return max_len;
+
+ hdr.network += sizeof(struct udphdr);
+ }
+
+ /*
+ * If everything has gone correctly hdr.network should be the
+ * data section of the packet and will be the end of the header.
+ * If not then it probably represents the end of the last recognized
+ * header.
*/
- u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
- E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
- if (hlen > IGB_RX_HDR_LEN)
- hlen = IGB_RX_HDR_LEN;
- return hlen;
+ if ((hdr.network - data) < max_len)
+ return hdr.network - data;
+ else
+ return max_len;
}
-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
+/**
+ * igb_pull_tail - igb specific version of skb_pull_tail
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being adjusted
+ *
+ * This function is an igb specific version of __pskb_pull_tail. The
+ * main difference between this version and the original function is that
+ * this function can make several assumptions about the state of things
+ * that allow for significant optimizations versus the standard function.
+ * As a result we can do things like drop a frag and maintain an accurate
+ * truesize for the skb.
+ */
+static void igb_pull_tail(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
- struct igb_ring *rx_ring = q_vector->rx.ring;
- union e1000_adv_rx_desc *rx_desc;
- const int current_node = numa_node_id();
- unsigned int total_bytes = 0, total_packets = 0;
- u16 cleaned_count = igb_desc_unused(rx_ring);
- u16 i = rx_ring->next_to_clean;
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+ unsigned char *va;
+ unsigned int pull_len;
- rx_desc = IGB_RX_DESC(rx_ring, i);
+ /*
+ * it is valid to use page_address instead of kmap since we are
+ * working with pages allocated out of the lomem pool per
+ * alloc_page(GFP_ATOMIC)
+ */
+ va = skb_frag_address(frag);
- while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
- struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
- struct sk_buff *skb = buffer_info->skb;
- union e1000_adv_rx_desc *next_rxd;
+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+ /* retrieve timestamp from buffer */
+ igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
- buffer_info->skb = NULL;
- prefetch(skb->data);
+ /* update pointers to remove timestamp header */
+ skb_frag_size_sub(frag, IGB_TS_HDR_LEN);
+ frag->page_offset += IGB_TS_HDR_LEN;
+ skb->data_len -= IGB_TS_HDR_LEN;
+ skb->len -= IGB_TS_HDR_LEN;
- i++;
- if (i == rx_ring->count)
- i = 0;
+ /* move va to start of packet data */
+ va += IGB_TS_HDR_LEN;
+ }
- next_rxd = IGB_RX_DESC(rx_ring, i);
- prefetch(next_rxd);
+ /*
+ * we need the header to contain the greater of either ETH_HLEN or
+ * 60 bytes if the skb->len is less than 60 for skb_pad.
+ */
+ pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN);
- /*
- * This memory barrier is needed to keep us from reading
- * any other fields out of the rx_desc until we know the
- * RXD_STAT_DD bit is set
- */
- rmb();
+ /* align pull length to size of long to optimize memcpy performance */
+ skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
- if (!skb_is_nonlinear(skb)) {
- __skb_put(skb, igb_get_hlen(rx_desc));
- dma_unmap_single(rx_ring->dev, buffer_info->dma,
- IGB_RX_HDR_LEN,
- DMA_FROM_DEVICE);
- buffer_info->dma = 0;
+ /* update all of the pointers */
+ skb_frag_size_sub(frag, pull_len);
+ frag->page_offset += pull_len;
+ skb->data_len -= pull_len;
+ skb->tail += pull_len;
+}
+
+/**
+ * igb_cleanup_headers - Correct corrupted or empty headers
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being fixed
+ *
+ * Address the case where we are pulling data in on pages only
+ * and as such no data is present in the skb header.
+ *
+ * In addition if skb is not at least 60 bytes we need to pad it so that
+ * it is large enough to qualify as a valid Ethernet frame.
+ *
+ * Returns true if an error was encountered and skb was freed.
+ **/
+static bool igb_cleanup_headers(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+
+ if (unlikely((igb_test_staterr(rx_desc,
+ E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
+ struct net_device *netdev = rx_ring->netdev;
+ if (!(netdev->features & NETIF_F_RXALL)) {
+ dev_kfree_skb_any(skb);
+ return true;
}
+ }
- if (rx_desc->wb.upper.length) {
- u16 length = le16_to_cpu(rx_desc->wb.upper.length);
+ /* place header in linear portion of buffer */
+ if (skb_is_nonlinear(skb))
+ igb_pull_tail(rx_ring, rx_desc, skb);
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
- buffer_info->page,
- buffer_info->page_offset,
- length);
+ /* if skb_pad returns an error the skb was freed */
+ if (unlikely(skb->len < 60)) {
+ int pad_len = 60 - skb->len;
- skb->len += length;
- skb->data_len += length;
- skb->truesize += PAGE_SIZE / 2;
+ if (skb_pad(skb, pad_len))
+ return true;
+ __skb_put(skb, pad_len);
+ }
- if ((page_count(buffer_info->page) != 1) ||
- (page_to_nid(buffer_info->page) != current_node))
- buffer_info->page = NULL;
- else
- get_page(buffer_info->page);
+ return false;
+}
- dma_unmap_page(rx_ring->dev, buffer_info->page_dma,
- PAGE_SIZE / 2, DMA_FROM_DEVICE);
- buffer_info->page_dma = 0;
- }
+/**
+ * igb_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, VLAN, timestamp, protocol, and
+ * other fields within the skb.
+ **/
+static void igb_process_skb_fields(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct net_device *dev = rx_ring->netdev;
- if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) {
- struct igb_rx_buffer *next_buffer;
- next_buffer = &rx_ring->rx_buffer_info[i];
- buffer_info->skb = next_buffer->skb;
- buffer_info->dma = next_buffer->dma;
- next_buffer->skb = skb;
- next_buffer->dma = 0;
- goto next_desc;
- }
+ igb_rx_hash(rx_ring, rx_desc, skb);
- if (unlikely((igb_test_staterr(rx_desc,
- E1000_RXDEXT_ERR_FRAME_ERR_MASK))
- && !(rx_ring->netdev->features & NETIF_F_RXALL))) {
- dev_kfree_skb_any(skb);
- goto next_desc;
- }
+ igb_rx_checksum(rx_ring, rx_desc, skb);
-#ifdef CONFIG_IGB_PTP
- igb_ptp_rx_hwtstamp(q_vector, rx_desc, skb);
-#endif /* CONFIG_IGB_PTP */
- igb_rx_hash(rx_ring, rx_desc, skb);
- igb_rx_checksum(rx_ring, rx_desc, skb);
- igb_rx_vlan(rx_ring, rx_desc, skb);
+ igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
- total_bytes += skb->len;
- total_packets++;
+ if ((dev->features & NETIF_F_HW_VLAN_RX) &&
+ igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
+ u16 vid;
+ if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
+ test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
+ vid = be16_to_cpu(rx_desc->wb.upper.vlan);
+ else
+ vid = le16_to_cpu(rx_desc->wb.upper.vlan);
- skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
- napi_gro_receive(&q_vector->napi, skb);
+ skb_record_rx_queue(skb, rx_ring->queue_index);
- budget--;
-next_desc:
- if (!budget)
- break;
+ skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
+static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
+{
+ struct igb_ring *rx_ring = q_vector->rx.ring;
+ struct sk_buff *skb = rx_ring->skb;
+ unsigned int total_bytes = 0, total_packets = 0;
+ u16 cleaned_count = igb_desc_unused(rx_ring);
+
+ do {
+ union e1000_adv_rx_desc *rx_desc;
- cleaned_count++;
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
igb_alloc_rx_buffers(rx_ring, cleaned_count);
cleaned_count = 0;
}
- /* use prefetched values */
- rx_desc = next_rxd;
- }
+ rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
- rx_ring->next_to_clean = i;
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.packets += total_packets;
- rx_ring->rx_stats.bytes += total_bytes;
- u64_stats_update_end(&rx_ring->rx_syncp);
- q_vector->rx.total_packets += total_packets;
- q_vector->rx.total_bytes += total_bytes;
+ if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
+ break;
- if (cleaned_count)
- igb_alloc_rx_buffers(rx_ring, cleaned_count);
+ /* retrieve a buffer from the ring */
+ skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
- return !!budget;
-}
+ /* exit if we failed to retrieve a buffer */
+ if (!skb)
+ break;
-static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring,
- struct igb_rx_buffer *bi)
-{
- struct sk_buff *skb = bi->skb;
- dma_addr_t dma = bi->dma;
+ cleaned_count++;
- if (dma)
- return true;
+ /* fetch next buffer in frame if non-eop */
+ if (igb_is_non_eop(rx_ring, rx_desc))
+ continue;
- if (likely(!skb)) {
- skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
- IGB_RX_HDR_LEN);
- bi->skb = skb;
- if (!skb) {
- rx_ring->rx_stats.alloc_failed++;
- return false;
+ /* verify the packet layout is correct */
+ if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
+ skb = NULL;
+ continue;
}
- /* initialize skb for ring */
- skb_record_rx_queue(skb, rx_ring->queue_index);
- }
+ /* probably a little skewed due to removing CRC */
+ total_bytes += skb->len;
- dma = dma_map_single(rx_ring->dev, skb->data,
- IGB_RX_HDR_LEN, DMA_FROM_DEVICE);
+ /* populate checksum, timestamp, VLAN, and protocol */
+ igb_process_skb_fields(rx_ring, rx_desc, skb);
- if (dma_mapping_error(rx_ring->dev, dma)) {
- rx_ring->rx_stats.alloc_failed++;
- return false;
- }
+ napi_gro_receive(&q_vector->napi, skb);
- bi->dma = dma;
- return true;
+ /* reset skb pointer */
+ skb = NULL;
+
+ /* update budget accounting */
+ total_packets++;
+ } while (likely(total_packets < budget));
+
+ /* place incomplete frames back on ring for completion */
+ rx_ring->skb = skb;
+
+ u64_stats_update_begin(&rx_ring->rx_syncp);
+ rx_ring->rx_stats.packets += total_packets;
+ rx_ring->rx_stats.bytes += total_bytes;
+ u64_stats_update_end(&rx_ring->rx_syncp);
+ q_vector->rx.total_packets += total_packets;
+ q_vector->rx.total_bytes += total_bytes;
+
+ if (cleaned_count)
+ igb_alloc_rx_buffers(rx_ring, cleaned_count);
+
+ return (total_packets < budget);
}
static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
struct igb_rx_buffer *bi)
{
struct page *page = bi->page;
- dma_addr_t page_dma = bi->page_dma;
- unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2);
+ dma_addr_t dma;
- if (page_dma)
+ /* since we are recycling buffers we should seldom need to alloc */
+ if (likely(page))
return true;
- if (!page) {
- page = __skb_alloc_page(GFP_ATOMIC, bi->skb);
- bi->page = page;
- if (unlikely(!page)) {
- rx_ring->rx_stats.alloc_failed++;
- return false;
- }
+ /* alloc new page for storage */
+ page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
+ if (unlikely(!page)) {
+ rx_ring->rx_stats.alloc_failed++;
+ return false;
}
- page_dma = dma_map_page(rx_ring->dev, page,
- page_offset, PAGE_SIZE / 2,
- DMA_FROM_DEVICE);
+ /* map page for use */
+ dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ /*
+ * if mapping failed free memory back to system since
+ * there isn't much point in holding memory we can't use
+ */
+ if (dma_mapping_error(rx_ring->dev, dma)) {
+ __free_page(page);
- if (dma_mapping_error(rx_ring->dev, page_dma)) {
rx_ring->rx_stats.alloc_failed++;
return false;
}
- bi->page_dma = page_dma;
- bi->page_offset = page_offset;
+ bi->dma = dma;
+ bi->page = page;
+ bi->page_offset = 0;
+
return true;
}
@@ -6120,22 +6461,23 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
struct igb_rx_buffer *bi;
u16 i = rx_ring->next_to_use;
+ /* nothing to do */
+ if (!cleaned_count)
+ return;
+
rx_desc = IGB_RX_DESC(rx_ring, i);
bi = &rx_ring->rx_buffer_info[i];
i -= rx_ring->count;
- while (cleaned_count--) {
- if (!igb_alloc_mapped_skb(rx_ring, bi))
- break;
-
- /* Refresh the desc even if buffer_addrs didn't change
- * because each write-back erases this info. */
- rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
-
+ do {
if (!igb_alloc_mapped_page(rx_ring, bi))
break;
- rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+ /*
+ * Refresh the desc even if buffer_addrs didn't change
+ * because each write-back erases this info.
+ */
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
rx_desc++;
bi++;
@@ -6148,17 +6490,25 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
/* clear the hdr_addr for the next_to_use descriptor */
rx_desc->read.hdr_addr = 0;
- }
+
+ cleaned_count--;
+ } while (cleaned_count);
i += rx_ring->count;
if (rx_ring->next_to_use != i) {
+ /* record the next descriptor to use */
rx_ring->next_to_use = i;
- /* Force memory writes to complete before letting h/w
+ /* update next to alloc since we have filled the ring */
+ rx_ring->next_to_alloc = i;
+
+ /*
+ * Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
- * such as IA-64). */
+ * such as IA-64).
+ */
wmb();
writel(i, rx_ring->tail);
}
@@ -6207,10 +6557,8 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG:
case SIOCSMIIREG:
return igb_mii_ioctl(netdev, ifr, cmd);
-#ifdef CONFIG_IGB_PTP
case SIOCSHWTSTAMP:
return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd);
-#endif /* CONFIG_IGB_PTP */
default:
return -EOPNOTSUPP;
}
@@ -6478,7 +6826,7 @@ static int igb_resume(struct device *dev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
- if (igb_init_interrupt_scheme(adapter)) {
+ if (igb_init_interrupt_scheme(adapter, true)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
@@ -6492,7 +6840,9 @@ static int igb_resume(struct device *dev)
wr32(E1000_WUS, ~0);
if (netdev->flags & IFF_UP) {
+ rtnl_lock();
err = __igb_open(netdev, true);
+ rtnl_unlock();
if (err)
return err;
}
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index ee21445157a3..ab3429729bde 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
adapter->ptp_tx_skb = NULL;
}
-void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
- union e1000_adv_rx_desc *rx_desc,
+/**
+ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
+ * @q_vector: Pointer to interrupt specific structure
+ * @va: Pointer to address containing Rx buffer
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the first buffer of an
+ * incoming frame. The value is stored in little endian format starting on
+ * byte 8.
+ */
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+ unsigned char *va,
+ struct sk_buff *skb)
+{
+ __le64 *regval = (__le64 *)va;
+
+ /*
+ * The timestamp is recorded in little endian format.
+ * DWORD: 0 1 2 3
+ * Field: Reserved Reserved SYSTIML SYSTIMH
+ */
+ igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
+ le64_to_cpu(regval[1]));
+}
+
+/**
+ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
+ * @q_vector: Pointer to interrupt specific structure
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the internal registers
+ * of the adapter and store it in the skb.
+ */
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
struct sk_buff *skb)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
u64 regval;
- if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
- E1000_RXDADV_STAT_TS))
- return;
-
/*
* If this bit is set, then the RX registers contain the time stamp. No
* other packet will be time stamped until we read these registers, so
@@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
* If nothing went wrong, then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps.
*/
- if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
- u32 *stamp = (u32 *)skb->data;
- regval = le32_to_cpu(*(stamp + 2));
- regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
- skb_pull(skb, IGB_TS_HDR_LEN);
- } else {
- if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
- return;
+ if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+ return;
- regval = rd32(E1000_RXSTMPL);
- regval |= (u64)rd32(E1000_RXSTMPH) << 32;
- }
+ regval = rd32(E1000_RXSTMPL);
+ regval |= (u64)rd32(E1000_RXSTMPH) << 32;
igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
}
@@ -532,18 +553,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
case HWTSTAMP_FILTER_NONE:
tsync_rx_ctl = 0;
break;
- case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
- case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
- case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
- case HWTSTAMP_FILTER_ALL:
- /*
- * register TSYNCRXCFG must be set, therefore it is not
- * possible to time stamp both Sync and Delay_Req messages
- * => fall back to time stamping all packets
- */
- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
- config.rx_filter = HWTSTAMP_FILTER_ALL;
- break;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
@@ -554,31 +563,33 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
is_l4 = true;
break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
- is_l2 = true;
- is_l4 = true;
- config.rx_filter = HWTSTAMP_FILTER_SOME;
- break;
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
- is_l2 = true;
- is_l4 = true;
- config.rx_filter = HWTSTAMP_FILTER_SOME;
- break;
- case HWTSTAMP_FILTER_PTP_V2_EVENT:
- case HWTSTAMP_FILTER_PTP_V2_SYNC:
- case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
is_l2 = true;
is_l4 = true;
break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_ALL:
+ /* 82576 cannot timestamp all packets, which it needs to do to
+ * support both V1 Sync and Delay_Req messages
+ */
+ if (hw->mac.type != e1000_82576) {
+ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ }
+ /* fall through */
default:
+ config.rx_filter = HWTSTAMP_FILTER_NONE;
return -ERANGE;
}
@@ -596,6 +607,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) {
tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ is_l2 = true;
+ is_l4 = true;
if ((hw->mac.type == e1000_i210) ||
(hw->mac.type == e1000_i211)) {
diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h
index 3e18045d8f89..d9fa999b1685 100644
--- a/drivers/net/ethernet/intel/igbvf/defines.h
+++ b/drivers/net/ethernet/intel/igbvf/defines.h
@@ -46,6 +46,7 @@
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
+#define E1000_RXDEXT_STATERR_LB 0x00040000
#define E1000_RXDEXT_STATERR_CE 0x01000000
#define E1000_RXDEXT_STATERR_SE 0x02000000
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index a895e2f7b34d..fdca7b672776 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -295,7 +295,7 @@ struct igbvf_info {
/* hardware capability, feature, and workaround flags */
#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
-
+#define IGBVF_FLAG_RX_LB_VLAN_BSWAP (1 << 1)
#define IGBVF_RX_DESC_ADV(R, i) \
(&((((R).desc))[i].rx_desc))
#define IGBVF_TX_DESC_ADV(R, i) \
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 0ac11f527a84..277f5dfe3d90 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -47,7 +47,7 @@
#include "igbvf.h"
-#define DRV_VERSION "2.0.1-k"
+#define DRV_VERSION "2.0.2-k"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
static const char igbvf_driver_string[] =
@@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
struct sk_buff *skb,
u32 status, u16 vlan)
{
+ u16 vid;
+
if (status & E1000_RXD_STAT_VP) {
- u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+ if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
+ (status & E1000_RXDEXT_STATERR_LB))
+ vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+ else
+ vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
if (test_bit(vid, adapter->active_vlans))
__vlan_hwaccel_put_tag(skb, vid);
}
- netif_receive_skb(skb);
+
+ napi_gro_receive(&adapter->rx_ring->napi, skb);
}
static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -184,6 +191,13 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
buffer_info->page_offset,
PAGE_SIZE / 2,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev,
+ buffer_info->page_dma)) {
+ __free_page(buffer_info->page);
+ buffer_info->page = NULL;
+ dev_err(&pdev->dev, "RX DMA map failed\n");
+ break;
+ }
}
if (!buffer_info->skb) {
@@ -197,6 +211,12 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
bufsz,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+ dev_kfree_skb(buffer_info->skb);
+ buffer_info->skb = NULL;
+ dev_err(&pdev->dev, "RX DMA map failed\n");
+ goto no_buffers;
+ }
}
/* Refresh the desc even if buffer_addrs didn't change because
* each write-back erases this info. */
@@ -1078,7 +1098,7 @@ out:
* igbvf_alloc_queues - Allocate memory for all rings
* @adapter: board private structure to initialize
**/
-static int __devinit igbvf_alloc_queues(struct igbvf_adapter *adapter)
+static int igbvf_alloc_queues(struct igbvf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -1530,7 +1550,7 @@ void igbvf_reinit_locked(struct igbvf_adapter *adapter)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter)
+static int igbvf_sw_init(struct igbvf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
s32 rc;
@@ -2598,8 +2618,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit igbvf_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct igbvf_adapter *adapter;
@@ -2754,6 +2773,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
/* reset the hardware with the new settings */
igbvf_reset(adapter);
+ /* set hardware-specific flags */
+ if (adapter->hw.mac.type == e1000_vfadapt_i350)
+ adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP;
+
strcpy(netdev->name, "eth%d");
err = register_netdev(netdev);
if (err)
@@ -2794,7 +2817,7 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit igbvf_remove(struct pci_dev *pdev)
+static void igbvf_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct igbvf_adapter *adapter = netdev_priv(netdev);
@@ -2851,7 +2874,7 @@ static struct pci_driver igbvf_driver = {
.name = igbvf_driver_name,
.id_table = igbvf_pci_tbl,
.probe = igbvf_probe,
- .remove = __devexit_p(igbvf_remove),
+ .remove = igbvf_remove,
#ifdef CONFIG_PM
/* Power Management Hooks */
.suspend = igbvf_suspend,
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index d99a2d51b948..ae96c10251be 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -73,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
static int ixgb_init_module(void);
static void ixgb_exit_module(void);
static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit ixgb_remove(struct pci_dev *pdev);
+static void ixgb_remove(struct pci_dev *pdev);
static int ixgb_sw_init(struct ixgb_adapter *adapter);
static int ixgb_open(struct net_device *netdev);
static int ixgb_close(struct net_device *netdev);
@@ -125,7 +125,7 @@ static struct pci_driver ixgb_driver = {
.name = ixgb_driver_name,
.id_table = ixgb_pci_tbl,
.probe = ixgb_probe,
- .remove = __devexit_p(ixgb_remove),
+ .remove = ixgb_remove,
.err_handler = &ixgb_err_handler
};
@@ -391,7 +391,7 @@ static const struct net_device_ops ixgb_netdev_ops = {
* and a hardware reset occur.
**/
-static int __devinit
+static int
ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
@@ -558,7 +558,7 @@ err_dma_mask:
* memory.
**/
-static void __devexit
+static void
ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -584,7 +584,7 @@ ixgb_remove(struct pci_dev *pdev)
* OS network device settings (MTU size).
**/
-static int __devinit
+static int
ixgb_sw_init(struct ixgb_adapter *adapter)
{
struct ixgb_hw *hw = &adapter->hw;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_param.c b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
index 07d83ab46e21..04a60640ddda 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_param.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
@@ -47,7 +47,7 @@
#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
#define IXGB_PARAM(X, desc) \
- static int __devinitdata X[IXGB_MAX_NIC+1] \
+ static int X[IXGB_MAX_NIC+1] \
= IXGB_PARAM_INIT; \
static unsigned int num_##X = 0; \
module_param_array_named(X, X, int, &num_##X, 0); \
@@ -199,7 +199,7 @@ struct ixgb_option {
} arg;
};
-static int __devinit
+static int
ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
{
if (*value == OPTION_UNSET) {
@@ -257,7 +257,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
* in a variable in the adapter structure.
**/
-void __devinit
+void
ixgb_check_options(struct ixgb_adapter *adapter)
{
int bd = adapter->bd_number;
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 89f40e51fc13..f3a632bf8d96 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -34,11 +34,10 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
- ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o
+ ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe_dcb_82599.o ixgbe_dcb_nl.o
-ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o
ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 30efc9f0f47a..8e786764c60e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -36,11 +36,9 @@
#include <linux/aer.h>
#include <linux/if_vlan.h>
-#ifdef CONFIG_IXGBE_PTP
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IXGBE_PTP */
#include "ixgbe_type.h"
#include "ixgbe_common.h"
@@ -135,6 +133,7 @@ struct vf_data_storage {
u16 tx_rate;
u16 vlan_count;
u8 spoofchk_enabled;
+ unsigned int vf_api;
};
struct vf_macvlans {
@@ -482,8 +481,9 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7)
#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8)
#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9)
-#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED (u32)(1 << 10)
+#define IXGBE_FLAG2_PTP_ENABLED (u32)(1 << 10)
#define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 11)
+#define IXGBE_FLAG2_BRIDGE_MODE_VEB (u32)(1 << 12)
/* Tx fast path data */
int num_tx_queues;
@@ -571,7 +571,6 @@ struct ixgbe_adapter {
u32 interrupt_event;
u32 led_reg;
-#ifdef CONFIG_IXGBE_PTP
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
unsigned long last_overflow_check;
@@ -580,8 +579,6 @@ struct ixgbe_adapter {
struct timecounter tc;
int rx_hwtstamp_filter;
u32 base_incval;
- u32 cycle_speed;
-#endif /* CONFIG_IXGBE_PTP */
/* SR-IOV */
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
@@ -600,6 +597,8 @@ struct ixgbe_adapter {
#ifdef CONFIG_DEBUG_FS
struct dentry *ixgbe_dbg_adapter;
#endif /*CONFIG_DEBUG_FS*/
+
+ u8 default_up;
};
struct ixgbe_fdir_filter {
@@ -691,6 +690,7 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
u16 soft_id);
extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
union ixgbe_atr_input *mask);
+extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
extern void ixgbe_set_rx_mode(struct net_device *netdev);
#ifdef CONFIG_IXGBE_DCB
extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
@@ -739,7 +739,6 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
return netdev_get_tx_queue(ring->netdev, ring->queue_index);
}
-#ifdef CONFIG_IXGBE_PTP
extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
@@ -751,7 +750,7 @@ extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
struct ifreq *ifr, int cmd);
extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
-#endif /* CONFIG_IXGBE_PTP */
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 1077cb2b38db..1073aea5da40 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
bool autoneg,
bool autoneg_wait_to_complete);
static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
{
@@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
- u32 reg_anlp1 = 0;
- u32 i = 0;
u16 list_offset, data_offset, data_value;
+ bool got_lock = false;
if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
ixgbe_init_mac_link_ops_82599(hw);
@@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
usleep_range(hw->eeprom.semaphore_delay * 1000,
hw->eeprom.semaphore_delay * 2000);
- /* Now restart DSP by setting Restart_AN and clearing LMS */
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
- IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
- IXGBE_AUTOC_AN_RESTART));
-
- /* Wait for AN to leave state 0 */
- for (i = 0; i < 10; i++) {
- usleep_range(4000, 8000);
- reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
- if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
- break;
+ /* Need SW/FW semaphore around AUTOC writes if LESM on,
+ * likewise reset_pipeline requires lock as it also writes
+ * AUTOC.
+ */
+ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (ret_val)
+ goto setup_sfp_out;
+
+ got_lock = true;
+ }
+
+ /* Restart DSP and set SFI mode */
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+ IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL));
+
+ ret_val = ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock) {
+ hw->mac.ops.release_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ got_lock = false;
}
- if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
- hw_dbg(hw, "sfp module setup not complete\n");
+
+ if (ret_val) {
+ hw_dbg(hw, " sfp module setup not complete\n");
ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
goto setup_sfp_out;
}
-
- /* Restart DSP by setting Restart_AN and return to SFI mode */
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
- IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
- IXGBE_AUTOC_AN_RESTART));
}
setup_sfp_out:
@@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
u32 links_reg;
u32 i;
s32 status = 0;
+ bool got_lock = false;
+
+ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ status = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (status)
+ goto out;
+
+ got_lock = true;
+ }
/* Restart link */
- autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- autoc_reg |= IXGBE_AUTOC_AN_RESTART;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+ ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
/* Only poll for autoneg to complete if specified to do so */
if (autoneg_wait_to_complete) {
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
IXGBE_AUTOC_LMS_KX4_KX_KR ||
(autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
/* Add delay to filter out noises during initial link setup */
msleep(50);
+out:
return status;
}
@@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
u32 links_reg;
u32 i;
ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+ bool got_lock = false;
/* Check to see if speed passed in is supported. */
status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
@@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
}
if (autoc != start_autoc) {
+ /* Need SW/FW semaphore around AUTOC writes if LESM is on,
+ * likewise reset_pipeline requires us to hold this lock as
+ * it also writes to AUTOC.
+ */
+ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ status = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (status != 0)
+ goto out;
+
+ got_lock = true;
+ }
+
/* Restart link */
- autoc |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+ ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
/* Only poll for autoneg to complete if specified to do so */
if (autoneg_wait_to_complete) {
@@ -994,9 +1031,28 @@ mac_reset_top:
hw->mac.orig_autoc2 = autoc2;
hw->mac.orig_link_settings_stored = true;
} else {
- if (autoc != hw->mac.orig_autoc)
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
- IXGBE_AUTOC_AN_RESTART));
+ if (autoc != hw->mac.orig_autoc) {
+ /* Need SW/FW semaphore around AUTOC writes if LESM is
+ * on, likewise reset_pipeline requires us to hold
+ * this lock as it also writes to AUTOC.
+ */
+ bool got_lock = false;
+ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ status = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (status)
+ goto reset_hw_out;
+
+ got_lock = true;
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+ ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ }
if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
(hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
@@ -1022,7 +1078,7 @@ mac_reset_top:
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
/* Add the SAN MAC address to the RAR only if it's a valid address */
- if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+ if (is_valid_ether_addr(hw->mac.san_addr)) {
hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
hw->mac.san_addr, 0, IXGBE_RAH_AV);
@@ -1983,7 +2039,7 @@ fw_version_out:
* Returns true if the LESM FW module is present and enabled. Otherwise
* returns false. Smart Speed must be disabled if LESM FW module is enabled.
**/
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
{
bool lesm_enabled = false;
u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
@@ -2080,6 +2136,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
return ret_val;
}
+/**
+ * ixgbe_reset_pipeline_82599 - perform pipeline reset
+ *
+ * @hw: pointer to hardware structure
+ *
+ * Reset pipeline by asserting Restart_AN together with LMS change to ensure
+ * full pipeline reset. Note - We must hold the SW/FW semaphore before writing
+ * to AUTOC, so this function assumes the semaphore is held.
+ **/
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+{
+ s32 i, autoc_reg, ret_val;
+ s32 anlp1_reg = 0;
+
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+
+ /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+
+ /* Wait for AN to leave state 0 */
+ for (i = 0; i < 10; i++) {
+ usleep_range(4000, 8000);
+ anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+ if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
+ break;
+ }
+
+ if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
+ hw_dbg(hw, "auto negotiation not completed\n");
+ ret_val = IXGBE_ERR_RESET_FAILED;
+ goto reset_pipeline_out;
+ }
+
+ ret_val = 0;
+
+reset_pipeline_out:
+ /* Write AUTOC register with original LMS field and Restart_AN */
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return ret_val;
+}
+
static struct ixgbe_mac_operations mac_ops_82599 = {
.init_hw = &ixgbe_init_hw_generic,
.reset_hw = &ixgbe_reset_hw_82599,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index dbf37e4a45fd..5e68afdd502a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -65,13 +65,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
* function check the device id to see if the associated phy supports
* autoneg flow control.
**/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
{
switch (hw->device_id) {
case IXGBE_DEV_ID_X540T:
case IXGBE_DEV_ID_X540T1:
- return 0;
case IXGBE_DEV_ID_82599_T3_LOM:
return 0;
default:
@@ -90,6 +89,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
s32 ret_val = 0;
u32 reg = 0, reg_bp = 0;
u16 reg_cu = 0;
+ bool got_lock = false;
/*
* Validate the requested mode. Strict IEEE mode does not allow
@@ -210,8 +210,29 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
*
*/
if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= IXGBE_AUTOC_AN_RESTART;
+ /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+ * LESM is on, likewise reset_pipeline requries the lock as
+ * it also writes AUTOC.
+ */
+ if ((hw->mac.type == ixgbe_mac_82599EB) &&
+ ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (ret_val)
+ goto out;
+
+ got_lock = true;
+ }
+
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+
+ if (hw->mac.type == ixgbe_mac_82599EB)
+ ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+
} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
(ixgbe_device_supports_autoneg_fc(hw) == 0)) {
hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
@@ -1762,30 +1783,6 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
}
/**
- * ixgbe_validate_mac_addr - Validate MAC address
- * @mac_addr: pointer to MAC address.
- *
- * Tests a MAC address to ensure it is a valid Individual Address
- **/
-s32 ixgbe_validate_mac_addr(u8 *mac_addr)
-{
- s32 status = 0;
-
- /* Make sure it is not a multicast address */
- if (IXGBE_IS_MULTICAST(mac_addr))
- status = IXGBE_ERR_INVALID_MAC_ADDR;
- /* Not a broadcast address */
- else if (IXGBE_IS_BROADCAST(mac_addr))
- status = IXGBE_ERR_INVALID_MAC_ADDR;
- /* Reject the zero address */
- else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
- mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
- status = IXGBE_ERR_INVALID_MAC_ADDR;
-
- return status;
-}
-
-/**
* ixgbe_set_rar_generic - Set Rx address register
* @hw: pointer to hardware structure
* @index: Receive address register to write
@@ -1889,8 +1886,7 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
* to the permanent address.
* Otherwise, use the permanent address from the eeprom.
*/
- if (ixgbe_validate_mac_addr(hw->mac.addr) ==
- IXGBE_ERR_INVALID_MAC_ADDR) {
+ if (!is_valid_ether_addr(hw->mac.addr)) {
/* Get the MAC address from the RAR0 for later reference */
hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
@@ -2617,6 +2613,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
bool link_up = false;
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ s32 ret_val = 0;
/*
* Link must be up to auto-blink the LEDs;
@@ -2625,10 +2622,28 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
hw->mac.ops.check_link(hw, &speed, &link_up, false);
if (!link_up) {
+ /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+ * LESM is on.
+ */
+ bool got_lock = false;
+
+ if ((hw->mac.type == ixgbe_mac_82599EB) &&
+ ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (ret_val)
+ goto out;
+
+ got_lock = true;
+ }
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
autoc_reg |= IXGBE_AUTOC_FLU;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
IXGBE_WRITE_FLUSH(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
usleep_range(10000, 20000);
}
@@ -2637,7 +2652,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
IXGBE_WRITE_FLUSH(hw);
- return 0;
+out:
+ return ret_val;
}
/**
@@ -2649,18 +2665,40 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
{
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ s32 ret_val = 0;
+ bool got_lock = false;
+
+ /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+ * LESM is on.
+ */
+ if ((hw->mac.type == ixgbe_mac_82599EB) &&
+ ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
+ if (ret_val)
+ goto out;
+
+ got_lock = true;
+ }
autoc_reg &= ~IXGBE_AUTOC_FLU;
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+ if (hw->mac.type == ixgbe_mac_82599EB)
+ ixgbe_reset_pipeline_82599(hw);
+
+ if (got_lock)
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
led_reg &= ~IXGBE_LED_MODE_MASK(index);
led_reg &= ~IXGBE_LED_BLINK(index);
led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
IXGBE_WRITE_FLUSH(hw);
- return 0;
+out:
+ return ret_val;
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index d813d1188c36..f7a0970a251c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -78,9 +78,9 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
-s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
@@ -107,6 +107,7 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
u32 headroom, int strategy);
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
#define IXGBE_EMC_INTERNAL_DATA 0x00
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
index 8d3a21889099..50aa546b8c7a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
@@ -37,20 +37,6 @@ static struct dentry *ixgbe_dbg_root;
static char ixgbe_dbg_reg_ops_buf[256] = "";
/**
- * ixgbe_dbg_reg_ops_open - prep the debugfs pokee data item when opened
- * @inode: inode that was opened
- * @filp: file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer where
- * we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_reg_ops_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
-/**
* ixgbe_dbg_reg_ops_read - read for reg_ops datum
* @filp: the opened file
* @buffer: where to write the data for the user to read
@@ -61,23 +47,27 @@ static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
struct ixgbe_adapter *adapter = filp->private_data;
- char buf[256];
- int bytes_not_copied;
+ char *buf;
int len;
/* don't allow partial reads */
if (*ppos != 0)
return 0;
- len = snprintf(buf, sizeof(buf), "%s: %s\n",
- adapter->netdev->name, ixgbe_dbg_reg_ops_buf);
- if (count < len)
+ buf = kasprintf(GFP_KERNEL, "%s: %s\n",
+ adapter->netdev->name,
+ ixgbe_dbg_reg_ops_buf);
+ if (!buf)
+ return -ENOMEM;
+
+ if (count < strlen(buf)) {
+ kfree(buf);
return -ENOSPC;
- bytes_not_copied = copy_to_user(buffer, buf, len);
- if (bytes_not_copied < 0)
- return bytes_not_copied;
+ }
+
+ len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
- *ppos = len;
+ kfree(buf);
return len;
}
@@ -93,7 +83,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
size_t count, loff_t *ppos)
{
struct ixgbe_adapter *adapter = filp->private_data;
- int bytes_not_copied;
+ int len;
/* don't allow partial writes */
if (*ppos != 0)
@@ -101,14 +91,15 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
if (count >= sizeof(ixgbe_dbg_reg_ops_buf))
return -ENOSPC;
- bytes_not_copied = copy_from_user(ixgbe_dbg_reg_ops_buf, buffer, count);
- if (bytes_not_copied < 0)
- return bytes_not_copied;
- else if (bytes_not_copied < count)
- count -= bytes_not_copied;
- else
- return -ENOSPC;
- ixgbe_dbg_reg_ops_buf[count] = '\0';
+ len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf,
+ sizeof(ixgbe_dbg_reg_ops_buf)-1,
+ ppos,
+ buffer,
+ count);
+ if (len < 0)
+ return len;
+
+ ixgbe_dbg_reg_ops_buf[len] = '\0';
if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) {
u32 reg, value;
@@ -142,7 +133,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
static const struct file_operations ixgbe_dbg_reg_ops_fops = {
.owner = THIS_MODULE,
- .open = ixgbe_dbg_reg_ops_open,
+ .open = simple_open,
.read = ixgbe_dbg_reg_ops_read,
.write = ixgbe_dbg_reg_ops_write,
};
@@ -150,20 +141,6 @@ static const struct file_operations ixgbe_dbg_reg_ops_fops = {
static char ixgbe_dbg_netdev_ops_buf[256] = "";
/**
- * ixgbe_dbg_netdev_ops_open - prep the debugfs netdev_ops data item
- * @inode: inode that was opened
- * @filp: file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer
- * where we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_netdev_ops_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
-/**
* ixgbe_dbg_netdev_ops_read - read for netdev_ops datum
* @filp: the opened file
* @buffer: where to write the data for the user to read
@@ -175,23 +152,27 @@ static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp,
size_t count, loff_t *ppos)
{
struct ixgbe_adapter *adapter = filp->private_data;
- char buf[256];
- int bytes_not_copied;
+ char *buf;
int len;
/* don't allow partial reads */
if (*ppos != 0)
return 0;
- len = snprintf(buf, sizeof(buf), "%s: %s\n",
- adapter->netdev->name, ixgbe_dbg_netdev_ops_buf);
- if (count < len)
+ buf = kasprintf(GFP_KERNEL, "%s: %s\n",
+ adapter->netdev->name,
+ ixgbe_dbg_netdev_ops_buf);
+ if (!buf)
+ return -ENOMEM;
+
+ if (count < strlen(buf)) {
+ kfree(buf);
return -ENOSPC;
- bytes_not_copied = copy_to_user(buffer, buf, len);
- if (bytes_not_copied < 0)
- return bytes_not_copied;
+ }
+
+ len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
- *ppos = len;
+ kfree(buf);
return len;
}
@@ -207,7 +188,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
size_t count, loff_t *ppos)
{
struct ixgbe_adapter *adapter = filp->private_data;
- int bytes_not_copied;
+ int len;
/* don't allow partial writes */
if (*ppos != 0)
@@ -215,15 +196,15 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
if (count >= sizeof(ixgbe_dbg_netdev_ops_buf))
return -ENOSPC;
- bytes_not_copied = copy_from_user(ixgbe_dbg_netdev_ops_buf,
- buffer, count);
- if (bytes_not_copied < 0)
- return bytes_not_copied;
- else if (bytes_not_copied < count)
- count -= bytes_not_copied;
- else
- return -ENOSPC;
- ixgbe_dbg_netdev_ops_buf[count] = '\0';
+ len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf,
+ sizeof(ixgbe_dbg_netdev_ops_buf)-1,
+ ppos,
+ buffer,
+ count);
+ if (len < 0)
+ return len;
+
+ ixgbe_dbg_netdev_ops_buf[len] = '\0';
if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev);
@@ -238,7 +219,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
.owner = THIS_MODULE,
- .open = ixgbe_dbg_netdev_ops_open,
+ .open = simple_open,
.read = ixgbe_dbg_netdev_ops_read,
.write = ixgbe_dbg_netdev_ops_write,
};
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 116f0e901bee..326858424345 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -383,6 +383,11 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
return -EINVAL;
+ /* some devices do not support autoneg of link flow control */
+ if ((pause->autoneg == AUTONEG_ENABLE) &&
+ (ixgbe_device_supports_autoneg_fc(hw) != 0))
+ return -EINVAL;
+
fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
@@ -887,24 +892,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
+ struct ixgbe_ring *temp_ring;
int i, err = 0;
u32 new_rx_count, new_tx_count;
- bool need_update = false;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
- new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD);
- new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD);
- new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
-
- new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD);
- new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD);
+ new_tx_count = clamp_t(u32, ring->tx_pending,
+ IXGBE_MIN_TXD, IXGBE_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE);
- if ((new_tx_count == adapter->tx_ring[0]->count) &&
- (new_rx_count == adapter->rx_ring[0]->count)) {
+ new_rx_count = clamp_t(u32, ring->rx_pending,
+ IXGBE_MIN_RXD, IXGBE_MAX_RXD);
+ new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+ if ((new_tx_count == adapter->tx_ring_count) &&
+ (new_rx_count == adapter->rx_ring_count)) {
/* nothing to do */
return 0;
}
@@ -922,81 +926,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
goto clear_reset;
}
- temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring));
- if (!temp_tx_ring) {
+ /* allocate temporary buffer to store rings in */
+ i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
+ temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
+
+ if (!temp_ring) {
err = -ENOMEM;
goto clear_reset;
}
+ ixgbe_down(adapter);
+
+ /*
+ * Setup new Tx resources and free the old Tx resources in that order.
+ * We can then assign the new resources to the rings via a memcpy.
+ * The advantage to this approach is that we are guaranteed to still
+ * have resources even in the case of an allocation failure.
+ */
if (new_tx_count != adapter->tx_ring_count) {
for (i = 0; i < adapter->num_tx_queues; i++) {
- memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
+ memcpy(&temp_ring[i], adapter->tx_ring[i],
sizeof(struct ixgbe_ring));
- temp_tx_ring[i].count = new_tx_count;
- err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
+
+ temp_ring[i].count = new_tx_count;
+ err = ixgbe_setup_tx_resources(&temp_ring[i]);
if (err) {
while (i) {
i--;
- ixgbe_free_tx_resources(&temp_tx_ring[i]);
+ ixgbe_free_tx_resources(&temp_ring[i]);
}
- goto clear_reset;
+ goto err_setup;
}
}
- need_update = true;
- }
- temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring));
- if (!temp_rx_ring) {
- err = -ENOMEM;
- goto err_setup;
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ ixgbe_free_tx_resources(adapter->tx_ring[i]);
+
+ memcpy(adapter->tx_ring[i], &temp_ring[i],
+ sizeof(struct ixgbe_ring));
+ }
+
+ adapter->tx_ring_count = new_tx_count;
}
+ /* Repeat the process for the Rx rings if needed */
if (new_rx_count != adapter->rx_ring_count) {
for (i = 0; i < adapter->num_rx_queues; i++) {
- memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
+ memcpy(&temp_ring[i], adapter->rx_ring[i],
sizeof(struct ixgbe_ring));
- temp_rx_ring[i].count = new_rx_count;
- err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
+
+ temp_ring[i].count = new_rx_count;
+ err = ixgbe_setup_rx_resources(&temp_ring[i]);
if (err) {
while (i) {
i--;
- ixgbe_free_rx_resources(&temp_rx_ring[i]);
+ ixgbe_free_rx_resources(&temp_ring[i]);
}
goto err_setup;
}
+
}
- need_update = true;
- }
- /* if rings need to be updated, here's the place to do it in one shot */
- if (need_update) {
- ixgbe_down(adapter);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ ixgbe_free_rx_resources(adapter->rx_ring[i]);
- /* tx */
- if (new_tx_count != adapter->tx_ring_count) {
- for (i = 0; i < adapter->num_tx_queues; i++) {
- ixgbe_free_tx_resources(adapter->tx_ring[i]);
- memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
- sizeof(struct ixgbe_ring));
- }
- adapter->tx_ring_count = new_tx_count;
+ memcpy(adapter->rx_ring[i], &temp_ring[i],
+ sizeof(struct ixgbe_ring));
}
- /* rx */
- if (new_rx_count != adapter->rx_ring_count) {
- for (i = 0; i < adapter->num_rx_queues; i++) {
- ixgbe_free_rx_resources(adapter->rx_ring[i]);
- memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
- sizeof(struct ixgbe_ring));
- }
- adapter->rx_ring_count = new_rx_count;
- }
- ixgbe_up(adapter);
+ adapter->rx_ring_count = new_rx_count;
}
- vfree(temp_rx_ring);
err_setup:
- vfree(temp_tx_ring);
+ ixgbe_up(adapter);
+ vfree(temp_ring);
clear_reset:
clear_bit(__IXGBE_RESETTING, &adapter->state);
return err;
@@ -2669,7 +2672,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
struct ixgbe_adapter *adapter = netdev_priv(dev);
switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IXGBE_PTP
case ixgbe_mac_X540:
case ixgbe_mac_82599EB:
info->so_timestamping =
@@ -2695,7 +2697,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
break;
-#endif /* CONFIG_IXGBE_PTP */
default:
return ethtool_op_get_ts_info(dev, info);
break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index ae73ef14fdf3..252850d9a3e0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -800,6 +800,10 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
return -EINVAL;
e_info(drv, "Enabling FCoE offload features.\n");
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ e_warn(probe, "Enabling FCoE on PF will disable legacy VFs\n");
+
if (netif_running(netdev))
netdev->netdev_ops->ndo_stop(netdev);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 17ecbcedd548..8c74f739011d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -802,10 +802,13 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
/* setup affinity mask and node */
if (cpu != -1)
cpumask_set_cpu(cpu, &q_vector->affinity_mask);
- else
- cpumask_copy(&q_vector->affinity_mask, cpu_online_mask);
q_vector->numa_node = node;
+#ifdef CONFIG_IXGBE_DCA
+ /* initialize CPU for DCA */
+ q_vector->cpu = -1;
+
+#endif
/* initialize NAPI */
netif_napi_add(adapter->netdev, &q_vector->napi,
ixgbe_poll, 64);
@@ -821,6 +824,21 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
/* initialize pointer to rings */
ring = q_vector->ring;
+ /* intialize ITR */
+ if (txr_count && !rxr_count) {
+ /* tx only vector */
+ if (adapter->tx_itr_setting == 1)
+ q_vector->itr = IXGBE_10K_ITR;
+ else
+ q_vector->itr = adapter->tx_itr_setting;
+ } else {
+ /* rx or rx/tx vector */
+ if (adapter->rx_itr_setting == 1)
+ q_vector->itr = IXGBE_20K_ITR;
+ else
+ q_vector->itr = adapter->rx_itr_setting;
+ }
+
while (txr_count) {
/* assign generic ring traits */
ring->dev = &adapter->pdev->dev;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index fa3d552e1f4a..20a5af6d87d0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -44,6 +44,7 @@
#include <linux/ethtool.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
#include <linux/prefetch.h>
#include <scsi/fc/fc_fcoe.h>
@@ -62,11 +63,7 @@ char ixgbe_default_device_descr[] =
static char ixgbe_default_device_descr[] =
"Intel(R) 10 Gigabit Network Connection";
#endif
-#define MAJ 3
-#define MIN 9
-#define BUILD 15
-#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
- __stringify(BUILD) "-k"
+#define DRV_VERSION "3.11.33-k"
const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
"Copyright (c) 1999-2012 Intel Corporation.";
@@ -335,11 +332,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
goto exit;
dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
- pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
+ pr_info(" %s %s %s %s\n",
+ "Queue [NTU] [NTC] [bi(ntc)->dma ]",
+ "leng", "ntw", "timestamp");
for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n];
tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
- pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n",
+ pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)dma_unmap_addr(tx_buffer, dma),
dma_unmap_len(tx_buffer, len),
@@ -355,13 +354,37 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
/* Transmit Descriptor Formats
*
- * Advanced Transmit Descriptor
+ * 82598 Advanced Transmit Descriptor
* +--------------------------------------------------------------+
* 0 | Buffer Address [63:0] |
* +--------------------------------------------------------------+
- * 8 | PAYLEN | PORTS | IDX | STA | DCMD |DTYP | RSV | DTALEN |
+ * 8 | PAYLEN | POPTS | IDX | STA | DCMD |DTYP | RSV | DTALEN |
* +--------------------------------------------------------------+
* 63 46 45 40 39 36 35 32 31 24 23 20 19 0
+ *
+ * 82598 Advanced Transmit Descriptor (Write-Back Format)
+ * +--------------------------------------------------------------+
+ * 0 | RSV [63:0] |
+ * +--------------------------------------------------------------+
+ * 8 | RSV | STA | NXTSEQ |
+ * +--------------------------------------------------------------+
+ * 63 36 35 32 31 0
+ *
+ * 82599+ Advanced Transmit Descriptor
+ * +--------------------------------------------------------------+
+ * 0 | Buffer Address [63:0] |
+ * +--------------------------------------------------------------+
+ * 8 |PAYLEN |POPTS|CC|IDX |STA |DCMD |DTYP |MAC |RSV |DTALEN |
+ * +--------------------------------------------------------------+
+ * 63 46 45 40 39 38 36 35 32 31 24 23 20 19 18 17 16 15 0
+ *
+ * 82599+ Advanced Transmit Descriptor (Write-Back Format)
+ * +--------------------------------------------------------------+
+ * 0 | RSV [63:0] |
+ * +--------------------------------------------------------------+
+ * 8 | RSV | STA | RSV |
+ * +--------------------------------------------------------------+
+ * 63 36 35 32 31 0
*/
for (n = 0; n < adapter->num_tx_queues; n++) {
@@ -369,40 +392,43 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
pr_info("------------------------------------\n");
pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index);
pr_info("------------------------------------\n");
- pr_info("T [desc] [address 63:0 ] "
- "[PlPOIdStDDt Ln] [bi->dma ] "
- "leng ntw timestamp bi->skb\n");
+ pr_info("%s%s %s %s %s %s\n",
+ "T [desc] [address 63:0 ] ",
+ "[PlPOIdStDDt Ln] [bi->dma ] ",
+ "leng", "ntw", "timestamp", "bi->skb");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
tx_desc = IXGBE_TX_DESC(tx_ring, i);
tx_buffer = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
- pr_info("T [0x%03X] %016llX %016llX %016llX"
- " %04X %p %016llX %p", i,
- le64_to_cpu(u0->a),
- le64_to_cpu(u0->b),
- (u64)dma_unmap_addr(tx_buffer, dma),
- dma_unmap_len(tx_buffer, len),
- tx_buffer->next_to_watch,
- (u64)tx_buffer->time_stamp,
- tx_buffer->skb);
- if (i == tx_ring->next_to_use &&
- i == tx_ring->next_to_clean)
- pr_cont(" NTC/U\n");
- else if (i == tx_ring->next_to_use)
- pr_cont(" NTU\n");
- else if (i == tx_ring->next_to_clean)
- pr_cont(" NTC\n");
- else
- pr_cont("\n");
-
- if (netif_msg_pktdata(adapter) &&
- tx_buffer->skb)
- print_hex_dump(KERN_INFO, "",
- DUMP_PREFIX_ADDRESS, 16, 1,
- tx_buffer->skb->data,
+ if (dma_unmap_len(tx_buffer, len) > 0) {
+ pr_info("T [0x%03X] %016llX %016llX %016llX %08X %p %016llX %p",
+ i,
+ le64_to_cpu(u0->a),
+ le64_to_cpu(u0->b),
+ (u64)dma_unmap_addr(tx_buffer, dma),
dma_unmap_len(tx_buffer, len),
- true);
+ tx_buffer->next_to_watch,
+ (u64)tx_buffer->time_stamp,
+ tx_buffer->skb);
+ if (i == tx_ring->next_to_use &&
+ i == tx_ring->next_to_clean)
+ pr_cont(" NTC/U\n");
+ else if (i == tx_ring->next_to_use)
+ pr_cont(" NTU\n");
+ else if (i == tx_ring->next_to_clean)
+ pr_cont(" NTC\n");
+ else
+ pr_cont("\n");
+
+ if (netif_msg_pktdata(adapter) &&
+ tx_buffer->skb)
+ print_hex_dump(KERN_INFO, "",
+ DUMP_PREFIX_ADDRESS, 16, 1,
+ tx_buffer->skb->data,
+ dma_unmap_len(tx_buffer, len),
+ true);
+ }
}
}
@@ -422,7 +448,9 @@ rx_ring_summary:
dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
- /* Advanced Receive Descriptor (Read) Format
+ /* Receive Descriptor Formats
+ *
+ * 82598 Advanced Receive Descriptor (Read) Format
* 63 1 0
* +-----------------------------------------------------+
* 0 | Packet Buffer Address [63:1] |A0/NSE|
@@ -431,27 +459,52 @@ rx_ring_summary:
* +-----------------------------------------------------+
*
*
- * Advanced Receive Descriptor (Write-Back) Format
+ * 82598 Advanced Receive Descriptor (Write-Back) Format
*
* 63 48 47 32 31 30 21 20 16 15 4 3 0
* +------------------------------------------------------+
- * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
- * | Checksum Ident | | | | Type | Type |
+ * 0 | RSS Hash / |SPH| HDR_LEN | RSV |Packet| RSS |
+ * | Packet | IP | | | | Type | Type |
+ * | Checksum | Ident | | | | | |
* +------------------------------------------------------+
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
* +------------------------------------------------------+
* 63 48 47 32 31 20 19 0
+ *
+ * 82599+ Advanced Receive Descriptor (Read) Format
+ * 63 1 0
+ * +-----------------------------------------------------+
+ * 0 | Packet Buffer Address [63:1] |A0/NSE|
+ * +----------------------------------------------+------+
+ * 8 | Header Buffer Address [63:1] | DD |
+ * +-----------------------------------------------------+
+ *
+ *
+ * 82599+ Advanced Receive Descriptor (Write-Back) Format
+ *
+ * 63 48 47 32 31 30 21 20 17 16 4 3 0
+ * +------------------------------------------------------+
+ * 0 |RSS / Frag Checksum|SPH| HDR_LEN |RSC- |Packet| RSS |
+ * |/ RTT / PCoE_PARAM | | | CNT | Type | Type |
+ * |/ Flow Dir Flt ID | | | | | |
+ * +------------------------------------------------------+
+ * 8 | VLAN Tag | Length |Extended Error| Xtnd Status/NEXTP |
+ * +------------------------------------------------------+
+ * 63 48 47 32 31 20 19 0
*/
+
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
pr_info("------------------------------------\n");
pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index);
pr_info("------------------------------------\n");
- pr_info("R [desc] [ PktBuf A0] "
- "[ HeadBuf DD] [bi->dma ] [bi->skb] "
+ pr_info("%s%s%s",
+ "R [desc] [ PktBuf A0] ",
+ "[ HeadBuf DD] [bi->dma ] [bi->skb ] ",
"<-- Adv Rx Read format\n");
- pr_info("RWB[desc] [PcsmIpSHl PtRs] "
- "[vl er S cks ln] ---------------- [bi->skb] "
+ pr_info("%s%s%s",
+ "RWB[desc] [PcsmIpSHl PtRs] ",
+ "[vl er S cks ln] ---------------- [bi->skb ] ",
"<-- Adv Rx Write-Back format\n");
for (i = 0; i < rx_ring->count; i++) {
@@ -646,6 +699,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_hw_stats *hwstats = &adapter->stats;
u32 xoff[8] = {0};
+ u8 tc;
int i;
bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
@@ -659,21 +713,26 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
/* update stats for each tc, only valid with PFC enabled */
for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
+ u32 pxoffrxc;
+
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+ pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
break;
default:
- xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+ pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
}
- hwstats->pxoffrxc[i] += xoff[i];
+ hwstats->pxoffrxc[i] += pxoffrxc;
+ /* Get the TC for given UP */
+ tc = netdev_get_prio_tc_map(adapter->netdev, i);
+ xoff[tc] += pxoffrxc;
}
/* disarm tx queues that have received xoff frames */
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
- u8 tc = tx_ring->dcb_tc;
+ tc = tx_ring->dcb_tc;
if (xoff[tc])
clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
}
@@ -791,10 +850,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;
-#ifdef CONFIG_IXGBE_PTP
if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP))
ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb);
-#endif
/* free the skb */
dev_kfree_skb_any(tx_buffer->skb);
@@ -967,7 +1024,6 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
* which will cause the DCA tag to be cleared.
*/
rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN |
- IXGBE_DCA_RXCTRL_DATA_DCA_EN |
IXGBE_DCA_RXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl);
@@ -1244,6 +1300,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
struct vlan_hdr *vlan;
/* l3 headers */
struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
} hdr;
__be16 protocol;
u8 nexthdr = 0; /* default to not TCP */
@@ -1281,20 +1338,30 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
if (hlen < sizeof(struct iphdr))
return hdr.network - data;
+ /* record next protocol if header is present */
+ if (!hdr.ipv4->frag_off)
+ nexthdr = hdr.ipv4->protocol;
+ } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+ if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+ return max_len;
+
/* record next protocol */
- nexthdr = hdr.ipv4->protocol;
- hdr.network += hlen;
+ nexthdr = hdr.ipv6->nexthdr;
+ hlen = sizeof(struct ipv6hdr);
#ifdef IXGBE_FCOE
} else if (protocol == __constant_htons(ETH_P_FCOE)) {
if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
return max_len;
- hdr.network += FCOE_HEADER_LEN;
+ hlen = FCOE_HEADER_LEN;
#endif
} else {
return hdr.network - data;
}
- /* finally sort out TCP */
+ /* relocate pointer to start of L4 header */
+ hdr.network += hlen;
+
+ /* finally sort out TCP/UDP */
if (nexthdr == IPPROTO_TCP) {
if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
return max_len;
@@ -1307,6 +1374,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
return hdr.network - data;
hdr.network += hlen;
+ } else if (nexthdr == IPPROTO_UDP) {
+ if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+ return max_len;
+
+ hdr.network += sizeof(struct udphdr);
}
/*
@@ -1369,9 +1441,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
ixgbe_rx_checksum(rx_ring, rx_desc, skb);
-#ifdef CONFIG_IXGBE_PTP
ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
-#endif
if ((dev->features & NETIF_F_HW_VLAN_RX) &&
ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
@@ -1781,7 +1851,7 @@ dma_sync:
**/
static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *rx_ring,
- int budget)
+ const int budget)
{
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
#ifdef IXGBE_FCOE
@@ -1832,7 +1902,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
- total_rx_packets++;
/* populate checksum, timestamp, VLAN, and protocol */
ixgbe_process_skb_fields(rx_ring, rx_desc, skb);
@@ -1865,8 +1934,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
ixgbe_rx_skb(q_vector, skb);
/* update budget accounting */
- budget--;
- } while (likely(budget));
+ total_rx_packets++;
+ } while (likely(total_rx_packets < budget));
u64_stats_update_begin(&rx_ring->syncp);
rx_ring->stats.packets += total_rx_packets;
@@ -1878,7 +1947,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
if (cleaned_count)
ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
- return !!budget;
+ return (total_rx_packets < budget);
}
/**
@@ -1914,20 +1983,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
ixgbe_for_each_ring(ring, q_vector->tx)
ixgbe_set_ivar(adapter, 1, ring->reg_idx, v_idx);
- if (q_vector->tx.ring && !q_vector->rx.ring) {
- /* tx only vector */
- if (adapter->tx_itr_setting == 1)
- q_vector->itr = IXGBE_10K_ITR;
- else
- q_vector->itr = adapter->tx_itr_setting;
- } else {
- /* rx or rx/tx vector */
- if (adapter->rx_itr_setting == 1)
- q_vector->itr = IXGBE_20K_ITR;
- else
- q_vector->itr = adapter->rx_itr_setting;
- }
-
ixgbe_write_eitr(q_vector);
}
@@ -2324,10 +2379,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
break;
}
-#ifdef CONFIG_IXGBE_PTP
if (adapter->hw.mac.type == ixgbe_mac_X540)
mask |= IXGBE_EIMS_TIMESYNC;
-#endif
if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
!(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
@@ -2393,10 +2446,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
ixgbe_check_fan_failure(adapter, eicr);
-#ifdef CONFIG_IXGBE_PTP
if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
/* re-enable the original interrupt state, no lsc, no queues */
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2588,10 +2639,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
}
ixgbe_check_fan_failure(adapter, eicr);
-#ifdef CONFIG_IXGBE_PTP
if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
/* would disable interrupts here but EIAM disabled it */
napi_schedule(&q_vector->napi);
@@ -2699,12 +2748,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
{
struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
- /* rx/tx vector */
- if (adapter->rx_itr_setting == 1)
- q_vector->itr = IXGBE_20K_ITR;
- else
- q_vector->itr = adapter->rx_itr_setting;
-
ixgbe_write_eitr(q_vector);
ixgbe_set_ivar(adapter, 0, 0, 0);
@@ -3132,14 +3175,6 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
ixgbe_configure_srrctl(adapter, ring);
ixgbe_configure_rscctl(adapter, ring);
- /* If operating in IOV mode set RLPML for X540 */
- if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
- hw->mac.type == ixgbe_mac_X540) {
- rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
- rxdctl |= ((ring->netdev->mtu + ETH_HLEN +
- ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN);
- }
-
if (hw->mac.type == ixgbe_mac_82598EB) {
/*
* enable cache line friendly hardware writes:
@@ -3211,7 +3246,8 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1);
- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+ if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0));
@@ -3234,8 +3270,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
- /* enable Tx loopback for VF/PF communication */
- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
/* Enable MAC Anti-Spoofing */
hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
@@ -3263,6 +3297,11 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
#endif /* IXGBE_FCOE */
+
+ /* adjust max frame to be at least the size of a standard frame */
+ if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
+ max_frame = (ETH_FRAME_LEN + ETH_FCS_LEN);
+
mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -3271,9 +3310,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
}
- /* MHADD will allow an extra 4 bytes past for vlan tagged frames */
- max_frame += VLAN_HLEN;
-
hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
/* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -4072,11 +4108,8 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
else
ixgbe_configure_msi_and_legacy(adapter);
- /* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */
- if (hw->mac.ops.enable_tx_laser &&
- ((hw->phy.multispeed_fiber) ||
- ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
- (hw->mac.type == ixgbe_mac_82599EB))))
+ /* enable the optics for 82599 SFP+ fiber */
+ if (hw->mac.ops.enable_tx_laser)
hw->mac.ops.enable_tx_laser(hw);
clear_bit(__IXGBE_DOWN, &adapter->state);
@@ -4192,6 +4225,9 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
/* update SAN MAC vmdq pool selection */
if (hw->mac.san_mac_rar_index)
hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0));
+
+ if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+ ixgbe_ptp_reset(adapter);
}
/**
@@ -4393,11 +4429,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
if (!pci_channel_offline(adapter->pdev))
ixgbe_reset(adapter);
- /* power down the optics for multispeed fiber and 82599 SFP+ fiber */
- if (hw->mac.ops.disable_tx_laser &&
- ((hw->phy.multispeed_fiber) ||
- ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
- (hw->mac.type == ixgbe_mac_82599EB))))
+ /* power down the optics for 82599 SFP+ fiber */
+ if (hw->mac.ops.disable_tx_laser)
hw->mac.ops.disable_tx_laser(hw);
ixgbe_clean_all_tx_rings(adapter);
@@ -4429,11 +4462,12 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
unsigned int rss;
+ u32 fwsm;
#ifdef CONFIG_IXGBE_DCB
int j;
struct tc_configuration *tc;
@@ -4457,7 +4491,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->max_q_vectors = MAX_Q_VECTORS_82598;
break;
case ixgbe_mac_X540:
- adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+ if (fwsm & IXGBE_FWSM_TS_ENABLED)
+ adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
case ixgbe_mac_82599EB:
adapter->max_q_vectors = MAX_Q_VECTORS_82599;
adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
@@ -4533,7 +4569,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
ixgbe_pbthresh_setup(adapter);
hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
hw->fc.send_xon = true;
- hw->fc.disable_fc_autoneg = false;
+ hw->fc.disable_fc_autoneg =
+ (ixgbe_device_supports_autoneg_fc(hw) == 0) ? false : true;
#ifdef CONFIG_PCI_IOV
/* assign number of SR-IOV VFs */
@@ -4828,14 +4865,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
/*
- * For 82599EB we cannot allow PF to change MTU greater than 1500
- * in SR-IOV mode as it may cause buffer overruns in guest VFs that
- * don't allocate and chain buffers correctly.
+ * For 82599EB we cannot allow legacy VFs to enable their receive
+ * paths when MTU greater than 1500 is configured. So display a
+ * warning that legacy VFs will be disabled.
*/
if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
(adapter->hw.mac.type == ixgbe_mac_82599EB) &&
(max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
- return -EINVAL;
+ e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -4901,6 +4938,8 @@ static int ixgbe_open(struct net_device *netdev)
if (err)
goto err_set_queues;
+ ixgbe_ptp_init(adapter);
+
ixgbe_up_complete(adapter);
return 0;
@@ -4932,6 +4971,8 @@ static int ixgbe_close(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ ixgbe_ptp_stop(adapter);
+
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
@@ -5022,14 +5063,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
if (wufc) {
ixgbe_set_rx_mode(netdev);
- /*
- * enable the optics for both mult-speed fiber and
- * 82599 SFP+ fiber as we can WoL.
- */
- if (hw->mac.ops.enable_tx_laser &&
- (hw->phy.multispeed_fiber ||
- (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber &&
- hw->mac.type == ixgbe_mac_82599EB)))
+ /* enable the optics for 82599 SFP+ fiber as we can WoL */
+ if (hw->mac.ops.enable_tx_laser)
hw->mac.ops.enable_tx_laser(hw);
/* turn on all-multi mode if wake on multicast is enabled */
@@ -5442,6 +5477,23 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
adapter->link_speed = link_speed;
}
+static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_DCB
+ struct net_device *netdev = adapter->netdev;
+ struct dcb_app app = {
+ .selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE,
+ .protocol = 0,
+ };
+ u8 up = 0;
+
+ if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
+ up = dcb_ieee_getapp_mask(netdev, &app);
+
+ adapter->default_up = (up > 1) ? (ffs(up) - 1) : 0;
+#endif
+}
+
/**
* ixgbe_watchdog_link_is_up - update netif_carrier status and
* print link up message
@@ -5482,9 +5534,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
break;
}
-#ifdef CONFIG_IXGBE_PTP
- ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+ if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+ ixgbe_ptp_start_cyclecounter(adapter);
e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
(link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
@@ -5501,6 +5552,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
netif_carrier_on(netdev);
ixgbe_check_vf_rate_limit(adapter);
+ /* update the default user priority for VFs */
+ ixgbe_update_default_up(adapter);
+
/* ping all the active vfs to let them know link has changed */
ixgbe_ping_all_vfs(adapter);
}
@@ -5526,9 +5580,8 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
-#ifdef CONFIG_IXGBE_PTP
- ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+ if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+ ixgbe_ptp_start_cyclecounter(adapter);
e_info(drv, "NIC Link is Down\n");
netif_carrier_off(netdev);
@@ -5833,9 +5886,7 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_watchdog_subtask(adapter);
ixgbe_fdir_reinit_subtask(adapter);
ixgbe_check_hang_subtask(adapter);
-#ifdef CONFIG_IXGBE_PTP
ixgbe_ptp_overflow_check(adapter);
-#endif
ixgbe_service_event_complete(adapter);
}
@@ -5988,10 +6039,8 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
-#ifdef CONFIG_IXGBE_PTP
if (tx_flags & IXGBE_TX_FLAGS_TSTAMP)
cmd_type |= cpu_to_le32(IXGBE_ADVTXD_MAC_TSTAMP);
-#endif
/* set segmentation enable bits for TSO/FSO */
#ifdef IXGBE_FCOE
@@ -6393,12 +6442,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
skb_tx_timestamp(skb);
-#ifdef CONFIG_IXGBE_PTP
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
}
-#endif
#ifdef CONFIG_PCI_IOV
/*
@@ -6485,6 +6532,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
+ skb_set_tail_pointer(skb, 17);
}
tx_ring = adapter->tx_ring[skb->queue_mapping];
@@ -6547,10 +6595,8 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
struct ixgbe_adapter *adapter = netdev_priv(netdev);
switch (cmd) {
-#ifdef CONFIG_IXGBE_PTP
case SIOCSHWTSTAMP:
return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd);
-#endif
default:
return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
}
@@ -6910,13 +6956,16 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return -EOPNOTSUPP;
- if (ndm->ndm_state & NUD_PERMANENT) {
+ /* Hardware does not support aging addresses so if a
+ * ndm_state is given only allow permanent addresses
+ */
+ if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
pr_info("%s: FDB only supports static addresses\n",
ixgbe_driver_name);
return -EINVAL;
}
- if (is_unicast_ether_addr(addr)) {
+ if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
u32 rar_uc_entries = IXGBE_MAX_PF_MACVLANS;
if (netdev_uc_count(dev) < rar_uc_entries)
@@ -6974,6 +7023,61 @@ static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
return idx;
}
+static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
+ struct nlmsghdr *nlh)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ struct nlattr *attr, *br_spec;
+ int rem;
+
+ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+ return -EOPNOTSUPP;
+
+ br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+
+ nla_for_each_nested(attr, br_spec, rem) {
+ __u16 mode;
+ u32 reg = 0;
+
+ if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ continue;
+
+ mode = nla_get_u16(attr);
+ if (mode == BRIDGE_MODE_VEPA) {
+ reg = 0;
+ adapter->flags2 &= ~IXGBE_FLAG2_BRIDGE_MODE_VEB;
+ } else if (mode == BRIDGE_MODE_VEB) {
+ reg = IXGBE_PFDTXGSWC_VT_LBEN;
+ adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+ } else
+ return -EINVAL;
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg);
+
+ e_info(drv, "enabling bridge mode: %s\n",
+ mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+ }
+
+ return 0;
+}
+
+static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ u16 mode;
+
+ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+ return 0;
+
+ if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+ mode = BRIDGE_MODE_VEB;
+ else
+ mode = BRIDGE_MODE_VEPA;
+
+ return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -7013,6 +7117,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_fdb_add = ixgbe_ndo_fdb_add,
.ndo_fdb_del = ixgbe_ndo_fdb_del,
.ndo_fdb_dump = ixgbe_ndo_fdb_dump,
+ .ndo_bridge_setlink = ixgbe_ndo_bridge_setlink,
+ .ndo_bridge_getlink = ixgbe_ndo_bridge_getlink,
};
/**
@@ -7042,6 +7148,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
break;
case IXGBE_SUBDEV_ID_82599_SFP:
case IXGBE_SUBDEV_ID_82599_RNDC:
+ case IXGBE_SUBDEV_ID_82599_ECNA_DP:
is_wol_supported = 1;
break;
}
@@ -7079,8 +7186,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit ixgbe_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct ixgbe_adapter *adapter = NULL;
@@ -7340,7 +7446,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len);
memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len);
- if (ixgbe_validate_mac_addr(netdev->perm_addr)) {
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
e_dev_err("invalid MAC address\n");
err = -EIO;
goto err_sw_init;
@@ -7364,10 +7470,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-#ifdef CONFIG_IXGBE_PTP
- ixgbe_ptp_init(adapter);
-#endif /* CONFIG_IXGBE_PTP*/
-
/* save off EEPROM version number */
hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
@@ -7420,11 +7522,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (err)
goto err_register;
- /* power down the optics for multispeed fiber and 82599 SFP+ fiber */
- if (hw->mac.ops.disable_tx_laser &&
- ((hw->phy.multispeed_fiber) ||
- ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
- (hw->mac.type == ixgbe_mac_82599EB))))
+ /* power down the optics for 82599 SFP+ fiber */
+ if (hw->mac.ops.disable_tx_laser)
hw->mac.ops.disable_tx_laser(hw);
/* carrier off reporting is important to ethtool even BEFORE open */
@@ -7493,7 +7592,7 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit ixgbe_remove(struct pci_dev *pdev)
+static void ixgbe_remove(struct pci_dev *pdev)
{
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
@@ -7505,9 +7604,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_DOWN, &adapter->state);
cancel_work_sync(&adapter->service_task);
-#ifdef CONFIG_IXGBE_PTP
- ixgbe_ptp_stop(adapter);
-#endif
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
@@ -7736,7 +7832,7 @@ static struct pci_driver ixgbe_driver = {
.name = ixgbe_driver_name,
.id_table = ixgbe_pci_tbl,
.probe = ixgbe_probe,
- .remove = __devexit_p(ixgbe_remove),
+ .remove = ixgbe_remove,
#ifdef CONFIG_PM
.suspend = ixgbe_suspend,
.resume = ixgbe_resume,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index 310bdd961075..42dd65e6ac97 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -62,12 +62,39 @@
/* bits 23:16 are used for exra info for certain messages */
#define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT)
+/* definitions to support mailbox API version negotiation */
+
+/*
+ * Each element denotes a version of the API; existing numbers may not
+ * change; any additions must go at the end
+ */
+enum ixgbe_pfvf_api_rev {
+ ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
+ ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
+ ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
+ /* This value should always be last */
+ ixgbe_mbox_api_unknown, /* indicates that API version is not known */
+};
+
+/* mailbox API, legacy requests */
#define IXGBE_VF_RESET 0x01 /* VF requests reset */
#define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
#define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
#define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
-#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
-#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */
+
+/* mailbox API, version 1.0 VF requests */
+#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
+#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */
+#define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
+
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index d9291316ee9f..1a751c9d09c4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -387,6 +387,15 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
struct ixgbe_hw *hw = &adapter->hw;
struct ptp_clock_event event;
+ event.type = PTP_CLOCK_PPS;
+
+ /* this check is necessary in case the interrupt was enabled via some
+ * alternative means (ex. debug_fs). Better to check here than
+ * everywhere that calls this function.
+ */
+ if (!adapter->ptp_clock)
+ return;
+
switch (hw->mac.type) {
case ixgbe_mac_X540:
ptp_clock_event(adapter->ptp_clock, &event);
@@ -411,7 +420,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
struct timespec ts;
- if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
+ if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
(elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
adapter->last_overflow_check = jiffies;
@@ -554,12 +563,14 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
adapter = q_vector->adapter;
hw = &adapter->hw;
+ if (likely(!ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+ return;
+
tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
/* Check if we have a valid timestamp and make sure the skb should
* have been timestamped */
- if (likely(!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID) ||
- !ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+ if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID))
return;
/*
@@ -622,8 +633,7 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
struct hwtstamp_config config;
u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
- u32 tsync_rx_mtrl = 0;
- bool is_l4 = false;
+ u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
bool is_l2 = false;
u32 regval;
@@ -646,16 +656,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
tsync_rx_ctl = 0;
+ tsync_rx_mtrl = 0;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
- is_l4 = true;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
- is_l4 = true;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -668,7 +677,6 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
is_l2 = true;
- is_l4 = true;
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
@@ -693,42 +701,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
/* Store filter value for later use */
adapter->rx_hwtstamp_filter = config.rx_filter;
- /* define ethertype filter for timestamped packets */
+ /* define ethertype filter for timestamping L2 packets */
if (is_l2)
- IXGBE_WRITE_REG(hw, IXGBE_ETQF(3),
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588),
(IXGBE_ETQF_FILTER_EN | /* enable filter */
IXGBE_ETQF_1588 | /* enable timestamping */
ETH_P_1588)); /* 1588 eth protocol type */
else
- IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0);
-
-#define PTP_PORT 319
- /* L4 Queue Filter[3]: filter by destination port and protocol */
- if (is_l4) {
- u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */
- | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */
- | IXGBE_FTQF_QUEUE_ENABLE);
-
- ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */
- & IXGBE_FTQF_DEST_PORT_MASK /* dest check */
- & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */
- << IXGBE_FTQF_5TUPLE_MASK_SHIFT);
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0);
- IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3),
- (3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 |
- IXGBE_IMIR_SIZE_BP_82599));
-
- /* enable port check */
- IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3),
- (htons(PTP_PORT) |
- htons(PTP_PORT) << 16));
-
- IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf);
-
- tsync_rx_mtrl |= PTP_PORT << 16;
- } else {
- IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0);
- }
/* enable/disable TX */
regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
@@ -759,58 +740,20 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
* ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
* @adapter: pointer to the adapter structure
*
- * this function initializes the timecounter and cyclecounter
- * structures for use in generated a ns counter from the arbitrary
- * fixed point cycles registers in the hardware.
- *
- * A change in link speed impacts the frequency of the DMA clock on
- * the device, which is used to generate the cycle counter
- * registers. Therefor this function is called whenever the link speed
- * changes.
- *
- * This function also turns on the SDP pin for clock out feature (X540
- * only), because this is where the shift is first calculated.
+ * This function should be called to set the proper values for the TIMINCA
+ * register and tell the cyclecounter structure what the tick rate of SYSTIME
+ * is. It does not directly modify SYSTIME registers or the timecounter
+ * structure. It should be called whenever a new TIMINCA value is necessary,
+ * such as during initialization or when the link speed changes.
*/
void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 incval = 0;
- u32 timinca = 0;
u32 shift = 0;
- u32 cycle_speed;
unsigned long flags;
/**
- * Determine what speed we need to set the cyclecounter
- * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
- * unknown speeds as 10Gb. (Hence why we can't just copy the
- * link_speed.
- */
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_100_FULL:
- case IXGBE_LINK_SPEED_1GB_FULL:
- case IXGBE_LINK_SPEED_10GB_FULL:
- cycle_speed = adapter->link_speed;
- break;
- default:
- /* cycle speed should be 10Gb when there is no link */
- cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
- break;
- }
-
- /*
- * grab the current TIMINCA value from the register so that it can be
- * double checked. If the register value has been cleared, it must be
- * reset to the correct value for generating a cyclecounter. If
- * TIMINCA is zero, the SYSTIME registers do not increment at all.
- */
- timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA);
-
- /* Bail if the cycle speed didn't change and TIMINCA is non-zero */
- if (adapter->cycle_speed == cycle_speed && timinca)
- return;
-
- /**
* Scale the NIC cycle counter by a large factor so that
* relatively small corrections to the frequency can be added
* or subtracted. The drawbacks of a large factor include
@@ -819,8 +762,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
* to nanoseconds using only a multiplier and a right-shift,
* and (c) the value must fit within the timinca register space
* => math based on internal DMA clock rate and available bits
+ *
+ * Note that when there is no link, internal DMA clock is same as when
+ * link speed is 10Gb. Set the registers correctly even when link is
+ * down to preserve the clock setting
*/
- switch (cycle_speed) {
+ switch (adapter->link_speed) {
case IXGBE_LINK_SPEED_100_FULL:
incval = IXGBE_INCVAL_100;
shift = IXGBE_INCVAL_SHIFT_100;
@@ -830,6 +777,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
shift = IXGBE_INCVAL_SHIFT_1GB;
break;
case IXGBE_LINK_SPEED_10GB_FULL:
+ default:
incval = IXGBE_INCVAL_10GB;
shift = IXGBE_INCVAL_SHIFT_10GB;
break;
@@ -857,18 +805,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
return;
}
- /* reset the system time registers */
- IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
- IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
- IXGBE_WRITE_FLUSH(hw);
-
- /* store the new cycle speed */
- adapter->cycle_speed = cycle_speed;
-
+ /* update the base incval used to calculate frequency adjustment */
ACCESS_ONCE(adapter->base_incval) = incval;
smp_mb();
- /* grab the ptp lock */
+ /* need lock to prevent incorrect read while modifying cyclecounter */
spin_lock_irqsave(&adapter->tmreg_lock, flags);
memset(&adapter->cc, 0, sizeof(adapter->cc));
@@ -877,6 +818,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
adapter->cc.shift = shift;
adapter->cc.mult = 1;
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+}
+
+/**
+ * ixgbe_ptp_reset
+ * @adapter: the ixgbe private board structure
+ *
+ * When the MAC resets, all timesync features are reset. This function should be
+ * called to re-enable the PTP clock structure. It will re-init the timecounter
+ * structure based on the kernel time as well as setup the cycle counter data.
+ */
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ /* set SYSTIME registers to 0 just in case */
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
+ IXGBE_WRITE_FLUSH(hw);
+
+ ixgbe_ptp_start_cyclecounter(adapter);
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
/* reset the ns time counter */
timecounter_init(&adapter->tc, &adapter->cc,
ktime_to_ns(ktime_get_real()));
@@ -904,7 +870,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
switch (adapter->hw.mac.type) {
case ixgbe_mac_X540:
- snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+ snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
adapter->ptp_caps.owner = THIS_MODULE;
adapter->ptp_caps.max_adj = 250000000;
adapter->ptp_caps.n_alarm = 0;
@@ -918,7 +884,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
adapter->ptp_caps.enable = ixgbe_ptp_enable;
break;
case ixgbe_mac_82599EB:
- snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+ snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
adapter->ptp_caps.owner = THIS_MODULE;
adapter->ptp_caps.max_adj = 250000000;
adapter->ptp_caps.n_alarm = 0;
@@ -942,11 +908,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
spin_lock_init(&adapter->tmreg_lock);
- ixgbe_ptp_start_cyclecounter(adapter);
-
- /* (Re)start the overflow check */
- adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
-
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
&adapter->pdev->dev);
if (IS_ERR(adapter->ptp_clock)) {
@@ -955,6 +916,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
} else
e_dev_info("registered PHC device on %s\n", netdev->name);
+ ixgbe_ptp_reset(adapter);
+
+ /* set the flag that PTP has been enabled */
+ adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
+
return;
}
@@ -967,7 +933,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
{
/* stop the overflow check task */
- adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
+ adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
IXGBE_FLAG2_PTP_PPS_ENABLED);
ixgbe_ptp_setup_sdp(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index dce48bf64d96..85cddac673ef 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -117,6 +117,10 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
}
}
+ /* Initialize default switching mode VEB */
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+ adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+
/* If call to enable VFs succeeded then allocate memory
* for per VF control structures.
*/
@@ -150,16 +154,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
IXGBE_FLAG2_RSC_ENABLED);
-#ifdef IXGBE_FCOE
- /*
- * When SR-IOV is enabled 82599 cannot support jumbo frames
- * so we must disable FCoE because we cannot support FCoE MTU.
- */
- if (adapter->hw.mac.type == ixgbe_mac_82599EB)
- adapter->flags &= ~(IXGBE_FLAG_FCOE_ENABLED |
- IXGBE_FLAG_FCOE_CAPABLE);
-#endif
-
/* enable spoof checking for all VFs */
for (i = 0; i < adapter->num_vfs; i++)
adapter->vfinfo[i].spoofchk_enabled = true;
@@ -265,8 +259,11 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
}
static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
- int entries, u16 *hash_list, u32 vf)
+ u32 *msgbuf, u32 vf)
{
+ int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
+ >> IXGBE_VT_MSGINFO_SHIFT;
+ u16 *hash_list = (u16 *)&msgbuf[1];
struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
struct ixgbe_hw *hw = &adapter->hw;
int i;
@@ -353,31 +350,89 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
}
-static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
- int new_mtu = msgbuf[1];
+ int max_frame = msgbuf[1];
u32 max_frs;
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- /* Only X540 supports jumbo frames in IOV mode */
- if (adapter->hw.mac.type != ixgbe_mac_X540)
- return;
+ /*
+ * For 82599EB we have to keep all PFs and VFs operating with
+ * the same max_frame value in order to avoid sending an oversize
+ * frame to a VF. In order to guarantee this is handled correctly
+ * for all cases we have several special exceptions to take into
+ * account before we can enable the VF for receive
+ */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ struct net_device *dev = adapter->netdev;
+ int pf_max_frame = dev->mtu + ETH_HLEN;
+ u32 reg_offset, vf_shift, vfre;
+ s32 err = 0;
+
+#ifdef CONFIG_FCOE
+ if (dev->features & NETIF_F_FCOE_MTU)
+ pf_max_frame = max_t(int, pf_max_frame,
+ IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+ switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_11:
+ /*
+ * Version 1.1 supports jumbo frames on VFs if PF has
+ * jumbo frames enabled which means legacy VFs are
+ * disabled
+ */
+ if (pf_max_frame > ETH_FRAME_LEN)
+ break;
+ default:
+ /*
+ * If the PF or VF are running w/ jumbo frames enabled
+ * we need to shut down the VF Rx path as we cannot
+ * support jumbo frames on legacy VFs
+ */
+ if ((pf_max_frame > ETH_FRAME_LEN) ||
+ (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+ err = -EINVAL;
+ break;
+ }
+
+ /* determine VF receive enable location */
+ vf_shift = vf % 32;
+ reg_offset = vf / 32;
+
+ /* enable or disable receive depending on error */
+ vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
+ if (err)
+ vfre &= ~(1 << vf_shift);
+ else
+ vfre |= 1 << vf_shift;
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre);
+
+ if (err) {
+ e_err(drv, "VF max_frame %d out of range\n", max_frame);
+ return err;
+ }
+ }
/* MTU < 68 is an error and causes problems on some kernels */
- if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
- e_err(drv, "VF mtu %d out of range\n", new_mtu);
- return;
+ if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+ e_err(drv, "VF max_frame %d out of range\n", max_frame);
+ return -EINVAL;
}
- max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
- IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
- if (max_frs < new_mtu) {
- max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+ /* pull current max frame size from hardware */
+ max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
+ max_frs &= IXGBE_MHADD_MFS_MASK;
+ max_frs >>= IXGBE_MHADD_MFS_SHIFT;
+
+ if (max_frs < max_frame) {
+ max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT;
IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
}
- e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+ e_info(hw, "VF requests change max MTU to %d\n", max_frame);
+
+ return 0;
}
static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
@@ -392,35 +447,47 @@ static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
}
-static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
+static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter,
+ u16 vid, u16 qos, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
+ u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) | IXGBE_VMVIR_VLANA_DEFAULT;
- if (vid)
- IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf),
- (vid | IXGBE_VMVIR_VLANA_DEFAULT));
- else
- IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
}
+static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+}
static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
+ struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+ u8 num_tcs = netdev_get_num_tc(adapter->netdev);
+
+ /* add PF assigned VLAN or VLAN 0 */
+ ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
/* reset offloads to defaults */
- if (adapter->vfinfo[vf].pf_vlan) {
- ixgbe_set_vf_vlan(adapter, true,
- adapter->vfinfo[vf].pf_vlan, vf);
- ixgbe_set_vmvir(adapter,
- (adapter->vfinfo[vf].pf_vlan |
- (adapter->vfinfo[vf].pf_qos <<
- VLAN_PRIO_SHIFT)), vf);
- ixgbe_set_vmolr(hw, vf, false);
+ ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
+
+ /* set outgoing tags for VFs */
+ if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
+ ixgbe_clear_vmvir(adapter, vf);
} else {
- ixgbe_set_vf_vlan(adapter, true, 0, vf);
- ixgbe_set_vmvir(adapter, 0, vf);
- ixgbe_set_vmolr(hw, vf, true);
+ if (vfinfo->pf_qos || !num_tcs)
+ ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+ vfinfo->pf_qos, vf);
+ else
+ ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+ adapter->default_up, vf);
+
+ if (vfinfo->spoofchk_enabled)
+ hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
}
/* reset multicast table array for vf */
@@ -430,6 +497,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
ixgbe_set_rx_mode(adapter->netdev);
hw->mac.ops.clear_rar(hw, rar_entry);
+
+ /* reset VF api back to unknown */
+ adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
}
static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
@@ -521,30 +591,221 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
return 0;
}
-static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 reg;
+ unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
+ u32 reg, msgbuf[4];
u32 reg_offset, vf_shift;
+ u8 *addr = (u8 *)(&msgbuf[1]);
+
+ e_info(probe, "VF Reset msg received from vf %d\n", vf);
+
+ /* reset the filters for the device */
+ ixgbe_vf_reset_event(adapter, vf);
+
+ /* set vf mac address */
+ ixgbe_set_vf_mac(adapter, vf, vf_mac);
vf_shift = vf % 32;
reg_offset = vf / 32;
- /* enable transmit and receive for vf */
+ /* enable transmit for vf */
reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
- reg |= (reg | (1 << vf_shift));
+ reg |= 1 << vf_shift;
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);
+ /* enable receive for vf */
reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
- reg |= (reg | (1 << vf_shift));
+ reg |= 1 << vf_shift;
+ /*
+ * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
+ * For more info take a look at ixgbe_set_vf_lpe
+ */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ struct net_device *dev = adapter->netdev;
+ int pf_max_frame = dev->mtu + ETH_HLEN;
+
+#ifdef CONFIG_FCOE
+ if (dev->features & NETIF_F_FCOE_MTU)
+ pf_max_frame = max_t(int, pf_max_frame,
+ IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+ if (pf_max_frame > ETH_FRAME_LEN)
+ reg &= ~(1 << vf_shift);
+ }
IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
+ /* enable VF mailbox for further messages */
+ adapter->vfinfo[vf].clear_to_send = true;
+
/* Enable counting of spoofed packets in the SSVPC register */
reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset));
reg |= (1 << vf_shift);
IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
- ixgbe_vf_reset_event(adapter, vf);
+ /* reply to reset with ack and vf mac address */
+ msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
+ memcpy(addr, vf_mac, ETH_ALEN);
+
+ /*
+ * Piggyback the multicast filter type so VF can compute the
+ * correct vectors
+ */
+ msgbuf[3] = hw->mac.mc_filter_type;
+ ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
+
+ return 0;
+}
+
+static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ u8 *new_mac = ((u8 *)(&msgbuf[1]));
+
+ if (!is_valid_ether_addr(new_mac)) {
+ e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+ return -1;
+ }
+
+ if (adapter->vfinfo[vf].pf_set_mac &&
+ memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac,
+ ETH_ALEN)) {
+ e_warn(drv,
+ "VF %d attempted to override administratively set MAC address\n"
+ "Reload the VF driver to resume operations\n",
+ vf);
+ return -1;
+ }
+
+ return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0;
+}
+
+static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+ int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
+ int err;
+ u8 tcs = netdev_get_num_tc(adapter->netdev);
+
+ if (adapter->vfinfo[vf].pf_vlan || tcs) {
+ e_warn(drv,
+ "VF %d attempted to override administratively set VLAN configuration\n"
+ "Reload the VF driver to resume operations\n",
+ vf);
+ return -1;
+ }
+
+ if (add)
+ adapter->vfinfo[vf].vlan_count++;
+ else if (adapter->vfinfo[vf].vlan_count)
+ adapter->vfinfo[vf].vlan_count--;
+
+ err = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+ if (!err && adapter->vfinfo[vf].spoofchk_enabled)
+ hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+
+ return err;
+}
+
+static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ u8 *new_mac = ((u8 *)(&msgbuf[1]));
+ int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
+ IXGBE_VT_MSGINFO_SHIFT;
+ int err;
+
+ if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
+ e_warn(drv,
+ "VF %d requested MACVLAN filter but is administratively denied\n",
+ vf);
+ return -1;
+ }
+
+ /* An non-zero index indicates the VF is setting a filter */
+ if (index) {
+ if (!is_valid_ether_addr(new_mac)) {
+ e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+ return -1;
+ }
+
+ /*
+ * If the VF is allowed to set MAC filters then turn off
+ * anti-spoofing to avoid false positives.
+ */
+ if (adapter->vfinfo[vf].spoofchk_enabled)
+ ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
+ }
+
+ err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac);
+ if (err == -ENOSPC)
+ e_warn(drv,
+ "VF %d has requested a MACVLAN filter but there is no space for it\n",
+ vf);
+
+ return err < 0;
+}
+
+static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ int api = msgbuf[1];
+
+ switch (api) {
+ case ixgbe_mbox_api_10:
+ case ixgbe_mbox_api_11:
+ adapter->vfinfo[vf].vf_api = api;
+ return 0;
+ default:
+ break;
+ }
+
+ e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
+
+ return -1;
+}
+
+static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ struct net_device *dev = adapter->netdev;
+ struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
+ unsigned int default_tc = 0;
+ u8 num_tcs = netdev_get_num_tc(dev);
+
+ /* verify the PF is supporting the correct APIs */
+ switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_20:
+ case ixgbe_mbox_api_11:
+ break;
+ default:
+ return -1;
+ }
+
+ /* only allow 1 Tx queue for bandwidth limiting */
+ msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+ msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+
+ /* if TCs > 1 determine which TC belongs to default user priority */
+ if (num_tcs > 1)
+ default_tc = netdev_get_prio_tc_map(dev, adapter->default_up);
+
+ /* notify VF of need for VLAN tag stripping, and correct queue */
+ if (num_tcs)
+ msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs;
+ else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos)
+ msgbuf[IXGBE_VF_TRANS_VLAN] = 1;
+ else
+ msgbuf[IXGBE_VF_TRANS_VLAN] = 0;
+
+ /* notify VF of default queue */
+ msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc;
+
+ return 0;
}
static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
@@ -553,10 +814,6 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
struct ixgbe_hw *hw = &adapter->hw;
s32 retval;
- int entries;
- u16 *hash_list;
- int add, vid, index;
- u8 *new_mac;
retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
@@ -572,39 +829,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
/* flush the ack before we write any messages back */
IXGBE_WRITE_FLUSH(hw);
+ if (msgbuf[0] == IXGBE_VF_RESET)
+ return ixgbe_vf_reset_msg(adapter, vf);
+
/*
* until the vf completes a virtual function reset it should not be
* allowed to start any configuration.
*/
-
- if (msgbuf[0] == IXGBE_VF_RESET) {
- unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
- new_mac = (u8 *)(&msgbuf[1]);
- e_info(probe, "VF Reset msg received from vf %d\n", vf);
- adapter->vfinfo[vf].clear_to_send = false;
- ixgbe_vf_reset_msg(adapter, vf);
- adapter->vfinfo[vf].clear_to_send = true;
-
- if (is_valid_ether_addr(new_mac) &&
- !adapter->vfinfo[vf].pf_set_mac)
- ixgbe_set_vf_mac(adapter, vf, vf_mac);
- else
- ixgbe_set_vf_mac(adapter,
- vf, adapter->vfinfo[vf].vf_mac_addresses);
-
- /* reply to reset with ack and vf mac address */
- msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
- memcpy(new_mac, vf_mac, ETH_ALEN);
- /*
- * Piggyback the multicast filter type so VF can compute the
- * correct vectors
- */
- msgbuf[3] = hw->mac.mc_filter_type;
- ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
-
- return retval;
- }
-
if (!adapter->vfinfo[vf].clear_to_send) {
msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
ixgbe_write_mbx(hw, msgbuf, 1, vf);
@@ -613,70 +844,25 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
switch ((msgbuf[0] & 0xFFFF)) {
case IXGBE_VF_SET_MAC_ADDR:
- new_mac = ((u8 *)(&msgbuf[1]));
- if (is_valid_ether_addr(new_mac) &&
- !adapter->vfinfo[vf].pf_set_mac) {
- ixgbe_set_vf_mac(adapter, vf, new_mac);
- } else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses,
- new_mac, ETH_ALEN)) {
- e_warn(drv, "VF %d attempted to override "
- "administratively set MAC address\nReload "
- "the VF driver to resume operations\n", vf);
- retval = -1;
- }
+ retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf);
break;
case IXGBE_VF_SET_MULTICAST:
- entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
- >> IXGBE_VT_MSGINFO_SHIFT;
- hash_list = (u16 *)&msgbuf[1];
- retval = ixgbe_set_vf_multicasts(adapter, entries,
- hash_list, vf);
- break;
- case IXGBE_VF_SET_LPE:
- ixgbe_set_vf_lpe(adapter, msgbuf);
+ retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf);
break;
case IXGBE_VF_SET_VLAN:
- add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
- >> IXGBE_VT_MSGINFO_SHIFT;
- vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
- if (adapter->vfinfo[vf].pf_vlan) {
- e_warn(drv, "VF %d attempted to override "
- "administratively set VLAN configuration\n"
- "Reload the VF driver to resume operations\n",
- vf);
- retval = -1;
- } else {
- if (add)
- adapter->vfinfo[vf].vlan_count++;
- else if (adapter->vfinfo[vf].vlan_count)
- adapter->vfinfo[vf].vlan_count--;
- retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
- if (!retval && adapter->vfinfo[vf].spoofchk_enabled)
- hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
- }
+ retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
+ break;
+ case IXGBE_VF_SET_LPE:
+ retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
break;
case IXGBE_VF_SET_MACVLAN:
- index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
- IXGBE_VT_MSGINFO_SHIFT;
- if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
- e_warn(drv, "VF %d requested MACVLAN filter but is "
- "administratively denied\n", vf);
- retval = -1;
- break;
- }
- /*
- * If the VF is allowed to set MAC filters then turn off
- * anti-spoofing to avoid false positives. An index
- * greater than 0 will indicate the VF is setting a
- * macvlan MAC filter.
- */
- if (index > 0 && adapter->vfinfo[vf].spoofchk_enabled)
- ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
- retval = ixgbe_set_vf_macvlan(adapter, vf, index,
- (unsigned char *)(&msgbuf[1]));
- if (retval == -ENOSPC)
- e_warn(drv, "VF %d has requested a MACVLAN filter "
- "but there is no space for it\n", vf);
+ retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
+ break;
+ case IXGBE_VF_API_NEGOTIATE:
+ retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf);
+ break;
+ case IXGBE_VF_GET_QUEUES:
+ retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
@@ -692,7 +878,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS;
- ixgbe_write_mbx(hw, msgbuf, 1, vf);
+ ixgbe_write_mbx(hw, msgbuf, mbx_size, vf);
return retval;
}
@@ -783,7 +969,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
if (err)
goto out;
- ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
+ ixgbe_set_vmvir(adapter, vlan, qos, vf);
ixgbe_set_vmolr(hw, vf, false);
if (adapter->vfinfo[vf].spoofchk_enabled)
hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
@@ -803,7 +989,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
} else {
err = ixgbe_set_vf_vlan(adapter, false,
adapter->vfinfo[vf].pf_vlan, vf);
- ixgbe_set_vmvir(adapter, vlan, vf);
+ ixgbe_clear_vmvir(adapter, vf);
ixgbe_set_vmolr(hw, vf, true);
hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
if (adapter->vfinfo[vf].vlan_count)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 0722f3368092..9cd8a13711d3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -56,6 +56,7 @@
#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
#define IXGBE_SUBDEV_ID_82599_RNDC 0x1F72
#define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0
+#define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
#define IXGBE_DEV_ID_82599_SFP_SF2 0x154D
#define IXGBE_DEV_ID_82599EN_SFP 0x1557
@@ -1833,15 +1834,6 @@ enum {
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
-/* Check whether address is multicast. This is little-endian specific check.*/
-#define IXGBE_IS_MULTICAST(Address) \
- (bool)(((u8 *)(Address))[0] & ((u8)0x01))
-
-/* Check whether an address is broadcast. */
-#define IXGBE_IS_BROADCAST(Address) \
- ((((u8 *)(Address))[0] == ((u8)0xff)) && \
- (((u8 *)(Address))[1] == ((u8)0xff)))
-
/* RAH */
#define IXGBE_RAH_VIND_MASK 0x003C0000
#define IXGBE_RAH_VIND_SHIFT 18
@@ -1962,6 +1954,8 @@ enum {
#define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000
#define IXGBE_MRQC_L3L4TXSWEN 0x00008000
+#define IXGBE_FWSM_TS_ENABLED 0x1
+
/* Queue Drop Enable */
#define IXGBE_QDE_ENABLE 0x00000001
#define IXGBE_QDE_IDX_MASK 0x00007F00
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index de4da5219b71..c73b92993391 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -152,7 +152,7 @@ mac_reset_top:
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
/* Add the SAN MAC address to the RAR only if it's a valid address */
- if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+ if (is_valid_ether_addr(hw->mac.san_addr)) {
hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
hw->mac.san_addr, 0, IXGBE_RAH_AV);
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index da17ccf5c09d..3147795bd135 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -33,8 +33,11 @@
#define IXGBE_DEV_ID_X540_VF 0x1515
#define IXGBE_VF_IRQ_CLEAR_MASK 7
-#define IXGBE_VF_MAX_TX_QUEUES 1
-#define IXGBE_VF_MAX_RX_QUEUES 1
+#define IXGBE_VF_MAX_TX_QUEUES 8
+#define IXGBE_VF_MAX_RX_QUEUES 8
+
+/* DCB define */
+#define IXGBE_VF_MAX_TRAFFIC_CLASS 8
/* Link speed */
typedef u32 ixgbe_link_speed;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 4a9c9c285685..fc0af9a3bb35 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -58,7 +58,6 @@ struct ixgbevf_ring {
struct ixgbevf_ring *next;
struct net_device *netdev;
struct device *dev;
- struct ixgbevf_adapter *adapter; /* backlink */
void *desc; /* descriptor ring memory */
dma_addr_t dma; /* phys. address of descriptor ring */
unsigned int size; /* length in bytes */
@@ -75,6 +74,8 @@ struct ixgbevf_ring {
u64 total_bytes;
u64 total_packets;
struct u64_stats_sync syncp;
+ u64 hw_csum_rx_error;
+ u64 hw_csum_rx_good;
u16 head;
u16 tail;
@@ -89,8 +90,8 @@ struct ixgbevf_ring {
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IXGBEVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
-#define MAX_RX_QUEUES 1
-#define MAX_TX_QUEUES 1
+#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES
+#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES
#define IXGBEVF_DEFAULT_TXD 1024
#define IXGBEVF_DEFAULT_RXD 512
@@ -101,10 +102,10 @@ struct ixgbevf_ring {
/* Supported Rx Buffer Sizes */
#define IXGBEVF_RXBUFFER_256 256 /* Used for packet split */
-#define IXGBEVF_RXBUFFER_3K 3072
-#define IXGBEVF_RXBUFFER_7K 7168
-#define IXGBEVF_RXBUFFER_15K 15360
-#define IXGBEVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */
+#define IXGBEVF_RXBUFFER_2K 2048
+#define IXGBEVF_RXBUFFER_4K 4096
+#define IXGBEVF_RXBUFFER_8K 8192
+#define IXGBEVF_RXBUFFER_10K 10240
#define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256
@@ -229,6 +230,7 @@ struct ixgbevf_adapter {
*/
u32 flags;
#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1)
+#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 1)
/* OS defined structs */
struct net_device *netdev;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index de1ad506665d..257357ae66c3 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -58,7 +58,7 @@ const char ixgbevf_driver_name[] = "ixgbevf";
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
-#define DRV_VERSION "2.6.0-k"
+#define DRV_VERSION "2.7.12-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
"Copyright (c) 2009 - 2012 Intel Corporation.";
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
/* forward decls */
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,
@@ -120,7 +121,6 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
* @direction: 0 for Rx, 1 for Tx, -1 for other causes
* @queue: queue to map the corresponding interrupt to
* @msix_vector: the vector to map to the corresponding queue
- *
*/
static void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction,
u8 queue, u8 msix_vector)
@@ -287,17 +287,19 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
if (is_vlan && test_bit(tag & VLAN_VID_MASK, adapter->active_vlans))
__vlan_hwaccel_put_tag(skb, tag);
- napi_gro_receive(&q_vector->napi, skb);
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+ napi_gro_receive(&q_vector->napi, skb);
+ else
+ netif_rx(skb);
}
/**
* ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum
- * @adapter: address of board private structure
+ * @ring: pointer to Rx descriptor ring structure
* @status_err: hardware indication of status of receive
* @skb: skb currently being received and modified
**/
-static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
- struct ixgbevf_ring *ring,
+static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring,
u32 status_err, struct sk_buff *skb)
{
skb_checksum_none_assert(skb);
@@ -309,7 +311,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
/* if IP and error */
if ((status_err & IXGBE_RXD_STAT_IPCS) &&
(status_err & IXGBE_RXDADV_ERR_IPE)) {
- adapter->hw_csum_rx_error++;
+ ring->hw_csum_rx_error++;
return;
}
@@ -317,13 +319,13 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
return;
if (status_err & IXGBE_RXDADV_ERR_TCPE) {
- adapter->hw_csum_rx_error++;
+ ring->hw_csum_rx_error++;
return;
}
/* It must be a TCP or UDP packet with a valid checksum */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- adapter->hw_csum_rx_good++;
+ ring->hw_csum_rx_good++;
}
/**
@@ -337,15 +339,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
struct pci_dev *pdev = adapter->pdev;
union ixgbe_adv_rx_desc *rx_desc;
struct ixgbevf_rx_buffer *bi;
- struct sk_buff *skb;
unsigned int i = rx_ring->next_to_use;
bi = &rx_ring->rx_buffer_info[i];
while (cleaned_count--) {
rx_desc = IXGBEVF_RX_DESC(rx_ring, i);
- skb = bi->skb;
- if (!skb) {
+
+ if (!bi->skb) {
+ struct sk_buff *skb;
+
skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
rx_ring->rx_buf_len);
if (!skb) {
@@ -353,11 +356,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
goto no_buffers;
}
bi->skb = skb;
- }
- if (!bi->dma) {
+
bi->dma = dma_map_single(&pdev->dev, skb->data,
rx_ring->rx_buf_len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(&pdev->dev, bi->dma)) {
+ dev_kfree_skb(skb);
+ bi->skb = NULL;
+ dev_err(&pdev->dev, "RX DMA map failed\n");
+ break;
+ }
}
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
@@ -370,7 +378,6 @@ 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);
}
}
@@ -454,7 +461,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
goto next_desc;
}
- ixgbevf_rx_checksum(adapter, rx_ring, staterr, skb);
+ ixgbevf_rx_checksum(rx_ring, staterr, skb);
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
@@ -471,6 +478,16 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
}
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+ /* Workaround hardware that can't do proper VEPA multicast
+ * source pruning.
+ */
+ if ((skb->pkt_type & (PACKET_BROADCAST | PACKET_MULTICAST)) &&
+ !(compare_ether_addr(adapter->netdev->dev_addr,
+ eth_hdr(skb)->h_source))) {
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc);
next_desc:
@@ -533,9 +550,11 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
else
per_ring_budget = budget;
+ adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
ixgbevf_for_each_ring(ring, q_vector->rx)
clean_complete &= ixgbevf_clean_rx_irq(q_vector, ring,
per_ring_budget);
+ adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL;
/* If all work not completed, return budget and keep polling */
if (!clean_complete)
@@ -743,7 +762,6 @@ static irqreturn_t ixgbevf_msix_other(int irq, void *data)
return IRQ_HANDLED;
}
-
/**
* ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues)
* @irq: unused
@@ -1065,20 +1083,20 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter)
max_frame += VLAN_HLEN;
/*
- * Make best use of allocation by using all but 1K of a
- * power of 2 allocation that will be used for skb->head.
+ * Allocate buffer sizes that fit well into 32K and
+ * take into account max frame size of 9.5K
*/
if ((hw->mac.type == ixgbe_mac_X540_vf) &&
(max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE))
rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- else if (max_frame <= IXGBEVF_RXBUFFER_3K)
- rx_buf_len = IXGBEVF_RXBUFFER_3K;
- else if (max_frame <= IXGBEVF_RXBUFFER_7K)
- rx_buf_len = IXGBEVF_RXBUFFER_7K;
- else if (max_frame <= IXGBEVF_RXBUFFER_15K)
- rx_buf_len = IXGBEVF_RXBUFFER_15K;
+ else if (max_frame <= IXGBEVF_RXBUFFER_2K)
+ rx_buf_len = IXGBEVF_RXBUFFER_2K;
+ else if (max_frame <= IXGBEVF_RXBUFFER_4K)
+ rx_buf_len = IXGBEVF_RXBUFFER_4K;
+ else if (max_frame <= IXGBEVF_RXBUFFER_8K)
+ rx_buf_len = IXGBEVF_RXBUFFER_8K;
else
- rx_buf_len = IXGBEVF_MAX_RXBUFFER;
+ rx_buf_len = IXGBEVF_RXBUFFER_10K;
for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i].rx_buf_len = rx_buf_len;
@@ -1128,15 +1146,12 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
struct ixgbe_hw *hw = &adapter->hw;
int err;
- if (!hw->mac.ops.set_vfta)
- return -EOPNOTSUPP;
-
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
/* add VID to filter table */
err = hw->mac.ops.set_vfta(hw, vid, 0, true);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
/* translate error return types so error makes sense */
if (err == IXGBE_ERR_MBX)
@@ -1156,13 +1171,12 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct ixgbe_hw *hw = &adapter->hw;
int err = -EOPNOTSUPP;
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
/* remove VID from filter table */
- if (hw->mac.ops.set_vfta)
- err = hw->mac.ops.set_vfta(hw, vid, 0, false);
+ err = hw->mac.ops.set_vfta(hw, vid, 0, false);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
clear_bit(vid, adapter->active_vlans);
@@ -1206,27 +1220,27 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
}
/**
- * ixgbevf_set_rx_mode - Multicast set
+ * ixgbevf_set_rx_mode - Multicast and unicast set
* @netdev: network interface device structure
*
* The set_rx_method entry point is called whenever the multicast address
- * list or the network interface flags are updated. This routine is
- * responsible for configuring the hardware for proper multicast mode.
+ * list, unicast address list or the network interface flags are updated.
+ * This routine is responsible for configuring the hardware for proper
+ * multicast mode and configuring requested unicast filters.
**/
static void ixgbevf_set_rx_mode(struct net_device *netdev)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
/* reprogram multicast list */
- if (hw->mac.ops.update_mc_addr_list)
- hw->mac.ops.update_mc_addr_list(hw, netdev);
+ hw->mac.ops.update_mc_addr_list(hw, netdev);
ixgbevf_write_uc_addr_list(netdev);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
}
static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter)
@@ -1290,8 +1304,8 @@ static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
"not set within the polling period\n", rxr);
}
- ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr],
- (adapter->rx_ring[rxr].count - 1));
+ ixgbevf_release_rx_desc(hw, &adapter->rx_ring[rxr],
+ adapter->rx_ring[rxr].count - 1);
}
static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter)
@@ -1335,11 +1349,12 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- int api[] = { ixgbe_mbox_api_10,
+ int api[] = { ixgbe_mbox_api_11,
+ ixgbe_mbox_api_10,
ixgbe_mbox_api_unknown };
int err = 0, idx = 0;
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
while (api[idx] != ixgbe_mbox_api_unknown) {
err = ixgbevf_negotiate_api_version(hw, api[idx]);
@@ -1348,7 +1363,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
idx++;
}
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
}
static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
@@ -1389,16 +1404,14 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
ixgbevf_configure_msix(adapter);
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
- if (hw->mac.ops.set_rar) {
- if (is_valid_ether_addr(hw->mac.addr))
- hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
- else
- hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
- }
+ if (is_valid_ether_addr(hw->mac.addr))
+ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+ else
+ hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
clear_bit(__IXGBEVF_DOWN, &adapter->state);
ixgbevf_napi_enable_all(adapter);
@@ -1413,12 +1426,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies);
}
+static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbevf_ring *rx_ring;
+ unsigned int def_q = 0;
+ unsigned int num_tcs = 0;
+ unsigned int num_rx_queues = 1;
+ int err, i;
+
+ spin_lock_bh(&adapter->mbx_lock);
+
+ /* fetch queue configuration from the PF */
+ err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+ spin_unlock_bh(&adapter->mbx_lock);
+
+ if (err)
+ return err;
+
+ if (num_tcs > 1) {
+ /* update default Tx ring register index */
+ adapter->tx_ring[0].reg_idx = def_q;
+
+ /* we need as many queues as traffic classes */
+ num_rx_queues = num_tcs;
+ }
+
+ /* nothing to do if we have the correct number of queues */
+ if (adapter->num_rx_queues == num_rx_queues)
+ return 0;
+
+ /* allocate new rings */
+ rx_ring = kcalloc(num_rx_queues,
+ sizeof(struct ixgbevf_ring), GFP_KERNEL);
+ if (!rx_ring)
+ return -ENOMEM;
+
+ /* setup ring fields */
+ for (i = 0; i < num_rx_queues; i++) {
+ rx_ring[i].count = adapter->rx_ring_count;
+ rx_ring[i].queue_index = i;
+ rx_ring[i].reg_idx = i;
+ rx_ring[i].dev = &adapter->pdev->dev;
+ rx_ring[i].netdev = adapter->netdev;
+
+ /* allocate resources on the ring */
+ err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+ if (err) {
+ while (i) {
+ i--;
+ ixgbevf_free_rx_resources(adapter, &rx_ring[i]);
+ }
+ kfree(rx_ring);
+ return err;
+ }
+ }
+
+ /* free the existing rings and queues */
+ ixgbevf_free_all_rx_resources(adapter);
+ adapter->num_rx_queues = 0;
+ kfree(adapter->rx_ring);
+
+ /* move new rings into position on the adapter struct */
+ adapter->rx_ring = rx_ring;
+ adapter->num_rx_queues = num_rx_queues;
+
+ /* reset ring to vector mapping */
+ ixgbevf_reset_q_vectors(adapter);
+ ixgbevf_map_rings_to_vectors(adapter);
+
+ return 0;
+}
+
void ixgbevf_up(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
ixgbevf_negotiate_api(adapter);
+ ixgbevf_reset_queues(adapter);
+
ixgbevf_configure(adapter);
ixgbevf_up_complete(adapter);
@@ -1497,7 +1585,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter,
return;
/* Free all the Tx ring sk_buffs */
-
for (i = 0; i < tx_ring->count; i++) {
tx_buffer_info = &tx_ring->tx_buffer_info[i];
ixgbevf_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
@@ -1593,13 +1680,6 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
msleep(1);
- /*
- * Check if PF is up before re-init. If not then skip until
- * later when the PF is up and ready to service requests from
- * the VF via mailbox. If the VF is up and running then the
- * watchdog task will continue to schedule reset tasks until
- * the PF is up and running.
- */
ixgbevf_down(adapter);
ixgbevf_up(adapter);
@@ -1611,15 +1691,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- spin_lock(&adapter->mbx_lock);
-
if (hw->mac.ops.reset_hw(hw))
hw_dbg(hw, "PF still resetting\n");
else
hw->mac.ops.init_hw(hw);
- spin_unlock(&adapter->mbx_lock);
-
if (is_valid_ether_addr(adapter->hw.mac.addr)) {
memcpy(netdev->dev_addr, adapter->hw.mac.addr,
netdev->addr_len);
@@ -1628,10 +1704,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
}
}
-static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
- int vectors)
+static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
+ int vectors)
{
- int err, vector_threshold;
+ int err = 0;
+ int vector_threshold;
/* We'll want at least 2 (vector_threshold):
* 1) TxQ[0] + RxQ[0] handler
@@ -1647,21 +1724,18 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
while (vectors >= vector_threshold) {
err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
vectors);
- if (!err) /* Success in acquiring all requested vectors. */
+ if (!err || err < 0) /* Success or a nasty failure. */
break;
- else if (err < 0)
- vectors = 0; /* Nasty failure, quit now */
else /* err == number of vectors we should try again with */
vectors = err;
}
- if (vectors < vector_threshold) {
- /* Can't allocate enough MSI-X interrupts? Oh well.
- * This just means we'll go with either a single MSI
- * vector or fall back to legacy interrupts.
- */
- hw_dbg(&adapter->hw,
- "Unable to allocate MSI-X interrupts\n");
+ if (vectors < vector_threshold)
+ err = -ENOMEM;
+
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to allocate MSI-X interrupts\n");
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
} else {
@@ -1672,6 +1746,8 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
*/
adapter->num_msix_vectors = vectors;
}
+
+ return err;
}
/**
@@ -1717,6 +1793,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) {
adapter->tx_ring[i].count = adapter->tx_ring_count;
adapter->tx_ring[i].queue_index = i;
+ /* reg_idx may be remapped later by DCB config */
adapter->tx_ring[i].reg_idx = i;
adapter->tx_ring[i].dev = &adapter->pdev->dev;
adapter->tx_ring[i].netdev = adapter->netdev;
@@ -1774,7 +1851,9 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter)
for (vector = 0; vector < v_budget; vector++)
adapter->msix_entries[vector].entry = vector;
- ixgbevf_acquire_msix_vectors(adapter, v_budget);
+ err = ixgbevf_acquire_msix_vectors(adapter, v_budget);
+ if (err)
+ goto out;
err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
if (err)
@@ -1834,18 +1913,13 @@ err_out:
**/
static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)
{
- int q_idx, num_q_vectors;
- int napi_vectors;
-
- num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
- napi_vectors = adapter->num_rx_queues;
+ int q_idx, num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx];
adapter->q_vector[q_idx] = NULL;
- if (q_idx < napi_vectors)
- netif_napi_del(&q_vector->napi);
+ netif_napi_del(&q_vector->napi);
kfree(q_vector);
}
}
@@ -1935,7 +2009,7 @@ static void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter)
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
-static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
+static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -1950,8 +2024,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
hw->subsystem_device_id = pdev->subsystem_device;
hw->mbx.ops.init_params(hw);
- hw->mac.max_tx_queues = MAX_TX_QUEUES;
- hw->mac.max_rx_queues = MAX_RX_QUEUES;
+
+ /* assume legacy case in which PF would only give VF 2 queues */
+ hw->mac.max_tx_queues = 2;
+ hw->mac.max_rx_queues = 2;
+
err = hw->mac.ops.reset_hw(hw);
if (err) {
dev_info(&pdev->dev,
@@ -1966,7 +2043,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
goto out;
}
memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr,
- adapter->netdev->addr_len);
+ adapter->netdev->addr_len);
}
/* lock to protect mailbox accesses */
@@ -2016,6 +2093,7 @@ out:
void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
+ int i;
UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc,
adapter->stats.vfgprc);
@@ -2029,6 +2107,15 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
adapter->stats.vfgotc);
UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
adapter->stats.vfmprc);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ adapter->hw_csum_rx_error +=
+ adapter->rx_ring[i].hw_csum_rx_error;
+ adapter->hw_csum_rx_good +=
+ adapter->rx_ring[i].hw_csum_rx_good;
+ adapter->rx_ring[i].hw_csum_rx_error = 0;
+ adapter->rx_ring[i].hw_csum_rx_good = 0;
+ }
}
/**
@@ -2103,6 +2190,7 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
struct ixgbe_hw *hw = &adapter->hw;
u32 link_speed = adapter->link_speed;
bool link_up = adapter->link_up;
+ s32 need_reset;
adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
@@ -2110,29 +2198,19 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
* Always check the link on the watchdog because we have
* no LSC interrupt
*/
- if (hw->mac.ops.check_link) {
- s32 need_reset;
-
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
- need_reset = hw->mac.ops.check_link(hw, &link_speed,
- &link_up, false);
+ need_reset = hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
- if (need_reset) {
- adapter->link_up = link_up;
- adapter->link_speed = link_speed;
- netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
- schedule_work(&adapter->reset_task);
- goto pf_has_reset;
- }
- } else {
- /* always assume link is up, if no check link
- * function */
- link_speed = IXGBE_LINK_SPEED_10GB_FULL;
- link_up = true;
+ if (need_reset) {
+ adapter->link_up = link_up;
+ adapter->link_speed = link_speed;
+ netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
+ schedule_work(&adapter->reset_task);
+ goto pf_has_reset;
}
adapter->link_up = link_up;
adapter->link_speed = link_speed;
@@ -2377,6 +2455,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter)
&adapter->rx_ring[i]);
}
+static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbevf_ring *rx_ring;
+ unsigned int def_q = 0;
+ unsigned int num_tcs = 0;
+ unsigned int num_rx_queues = 1;
+ int err, i;
+
+ spin_lock_bh(&adapter->mbx_lock);
+
+ /* fetch queue configuration from the PF */
+ err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+ spin_unlock_bh(&adapter->mbx_lock);
+
+ if (err)
+ return err;
+
+ if (num_tcs > 1) {
+ /* update default Tx ring register index */
+ adapter->tx_ring[0].reg_idx = def_q;
+
+ /* we need as many queues as traffic classes */
+ num_rx_queues = num_tcs;
+ }
+
+ /* nothing to do if we have the correct number of queues */
+ if (adapter->num_rx_queues == num_rx_queues)
+ return 0;
+
+ /* allocate new rings */
+ rx_ring = kcalloc(num_rx_queues,
+ sizeof(struct ixgbevf_ring), GFP_KERNEL);
+ if (!rx_ring)
+ return -ENOMEM;
+
+ /* setup ring fields */
+ for (i = 0; i < num_rx_queues; i++) {
+ rx_ring[i].count = adapter->rx_ring_count;
+ rx_ring[i].queue_index = i;
+ rx_ring[i].reg_idx = i;
+ rx_ring[i].dev = &adapter->pdev->dev;
+ rx_ring[i].netdev = adapter->netdev;
+ }
+
+ /* free the existing ring and queues */
+ adapter->num_rx_queues = 0;
+ kfree(adapter->rx_ring);
+
+ /* move new rings into position on the adapter struct */
+ adapter->rx_ring = rx_ring;
+ adapter->num_rx_queues = num_rx_queues;
+
+ return 0;
+}
+
/**
* ixgbevf_open - Called when a network interface is made active
* @netdev: network interface device structure
@@ -2413,6 +2548,11 @@ static int ixgbevf_open(struct net_device *netdev)
ixgbevf_negotiate_api(adapter);
+ /* setup queue reg_idx and Rx queue count */
+ err = ixgbevf_setup_queues(adapter);
+ if (err)
+ goto err_setup_queues;
+
/* allocate transmit descriptors */
err = ixgbevf_setup_all_tx_resources(adapter);
if (err)
@@ -2451,6 +2591,7 @@ err_setup_rx:
ixgbevf_free_all_rx_resources(adapter);
err_setup_tx:
ixgbevf_free_all_tx_resources(adapter);
+err_setup_queues:
ixgbevf_reset(adapter);
err_setup_reset:
@@ -2562,9 +2703,6 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
static bool ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
struct sk_buff *skb, u32 tx_flags)
{
-
-
-
u32 vlan_macip_lens = 0;
u32 mss_l4len_idx = 0;
u32 type_tucmd = 0;
@@ -2678,10 +2816,10 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
tx_buffer_info->dma =
skb_frag_dma_map(tx_ring->dev, frag,
offset, size, DMA_TO_DEVICE);
- tx_buffer_info->mapped_as_page = true;
if (dma_mapping_error(tx_ring->dev,
tx_buffer_info->dma))
goto dma_error;
+ tx_buffer_info->mapped_as_page = true;
tx_buffer_info->next_to_watch = i;
len -= size;
@@ -2754,7 +2892,6 @@ static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags,
olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
if (tx_flags & IXGBE_TX_FLAGS_IPV4)
olinfo_status |= IXGBE_ADVTXD_POPTS_IXSM;
-
}
/*
@@ -2823,6 +2960,11 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
unsigned short f;
#endif
+ u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL);
+ if (!dst_mac || is_link_local_ether_addr(dst_mac)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
tx_ring = &adapter->tx_ring[r_idx];
@@ -2902,12 +3044,11 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p)
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
- spin_lock(&adapter->mbx_lock);
+ spin_lock_bh(&adapter->mbx_lock);
- if (hw->mac.ops.set_rar)
- hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
- spin_unlock(&adapter->mbx_lock);
+ spin_unlock_bh(&adapter->mbx_lock);
return 0;
}
@@ -2925,8 +3066,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
- if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+ switch (adapter->hw.api_version) {
+ case ixgbe_mbox_api_11:
max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+ break;
+ default:
+ if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+ max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+ break;
+ }
/* MTU < 68 is an error and causes problems on some kernels */
if ((new_mtu < 68) || (max_frame > max_possible_frame))
@@ -3094,8 +3242,7 @@ static void ixgbevf_assign_netdev_ops(struct net_device *dev)
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-static int __devinit ixgbevf_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct ixgbevf_adapter *adapter = NULL;
@@ -3223,10 +3370,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
if (err)
goto err_sw_init;
- /* pick up the PCI bus settings for reporting later */
- if (hw->mac.ops.get_bus_info)
- hw->mac.ops.get_bus_info(hw);
-
strcpy(netdev->name, "eth%d");
err = register_netdev(netdev);
@@ -3270,7 +3413,7 @@ err_dma:
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit ixgbevf_remove(struct pci_dev *pdev)
+static void ixgbevf_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -3384,7 +3527,7 @@ static struct pci_driver ixgbevf_driver = {
.name = ixgbevf_driver_name,
.id_table = ixgbevf_pci_tbl,
.probe = ixgbevf_probe,
- .remove = __devexit_p(ixgbevf_remove),
+ .remove = ixgbevf_remove,
#ifdef CONFIG_PM
/* Power Management Hooks */
.suspend = ixgbevf_suspend,
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index 946ce86f337f..0bc30058ff82 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -85,6 +85,7 @@
enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
+ ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */
#define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUE 0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */
+
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 0c7447e6fcc8..0c94557b53df 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -331,6 +331,9 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
netdev_for_each_mc_addr(ha, netdev) {
if (i == cnt)
break;
+ if (is_link_local_ether_addr(ha->addr))
+ continue;
+
vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
}
@@ -513,6 +516,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
return err;
}
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+ unsigned int *default_tc)
+{
+ int err;
+ u32 msg[5];
+
+ /* do nothing if API doesn't support ixgbevf_get_queues */
+ switch (hw->api_version) {
+ case ixgbe_mbox_api_11:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Fetch queue configuration from the PF */
+ msg[0] = IXGBE_VF_GET_QUEUE;
+ msg[1] = msg[2] = msg[3] = msg[4] = 0;
+ err = hw->mbx.ops.write_posted(hw, msg, 5);
+
+ if (!err)
+ err = hw->mbx.ops.read_posted(hw, msg, 5);
+
+ if (!err) {
+ msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+
+ /*
+ * if we we didn't get an ACK there must have been
+ * some sort of mailbox error so we should treat it
+ * as such
+ */
+ if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK))
+ return IXGBE_ERR_MBX;
+
+ /* record and validate values from message */
+ hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES];
+ if (hw->mac.max_tx_queues == 0 ||
+ hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES)
+ hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+ hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES];
+ if (hw->mac.max_rx_queues == 0 ||
+ hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES)
+ hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+
+ *num_tcs = msg[IXGBE_VF_TRANS_VLAN];
+ /* in case of unknown state assume we cannot tag frames */
+ if (*num_tcs > hw->mac.max_rx_queues)
+ *num_tcs = 1;
+
+ *default_tc = msg[IXGBE_VF_DEF_QUEUE];
+ /* default to queue 0 on out-of-bounds queue number */
+ if (*default_tc >= hw->mac.max_tx_queues)
+ *default_tc = 0;
+ }
+
+ return err;
+}
+
static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
.init_hw = ixgbevf_init_hw_vf,
.reset_hw = ixgbevf_reset_hw_vf,
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 47f11a584d8c..7b1f502d1716 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -174,5 +174,7 @@ struct ixgbevf_info {
void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+ unsigned int *default_tc);
#endif /* __IXGBE_VF_H__ */
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 60ac46f4ac08..0519afa413d2 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2965,7 +2965,7 @@ static const struct net_device_ops jme_netdev_ops = {
#endif
};
-static int __devinit
+static int
jme_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3203,7 +3203,7 @@ err_out:
return rc;
}
-static void __devexit
+static void
jme_remove_one(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3318,7 +3318,7 @@ static struct pci_driver jme_driver = {
.name = DRV_NAME,
.id_table = jme_pci_tbl,
.probe = jme_init_one,
- .remove = __devexit_p(jme_remove_one),
+ .remove = jme_remove_one,
.shutdown = jme_shutdown,
.driver.pm = JME_PM_OPS,
};
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 003c5bc7189f..c124e67a1a1c 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -774,7 +774,7 @@ err_out:
return err;
}
-static int __devexit
+static int
ltq_etop_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
@@ -789,7 +789,7 @@ ltq_etop_remove(struct platform_device *pdev)
}
static struct platform_driver ltq_mii_driver = {
- .remove = __devexit_p(ltq_etop_remove),
+ .remove = ltq_etop_remove,
.driver = {
.name = "ltq_etop",
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 59489722e898..10d678d3dd01 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1131,7 +1131,7 @@ static int pxa168_eth_open(struct net_device *dev)
err = request_irq(dev->irq, pxa168_eth_int_handler,
IRQF_DISABLED, dev->name, dev);
if (err) {
- dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+ dev_err(&dev->dev, "can't assign irq\n");
return -EAGAIN;
}
pep->rx_resource_err = 0;
@@ -1201,9 +1201,8 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
*/
pxa168_eth_stop(dev);
if (pxa168_eth_open(dev)) {
- dev_printk(KERN_ERR, &dev->dev,
- "fatal error on re-opening device after "
- "MTU change\n");
+ dev_err(&dev->dev,
+ "fatal error on re-opening device after MTU change\n");
}
return 0;
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index d19a143aa5a8..5544a1fe2f94 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3860,7 +3860,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
return dev;
}
-static void __devinit skge_show_addr(struct net_device *dev)
+static void skge_show_addr(struct net_device *dev)
{
const struct skge_port *skge = netdev_priv(dev);
@@ -3869,8 +3869,7 @@ static void __devinit skge_show_addr(struct net_device *dev)
static int only_32bit_dma;
-static int __devinit skge_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev, *dev1;
struct skge_hw *hw;
@@ -4012,7 +4011,7 @@ err_out:
return err;
}
-static void __devexit skge_remove(struct pci_dev *pdev)
+static void skge_remove(struct pci_dev *pdev)
{
struct skge_hw *hw = pci_get_drvdata(pdev);
struct net_device *dev0, *dev1;
@@ -4142,7 +4141,7 @@ static struct pci_driver skge_driver = {
.name = DRV_NAME,
.id_table = skge_id_table,
.probe = skge_probe,
- .remove = __devexit_p(skge_remove),
+ .remove = skge_remove,
.shutdown = skge_shutdown,
.driver.pm = SKGE_PM_OPS,
};
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 78946feab4a2..3269eb38cc57 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -3140,7 +3140,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
}
-static int __devinit sky2_init(struct sky2_hw *hw)
+static int sky2_init(struct sky2_hw *hw)
{
u8 t8;
@@ -4741,9 +4741,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
};
/* Initialize network device */
-static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
- unsigned port,
- int highmem, int wol)
+static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
+ int highmem, int wol)
{
struct sky2_port *sky2;
struct net_device *dev = alloc_etherdev(sizeof(*sky2));
@@ -4807,7 +4806,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
return dev;
}
-static void __devinit sky2_show_addr(struct net_device *dev)
+static void sky2_show_addr(struct net_device *dev)
{
const struct sky2_port *sky2 = netdev_priv(dev);
@@ -4815,7 +4814,7 @@ static void __devinit sky2_show_addr(struct net_device *dev)
}
/* Handle software interrupt used during MSI test */
-static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
+static irqreturn_t sky2_test_intr(int irq, void *dev_id)
{
struct sky2_hw *hw = dev_id;
u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
@@ -4834,7 +4833,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
}
/* Test interrupt path by forcing a a software IRQ */
-static int __devinit sky2_test_msi(struct sky2_hw *hw)
+static int sky2_test_msi(struct sky2_hw *hw)
{
struct pci_dev *pdev = hw->pdev;
int err;
@@ -4896,8 +4895,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
return buf;
}
-static int __devinit sky2_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev, *dev1;
struct sky2_hw *hw;
@@ -4919,13 +4917,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
err = pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
if (err) {
dev_err(&pdev->dev, "PCI read config failed\n");
- goto err_out;
+ goto err_out_disable;
}
if (~reg == 0) {
dev_err(&pdev->dev, "PCI configuration read error\n");
err = -EIO;
- goto err_out;
+ goto err_out_disable;
}
err = pci_request_regions(pdev, DRV_NAME);
@@ -5012,10 +5010,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
if (!disable_msi && pci_enable_msi(pdev) == 0) {
err = sky2_test_msi(hw);
- if (err == -EOPNOTSUPP)
+ if (err) {
pci_disable_msi(pdev);
- else if (err)
- goto err_out_free_netdev;
+ if (err != -EOPNOTSUPP)
+ goto err_out_free_netdev;
+ }
}
err = register_netdev(dev);
@@ -5063,10 +5062,10 @@ err_out_unregister_dev1:
err_out_free_dev1:
free_netdev(dev1);
err_out_unregister:
- if (hw->flags & SKY2_HW_USE_MSI)
- pci_disable_msi(pdev);
unregister_netdev(dev);
err_out_free_netdev:
+ if (hw->flags & SKY2_HW_USE_MSI)
+ pci_disable_msi(pdev);
free_netdev(dev);
err_out_free_pci:
pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
@@ -5086,7 +5085,7 @@ err_out:
return err;
}
-static void __devexit sky2_remove(struct pci_dev *pdev)
+static void sky2_remove(struct pci_dev *pdev)
{
struct sky2_hw *hw = pci_get_drvdata(pdev);
int i;
@@ -5207,7 +5206,7 @@ static struct pci_driver sky2_driver = {
.name = DRV_NAME,
.id_table = sky2_id_table,
.probe = sky2_probe,
- .remove = __devexit_p(sky2_remove),
+ .remove = sky2_remove,
.shutdown = sky2_shutdown,
.driver.pm = SKY2_PM_OPS,
};
diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig
index d8099a7903d3..bcdbc14aeff0 100644
--- a/drivers/net/ethernet/mellanox/Kconfig
+++ b/drivers/net/ethernet/mellanox/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_MELLANOX
bool "Mellanox devices"
default y
- depends on PCI && INET
+ depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 5f027f95cc84..eb520ab64014 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -4,9 +4,8 @@
config MLX4_EN
tristate "Mellanox Technologies 10Gbit Ethernet support"
- depends on PCI && INET
+ depends on PCI
select MLX4_CORE
- select INET_LRO
---help---
This driver supports Mellanox Technologies ConnectX Ethernet
devices.
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 9d0b88eea02b..03447dad07e9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -43,6 +43,34 @@
#define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)
#define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff)
+static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_cq[i].moder_cnt = priv->tx_frames;
+ priv->tx_cq[i].moder_time = priv->tx_usecs;
+ err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]);
+ if (err)
+ return err;
+ }
+
+ if (priv->adaptive_rx_coal)
+ return 0;
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_cq[i].moder_cnt = priv->rx_frames;
+ priv->rx_cq[i].moder_time = priv->rx_usecs;
+ priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+ err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
+ if (err)
+ return err;
+ }
+
+ return err;
+}
+
static void
mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
@@ -381,7 +409,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- int err, i;
priv->rx_frames = (coal->rx_max_coalesced_frames ==
MLX4_EN_AUTO_CONF) ?
@@ -397,14 +424,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
coal->tx_max_coalesced_frames != priv->tx_frames) {
priv->tx_usecs = coal->tx_coalesce_usecs;
priv->tx_frames = coal->tx_max_coalesced_frames;
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_cq[i].moder_cnt = priv->tx_frames;
- priv->tx_cq[i].moder_time = priv->tx_usecs;
- if (mlx4_en_set_cq_moder(priv, &priv->tx_cq[i])) {
- en_warn(priv, "Failed changing moderation "
- "for TX cq %d\n", i);
- }
- }
}
/* Set adaptive coalescing params */
@@ -414,18 +433,8 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
priv->sample_interval = coal->rate_sample_interval;
priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
- if (priv->adaptive_rx_coal)
- return 0;
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i].moder_cnt = priv->rx_frames;
- priv->rx_cq[i].moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
- if (err)
- return err;
- }
- return 0;
+ return mlx4_en_moderation_update(priv);
}
static int mlx4_en_set_pauseparam(struct net_device *dev,
@@ -466,7 +475,6 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
u32 rx_size, tx_size;
int port_up = 0;
int err = 0;
- int i;
if (param->rx_jumbo_pending || param->rx_mini_pending)
return -EINVAL;
@@ -505,14 +513,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
en_err(priv, "Failed starting port\n");
}
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i].moder_cnt = priv->rx_frames;
- priv->rx_cq[i].moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
- if (err)
- goto out;
- }
+ err = mlx4_en_moderation_update(priv);
out:
mutex_unlock(&mdev->state_lock);
@@ -612,13 +613,17 @@ static int mlx4_en_validate_flow(struct net_device *dev,
struct ethtool_usrip4_spec *l3_mask;
struct ethtool_tcpip4_spec *l4_mask;
struct ethhdr *eth_mask;
- u64 full_mac = ~0ull;
- u64 zero_mac = 0;
if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)
return -EINVAL;
- switch (cmd->fs.flow_type & ~FLOW_EXT) {
+ if (cmd->fs.flow_type & FLOW_MAC_EXT) {
+ /* dest mac mask must be ff:ff:ff:ff:ff:ff */
+ if (!is_broadcast_ether_addr(cmd->fs.m_ext.h_dest))
+ return -EINVAL;
+ }
+
+ switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
case TCP_V4_FLOW:
case UDP_V4_FLOW:
if (cmd->fs.m_u.tcp_ip4_spec.tos)
@@ -643,11 +648,11 @@ static int mlx4_en_validate_flow(struct net_device *dev,
case ETHER_FLOW:
eth_mask = &cmd->fs.m_u.ether_spec;
/* source mac mask must not be set */
- if (memcmp(eth_mask->h_source, &zero_mac, ETH_ALEN))
+ if (!is_zero_ether_addr(eth_mask->h_source))
return -EINVAL;
/* dest mac mask must be ff:ff:ff:ff:ff:ff */
- if (memcmp(eth_mask->h_dest, &full_mac, ETH_ALEN))
+ if (!is_broadcast_ether_addr(eth_mask->h_dest))
return -EINVAL;
if (!all_zeros_or_all_ones(eth_mask->h_proto))
@@ -746,7 +751,6 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
struct list_head *rule_list_h)
{
int err;
- u64 mac;
__be64 be_mac;
struct ethhdr *eth_spec;
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -761,12 +765,16 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
if (!spec_l2)
return -ENOMEM;
- mac = priv->mac & MLX4_MAC_MASK;
- be_mac = cpu_to_be64(mac << 16);
+ if (cmd->fs.flow_type & FLOW_MAC_EXT) {
+ memcpy(&be_mac, cmd->fs.h_ext.h_dest, ETH_ALEN);
+ } else {
+ u64 mac = priv->mac & MLX4_MAC_MASK;
+ be_mac = cpu_to_be64(mac << 16);
+ }
spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH;
memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN);
- if ((cmd->fs.flow_type & ~FLOW_EXT) != ETHER_FLOW)
+ if ((cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) != ETHER_FLOW)
memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN);
if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) {
@@ -776,7 +784,7 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
list_add_tail(&spec_l2->list, rule_list_h);
- switch (cmd->fs.flow_type & ~FLOW_EXT) {
+ switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
case ETHER_FLOW:
eth_spec = &cmd->fs.h_u.ether_spec;
memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN);
@@ -998,6 +1006,73 @@ static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return err;
}
+static void mlx4_en_get_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ memset(channel, 0, sizeof(*channel));
+
+ channel->max_rx = MAX_RX_RINGS;
+ channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
+
+ channel->rx_count = priv->rx_ring_num;
+ channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
+}
+
+static int mlx4_en_set_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up;
+ int err = 0;
+
+ if (channel->other_count || channel->combined_count ||
+ channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
+ channel->rx_count > MAX_RX_RINGS ||
+ !channel->tx_count || !channel->rx_count)
+ return -EINVAL;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+
+ mlx4_en_free_resources(priv);
+
+ priv->num_tx_rings_p_up = channel->tx_count;
+ priv->tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
+ priv->rx_ring_num = channel->rx_count;
+
+ err = mlx4_en_alloc_resources(priv);
+ if (err) {
+ en_err(priv, "Failed reallocating port resources\n");
+ goto out;
+ }
+
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+ netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
+
+ mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
+
+ en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
+ en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
+
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+ }
+
+ err = mlx4_en_moderation_update(priv);
+
+out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
@@ -1022,6 +1097,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
.get_rxfh_indir = mlx4_en_get_rxfh_indir,
.set_rxfh_indir = mlx4_en_set_rxfh_indir,
+ .get_channels = mlx4_en_get_channels,
+ .set_channels = mlx4_en_set_channels,
};
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a52922ed85c1..3a2b8c65642d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -250,7 +250,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
min_t(int,
dev->caps.num_comp_vectors,
- MAX_RX_RINGS)));
+ DEF_RX_RINGS)));
} else {
mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
min_t(int, dev->caps.comp_pool/
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index edd9cb8d3e1d..7d1287f81a31 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -47,11 +47,11 @@
#include "mlx4_en.h"
#include "en_port.h"
-static int mlx4_en_setup_tc(struct net_device *dev, u8 up)
+int mlx4_en_setup_tc(struct net_device *dev, u8 up)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int i;
- unsigned int q, offset = 0;
+ unsigned int offset = 0;
if (up && up != MLX4_EN_NUM_UP)
return -EINVAL;
@@ -59,10 +59,9 @@ static int mlx4_en_setup_tc(struct net_device *dev, u8 up)
netdev_set_num_tc(dev, up);
/* Partition Tx queues evenly amongst UP's */
- q = priv->tx_ring_num / up;
for (i = 0; i < up; i++) {
- netdev_set_tc_queue(dev, i, q, offset);
- offset += q;
+ netdev_set_tc_queue(dev, i, priv->num_tx_rings_p_up, offset);
+ offset += priv->num_tx_rings_p_up;
}
return 0;
@@ -870,7 +869,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
/* If we haven't received a specific coalescing setting
* (module param), we set the moderation parameters as follows:
* - moder_cnt is set to the number of mtu sized packets to
- * satisfy our coelsing target.
+ * satisfy our coalescing target.
* - moder_time is set to a fixed value.
*/
priv->rx_frames = MLX4_EN_RX_COAL_TARGET;
@@ -1114,7 +1113,7 @@ int mlx4_en_start_port(struct net_device *dev)
/* Configure ring */
tx_ring = &priv->tx_ring[i];
err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
- i / priv->mdev->profile.num_tx_rings_p_up);
+ i / priv->num_tx_rings_p_up);
if (err) {
en_err(priv, "Failed allocating Tx ring\n");
mlx4_en_deactivate_cq(priv, cq);
@@ -1564,10 +1563,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
int err;
dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
- prof->tx_ring_num, prof->rx_ring_num);
+ MAX_TX_RINGS, MAX_RX_RINGS);
if (dev == NULL)
return -ENOMEM;
+ netif_set_real_num_tx_queues(dev, prof->tx_ring_num);
+ netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
+
SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
dev->dev_id = port - 1;
@@ -1586,15 +1588,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
priv->flags = prof->flags;
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
MLX4_WQE_CTRL_SOLICITED);
+ priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
priv->tx_ring_num = prof->tx_ring_num;
- priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) *
- priv->tx_ring_num, GFP_KERNEL);
+
+ priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) * MAX_TX_RINGS,
+ GFP_KERNEL);
if (!priv->tx_ring) {
err = -ENOMEM;
goto out;
}
- priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * priv->tx_ring_num,
- GFP_KERNEL);
+ priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * MAX_RX_RINGS,
+ GFP_KERNEL);
if (!priv->tx_cq) {
err = -ENOMEM;
goto out;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 5aba5ecdf1e2..f76c9671f362 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -630,7 +630,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
(cqe->checksum == cpu_to_be16(0xffff))) {
ring->csum_ok++;
- /* This packet is eligible for LRO if it is:
+ /* This packet is eligible for GRO if it is:
* - DIX Ethernet (type interpretation)
* - TCP/IP (v4)
* - without IP options
@@ -667,7 +667,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
goto next;
}
- /* LRO not possible, complete processing here */
+ /* GRO not possible, complete processing here */
ip_summed = CHECKSUM_UNNECESSARY;
} else {
ip_summed = CHECKSUM_NONE;
@@ -710,11 +710,8 @@ next:
++cq->mcq.cons_index;
index = (cq->mcq.cons_index) & ring->size_mask;
cqe = &cq->buf[index];
- if (++polled == budget) {
- /* We are here because we reached the NAPI budget -
- * flush only pending LRO sessions */
+ if (++polled == budget)
goto out;
- }
}
out:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index b35094c590ba..1f571d009155 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -523,7 +523,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- u16 rings_p_up = priv->mdev->profile.num_tx_rings_p_up;
+ u16 rings_p_up = priv->num_tx_rings_p_up;
u8 up = 0;
if (dev->num_tc)
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index b84a88bc44dc..c48cf6f6529c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -1267,7 +1267,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
/* Temporary use polling for command completions */
mlx4_cmd_use_polling(dev);
- /* Map the new eq to handle all asyncronous events */
+ /* Map the new eq to handle all asynchronous events */
err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
priv->eq_table.eq[i].eqn);
if (err) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 2aa80afd98d2..200cc0ec8052 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
#define HCA_GLOBAL_CAP_MASK 0
#define PF_CONTEXT_BEHAVIOUR_MASK 0
-static char mlx4_version[] __devinitdata =
+static char mlx4_version[] =
DRV_NAME ": Mellanox ConnectX core driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -2224,8 +2224,7 @@ err_disable_pdev:
return err;
}
-static int __devinit mlx4_init_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
printk_once(KERN_INFO "%s", mlx4_version);
@@ -2391,7 +2390,7 @@ static struct pci_driver mlx4_driver = {
.name = DRV_NAME,
.id_table = mlx4_pci_table,
.probe = mlx4_init_one,
- .remove = __devexit_p(mlx4_remove_one),
+ .remove = mlx4_remove_one,
.err_handler = &mlx4_err_handler,
};
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 9d27e42264e2..334ec483480b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -67,7 +67,8 @@
#define MLX4_EN_PAGE_SHIFT 12
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_RX_RINGS 16
+#define DEF_RX_RINGS 16
+#define MAX_RX_RINGS 128
#define MIN_RX_RINGS 4
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
@@ -95,8 +96,6 @@
#define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384)
#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE)
-#define MLX4_EN_MAX_LRO_DESCRIPTORS 32
-
/* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU
* and 4K allocations) */
enum {
@@ -120,13 +119,15 @@ enum {
#define MLX4_EN_NUM_UP 8
#define MLX4_EN_DEF_TX_RING_SIZE 512
#define MLX4_EN_DEF_RX_RING_SIZE 1024
+#define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \
+ MLX4_EN_NUM_UP)
/* Target number of packets to coalesce with interrupt moderation */
#define MLX4_EN_RX_COAL_TARGET 44
#define MLX4_EN_RX_COAL_TIME 0x10
#define MLX4_EN_TX_COAL_PKTS 16
-#define MLX4_EN_TX_COAL_TIME 0x80
+#define MLX4_EN_TX_COAL_TIME 0x10
#define MLX4_EN_RX_RATE_LOW 400000
#define MLX4_EN_RX_COAL_TIME_LOW 0
@@ -290,21 +291,6 @@ struct mlx4_en_rx_ring {
unsigned long csum_none;
};
-
-static inline int mlx4_en_can_lro(__be16 status)
-{
- return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPV4F |
- MLX4_CQE_STATUS_IPV6 |
- MLX4_CQE_STATUS_IPV4OPT |
- MLX4_CQE_STATUS_TCP |
- MLX4_CQE_STATUS_UDP |
- MLX4_CQE_STATUS_IPOK)) ==
- cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPOK |
- MLX4_CQE_STATUS_TCP);
-}
-
struct mlx4_en_cq {
struct mlx4_cq mcq;
struct mlx4_hwq_resources wqres;
@@ -493,6 +479,7 @@ struct mlx4_en_priv {
u32 flags;
#define MLX4_EN_FLAG_PROMISC 0x1
#define MLX4_EN_FLAG_MC_PROMISC 0x2
+ u8 num_tx_rings_p_up;
u32 tx_ring_num;
u32 rx_ring_num;
u32 rx_skb_size;
@@ -613,6 +600,8 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops;
#endif
+int mlx4_en_setup_tc(struct net_device *dev, u8 up);
+
#ifdef CONFIG_RFS_ACCEL
void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *rx_ring);
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index dccae1d1743a..07a6ebc47c92 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -1249,9 +1249,6 @@ ks8695_open(struct net_device *ndev)
struct ks8695_priv *ksp = netdev_priv(ndev);
int ret;
- if (!is_valid_ether_addr(ndev->dev_addr))
- return -EADDRNOTAVAIL;
-
ks8695_reset(ksp);
ks8695_update_mac(ksp);
@@ -1277,7 +1274,7 @@ ks8695_open(struct net_device *ndev)
* This initialises the LAN switch in the KS8695 to a known-good
* set of defaults.
*/
-static void __devinit
+static void
ks8695_init_switch(struct ks8695_priv *ksp)
{
u32 ctrl;
@@ -1305,7 +1302,7 @@ ks8695_init_switch(struct ks8695_priv *ksp)
* This initialises a KS8695's WAN phy to sensible values for
* autonegotiation etc.
*/
-static void __devinit
+static void
ks8695_init_wan_phy(struct ks8695_priv *ksp)
{
u32 ctrl;
@@ -1349,7 +1346,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
* wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
* port.
*/
-static int __devinit
+static int
ks8695_probe(struct platform_device *pdev)
{
struct ks8695_priv *ksp;
@@ -1597,7 +1594,7 @@ ks8695_drv_resume(struct platform_device *pdev)
*
* This unregisters and releases a KS8695 ethernet device.
*/
-static int __devexit
+static int
ks8695_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1620,7 +1617,7 @@ static struct platform_driver ks8695_driver = {
.owner = THIS_MODULE,
},
.probe = ks8695_probe,
- .remove = __devexit_p(ks8695_drv_remove),
+ .remove = ks8695_drv_remove,
.suspend = ks8695_drv_suspend,
.resume = ks8695_drv_resume,
};
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 24fb049ac2f2..b71eb39ab448 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -1141,7 +1141,7 @@ static const struct ethtool_ops ks8842_ethtool_ops = {
.get_link = ethtool_op_get_link,
};
-static int __devinit ks8842_probe(struct platform_device *pdev)
+static int ks8842_probe(struct platform_device *pdev)
{
int err = -ENOMEM;
struct resource *iomem;
@@ -1240,7 +1240,7 @@ err_mem_region:
return err;
}
-static int __devexit ks8842_remove(struct platform_device *pdev)
+static int ks8842_remove(struct platform_device *pdev)
{
struct net_device *netdev = platform_get_drvdata(pdev);
struct ks8842_adapter *adapter = netdev_priv(netdev);
@@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = {
.owner = THIS_MODULE,
},
.probe = ks8842_probe,
- .remove = __devexit_p(ks8842_remove),
+ .remove = ks8842_remove,
};
module_platform_driver(ks8842_platform_driver);
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 1540ebeb8669..286816a4e783 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1415,7 +1415,7 @@ static int ks8851_resume(struct spi_device *spi)
#define ks8851_resume NULL
#endif
-static int __devinit ks8851_probe(struct spi_device *spi)
+static int ks8851_probe(struct spi_device *spi)
{
struct net_device *ndev;
struct ks8851_net *ks;
@@ -1534,7 +1534,7 @@ err_irq:
return ret;
}
-static int __devexit ks8851_remove(struct spi_device *spi)
+static int ks8851_remove(struct spi_device *spi)
{
struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
@@ -1554,7 +1554,7 @@ static struct spi_driver ks8851_driver = {
.owner = THIS_MODULE,
},
.probe = ks8851_probe,
- .remove = __devexit_p(ks8851_remove),
+ .remove = ks8851_remove,
.suspend = ks8851_suspend,
.resume = ks8851_resume,
};
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index 38529edfe350..ef8f9f92e547 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -1506,7 +1506,7 @@ static int ks_hw_init(struct ks_net *ks)
}
-static int __devinit ks8851_probe(struct platform_device *pdev)
+static int ks8851_probe(struct platform_device *pdev)
{
int err = -ENOMEM;
struct resource *io_d, *io_c;
@@ -1641,7 +1641,7 @@ err_mem_region:
return err;
}
-static int __devexit ks8851_remove(struct platform_device *pdev)
+static int ks8851_remove(struct platform_device *pdev)
{
struct net_device *netdev = platform_get_drvdata(pdev);
struct ks_net *ks = netdev_priv(netdev);
@@ -1663,7 +1663,7 @@ static struct platform_driver ks8851_platform_driver = {
.owner = THIS_MODULE,
},
.probe = ks8851_probe,
- .remove = __devexit_p(ks8851_remove),
+ .remove = ks8851_remove,
};
module_platform_driver(ks8851_platform_driver);
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 69e01977a1dd..83f0ea929d3d 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -1487,7 +1487,7 @@ struct dev_priv {
#define DRV_VERSION "1.0.0"
#define DRV_RELDATE "Feb 8, 2010"
-static char version[] __devinitdata =
+static char version[] =
"Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")";
static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 };
@@ -6769,7 +6769,7 @@ static int stp;
/*
* This enables fast aging in the KSZ8842 switch. Not sure what situation
* needs that. However, fast aging is used to flush the dynamic MAC table when
- * STP suport is enabled.
+ * STP support is enabled.
*/
static int fast_aging;
@@ -6919,8 +6919,7 @@ static void read_other_addr(struct ksz_hw *hw)
#define PCI_VENDOR_ID_MICREL_KS 0x16c6
#endif
-static int __devinit pcidev_init(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *dev;
struct dev_priv *priv;
@@ -7243,18 +7242,7 @@ static struct pci_driver pci_device_driver = {
.remove = pcidev_exit
};
-static int __init ksz884x_init_module(void)
-{
- return pci_register_driver(&pci_device_driver);
-}
-
-static void __exit ksz884x_cleanup_module(void)
-{
- pci_unregister_driver(&pci_device_driver);
-}
-
-module_init(ksz884x_init_module);
-module_exit(ksz884x_cleanup_module);
+module_pci_driver(pci_device_driver);
MODULE_DESCRIPTION("KSZ8841/2 PCI network driver");
MODULE_AUTHOR("Tristram Ha <Tristram.Ha@micrel.com>");
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 6118bdad244f..a99456c3dd87 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1541,7 +1541,7 @@ static const struct net_device_ops enc28j60_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit enc28j60_probe(struct spi_device *spi)
+static int enc28j60_probe(struct spi_device *spi)
{
struct net_device *dev;
struct enc28j60_net *priv;
@@ -1617,7 +1617,7 @@ error_alloc:
return ret;
}
-static int __devexit enc28j60_remove(struct spi_device *spi)
+static int enc28j60_remove(struct spi_device *spi)
{
struct enc28j60_net *priv = dev_get_drvdata(&spi->dev);
@@ -1637,7 +1637,7 @@ static struct spi_driver enc28j60_driver = {
.owner = THIS_MODULE,
},
.probe = enc28j60_probe,
- .remove = __devexit_p(enc28j60_remove),
+ .remove = enc28j60_remove,
};
static int __init enc28j60_init(void)
diff --git a/drivers/net/ethernet/myricom/Kconfig b/drivers/net/ethernet/myricom/Kconfig
index 540f0c6fc160..3932d081fa21 100644
--- a/drivers/net/ethernet/myricom/Kconfig
+++ b/drivers/net/ethernet/myricom/Kconfig
@@ -23,7 +23,6 @@ config MYRI10GE
depends on PCI && INET
select FW_LOADER
select CRC32
- select INET_LRO
---help---
This driver supports Myricom Myri-10G Dual Protocol interface in
Ethernet mode. If the eeprom on your board is not recent enough,
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 83516e3369c9..f8408d6e961c 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -50,7 +50,6 @@
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
#include <linux/dca.h>
#include <linux/ip.h>
#include <linux/inet.h>
@@ -96,8 +95,6 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MYRI10GE_EEPROM_STRINGS_SIZE 256
#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
-#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
-#define MYRI10GE_LRO_MAX_PKTS 64
#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
@@ -165,8 +162,6 @@ struct myri10ge_rx_done {
dma_addr_t bus;
int cnt;
int idx;
- struct net_lro_mgr lro_mgr;
- struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
};
struct myri10ge_slice_netstats {
@@ -338,11 +333,6 @@ static int myri10ge_debug = -1; /* defaults above */
module_param(myri10ge_debug, int, 0);
MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
-static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
-module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_lro_max_pkts,
- "Number of LRO packets to be aggregated");
-
static int myri10ge_fill_thresh = 256;
module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed");
@@ -1197,36 +1187,6 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
}
}
-static inline void
-myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
- struct skb_frag_struct *rx_frags, int len, int hlen)
-{
- struct skb_frag_struct *skb_frags;
-
- skb->len = skb->data_len = len;
- /* attach the page(s) */
-
- skb_frags = skb_shinfo(skb)->frags;
- while (len > 0) {
- memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
- len -= skb_frag_size(rx_frags);
- skb_frags++;
- rx_frags++;
- skb_shinfo(skb)->nr_frags++;
- }
-
- /* pskb_may_pull is not available in irq context, but
- * skb_pull() (for ether_pad and eth_type_trans()) requires
- * the beginning of the packet in skb_headlen(), move it
- * manually */
- skb_copy_to_linear_data(skb, va, hlen);
- skb_shinfo(skb)->frags[0].page_offset += hlen;
- skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hlen);
- skb->data_len -= hlen;
- skb->tail += hlen;
- skb_pull(skb, MXGEFW_PAD);
-}
-
static void
myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
int bytes, int watchdog)
@@ -1304,18 +1264,50 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
}
}
-#define MYRI10GE_HLEN 64 /* The number of bytes to copy from a
- * page into an skb */
+/*
+ * GRO does not support acceleration of tagged vlan frames, and
+ * this NIC does not support vlan tag offload, so we must pop
+ * the tag ourselves to be able to achieve GRO performance that
+ * is comparable to LRO.
+ */
+
+static inline void
+myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb)
+{
+ u8 *va;
+ struct vlan_ethhdr *veh;
+ struct skb_frag_struct *frag;
+ __wsum vsum;
+
+ va = addr;
+ va += MXGEFW_PAD;
+ veh = (struct vlan_ethhdr *)va;
+ if ((dev->features & NETIF_F_HW_VLAN_RX) == NETIF_F_HW_VLAN_RX &&
+ veh->h_vlan_proto == htons(ETH_P_8021Q)) {
+ /* fixup csum if needed */
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ vsum = csum_partial(va + ETH_HLEN, VLAN_HLEN, 0);
+ skb->csum = csum_sub(skb->csum, vsum);
+ }
+ /* pop tag */
+ __vlan_hwaccel_put_tag(skb, ntohs(veh->h_vlan_TCI));
+ memmove(va + VLAN_HLEN, va, 2 * ETH_ALEN);
+ skb->len -= VLAN_HLEN;
+ skb->data_len -= VLAN_HLEN;
+ frag = skb_shinfo(skb)->frags;
+ frag->page_offset += VLAN_HLEN;
+ skb_frag_size_set(frag, skb_frag_size(frag) - VLAN_HLEN);
+ }
+}
static inline int
-myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
- bool lro_enabled)
+myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
{
struct myri10ge_priv *mgp = ss->mgp;
struct sk_buff *skb;
- struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
+ struct skb_frag_struct *rx_frags;
struct myri10ge_rx_buf *rx;
- int i, idx, hlen, remainder, bytes;
+ int i, idx, remainder, bytes;
struct pci_dev *pdev = mgp->pdev;
struct net_device *dev = mgp->dev;
u8 *va;
@@ -1332,67 +1324,48 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
idx = rx->cnt & rx->mask;
va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
prefetch(va);
+
+ skb = napi_get_frags(&ss->napi);
+ if (unlikely(skb == NULL)) {
+ ss->stats.rx_dropped++;
+ for (i = 0, remainder = len; remainder > 0; i++) {
+ myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
+ put_page(rx->info[idx].page);
+ rx->cnt++;
+ idx = rx->cnt & rx->mask;
+ remainder -= MYRI10GE_ALLOC_SIZE;
+ }
+ return 0;
+ }
+ rx_frags = skb_shinfo(skb)->frags;
/* Fill skb_frag_struct(s) with data from our receive */
for (i = 0, remainder = len; remainder > 0; i++) {
myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
- __skb_frag_set_page(&rx_frags[i], rx->info[idx].page);
- rx_frags[i].page_offset = rx->info[idx].page_offset;
- if (remainder < MYRI10GE_ALLOC_SIZE)
- skb_frag_size_set(&rx_frags[i], remainder);
- else
- skb_frag_size_set(&rx_frags[i], MYRI10GE_ALLOC_SIZE);
+ skb_fill_page_desc(skb, i, rx->info[idx].page,
+ rx->info[idx].page_offset,
+ remainder < MYRI10GE_ALLOC_SIZE ?
+ remainder : MYRI10GE_ALLOC_SIZE);
rx->cnt++;
idx = rx->cnt & rx->mask;
remainder -= MYRI10GE_ALLOC_SIZE;
}
- if (lro_enabled) {
- rx_frags[0].page_offset += MXGEFW_PAD;
- skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD);
- len -= MXGEFW_PAD;
- lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags,
- /* opaque, will come back in get_frag_header */
- len, len,
- (void *)(__force unsigned long)csum, csum);
-
- return 1;
- }
-
- hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
-
- /* allocate an skb to attach the page(s) to. This is done
- * after trying LRO, so as to avoid skb allocation overheads */
-
- skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
- if (unlikely(skb == NULL)) {
- ss->stats.rx_dropped++;
- do {
- i--;
- __skb_frag_unref(&rx_frags[i]);
- } while (i != 0);
- return 0;
- }
+ /* remove padding */
+ rx_frags[0].page_offset += MXGEFW_PAD;
+ rx_frags[0].size -= MXGEFW_PAD;
+ len -= MXGEFW_PAD;
- /* Attach the pages to the skb, and trim off any padding */
- myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
- if (skb_frag_size(&skb_shinfo(skb)->frags[0]) <= 0) {
- skb_frag_unref(skb, 0);
- skb_shinfo(skb)->nr_frags = 0;
- } else {
- skb->truesize += bytes * skb_shinfo(skb)->nr_frags;
+ skb->len = len;
+ skb->data_len = len;
+ skb->truesize += len;
+ if (dev->features & NETIF_F_RXCSUM) {
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = csum;
}
- skb->protocol = eth_type_trans(skb, dev);
+ myri10ge_vlan_rx(mgp->dev, va, skb);
skb_record_rx_queue(skb, ss - &mgp->ss[0]);
- if (dev->features & NETIF_F_RXCSUM) {
- if ((skb->protocol == htons(ETH_P_IP)) ||
- (skb->protocol == htons(ETH_P_IPV6))) {
- skb->csum = csum;
- skb->ip_summed = CHECKSUM_COMPLETE;
- } else
- myri10ge_vlan_ip_csum(skb, csum);
- }
- netif_receive_skb(skb);
+ napi_gro_frags(&ss->napi);
return 1;
}
@@ -1480,18 +1453,11 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
u16 length;
__wsum checksum;
- /*
- * Prevent compiler from generating more than one ->features memory
- * access to avoid theoretical race condition with functions that
- * change NETIF_F_LRO flag at runtime.
- */
- bool lro_enabled = !!(ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO);
-
while (rx_done->entry[idx].length != 0 && work_done < budget) {
length = ntohs(rx_done->entry[idx].length);
rx_done->entry[idx].length = 0;
checksum = csum_unfold(rx_done->entry[idx].checksum);
- rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
+ rx_ok = myri10ge_rx_done(ss, length, checksum);
rx_packets += rx_ok;
rx_bytes += rx_ok * (unsigned long)length;
cnt++;
@@ -1503,9 +1469,6 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
ss->stats.rx_packets += rx_packets;
ss->stats.rx_bytes += rx_bytes;
- if (lro_enabled)
- lro_flush_all(&rx_done->lro_mgr);
-
/* restock receive rings if needed */
if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh)
myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
@@ -1779,7 +1742,6 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
"tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
"rx_small_cnt", "rx_big_cnt",
"wake_queue", "stop_queue", "tx_linearized",
- "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
};
#define MYRI10GE_NET_STATS_LEN 21
@@ -1880,14 +1842,6 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
data[i++] = (unsigned int)ss->tx.wake_queue;
data[i++] = (unsigned int)ss->tx.stop_queue;
data[i++] = (unsigned int)ss->tx.linearized;
- data[i++] = ss->rx_done.lro_mgr.stats.aggregated;
- data[i++] = ss->rx_done.lro_mgr.stats.flushed;
- if (ss->rx_done.lro_mgr.stats.flushed)
- data[i++] = ss->rx_done.lro_mgr.stats.aggregated /
- ss->rx_done.lro_mgr.stats.flushed;
- else
- data[i++] = 0;
- data[i++] = ss->rx_done.lro_mgr.stats.no_desc;
}
}
@@ -1931,7 +1885,7 @@ static int myri10ge_led(struct myri10ge_priv *mgp, int on)
}
if (!on)
pattern = swab32(readl(mgp->sram + pattern_off + 4));
- writel(htonl(pattern), mgp->sram + pattern_off);
+ writel(swab32(pattern), mgp->sram + pattern_off);
return 0;
}
@@ -2271,67 +2225,6 @@ static void myri10ge_free_irq(struct myri10ge_priv *mgp)
pci_disable_msix(pdev);
}
-static int
-myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
- void **ip_hdr, void **tcpudp_hdr,
- u64 * hdr_flags, void *priv)
-{
- struct ethhdr *eh;
- struct vlan_ethhdr *veh;
- struct iphdr *iph;
- u8 *va = skb_frag_address(frag);
- unsigned long ll_hlen;
- /* passed opaque through lro_receive_frags() */
- __wsum csum = (__force __wsum) (unsigned long)priv;
-
- /* find the mac header, aborting if not IPv4 */
-
- eh = (struct ethhdr *)va;
- *mac_hdr = eh;
- ll_hlen = ETH_HLEN;
- if (eh->h_proto != htons(ETH_P_IP)) {
- if (eh->h_proto == htons(ETH_P_8021Q)) {
- veh = (struct vlan_ethhdr *)va;
- if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
- return -1;
-
- ll_hlen += VLAN_HLEN;
-
- /*
- * HW checksum starts ETH_HLEN bytes into
- * frame, so we must subtract off the VLAN
- * header's checksum before csum can be used
- */
- csum = csum_sub(csum, csum_partial(va + ETH_HLEN,
- VLAN_HLEN, 0));
- } else {
- return -1;
- }
- }
- *hdr_flags = LRO_IPV4;
-
- iph = (struct iphdr *)(va + ll_hlen);
- *ip_hdr = iph;
- if (iph->protocol != IPPROTO_TCP)
- return -1;
- if (ip_is_fragment(iph))
- return -1;
- *hdr_flags |= LRO_TCP;
- *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
-
- /* verify the IP checksum */
- if (unlikely(ip_fast_csum((u8 *) iph, iph->ihl)))
- return -1;
-
- /* verify the checksum */
- if (unlikely(csum_tcpudp_magic(iph->saddr, iph->daddr,
- ntohs(iph->tot_len) - (iph->ihl << 2),
- IPPROTO_TCP, csum)))
- return -1;
-
- return 0;
-}
-
static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
{
struct myri10ge_cmd cmd;
@@ -2401,8 +2294,7 @@ static int myri10ge_open(struct net_device *dev)
struct myri10ge_priv *mgp = netdev_priv(dev);
struct myri10ge_cmd cmd;
int i, status, big_pow2, slice;
- u8 *itable;
- struct net_lro_mgr *lro_mgr;
+ u8 __iomem *itable;
if (mgp->running != MYRI10GE_ETH_STOPPED)
return -EBUSY;
@@ -2513,19 +2405,6 @@ static int myri10ge_open(struct net_device *dev)
goto abort_with_rings;
}
- lro_mgr = &ss->rx_done.lro_mgr;
- lro_mgr->dev = dev;
- lro_mgr->features = LRO_F_NAPI;
- lro_mgr->ip_summed = CHECKSUM_COMPLETE;
- lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
- lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
- lro_mgr->lro_arr = ss->rx_done.lro_desc;
- lro_mgr->get_frag_header = myri10ge_get_frag_header;
- lro_mgr->max_aggr = myri10ge_lro_max_pkts;
- lro_mgr->frag_align_pad = 2;
- if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
- lro_mgr->max_aggr = MAX_SKB_FRAGS;
-
/* must happen prior to any irq */
napi_enable(&(ss)->napi);
}
@@ -2878,7 +2757,7 @@ again:
flags_next |= next_is_first *
MXGEFW_FLAGS_FIRST;
rdma_count |= -(chop | next_is_first);
- rdma_count += chop & !next_is_first;
+ rdma_count += chop & ~next_is_first;
} else if (likely(cum_len_next >= 0)) { /* header ends */
int small;
@@ -3143,15 +3022,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
return 0;
}
-static netdev_features_t myri10ge_fix_features(struct net_device *dev,
- netdev_features_t features)
-{
- if (!(features & NETIF_F_RXCSUM))
- features &= ~NETIF_F_LRO;
-
- return features;
-}
-
static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
{
struct myri10ge_priv *mgp = netdev_priv(dev);
@@ -3878,7 +3748,6 @@ static const struct net_device_ops myri10ge_netdev_ops = {
.ndo_get_stats64 = myri10ge_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = myri10ge_change_mtu,
- .ndo_fix_features = myri10ge_fix_features,
.ndo_set_rx_mode = myri10ge_set_multicast_list,
.ndo_set_mac_address = myri10ge_set_mac_address,
};
@@ -3967,9 +3836,9 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto abort_with_mtrr;
}
hdr_offset =
- ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
+ swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs);
- mgp->sram_size = ntohl(__raw_readl(mgp->sram + ss_offset));
+ mgp->sram_size = swab32(readl(mgp->sram + ss_offset));
if (mgp->sram_size > mgp->board_span ||
mgp->sram_size <= MYRI10GE_FW_OFFSET) {
dev_err(&pdev->dev,
@@ -4018,7 +3887,11 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &myri10ge_netdev_ops;
netdev->mtu = myri10ge_initial_mtu;
- netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM;
+ netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
+
+ /* fake NETIF_F_HW_VLAN_RX for good GRO performance */
+ netdev->hw_features |= NETIF_F_HW_VLAN_RX;
+
netdev->features = netdev->hw_features;
if (dac_enabled)
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
index 7ec4b864a550..75ec5e7cf50d 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
@@ -27,7 +27,7 @@ struct mcp_gen_header {
*
* Fields below this comment are extensions added in later versions
* of this struct, drivers should compare the header_length against
- * offsetof(field) to check wether a given MCP implements them.
+ * offsetof(field) to check whether a given MCP implements them.
*
* Never remove any field. Keep everything naturally align.
*/
diff --git a/drivers/net/ethernet/natsemi/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c
index 3f94ddbf4dc0..923e640d604c 100644
--- a/drivers/net/ethernet/natsemi/ibmlana.c
+++ b/drivers/net/ethernet/natsemi/ibmlana.c
@@ -900,7 +900,7 @@ static short ibmlana_adapter_ids[] __initdata = {
0x0000
};
-static char *ibmlana_adapter_names[] __devinitdata = {
+static char *ibmlana_adapter_names[] = {
"IBM LAN Adapter/A",
NULL
};
@@ -916,7 +916,7 @@ static const struct net_device_ops ibmlana_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit ibmlana_init_one(struct device *kdev)
+static int ibmlana_init_one(struct device *kdev)
{
struct mca_device *mdev = to_mca_device(kdev);
struct net_device *dev;
diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
index 95dd39ffb230..b0b361546365 100644
--- a/drivers/net/ethernet/natsemi/jazzsonic.c
+++ b/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -117,7 +117,7 @@ static const struct net_device_ops sonic_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit sonic_probe1(struct net_device *dev)
+static int sonic_probe1(struct net_device *dev)
{
static unsigned version_printed;
unsigned int silicon_revision;
@@ -220,7 +220,7 @@ out:
* Probe for a SONIC ethernet controller on a Mips Jazz board.
* Actually probing is superfluous but we're paranoid.
*/
-static int __devinit jazz_sonic_probe(struct platform_device *pdev)
+static int jazz_sonic_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sonic_local *lp;
@@ -270,7 +270,7 @@ MODULE_ALIAS("platform:jazzsonic");
#include "sonic.c"
-static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
+static int jazz_sonic_device_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sonic_local* lp = netdev_priv(dev);
@@ -286,7 +286,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
static struct platform_driver jazz_sonic_driver = {
.probe = jazz_sonic_probe,
- .remove = __devexit_p(jazz_sonic_device_remove),
+ .remove = jazz_sonic_device_remove,
.driver = {
.name = jazz_sonic_string,
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index b9680ba5a325..0ffde69c8d01 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -196,7 +196,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit macsonic_init(struct net_device *dev)
+static int macsonic_init(struct net_device *dev)
{
struct sonic_local* lp = netdev_priv(dev);
@@ -245,7 +245,7 @@ static int __devinit macsonic_init(struct net_device *dev)
memcmp(mac, "\x00\x80\x19", 3) && \
memcmp(mac, "\x00\x05\x02", 3))
-static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+static void mac_onboard_sonic_ethernet_addr(struct net_device *dev)
{
struct sonic_local *lp = netdev_priv(dev);
const int prom_addr = ONBOARD_SONIC_PROM_BASE;
@@ -309,7 +309,7 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
eth_hw_addr_random(dev);
}
-static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
+static int mac_onboard_sonic_probe(struct net_device *dev)
{
struct sonic_local* lp = netdev_priv(dev);
int sr;
@@ -420,9 +420,8 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
return macsonic_init(dev);
}
-static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
- unsigned long prom_addr,
- int id)
+static int mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+ unsigned long prom_addr, int id)
{
int i;
for(i = 0; i < 6; i++)
@@ -435,7 +434,7 @@ static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
return 0;
}
-static int __devinit macsonic_ident(struct nubus_dev *ndev)
+static int macsonic_ident(struct nubus_dev *ndev)
{
if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
@@ -460,7 +459,7 @@ static int __devinit macsonic_ident(struct nubus_dev *ndev)
return -1;
}
-static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
+static int mac_nubus_sonic_probe(struct net_device *dev)
{
static int slots;
struct nubus_dev* ndev = NULL;
@@ -573,7 +572,7 @@ static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
return macsonic_init(dev);
}
-static int __devinit mac_sonic_probe(struct platform_device *pdev)
+static int mac_sonic_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sonic_local *lp;
@@ -619,7 +618,7 @@ MODULE_ALIAS("platform:macsonic");
#include "sonic.c"
-static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
+static int mac_sonic_device_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sonic_local* lp = netdev_priv(dev);
@@ -634,7 +633,7 @@ static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
static struct platform_driver mac_sonic_driver = {
.probe = mac_sonic_probe,
- .remove = __devexit_p(mac_sonic_device_remove),
+ .remove = mac_sonic_device_remove,
.driver = {
.name = mac_sonic_string,
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index dbaaa99a0d43..f4ad60c97eae 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -127,7 +127,7 @@ static int full_duplex[MAX_UNITS];
#define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME " dp8381x driver, version "
DRV_VERSION ", " DRV_RELDATE "\n"
" originally by Donald Becker <becker@scyld.com>\n"
@@ -242,7 +242,7 @@ static struct {
const char *name;
unsigned long flags;
unsigned int eeprom_size;
-} natsemi_pci_info[] __devinitdata = {
+} natsemi_pci_info[] = {
{ "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
{ "NatSemi DP8381[56]", 0, 24 },
};
@@ -742,7 +742,7 @@ static void move_int_phy(struct net_device *dev, int addr)
udelay(1);
}
-static void __devinit natsemi_init_media (struct net_device *dev)
+static void natsemi_init_media(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
u32 tmp;
@@ -797,8 +797,7 @@ static const struct net_device_ops natsemi_netdev_ops = {
#endif
};
-static int __devinit natsemi_probe1 (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct netdev_private *np;
@@ -3214,7 +3213,7 @@ static int netdev_close(struct net_device *dev)
}
-static void __devexit natsemi_remove1 (struct pci_dev *pdev)
+static void natsemi_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
void __iomem * ioaddr = ns_ioaddr(dev);
@@ -3353,7 +3352,7 @@ static struct pci_driver natsemi_driver = {
.name = DRV_NAME,
.id_table = natsemi_pci_tbl,
.probe = natsemi_probe1,
- .remove = __devexit_p(natsemi_remove1),
+ .remove = natsemi_remove1,
#ifdef CONFIG_PM
.suspend = natsemi_suspend,
.resume = natsemi_resume,
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index d52728b3c436..77c070de621e 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -1941,8 +1941,8 @@ static const struct net_device_ops netdev_ops = {
.ndo_tx_timeout = ns83820_tx_timeout,
};
-static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
- const struct pci_device_id *id)
+static int ns83820_init_one(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
{
struct net_device *ndev;
struct ns83820 *dev;
@@ -2241,7 +2241,7 @@ out:
return err;
}
-static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
+static void ns83820_remove_one(struct pci_dev *pci_dev)
{
struct net_device *ndev = pci_get_drvdata(pci_dev);
struct ns83820 *dev = PRIV(ndev); /* ok even if NULL */
@@ -2272,7 +2272,7 @@ static struct pci_driver driver = {
.name = "ns83820",
.id_table = ns83820_pci_tbl,
.probe = ns83820_init_one,
- .remove = __devexit_p(ns83820_remove_one),
+ .remove = ns83820_remove_one,
#if 0 /* FIXME: implement */
.suspend = ,
.resume = ,
diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index 7dfe88398d7d..5e4748e855f6 100644
--- a/drivers/net/ethernet/natsemi/xtsonic.c
+++ b/drivers/net/ethernet/natsemi/xtsonic.c
@@ -249,7 +249,7 @@ out:
* Actually probing is superfluous but we're paranoid.
*/
-int __devinit xtsonic_probe(struct platform_device *pdev)
+int xtsonic_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sonic_local *lp;
@@ -297,7 +297,7 @@ MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)");
#include "sonic.c"
-static int __devexit xtsonic_device_remove (struct platform_device *pdev)
+static int xtsonic_device_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sonic_local *lp = netdev_priv(dev);
@@ -314,7 +314,7 @@ static int __devexit xtsonic_device_remove (struct platform_device *pdev)
static struct platform_driver xtsonic_driver = {
.probe = xtsonic_probe,
- .remove = __devexit_p(xtsonic_device_remove),
+ .remove = xtsonic_device_remove,
.driver = {
.name = xtsonic_string,
},
diff --git a/drivers/net/ethernet/neterion/Kconfig b/drivers/net/ethernet/neterion/Kconfig
index ff26b54bd3fb..87abb4f10c43 100644
--- a/drivers/net/ethernet/neterion/Kconfig
+++ b/drivers/net/ethernet/neterion/Kconfig
@@ -32,7 +32,7 @@ config S2IO
config VXGE
tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
- depends on PCI && INET
+ depends on PCI
---help---
This driver supports Exar Corp's X3100 Series 10 GbE PCIe
I/O Virtualized Server Adapter.
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index de50547c187d..7c94c089212f 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -494,7 +494,7 @@ static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
- .remove = __devexit_p(s2io_rem_nic),
+ .remove = s2io_rem_nic,
.err_handler = &s2io_err_handler,
};
@@ -1040,7 +1040,7 @@ static int s2io_verify_pci_mode(struct s2io_nic *nic)
static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
{
struct pci_dev *tdev = NULL;
- while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
+ for_each_pci_dev(tdev) {
if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) {
if (tdev->bus == s2io_pdev->bus->parent) {
pci_dev_put(tdev);
@@ -7702,7 +7702,7 @@ static const struct net_device_ops s2io_netdev_ops = {
* returns 0 on success and negative on failure.
*/
-static int __devinit
+static int
s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
{
struct s2io_nic *sp;
@@ -8200,7 +8200,7 @@ mem_alloc_failed:
* from memory.
*/
-static void __devexit s2io_rem_nic(struct pci_dev *pdev)
+static void s2io_rem_nic(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct s2io_nic *sp;
@@ -8239,7 +8239,8 @@ static int __init s2io_starter(void)
/**
* s2io_closer - Cleanup routine for the driver
- * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
+ * Description: This function is the cleanup routine for the driver. It
+ * unregisters the driver.
*/
static __exit void s2io_closer(void)
diff --git a/drivers/net/ethernet/neterion/s2io.h b/drivers/net/ethernet/neterion/s2io.h
index d5596926a1ef..d89b6ed82c51 100644
--- a/drivers/net/ethernet/neterion/s2io.h
+++ b/drivers/net/ethernet/neterion/s2io.h
@@ -1075,9 +1075,8 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
/*
* Prototype declaration.
*/
-static int __devinit s2io_init_nic(struct pci_dev *pdev,
- const struct pci_device_id *pre);
-static void __devexit s2io_rem_nic(struct pci_dev *pdev);
+static int s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre);
+static void s2io_rem_nic(struct pci_dev *pdev);
static int init_shared_mem(struct s2io_nic *sp);
static void free_shared_mem(struct s2io_nic *sp);
static int init_nic(struct s2io_nic *nic);
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c
index c2e420a84d22..fbe5363cb89c 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
@@ -993,7 +993,7 @@ exit:
* for the driver, FW version information, and the first mac address for
* each vpath
*/
-enum vxge_hw_status __devinit
+enum vxge_hw_status
vxge_hw_device_hw_info_get(void __iomem *bar0,
struct vxge_hw_device_hw_info *hw_info)
{
@@ -1310,7 +1310,7 @@ __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
* When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
* to enable the latter to perform Titan hardware initialization.
*/
-enum vxge_hw_status __devinit
+enum vxge_hw_status
vxge_hw_device_initialize(
struct __vxge_hw_device **devh,
struct vxge_hw_device_attr *attr,
@@ -2917,7 +2917,7 @@ exit:
* vxge_hw_device_config_default_get - Initialize device config with defaults.
* Initialize Titan device config with default values.
*/
-enum vxge_hw_status __devinit
+enum vxge_hw_status
vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config)
{
u32 i;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h
index 9e0c1eed5dc5..6ce4412fcc1a 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h
@@ -1846,11 +1846,11 @@ struct vxge_hw_vpath_attr {
struct vxge_hw_fifo_attr fifo_attr;
};
-enum vxge_hw_status __devinit vxge_hw_device_hw_info_get(
+enum vxge_hw_status vxge_hw_device_hw_info_get(
void __iomem *bar0,
struct vxge_hw_device_hw_info *hw_info);
-enum vxge_hw_status __devinit vxge_hw_device_config_default_get(
+enum vxge_hw_status vxge_hw_device_config_default_get(
struct vxge_hw_device_config *device_config);
/**
@@ -1877,7 +1877,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *devh);
const u8 *
vxge_hw_device_product_name_get(struct __vxge_hw_device *devh);
-enum vxge_hw_status __devinit vxge_hw_device_initialize(
+enum vxge_hw_status vxge_hw_device_initialize(
struct __vxge_hw_device **devh,
struct vxge_hw_device_attr *attr,
struct vxge_hw_device_config *device_config);
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 3e5b7509502c..7c87105ca049 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -3371,10 +3371,9 @@ static const struct net_device_ops vxge_netdev_ops = {
#endif
};
-static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
- struct vxge_config *config,
- int high_dma, int no_of_vpath,
- struct vxgedev **vdev_out)
+static int vxge_device_register(struct __vxge_hw_device *hldev,
+ struct vxge_config *config, int high_dma,
+ int no_of_vpath, struct vxgedev **vdev_out)
{
struct net_device *ndev;
enum vxge_hw_status status = VXGE_HW_OK;
@@ -3672,9 +3671,8 @@ static void verify_bandwidth(void)
/*
* Vpath configuration
*/
-static int __devinit vxge_config_vpaths(
- struct vxge_hw_device_config *device_config,
- u64 vpath_mask, struct vxge_config *config_param)
+static int vxge_config_vpaths(struct vxge_hw_device_config *device_config,
+ u64 vpath_mask, struct vxge_config *config_param)
{
int i, no_of_vpaths = 0, default_no_vpath = 0, temp;
u32 txdl_size, txdl_per_memblock;
@@ -3859,9 +3857,8 @@ static int __devinit vxge_config_vpaths(
}
/* initialize device configuratrions */
-static void __devinit vxge_device_config_init(
- struct vxge_hw_device_config *device_config,
- int *intr_type)
+static void vxge_device_config_init(struct vxge_hw_device_config *device_config,
+ int *intr_type)
{
/* Used for CQRQ/SRQ. */
device_config->dma_blockpool_initial =
@@ -3912,7 +3909,7 @@ static void __devinit vxge_device_config_init(
device_config->rth_it_type);
}
-static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
+static void vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
{
int i;
@@ -4269,7 +4266,7 @@ static int vxge_probe_fw_update(struct vxgedev *vdev)
return ret;
}
-static int __devinit is_sriov_initialized(struct pci_dev *pdev)
+static int is_sriov_initialized(struct pci_dev *pdev)
{
int pos;
u16 ctrl;
@@ -4300,7 +4297,7 @@ static const struct vxge_hw_uld_cbs vxge_callbacks = {
* returns 0 on success and negative on failure.
*
*/
-static int __devinit
+static int
vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
{
struct __vxge_hw_device *hldev;
@@ -4764,7 +4761,7 @@ _exit0:
* Description: This function is called by the Pci subsystem to release a
* PCI device and free up all resource held up by the device.
*/
-static void __devexit vxge_remove(struct pci_dev *pdev)
+static void vxge_remove(struct pci_dev *pdev)
{
struct __vxge_hw_device *hldev;
struct vxgedev *vdev;
@@ -4809,7 +4806,7 @@ static struct pci_driver vxge_driver = {
.name = VXGE_DRIVER_NAME,
.id_table = vxge_id_table,
.probe = vxge_probe,
- .remove = __devexit_p(vxge_remove),
+ .remove = vxge_remove,
#ifdef CONFIG_PM
.suspend = vxge_pm_suspend,
.resume = vxge_pm_resume,
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index 6893a65ae55f..cbd6a529d0c0 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -978,7 +978,7 @@ static int w90p910_ether_setup(struct net_device *dev)
return 0;
}
-static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+static int w90p910_ether_probe(struct platform_device *pdev)
{
struct w90p910_ether *ether;
struct net_device *dev;
@@ -1071,7 +1071,7 @@ failed_free:
return error;
}
-static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+static int w90p910_ether_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct w90p910_ether *ether = netdev_priv(dev);
@@ -1096,7 +1096,7 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
static struct platform_driver w90p910_ether_driver = {
.probe = w90p910_ether_probe,
- .remove = __devexit_p(w90p910_ether_remove),
+ .remove = w90p910_ether_remove,
.driver = {
.name = "nuc900-emc",
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 876beceaf2d7..653487dc7b52 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -5520,7 +5520,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
#endif
};
-static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct net_device *dev;
struct fe_priv *np;
@@ -5995,7 +5995,7 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
base + NvRegTransmitPoll);
}
-static void __devexit nv_remove(struct pci_dev *pci_dev)
+static void nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
@@ -6271,7 +6271,7 @@ static struct pci_driver driver = {
.name = DRV_NAME,
.id_table = pci_tbl,
.probe = nv_probe,
- .remove = __devexit_p(nv_remove),
+ .remove = nv_remove,
.shutdown = nv_shutdown,
.driver.pm = NV_PM_OPS,
};
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index af8b4142088c..3466ca1e8f6c 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1219,9 +1219,6 @@ static int lpc_eth_open(struct net_device *ndev)
if (netif_msg_ifup(pldat))
dev_dbg(&pldat->pdev->dev, "enabling %s\n", ndev->name);
- if (!is_valid_ether_addr(ndev->dev_addr))
- return -EADDRNOTAVAIL;
-
__lpc_eth_clock_enable(pldat, true);
/* Reset and initialize */
@@ -1301,6 +1298,7 @@ static const struct net_device_ops lpc_netdev_ops = {
.ndo_set_rx_mode = lpc_eth_set_multicast_list,
.ndo_do_ioctl = lpc_eth_ioctl,
.ndo_set_mac_address = lpc_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
};
@@ -1597,7 +1595,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match);
static struct platform_driver lpc_eth_driver = {
.probe = lpc_eth_drv_probe,
- .remove = __devexit_p(lpc_eth_drv_remove),
+ .remove = lpc_eth_drv_remove,
#ifdef CONFIG_PM
.suspend = lpc_eth_drv_suspend,
.resume = lpc_eth_drv_resume,
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index f97719c48516..b5499198e029 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -1419,7 +1419,7 @@ static const struct net_device_ops octeon_mgmt_ops = {
#endif
};
-static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
+static int octeon_mgmt_probe(struct platform_device *pdev)
{
struct net_device *netdev;
struct octeon_mgmt *p;
@@ -1559,7 +1559,7 @@ err:
return result;
}
-static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
+static int octeon_mgmt_remove(struct platform_device *pdev)
{
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
@@ -1583,7 +1583,7 @@ static struct platform_driver octeon_mgmt_driver = {
.of_match_table = octeon_mgmt_match,
},
.probe = octeon_mgmt_probe,
- .remove = __devexit_p(octeon_mgmt_remove),
+ .remove = octeon_mgmt_remove,
};
extern void octeon_mdiobus_force_mod_depencency(void);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 5296cc8d3cba..34d05bf72b2e 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -7,6 +7,7 @@ config PCH_GBE
depends on PCI
select NET_CORE
select MII
+ select PTP_1588_CLOCK_PCH
---help---
This is a gigabit ethernet driver for EG20T PCH.
EG20T PCH is the platform controller hub that is used in Intel's
@@ -20,19 +21,3 @@ config PCH_GBE
purpose use.
ML7223/ML7831 is companion chip for Intel Atom E6xx series.
ML7223/ML7831 is completely compatible for Intel EG20T PCH.
-
-if PCH_GBE
-
-config PCH_PTP
- bool "PCH PTP clock support"
- default n
- depends on EXPERIMENTAL
- select PPS
- select PTP_1588_CLOCK
- select PTP_1588_CLOCK_PCH
- ---help---
- Say Y here if you want to use Precision Time Protocol (PTP) in the
- driver. PTP is a method to precisely synchronize distributed clocks
- over Ethernet networks.
-
-endif # PCH_GBE
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index b07311eaa693..7fb7e178c74e 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -649,7 +649,6 @@ extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
struct pch_gbe_rx_ring *rx_ring);
extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
-#ifdef CONFIG_PCH_PTP
extern u32 pch_ch_control_read(struct pci_dev *pdev);
extern void pch_ch_control_write(struct pci_dev *pdev, u32 val);
extern u32 pch_ch_event_read(struct pci_dev *pdev);
@@ -659,7 +658,6 @@ extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
extern u64 pch_rx_snap_read(struct pci_dev *pdev);
extern u64 pch_tx_snap_read(struct pci_dev *pdev);
extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
-#endif
/* pch_gbe_param.c */
extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 4c4fe5b1a29a..39ab4d09faaa 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -21,10 +21,8 @@
#include "pch_gbe.h"
#include "pch_gbe_api.h"
#include <linux/module.h>
-#ifdef CONFIG_PCH_PTP
#include <linux/net_tstamp.h>
#include <linux/ptp_classify.h>
-#endif
#define DRV_VERSION "1.01"
const char pch_driver_version[] = DRV_VERSION;
@@ -98,7 +96,6 @@ const char pch_driver_version[] = DRV_VERSION;
#define PCH_GBE_INT_DISABLE_ALL 0
-#ifdef CONFIG_PCH_PTP
/* Macros for ieee1588 */
/* 0x40 Time Synchronization Channel Control Register Bits */
#define MASTER_MODE (1<<0)
@@ -113,7 +110,6 @@ const char pch_driver_version[] = DRV_VERSION;
#define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
#define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
-#endif
static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
@@ -122,7 +118,6 @@ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
int data);
static void pch_gbe_set_multi(struct net_device *netdev);
-#ifdef CONFIG_PCH_PTP
static struct sock_filter ptp_filter[] = {
PTP_FILTER
};
@@ -291,7 +286,6 @@ 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;
}
-#endif
inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw)
{
@@ -1244,9 +1238,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
(int)sizeof(struct pch_gbe_tx_desc) * ring_num,
&hw->reg->TX_DSC_SW_P);
-#ifdef CONFIG_PCH_PTP
pch_tx_timestamp(adapter, skb);
-#endif
dev_kfree_skb_any(skb);
}
@@ -1730,9 +1722,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
/* Write meta date of skb */
skb_put(skb, length);
-#ifdef CONFIG_PCH_PTP
pch_rx_timestamp(adapter, skb);
-#endif
skb->protocol = eth_type_trans(skb, netdev);
if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
@@ -2334,10 +2324,8 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
pr_debug("cmd : 0x%04x\n", cmd);
-#ifdef CONFIG_PCH_PTP
if (cmd == SIOCSHWTSTAMP)
return hwtstamp_ioctl(netdev, ifr, cmd);
-#endif
return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
}
@@ -2623,14 +2611,12 @@ static int pch_gbe_probe(struct pci_dev *pdev,
goto err_free_netdev;
}
-#ifdef CONFIG_PCH_PTP
adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
PCI_DEVFN(12, 4));
if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
pr_err("Bad ptp filter\n");
return -EINVAL;
}
-#endif
netdev->netdev_ops = &pch_gbe_netdev_ops;
netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index c2367158350e..bf829ee30077 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -166,7 +166,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <asm/unaligned.h>
#include <asm/cache.h>
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"
" Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
" Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
@@ -576,8 +576,8 @@ static const struct net_device_ops hamachi_netdev_ops = {
};
-static int __devinit hamachi_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int hamachi_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct hamachi_private *hmp;
int option, i, rx_int_var, tx_int_var, boguscnt;
@@ -791,7 +791,7 @@ err_out:
return ret;
}
-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
+static int read_eeprom(void __iomem *ioaddr, int location)
{
int bogus_cnt = 1000;
@@ -1894,7 +1894,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
-static void __devexit hamachi_remove_one (struct pci_dev *pdev)
+static void hamachi_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -1923,7 +1923,7 @@ static struct pci_driver hamachi_driver = {
.name = DRV_NAME,
.id_table = hamachi_pci_tbl,
.probe = hamachi_init_one,
- .remove = __devexit_p(hamachi_remove_one),
+ .remove = hamachi_remove_one,
};
static int __init hamachi_init (void)
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 04e622fd468d..fbaed4fa72fa 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -106,7 +106,7 @@ static int gx_fix;
#include <asm/io.h>
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n"
" (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
@@ -367,8 +367,8 @@ static const struct net_device_ops netdev_ops = {
.ndo_tx_timeout = yellowfin_tx_timeout,
};
-static int __devinit yellowfin_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int yellowfin_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
struct yellowfin_private *np;
@@ -522,7 +522,7 @@ err_out_free_netdev:
return -ENODEV;
}
-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
+static int read_eeprom(void __iomem *ioaddr, int location)
{
int bogus_cnt = 10000; /* Typical 33Mhz: 1050 ticks */
@@ -1372,7 +1372,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
-static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
+static void yellowfin_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct yellowfin_private *np;
@@ -1399,7 +1399,7 @@ static struct pci_driver yellowfin_driver = {
.name = DRV_NAME,
.id_table = yellowfin_pci_tbl,
.probe = yellowfin_init_one,
- .remove = __devexit_p(yellowfin_remove_one),
+ .remove = yellowfin_remove_one,
};
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 6fa74d530e44..0be5844d6372 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1727,7 +1727,7 @@ static const struct net_device_ops pasemi_netdev_ops = {
#endif
};
-static int __devinit
+static int
pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
@@ -1849,7 +1849,7 @@ out_disable_device:
}
-static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
+static void pasemi_mac_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct pasemi_mac *mac;
@@ -1884,7 +1884,7 @@ static struct pci_driver pasemi_mac_driver = {
.name = "pasemi_mac",
.id_table = pasemi_mac_pci_tbl,
.probe = pasemi_mac_probe,
- .remove = __devexit_p(pasemi_mac_remove),
+ .remove = pasemi_mac_remove,
};
static void __exit pasemi_mac_cleanup_module(void)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 10468e7932dd..4ca2c196c98a 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -218,7 +218,7 @@ skip:
check_sfp_module = netif_running(dev) &&
adapter->has_link_events;
} else {
- ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
+ ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
ecmd->advertising |=
(ADVERTISED_TP | ADVERTISED_Autoneg);
ecmd->port = PORT_TP;
@@ -381,7 +381,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
static int
netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
- u8 * bytes)
+ u8 *bytes)
{
struct netxen_adapter *adapter = netdev_priv(dev);
int offset;
@@ -488,6 +488,8 @@ netxen_nic_get_pauseparam(struct net_device *dev,
__u32 val;
int port = adapter->physical_port;
+ pause->autoneg = 0;
+
if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
return;
@@ -496,19 +498,19 @@ netxen_nic_get_pauseparam(struct net_device *dev,
pause->rx_pause = netxen_gb_get_rx_flowctl(val);
val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
switch (port) {
- case 0:
- pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
- break;
- case 1:
- pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
- break;
- case 2:
- pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
- break;
- case 3:
- default:
- pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
- break;
+ case 0:
+ pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
+ break;
+ case 1:
+ pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
+ break;
+ case 2:
+ pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
+ break;
+ case 3:
+ default:
+ pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
+ break;
}
} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
@@ -532,6 +534,11 @@ netxen_nic_set_pauseparam(struct net_device *dev,
struct netxen_adapter *adapter = netdev_priv(dev);
__u32 val;
int port = adapter->physical_port;
+
+ /* not supported */
+ if (pause->autoneg)
+ return -EINVAL;
+
/* read mode */
if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
@@ -549,31 +556,31 @@ netxen_nic_set_pauseparam(struct net_device *dev,
/* set autoneg */
val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
switch (port) {
- case 0:
- if (pause->tx_pause)
- netxen_gb_unset_gb0_mask(val);
- else
- netxen_gb_set_gb0_mask(val);
- break;
- case 1:
- if (pause->tx_pause)
- netxen_gb_unset_gb1_mask(val);
- else
- netxen_gb_set_gb1_mask(val);
- break;
- case 2:
- if (pause->tx_pause)
- netxen_gb_unset_gb2_mask(val);
- else
- netxen_gb_set_gb2_mask(val);
- break;
- case 3:
- default:
- if (pause->tx_pause)
- netxen_gb_unset_gb3_mask(val);
- else
- netxen_gb_set_gb3_mask(val);
- break;
+ case 0:
+ if (pause->tx_pause)
+ netxen_gb_unset_gb0_mask(val);
+ else
+ netxen_gb_set_gb0_mask(val);
+ break;
+ case 1:
+ if (pause->tx_pause)
+ netxen_gb_unset_gb1_mask(val);
+ else
+ netxen_gb_set_gb1_mask(val);
+ break;
+ case 2:
+ if (pause->tx_pause)
+ netxen_gb_unset_gb2_mask(val);
+ else
+ netxen_gb_set_gb2_mask(val);
+ break;
+ case 3:
+ default:
+ if (pause->tx_pause)
+ netxen_gb_unset_gb3_mask(val);
+ else
+ netxen_gb_set_gb3_mask(val);
+ break;
}
NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
@@ -636,7 +643,7 @@ static int netxen_get_sset_count(struct net_device *dev, int sset)
static void
netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
- u64 * data)
+ u64 *data)
{
memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
if ((data[0] = netxen_nic_reg_test(dev)))
@@ -647,7 +654,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
}
static void
-netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
int index;
@@ -668,7 +675,7 @@ netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
static void
netxen_nic_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 * data)
+ struct ethtool_stats *stats, u64 *data)
{
struct netxen_adapter *adapter = netdev_priv(dev);
int index;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index df450616ab37..6098fd4adfeb 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -60,9 +60,9 @@ static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
module_param(auto_fw_reset, int, 0644);
MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled");
-static int __devinit netxen_nic_probe(struct pci_dev *pdev,
+static int netxen_nic_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
-static void __devexit netxen_nic_remove(struct pci_dev *pdev);
+static void netxen_nic_remove(struct pci_dev *pdev);
static int netxen_nic_open(struct net_device *netdev);
static int netxen_nic_close(struct net_device *netdev);
static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *,
@@ -1397,7 +1397,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
}
#endif
-static int __devinit
+static int
netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
@@ -1569,7 +1569,7 @@ void netxen_cleanup_minidump(struct netxen_adapter *adapter)
}
}
-static void __devexit netxen_nic_remove(struct pci_dev *pdev)
+static void netxen_nic_remove(struct pci_dev *pdev)
{
struct netxen_adapter *adapter;
struct net_device *netdev;
@@ -3350,7 +3350,7 @@ static struct pci_driver netxen_driver = {
.name = netxen_nic_driver_name,
.id_table = netxen_pci_tbl,
.probe = netxen_nic_probe,
- .remove = __devexit_p(netxen_nic_remove),
+ .remove = netxen_nic_remove,
#ifdef CONFIG_PM
.suspend = netxen_nic_suspend,
.resume = netxen_nic_resume,
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 6407d0d77e81..67a679aaf29a 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -1920,7 +1920,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
{
struct ql_tx_buf_cb *tx_cb;
int i;
- int retval = 0;
if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
netdev_warn(qdev->ndev,
@@ -1935,7 +1934,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
"Frame too short to be legal, frame not sent\n");
qdev->ndev->stats.tx_errors++;
- retval = -EIO;
goto frame_not_sent;
}
@@ -1944,7 +1942,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
mac_rsp->transaction_id);
qdev->ndev->stats.tx_errors++;
- retval = -EIO;
goto invalid_seg_count;
}
@@ -3772,8 +3769,8 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
.ndo_tx_timeout = ql3xxx_tx_timeout,
};
-static int __devinit ql3xxx_probe(struct pci_dev *pdev,
- const struct pci_device_id *pci_entry)
+static int ql3xxx_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_entry)
{
struct net_device *ndev = NULL;
struct ql3_adapter *qdev = NULL;
@@ -3928,7 +3925,7 @@ err_out:
return err;
}
-static void __devexit ql3xxx_remove(struct pci_dev *pdev)
+static void ql3xxx_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql3_adapter *qdev = netdev_priv(ndev);
@@ -3955,18 +3952,7 @@ static struct pci_driver ql3xxx_driver = {
.name = DRV_NAME,
.id_table = ql3xxx_pci_tbl,
.probe = ql3xxx_probe,
- .remove = __devexit_p(ql3xxx_remove),
+ .remove = ql3xxx_remove,
};
-static int __init ql3xxx_init_module(void)
-{
- return pci_register_driver(&ql3xxx_driver);
-}
-
-static void __exit ql3xxx_exit(void)
-{
- pci_unregister_driver(&ql3xxx_driver);
-}
-
-module_init(ql3xxx_init_module);
-module_exit(ql3xxx_exit);
+module_pci_driver(ql3xxx_driver);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index ddba83ef3f44..c4b8ced83829 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
- qlcnic_ethtool.o qlcnic_ctx.o
+ qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
+ qlcnic_sysfs.o qlcnic_minidump.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index eaa1db9fec32..537902479689 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -89,16 +89,6 @@
#define QLCNIC_CT_DEFAULT_RX_BUF_LEN 2048
#define QLCNIC_LRO_BUFFER_EXTRA 2048
-/* Opcodes to be used with the commands */
-#define TX_ETHER_PKT 0x01
-#define TX_TCP_PKT 0x02
-#define TX_UDP_PKT 0x03
-#define TX_IP_PKT 0x04
-#define TX_TCP_LSO 0x05
-#define TX_TCP_LSO6 0x06
-#define TX_TCPV6_PKT 0x0b
-#define TX_UDPV6_PKT 0x0c
-
/* Tx defines */
#define QLCNIC_MAX_FRAGS_PER_TX 14
#define MAX_TSO_HEADER_DESC 2
@@ -147,28 +137,6 @@
* Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
* we are doing LSO (above the 1500 size packet) only.
*/
-
-#define FLAGS_VLAN_TAGGED 0x10
-#define FLAGS_VLAN_OOB 0x40
-
-#define qlcnic_set_tx_vlan_tci(cmd_desc, v) \
- (cmd_desc)->vlan_TCI = cpu_to_le16(v);
-#define qlcnic_set_cmd_desc_port(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
-#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-
-#define qlcnic_set_tx_port(_desc, _port) \
- ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
-
-#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
- ((_desc)->flags_opcode |= \
- cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
-
-#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
- ((_desc)->nfrags__length = \
- cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
-
struct cmd_desc_type0 {
u8 tcp_hdr_offset; /* For LSO only */
u8 ip_hdr_offset; /* For LSO only */
@@ -203,65 +171,6 @@ struct rcv_desc {
__le64 addr_buffer;
} __packed;
-/* opcode field in status_desc */
-#define QLCNIC_SYN_OFFLOAD 0x03
-#define QLCNIC_RXPKT_DESC 0x04
-#define QLCNIC_OLD_RXPKT_DESC 0x3f
-#define QLCNIC_RESPONSE_DESC 0x05
-#define QLCNIC_LRO_DESC 0x12
-
-/* for status field in status_desc */
-#define STATUS_CKSUM_LOOP 0
-#define STATUS_CKSUM_OK 2
-
-/* owner bits of status_desc */
-#define STATUS_OWNER_HOST (0x1ULL << 56)
-#define STATUS_OWNER_PHANTOM (0x2ULL << 56)
-
-/* Status descriptor:
- 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
- 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
- 53-55 desc_cnt, 56-57 owner, 58-63 opcode
- */
-#define qlcnic_get_sts_port(sts_data) \
- ((sts_data) & 0x0F)
-#define qlcnic_get_sts_status(sts_data) \
- (((sts_data) >> 4) & 0x0F)
-#define qlcnic_get_sts_type(sts_data) \
- (((sts_data) >> 8) & 0x0F)
-#define qlcnic_get_sts_totallength(sts_data) \
- (((sts_data) >> 12) & 0xFFFF)
-#define qlcnic_get_sts_refhandle(sts_data) \
- (((sts_data) >> 28) & 0xFFFF)
-#define qlcnic_get_sts_prot(sts_data) \
- (((sts_data) >> 44) & 0x0F)
-#define qlcnic_get_sts_pkt_offset(sts_data) \
- (((sts_data) >> 48) & 0x1F)
-#define qlcnic_get_sts_desc_cnt(sts_data) \
- (((sts_data) >> 53) & 0x7)
-#define qlcnic_get_sts_opcode(sts_data) \
- (((sts_data) >> 58) & 0x03F)
-
-#define qlcnic_get_lro_sts_refhandle(sts_data) \
- ((sts_data) & 0x0FFFF)
-#define qlcnic_get_lro_sts_length(sts_data) \
- (((sts_data) >> 16) & 0x0FFFF)
-#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \
- (((sts_data) >> 32) & 0x0FF)
-#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data) \
- (((sts_data) >> 40) & 0x0FF)
-#define qlcnic_get_lro_sts_timestamp(sts_data) \
- (((sts_data) >> 48) & 0x1)
-#define qlcnic_get_lro_sts_type(sts_data) \
- (((sts_data) >> 49) & 0x7)
-#define qlcnic_get_lro_sts_push_flag(sts_data) \
- (((sts_data) >> 52) & 0x1)
-#define qlcnic_get_lro_sts_seq_number(sts_data) \
- ((sts_data) & 0x0FFFFFFFF)
-#define qlcnic_get_lro_sts_mss(sts_data1) \
- ((sts_data1 >> 32) & 0x0FFFF)
-
-
struct status_desc {
__le64 status_desc_data[2];
} __attribute__ ((aligned(16)));
@@ -280,16 +189,16 @@ struct status_desc {
#define QLCNIC_UNI_FIRMWARE_IDX_OFF 29
struct uni_table_desc{
- u32 findex;
- u32 num_entries;
- u32 entry_size;
- u32 reserved[5];
+ __le32 findex;
+ __le32 num_entries;
+ __le32 entry_size;
+ __le32 reserved[5];
};
struct uni_data_desc{
- u32 findex;
- u32 size;
- u32 reserved[5];
+ __le32 findex;
+ __le32 size;
+ __le32 reserved[5];
};
/* Flash Defines and Structures */
@@ -416,19 +325,19 @@ struct qlcnic_nic_intr_coalesce {
};
struct qlcnic_dump_template_hdr {
- __le32 type;
- __le32 offset;
- __le32 size;
- __le32 cap_mask;
- __le32 num_entries;
- __le32 version;
- __le32 timestamp;
- __le32 checksum;
- __le32 drv_cap_mask;
- __le32 sys_info[3];
- __le32 saved_state[16];
- __le32 cap_sizes[8];
- __le32 rsvd[0];
+ u32 type;
+ u32 offset;
+ u32 size;
+ u32 cap_mask;
+ u32 num_entries;
+ u32 version;
+ u32 timestamp;
+ u32 checksum;
+ u32 drv_cap_mask;
+ u32 sys_info[3];
+ u32 saved_state[16];
+ u32 cap_sizes[8];
+ u32 rsvd[0];
};
struct qlcnic_fw_dump {
@@ -456,11 +365,41 @@ struct qlcnic_hardware_context {
u8 pci_func;
u8 linkup;
u8 loopback_state;
+ u8 beacon_state;
+ u8 has_link_events;
+ u8 fw_type;
+ u8 physical_port;
+ u8 reset_context;
+ u8 msix_supported;
+ u8 max_mac_filters;
+ u8 mc_enabled;
+ u8 max_mc_count;
+ u8 diag_test;
+ u8 num_msix;
+ u8 nic_mode;
+ char diag_cnt;
+
u16 port_type;
u16 board_type;
- u8 beacon_state;
+ u16 link_speed;
+ u16 link_duplex;
+ u16 link_autoneg;
+ u16 module_type;
+ u16 op_mode;
+ u16 switch_mode;
+ u16 max_tx_ques;
+ u16 max_rx_ques;
+ u16 max_mtu;
+ u32 msg_enable;
+ u16 act_pci_func;
+
+ u32 capabilities;
+ u32 temp;
+ u32 int_vec_bit;
+ u32 fw_hal_version;
+ struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
};
@@ -521,6 +460,7 @@ struct qlcnic_host_sds_ring {
} ____cacheline_internodealigned_in_smp;
struct qlcnic_host_tx_ring {
+ u16 ctx_id;
u32 producer;
u32 sw_consumer;
u32 num_desc;
@@ -985,6 +925,7 @@ struct qlcnic_adapter {
unsigned long state;
u32 flags;
+ int max_drv_tx_rings;
u16 num_txd;
u16 num_rxd;
u16 num_jumbo_rxd;
@@ -993,57 +934,28 @@ struct qlcnic_adapter {
u8 max_rds_rings;
u8 max_sds_rings;
- u8 msix_supported;
u8 portnum;
- u8 physical_port;
- u8 reset_context;
- u8 mc_enabled;
- u8 max_mc_count;
u8 fw_wait_cnt;
u8 fw_fail_cnt;
u8 tx_timeo_cnt;
u8 need_fw_reset;
- u8 has_link_events;
- u8 fw_type;
- u16 tx_context_id;
u16 is_up;
-
- u16 link_speed;
- u16 link_duplex;
- u16 link_autoneg;
- u16 module_type;
-
- u16 op_mode;
- u16 switch_mode;
- u16 max_tx_ques;
- u16 max_rx_ques;
- u16 max_mtu;
u16 pvid;
- u32 fw_hal_version;
- u32 capabilities;
u32 irq;
- u32 temp;
-
- u32 int_vec_bit;
u32 heartbeat;
- u8 max_mac_filters;
u8 dev_state;
- u8 diag_test;
- char diag_cnt;
u8 reset_ack_timeo;
u8 dev_init_timeo;
- u16 msg_enable;
u8 mac_addr[ETH_ALEN];
u64 dev_rst_time;
u8 mac_learn;
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
-
struct qlcnic_npar_info *npars;
struct qlcnic_eswitch *eswitch;
struct qlcnic_nic_template *nic_ops;
@@ -1057,24 +969,22 @@ struct qlcnic_adapter {
void __iomem *isr_int_vec;
struct msix_entry *msix_entries;
-
struct delayed_work fw_work;
-
struct qlcnic_filter_hash fhash;
spinlock_t tx_clean_lock;
spinlock_t mac_learn_lock;
- __le32 file_prd_off; /*File fw product offset*/
+ u32 file_prd_off; /*File fw product offset*/
u32 fw_version;
const struct firmware *fw;
};
-struct qlcnic_info {
+struct qlcnic_info_le {
__le16 pci_func;
- __le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */
+ __le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */
__le16 phys_port;
- __le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */
+ __le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */
__le32 capabilities;
u8 max_mac_filters;
@@ -1088,13 +998,28 @@ struct qlcnic_info {
u8 reserved2[104];
} __packed;
-struct qlcnic_pci_info {
- __le16 id; /* pci function id */
- __le16 active; /* 1 = Enabled */
- __le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
- __le16 default_port; /* default port number */
+struct qlcnic_info {
+ u16 pci_func;
+ u16 op_mode;
+ u16 phys_port;
+ u16 switch_mode;
+ u32 capabilities;
+ u8 max_mac_filters;
+ u8 reserved1;
+ u16 max_mtu;
+ u16 max_tx_ques;
+ u16 max_rx_ques;
+ u16 min_tx_bw;
+ u16 max_tx_bw;
+};
+
+struct qlcnic_pci_info_le {
+ __le16 id; /* pci function id */
+ __le16 active; /* 1 = Enabled */
+ __le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
+ __le16 default_port; /* default port number */
- __le16 tx_min_bw; /* Multiple of 100mbpc */
+ __le16 tx_min_bw; /* Multiple of 100mbpc */
__le16 tx_max_bw;
__le16 reserved1[2];
@@ -1102,6 +1027,16 @@ struct qlcnic_pci_info {
u8 reserved2[106];
} __packed;
+struct qlcnic_pci_info {
+ u16 id;
+ u16 active;
+ u16 type;
+ u16 default_port;
+ u16 tx_min_bw;
+ u16 tx_max_bw;
+ u8 mac[ETH_ALEN];
+};
+
struct qlcnic_npar_info {
u16 pvid;
u16 min_bw;
@@ -1116,6 +1051,7 @@ struct qlcnic_npar_info {
u8 mac_anti_spoof;
u8 promisc_mode;
u8 offload_flags;
+ u8 pci_func;
};
struct qlcnic_eswitch {
@@ -1208,7 +1144,7 @@ do { \
(VAL1) += (VAL2); \
} while (0)
-struct qlcnic_mac_statistics{
+struct qlcnic_mac_statistics_le {
__le64 mac_tx_frames;
__le64 mac_tx_bytes;
__le64 mac_tx_mcast_pkts;
@@ -1248,7 +1184,45 @@ struct qlcnic_mac_statistics{
__le64 mac_align_error;
} __packed;
-struct __qlcnic_esw_statistics {
+struct qlcnic_mac_statistics {
+ u64 mac_tx_frames;
+ u64 mac_tx_bytes;
+ u64 mac_tx_mcast_pkts;
+ u64 mac_tx_bcast_pkts;
+ u64 mac_tx_pause_cnt;
+ u64 mac_tx_ctrl_pkt;
+ u64 mac_tx_lt_64b_pkts;
+ u64 mac_tx_lt_127b_pkts;
+ u64 mac_tx_lt_255b_pkts;
+ u64 mac_tx_lt_511b_pkts;
+ u64 mac_tx_lt_1023b_pkts;
+ u64 mac_tx_lt_1518b_pkts;
+ u64 mac_tx_gt_1518b_pkts;
+ u64 rsvd1[3];
+ u64 mac_rx_frames;
+ u64 mac_rx_bytes;
+ u64 mac_rx_mcast_pkts;
+ u64 mac_rx_bcast_pkts;
+ u64 mac_rx_pause_cnt;
+ u64 mac_rx_ctrl_pkt;
+ u64 mac_rx_lt_64b_pkts;
+ u64 mac_rx_lt_127b_pkts;
+ u64 mac_rx_lt_255b_pkts;
+ u64 mac_rx_lt_511b_pkts;
+ u64 mac_rx_lt_1023b_pkts;
+ u64 mac_rx_lt_1518b_pkts;
+ u64 mac_rx_gt_1518b_pkts;
+ u64 rsvd2[3];
+ u64 mac_rx_length_error;
+ u64 mac_rx_length_small;
+ u64 mac_rx_length_large;
+ u64 mac_rx_jabber;
+ u64 mac_rx_dropped;
+ u64 mac_rx_crc_error;
+ u64 mac_align_error;
+};
+
+struct qlcnic_esw_stats_le {
__le16 context_id;
__le16 version;
__le16 size;
@@ -1263,147 +1237,27 @@ struct __qlcnic_esw_statistics {
__le64 rsvd[3];
} __packed;
+struct __qlcnic_esw_statistics {
+ u16 context_id;
+ u16 version;
+ u16 size;
+ u16 unused;
+ u64 unicast_frames;
+ u64 multicast_frames;
+ u64 broadcast_frames;
+ u64 dropped_frames;
+ u64 errors;
+ u64 local_frames;
+ u64 numbytes;
+ u64 rsvd[3];
+};
+
struct qlcnic_esw_statistics {
struct __qlcnic_esw_statistics rx;
struct __qlcnic_esw_statistics tx;
};
-struct qlcnic_common_entry_hdr {
- __le32 type;
- __le32 offset;
- __le32 cap_size;
- u8 mask;
- u8 rsvd[2];
- u8 flags;
-} __packed;
-
-struct __crb {
- __le32 addr;
- u8 stride;
- u8 rsvd1[3];
- __le32 data_size;
- __le32 no_ops;
- __le32 rsvd2[4];
-} __packed;
-
-struct __ctrl {
- __le32 addr;
- u8 stride;
- u8 index_a;
- __le16 timeout;
- __le32 data_size;
- __le32 no_ops;
- u8 opcode;
- u8 index_v;
- u8 shl_val;
- u8 shr_val;
- __le32 val1;
- __le32 val2;
- __le32 val3;
-} __packed;
-
-struct __cache {
- __le32 addr;
- __le16 stride;
- __le16 init_tag_val;
- __le32 size;
- __le32 no_ops;
- __le32 ctrl_addr;
- __le32 ctrl_val;
- __le32 read_addr;
- u8 read_addr_stride;
- u8 read_addr_num;
- u8 rsvd1[2];
-} __packed;
-
-struct __ocm {
- u8 rsvd[8];
- __le32 size;
- __le32 no_ops;
- u8 rsvd1[8];
- __le32 read_addr;
- __le32 read_addr_stride;
-} __packed;
-
-struct __mem {
- u8 rsvd[24];
- __le32 addr;
- __le32 size;
-} __packed;
-
-struct __mux {
- __le32 addr;
- u8 rsvd[4];
- __le32 size;
- __le32 no_ops;
- __le32 val;
- __le32 val_stride;
- __le32 read_addr;
- u8 rsvd2[4];
-} __packed;
-
-struct __queue {
- __le32 sel_addr;
- __le16 stride;
- u8 rsvd[2];
- __le32 size;
- __le32 no_ops;
- u8 rsvd2[8];
- __le32 read_addr;
- u8 read_addr_stride;
- u8 read_addr_cnt;
- u8 rsvd3[2];
-} __packed;
-
-struct qlcnic_dump_entry {
- struct qlcnic_common_entry_hdr hdr;
- union {
- struct __crb crb;
- struct __cache cache;
- struct __ocm ocm;
- struct __mem mem;
- struct __mux mux;
- struct __queue que;
- struct __ctrl ctrl;
- } region;
-} __packed;
-
-enum op_codes {
- QLCNIC_DUMP_NOP = 0,
- QLCNIC_DUMP_READ_CRB = 1,
- QLCNIC_DUMP_READ_MUX = 2,
- QLCNIC_DUMP_QUEUE = 3,
- QLCNIC_DUMP_BRD_CONFIG = 4,
- QLCNIC_DUMP_READ_OCM = 6,
- QLCNIC_DUMP_PEG_REG = 7,
- QLCNIC_DUMP_L1_DTAG = 8,
- QLCNIC_DUMP_L1_ITAG = 9,
- QLCNIC_DUMP_L1_DATA = 11,
- QLCNIC_DUMP_L1_INST = 12,
- QLCNIC_DUMP_L2_DTAG = 21,
- QLCNIC_DUMP_L2_ITAG = 22,
- QLCNIC_DUMP_L2_DATA = 23,
- QLCNIC_DUMP_L2_INST = 24,
- QLCNIC_DUMP_READ_ROM = 71,
- QLCNIC_DUMP_READ_MEM = 72,
- QLCNIC_DUMP_READ_CTRL = 98,
- QLCNIC_DUMP_TLHDR = 99,
- QLCNIC_DUMP_RDEND = 255
-};
-
-#define QLCNIC_DUMP_WCRB BIT_0
-#define QLCNIC_DUMP_RWCRB BIT_1
-#define QLCNIC_DUMP_ANDCRB BIT_2
-#define QLCNIC_DUMP_ORCRB BIT_3
-#define QLCNIC_DUMP_POLLCRB BIT_4
-#define QLCNIC_DUMP_RD_SAVE BIT_5
-#define QLCNIC_DUMP_WRT_SAVED BIT_6
-#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7
-#define QLCNIC_DUMP_SKIP BIT_7
-
-#define QLCNIC_DUMP_MASK_MIN 3
#define QLCNIC_DUMP_MASK_DEF 0x1f
-#define QLCNIC_DUMP_MASK_MAX 0xff
#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
@@ -1411,12 +1265,6 @@ enum op_codes {
#define QLCNIC_SET_QUIESCENT 0xadd00010
#define QLCNIC_RESET_QUIESCENT 0xadd00020
-struct qlcnic_dump_operations {
- enum op_codes opcode;
- u32 (*handler)(struct qlcnic_adapter *,
- struct qlcnic_dump_entry *, u32 *);
-};
-
struct _cdrp_cmd {
u32 cmd;
u32 arg1;
@@ -1432,7 +1280,7 @@ struct qlcnic_cmd_args {
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
-u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
+int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data);
int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data);
int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data);
@@ -1474,6 +1322,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
#define __QLCNIC_MAX_LED_RATE 0xf
#define __QLCNIC_MAX_LED_STATE 0x2
+#define MAX_CTL_CHECK 1000
+
int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
@@ -1496,7 +1346,7 @@ int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter);
void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter);
-void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32);
+void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *, u32);
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);
@@ -1530,9 +1380,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
-void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
+void qlcnic_fetch_mac(u32, u32, u8, u8 *);
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
@@ -1571,12 +1420,32 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
extern int qlcnic_config_tso;
+int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *);
+void qlcnic_napi_del(struct qlcnic_adapter *adapter);
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter);
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter);
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
+void qlcnic_free_tx_rings(struct qlcnic_adapter *);
+int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
+int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
+void qlcnic_set_vlan_config(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
+
/*
* QLOGIC Board information
*/
#define QLCNIC_MAX_BOARD_NAME_LEN 100
-struct qlcnic_brdinfo {
+struct qlcnic_board_info {
unsigned short vendor;
unsigned short device;
unsigned short sub_vendor;
@@ -1584,30 +1453,6 @@ struct qlcnic_brdinfo {
char short_name[QLCNIC_MAX_BOARD_NAME_LEN];
};
-static const struct qlcnic_brdinfo qlcnic_boards[] = {
- {0x1077, 0x8020, 0x1077, 0x203,
- "8200 Series Single Port 10GbE Converged Network Adapter "
- "(TCP/IP Networking)"},
- {0x1077, 0x8020, 0x1077, 0x207,
- "8200 Series Dual Port 10GbE Converged Network Adapter "
- "(TCP/IP Networking)"},
- {0x1077, 0x8020, 0x1077, 0x20b,
- "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x1077, 0x20c,
- "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x1077, 0x20f,
- "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x103c, 0x3733,
- "NC523SFP 10Gb 2-port Server Adapter"},
- {0x1077, 0x8020, 0x103c, 0x3346,
- "CN1000Q Dual Port Converged Network Adapter"},
- {0x1077, 0x8020, 0x1077, 0x210,
- "QME8242-k 10GbE Dual Port Mezzanine Card"},
- {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
-};
-
-#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
-
static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
{
if (likely(tx_ring->producer < tx_ring->sw_consumer))
@@ -1617,6 +1462,21 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
tx_ring->producer;
}
+static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+ writel(0, sds_ring->crb_intr_mask);
+}
+
+static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+ writel(0x1, sds_ring->crb_intr_mask);
+
+ if (!QLCNIC_IS_MSI_FAMILY(adapter))
+ writel(0xfbff, adapter->tgt_mask_reg);
+}
+
extern const struct ethtool_ops qlcnic_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
@@ -1627,10 +1487,17 @@ struct qlcnic_nic_template {
};
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
- if (NETIF_MSG_##lvl & adapter->msg_enable) \
+ if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
printk(KERN_INFO "%s: %s: " _fmt, \
dev_name(&adapter->pdev->dev), \
__func__, ##_args); \
} while (0)
+#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
+static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
+{
+ unsigned short device = adapter->pdev->device;
+ return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false;
+}
+
#endif /* __QLCNIC_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 2a179d087207..58f094ca052e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -7,6 +7,18 @@
#include "qlcnic.h"
+static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
+{
+ int i;
+
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+ if (adapter->npars[i].pci_func == pci_func)
+ return i;
+ }
+
+ return -1;
+}
+
static u32
qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
{
@@ -35,7 +47,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
struct qlcnic_hardware_context *ahw = adapter->ahw;
signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func,
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
/* Acquire semaphore before accessing CRB */
if (qlcnic_api_lock(adapter)) {
@@ -103,7 +115,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
}
-static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
+static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)
{
uint64_t sum = 0;
int count = temp_size / sizeof(uint32_t);
@@ -117,9 +129,9 @@ static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
{
int err, i;
- u16 temp_size;
void *tmp_addr;
- u32 version, csum, *template, *tmp_buf;
+ u32 temp_size, version, csum, *template;
+ __le32 *tmp_buf;
struct qlcnic_cmd_args cmd;
struct qlcnic_hardware_context *ahw;
struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
@@ -163,13 +175,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
goto error;
}
tmp_tmpl = tmp_addr;
- csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
- if (csum) {
- dev_err(&adapter->pdev->dev,
- "Template header checksum validation failed\n");
- err = -EIO;
- goto error;
- }
ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
if (!ahw->fw_dump.tmpl_hdr) {
err = -EIO;
@@ -180,6 +185,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
for (i = 0; i < temp_size/sizeof(u32); i++)
*template++ = __le32_to_cpu(*tmp_buf++);
+ csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size);
+ if (csum) {
+ dev_err(&adapter->pdev->dev,
+ "Template header checksum validation failed\n");
+ err = -EIO;
+ goto error;
+ }
+
tmpl_hdr = ahw->fw_dump.tmpl_hdr;
tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
ahw->fw_dump.enable = 1;
@@ -231,6 +244,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
size_t rq_size, rsp_size;
u32 cap, reg, val, reg2;
int err;
+ u16 temp;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
@@ -267,8 +281,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
cap |= QLCNIC_CAP0_LRO_MSS;
- prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
- msix_handler);
+ temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
+ prq->valid_field_offset = cpu_to_le16(temp);
prq->txrx_sds_binding = nsds_rings - 1;
prq->capabilities[0] = cpu_to_le32(cap);
@@ -453,8 +467,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
- adapter->tx_context_id =
- le16_to_cpu(prsp->context_id);
+ adapter->tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
} else {
dev_err(&adapter->pdev->dev,
"Failed to create tx ctx in firmware%d\n", err);
@@ -476,7 +489,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
struct qlcnic_cmd_args cmd;
memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = adapter->tx_context_id;
+ cmd.req.arg1 = adapter->tx_ring->ctx_id;
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
cmd.req.arg3 = 0;
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
@@ -671,7 +684,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS)
- qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
+ qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
else {
dev_err(&adapter->pdev->dev,
"Failed to get mac address%d\n", err);
@@ -687,10 +700,10 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
{
int err;
dma_addr_t nic_dma_t;
- struct qlcnic_info *nic_info;
+ struct qlcnic_info_le *nic_info;
void *nic_info_addr;
struct qlcnic_cmd_args cmd;
- size_t nic_size = sizeof(struct qlcnic_info);
+ size_t nic_size = sizeof(struct qlcnic_info_le);
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
&nic_dma_t, GFP_KERNEL);
@@ -745,10 +758,10 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
dma_addr_t nic_dma_t;
void *nic_info_addr;
struct qlcnic_cmd_args cmd;
- struct qlcnic_info *nic_info;
- size_t nic_size = sizeof(struct qlcnic_info);
+ struct qlcnic_info_le *nic_info;
+ size_t nic_size = sizeof(struct qlcnic_info_le);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return err;
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
@@ -796,9 +809,9 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
int err = 0, i;
struct qlcnic_cmd_args cmd;
dma_addr_t pci_info_dma_t;
- struct qlcnic_pci_info *npar;
+ struct qlcnic_pci_info_le *npar;
void *pci_info_addr;
- size_t npar_size = sizeof(struct qlcnic_pci_info);
+ size_t npar_size = sizeof(struct qlcnic_pci_info_le);
size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
@@ -816,11 +829,14 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
+ adapter->ahw->act_pci_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
pci_info->id = le16_to_cpu(npar->id);
pci_info->active = le16_to_cpu(npar->active);
pci_info->type = le16_to_cpu(npar->type);
+ if (pci_info->type == QLCNIC_TYPE_NIC)
+ adapter->ahw->act_pci_func++;
pci_info->default_port =
le16_to_cpu(npar->default_port);
pci_info->tx_min_bw =
@@ -848,8 +864,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
u32 arg1;
struct qlcnic_cmd_args cmd;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
- !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
+ !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
return err;
arg1 = id | (enable_mirroring ? BIT_4 : 0);
@@ -877,8 +893,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
- size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
- struct __qlcnic_esw_statistics *stats;
+ size_t stats_size = sizeof(struct qlcnic_esw_stats_le);
+ struct qlcnic_esw_stats_le *stats;
dma_addr_t stats_dma_t;
void *stats_addr;
u32 arg1;
@@ -888,8 +904,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
if (esw_stats == NULL)
return -ENOMEM;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
- func != adapter->ahw->pci_func) {
+ if ((adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) &&
+ (func != adapter->ahw->pci_func)) {
dev_err(&adapter->pdev->dev,
"Not privilege to query stats for func=%d", func);
return -EIO;
@@ -939,9 +955,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
struct qlcnic_mac_statistics *mac_stats)
{
- struct qlcnic_mac_statistics *stats;
+ struct qlcnic_mac_statistics_le *stats;
struct qlcnic_cmd_args cmd;
- size_t stats_size = sizeof(struct qlcnic_mac_statistics);
+ size_t stats_size = sizeof(struct qlcnic_mac_statistics_le);
dma_addr_t stats_dma_t;
void *stats_addr;
int err;
@@ -1000,7 +1016,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
if (esw_stats == NULL)
return -ENOMEM;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return -EIO;
if (adapter->npars == NULL)
return -EIO;
@@ -1015,12 +1031,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
esw_stats->context_id = eswitch;
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
if (adapter->npars[i].phy_port != eswitch)
continue;
memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
- if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+ if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func,
+ rx_tx, &port_stats))
continue;
esw_stats->size = port_stats.size;
@@ -1051,7 +1068,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
u32 arg1;
struct qlcnic_cmd_args cmd;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return -EIO;
if (func_esw == QLCNIC_STATS_PORT) {
@@ -1119,15 +1136,18 @@ op_type = 1 for port vlan_id
int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
- int err = -EIO;
+ int err = -EIO, index;
u32 arg1, arg2 = 0;
struct qlcnic_cmd_args cmd;
u8 pci_func;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return err;
pci_func = esw_cfg->pci_func;
- arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+ index = qlcnic_is_valid_nic_func(adapter, pci_func);
+ if (index < 0)
+ return err;
+ arg1 = (adapter->npars[index].phy_port & BIT_0);
arg1 |= (pci_func << 8);
if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
@@ -1139,7 +1159,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
case QLCNIC_PORT_DEFAULTS:
arg1 |= (BIT_4 | BIT_6 | BIT_7);
arg2 |= (BIT_0 | BIT_1);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
arg2 |= (BIT_2 | BIT_3);
if (!(esw_cfg->discard_tagged))
arg1 &= ~BIT_4;
@@ -1191,11 +1211,17 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
u32 arg1, arg2;
+ int index;
u8 phy_port;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
- phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
- else
- phy_port = adapter->physical_port;
+
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+ index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func);
+ if (index < 0)
+ return -EIO;
+ phy_port = adapter->npars[index].phy_port;
+ } else {
+ phy_port = adapter->ahw->physical_port;
+ }
arg1 = phy_port;
arg1 |= (esw_cfg->pci_func << 8);
if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 9e9e78a5c4d7..74b98110c5b4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -208,9 +208,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full);
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->duplex = adapter->link_duplex;
- ecmd->autoneg = adapter->link_autoneg;
+ ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
+ ecmd->duplex = adapter->ahw->link_duplex;
+ ecmd->autoneg = adapter->ahw->link_autoneg;
} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
u32 val;
@@ -224,10 +224,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_10000baseT_Full;
}
- if (netif_running(dev) && adapter->has_link_events) {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->autoneg = adapter->link_autoneg;
- ecmd->duplex = adapter->link_duplex;
+ if (netif_running(dev) && adapter->ahw->has_link_events) {
+ ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
+ ecmd->autoneg = adapter->ahw->link_autoneg;
+ ecmd->duplex = adapter->ahw->link_duplex;
goto skip;
}
@@ -238,7 +238,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EIO;
skip:
- ecmd->phy_address = adapter->physical_port;
+ ecmd->phy_address = adapter->ahw->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;
switch (adapter->ahw->board_type) {
@@ -254,7 +254,7 @@ skip:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
- ecmd->autoneg = adapter->link_autoneg;
+ ecmd->autoneg = adapter->ahw->link_autoneg;
break;
case QLCNIC_BRDTYPE_P3P_IMEZ:
case QLCNIC_BRDTYPE_P3P_XG_LOM:
@@ -270,7 +270,7 @@ skip:
ecmd->advertising |= ADVERTISED_TP;
ecmd->supported |= SUPPORTED_TP;
check_sfp_module = netif_running(dev) &&
- adapter->has_link_events;
+ adapter->ahw->has_link_events;
case QLCNIC_BRDTYPE_P3P_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
@@ -285,7 +285,7 @@ skip:
(ADVERTISED_FIBRE | ADVERTISED_TP);
ecmd->port = PORT_FIBRE;
check_sfp_module = netif_running(dev) &&
- adapter->has_link_events;
+ adapter->ahw->has_link_events;
} else {
ecmd->autoneg = AUTONEG_ENABLE;
ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
@@ -301,7 +301,7 @@ skip:
}
if (check_sfp_module) {
- switch (adapter->module_type) {
+ switch (adapter->ahw->module_type) {
case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
case LINKEVENT_MODULE_OPTICAL_SRLR:
case LINKEVENT_MODULE_OPTICAL_LRM:
@@ -359,9 +359,9 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
else if (ret)
return -EIO;
- adapter->link_speed = ethtool_cmd_speed(ecmd);
- adapter->link_duplex = ecmd->duplex;
- adapter->link_autoneg = ecmd->autoneg;
+ adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
+ adapter->ahw->link_duplex = ecmd->duplex;
+ adapter->ahw->link_autoneg = ecmd->autoneg;
if (!netif_running(dev))
return 0;
@@ -508,14 +508,15 @@ qlcnic_set_ringparam(struct net_device *dev,
static void qlcnic_get_channels(struct net_device *dev,
struct ethtool_channels *channel)
{
+ int min;
struct qlcnic_adapter *adapter = netdev_priv(dev);
- channel->max_rx = rounddown_pow_of_two(min_t(int,
- adapter->max_rx_ques, num_online_cpus()));
- channel->max_tx = adapter->max_tx_ques;
+ min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus());
+ channel->max_rx = rounddown_pow_of_two(min);
+ channel->max_tx = adapter->ahw->max_tx_ques;
channel->rx_count = adapter->max_sds_rings;
- channel->tx_count = adapter->max_tx_ques;
+ channel->tx_count = adapter->ahw->max_tx_ques;
}
static int qlcnic_set_channels(struct net_device *dev,
@@ -543,7 +544,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- int port = adapter->physical_port;
+ int port = adapter->ahw->physical_port;
__u32 val;
if (adapter->ahw->port_type == QLCNIC_GBE) {
@@ -588,7 +589,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- int port = adapter->physical_port;
+ int port = adapter->ahw->physical_port;
__u32 val;
/* read mode */
@@ -703,7 +704,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
if (ret)
goto clear_it;
- adapter->diag_cnt = 0;
+ adapter->ahw->diag_cnt = 0;
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
cmd.req.arg1 = adapter->ahw->pci_func;
@@ -715,7 +716,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
msleep(10);
- ret = !adapter->diag_cnt;
+ ret = !adapter->ahw->diag_cnt;
done:
qlcnic_diag_free_res(netdev, max_sds_rings);
@@ -761,7 +762,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
- adapter->diag_cnt = 0;
+ adapter->ahw->diag_cnt = 0;
qlcnic_xmit_frame(skb, adapter->netdev);
loop = 0;
@@ -770,11 +771,11 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
qlcnic_process_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
break;
- } while (!adapter->diag_cnt);
+ } while (!adapter->ahw->diag_cnt);
dev_kfree_skb_any(skb);
- if (!adapter->diag_cnt)
+ if (!adapter->ahw->diag_cnt)
QLCDB(adapter, DRV,
"LB Test: packet #%d was not received\n", i + 1);
else
@@ -800,14 +801,15 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
int loop = 0;
int ret;
- if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
+ if (!(adapter->ahw->capabilities &
+ QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
netdev_info(netdev, "Firmware is not loopback test capable\n");
return -EOPNOTSUPP;
}
QLCDB(adapter, DRV, "%s loopback test in progress\n",
mode == QLCNIC_ILB_MODE ? "internal" : "external");
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(netdev, "Loopback test not supported for non "
"privilege function\n");
return 0;
@@ -826,7 +828,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
if (ret)
goto free_res;
- adapter->diag_cnt = 0;
+ adapter->ahw->diag_cnt = 0;
do {
msleep(500);
qlcnic_process_rcv_ring_diag(sds_ring);
@@ -835,8 +837,8 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
" configure request\n");
ret = -QLCNIC_FW_NOT_RESPOND;
goto free_res;
- } else if (adapter->diag_cnt) {
- ret = adapter->diag_cnt;
+ } else if (adapter->ahw->diag_cnt) {
+ ret = adapter->ahw->diag_cnt;
goto free_res;
}
} while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
@@ -1028,7 +1030,7 @@ static int qlcnic_set_led(struct net_device *dev,
int max_sds_rings = adapter->max_sds_rings;
int err = -EIO, active = 1;
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(dev, "LED test not supported for non "
"privilege function\n");
return -EOPNOTSUPP;
@@ -1207,14 +1209,14 @@ static u32 qlcnic_get_msglevel(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- return adapter->msg_enable;
+ return adapter->ahw->msg_enable;
}
static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- adapter->msg_enable = msglvl;
+ adapter->ahw->msg_enable = msglvl;
}
static int
@@ -1247,7 +1249,8 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
void *buffer)
{
int i, copy_sz;
- u32 *hdr_ptr, *data;
+ u32 *hdr_ptr;
+ __le32 *data;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 28a6b28192e3..49cc1ac4f057 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -792,22 +792,6 @@ static const u32 MIU_TEST_READ_DATA[] = {
#define QLCNIC_FLASH_SEM2_ULK 0x0013C014
#define QLCNIC_FLASH_LOCK_ID 0x001B2100
-#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do { \
- writel((addr & 0xFFFF0000), (void *) (bar0 + \
- QLCNIC_FW_DUMP_REG1)); \
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \
- *data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + \
- LSW(addr))); \
-} while (0)
-
-#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do { \
- writel((addr & 0xFFFF0000), (void *) (bar0 + \
- QLCNIC_FW_DUMP_REG1)); \
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \
- writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr))); \
-} while (0)
-
/* PCI function operational mode */
enum {
QLCNIC_MGMT_FUNC = 0,
@@ -832,55 +816,63 @@ enum {
#define LSD(x) ((uint32_t)((uint64_t)(x)))
#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
+#define QLCNIC_MS_CTRL 0x41000090
+#define QLCNIC_MS_ADDR_LO 0x41000094
+#define QLCNIC_MS_ADDR_HI 0x41000098
+#define QLCNIC_MS_WRTDATA_LO 0x410000A0
+#define QLCNIC_MS_WRTDATA_HI 0x410000A4
+#define QLCNIC_MS_WRTDATA_ULO 0x410000B0
+#define QLCNIC_MS_WRTDATA_UHI 0x410000B4
+#define QLCNIC_MS_RDDATA_LO 0x410000A8
+#define QLCNIC_MS_RDDATA_HI 0x410000AC
+#define QLCNIC_MS_RDDATA_ULO 0x410000B8
+#define QLCNIC_MS_RDDATA_UHI 0x410000BC
+
+#define QLCNIC_TA_WRITE_ENABLE (TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLCNIC_TA_WRITE_START (TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLCNIC_TA_START_ENABLE (TA_CTL_START | TA_CTL_ENABLE)
+
#define QLCNIC_LEGACY_INTR_CONFIG \
{ \
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \
.tgt_status_reg = ISR_INT_TARGET_STATUS, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, }, \
}
/* NIU REGS */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 2a0c9dc48eb3..fc48e000f35f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -6,6 +6,7 @@
*/
#include "qlcnic.h"
+#include "qlcnic_hdr.h"
#include <linux/slab.h>
#include <net/ip.h>
@@ -22,6 +23,15 @@
#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
#define CRB_INDIRECT_2M (0x1e0000UL)
+struct qlcnic_ms_reg_ctrl {
+ u32 ocm_window;
+ u32 control;
+ u32 hi;
+ u32 low;
+ u32 rd[4];
+ u32 wd[4];
+ u64 off;
+};
#ifndef readq
static inline u64 readq(void __iomem *addr)
@@ -266,10 +276,44 @@ static const unsigned crb_hub_agt[64] = {
0,
};
+static const u32 msi_tgt_status[8] = {
+ ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
+};
+
/* PCI Windowing for DDR regions. */
#define QLCNIC_PCIE_SEM_TIMEOUT 10000
+static void qlcnic_read_window_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ *data = readl(val);
+}
+
+static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ writel(data, val);
+ readl(val);
+}
+
int
qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
{
@@ -300,6 +344,23 @@ qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem)
QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
}
+static int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
+{
+ u32 data;
+
+ if (qlcnic_82xx_check(adapter))
+ qlcnic_read_window_reg(addr, adapter->ahw->pci_base0, &data);
+ else
+ return -EIO;
+ return data;
+}
+
+static void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
+{
+ if (qlcnic_82xx_check(adapter))
+ qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data);
+}
+
static int
qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
@@ -350,7 +411,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
tx_ring->producer = producer;
- qlcnic_update_cmd_producer(adapter, tx_ring);
+ qlcnic_update_cmd_producer(tx_ring);
__netif_tx_unlock_bh(tx_ring->txq);
@@ -434,7 +495,7 @@ void qlcnic_set_multi(struct net_device *netdev)
}
if ((netdev->flags & IFF_ALLMULTI) ||
- (netdev_mc_count(netdev) > adapter->max_mc_count)) {
+ (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
goto send_fw_cmd;
}
@@ -540,7 +601,7 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
}
}
-int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
{
struct qlcnic_nic_req req;
int rv;
@@ -863,9 +924,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
* 0 if no window access is needed. 'off' is set to 2M addr
* In: 'off' is offset from base in 128M pci map
*/
-static int
-qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
- ulong off, void __iomem **addr)
+static int qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw,
+ ulong off, void __iomem **addr)
{
const struct crb_128M_2M_sub_block_map *m;
@@ -880,7 +940,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
- *addr = adapter->ahw->pci_base0 + m->start_2M +
+ *addr = ahw->pci_base0 + m->start_2M +
(off - m->start_128M);
return 0;
}
@@ -888,7 +948,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
/*
* Not in direct map, use crb window
*/
- *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
+ *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
return 1;
}
@@ -929,7 +989,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
int rv;
void __iomem *addr = NULL;
- rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
if (rv == 0) {
writel(data, addr);
@@ -954,15 +1014,14 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
return -EIO;
}
-u32
-qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
+int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
{
unsigned long flags;
int rv;
u32 data = -1;
void __iomem *addr = NULL;
- rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
if (rv == 0)
return readl(addr);
@@ -985,46 +1044,28 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
}
-void __iomem *
-qlcnic_get_ioaddr(struct qlcnic_adapter *adapter, u32 offset)
+void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw,
+ u32 offset)
{
void __iomem *addr = NULL;
- WARN_ON(qlcnic_pci_get_crb_addr_2M(adapter, offset, &addr));
+ WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr));
return addr;
}
-
-static int
-qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter,
- u64 addr, u32 *start)
-{
- u32 window;
-
- window = OCM_WIN_P3P(addr);
-
- writel(window, adapter->ahw->ocm_win_crb);
- /* read back to flush */
- readl(adapter->ahw->ocm_win_crb);
-
- *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);
- return 0;
-}
-
-static int
-qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
- u64 *data, int op)
+static int qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter,
+ u32 window, u64 off, u64 *data, int op)
{
void __iomem *addr;
- int ret;
u32 start;
mutex_lock(&adapter->ahw->mem_lock);
- ret = qlcnic_pci_set_window_2M(adapter, off, &start);
- if (ret != 0)
- goto unlock;
+ writel(window, adapter->ahw->ocm_win_crb);
+ /* read back to flush */
+ readl(adapter->ahw->ocm_win_crb);
+ start = QLCNIC_PCI_OCM0_2M + off;
addr = adapter->ahw->pci_base0 + start;
@@ -1033,10 +1074,12 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
else /* write */
writeq(*data, addr);
-unlock:
- mutex_unlock(&adapter->ahw->mem_lock);
+ /* Set window to 0 */
+ writel(0, adapter->ahw->ocm_win_crb);
+ readl(adapter->ahw->ocm_win_crb);
- return ret;
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return 0;
}
void
@@ -1061,54 +1104,74 @@ qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
mutex_unlock(&adapter->ahw->mem_lock);
}
-#define MAX_CTL_CHECK 1000
-int
-qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
- u64 off, u64 data)
+
+/* Set MS memory control data for different adapters */
+static void qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off,
+ struct qlcnic_ms_reg_ctrl *ms)
+{
+ ms->control = QLCNIC_MS_CTRL;
+ ms->low = QLCNIC_MS_ADDR_LO;
+ ms->hi = QLCNIC_MS_ADDR_HI;
+ if (off & 0xf) {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_LO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_LO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_HI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_ULO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_ULO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_UHI;
+ } else {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_ULO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_ULO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_UHI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_LO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_LO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_HI;
+ }
+
+ ms->ocm_window = OCM_WIN_P3P(off);
+ ms->off = GET_MEM_OFFS_2M(off);
+}
+
+int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
{
- int i, j, ret;
+ int j, ret = 0;
u32 temp, off8;
- void __iomem *mem_crb;
+ struct qlcnic_ms_reg_ctrl ms;
/* Only 64-bit aligned access */
if (off & 7)
return -EIO;
- /* P3 onward, test agent base for MIU and SIU is same */
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX) ||
+ ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX)))
+ return -EIO;
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ qlcnic_set_ms_controls(adapter, off, &ms);
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
- return qlcnic_pci_mem_access_direct(adapter, off, &data, 1);
-
- return -EIO;
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, &data, 1);
-correct:
off8 = off & ~0xf;
mutex_lock(&adapter->ahw->mem_lock);
- writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
- writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
- i = 0;
- writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE),
- (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1118,24 +1181,18 @@ correct:
goto done;
}
- i = (off & 0xf) ? 0 : 2;
- writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)),
- mem_crb + MIU_TEST_AGT_WRDATA(i));
- writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)),
- mem_crb + MIU_TEST_AGT_WRDATA(i+1));
- i = (off & 0xf) ? 2 : 0;
-
- writel(data & 0xffffffff,
- mem_crb + MIU_TEST_AGT_WRDATA(i));
- writel((data >> 32) & 0xffffffff,
- mem_crb + MIU_TEST_AGT_WRDATA(i+1));
+ /* This is the modify part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0]));
+ qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1]));
+ /* This is the write part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff);
+ qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff);
- writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
- (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_START);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1154,52 +1211,41 @@ done:
return ret;
}
-int
-qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
- u64 off, u64 *data)
+int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
{
int j, ret;
u32 temp, off8;
u64 val;
- void __iomem *mem_crb;
+ struct qlcnic_ms_reg_ctrl ms;
/* Only 64-bit aligned access */
if (off & 7)
return -EIO;
+ if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX) ||
+ ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX)))
+ return -EIO;
- /* P3 onward, test agent base for MIU and SIU is same */
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
-
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ qlcnic_set_ms_controls(adapter, off, &ms);
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) {
- return qlcnic_pci_mem_access_direct(adapter,
- off, data, 0);
- }
+ if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, data, 0);
- return -EIO;
+ mutex_lock(&adapter->ahw->mem_lock);
-correct:
off8 = off & ~0xf;
- mutex_lock(&adapter->ahw->mem_lock);
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
- writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
- writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
- writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1210,13 +1256,10 @@ correct:
"failed to read through agent\n");
ret = -EIO;
} else {
- off8 = MIU_TEST_AGT_RDDATA_LO;
- if (off & 0xf)
- off8 = MIU_TEST_AGT_RDDATA_UPPER_LO;
- temp = readl(mem_crb + off8 + 4);
+ temp = qlcnic_ind_rd(adapter, ms.rd[3]);
val = (u64)temp << 32;
- val |= readl(mem_crb + off8);
+ val |= qlcnic_ind_rd(adapter, ms.rd[2]);
*data = val;
ret = 0;
}
@@ -1320,469 +1363,3 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return rv;
}
-
-/* FW dump related functions */
-static u32
-qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i;
- u32 addr, data;
- struct __crb *crb = &entry->region.crb;
- void __iomem *base = adapter->ahw->pci_base0;
-
- addr = crb->addr;
-
- for (i = 0; i < crb->no_ops; i++) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(addr);
- *buffer++ = cpu_to_le32(data);
- addr += crb->stride;
- }
- return crb->no_ops * 2 * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i, k, timeout = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- u32 addr, data;
- u8 opcode, no_ops;
- struct __ctrl *ctr = &entry->region.ctrl;
- struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
-
- addr = ctr->addr;
- no_ops = ctr->no_ops;
-
- for (i = 0; i < no_ops; i++) {
- k = 0;
- opcode = 0;
- for (k = 0; k < 8; k++) {
- if (!(ctr->opcode & (1 << k)))
- continue;
- switch (1 << k) {
- case QLCNIC_DUMP_WCRB:
- QLCNIC_WR_DUMP_REG(addr, base, ctr->val1);
- break;
- case QLCNIC_DUMP_RWCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base, data);
- break;
- case QLCNIC_DUMP_ANDCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base,
- (data & ctr->val2));
- break;
- case QLCNIC_DUMP_ORCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base,
- (data | ctr->val3));
- break;
- case QLCNIC_DUMP_POLLCRB:
- while (timeout <= ctr->timeout) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- if ((data & ctr->val2) == ctr->val1)
- break;
- msleep(1);
- timeout++;
- }
- if (timeout > ctr->timeout) {
- dev_info(&adapter->pdev->dev,
- "Timed out, aborting poll CRB\n");
- return -EINVAL;
- }
- break;
- case QLCNIC_DUMP_RD_SAVE:
- if (ctr->index_a)
- addr = t_hdr->saved_state[ctr->index_a];
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- t_hdr->saved_state[ctr->index_v] = data;
- break;
- case QLCNIC_DUMP_WRT_SAVED:
- if (ctr->index_v)
- data = t_hdr->saved_state[ctr->index_v];
- else
- data = ctr->val1;
- if (ctr->index_a)
- addr = t_hdr->saved_state[ctr->index_a];
- QLCNIC_WR_DUMP_REG(addr, base, data);
- break;
- case QLCNIC_DUMP_MOD_SAVE_ST:
- data = t_hdr->saved_state[ctr->index_v];
- data <<= ctr->shl_val;
- data >>= ctr->shr_val;
- if (ctr->val2)
- data &= ctr->val2;
- data |= ctr->val3;
- data += ctr->val1;
- t_hdr->saved_state[ctr->index_v] = data;
- break;
- default:
- dev_info(&adapter->pdev->dev,
- "Unknown opcode\n");
- break;
- }
- }
- addr += ctr->stride;
- }
- return 0;
-}
-
-static u32
-qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int loop;
- u32 val, data = 0;
- struct __mux *mux = &entry->region.mux;
- void __iomem *base = adapter->ahw->pci_base0;
-
- val = mux->val;
- for (loop = 0; loop < mux->no_ops; loop++) {
- QLCNIC_WR_DUMP_REG(mux->addr, base, val);
- QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data);
- *buffer++ = cpu_to_le32(val);
- *buffer++ = cpu_to_le32(data);
- val += mux->val_stride;
- }
- return 2 * mux->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i, loop;
- u32 cnt, addr, data, que_id = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __queue *que = &entry->region.que;
-
- addr = que->read_addr;
- cnt = que->read_addr_cnt;
-
- for (loop = 0; loop < que->no_ops; loop++) {
- QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id);
- addr = que->read_addr;
- for (i = 0; i < cnt; i++) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += que->read_addr_stride;
- }
- que_id += que->stride;
- }
- return que->no_ops * cnt * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i;
- u32 data;
- void __iomem *addr;
- struct __ocm *ocm = &entry->region.ocm;
-
- addr = adapter->ahw->pci_base0 + ocm->read_addr;
- for (i = 0; i < ocm->no_ops; i++) {
- data = readl(addr);
- *buffer++ = cpu_to_le32(data);
- addr += ocm->read_addr_stride;
- }
- return ocm->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i, count = 0;
- u32 fl_addr, size, val, lck_val, addr;
- struct __mem *rom = &entry->region.mem;
- void __iomem *base = adapter->ahw->pci_base0;
-
- fl_addr = rom->addr;
- size = rom->size/4;
-lock_try:
- lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
- if (!lck_val && count < MAX_CTL_CHECK) {
- msleep(10);
- count++;
- goto lock_try;
- }
- writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
- for (i = 0; i < size; i++) {
- addr = fl_addr & 0xFFFF0000;
- QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr);
- addr = LSW(fl_addr) + FLASH_ROM_DATA;
- QLCNIC_RD_DUMP_REG(addr, base, &val);
- fl_addr += 4;
- *buffer++ = cpu_to_le32(val);
- }
- readl(base + QLCNIC_FLASH_SEM2_ULK);
- return rom->size;
-}
-
-static u32
-qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i;
- u32 cnt, val, data, addr;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __cache *l1 = &entry->region.cache;
-
- val = l1->init_tag_val;
-
- for (i = 0; i < l1->no_ops; i++) {
- QLCNIC_WR_DUMP_REG(l1->addr, base, val);
- QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val));
- addr = l1->read_addr;
- cnt = l1->read_addr_num;
- while (cnt) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += l1->read_addr_stride;
- cnt--;
- }
- val += l1->stride;
- }
- return l1->no_ops * l1->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i;
- u32 cnt, val, data, addr;
- u8 poll_mask, poll_to, time_out = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __cache *l2 = &entry->region.cache;
-
- val = l2->init_tag_val;
- poll_mask = LSB(MSW(l2->ctrl_val));
- poll_to = MSB(MSW(l2->ctrl_val));
-
- for (i = 0; i < l2->no_ops; i++) {
- QLCNIC_WR_DUMP_REG(l2->addr, base, val);
- if (LSW(l2->ctrl_val))
- QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
- LSW(l2->ctrl_val));
- if (!poll_mask)
- goto skip_poll;
- do {
- QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
- if (!(data & poll_mask))
- break;
- msleep(1);
- time_out++;
- } while (time_out <= poll_to);
-
- if (time_out > poll_to) {
- dev_err(&adapter->pdev->dev,
- "Timeout exceeded in %s, aborting dump\n",
- __func__);
- return -EINVAL;
- }
-skip_poll:
- addr = l2->read_addr;
- cnt = l2->read_addr_num;
- while (cnt) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += l2->read_addr_stride;
- cnt--;
- }
- val += l2->stride;
- }
- return l2->no_ops * l2->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_read_memory(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- u32 addr, data, test, ret = 0;
- int i, reg_read;
- struct __mem *mem = &entry->region.mem;
- void __iomem *base = adapter->ahw->pci_base0;
-
- reg_read = mem->size;
- addr = mem->addr;
- /* check for data size of multiple of 16 and 16 byte alignment */
- if ((addr & 0xf) || (reg_read%16)) {
- dev_info(&adapter->pdev->dev,
- "Unaligned memory addr:0x%x size:0x%x\n",
- addr, reg_read);
- return -EINVAL;
- }
-
- mutex_lock(&adapter->ahw->mem_lock);
-
- while (reg_read != 0) {
- QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr);
- QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0);
- QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base,
- TA_CTL_ENABLE | TA_CTL_START);
-
- for (i = 0; i < MAX_CTL_CHECK; i++) {
- QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test);
- if (!(test & TA_CTL_BUSY))
- break;
- }
- if (i == MAX_CTL_CHECK) {
- if (printk_ratelimit()) {
- dev_err(&adapter->pdev->dev,
- "failed to read through agent\n");
- ret = -EINVAL;
- goto out;
- }
- }
- for (i = 0; i < 4; i++) {
- QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data);
- *buffer++ = cpu_to_le32(data);
- }
- addr += 16;
- reg_read -= 16;
- ret += 16;
- }
-out:
- mutex_unlock(&adapter->ahw->mem_lock);
- return mem->size;
-}
-
-static u32
-qlcnic_dump_nop(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- return 0;
-}
-
-struct qlcnic_dump_operations fw_dump_ops[] = {
- { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
- { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
- { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
- { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
- { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
- { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
- { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
- { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
- { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
- { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
- { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
- { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
-};
-
-/* Walk the template and collect dump for each entry in the dump template */
-static int
-qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
- u32 size)
-{
- int ret = 1;
- if (size != entry->hdr.cap_size) {
- dev_info(dev,
- "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
- entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
- dev_info(dev, "Aborting further dump capture\n");
- ret = 0;
- }
- return ret;
-}
-
-int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
-{
- u32 *buffer;
- char mesg[64];
- char *msg[] = {mesg, NULL};
- int i, k, ops_cnt, ops_index, dump_size = 0;
- u32 entry_offset, dump, no_entries, buf_offset = 0;
- struct qlcnic_dump_entry *entry;
- struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
- struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
-
- if (fw_dump->clr) {
- dev_info(&adapter->pdev->dev,
- "Previous dump not cleared, not capturing dump\n");
- return -EIO;
- }
- /* Calculate the size for dump data area only */
- for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
- if (i & tmpl_hdr->drv_cap_mask)
- dump_size += tmpl_hdr->cap_sizes[k];
- if (!dump_size)
- return -EIO;
-
- fw_dump->data = vzalloc(dump_size);
- if (!fw_dump->data) {
- dev_info(&adapter->pdev->dev,
- "Unable to allocate (%d KB) for fw dump\n",
- dump_size/1024);
- return -ENOMEM;
- }
- buffer = fw_dump->data;
- fw_dump->size = dump_size;
- no_entries = tmpl_hdr->num_entries;
- ops_cnt = ARRAY_SIZE(fw_dump_ops);
- entry_offset = tmpl_hdr->offset;
- tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
- tmpl_hdr->sys_info[1] = adapter->fw_version;
-
- for (i = 0; i < no_entries; i++) {
- entry = (void *)tmpl_hdr + entry_offset;
- if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- entry_offset += entry->hdr.offset;
- continue;
- }
- /* Find the handler for this entry */
- ops_index = 0;
- while (ops_index < ops_cnt) {
- if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
- break;
- ops_index++;
- }
- if (ops_index == ops_cnt) {
- dev_info(&adapter->pdev->dev,
- "Invalid entry type %d, exiting dump\n",
- entry->hdr.type);
- goto error;
- }
- /* Collect dump for this entry */
- dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
- if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
- dump))
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- buf_offset += entry->hdr.cap_size;
- entry_offset += entry->hdr.offset;
- buffer = fw_dump->data + buf_offset;
- }
- if (dump_size != buf_offset) {
- dev_info(&adapter->pdev->dev,
- "Captured(%d) and expected size(%d) do not match\n",
- buf_offset, dump_size);
- goto error;
- } else {
- fw_dump->clr = 1;
- snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
- adapter->netdev->name);
- dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
- fw_dump->size);
- /* Send a udev event to notify availability of FW dump */
- kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
- return 0;
- }
-error:
- vfree(fw_dump->data);
- return -EINVAL;
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 0bcda9c51e9b..de79cde233de 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -25,10 +25,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
#define QLCNIC_ADDR_ERROR (0xffffffff)
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring);
-
static int
qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
@@ -250,7 +246,8 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
rds_ring->dma_size =
QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (adapter->ahw->capabilities &
+ QLCNIC_FW_CAPABILITY_HW_LRO)
rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
rds_ring->skb_size =
@@ -659,7 +656,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
"Not an Ethernet NIC func=%u\n", val);
return -EIO;
}
- adapter->physical_port = (val >> 2);
+ adapter->ahw->physical_port = (val >> 2);
if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
timeo = QLCNIC_INIT_TIMEOUT_SECS;
@@ -778,15 +775,15 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter)
static
struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
{
- u32 i;
+ u32 i, entries;
struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
- __le32 entries = cpu_to_le32(directory->num_entries);
+ entries = le32_to_cpu(directory->num_entries);
for (i = 0; i < entries; i++) {
- __le32 offs = cpu_to_le32(directory->findex) +
- (i * cpu_to_le32(directory->entry_size));
- __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
+ u32 offs = le32_to_cpu(directory->findex) +
+ i * le32_to_cpu(directory->entry_size);
+ u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8));
if (tab_type == section)
return (struct uni_table_desc *) &unirom[offs];
@@ -802,17 +799,16 @@ qlcnic_validate_header(struct qlcnic_adapter *adapter)
{
const u8 *unirom = adapter->fw->data;
struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
- __le32 fw_file_size = adapter->fw->size;
- __le32 entries;
- __le32 entry_size;
- __le32 tab_size;
+ u32 entries, entry_size, tab_size, fw_file_size;
+
+ fw_file_size = adapter->fw->size;
if (fw_file_size < FILEHEADER_SIZE)
return -EINVAL;
- entries = cpu_to_le32(directory->num_entries);
- entry_size = cpu_to_le32(directory->entry_size);
- tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
+ entries = le32_to_cpu(directory->num_entries);
+ entry_size = le32_to_cpu(directory->entry_size);
+ tab_size = le32_to_cpu(directory->findex) + (entries * entry_size);
if (fw_file_size < tab_size)
return -EINVAL;
@@ -825,29 +821,29 @@ qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
{
struct uni_table_desc *tab_desc;
struct uni_data_desc *descr;
+ u32 offs, tab_size, data_size, idx;
const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- QLCNIC_UNI_BOOTLD_IDX_OFF));
- __le32 offs;
- __le32 tab_size;
- __le32 data_size;
+ __le32 temp;
+ temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+ QLCNIC_UNI_BOOTLD_IDX_OFF);
+ idx = le32_to_cpu(temp);
tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
if (!tab_desc)
return -EINVAL;
- tab_size = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+ tab_size = le32_to_cpu(tab_desc->findex) +
+ le32_to_cpu(tab_desc->entry_size) * (idx + 1);
if (adapter->fw->size < tab_size)
return -EINVAL;
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx));
+ offs = le32_to_cpu(tab_desc->findex) +
+ le32_to_cpu(tab_desc->entry_size) * idx;
descr = (struct uni_data_desc *)&unirom[offs];
- data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+ data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
if (adapter->fw->size < data_size)
return -EINVAL;
@@ -861,27 +857,27 @@ qlcnic_validate_fw(struct qlcnic_adapter *adapter)
struct uni_table_desc *tab_desc;
struct uni_data_desc *descr;
const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- QLCNIC_UNI_FIRMWARE_IDX_OFF));
- __le32 offs;
- __le32 tab_size;
- __le32 data_size;
+ u32 offs, tab_size, data_size, idx;
+ __le32 temp;
+ temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+ QLCNIC_UNI_FIRMWARE_IDX_OFF);
+ idx = le32_to_cpu(temp);
tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
if (!tab_desc)
return -EINVAL;
- tab_size = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+ tab_size = le32_to_cpu(tab_desc->findex) +
+ le32_to_cpu(tab_desc->entry_size) * (idx + 1);
if (adapter->fw->size < tab_size)
return -EINVAL;
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx));
+ offs = le32_to_cpu(tab_desc->findex) +
+ le32_to_cpu(tab_desc->entry_size) * idx;
descr = (struct uni_data_desc *)&unirom[offs];
- data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+ data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
if (adapter->fw->size < data_size)
return -EINVAL;
@@ -895,19 +891,17 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
struct uni_table_desc *ptab_descr;
const u8 *unirom = adapter->fw->data;
int mn_present = qlcnic_has_mn(adapter);
- __le32 entries;
- __le32 entry_size;
- __le32 tab_size;
- u32 i;
+ u32 entries, entry_size, tab_size, i;
+ __le32 temp;
ptab_descr = qlcnic_get_table_desc(unirom,
QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
if (!ptab_descr)
return -EINVAL;
- entries = cpu_to_le32(ptab_descr->num_entries);
- entry_size = cpu_to_le32(ptab_descr->entry_size);
- tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
+ entries = le32_to_cpu(ptab_descr->num_entries);
+ entry_size = le32_to_cpu(ptab_descr->entry_size);
+ tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size);
if (adapter->fw->size < tab_size)
return -EINVAL;
@@ -915,16 +909,16 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
nomn:
for (i = 0; i < entries; i++) {
- __le32 flags, file_chiprev, offs;
+ u32 flags, file_chiprev, offs;
u8 chiprev = adapter->ahw->revision_id;
u32 flagbit;
- offs = cpu_to_le32(ptab_descr->findex) +
- (i * cpu_to_le32(ptab_descr->entry_size));
- flags = cpu_to_le32(*((int *)&unirom[offs] +
- QLCNIC_UNI_FLAGS_OFF));
- file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
- QLCNIC_UNI_CHIP_REV_OFF));
+ offs = le32_to_cpu(ptab_descr->findex) +
+ i * le32_to_cpu(ptab_descr->entry_size);
+ temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF);
+ flags = le32_to_cpu(temp);
+ temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF);
+ file_chiprev = le32_to_cpu(temp);
flagbit = mn_present ? 1 : 2;
@@ -976,18 +970,20 @@ struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
u32 section, u32 idx_offset)
{
const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- idx_offset));
struct uni_table_desc *tab_desc;
- __le32 offs;
+ u32 offs, idx;
+ __le32 temp;
+
+ temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset);
+ idx = le32_to_cpu(temp);
tab_desc = qlcnic_get_table_desc(unirom, section);
if (tab_desc == NULL)
return NULL;
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * idx);
+ offs = le32_to_cpu(tab_desc->findex) +
+ le32_to_cpu(tab_desc->entry_size) * idx;
return (struct uni_data_desc *)&unirom[offs];
}
@@ -996,11 +992,13 @@ static u8 *
qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
{
u32 offs = QLCNIC_BOOTLD_START;
+ struct uni_data_desc *data_desc;
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_BOOTLD,
- QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
+ data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
+ QLCNIC_UNI_BOOTLD_IDX_OFF);
+
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ offs = le32_to_cpu(data_desc->findex);
return (u8 *)&adapter->fw->data[offs];
}
@@ -1009,43 +1007,48 @@ static u8 *
qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
{
u32 offs = QLCNIC_IMAGE_START;
+ struct uni_data_desc *data_desc;
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_FW,
- QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
+ data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+ QLCNIC_UNI_FIRMWARE_IDX_OFF);
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ offs = le32_to_cpu(data_desc->findex);
return (u8 *)&adapter->fw->data[offs];
}
-static __le32
-qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
{
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_FW,
- QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
+ struct uni_data_desc *data_desc;
+ const u8 *unirom = adapter->fw->data;
+
+ data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+ QLCNIC_UNI_FIRMWARE_IDX_OFF);
+
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ return le32_to_cpu(data_desc->size);
else
- return cpu_to_le32(
- *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]);
+ return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]);
}
-static __le32
-qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
{
struct uni_data_desc *fw_data_desc;
const struct firmware *fw = adapter->fw;
- __le32 major, minor, sub;
+ u32 major, minor, sub;
+ __le32 version_offset;
const u8 *ver_str;
int i, ret;
- if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+ version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET];
+ return le32_to_cpu(version_offset);
+ }
fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
QLCNIC_UNI_FIRMWARE_IDX_OFF);
- ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
- cpu_to_le32(fw_data_desc->size) - 17;
+ ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) +
+ le32_to_cpu(fw_data_desc->size) - 17;
for (i = 0; i < 12; i++) {
if (!strncmp(&ver_str[i], "REV=", 4)) {
@@ -1061,18 +1064,20 @@ qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
return 0;
}
-static __le32
-qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
{
const struct firmware *fw = adapter->fw;
- __le32 bios_ver, prd_off = adapter->file_prd_off;
+ u32 bios_ver, prd_off = adapter->file_prd_off;
+ u8 *version_offset;
+ __le32 temp;
- if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32(
- *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+ version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET];
+ return le32_to_cpu(*(__le32 *)version_offset);
+ }
- bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
- + QLCNIC_UNI_BIOS_VERSION_OFF));
+ temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF);
+ bios_ver = le32_to_cpu(temp);
return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
}
@@ -1131,24 +1136,24 @@ static const char *fw_name[] = {
int
qlcnic_load_firmware(struct qlcnic_adapter *adapter)
{
- u64 *ptr64;
+ __le64 *ptr64;
u32 i, flashaddr, size;
const struct firmware *fw = adapter->fw;
struct pci_dev *pdev = adapter->pdev;
dev_info(&pdev->dev, "loading firmware from %s\n",
- fw_name[adapter->fw_type]);
+ fw_name[adapter->ahw->fw_type]);
if (fw) {
- __le64 data;
+ u64 data;
size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
- ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter);
+ ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter);
flashaddr = QLCNIC_BOOTLD_START;
for (i = 0; i < size; i++) {
- data = cpu_to_le64(ptr64[i]);
+ data = le64_to_cpu(ptr64[i]);
if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
return -EIO;
@@ -1156,13 +1161,13 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
flashaddr += 8;
}
- size = (__force u32)qlcnic_get_fw_size(adapter) / 8;
+ size = qlcnic_get_fw_size(adapter) / 8;
- ptr64 = (u64 *)qlcnic_get_fw_offs(adapter);
+ ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter);
flashaddr = QLCNIC_IMAGE_START;
for (i = 0; i < size; i++) {
- data = cpu_to_le64(ptr64[i]);
+ data = le64_to_cpu(ptr64[i]);
if (qlcnic_pci_mem_write_2M(adapter,
flashaddr, data))
@@ -1171,9 +1176,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
flashaddr += 8;
}
- size = (__force u32)qlcnic_get_fw_size(adapter) % 8;
+ size = qlcnic_get_fw_size(adapter) % 8;
if (size) {
- data = cpu_to_le64(ptr64[i]);
+ data = le64_to_cpu(ptr64[i]);
if (qlcnic_pci_mem_write_2M(adapter,
flashaddr, data))
@@ -1225,11 +1230,11 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
static int
qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
{
- __le32 val;
+ u32 val;
u32 ver, bios, min_size;
struct pci_dev *pdev = adapter->pdev;
const struct firmware *fw = adapter->fw;
- u8 fw_type = adapter->fw_type;
+ u8 fw_type = adapter->ahw->fw_type;
if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
if (qlcnic_validate_unified_romimage(adapter))
@@ -1237,8 +1242,8 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
min_size = QLCNIC_UNI_FW_MIN_SIZE;
} else {
- val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
- if ((__force u32)val != QLCNIC_BDINFO_MAGIC)
+ val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
+ if (val != QLCNIC_BDINFO_MAGIC)
return -EINVAL;
min_size = QLCNIC_FW_MIN_SIZE;
@@ -1259,7 +1264,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
val = qlcnic_get_bios_version(adapter);
qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
- if ((__force u32)val != bios) {
+ if (val != bios) {
dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
fw_name[fw_type]);
return -EINVAL;
@@ -1274,7 +1279,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
{
u8 fw_type;
- switch (adapter->fw_type) {
+ switch (adapter->ahw->fw_type) {
case QLCNIC_UNKNOWN_ROMIMAGE:
fw_type = QLCNIC_UNIFIED_ROMIMAGE;
break;
@@ -1285,7 +1290,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
break;
}
- adapter->fw_type = fw_type;
+ adapter->ahw->fw_type = fw_type;
}
@@ -1295,16 +1300,17 @@ void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int rc;
- adapter->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
+ adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
next:
qlcnic_get_next_fwtype(adapter);
- if (adapter->fw_type == QLCNIC_FLASH_ROMIMAGE) {
+ if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
adapter->fw = NULL;
} else {
rc = request_firmware(&adapter->fw,
- fw_name[adapter->fw_type], &pdev->dev);
+ fw_name[adapter->ahw->fw_type],
+ &pdev->dev);
if (rc != 0)
goto next;
@@ -1324,633 +1330,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter)
release_firmware(adapter->fw);
adapter->fw = NULL;
}
-
-static void
-qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
- struct qlcnic_fw_msg *msg)
-{
- u32 cable_OUI;
- u16 cable_len;
- u16 link_speed;
- u8 link_status, module, duplex, autoneg;
- u8 lb_status = 0;
- struct net_device *netdev = adapter->netdev;
-
- adapter->has_link_events = 1;
-
- cable_OUI = msg->body[1] & 0xffffffff;
- cable_len = (msg->body[1] >> 32) & 0xffff;
- link_speed = (msg->body[1] >> 48) & 0xffff;
-
- link_status = msg->body[2] & 0xff;
- duplex = (msg->body[2] >> 16) & 0xff;
- autoneg = (msg->body[2] >> 24) & 0xff;
- lb_status = (msg->body[2] >> 32) & 0x3;
-
- module = (msg->body[2] >> 8) & 0xff;
- if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
- dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, "
- "length %d\n", cable_OUI, cable_len);
- else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
- dev_info(&netdev->dev, "unsupported cable length %d\n",
- cable_len);
-
- if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
- lb_status == QLCNIC_ELB_MODE))
- adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
-
- qlcnic_advert_link_change(adapter, link_status);
-
- if (duplex == LINKEVENT_FULL_DUPLEX)
- adapter->link_duplex = DUPLEX_FULL;
- else
- adapter->link_duplex = DUPLEX_HALF;
-
- adapter->module_type = module;
- adapter->link_autoneg = autoneg;
-
- if (link_status) {
- adapter->link_speed = link_speed;
- } else {
- adapter->link_speed = SPEED_UNKNOWN;
- adapter->link_duplex = DUPLEX_UNKNOWN;
- }
-}
-
-static void
-qlcnic_handle_fw_message(int desc_cnt, int index,
- struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_fw_msg msg;
- struct status_desc *desc;
- struct qlcnic_adapter *adapter;
- struct device *dev;
- int i = 0, opcode, ret;
-
- while (desc_cnt > 0 && i < 8) {
- desc = &sds_ring->desc_head[index];
- msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
- msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
-
- index = get_next_index(index, sds_ring->num_desc);
- desc_cnt--;
- }
-
- adapter = sds_ring->adapter;
- dev = &adapter->pdev->dev;
- opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
-
- switch (opcode) {
- case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
- qlcnic_handle_linkevent(adapter, &msg);
- break;
- case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
- ret = (u32)(msg.body[1]);
- switch (ret) {
- case 0:
- adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
- break;
- case 1:
- dev_info(dev, "loopback already in progress\n");
- adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
- break;
- case 2:
- dev_info(dev, "loopback cable is not connected\n");
- adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
- break;
- default:
- dev_info(dev, "loopback configure request failed,"
- " ret %x\n", ret);
- adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static int
-qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring,
- struct qlcnic_rx_buffer *buffer)
-{
- struct sk_buff *skb;
- dma_addr_t dma;
- struct pci_dev *pdev = adapter->pdev;
-
- skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
- if (!skb) {
- adapter->stats.skb_alloc_failure++;
- return -ENOMEM;
- }
-
- skb_reserve(skb, NET_IP_ALIGN);
-
- dma = pci_map_single(pdev, skb->data,
- rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-
- if (pci_dma_mapping_error(pdev, dma)) {
- adapter->stats.rx_dma_map_error++;
- dev_kfree_skb_any(skb);
- return -ENOMEM;
- }
-
- buffer->skb = skb;
- buffer->dma = dma;
-
- return 0;
-}
-
-static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
-{
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- if (unlikely(buffer->skb == NULL)) {
- WARN_ON(1);
- return NULL;
- }
-
- pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
-
- skb = buffer->skb;
-
- if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
- (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
- adapter->stats.csummed++;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else {
- skb_checksum_none_assert(skb);
- }
-
- buffer->skb = NULL;
-
- return skb;
-}
-
-static inline int
-qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
- u16 *vlan_tag)
-{
- struct ethhdr *eth_hdr;
-
- if (!__vlan_get_tag(skb, vlan_tag)) {
- eth_hdr = (struct ethhdr *) skb->data;
- memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
- skb_pull(skb, VLAN_HLEN);
- }
- if (!adapter->pvid)
- return 0;
-
- if (*vlan_tag == adapter->pvid) {
- /* Outer vlan tag. Packet should follow non-vlan path */
- *vlan_tag = 0xffff;
- return 0;
- }
- if (adapter->flags & QLCNIC_TAGGING_ENABLED)
- return 0;
-
- return -EINVAL;
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_rcv(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0)
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum, pkt_offset;
- u16 vid = 0xffff;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_sts_refhandle(sts_data0);
- if (unlikely(index >= rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- length = qlcnic_get_sts_totallength(sts_data0);
- cksum = qlcnic_get_sts_status(sts_data0);
- pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
- if (!skb)
- return buffer;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (pkt_offset)
- skb_pull(skb, pkt_offset);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
-
- napi_gro_receive(&sds_ring->napi, skb);
-
- adapter->stats.rx_pkts++;
- adapter->stats.rxbytes += length;
-
- return buffer;
-}
-
-#define QLC_TCP_HDR_SIZE 20
-#define QLC_TCP_TS_OPTION_SIZE 12
-#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_lro(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0, u64 sts_data1)
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- struct iphdr *iph;
- struct tcphdr *th;
- bool push, timestamp;
- int l2_hdr_offset, l4_hdr_offset;
- int index;
- u16 lro_length, length, data_offset;
- u32 seq_number;
- u16 vid = 0xffff;
-
- if (unlikely(ring > adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_lro_sts_refhandle(sts_data0);
- if (unlikely(index > rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
- lro_length = qlcnic_get_lro_sts_length(sts_data0);
- l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
- l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
- push = qlcnic_get_lro_sts_push_flag(sts_data0);
- seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
- if (!skb)
- return buffer;
-
- if (timestamp)
- data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
- else
- data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
-
- skb_put(skb, lro_length + data_offset);
-
- skb_pull(skb, l2_hdr_offset);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- iph = (struct iphdr *)skb->data;
- th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-
- length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
- iph->tot_len = htons(length);
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
- th->psh = push;
- th->seq = htonl(seq_number);
-
- length = skb->len;
-
- if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
- skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
- netif_receive_skb(skb);
-
- adapter->stats.lro_pkts++;
- adapter->stats.lrobytes += length;
-
- return buffer;
-}
-
-int
-qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct list_head *cur;
- struct status_desc *desc;
- struct qlcnic_rx_buffer *rxbuf;
- u64 sts_data0, sts_data1;
-
- int count = 0;
- int opcode, ring, desc_cnt;
- u32 consumer = sds_ring->consumer;
-
- while (count < max) {
- desc = &sds_ring->desc_head[consumer];
- sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
- if (!(sts_data0 & STATUS_OWNER_HOST))
- break;
-
- desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
- opcode = qlcnic_get_sts_opcode(sts_data0);
-
- switch (opcode) {
- case QLCNIC_RXPKT_DESC:
- case QLCNIC_OLD_RXPKT_DESC:
- case QLCNIC_SYN_OFFLOAD:
- ring = qlcnic_get_sts_type(sts_data0);
- rxbuf = qlcnic_process_rcv(adapter, sds_ring,
- ring, sts_data0);
- break;
- case QLCNIC_LRO_DESC:
- ring = qlcnic_get_lro_sts_type(sts_data0);
- sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
- rxbuf = qlcnic_process_lro(adapter, sds_ring,
- ring, sts_data0, sts_data1);
- break;
- case QLCNIC_RESPONSE_DESC:
- qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
- default:
- goto skip;
- }
-
- WARN_ON(desc_cnt > 1);
-
- if (likely(rxbuf))
- list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
- else
- adapter->stats.null_rxbuf++;
-
-skip:
- for (; desc_cnt > 0; desc_cnt--) {
- desc = &sds_ring->desc_head[consumer];
- desc->status_desc_data[0] =
- cpu_to_le64(STATUS_OWNER_PHANTOM);
- consumer = get_next_index(consumer, sds_ring->num_desc);
- }
- count++;
- }
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- struct qlcnic_host_rds_ring *rds_ring =
- &adapter->recv_ctx->rds_rings[ring];
-
- if (!list_empty(&sds_ring->free_list[ring])) {
- list_for_each(cur, &sds_ring->free_list[ring]) {
- rxbuf = list_entry(cur,
- struct qlcnic_rx_buffer, list);
- qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
- }
- spin_lock(&rds_ring->lock);
- list_splice_tail_init(&sds_ring->free_list[ring],
- &rds_ring->free_list);
- spin_unlock(&rds_ring->lock);
- }
-
- qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
- }
-
- if (count) {
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
- }
-
- return count;
-}
-
-void
-qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
-{
- struct rcv_desc *pdesc;
- struct qlcnic_rx_buffer *buffer;
- int count = 0;
- u32 producer;
- struct list_head *head;
-
- producer = rds_ring->producer;
-
- head = &rds_ring->free_list;
- while (!list_empty(head)) {
-
- buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
- if (!buffer->skb) {
- if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
- break;
- }
-
- count++;
- list_del(&buffer->list);
-
- /* make a rcv descriptor */
- pdesc = &rds_ring->desc_head[producer];
- pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-
- producer = get_next_index(producer, rds_ring->num_desc);
- }
-
- if (count) {
- rds_ring->producer = producer;
- writel((producer-1) & (rds_ring->num_desc-1),
- rds_ring->crb_rcv_producer);
- }
-}
-
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
-{
- struct rcv_desc *pdesc;
- struct qlcnic_rx_buffer *buffer;
- int count = 0;
- uint32_t producer;
- struct list_head *head;
-
- if (!spin_trylock(&rds_ring->lock))
- return;
-
- producer = rds_ring->producer;
-
- head = &rds_ring->free_list;
- while (!list_empty(head)) {
-
- buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
- if (!buffer->skb) {
- if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
- break;
- }
-
- count++;
- list_del(&buffer->list);
-
- /* make a rcv descriptor */
- pdesc = &rds_ring->desc_head[producer];
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
- pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-
- producer = get_next_index(producer, rds_ring->num_desc);
- }
-
- if (count) {
- rds_ring->producer = producer;
- writel((producer - 1) & (rds_ring->num_desc - 1),
- rds_ring->crb_rcv_producer);
- }
- spin_unlock(&rds_ring->lock);
-}
-
-static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
-{
- int i;
- unsigned char *data = skb->data;
-
- printk(KERN_INFO "\n");
- for (i = 0; i < skb->len; i++) {
- QLCDB(adapter, DRV, "%02x ", data[i]);
- if ((i & 0x0f) == 8)
- printk(KERN_INFO "\n");
- }
-}
-
-void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0)
-{
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum, pkt_offset;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_sts_refhandle(sts_data0);
- length = qlcnic_get_sts_totallength(sts_data0);
- if (unlikely(index >= rds_ring->num_desc))
- return;
-
- cksum = qlcnic_get_sts_status(sts_data0);
- pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
- if (!skb)
- return;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (pkt_offset)
- skb_pull(skb, pkt_offset);
-
- if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
- adapter->diag_cnt++;
- else
- dump_skb(skb, adapter);
-
- dev_kfree_skb_any(skb);
- adapter->stats.rx_pkts++;
- adapter->stats.rxbytes += length;
-
- return;
-}
-
-void
-qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct status_desc *desc;
- u64 sts_data0;
- int ring, opcode, desc_cnt;
-
- u32 consumer = sds_ring->consumer;
-
- desc = &sds_ring->desc_head[consumer];
- sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
- if (!(sts_data0 & STATUS_OWNER_HOST))
- return;
-
- desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
- opcode = qlcnic_get_sts_opcode(sts_data0);
- switch (opcode) {
- case QLCNIC_RESPONSE_DESC:
- qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
- break;
- default:
- ring = qlcnic_get_sts_type(sts_data0);
- qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
- break;
- }
-
- for (; desc_cnt > 0; desc_cnt--) {
- desc = &sds_ring->desc_head[consumer];
- desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
- consumer = get_next_index(consumer, sds_ring->num_desc);
- }
-
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
-}
-
-void
-qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
- u8 alt_mac, u8 *mac)
-{
- u32 mac_low, mac_high;
- int i;
-
- mac_low = off1;
- mac_high = off2;
-
- if (alt_mac) {
- mac_low |= (mac_low >> 16) | (mac_high << 16);
- mac_high >>= 16;
- }
-
- for (i = 0; i < 2; i++)
- mac[i] = (u8)(mac_high >> ((1 - i) * 8));
- for (i = 2; i < 6; i++)
- mac[i] = (u8)(mac_low >> ((5 - i) * 8));
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
new file mode 100644
index 000000000000..6f82812d0fab
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -0,0 +1,1309 @@
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+
+#include "qlcnic.h"
+
+#define QLCNIC_MAC_HASH(MAC)\
+ ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+#define TX_ETHER_PKT 0x01
+#define TX_TCP_PKT 0x02
+#define TX_UDP_PKT 0x03
+#define TX_IP_PKT 0x04
+#define TX_TCP_LSO 0x05
+#define TX_TCP_LSO6 0x06
+#define TX_TCPV6_PKT 0x0b
+#define TX_UDPV6_PKT 0x0c
+#define FLAGS_VLAN_TAGGED 0x10
+#define FLAGS_VLAN_OOB 0x40
+
+#define qlcnic_set_tx_vlan_tci(cmd_desc, v) \
+ (cmd_desc)->vlan_TCI = cpu_to_le16(v);
+#define qlcnic_set_cmd_desc_port(cmd_desc, var) \
+ ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
+#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \
+ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
+
+#define qlcnic_set_tx_port(_desc, _port) \
+ ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
+
+#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
+ ((_desc)->flags_opcode |= \
+ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
+
+#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
+ ((_desc)->nfrags__length = \
+ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
+
+/* owner bits of status_desc */
+#define STATUS_OWNER_HOST (0x1ULL << 56)
+#define STATUS_OWNER_PHANTOM (0x2ULL << 56)
+
+/* Status descriptor:
+ 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+ 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+ 53-55 desc_cnt, 56-57 owner, 58-63 opcode
+ */
+#define qlcnic_get_sts_port(sts_data) \
+ ((sts_data) & 0x0F)
+#define qlcnic_get_sts_status(sts_data) \
+ (((sts_data) >> 4) & 0x0F)
+#define qlcnic_get_sts_type(sts_data) \
+ (((sts_data) >> 8) & 0x0F)
+#define qlcnic_get_sts_totallength(sts_data) \
+ (((sts_data) >> 12) & 0xFFFF)
+#define qlcnic_get_sts_refhandle(sts_data) \
+ (((sts_data) >> 28) & 0xFFFF)
+#define qlcnic_get_sts_prot(sts_data) \
+ (((sts_data) >> 44) & 0x0F)
+#define qlcnic_get_sts_pkt_offset(sts_data) \
+ (((sts_data) >> 48) & 0x1F)
+#define qlcnic_get_sts_desc_cnt(sts_data) \
+ (((sts_data) >> 53) & 0x7)
+#define qlcnic_get_sts_opcode(sts_data) \
+ (((sts_data) >> 58) & 0x03F)
+
+#define qlcnic_get_lro_sts_refhandle(sts_data) \
+ ((sts_data) & 0x07FFF)
+#define qlcnic_get_lro_sts_length(sts_data) \
+ (((sts_data) >> 16) & 0x0FFFF)
+#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \
+ (((sts_data) >> 32) & 0x0FF)
+#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data) \
+ (((sts_data) >> 40) & 0x0FF)
+#define qlcnic_get_lro_sts_timestamp(sts_data) \
+ (((sts_data) >> 48) & 0x1)
+#define qlcnic_get_lro_sts_type(sts_data) \
+ (((sts_data) >> 49) & 0x7)
+#define qlcnic_get_lro_sts_push_flag(sts_data) \
+ (((sts_data) >> 52) & 0x1)
+#define qlcnic_get_lro_sts_seq_number(sts_data) \
+ ((sts_data) & 0x0FFFFFFFF)
+#define qlcnic_get_lro_sts_mss(sts_data1) \
+ ((sts_data1 >> 32) & 0x0FFFF)
+
+/* opcode field in status_desc */
+#define QLCNIC_SYN_OFFLOAD 0x03
+#define QLCNIC_RXPKT_DESC 0x04
+#define QLCNIC_OLD_RXPKT_DESC 0x3f
+#define QLCNIC_RESPONSE_DESC 0x05
+#define QLCNIC_LRO_DESC 0x12
+
+/* for status field in status_desc */
+#define STATUS_CKSUM_LOOP 0
+#define STATUS_CKSUM_OK 2
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+ u64 uaddr, __le16 vlan_id,
+ struct qlcnic_host_tx_ring *tx_ring)
+{
+ struct cmd_desc_type0 *hwdesc;
+ struct qlcnic_nic_req *req;
+ struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
+ u32 producer;
+ u64 word;
+
+ producer = tx_ring->producer;
+ hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+ req = (struct qlcnic_nic_req *)hwdesc;
+ memset(req, 0, sizeof(struct qlcnic_nic_req));
+ req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+ word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+ req->req_hdr = cpu_to_le64(word);
+
+ mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+ mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+ memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+ vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+ vlan_req->vlan_id = vlan_id;
+
+ tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+ smp_mb();
+}
+
+static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
+{
+ struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct qlcnic_filter *fil, *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ u64 src_addr = 0;
+ __le16 vlan_id = 0;
+ u8 hindex;
+
+ if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
+ return;
+
+ if (adapter->fhash.fnum >= adapter->fhash.fmax)
+ return;
+
+ /* Only NPAR capable devices support vlan based learning*/
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ vlan_id = first_desc->vlan_TCI;
+ memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+ hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+ head = &(adapter->fhash.fhead[hindex]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+ tmp_fil->vlan_id == vlan_id) {
+
+ if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
+ qlcnic_change_filter(adapter, src_addr, vlan_id,
+ tx_ring);
+ tmp_fil->ftime = jiffies;
+ return;
+ }
+ }
+
+ fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+ if (!fil)
+ return;
+
+ qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+ fil->ftime = jiffies;
+ fil->vlan_id = vlan_id;
+ memcpy(fil->faddr, &src_addr, ETH_ALEN);
+
+ spin_lock(&adapter->mac_learn_lock);
+
+ hlist_add_head(&(fil->fnode), head);
+ adapter->fhash.fnum++;
+
+ spin_unlock(&adapter->mac_learn_lock);
+}
+
+static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
+ struct cmd_desc_type0 *first_desc, struct sk_buff *skb)
+{
+ u8 l4proto, opcode = 0, hdr_len = 0;
+ u16 flags = 0, vlan_tci = 0;
+ int copied, offset, copy_len, size;
+ struct cmd_desc_type0 *hwdesc;
+ struct vlan_ethhdr *vh;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+ u16 protocol = ntohs(skb->protocol);
+ u32 producer = tx_ring->producer;
+
+ if (protocol == ETH_P_8021Q) {
+ vh = (struct vlan_ethhdr *)skb->data;
+ flags = FLAGS_VLAN_TAGGED;
+ vlan_tci = ntohs(vh->h_vlan_TCI);
+ protocol = ntohs(vh->h_vlan_encapsulated_proto);
+ } else if (vlan_tx_tag_present(skb)) {
+ flags = FLAGS_VLAN_OOB;
+ vlan_tci = vlan_tx_tag_get(skb);
+ }
+ if (unlikely(adapter->pvid)) {
+ if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+ return -EIO;
+ if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+ goto set_flags;
+
+ flags = FLAGS_VLAN_OOB;
+ vlan_tci = adapter->pvid;
+ }
+set_flags:
+ qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
+ qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ if (*(skb->data) & BIT_0) {
+ flags |= BIT_0;
+ memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
+ }
+ opcode = TX_ETHER_PKT;
+ if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ first_desc->total_hdr_length = hdr_len;
+ opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
+
+ /* For LSO, we need to copy the MAC/IP/TCP headers into
+ * the descriptor ring */
+ copied = 0;
+ offset = 2;
+
+ if (flags & FLAGS_VLAN_OOB) {
+ first_desc->total_hdr_length += VLAN_HLEN;
+ first_desc->tcp_hdr_offset = VLAN_HLEN;
+ first_desc->ip_hdr_offset = VLAN_HLEN;
+
+ /* Only in case of TSO on vlan device */
+ flags |= FLAGS_VLAN_TAGGED;
+
+ /* Create a TSO vlan header template for firmware */
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) -
+ offset, hdr_len + VLAN_HLEN);
+
+ vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
+ skb_copy_from_linear_data(skb, vh, 12);
+ vh->h_vlan_proto = htons(ETH_P_8021Q);
+ vh->h_vlan_TCI = htons(vlan_tci);
+
+ skb_copy_from_linear_data_offset(skb, 12,
+ (char *)vh + 16,
+ copy_len - 16);
+ copied = copy_len - VLAN_HLEN;
+ offset = 0;
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ while (copied < hdr_len) {
+ size = (int)sizeof(struct cmd_desc_type0) - offset;
+ copy_len = min(size, (hdr_len - copied));
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+ skb_copy_from_linear_data_offset(skb, copied,
+ (char *)hwdesc +
+ offset, copy_len);
+ copied += copy_len;
+ offset = 0;
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ tx_ring->producer = producer;
+ smp_mb();
+ adapter->stats.lso_frames++;
+
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (protocol == ETH_P_IP) {
+ l4proto = ip_hdr(skb)->protocol;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCP_PKT;
+ else if (l4proto == IPPROTO_UDP)
+ opcode = TX_UDP_PKT;
+ } else if (protocol == ETH_P_IPV6) {
+ l4proto = ipv6_hdr(skb)->nexthdr;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCPV6_PKT;
+ else if (l4proto == IPPROTO_UDP)
+ opcode = TX_UDPV6_PKT;
+ }
+ }
+ first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+ first_desc->ip_hdr_offset += skb_network_offset(skb);
+ qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ return 0;
+}
+
+static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+ struct qlcnic_cmd_buffer *pbuf)
+{
+ struct qlcnic_skb_frag *nf;
+ struct skb_frag_struct *frag;
+ int i, nr_frags;
+ dma_addr_t map;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ nf = &pbuf->frag_array[0];
+
+ map = pci_map_single(pdev, skb->data, skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, map))
+ goto out_err;
+
+ nf->dma = map;
+ nf->length = skb_headlen(skb);
+
+ for (i = 0; i < nr_frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ nf = &pbuf->frag_array[i+1];
+ map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&pdev->dev, map))
+ goto unwind;
+
+ nf->dma = map;
+ nf->length = skb_frag_size(frag);
+ }
+
+ return 0;
+
+unwind:
+ while (--i >= 0) {
+ nf = &pbuf->frag_array[i+1];
+ pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+ }
+
+ nf = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+
+out_err:
+ return -ENOMEM;
+}
+
+static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
+ struct qlcnic_cmd_buffer *pbuf)
+{
+ struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
+ int i, nr_frags = skb_shinfo(skb)->nr_frags;
+
+ for (i = 0; i < nr_frags; i++) {
+ nf = &pbuf->frag_array[i+1];
+ pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+ }
+
+ nf = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+ pbuf->skb = NULL;
+}
+
+static inline void qlcnic_clear_cmddesc(u64 *desc)
+{
+ desc[0] = 0ULL;
+ desc[2] = 0ULL;
+ desc[7] = 0ULL;
+}
+
+netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+ struct qlcnic_cmd_buffer *pbuf;
+ struct qlcnic_skb_frag *buffrag;
+ struct cmd_desc_type0 *hwdesc, *first_desc;
+ struct pci_dev *pdev;
+ struct ethhdr *phdr;
+ int i, k, frag_count, delta = 0;
+ u32 producer, num_txd;
+
+ num_txd = tx_ring->num_desc;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ netif_stop_queue(netdev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (adapter->flags & QLCNIC_MACSPOOF) {
+ phdr = (struct ethhdr *)skb->data;
+ if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
+ goto drop_packet;
+ }
+
+ frag_count = skb_shinfo(skb)->nr_frags + 1;
+ /* 14 frags supported for normal packet and
+ * 32 frags supported for TSO packet
+ */
+ if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+ for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+ delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
+ if (!__pskb_pull_tail(skb, delta))
+ goto drop_packet;
+
+ frag_count = 1 + skb_shinfo(skb)->nr_frags;
+ }
+
+ if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
+ netif_stop_queue(netdev);
+ if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+ netif_start_queue(netdev);
+ } else {
+ adapter->stats.xmit_off++;
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ producer = tx_ring->producer;
+ pbuf = &tx_ring->cmd_buf_arr[producer];
+ pdev = adapter->pdev;
+ first_desc = &tx_ring->desc_head[producer];
+ hwdesc = &tx_ring->desc_head[producer];
+ qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+ if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
+ adapter->stats.tx_dma_map_error++;
+ goto drop_packet;
+ }
+
+ pbuf->skb = skb;
+ pbuf->frag_count = frag_count;
+
+ qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
+ qlcnic_set_tx_port(first_desc, adapter->portnum);
+
+ for (i = 0; i < frag_count; i++) {
+ k = i % 4;
+
+ if ((k == 0) && (i > 0)) {
+ /* move to next desc.*/
+ producer = get_next_index(producer, num_txd);
+ hwdesc = &tx_ring->desc_head[producer];
+ qlcnic_clear_cmddesc((u64 *)hwdesc);
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+ }
+
+ buffrag = &pbuf->frag_array[i];
+ hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
+ switch (k) {
+ case 0:
+ hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+ break;
+ case 1:
+ hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
+ break;
+ case 2:
+ hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
+ break;
+ case 3:
+ hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
+ break;
+ }
+ }
+
+ tx_ring->producer = get_next_index(producer, num_txd);
+ smp_mb();
+
+ if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
+ goto unwind_buff;
+
+ if (adapter->mac_learn)
+ qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
+ adapter->stats.txbytes += skb->len;
+ adapter->stats.xmitcalled++;
+
+ qlcnic_update_cmd_producer(tx_ring);
+
+ return NETDEV_TX_OK;
+
+unwind_buff:
+ qlcnic_unmap_buffers(pdev, skb, pbuf);
+drop_packet:
+ adapter->stats.txdropped++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (adapter->ahw->linkup && !linkup) {
+ netdev_info(netdev, "NIC Link is down\n");
+ adapter->ahw->linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else if (!adapter->ahw->linkup && linkup) {
+ netdev_info(netdev, "NIC Link is up\n");
+ adapter->ahw->linkup = 1;
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
+static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring,
+ struct qlcnic_rx_buffer *buffer)
+{
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ struct pci_dev *pdev = adapter->pdev;
+
+ skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
+ if (!skb) {
+ adapter->stats.skb_alloc_failure++;
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+
+ if (pci_dma_mapping_error(pdev, dma)) {
+ adapter->stats.rx_dma_map_error++;
+ dev_kfree_skb_any(skb);
+ return -ENOMEM;
+ }
+
+ buffer->skb = skb;
+ buffer->dma = dma;
+
+ return 0;
+}
+
+static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring)
+{
+ struct rcv_desc *pdesc;
+ struct qlcnic_rx_buffer *buffer;
+ int count = 0;
+ uint32_t producer;
+ struct list_head *head;
+
+ if (!spin_trylock(&rds_ring->lock))
+ return;
+
+ producer = rds_ring->producer;
+ head = &rds_ring->free_list;
+
+ while (!list_empty(head)) {
+ buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+ if (!buffer->skb) {
+ if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+ break;
+ }
+
+ count++;
+ list_del(&buffer->list);
+
+ /* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+ pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+ producer = get_next_index(producer, rds_ring->num_desc);
+ }
+
+ if (count) {
+ rds_ring->producer = producer;
+ writel((producer - 1) & (rds_ring->num_desc - 1),
+ rds_ring->crb_rcv_producer);
+ }
+
+ spin_unlock(&rds_ring->lock);
+}
+
+static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+{
+ u32 sw_consumer, hw_consumer;
+ int i, done, count = 0;
+ struct qlcnic_cmd_buffer *buffer;
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_skb_frag *frag;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+ if (!spin_trylock(&adapter->tx_clean_lock))
+ return 1;
+
+ sw_consumer = tx_ring->sw_consumer;
+ hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+ while (sw_consumer != hw_consumer) {
+ buffer = &tx_ring->cmd_buf_arr[sw_consumer];
+ if (buffer->skb) {
+ frag = &buffer->frag_array[0];
+ pci_unmap_single(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
+ for (i = 1; i < buffer->frag_count; i++) {
+ frag++;
+ pci_unmap_page(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
+ }
+
+ adapter->stats.xmitfinished++;
+ dev_kfree_skb_any(buffer->skb);
+ buffer->skb = NULL;
+ }
+
+ sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
+ if (++count >= MAX_STATUS_HANDLE)
+ break;
+ }
+
+ if (count && netif_running(netdev)) {
+ tx_ring->sw_consumer = sw_consumer;
+
+ smp_mb();
+
+ if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+ if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+ netif_wake_queue(netdev);
+ adapter->stats.xmit_on++;
+ }
+ }
+ adapter->tx_timeo_cnt = 0;
+ }
+ /*
+ * If everything is freed up to consumer then check if the ring is full
+ * If the ring is full then check if more needs to be freed and
+ * schedule the call back again.
+ *
+ * This happens when there are 2 CPUs. One could be freeing and the
+ * other filling it. If the ring is full when we get out of here and
+ * the card has already interrupted the host then the host can miss the
+ * interrupt.
+ *
+ * There is still a possible race condition and the host could miss an
+ * interrupt. The card has to take care of this.
+ */
+ hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+ done = (sw_consumer == hw_consumer);
+
+ spin_unlock(&adapter->tx_clean_lock);
+
+ return done;
+}
+
+static int qlcnic_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_adapter *adapter;
+ int tx_complete, work_done;
+
+ sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+ adapter = sds_ring->adapter;
+
+ tx_complete = qlcnic_process_cmd_ring(adapter);
+ work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+ if ((work_done < budget) && tx_complete) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_enable_int(sds_ring);
+ }
+
+ return work_done;
+}
+
+static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_adapter *adapter;
+ int work_done;
+
+ sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+ adapter = sds_ring->adapter;
+
+ work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+ if (work_done < budget) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_enable_int(sds_ring);
+ }
+
+ return work_done;
+}
+
+static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
+ struct qlcnic_fw_msg *msg)
+{
+ u32 cable_OUI;
+ u16 cable_len, link_speed;
+ u8 link_status, module, duplex, autoneg, lb_status = 0;
+ struct net_device *netdev = adapter->netdev;
+
+ adapter->ahw->has_link_events = 1;
+
+ cable_OUI = msg->body[1] & 0xffffffff;
+ cable_len = (msg->body[1] >> 32) & 0xffff;
+ link_speed = (msg->body[1] >> 48) & 0xffff;
+
+ link_status = msg->body[2] & 0xff;
+ duplex = (msg->body[2] >> 16) & 0xff;
+ autoneg = (msg->body[2] >> 24) & 0xff;
+ lb_status = (msg->body[2] >> 32) & 0x3;
+
+ module = (msg->body[2] >> 8) & 0xff;
+ if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
+ dev_info(&netdev->dev,
+ "unsupported cable: OUI 0x%x, length %d\n",
+ cable_OUI, cable_len);
+ else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
+ dev_info(&netdev->dev, "unsupported cable length %d\n",
+ cable_len);
+
+ if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+ lb_status == QLCNIC_ELB_MODE))
+ adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
+ qlcnic_advert_link_change(adapter, link_status);
+
+ if (duplex == LINKEVENT_FULL_DUPLEX)
+ adapter->ahw->link_duplex = DUPLEX_FULL;
+ else
+ adapter->ahw->link_duplex = DUPLEX_HALF;
+
+ adapter->ahw->module_type = module;
+ adapter->ahw->link_autoneg = autoneg;
+
+ if (link_status) {
+ adapter->ahw->link_speed = link_speed;
+ } else {
+ adapter->ahw->link_speed = SPEED_UNKNOWN;
+ adapter->ahw->link_duplex = DUPLEX_UNKNOWN;
+ }
+}
+
+static void qlcnic_handle_fw_message(int desc_cnt, int index,
+ struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_fw_msg msg;
+ struct status_desc *desc;
+ struct qlcnic_adapter *adapter;
+ struct device *dev;
+ int i = 0, opcode, ret;
+
+ while (desc_cnt > 0 && i < 8) {
+ desc = &sds_ring->desc_head[index];
+ msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+ msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+ index = get_next_index(index, sds_ring->num_desc);
+ desc_cnt--;
+ }
+
+ adapter = sds_ring->adapter;
+ dev = &adapter->pdev->dev;
+ opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
+ switch (opcode) {
+ case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+ qlcnic_handle_linkevent(adapter, &msg);
+ break;
+ case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+ ret = (u32)(msg.body[1]);
+ switch (ret) {
+ case 0:
+ adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+ break;
+ case 1:
+ dev_info(dev, "loopback already in progress\n");
+ adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+ break;
+ case 2:
+ dev_info(dev, "loopback cable is not connected\n");
+ adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+ break;
+ default:
+ dev_info(dev,
+ "loopback configure request failed, err %x\n",
+ ret);
+ adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static struct sk_buff *
+qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring, u16 index,
+ u16 cksum)
+{
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ if (unlikely(buffer->skb == NULL)) {
+ WARN_ON(1);
+ return NULL;
+ }
+
+ pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+
+ skb = buffer->skb;
+
+ if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
+ (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
+ adapter->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else {
+ skb_checksum_none_assert(skb);
+ }
+
+ buffer->skb = NULL;
+
+ return skb;
+}
+
+static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
+ struct sk_buff *skb, u16 *vlan_tag)
+{
+ struct ethhdr *eth_hdr;
+
+ if (!__vlan_get_tag(skb, vlan_tag)) {
+ eth_hdr = (struct ethhdr *)skb->data;
+ memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+ skb_pull(skb, VLAN_HLEN);
+ }
+ if (!adapter->pvid)
+ return 0;
+
+ if (*vlan_tag == adapter->pvid) {
+ /* Outer vlan tag. Packet should follow non-vlan path */
+ *vlan_tag = 0xffff;
+ return 0;
+ }
+ if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+ return 0;
+
+ return -EINVAL;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_rcv(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring, int ring,
+ u64 sts_data0)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+ length = qlcnic_get_sts_totallength(sts_data0);
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return buffer;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+
+ napi_gro_receive(&sds_ring->napi, skb);
+
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return buffer;
+}
+
+#define QLC_TCP_HDR_SIZE 20
+#define QLC_TCP_TS_OPTION_SIZE 12
+#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_lro(struct qlcnic_adapter *adapter,
+ int ring, u64 sts_data0, u64 sts_data1)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ bool push, timestamp;
+ int index, l2_hdr_offset, l4_hdr_offset;
+ u16 lro_length, length, data_offset, vid = 0xffff;
+ u32 seq_number;
+
+ if (unlikely(ring > adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_lro_sts_refhandle(sts_data0);
+ if (unlikely(index > rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
+ lro_length = qlcnic_get_lro_sts_length(sts_data0);
+ l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
+ l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
+ push = qlcnic_get_lro_sts_push_flag(sts_data0);
+ seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return buffer;
+
+ if (timestamp)
+ data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+ else
+ data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+ skb_put(skb, lro_length + data_offset);
+ skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+ iph = (struct iphdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+ length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+ iph->tot_len = htons(length);
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ th->psh = push;
+ th->seq = htonl(seq_number);
+ length = skb->len;
+
+ if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+ skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+ netif_receive_skb(skb);
+
+ adapter->stats.lro_pkts++;
+ adapter->stats.lrobytes += length;
+
+ return buffer;
+}
+
+int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct list_head *cur;
+ struct status_desc *desc;
+ struct qlcnic_rx_buffer *rxbuf;
+ u64 sts_data0, sts_data1;
+ __le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ int opcode, ring, desc_cnt, count = 0;
+ u32 consumer = sds_ring->consumer;
+
+ while (count < max) {
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ break;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+
+ switch (opcode) {
+ case QLCNIC_RXPKT_DESC:
+ case QLCNIC_OLD_RXPKT_DESC:
+ case QLCNIC_SYN_OFFLOAD:
+ ring = qlcnic_get_sts_type(sts_data0);
+ rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring,
+ sts_data0);
+ break;
+ case QLCNIC_LRO_DESC:
+ ring = qlcnic_get_lro_sts_type(sts_data0);
+ sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+ rxbuf = qlcnic_process_lro(adapter, ring, sts_data0,
+ sts_data1);
+ break;
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ default:
+ goto skip;
+ }
+
+ WARN_ON(desc_cnt > 1);
+
+ if (likely(rxbuf))
+ list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+ else
+ adapter->stats.null_rxbuf++;
+
+skip:
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = owner_phantom;
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+ count++;
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &adapter->recv_ctx->rds_rings[ring];
+
+ if (!list_empty(&sds_ring->free_list[ring])) {
+ list_for_each(cur, &sds_ring->free_list[ring]) {
+ rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
+ list);
+ qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+ }
+ spin_lock(&rds_ring->lock);
+ list_splice_tail_init(&sds_ring->free_list[ring],
+ &rds_ring->free_list);
+ spin_unlock(&rds_ring->lock);
+ }
+
+ qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
+ }
+
+ if (count) {
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+ }
+
+ return count;
+}
+
+void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring)
+{
+ struct rcv_desc *pdesc;
+ struct qlcnic_rx_buffer *buffer;
+ int count = 0;
+ u32 producer;
+ struct list_head *head;
+
+ producer = rds_ring->producer;
+ head = &rds_ring->free_list;
+
+ while (!list_empty(head)) {
+
+ buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+ if (!buffer->skb) {
+ if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+ break;
+ }
+
+ count++;
+ list_del(&buffer->list);
+
+ /* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+ producer = get_next_index(producer, rds_ring->num_desc);
+ }
+
+ if (count) {
+ rds_ring->producer = producer;
+ writel((producer-1) & (rds_ring->num_desc-1),
+ rds_ring->crb_rcv_producer);
+ }
+}
+
+static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ pr_info(KERN_INFO "\n");
+ for (i = 0; i < skb->len; i++) {
+ QLCDB(adapter, DRV, "%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ pr_info(KERN_INFO "\n");
+ }
+}
+
+static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
+ u64 sts_data0)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ length = qlcnic_get_sts_totallength(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->ahw->diag_cnt++;
+ else
+ dump_skb(skb, adapter);
+
+ dev_kfree_skb_any(skb);
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return;
+}
+
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data0;
+ int ring, opcode, desc_cnt;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ return;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+ switch (opcode) {
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ break;
+ default:
+ ring = qlcnic_get_sts_type(sts_data0);
+ qlcnic_process_rcv_diag(adapter, ring, sts_data0);
+ break;
+ }
+
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
+
+void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac)
+{
+ u32 mac_low, mac_high;
+ int i;
+
+ mac_low = off1;
+ mac_high = off2;
+
+ if (alt_mac) {
+ mac_low |= (mac_low >> 16) | (mac_high << 16);
+ mac_high >>= 16;
+ }
+
+ for (i = 0; i < 2; i++)
+ mac[i] = (u8)(mac_high >> ((1 - i) * 8));
+ for (i = 2; i < 6; i++)
+ mac[i] = (u8)(mac_low >> ((5 - i) * 8));
+}
+
+int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+ int ring, max_sds_rings;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+ return -ENOMEM;
+
+ max_sds_rings = adapter->max_sds_rings;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+
+ if (ring == max_sds_rings - 1)
+ netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
+ QLCNIC_NETDEV_WEIGHT / max_sds_rings);
+ else
+ netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
+ QLCNIC_NETDEV_WEIGHT*2);
+ }
+
+ return 0;
+}
+
+void qlcnic_napi_del(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ netif_napi_del(&sds_ring->napi);
+ }
+
+ qlcnic_free_sds_rings(adapter->recv_ctx);
+}
+
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ napi_enable(&sds_ring->napi);
+ qlcnic_enable_int(sds_ring);
+ }
+}
+
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ qlcnic_disable_int(sds_ring);
+ napi_synchronize(&sds_ring->napi);
+ napi_disable(&sds_ring->napi);
+ }
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 24ad17ec7fcd..a7554d9aab0c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -34,29 +34,28 @@ static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0444);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
-static int use_msi = 1;
-module_param(use_msi, int, 0444);
+static int qlcnic_use_msi = 1;
MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
+module_param_named(use_msi, qlcnic_use_msi, int, 0444);
-static int use_msi_x = 1;
-module_param(use_msi_x, int, 0444);
+static int qlcnic_use_msi_x = 1;
MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
+module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
-static int auto_fw_reset = 1;
-module_param(auto_fw_reset, int, 0644);
+static int qlcnic_auto_fw_reset = 1;
MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
+module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
-static int load_fw_file;
-module_param(load_fw_file, int, 0444);
+static int qlcnic_load_fw_file;
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
+module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
static int qlcnic_config_npars;
module_param(qlcnic_config_npars, int, 0444);
MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
-static int __devinit qlcnic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
-static void __devexit qlcnic_remove(struct pci_dev *pdev);
+static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void qlcnic_remove(struct pci_dev *pdev);
static int qlcnic_open(struct net_device *netdev);
static int qlcnic_close(struct net_device *netdev);
static void qlcnic_tx_timeout(struct net_device *netdev);
@@ -66,17 +65,10 @@ static void qlcnic_fw_poll_work(struct work_struct *work);
static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay);
static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
-static int qlcnic_poll(struct napi_struct *napi, int budget);
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev);
#endif
-static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
-
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
@@ -92,14 +84,15 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
-static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
-static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
static int qlcnic_vlan_rx_add(struct net_device *, u16);
static int qlcnic_vlan_rx_del(struct net_device *, u16);
+#define QLCNIC_IS_TSO_CAPABLE(adapter) \
+ ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+
/* PCI Device ID Table */
#define ENTRY(device) \
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -115,9 +108,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);
-inline void
-qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
+inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
{
writel(tx_ring->producer, tx_ring->crb_cmd_producer);
}
@@ -129,26 +120,34 @@ static const u32 msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};
-static const
-struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
-
-static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
- writel(0, sds_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
+static const struct qlcnic_board_info qlcnic_boards[] = {
+ {0x1077, 0x8020, 0x1077, 0x203,
+ "8200 Series Single Port 10GbE Converged Network Adapter"
+ "(TCP/IP Networking)"},
+ {0x1077, 0x8020, 0x1077, 0x207,
+ "8200 Series Dual Port 10GbE Converged Network Adapter"
+ "(TCP/IP Networking)"},
+ {0x1077, 0x8020, 0x1077, 0x20b,
+ "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x20c,
+ "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x20f,
+ "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x103c, 0x3733,
+ "NC523SFP 10Gb 2-port Server Adapter"},
+ {0x1077, 0x8020, 0x103c, 0x3346,
+ "CN1000Q Dual Port Converged Network Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x210,
+ "QME8242-k 10GbE Dual Port Mezzanine Card"},
+ {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
+};
- writel(0x1, sds_ring->crb_intr_mask);
+#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
- if (!QLCNIC_IS_MSI_FAMILY(adapter))
- writel(0xfbff, adapter->tgt_mask_reg);
-}
+static const
+struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
-static int
-qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
{
int size = sizeof(struct qlcnic_host_sds_ring) * count;
@@ -157,8 +156,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
return recv_ctx->sds_rings == NULL;
}
-static void
-qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
{
if (recv_ctx->sds_rings != NULL)
kfree(recv_ctx->sds_rings);
@@ -166,80 +164,6 @@ qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
recv_ctx->sds_rings = NULL;
}
-static int
-qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
- return -ENOMEM;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
-
- if (ring == adapter->max_sds_rings - 1)
- netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
- QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
- else
- netif_napi_add(netdev, &sds_ring->napi,
- qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2);
- }
-
- return 0;
-}
-
-static void
-qlcnic_napi_del(struct qlcnic_adapter *adapter)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- netif_napi_del(&sds_ring->napi);
- }
-
- qlcnic_free_sds_rings(adapter->recv_ctx);
-}
-
-static void
-qlcnic_napi_enable(struct qlcnic_adapter *adapter)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
- return;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- napi_enable(&sds_ring->napi);
- qlcnic_enable_int(sds_ring);
- }
-}
-
-static void
-qlcnic_napi_disable(struct qlcnic_adapter *adapter)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
- return;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- qlcnic_disable_int(sds_ring);
- napi_synchronize(&sds_ring->napi);
- napi_disable(&sds_ring->napi);
- }
-}
-
static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
{
memset(&adapter->stats, 0, sizeof(adapter->stats));
@@ -363,7 +287,7 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
qlcnic_set_msix_bit(pdev, 0);
- if (adapter->msix_supported) {
+ if (adapter->ahw->msix_supported) {
enable_msix:
qlcnic_init_msix_entries(adapter, num_msix);
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
@@ -385,32 +309,31 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
return err;
}
-
static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
{
+ u32 offset, mask_reg;
const struct qlcnic_legacy_intr_set *legacy_intrp;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
struct pci_dev *pdev = adapter->pdev;
- if (use_msi && !pci_enable_msi(pdev)) {
+ if (qlcnic_use_msi && !pci_enable_msi(pdev)) {
adapter->flags |= QLCNIC_MSI_ENABLED;
- adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
- msi_tgt_status[adapter->ahw->pci_func]);
+ offset = msi_tgt_status[adapter->ahw->pci_func];
+ adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
+ offset);
dev_info(&pdev->dev, "using msi interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
return;
}
legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
-
- adapter->int_vec_bit = legacy_intrp->int_vec_bit;
- adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
- legacy_intrp->tgt_status_reg);
- adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
- legacy_intrp->tgt_mask_reg);
- adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
-
- adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
- ISR_INT_STATE_REG);
+ adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
+ offset = legacy_intrp->tgt_status_reg;
+ adapter->tgt_status_reg = qlcnic_get_ioaddr(ahw, offset);
+ mask_reg = legacy_intrp->tgt_mask_reg;
+ adapter->tgt_mask_reg = qlcnic_get_ioaddr(ahw, mask_reg);
+ adapter->isr_int_vec = qlcnic_get_ioaddr(ahw, ISR_INT_VECTOR);
+ adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG);
dev_info(&pdev->dev, "using legacy interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
}
@@ -420,7 +343,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
{
int num_msix;
- if (adapter->msix_supported) {
+ if (adapter->ahw->msix_supported) {
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
QLCNIC_DEF_NUM_STS_DESC_RINGS));
} else
@@ -448,19 +371,25 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
iounmap(adapter->ahw->pci_base0);
}
-static int
-qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
+static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{
struct qlcnic_pci_info *pci_info;
- int i, ret = 0;
+ int i, ret = 0, j = 0;
+ u16 act_pci_func;
u8 pfn;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info)
return -ENOMEM;
+ ret = qlcnic_get_pci_info(adapter, pci_info);
+ if (ret)
+ goto err_pci_info;
+
+ act_pci_func = adapter->ahw->act_pci_func;
+
adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
- QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
+ act_pci_func, GFP_KERNEL);
if (!adapter->npars) {
ret = -ENOMEM;
goto err_pci_info;
@@ -473,21 +402,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
goto err_npars;
}
- ret = qlcnic_get_pci_info(adapter, pci_info);
- if (ret)
- goto err_eswitch;
-
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
pfn = pci_info[i].id;
+
if (pfn >= QLCNIC_MAX_PCI_FUNC) {
ret = QL_STATUS_INVALID_PARAM;
goto err_eswitch;
}
- adapter->npars[pfn].active = (u8)pci_info[i].active;
- adapter->npars[pfn].type = (u8)pci_info[i].type;
- adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
- adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
- adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
+
+ if (!pci_info[i].active ||
+ (pci_info[i].type != QLCNIC_TYPE_NIC))
+ continue;
+
+ adapter->npars[j].pci_func = pfn;
+ adapter->npars[j].active = (u8)pci_info[i].active;
+ adapter->npars[j].type = (u8)pci_info[i].type;
+ adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
+ adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
+ adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
+ j++;
}
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -515,7 +448,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
u32 ref_count;
int i, ret = 1;
u32 data = QLCNIC_MGMT_FUNC;
- void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
/* If other drivers are not in use set their privilege level */
ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
@@ -524,21 +457,20 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
goto err_lock;
if (qlcnic_config_npars) {
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- id = i;
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
- id == adapter->ahw->pci_func)
+ for (i = 0; i < ahw->act_pci_func; i++) {
+ id = adapter->npars[i].pci_func;
+ if (id == ahw->pci_func)
continue;
data |= (qlcnic_config_npars &
QLC_DEV_SET_DRV(0xf, id));
}
} else {
- data = readl(priv_op);
- data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) |
+ data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE);
+ data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
(QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
- adapter->ahw->pci_func));
+ ahw->pci_func));
}
- writel(data, priv_op);
+ QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data);
qlcnic_api_unlock(adapter);
err_lock:
return ret;
@@ -554,8 +486,8 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
u32 op_mode, priv_level;
/* Determine FW API version */
- adapter->fw_hal_version = readl(adapter->ahw->pci_base0 +
- QLCNIC_FW_API);
+ adapter->ahw->fw_hal_version = readl(adapter->ahw->pci_base0 +
+ QLCNIC_FW_API);
/* Find PCI function number */
pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
@@ -573,29 +505,41 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
if (priv_level == QLCNIC_NON_PRIV_FUNC) {
- adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
+ adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d Non Privileged function\n",
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
adapter->nic_ops = &qlcnic_vf_ops;
} else
adapter->nic_ops = &qlcnic_ops;
}
-static int
-qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
+#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
+static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
{
+ switch (dev_id) {
+ case PCI_DEVICE_ID_QLOGIC_QLE824X:
+ *bar = QLCNIC_82XX_BAR0_LENGTH;
+ break;
+ default:
+ *bar = 0;
+ }
+}
+
+static int qlcnic_setup_pci_map(struct pci_dev *pdev,
+ struct qlcnic_hardware_context *ahw)
+{
+ u32 offset;
void __iomem *mem_ptr0 = NULL;
resource_size_t mem_base;
- unsigned long mem_len, pci_len0 = 0;
-
- struct pci_dev *pdev = adapter->pdev;
+ unsigned long mem_len, pci_len0 = 0, bar0_len;
/* remap phys address */
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
mem_len = pci_resource_len(pdev, 0);
- if (mem_len == QLCNIC_PCI_2MB_SIZE) {
+ qlcnic_get_bar_length(pdev->device, &bar0_len);
+ if (mem_len >= bar0_len) {
mem_ptr0 = pci_ioremap_bar(pdev, 0);
if (mem_ptr0 == NULL) {
@@ -608,20 +552,15 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
}
dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
-
- adapter->ahw->pci_base0 = mem_ptr0;
- adapter->ahw->pci_len0 = pci_len0;
-
- qlcnic_check_vf(adapter);
-
- adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(
- adapter->ahw->pci_func)));
+ ahw->pci_base0 = mem_ptr0;
+ ahw->pci_len0 = pci_len0;
+ offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func));
+ qlcnic_get_ioaddr(ahw, offset);
return 0;
}
-static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
+static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
{
struct pci_dev *pdev = adapter->pdev;
int i, found = 0;
@@ -659,7 +598,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
if (fw_dump->tmpl_hdr == NULL ||
adapter->fw_version > prev_fw_version) {
if (fw_dump->tmpl_hdr)
@@ -691,7 +630,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
}
- adapter->msix_supported = !!use_msi_x;
+ adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
adapter->num_txd = MAX_CMD_DESCRIPTORS;
@@ -704,19 +643,20 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
int err;
struct qlcnic_info nic_info;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
if (err)
return err;
- adapter->physical_port = (u8)nic_info.phys_port;
- adapter->switch_mode = nic_info.switch_mode;
- adapter->max_tx_ques = nic_info.max_tx_ques;
- adapter->max_rx_ques = nic_info.max_rx_ques;
- adapter->capabilities = nic_info.capabilities;
- adapter->max_mac_filters = nic_info.max_mac_filters;
- adapter->max_mtu = nic_info.max_mtu;
+ adapter->ahw->physical_port = (u8)nic_info.phys_port;
+ adapter->ahw->switch_mode = nic_info.switch_mode;
+ adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
+ adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
+ adapter->ahw->capabilities = nic_info.capabilities;
+ adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
+ adapter->ahw->max_mtu = nic_info.max_mtu;
- if (adapter->capabilities & BIT_6)
+ if (adapter->ahw->capabilities & BIT_6)
adapter->flags |= QLCNIC_ESWITCH_ENABLED;
else
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
@@ -724,9 +664,8 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
return err;
}
-static void
-qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
{
if (esw_cfg->discard_tagged)
adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
@@ -757,9 +696,8 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
return 0;
}
-static void
-qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
{
adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
QLCNIC_PROMISC_DISABLED);
@@ -776,8 +714,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
qlcnic_set_netdev_features(adapter, esw_cfg);
}
-static int
-qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
{
struct qlcnic_esw_func_cfg esw_cfg;
@@ -805,7 +742,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
features |= (NETIF_F_TSO | NETIF_F_TSO6);
vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
}
@@ -851,7 +788,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
if (priv_level == QLCNIC_MGMT_FUNC) {
- adapter->op_mode = QLCNIC_MGMT_FUNC;
+ adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
err = qlcnic_init_pci_info(adapter);
if (err)
return err;
@@ -859,12 +796,12 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
qlcnic_set_function_modes(adapter);
dev_info(&adapter->pdev->dev,
"HAL Version: %d, Management function\n",
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
} else if (priv_level == QLCNIC_PRIV_FUNC) {
- adapter->op_mode = QLCNIC_PRIV_FUNC;
+ adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d, Privileged function\n",
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
}
}
@@ -873,8 +810,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
return err;
}
-static int
-qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
+static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
{
struct qlcnic_esw_func_cfg esw_cfg;
struct qlcnic_npar_info *npar;
@@ -883,16 +819,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
return 0;
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
- esw_cfg.pci_func = i;
- esw_cfg.offload_flags = BIT_0;
+ esw_cfg.pci_func = adapter->npars[i].pci_func;
esw_cfg.mac_override = BIT_0;
esw_cfg.promisc_mode = BIT_0;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
- esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+ if (qlcnic_82xx_check(adapter)) {
+ esw_cfg.offload_flags = BIT_0;
+ if (QLCNIC_IS_TSO_CAPABLE(adapter))
+ esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+ }
if (qlcnic_config_switch_port(adapter, &esw_cfg))
return -EIO;
npar = &adapter->npars[i];
@@ -930,22 +866,24 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
return 0;
}
-static int
-qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
{
int i, err;
struct qlcnic_npar_info *npar;
struct qlcnic_info nic_info;
+ u8 pci_func;
- if (!adapter->need_fw_reset)
- return 0;
+ if (qlcnic_82xx_check(adapter))
+ if (!adapter->need_fw_reset)
+ return 0;
/* Set the NPAR config data after FW reset */
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
npar = &adapter->npars[i];
- if (npar->type != QLCNIC_TYPE_NIC)
- continue;
- err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ pci_func = npar->pci_func;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
+ err = qlcnic_get_nic_info(adapter,
+ &nic_info, pci_func);
if (err)
return err;
nic_info.min_tx_bw = npar->min_bw;
@@ -956,11 +894,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
if (npar->enable_pm) {
err = qlcnic_config_port_mirroring(adapter,
- npar->dest_npar, 1, i);
+ npar->dest_npar, 1,
+ pci_func);
if (err)
return err;
}
- err = qlcnic_reset_eswitch_config(adapter, npar, i);
+ err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
if (err)
return err;
}
@@ -972,7 +911,7 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
u32 npar_state;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
return 0;
npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
@@ -994,7 +933,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
int err;
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
+ adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return 0;
err = qlcnic_set_default_offload_settings(adapter);
@@ -1021,14 +960,14 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
else if (!err)
goto check_fw_status;
- if (load_fw_file)
+ if (qlcnic_load_fw_file)
qlcnic_request_firmware(adapter);
else {
err = qlcnic_check_flash_fw_ver(adapter);
if (err)
goto err_out;
- adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
+ adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
}
err = qlcnic_need_fw_reset(adapter);
@@ -1089,7 +1028,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
handler = qlcnic_tmp_intr;
if (!QLCNIC_IS_MSI_FAMILY(adapter))
flags |= IRQF_SHARED;
@@ -1148,7 +1087,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (qlcnic_set_eswitch_port_config(adapter))
return -EIO;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
@@ -1179,7 +1118,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_linkevent_request(adapter, 1);
- adapter->reset_context = 0;
+ adapter->ahw->reset_context = 0;
set_bit(__QLCNIC_DEV_UP, &adapter->state);
return 0;
}
@@ -1312,7 +1251,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
int ring;
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
qlcnic_disable_int(sds_ring);
@@ -1323,7 +1262,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
qlcnic_detach(adapter);
- adapter->diag_test = 0;
+ adapter->ahw->diag_test = 0;
adapter->max_sds_rings = max_sds_rings;
if (qlcnic_attach(adapter))
@@ -1393,7 +1332,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_detach(adapter);
adapter->max_sds_rings = 1;
- adapter->diag_test = test;
+ adapter->ahw->diag_test = test;
ret = qlcnic_attach(adapter);
if (ret) {
@@ -1413,14 +1352,14 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_post_rx_buffers(adapter, rds_ring);
}
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
qlcnic_enable_int(sds_ring);
}
}
- if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
adapter->ahw->loopback_state = 0;
qlcnic_linkevent_request(adapter, 1);
}
@@ -1485,14 +1424,14 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
}
static int
-qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
- struct net_device *netdev, u8 pci_using_dac)
+qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
+ int pci_using_dac)
{
int err;
struct pci_dev *pdev = adapter->pdev;
- adapter->mc_enabled = 0;
- adapter->max_mc_count = 38;
+ adapter->ahw->mc_enabled = 0;
+ adapter->ahw->max_mc_count = 38;
netdev->netdev_ops = &qlcnic_netdev_ops;
netdev->watchdog_timeo = 5*HZ;
@@ -1504,16 +1443,16 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
- if (pci_using_dac)
+ if (pci_using_dac == 1)
netdev->hw_features |= NETIF_F_HIGHDMA;
netdev->vlan_features = netdev->hw_features;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
netdev->hw_features |= NETIF_F_HW_VLAN_TX;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
netdev->hw_features |= NETIF_F_LRO;
netdev->features |= netdev->hw_features |
@@ -1530,7 +1469,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
return 0;
}
-static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
+static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
{
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
@@ -1559,15 +1498,14 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
return -ENOMEM;
}
-static int __devinit
+static int
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct qlcnic_adapter *adapter = NULL;
- int err;
+ int err, pci_using_dac = -1;
uint8_t revision_id;
- uint8_t pci_using_dac;
- char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
+ char board_name[QLCNIC_MAX_BOARD_NAME_LEN];
err = pci_enable_device(pdev);
if (err)
@@ -1616,9 +1554,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list);
- err = qlcnic_setup_pci_map(adapter);
+ err = qlcnic_setup_pci_map(pdev, adapter->ahw);
if (err)
goto err_out_free_hw;
+ qlcnic_check_vf(adapter);
/* This will be reset for mezz cards */
adapter->portnum = adapter->ahw->pci_func;
@@ -1646,16 +1585,15 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_warn(&pdev->dev, "failed to read mac addr\n");
if (adapter->portnum == 0) {
- get_brd_name(adapter, brd_name);
-
+ qlcnic_get_board_name(adapter, board_name);
pr_info("%s: %s Board Chip rev 0x%x\n",
- module_name(THIS_MODULE),
- brd_name, adapter->ahw->revision_id);
+ module_name(THIS_MODULE),
+ board_name, adapter->ahw->revision_id);
}
qlcnic_clear_stats(adapter);
- err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques);
+ err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques);
if (err)
goto err_out_decr_ref;
@@ -1667,7 +1605,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, adapter);
- qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+ if (qlcnic_82xx_check(adapter))
+ qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+ FW_POLL_DELAY);
switch (adapter->ahw->port_type) {
case QLCNIC_GBE:
@@ -1724,7 +1664,7 @@ err_out_maintenance_mode:
return 0;
}
-static void __devexit qlcnic_remove(struct pci_dev *pdev)
+static void qlcnic_remove(struct pci_dev *pdev)
{
struct qlcnic_adapter *adapter;
struct net_device *netdev;
@@ -1746,7 +1686,8 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
if (adapter->eswitch != NULL)
kfree(adapter->eswitch);
- qlcnic_clr_all_drv_state(adapter, 0);
+ if (qlcnic_82xx_check(adapter))
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1782,7 +1723,8 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
if (netif_running(netdev))
qlcnic_down(adapter, netdev);
- qlcnic_clr_all_drv_state(adapter, 0);
+ if (qlcnic_82xx_check(adapter))
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1790,9 +1732,11 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
if (retval)
return retval;
- if (qlcnic_wol_supported(adapter)) {
- pci_enable_wake(pdev, PCI_D3cold, 1);
- pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (qlcnic_82xx_check(adapter)) {
+ if (qlcnic_wol_supported(adapter)) {
+ pci_enable_wake(pdev, PCI_D3cold, 1);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ }
}
return 0;
@@ -1927,435 +1871,14 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
adapter->fhash.fmax = 0;
}
-static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
- u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
-{
- struct cmd_desc_type0 *hwdesc;
- struct qlcnic_nic_req *req;
- struct qlcnic_mac_req *mac_req;
- struct qlcnic_vlan_req *vlan_req;
- u32 producer;
- u64 word;
-
- producer = tx_ring->producer;
- hwdesc = &tx_ring->desc_head[tx_ring->producer];
-
- req = (struct qlcnic_nic_req *)hwdesc;
- memset(req, 0, sizeof(struct qlcnic_nic_req));
- req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
-
- word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
- req->req_hdr = cpu_to_le64(word);
-
- mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
- mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
- memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
-
- vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
- vlan_req->vlan_id = vlan_id;
-
- tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
- smp_mb();
-}
-
-#define QLCNIC_MAC_HASH(MAC)\
- ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
-
-static void
-qlcnic_send_filter(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring,
- struct cmd_desc_type0 *first_desc,
- struct sk_buff *skb)
-{
- struct ethhdr *phdr = (struct ethhdr *)(skb->data);
- struct qlcnic_filter *fil, *tmp_fil;
- struct hlist_node *tmp_hnode, *n;
- struct hlist_head *head;
- u64 src_addr = 0;
- __le16 vlan_id = 0;
- u8 hindex;
-
- if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
- return;
-
- if (adapter->fhash.fnum >= adapter->fhash.fmax)
- return;
-
- /* Only NPAR capable devices support vlan based learning*/
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
- vlan_id = first_desc->vlan_TCI;
- memcpy(&src_addr, phdr->h_source, ETH_ALEN);
- hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
- head = &(adapter->fhash.fhead[hindex]);
-
- hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
- if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
- tmp_fil->vlan_id == vlan_id) {
-
- if (jiffies >
- (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
- qlcnic_change_filter(adapter, src_addr, vlan_id,
- tx_ring);
- tmp_fil->ftime = jiffies;
- return;
- }
- }
-
- fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
- if (!fil)
- return;
-
- qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
-
- fil->ftime = jiffies;
- fil->vlan_id = vlan_id;
- memcpy(fil->faddr, &src_addr, ETH_ALEN);
- spin_lock(&adapter->mac_learn_lock);
- hlist_add_head(&(fil->fnode), head);
- adapter->fhash.fnum++;
- spin_unlock(&adapter->mac_learn_lock);
-}
-
-static int
-qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
- struct cmd_desc_type0 *first_desc,
- struct sk_buff *skb)
-{
- u8 opcode = 0, hdr_len = 0;
- u16 flags = 0, vlan_tci = 0;
- int copied, offset, copy_len;
- struct cmd_desc_type0 *hwdesc;
- struct vlan_ethhdr *vh;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
- u16 protocol = ntohs(skb->protocol);
- u32 producer = tx_ring->producer;
-
- if (protocol == ETH_P_8021Q) {
- vh = (struct vlan_ethhdr *)skb->data;
- flags = FLAGS_VLAN_TAGGED;
- vlan_tci = vh->h_vlan_TCI;
- protocol = ntohs(vh->h_vlan_encapsulated_proto);
- } else if (vlan_tx_tag_present(skb)) {
- flags = FLAGS_VLAN_OOB;
- vlan_tci = vlan_tx_tag_get(skb);
- }
- if (unlikely(adapter->pvid)) {
- if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
- return -EIO;
- if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
- goto set_flags;
-
- flags = FLAGS_VLAN_OOB;
- vlan_tci = adapter->pvid;
- }
-set_flags:
- qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
- qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
- if (*(skb->data) & BIT_0) {
- flags |= BIT_0;
- memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
- }
- opcode = TX_ETHER_PKT;
- if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
- skb_shinfo(skb)->gso_size > 0) {
-
- hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-
- first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- first_desc->total_hdr_length = hdr_len;
-
- opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
-
- /* For LSO, we need to copy the MAC/IP/TCP headers into
- * the descriptor ring */
- copied = 0;
- offset = 2;
-
- if (flags & FLAGS_VLAN_OOB) {
- first_desc->total_hdr_length += VLAN_HLEN;
- first_desc->tcp_hdr_offset = VLAN_HLEN;
- first_desc->ip_hdr_offset = VLAN_HLEN;
- /* Only in case of TSO on vlan device */
- flags |= FLAGS_VLAN_TAGGED;
-
- /* Create a TSO vlan header template for firmware */
-
- hwdesc = &tx_ring->desc_head[producer];
- tx_ring->cmd_buf_arr[producer].skb = NULL;
-
- copy_len = min((int)sizeof(struct cmd_desc_type0) -
- offset, hdr_len + VLAN_HLEN);
-
- vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
- skb_copy_from_linear_data(skb, vh, 12);
- vh->h_vlan_proto = htons(ETH_P_8021Q);
- vh->h_vlan_TCI = htons(vlan_tci);
-
- skb_copy_from_linear_data_offset(skb, 12,
- (char *)vh + 16, copy_len - 16);
-
- copied = copy_len - VLAN_HLEN;
- offset = 0;
-
- producer = get_next_index(producer, tx_ring->num_desc);
- }
-
- while (copied < hdr_len) {
-
- copy_len = min((int)sizeof(struct cmd_desc_type0) -
- offset, (hdr_len - copied));
-
- hwdesc = &tx_ring->desc_head[producer];
- tx_ring->cmd_buf_arr[producer].skb = NULL;
-
- skb_copy_from_linear_data_offset(skb, copied,
- (char *) hwdesc + offset, copy_len);
-
- copied += copy_len;
- offset = 0;
-
- producer = get_next_index(producer, tx_ring->num_desc);
- }
-
- tx_ring->producer = producer;
- smp_mb();
- adapter->stats.lso_frames++;
-
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- u8 l4proto;
-
- if (protocol == ETH_P_IP) {
- l4proto = ip_hdr(skb)->protocol;
-
- if (l4proto == IPPROTO_TCP)
- opcode = TX_TCP_PKT;
- else if (l4proto == IPPROTO_UDP)
- opcode = TX_UDP_PKT;
- } else if (protocol == ETH_P_IPV6) {
- l4proto = ipv6_hdr(skb)->nexthdr;
-
- if (l4proto == IPPROTO_TCP)
- opcode = TX_TCPV6_PKT;
- else if (l4proto == IPPROTO_UDP)
- opcode = TX_UDPV6_PKT;
- }
- }
- first_desc->tcp_hdr_offset += skb_transport_offset(skb);
- first_desc->ip_hdr_offset += skb_network_offset(skb);
- qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
- return 0;
-}
-
-static int
-qlcnic_map_tx_skb(struct pci_dev *pdev,
- struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
-{
- struct qlcnic_skb_frag *nf;
- struct skb_frag_struct *frag;
- int i, nr_frags;
- dma_addr_t map;
-
- nr_frags = skb_shinfo(skb)->nr_frags;
- nf = &pbuf->frag_array[0];
-
- map = pci_map_single(pdev, skb->data,
- skb_headlen(skb), PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, map))
- goto out_err;
-
- nf->dma = map;
- nf->length = skb_headlen(skb);
-
- for (i = 0; i < nr_frags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- nf = &pbuf->frag_array[i+1];
-
- map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
- DMA_TO_DEVICE);
- if (dma_mapping_error(&pdev->dev, map))
- goto unwind;
-
- nf->dma = map;
- nf->length = skb_frag_size(frag);
- }
-
- return 0;
-
-unwind:
- while (--i >= 0) {
- nf = &pbuf->frag_array[i+1];
- pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
- }
-
- nf = &pbuf->frag_array[0];
- pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-
-out_err:
- return -ENOMEM;
-}
-
-static void
-qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
- struct qlcnic_cmd_buffer *pbuf)
-{
- struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
- int nr_frags = skb_shinfo(skb)->nr_frags;
- int i;
-
- for (i = 0; i < nr_frags; i++) {
- nf = &pbuf->frag_array[i+1];
- pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
- }
-
- nf = &pbuf->frag_array[0];
- pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
- pbuf->skb = NULL;
-}
-
-static inline void
-qlcnic_clear_cmddesc(u64 *desc)
-{
- desc[0] = 0ULL;
- desc[2] = 0ULL;
- desc[7] = 0ULL;
-}
-
-netdev_tx_t
-qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
- struct qlcnic_cmd_buffer *pbuf;
- struct qlcnic_skb_frag *buffrag;
- struct cmd_desc_type0 *hwdesc, *first_desc;
- struct pci_dev *pdev;
- struct ethhdr *phdr;
- int delta = 0;
- int i, k;
-
- u32 producer;
- int frag_count;
- u32 num_txd = tx_ring->num_desc;
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- netif_stop_queue(netdev);
- return NETDEV_TX_BUSY;
- }
-
- if (adapter->flags & QLCNIC_MACSPOOF) {
- phdr = (struct ethhdr *)skb->data;
- if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
- goto drop_packet;
- }
-
- frag_count = skb_shinfo(skb)->nr_frags + 1;
- /* 14 frags supported for normal packet and
- * 32 frags supported for TSO packet
- */
- if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
-
- for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
- delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
-
- if (!__pskb_pull_tail(skb, delta))
- goto drop_packet;
-
- frag_count = 1 + skb_shinfo(skb)->nr_frags;
- }
-
- if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
- netif_stop_queue(netdev);
- if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
- netif_start_queue(netdev);
- else {
- adapter->stats.xmit_off++;
- return NETDEV_TX_BUSY;
- }
- }
-
- producer = tx_ring->producer;
- pbuf = &tx_ring->cmd_buf_arr[producer];
-
- pdev = adapter->pdev;
-
- first_desc = hwdesc = &tx_ring->desc_head[producer];
- qlcnic_clear_cmddesc((u64 *)hwdesc);
-
- if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
- adapter->stats.tx_dma_map_error++;
- goto drop_packet;
- }
-
- pbuf->skb = skb;
- pbuf->frag_count = frag_count;
-
- qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
- qlcnic_set_tx_port(first_desc, adapter->portnum);
-
- for (i = 0; i < frag_count; i++) {
-
- k = i % 4;
-
- if ((k == 0) && (i > 0)) {
- /* move to next desc.*/
- producer = get_next_index(producer, num_txd);
- hwdesc = &tx_ring->desc_head[producer];
- qlcnic_clear_cmddesc((u64 *)hwdesc);
- tx_ring->cmd_buf_arr[producer].skb = NULL;
- }
-
- buffrag = &pbuf->frag_array[i];
-
- hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
- switch (k) {
- case 0:
- hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
- break;
- case 1:
- hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
- break;
- case 2:
- hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
- break;
- case 3:
- hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
- break;
- }
- }
-
- tx_ring->producer = get_next_index(producer, num_txd);
- smp_mb();
-
- if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
- goto unwind_buff;
-
- if (adapter->mac_learn)
- qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
-
- adapter->stats.txbytes += skb->len;
- adapter->stats.xmitcalled++;
-
- qlcnic_update_cmd_producer(adapter, tx_ring);
-
- return NETDEV_TX_OK;
-
-unwind_buff:
- qlcnic_unmap_buffers(pdev, skb, pbuf);
-drop_packet:
- adapter->stats.txdropped++;
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
-}
-
static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- u32 temp, temp_state, temp_val;
+ u32 temp_state, temp_val, temp = 0;
int rv = 0;
- temp = QLCRD32(adapter, CRB_TEMP_STATE);
+ if (qlcnic_82xx_check(adapter))
+ temp = QLCRD32(adapter, CRB_TEMP_STATE);
temp_state = qlcnic_get_temp_state(temp);
temp_val = qlcnic_get_temp_val(temp);
@@ -2367,7 +1890,7 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
temp_val);
rv = 1;
} else if (temp_state == QLCNIC_TEMP_WARN) {
- if (adapter->temp == QLCNIC_TEMP_NORMAL) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
dev_err(&netdev->dev,
"Device temperature %d degrees C "
"exceeds operating range."
@@ -2375,37 +1898,16 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
temp_val);
}
} else {
- if (adapter->temp == QLCNIC_TEMP_WARN) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
dev_info(&netdev->dev,
"Device temperature is now %d degrees C"
" in normal range.\n", temp_val);
}
}
- adapter->temp = temp_state;
+ adapter->ahw->temp = temp_state;
return rv;
}
-void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (adapter->ahw->linkup && !linkup) {
- netdev_info(netdev, "NIC Link is down\n");
- adapter->ahw->linkup = 0;
- if (netif_running(netdev)) {
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- } else if (!adapter->ahw->linkup && linkup) {
- netdev_info(netdev, "NIC Link is up\n");
- adapter->ahw->linkup = 1;
- if (netif_running(netdev)) {
- netif_carrier_on(netdev);
- netif_wake_queue(netdev);
- }
- }
-}
-
static void qlcnic_tx_timeout(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -2418,7 +1920,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
adapter->need_fw_reset = 1;
else
- adapter->reset_context = 1;
+ adapter->ahw->reset_context = 1;
}
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
@@ -2442,7 +1944,7 @@ static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
status = readl(adapter->isr_int_vec);
- if (!(status & adapter->int_vec_bit))
+ if (!(status & adapter->ahw->int_vec_bit))
return IRQ_NONE;
/* check interrupt state machine, to be sure */
@@ -2474,7 +1976,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
return IRQ_NONE;
done:
- adapter->diag_cnt++;
+ adapter->ahw->diag_cnt++;
qlcnic_enable_int(sds_ring);
return IRQ_HANDLED;
}
@@ -2512,122 +2014,6 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data)
return IRQ_HANDLED;
}
-static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
-{
- u32 sw_consumer, hw_consumer;
- int count = 0, i;
- struct qlcnic_cmd_buffer *buffer;
- struct pci_dev *pdev = adapter->pdev;
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_skb_frag *frag;
- int done;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
- if (!spin_trylock(&adapter->tx_clean_lock))
- return 1;
-
- sw_consumer = tx_ring->sw_consumer;
- hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-
- while (sw_consumer != hw_consumer) {
- buffer = &tx_ring->cmd_buf_arr[sw_consumer];
- if (buffer->skb) {
- frag = &buffer->frag_array[0];
- pci_unmap_single(pdev, frag->dma, frag->length,
- PCI_DMA_TODEVICE);
- frag->dma = 0ULL;
- for (i = 1; i < buffer->frag_count; i++) {
- frag++;
- pci_unmap_page(pdev, frag->dma, frag->length,
- PCI_DMA_TODEVICE);
- frag->dma = 0ULL;
- }
-
- adapter->stats.xmitfinished++;
- dev_kfree_skb_any(buffer->skb);
- buffer->skb = NULL;
- }
-
- sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
- if (++count >= MAX_STATUS_HANDLE)
- break;
- }
-
- if (count && netif_running(netdev)) {
- tx_ring->sw_consumer = sw_consumer;
-
- smp_mb();
-
- if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
- if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
- netif_wake_queue(netdev);
- adapter->stats.xmit_on++;
- }
- }
- adapter->tx_timeo_cnt = 0;
- }
- /*
- * If everything is freed up to consumer then check if the ring is full
- * If the ring is full then check if more needs to be freed and
- * schedule the call back again.
- *
- * This happens when there are 2 CPUs. One could be freeing and the
- * other filling it. If the ring is full when we get out of here and
- * the card has already interrupted the host then the host can miss the
- * interrupt.
- *
- * There is still a possible race condition and the host could miss an
- * interrupt. The card has to take care of this.
- */
- hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
- done = (sw_consumer == hw_consumer);
- spin_unlock(&adapter->tx_clean_lock);
-
- return done;
-}
-
-static int qlcnic_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
-
- int tx_complete;
- int work_done;
-
- tx_complete = qlcnic_process_cmd_ring(adapter);
-
- work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
- if ((work_done < budget) && tx_complete) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_enable_int(sds_ring);
- }
-
- return work_done;
-}
-
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- int work_done;
-
- work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
- if (work_done < budget) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_enable_int(sds_ring);
- }
-
- return work_done;
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev)
{
@@ -2871,7 +2257,7 @@ qlcnic_fwinit_work(struct work_struct *work)
return;
}
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
qlcnic_api_unlock(adapter);
goto wait_npar;
}
@@ -2987,9 +2373,9 @@ qlcnic_detach_work(struct work_struct *work)
goto err_ret;
}
- if (adapter->temp == QLCNIC_TEMP_PANIC) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
- adapter->temp);
+ adapter->ahw->temp);
goto err_ret;
}
@@ -3114,7 +2500,7 @@ qlcnic_attach_work(struct work_struct *work)
struct net_device *netdev = adapter->netdev;
u32 npar_state;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC) {
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
qlcnic_clr_all_drv_state(adapter, 0);
@@ -3171,7 +2557,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->reset_context && auto_fw_reset) {
+ if (adapter->ahw->reset_context && qlcnic_auto_fw_reset) {
qlcnic_reset_hw_context(adapter);
adapter->netdev->trans_start = jiffies;
}
@@ -3186,7 +2572,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
- if (auto_fw_reset)
+ if (qlcnic_auto_fw_reset)
clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
dev_err(&adapter->pdev->dev, "firmware hang detected\n");
@@ -3211,8 +2597,8 @@ detach:
adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
QLCNIC_DEV_NEED_RESET;
- if (auto_fw_reset &&
- !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
+ if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING,
+ &adapter->state)) {
qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
QLCDB(adapter, DRV, "fw recovery scheduled.\n");
@@ -3283,7 +2669,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (qlcnic_api_lock(adapter))
return -EINVAL;
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
+ if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
@@ -3395,96 +2781,9 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
return err;
}
-static int
-qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
-{
- return -EOPNOTSUPP;
-}
-
-static int
-qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
-{
- return -EOPNOTSUPP;
-}
-
-static ssize_t
-qlcnic_store_bridged_mode(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- unsigned long new;
- int ret = -EINVAL;
-
- if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
- goto err_out;
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
- goto err_out;
-
- if (strict_strtoul(buf, 2, &new))
- goto err_out;
-
- if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
- ret = len;
-
-err_out:
- return ret;
-}
-
-static ssize_t
-qlcnic_show_bridged_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int bridged_mode = 0;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
-
- return sprintf(buf, "%d\n", bridged_mode);
-}
-
-static struct device_attribute dev_attr_bridged_mode = {
- .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_bridged_mode,
- .store = qlcnic_store_bridged_mode,
-};
-
-static ssize_t
-qlcnic_store_diag_mode(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- unsigned long new;
-
- if (strict_strtoul(buf, 2, &new))
- return -EINVAL;
-
- if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
- adapter->flags ^= QLCNIC_DIAG_ENABLED;
-
- return len;
-}
-
-static ssize_t
-qlcnic_show_diag_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n",
- !!(adapter->flags & QLCNIC_DIAG_ENABLED));
-}
-
-static struct device_attribute dev_attr_diag_mode = {
- .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_diag_mode,
- .store = qlcnic_store_diag_mode,
-};
-
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
{
- if (!use_msi_x && !use_msi) {
+ if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
netdev_info(netdev, "no msix or msi support, hence no rss\n");
return -EINVAL;
}
@@ -3532,859 +2831,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
return err;
}
-static int
-qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
- u8 *rate)
-{
- *rate = LSB(beacon);
- *state = MSB(beacon);
-
- QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
-
- if (!*state) {
- *rate = __QLCNIC_MAX_LED_RATE;
- return 0;
- } else if (*state > __QLCNIC_MAX_LED_STATE)
- return -EINVAL;
-
- if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
- return -EINVAL;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_store_beacon(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int max_sds_rings = adapter->max_sds_rings;
- u16 beacon;
- u8 b_state, b_rate;
- int err;
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
- dev_warn(dev, "LED test not supported for non "
- "privilege function\n");
- return -EOPNOTSUPP;
- }
-
- if (len != sizeof(u16))
- return QL_STATUS_INVALID_PARAM;
-
- memcpy(&beacon, buf, sizeof(u16));
- err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
- if (err)
- return err;
-
- if (adapter->ahw->beacon_state == b_state)
- return len;
-
- rtnl_lock();
-
- if (!adapter->ahw->beacon_state)
- if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
- rtnl_unlock();
- return -EBUSY;
- }
-
- if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
- err = -EIO;
- goto out;
- }
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
- if (err)
- goto out;
- set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
- }
-
- err = qlcnic_config_led(adapter, b_state, b_rate);
-
- if (!err) {
- err = len;
- adapter->ahw->beacon_state = b_state;
- }
-
- if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
- qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
-
- out:
- if (!adapter->ahw->beacon_state)
- clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
- rtnl_unlock();
-
- return err;
-}
-
-static ssize_t
-qlcnic_show_beacon(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
-}
-
-static struct device_attribute dev_attr_beacon = {
- .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_beacon,
- .store = qlcnic_store_beacon,
-};
-
-static int
-qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
- loff_t offset, size_t size)
-{
- size_t crb_size = 4;
-
- if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
- return -EIO;
-
- if (offset < QLCNIC_PCI_CRBSPACE) {
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
- QLCNIC_PCI_CAMQM_END))
- crb_size = 8;
- else
- return -EINVAL;
- }
-
- if ((size != crb_size) || (offset & (crb_size-1)))
- return -EINVAL;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u32 data;
- u64 qmdata;
- int ret;
-
- ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
- memcpy(buf, &qmdata, size);
- } else {
- data = QLCRD32(adapter, offset);
- memcpy(buf, &data, size);
- }
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u32 data;
- u64 qmdata;
- int ret;
-
- ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- memcpy(&qmdata, buf, size);
- qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
- } else {
- memcpy(&data, buf, size);
- QLCWR32(adapter, offset, data);
- }
- return size;
-}
-
-static int
-qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
- loff_t offset, size_t size)
-{
- if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
- return -EIO;
-
- if ((size != 8) || (offset & 0x7))
- return -EIO;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u64 data;
- int ret;
-
- ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
- return -EIO;
-
- memcpy(buf, &data, size);
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u64 data;
- int ret;
-
- ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- memcpy(&data, buf, size);
-
- if (qlcnic_pci_mem_write_2M(adapter, offset, data))
- return -EIO;
-
- return size;
-}
-
-static struct bin_attribute bin_attr_crb = {
- .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_crb,
- .write = qlcnic_sysfs_write_crb,
-};
-
-static struct bin_attribute bin_attr_mem = {
- .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_mem,
- .write = qlcnic_sysfs_write_mem,
-};
-
-static int
-validate_pm_config(struct qlcnic_adapter *adapter,
- struct qlcnic_pm_func_cfg *pm_cfg, int count)
-{
-
- u8 src_pci_func, s_esw_id, d_esw_id;
- u8 dest_pci_func;
- int i;
-
- for (i = 0; i < count; i++) {
- src_pci_func = pm_cfg[i].pci_func;
- dest_pci_func = pm_cfg[i].dest_npar;
- if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
- || dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- s_esw_id = adapter->npars[src_pci_func].phy_port;
- d_esw_id = adapter->npars[dest_pci_func].phy_port;
-
- if (s_esw_id != d_esw_id)
- return QL_STATUS_INVALID_PARAM;
-
- }
- return 0;
-
-}
-
-static ssize_t
-qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pm_func_cfg *pm_cfg;
- u32 id, action, pci_func;
- int count, rem, i, ret;
-
- count = size / sizeof(struct qlcnic_pm_func_cfg);
- rem = size % sizeof(struct qlcnic_pm_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- pm_cfg = (struct qlcnic_pm_func_cfg *) buf;
-
- ret = validate_pm_config(adapter, pm_cfg, count);
- if (ret)
- return ret;
- for (i = 0; i < count; i++) {
- pci_func = pm_cfg[i].pci_func;
- action = !!pm_cfg[i].action;
- id = adapter->npars[pci_func].phy_port;
- ret = qlcnic_config_port_mirroring(adapter, id,
- action, pci_func);
- if (ret)
- return ret;
- }
-
- for (i = 0; i < count; i++) {
- pci_func = pm_cfg[i].pci_func;
- id = adapter->npars[pci_func].phy_port;
- adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
- adapter->npars[pci_func].dest_npar = id;
- }
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
- int i;
-
- if (size != sizeof(pm_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- pm_cfg[i].action = adapter->npars[i].enable_pm;
- pm_cfg[i].dest_npar = 0;
- pm_cfg[i].pci_func = i;
- }
- memcpy(buf, &pm_cfg, size);
-
- return size;
-}
-
-static int
-validate_esw_config(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg, int count)
-{
- u32 op_mode;
- u8 pci_func;
- int i;
-
- op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
-
- for (i = 0; i < count; i++) {
- pci_func = esw_cfg[i].pci_func;
- if (pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
- QLCNIC_NON_PRIV_FUNC) {
- if (esw_cfg[i].mac_anti_spoof != 0)
- return QL_STATUS_INVALID_PARAM;
- if (esw_cfg[i].mac_override != 1)
- return QL_STATUS_INVALID_PARAM;
- if (esw_cfg[i].promisc_mode != 1)
- return QL_STATUS_INVALID_PARAM;
- }
- break;
- case QLCNIC_ADD_VLAN:
- if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
- return QL_STATUS_INVALID_PARAM;
- if (!esw_cfg[i].op_type)
- return QL_STATUS_INVALID_PARAM;
- break;
- case QLCNIC_DEL_VLAN:
- if (!esw_cfg[i].op_type)
- return QL_STATUS_INVALID_PARAM;
- break;
- default:
- return QL_STATUS_INVALID_PARAM;
- }
- }
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_func_cfg *esw_cfg;
- struct qlcnic_npar_info *npar;
- int count, rem, i, ret;
- u8 pci_func, op_mode = 0;
-
- count = size / sizeof(struct qlcnic_esw_func_cfg);
- rem = size % sizeof(struct qlcnic_esw_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- esw_cfg = (struct qlcnic_esw_func_cfg *) buf;
- ret = validate_esw_config(adapter, esw_cfg, count);
- if (ret)
- return ret;
-
- for (i = 0; i < count; i++) {
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
- if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
- continue;
-
- op_mode = esw_cfg[i].op_mode;
- qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
- esw_cfg[i].op_mode = op_mode;
- esw_cfg[i].pci_func = adapter->ahw->pci_func;
-
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
- break;
- case QLCNIC_ADD_VLAN:
- qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
- break;
- case QLCNIC_DEL_VLAN:
- esw_cfg[i].vlan_id = 0;
- qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
- break;
- }
- }
-
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- goto out;
-
- for (i = 0; i < count; i++) {
- pci_func = esw_cfg[i].pci_func;
- npar = &adapter->npars[pci_func];
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- npar->promisc_mode = esw_cfg[i].promisc_mode;
- npar->mac_override = esw_cfg[i].mac_override;
- npar->offload_flags = esw_cfg[i].offload_flags;
- npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
- npar->discard_tagged = esw_cfg[i].discard_tagged;
- break;
- case QLCNIC_ADD_VLAN:
- npar->pvid = esw_cfg[i].vlan_id;
- break;
- case QLCNIC_DEL_VLAN:
- npar->pvid = 0;
- break;
- }
- }
-out:
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
- u8 i;
-
- if (size != sizeof(esw_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- esw_cfg[i].pci_func = i;
- if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
- return QL_STATUS_INVALID_PARAM;
- }
- memcpy(buf, &esw_cfg, size);
-
- return size;
-}
-
-static int
-validate_npar_config(struct qlcnic_adapter *adapter,
- struct qlcnic_npar_func_cfg *np_cfg, int count)
-{
- u8 pci_func, i;
-
- for (i = 0; i < count; i++) {
- pci_func = np_cfg[i].pci_func;
- if (pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- if (!IS_VALID_BW(np_cfg[i].min_bw) ||
- !IS_VALID_BW(np_cfg[i].max_bw))
- return QL_STATUS_INVALID_PARAM;
- }
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_info nic_info;
- struct qlcnic_npar_func_cfg *np_cfg;
- int i, count, rem, ret;
- u8 pci_func;
-
- count = size / sizeof(struct qlcnic_npar_func_cfg);
- rem = size % sizeof(struct qlcnic_npar_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- np_cfg = (struct qlcnic_npar_func_cfg *) buf;
- ret = validate_npar_config(adapter, np_cfg, count);
- if (ret)
- return ret;
-
- for (i = 0; i < count ; i++) {
- pci_func = np_cfg[i].pci_func;
- ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
- if (ret)
- return ret;
- nic_info.pci_func = pci_func;
- nic_info.min_tx_bw = np_cfg[i].min_bw;
- nic_info.max_tx_bw = np_cfg[i].max_bw;
- ret = qlcnic_set_nic_info(adapter, &nic_info);
- if (ret)
- return ret;
- adapter->npars[i].min_bw = nic_info.min_tx_bw;
- adapter->npars[i].max_bw = nic_info.max_tx_bw;
- }
-
- return size;
-
-}
-static ssize_t
-qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_info nic_info;
- struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
- int i, ret;
-
- if (size != sizeof(np_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- ret = qlcnic_get_nic_info(adapter, &nic_info, i);
- if (ret)
- return ret;
-
- np_cfg[i].pci_func = i;
- np_cfg[i].op_mode = (u8)nic_info.op_mode;
- np_cfg[i].port_num = nic_info.phys_port;
- np_cfg[i].fw_capab = nic_info.capabilities;
- np_cfg[i].min_bw = nic_info.min_tx_bw ;
- np_cfg[i].max_bw = nic_info.max_tx_bw;
- np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
- np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
- }
- memcpy(buf, &np_cfg, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_statistics port_stats;
- int ret;
-
- if (size != sizeof(struct qlcnic_esw_statistics))
- return QL_STATUS_INVALID_PARAM;
-
- if (offset >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- memset(&port_stats, 0, size);
- ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
- &port_stats.rx);
- if (ret)
- return ret;
-
- ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
- &port_stats.tx);
- if (ret)
- return ret;
-
- memcpy(buf, &port_stats, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_statistics esw_stats;
- int ret;
-
- if (size != sizeof(struct qlcnic_esw_statistics))
- return QL_STATUS_INVALID_PARAM;
-
- if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
- return QL_STATUS_INVALID_PARAM;
-
- memset(&esw_stats, 0, size);
- ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
- &esw_stats.rx);
- if (ret)
- return ret;
-
- ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
- &esw_stats.tx);
- if (ret)
- return ret;
-
- memcpy(buf, &esw_stats, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
- return QL_STATUS_INVALID_PARAM;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
- QLCNIC_QUERY_RX_COUNTER);
- if (ret)
- return ret;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
- QLCNIC_QUERY_TX_COUNTER);
- if (ret)
- return ret;
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- if (offset >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
- QLCNIC_QUERY_RX_COUNTER);
- if (ret)
- return ret;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
- QLCNIC_QUERY_TX_COUNTER);
- if (ret)
- return ret;
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
- struct qlcnic_pci_info *pci_info;
- int i, ret;
-
- if (size != sizeof(pci_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
- if (!pci_info)
- return -ENOMEM;
-
- ret = qlcnic_get_pci_info(adapter, pci_info);
- if (ret) {
- kfree(pci_info);
- return ret;
- }
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
- pci_cfg[i].pci_func = pci_info[i].id;
- pci_cfg[i].func_type = pci_info[i].type;
- pci_cfg[i].port_num = pci_info[i].default_port;
- pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
- pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
- memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
- }
- memcpy(buf, &pci_cfg, size);
- kfree(pci_info);
- return size;
-}
-static struct bin_attribute bin_attr_npar_config = {
- .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_npar_config,
- .write = qlcnic_sysfs_write_npar_config,
-};
-
-static struct bin_attribute bin_attr_pci_config = {
- .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_pci_config,
- .write = NULL,
-};
-
-static struct bin_attribute bin_attr_port_stats = {
- .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_get_port_stats,
- .write = qlcnic_sysfs_clear_port_stats,
-};
-
-static struct bin_attribute bin_attr_esw_stats = {
- .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_get_esw_stats,
- .write = qlcnic_sysfs_clear_esw_stats,
-};
-
-static struct bin_attribute bin_attr_esw_config = {
- .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_esw_config,
- .write = qlcnic_sysfs_write_esw_config,
-};
-
-static struct bin_attribute bin_attr_pm_config = {
- .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_pm_config,
- .write = qlcnic_sysfs_write_pm_config,
-};
-
-static void
-qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- if (device_create_file(dev, &dev_attr_bridged_mode))
- dev_warn(dev,
- "failed to create bridged_mode sysfs entry\n");
-}
-
-static void
-qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- device_remove_file(dev, &dev_attr_bridged_mode);
-}
-
-static void
-qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
- u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
- if (device_create_bin_file(dev, &bin_attr_port_stats))
- dev_info(dev, "failed to create port stats sysfs entry");
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return;
- if (device_create_file(dev, &dev_attr_diag_mode))
- dev_info(dev, "failed to create diag_mode sysfs entry\n");
- if (device_create_bin_file(dev, &bin_attr_crb))
- dev_info(dev, "failed to create crb sysfs entry\n");
- if (device_create_bin_file(dev, &bin_attr_mem))
- dev_info(dev, "failed to create mem sysfs entry\n");
-
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
- return;
-
- if (device_create_bin_file(dev, &bin_attr_pci_config))
- dev_info(dev, "failed to create pci config sysfs entry");
- if (device_create_file(dev, &dev_attr_beacon))
- dev_info(dev, "failed to create beacon sysfs entry");
-
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
- if (device_create_bin_file(dev, &bin_attr_esw_config))
- dev_info(dev, "failed to create esw config sysfs entry");
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return;
- if (device_create_bin_file(dev, &bin_attr_npar_config))
- dev_info(dev, "failed to create npar config sysfs entry");
- if (device_create_bin_file(dev, &bin_attr_pm_config))
- dev_info(dev, "failed to create pm config sysfs entry");
- if (device_create_bin_file(dev, &bin_attr_esw_stats))
- dev_info(dev, "failed to create eswitch stats sysfs entry");
-}
-
-static void
-qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
- u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
- device_remove_bin_file(dev, &bin_attr_port_stats);
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return;
- device_remove_file(dev, &dev_attr_diag_mode);
- device_remove_bin_file(dev, &bin_attr_crb);
- device_remove_bin_file(dev, &bin_attr_mem);
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
- return;
- device_remove_bin_file(dev, &bin_attr_pci_config);
- device_remove_file(dev, &dev_attr_beacon);
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
- device_remove_bin_file(dev, &bin_attr_esw_config);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return;
- device_remove_bin_file(dev, &bin_attr_npar_config);
- device_remove_bin_file(dev, &bin_attr_pm_config);
- device_remove_bin_file(dev, &bin_attr_esw_stats);
-}
-
#ifdef CONFIG_INET
#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
@@ -4523,7 +2969,7 @@ static void
qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
-static const struct pci_error_handlers qlcnic_err_handler = {
+static struct pci_error_handlers qlcnic_err_handler = {
.error_detected = qlcnic_io_error_detected,
.slot_reset = qlcnic_io_slot_reset,
.resume = qlcnic_io_resume,
@@ -4533,7 +2979,7 @@ static struct pci_driver qlcnic_driver = {
.name = qlcnic_driver_name,
.id_table = qlcnic_pci_tbl,
.probe = qlcnic_probe,
- .remove = __devexit_p(qlcnic_remove),
+ .remove = qlcnic_remove,
#ifdef CONFIG_PM
.suspend = qlcnic_suspend,
.resume = qlcnic_resume,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
new file mode 100644
index 000000000000..12ff29270745
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -0,0 +1,629 @@
+#include "qlcnic.h"
+#include "qlcnic_hdr.h"
+
+#include <net/ip.h>
+
+#define QLCNIC_DUMP_WCRB BIT_0
+#define QLCNIC_DUMP_RWCRB BIT_1
+#define QLCNIC_DUMP_ANDCRB BIT_2
+#define QLCNIC_DUMP_ORCRB BIT_3
+#define QLCNIC_DUMP_POLLCRB BIT_4
+#define QLCNIC_DUMP_RD_SAVE BIT_5
+#define QLCNIC_DUMP_WRT_SAVED BIT_6
+#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7
+#define QLCNIC_DUMP_SKIP BIT_7
+
+#define QLCNIC_DUMP_MASK_MAX 0xff
+
+struct qlcnic_common_entry_hdr {
+ u32 type;
+ u32 offset;
+ u32 cap_size;
+ u8 mask;
+ u8 rsvd[2];
+ u8 flags;
+} __packed;
+
+struct __crb {
+ u32 addr;
+ u8 stride;
+ u8 rsvd1[3];
+ u32 data_size;
+ u32 no_ops;
+ u32 rsvd2[4];
+} __packed;
+
+struct __ctrl {
+ u32 addr;
+ u8 stride;
+ u8 index_a;
+ u16 timeout;
+ u32 data_size;
+ u32 no_ops;
+ u8 opcode;
+ u8 index_v;
+ u8 shl_val;
+ u8 shr_val;
+ u32 val1;
+ u32 val2;
+ u32 val3;
+} __packed;
+
+struct __cache {
+ u32 addr;
+ u16 stride;
+ u16 init_tag_val;
+ u32 size;
+ u32 no_ops;
+ u32 ctrl_addr;
+ u32 ctrl_val;
+ u32 read_addr;
+ u8 read_addr_stride;
+ u8 read_addr_num;
+ u8 rsvd1[2];
+} __packed;
+
+struct __ocm {
+ u8 rsvd[8];
+ u32 size;
+ u32 no_ops;
+ u8 rsvd1[8];
+ u32 read_addr;
+ u32 read_addr_stride;
+} __packed;
+
+struct __mem {
+ u8 rsvd[24];
+ u32 addr;
+ u32 size;
+} __packed;
+
+struct __mux {
+ u32 addr;
+ u8 rsvd[4];
+ u32 size;
+ u32 no_ops;
+ u32 val;
+ u32 val_stride;
+ u32 read_addr;
+ u8 rsvd2[4];
+} __packed;
+
+struct __queue {
+ u32 sel_addr;
+ u16 stride;
+ u8 rsvd[2];
+ u32 size;
+ u32 no_ops;
+ u8 rsvd2[8];
+ u32 read_addr;
+ u8 read_addr_stride;
+ u8 read_addr_cnt;
+ u8 rsvd3[2];
+} __packed;
+
+struct qlcnic_dump_entry {
+ struct qlcnic_common_entry_hdr hdr;
+ union {
+ struct __crb crb;
+ struct __cache cache;
+ struct __ocm ocm;
+ struct __mem mem;
+ struct __mux mux;
+ struct __queue que;
+ struct __ctrl ctrl;
+ } region;
+} __packed;
+
+enum qlcnic_minidump_opcode {
+ QLCNIC_DUMP_NOP = 0,
+ QLCNIC_DUMP_READ_CRB = 1,
+ QLCNIC_DUMP_READ_MUX = 2,
+ QLCNIC_DUMP_QUEUE = 3,
+ QLCNIC_DUMP_BRD_CONFIG = 4,
+ QLCNIC_DUMP_READ_OCM = 6,
+ QLCNIC_DUMP_PEG_REG = 7,
+ QLCNIC_DUMP_L1_DTAG = 8,
+ QLCNIC_DUMP_L1_ITAG = 9,
+ QLCNIC_DUMP_L1_DATA = 11,
+ QLCNIC_DUMP_L1_INST = 12,
+ QLCNIC_DUMP_L2_DTAG = 21,
+ QLCNIC_DUMP_L2_ITAG = 22,
+ QLCNIC_DUMP_L2_DATA = 23,
+ QLCNIC_DUMP_L2_INST = 24,
+ QLCNIC_DUMP_READ_ROM = 71,
+ QLCNIC_DUMP_READ_MEM = 72,
+ QLCNIC_DUMP_READ_CTRL = 98,
+ QLCNIC_DUMP_TLHDR = 99,
+ QLCNIC_DUMP_RDEND = 255
+};
+
+struct qlcnic_dump_operations {
+ enum qlcnic_minidump_opcode opcode;
+ u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,
+ __le32 *);
+};
+
+static void qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+ u32 dest;
+ void __iomem *window_reg;
+
+ dest = addr & 0xFFFF0000;
+ window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, window_reg);
+ readl(window_reg);
+ window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ *data = readl(window_reg);
+}
+
+static void qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+ u32 dest;
+ void __iomem *window_reg;
+
+ dest = addr & 0xFFFF0000;
+ window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, window_reg);
+ readl(window_reg);
+ window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ writel(data, window_reg);
+ readl(window_reg);
+}
+
+/* FW dump related functions */
+static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i;
+ u32 addr, data;
+ struct __crb *crb = &entry->region.crb;
+ void __iomem *base = adapter->ahw->pci_base0;
+
+ addr = crb->addr;
+
+ for (i = 0; i < crb->no_ops; i++) {
+ qlcnic_read_dump_reg(addr, base, &data);
+ *buffer++ = cpu_to_le32(addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += crb->stride;
+ }
+ return crb->no_ops * 2 * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i, k, timeout = 0;
+ void __iomem *base = adapter->ahw->pci_base0;
+ u32 addr, data;
+ u8 opcode, no_ops;
+ struct __ctrl *ctr = &entry->region.ctrl;
+ struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
+
+ addr = ctr->addr;
+ no_ops = ctr->no_ops;
+
+ for (i = 0; i < no_ops; i++) {
+ k = 0;
+ opcode = 0;
+ for (k = 0; k < 8; k++) {
+ if (!(ctr->opcode & (1 << k)))
+ continue;
+ switch (1 << k) {
+ case QLCNIC_DUMP_WCRB:
+ qlcnic_write_dump_reg(addr, base, ctr->val1);
+ break;
+ case QLCNIC_DUMP_RWCRB:
+ qlcnic_read_dump_reg(addr, base, &data);
+ qlcnic_write_dump_reg(addr, base, data);
+ break;
+ case QLCNIC_DUMP_ANDCRB:
+ qlcnic_read_dump_reg(addr, base, &data);
+ qlcnic_write_dump_reg(addr, base,
+ data & ctr->val2);
+ break;
+ case QLCNIC_DUMP_ORCRB:
+ qlcnic_read_dump_reg(addr, base, &data);
+ qlcnic_write_dump_reg(addr, base,
+ data | ctr->val3);
+ break;
+ case QLCNIC_DUMP_POLLCRB:
+ while (timeout <= ctr->timeout) {
+ qlcnic_read_dump_reg(addr, base, &data);
+ if ((data & ctr->val2) == ctr->val1)
+ break;
+ msleep(1);
+ timeout++;
+ }
+ if (timeout > ctr->timeout) {
+ dev_info(&adapter->pdev->dev,
+ "Timed out, aborting poll CRB\n");
+ return -EINVAL;
+ }
+ break;
+ case QLCNIC_DUMP_RD_SAVE:
+ if (ctr->index_a)
+ addr = t_hdr->saved_state[ctr->index_a];
+ qlcnic_read_dump_reg(addr, base, &data);
+ t_hdr->saved_state[ctr->index_v] = data;
+ break;
+ case QLCNIC_DUMP_WRT_SAVED:
+ if (ctr->index_v)
+ data = t_hdr->saved_state[ctr->index_v];
+ else
+ data = ctr->val1;
+ if (ctr->index_a)
+ addr = t_hdr->saved_state[ctr->index_a];
+ qlcnic_write_dump_reg(addr, base, data);
+ break;
+ case QLCNIC_DUMP_MOD_SAVE_ST:
+ data = t_hdr->saved_state[ctr->index_v];
+ data <<= ctr->shl_val;
+ data >>= ctr->shr_val;
+ if (ctr->val2)
+ data &= ctr->val2;
+ data |= ctr->val3;
+ data += ctr->val1;
+ t_hdr->saved_state[ctr->index_v] = data;
+ break;
+ default:
+ dev_info(&adapter->pdev->dev,
+ "Unknown opcode\n");
+ break;
+ }
+ }
+ addr += ctr->stride;
+ }
+ return 0;
+}
+
+static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int loop;
+ u32 val, data = 0;
+ struct __mux *mux = &entry->region.mux;
+ void __iomem *base = adapter->ahw->pci_base0;
+
+ val = mux->val;
+ for (loop = 0; loop < mux->no_ops; loop++) {
+ qlcnic_write_dump_reg(mux->addr, base, val);
+ qlcnic_read_dump_reg(mux->read_addr, base, &data);
+ *buffer++ = cpu_to_le32(val);
+ *buffer++ = cpu_to_le32(data);
+ val += mux->val_stride;
+ }
+ return 2 * mux->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i, loop;
+ u32 cnt, addr, data, que_id = 0;
+ void __iomem *base = adapter->ahw->pci_base0;
+ struct __queue *que = &entry->region.que;
+
+ addr = que->read_addr;
+ cnt = que->read_addr_cnt;
+
+ for (loop = 0; loop < que->no_ops; loop++) {
+ qlcnic_write_dump_reg(que->sel_addr, base, que_id);
+ addr = que->read_addr;
+ for (i = 0; i < cnt; i++) {
+ qlcnic_read_dump_reg(addr, base, &data);
+ *buffer++ = cpu_to_le32(data);
+ addr += que->read_addr_stride;
+ }
+ que_id += que->stride;
+ }
+ return que->no_ops * cnt * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ocm(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i;
+ u32 data;
+ void __iomem *addr;
+ struct __ocm *ocm = &entry->region.ocm;
+
+ addr = adapter->ahw->pci_base0 + ocm->read_addr;
+ for (i = 0; i < ocm->no_ops; i++) {
+ data = readl(addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += ocm->read_addr_stride;
+ }
+ return ocm->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i, count = 0;
+ u32 fl_addr, size, val, lck_val, addr;
+ struct __mem *rom = &entry->region.mem;
+ void __iomem *base = adapter->ahw->pci_base0;
+
+ fl_addr = rom->addr;
+ size = rom->size/4;
+lock_try:
+ lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
+ if (!lck_val && count < MAX_CTL_CHECK) {
+ msleep(10);
+ count++;
+ goto lock_try;
+ }
+ writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
+ for (i = 0; i < size; i++) {
+ addr = fl_addr & 0xFFFF0000;
+ qlcnic_write_dump_reg(FLASH_ROM_WINDOW, base, addr);
+ addr = LSW(fl_addr) + FLASH_ROM_DATA;
+ qlcnic_read_dump_reg(addr, base, &val);
+ fl_addr += 4;
+ *buffer++ = cpu_to_le32(val);
+ }
+ readl(base + QLCNIC_FLASH_SEM2_ULK);
+ return rom->size;
+}
+
+static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i;
+ u32 cnt, val, data, addr;
+ void __iomem *base = adapter->ahw->pci_base0;
+ struct __cache *l1 = &entry->region.cache;
+
+ val = l1->init_tag_val;
+
+ for (i = 0; i < l1->no_ops; i++) {
+ qlcnic_write_dump_reg(l1->addr, base, val);
+ qlcnic_write_dump_reg(l1->ctrl_addr, base, LSW(l1->ctrl_val));
+ addr = l1->read_addr;
+ cnt = l1->read_addr_num;
+ while (cnt) {
+ qlcnic_read_dump_reg(addr, base, &data);
+ *buffer++ = cpu_to_le32(data);
+ addr += l1->read_addr_stride;
+ cnt--;
+ }
+ val += l1->stride;
+ }
+ return l1->no_ops * l1->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ int i;
+ u32 cnt, val, data, addr;
+ u8 poll_mask, poll_to, time_out = 0;
+ void __iomem *base = adapter->ahw->pci_base0;
+ struct __cache *l2 = &entry->region.cache;
+
+ val = l2->init_tag_val;
+ poll_mask = LSB(MSW(l2->ctrl_val));
+ poll_to = MSB(MSW(l2->ctrl_val));
+
+ for (i = 0; i < l2->no_ops; i++) {
+ qlcnic_write_dump_reg(l2->addr, base, val);
+ if (LSW(l2->ctrl_val))
+ qlcnic_write_dump_reg(l2->ctrl_addr, base,
+ LSW(l2->ctrl_val));
+ if (!poll_mask)
+ goto skip_poll;
+ do {
+ qlcnic_read_dump_reg(l2->ctrl_addr, base, &data);
+ if (!(data & poll_mask))
+ break;
+ msleep(1);
+ time_out++;
+ } while (time_out <= poll_to);
+
+ if (time_out > poll_to) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return -EINVAL;
+ }
+skip_poll:
+ addr = l2->read_addr;
+ cnt = l2->read_addr_num;
+ while (cnt) {
+ qlcnic_read_dump_reg(addr, base, &data);
+ *buffer++ = cpu_to_le32(data);
+ addr += l2->read_addr_stride;
+ cnt--;
+ }
+ val += l2->stride;
+ }
+ return l2->no_ops * l2->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ u32 addr, data, test, ret = 0;
+ int i, reg_read;
+ struct __mem *mem = &entry->region.mem;
+ void __iomem *base = adapter->ahw->pci_base0;
+
+ reg_read = mem->size;
+ addr = mem->addr;
+ /* check for data size of multiple of 16 and 16 byte alignment */
+ if ((addr & 0xf) || (reg_read%16)) {
+ dev_info(&adapter->pdev->dev,
+ "Unaligned memory addr:0x%x size:0x%x\n",
+ addr, reg_read);
+ return -EINVAL;
+ }
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ while (reg_read != 0) {
+ qlcnic_write_dump_reg(MIU_TEST_ADDR_LO, base, addr);
+ qlcnic_write_dump_reg(MIU_TEST_ADDR_HI, base, 0);
+ qlcnic_write_dump_reg(MIU_TEST_CTR, base,
+ TA_CTL_ENABLE | TA_CTL_START);
+
+ for (i = 0; i < MAX_CTL_CHECK; i++) {
+ qlcnic_read_dump_reg(MIU_TEST_CTR, base, &test);
+ if (!(test & TA_CTL_BUSY))
+ break;
+ }
+ if (i == MAX_CTL_CHECK) {
+ if (printk_ratelimit()) {
+ dev_err(&adapter->pdev->dev,
+ "failed to read through agent\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ for (i = 0; i < 4; i++) {
+ qlcnic_read_dump_reg(MIU_TEST_READ_DATA[i], base,
+ &data);
+ *buffer++ = cpu_to_le32(data);
+ }
+ addr += 16;
+ reg_read -= 16;
+ ret += 16;
+ }
+out:
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return mem->size;
+}
+
+static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ return 0;
+}
+
+static const struct qlcnic_dump_operations fw_dump_ops[] = {
+ { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
+ { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
+ { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
+ { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
+ { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
+ { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
+ { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
+ { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
+ { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
+ { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
+};
+
+/* Walk the template and collect dump for each entry in the dump template */
+static int
+qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
+ u32 size)
+{
+ int ret = 1;
+ if (size != entry->hdr.cap_size) {
+ dev_info(dev,
+ "Invalid dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
+ entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
+ dev_info(dev, "Aborting further dump capture\n");
+ ret = 0;
+ }
+ return ret;
+}
+
+int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
+{
+ __le32 *buffer;
+ char mesg[64];
+ char *msg[] = {mesg, NULL};
+ int i, k, ops_cnt, ops_index, dump_size = 0;
+ u32 entry_offset, dump, no_entries, buf_offset = 0;
+ struct qlcnic_dump_entry *entry;
+ struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
+
+ if (fw_dump->clr) {
+ dev_info(&adapter->pdev->dev,
+ "Previous dump not cleared, not capturing dump\n");
+ return -EIO;
+ }
+ /* Calculate the size for dump data area only */
+ for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
+ if (i & tmpl_hdr->drv_cap_mask)
+ dump_size += tmpl_hdr->cap_sizes[k];
+ if (!dump_size)
+ return -EIO;
+
+ fw_dump->data = vzalloc(dump_size);
+ if (!fw_dump->data) {
+ dev_info(&adapter->pdev->dev,
+ "Unable to allocate (%d KB) for fw dump\n",
+ dump_size / 1024);
+ return -ENOMEM;
+ }
+ buffer = fw_dump->data;
+ fw_dump->size = dump_size;
+ no_entries = tmpl_hdr->num_entries;
+ ops_cnt = ARRAY_SIZE(fw_dump_ops);
+ entry_offset = tmpl_hdr->offset;
+ tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
+ tmpl_hdr->sys_info[1] = adapter->fw_version;
+
+ for (i = 0; i < no_entries; i++) {
+ entry = (void *)tmpl_hdr + entry_offset;
+ if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ entry_offset += entry->hdr.offset;
+ continue;
+ }
+ /* Find the handler for this entry */
+ ops_index = 0;
+ while (ops_index < ops_cnt) {
+ if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
+ break;
+ ops_index++;
+ }
+ if (ops_index == ops_cnt) {
+ dev_info(&adapter->pdev->dev,
+ "Invalid entry type %d, exiting dump\n",
+ entry->hdr.type);
+ goto error;
+ }
+ /* Collect dump for this entry */
+ dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
+ if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
+ dump))
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ buf_offset += entry->hdr.cap_size;
+ entry_offset += entry->hdr.offset;
+ buffer = fw_dump->data + buf_offset;
+ }
+ if (dump_size != buf_offset) {
+ dev_info(&adapter->pdev->dev,
+ "Captured(%d) and expected size(%d) do not match\n",
+ buf_offset, dump_size);
+ goto error;
+ } else {
+ fw_dump->clr = 1;
+ snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
+ adapter->netdev->name);
+ dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
+ fw_dump->size);
+ /* Send a udev event to notify availability of FW dump */
+ kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
+ return 0;
+ }
+error:
+ vfree(fw_dump->data);
+ return -EINVAL;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
new file mode 100644
index 000000000000..341d37c867ff
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -0,0 +1,960 @@
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+
+#include "qlcnic.h"
+
+#include <linux/swab.h>
+#include <linux/dma-mapping.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <linux/inetdevice.h>
+#include <linux/sysfs.h>
+#include <linux/aer.h>
+#include <linux/log2.h>
+
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
+{
+ return -EOPNOTSUPP;
+}
+
+int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
+{
+ return -EOPNOTSUPP;
+}
+
+static ssize_t qlcnic_store_bridged_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ unsigned long new;
+ int ret = -EINVAL;
+
+ if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
+ goto err_out;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ goto err_out;
+
+ if (strict_strtoul(buf, 2, &new))
+ goto err_out;
+
+ if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
+ ret = len;
+
+err_out:
+ return ret;
+}
+
+static ssize_t qlcnic_show_bridged_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int bridged_mode = 0;
+
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
+
+ return sprintf(buf, "%d\n", bridged_mode);
+}
+
+static ssize_t qlcnic_store_diag_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ unsigned long new;
+
+ if (strict_strtoul(buf, 2, &new))
+ return -EINVAL;
+
+ if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ adapter->flags ^= QLCNIC_DIAG_ENABLED;
+
+ return len;
+}
+
+static ssize_t qlcnic_show_diag_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n",
+ !!(adapter->flags & QLCNIC_DIAG_ENABLED));
+}
+
+static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
+ u8 *state, u8 *rate)
+{
+ *rate = LSB(beacon);
+ *state = MSB(beacon);
+
+ QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
+
+ if (!*state) {
+ *rate = __QLCNIC_MAX_LED_RATE;
+ return 0;
+ } else if (*state > __QLCNIC_MAX_LED_STATE) {
+ return -EINVAL;
+ }
+
+ if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t qlcnic_store_beacon(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int max_sds_rings = adapter->max_sds_rings;
+ u16 beacon;
+ u8 b_state, b_rate;
+ int err;
+
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ dev_warn(dev,
+ "LED test not supported in non privileged mode\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (len != sizeof(u16))
+ return QL_STATUS_INVALID_PARAM;
+
+ memcpy(&beacon, buf, sizeof(u16));
+ err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
+ if (err)
+ return err;
+
+ if (adapter->ahw->beacon_state == b_state)
+ return len;
+
+ rtnl_lock();
+
+ if (!adapter->ahw->beacon_state)
+ if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
+ rtnl_unlock();
+ return -EBUSY;
+ }
+
+ if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+ err = -EIO;
+ goto out;
+ }
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
+ if (err)
+ goto out;
+ set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
+ }
+
+ err = qlcnic_config_led(adapter, b_state, b_rate);
+
+ if (!err) {
+ err = len;
+ adapter->ahw->beacon_state = b_state;
+ }
+
+ if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
+ qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
+
+ out:
+ if (!adapter->ahw->beacon_state)
+ clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+ rtnl_unlock();
+
+ return err;
+}
+
+static ssize_t qlcnic_show_beacon(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
+}
+
+static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
+ loff_t offset, size_t size)
+{
+ size_t crb_size = 4;
+
+ if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ return -EIO;
+
+ if (offset < QLCNIC_PCI_CRBSPACE) {
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
+ QLCNIC_PCI_CAMQM_END))
+ crb_size = 8;
+ else
+ return -EINVAL;
+ }
+
+ if ((size != crb_size) || (offset & (crb_size-1)))
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u32 data;
+ u64 qmdata;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+ memcpy(buf, &qmdata, size);
+ } else {
+ data = QLCRD32(adapter, offset);
+ memcpy(buf, &data, size);
+ }
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u32 data;
+ u64 qmdata;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ memcpy(&qmdata, buf, size);
+ qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+ } else {
+ memcpy(&data, buf, size);
+ QLCWR32(adapter, offset, data);
+ }
+ return size;
+}
+
+static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
+ loff_t offset, size_t size)
+{
+ if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ return -EIO;
+
+ if ((size != 8) || (offset & 0x7))
+ return -EIO;
+
+ return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u64 data;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
+ return -EIO;
+
+ memcpy(buf, &data, size);
+
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u64 data;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ memcpy(&data, buf, size);
+
+ if (qlcnic_pci_mem_write_2M(adapter, offset, data))
+ return -EIO;
+
+ return size;
+}
+
+static int validate_pm_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_pm_func_cfg *pm_cfg, int count)
+{
+ u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ src_pci_func = pm_cfg[i].pci_func;
+ dest_pci_func = pm_cfg[i].dest_npar;
+ if (src_pci_func >= QLCNIC_MAX_PCI_FUNC ||
+ dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ s_esw_id = adapter->npars[src_pci_func].phy_port;
+ d_esw_id = adapter->npars[dest_pci_func].phy_port;
+
+ if (s_esw_id != d_esw_id)
+ return QL_STATUS_INVALID_PARAM;
+ }
+ return 0;
+
+}
+
+static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pm_func_cfg *pm_cfg;
+ u32 id, action, pci_func;
+ int count, rem, i, ret;
+
+ count = size / sizeof(struct qlcnic_pm_func_cfg);
+ rem = size % sizeof(struct qlcnic_pm_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
+
+ ret = validate_pm_config(adapter, pm_cfg, count);
+ if (ret)
+ return ret;
+ for (i = 0; i < count; i++) {
+ pci_func = pm_cfg[i].pci_func;
+ action = !!pm_cfg[i].action;
+ id = adapter->npars[pci_func].phy_port;
+ ret = qlcnic_config_port_mirroring(adapter, id, action,
+ pci_func);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < count; i++) {
+ pci_func = pm_cfg[i].pci_func;
+ id = adapter->npars[pci_func].phy_port;
+ adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
+ adapter->npars[pci_func].dest_npar = id;
+ }
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
+ int i;
+
+ if (size != sizeof(pm_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ pm_cfg[i].action = adapter->npars[i].enable_pm;
+ pm_cfg[i].dest_npar = 0;
+ pm_cfg[i].pci_func = i;
+ }
+ memcpy(buf, &pm_cfg, size);
+
+ return size;
+}
+
+static int validate_esw_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg, int count)
+{
+ u32 op_mode;
+ u8 pci_func;
+ int i;
+
+ op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+
+ for (i = 0; i < count; i++) {
+ pci_func = esw_cfg[i].pci_func;
+ if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+ if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+ }
+
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+ QLCNIC_NON_PRIV_FUNC) {
+ if (esw_cfg[i].mac_anti_spoof != 0)
+ return QL_STATUS_INVALID_PARAM;
+ if (esw_cfg[i].mac_override != 1)
+ return QL_STATUS_INVALID_PARAM;
+ if (esw_cfg[i].promisc_mode != 1)
+ return QL_STATUS_INVALID_PARAM;
+ }
+ break;
+ case QLCNIC_ADD_VLAN:
+ if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+ return QL_STATUS_INVALID_PARAM;
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ case QLCNIC_DEL_VLAN:
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ default:
+ return QL_STATUS_INVALID_PARAM;
+ }
+ }
+ return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_func_cfg *esw_cfg;
+ struct qlcnic_npar_info *npar;
+ int count, rem, i, ret;
+ u8 pci_func, op_mode = 0;
+
+ count = size / sizeof(struct qlcnic_esw_func_cfg);
+ rem = size % sizeof(struct qlcnic_esw_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
+ ret = validate_esw_config(adapter, esw_cfg, count);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < count; i++) {
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+ if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
+ }
+
+ if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
+ continue;
+
+ op_mode = esw_cfg[i].op_mode;
+ qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+ esw_cfg[i].op_mode = op_mode;
+ esw_cfg[i].pci_func = adapter->ahw->pci_func;
+
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_ADD_VLAN:
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_DEL_VLAN:
+ esw_cfg[i].vlan_id = 0;
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ }
+ }
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ goto out;
+
+ for (i = 0; i < count; i++) {
+ pci_func = esw_cfg[i].pci_func;
+ npar = &adapter->npars[pci_func];
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ npar->promisc_mode = esw_cfg[i].promisc_mode;
+ npar->mac_override = esw_cfg[i].mac_override;
+ npar->offload_flags = esw_cfg[i].offload_flags;
+ npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+ npar->discard_tagged = esw_cfg[i].discard_tagged;
+ break;
+ case QLCNIC_ADD_VLAN:
+ npar->pvid = esw_cfg[i].vlan_id;
+ break;
+ case QLCNIC_DEL_VLAN:
+ npar->pvid = 0;
+ break;
+ }
+ }
+out:
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
+ u8 i;
+
+ if (size != sizeof(esw_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ esw_cfg[i].pci_func = i;
+ if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
+ }
+ memcpy(buf, &esw_cfg, size);
+
+ return size;
+}
+
+static int validate_npar_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_npar_func_cfg *np_cfg,
+ int count)
+{
+ u8 pci_func, i;
+
+ for (i = 0; i < count; i++) {
+ pci_func = np_cfg[i].pci_func;
+ if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+ !IS_VALID_BW(np_cfg[i].max_bw))
+ return QL_STATUS_INVALID_PARAM;
+ }
+ return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_info nic_info;
+ struct qlcnic_npar_func_cfg *np_cfg;
+ int i, count, rem, ret;
+ u8 pci_func;
+
+ count = size / sizeof(struct qlcnic_npar_func_cfg);
+ rem = size % sizeof(struct qlcnic_npar_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ np_cfg = (struct qlcnic_npar_func_cfg *)buf;
+ ret = validate_npar_config(adapter, np_cfg, count);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < count ; i++) {
+ pci_func = np_cfg[i].pci_func;
+ ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+ if (ret)
+ return ret;
+ nic_info.pci_func = pci_func;
+ nic_info.min_tx_bw = np_cfg[i].min_bw;
+ nic_info.max_tx_bw = np_cfg[i].max_bw;
+ ret = qlcnic_set_nic_info(adapter, &nic_info);
+ if (ret)
+ return ret;
+ adapter->npars[i].min_bw = nic_info.min_tx_bw;
+ adapter->npars[i].max_bw = nic_info.max_tx_bw;
+ }
+
+ return size;
+
+}
+
+static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_info nic_info;
+ struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
+ int i, ret;
+
+ if (size != sizeof(np_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ ret = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (ret)
+ return ret;
+
+ np_cfg[i].pci_func = i;
+ np_cfg[i].op_mode = (u8)nic_info.op_mode;
+ np_cfg[i].port_num = nic_info.phys_port;
+ np_cfg[i].fw_capab = nic_info.capabilities;
+ np_cfg[i].min_bw = nic_info.min_tx_bw;
+ np_cfg[i].max_bw = nic_info.max_tx_bw;
+ np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
+ np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+ }
+ memcpy(buf, &np_cfg, size);
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics port_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&port_stats, 0, size);
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &port_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &port_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &port_stats, size);
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics esw_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&esw_stats, 0, size);
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &esw_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &esw_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &esw_stats, size);
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
+ struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset,
+ size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
+ struct qlcnic_pci_info *pci_info;
+ int i, ret;
+
+ if (size != sizeof(pci_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+ if (!pci_info)
+ return -ENOMEM;
+
+ ret = qlcnic_get_pci_info(adapter, pci_info);
+ if (ret) {
+ kfree(pci_info);
+ return ret;
+ }
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
+ pci_cfg[i].pci_func = pci_info[i].id;
+ pci_cfg[i].func_type = pci_info[i].type;
+ pci_cfg[i].port_num = pci_info[i].default_port;
+ pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
+ pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
+ memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
+ }
+ memcpy(buf, &pci_cfg, size);
+ kfree(pci_info);
+ return size;
+}
+
+static struct device_attribute dev_attr_bridged_mode = {
+ .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_bridged_mode,
+ .store = qlcnic_store_bridged_mode,
+};
+
+static struct device_attribute dev_attr_diag_mode = {
+ .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_diag_mode,
+ .store = qlcnic_store_diag_mode,
+};
+
+static struct device_attribute dev_attr_beacon = {
+ .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_beacon,
+ .store = qlcnic_store_beacon,
+};
+
+static struct bin_attribute bin_attr_crb = {
+ .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_crb,
+ .write = qlcnic_sysfs_write_crb,
+};
+
+static struct bin_attribute bin_attr_mem = {
+ .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_mem,
+ .write = qlcnic_sysfs_write_mem,
+};
+
+static struct bin_attribute bin_attr_npar_config = {
+ .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_npar_config,
+ .write = qlcnic_sysfs_write_npar_config,
+};
+
+static struct bin_attribute bin_attr_pci_config = {
+ .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_pci_config,
+ .write = NULL,
+};
+
+static struct bin_attribute bin_attr_port_stats = {
+ .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_port_stats,
+ .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+ .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_esw_stats,
+ .write = qlcnic_sysfs_clear_esw_stats,
+};
+
+static struct bin_attribute bin_attr_esw_config = {
+ .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_esw_config,
+ .write = qlcnic_sysfs_write_esw_config,
+};
+
+static struct bin_attribute bin_attr_pm_config = {
+ .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_pm_config,
+ .write = qlcnic_sysfs_write_pm_config,
+};
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ if (device_create_file(dev, &dev_attr_bridged_mode))
+ dev_warn(dev,
+ "failed to create bridged_mode sysfs entry\n");
+}
+
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ device_remove_file(dev, &dev_attr_bridged_mode);
+}
+
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+ if (device_create_bin_file(dev, &bin_attr_port_stats))
+ dev_info(dev, "failed to create port stats sysfs entry");
+
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
+ if (device_create_file(dev, &dev_attr_diag_mode))
+ dev_info(dev, "failed to create diag_mode sysfs entry\n");
+ if (device_create_bin_file(dev, &bin_attr_crb))
+ dev_info(dev, "failed to create crb sysfs entry\n");
+ if (device_create_bin_file(dev, &bin_attr_mem))
+ dev_info(dev, "failed to create mem sysfs entry\n");
+
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+ return;
+
+ if (device_create_bin_file(dev, &bin_attr_pci_config))
+ dev_info(dev, "failed to create pci config sysfs entry");
+ if (device_create_file(dev, &dev_attr_beacon))
+ dev_info(dev, "failed to create beacon sysfs entry");
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ if (device_create_bin_file(dev, &bin_attr_esw_config))
+ dev_info(dev, "failed to create esw config sysfs entry");
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return;
+ if (device_create_bin_file(dev, &bin_attr_npar_config))
+ dev_info(dev, "failed to create npar config sysfs entry");
+ if (device_create_bin_file(dev, &bin_attr_pm_config))
+ dev_info(dev, "failed to create pm config sysfs entry");
+ if (device_create_bin_file(dev, &bin_attr_esw_stats))
+ dev_info(dev, "failed to create eswitch stats sysfs entry");
+}
+
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+ device_remove_bin_file(dev, &bin_attr_port_stats);
+
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
+ device_remove_file(dev, &dev_attr_diag_mode);
+ device_remove_bin_file(dev, &bin_attr_crb);
+ device_remove_bin_file(dev, &bin_attr_mem);
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+ return;
+ device_remove_bin_file(dev, &bin_attr_pci_config);
+ device_remove_file(dev, &dev_attr_beacon);
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ device_remove_bin_file(dev, &bin_attr_esw_config);
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return;
+ device_remove_bin_file(dev, &bin_attr_npar_config);
+ device_remove_bin_file(dev, &bin_attr_pm_config);
+ device_remove_bin_file(dev, &bin_attr_esw_stats);
+}
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
index 58185b604b72..10093f0c4c0f 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
@@ -86,7 +86,7 @@ exit:
}
/* Read out the SERDES registers */
-static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data)
+static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
{
int status;
@@ -364,7 +364,7 @@ exit:
/* Read the 400 xgmac control/statistics registers
* skipping unused locations.
*/
-static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf,
unsigned int other_function)
{
int status = 0;
@@ -405,7 +405,7 @@ static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
return status;
}
-static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf)
{
int status = 0;
int i;
@@ -423,7 +423,7 @@ static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
return status;
}
-static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
+static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf)
{
int i;
@@ -434,7 +434,7 @@ static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
}
}
-static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf)
{
int i, status;
u32 value[3];
@@ -471,7 +471,7 @@ err:
return status;
}
-static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_routing_entries(struct ql_adapter *qdev, u32 *buf)
{
int status;
u32 value, i;
@@ -496,7 +496,7 @@ err:
}
/* Read the MPI Processor shadow registers */
-static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 *buf)
{
u32 i;
int status;
@@ -515,7 +515,7 @@ end:
}
/* Read the MPI Processor core registers */
-static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf,
u32 offset, u32 count)
{
int i, status = 0;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b262d6156816..f80cd975daed 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4491,8 +4491,8 @@ static void ql_release_all(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-static int __devinit ql_init_device(struct pci_dev *pdev,
- struct net_device *ndev, int cards_found)
+static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev,
+ int cards_found)
{
struct ql_adapter *qdev = netdev_priv(ndev);
int err = 0;
@@ -4656,8 +4656,8 @@ static void ql_timer(unsigned long data)
mod_timer(&qdev->timer, jiffies + (5*HZ));
}
-static int __devinit qlge_probe(struct pci_dev *pdev,
- const struct pci_device_id *pci_entry)
+static int qlge_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_entry)
{
struct net_device *ndev = NULL;
struct ql_adapter *qdev = NULL;
@@ -4729,7 +4729,7 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget)
return ql_clean_inbound_rx_ring(rx_ring, budget);
}
-static void __devexit qlge_remove(struct pci_dev *pdev)
+static void qlge_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
@@ -4921,7 +4921,7 @@ static struct pci_driver qlge_driver = {
.name = DRV_NAME,
.id_table = qlge_pci_tbl,
.probe = qlge_probe,
- .remove = __devexit_p(qlge_remove),
+ .remove = qlge_remove,
#ifdef CONFIG_PM
.suspend = qlge_suspend,
.resume = qlge_resume,
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index 557a26545d75..63c13125db6c 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -206,7 +206,7 @@ struct r6040_private {
int old_duplex;
};
-static char version[] __devinitdata = DRV_NAME
+static char version[] = DRV_NAME
": RDC R6040 NAPI net driver,"
"version "DRV_VERSION " (" DRV_RELDATE ")";
@@ -1073,8 +1073,7 @@ static int r6040_mii_probe(struct net_device *dev)
return 0;
}
-static int __devinit r6040_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct r6040_private *lp;
@@ -1246,7 +1245,7 @@ err_out:
return err;
}
-static void __devexit r6040_remove_one(struct pci_dev *pdev)
+static void r6040_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct r6040_private *lp = netdev_priv(dev);
@@ -1274,7 +1273,7 @@ static struct pci_driver r6040_driver = {
.name = DRV_NAME,
.id_table = r6040_pci_tbl,
.probe = r6040_init_one,
- .remove = __devexit_p(r6040_remove_one),
+ .remove = r6040_remove_one,
};
module_pci_driver(r6040_driver);
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 609125a249d9..cb6fc5a743ca 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp)
{
unsigned tx_head = cp->tx_head;
unsigned tx_tail = cp->tx_tail;
+ unsigned bytes_compl = 0, pkts_compl = 0;
while (tx_tail != tx_head) {
struct cp_desc *txd = cp->tx_ring + tx_tail;
@@ -666,6 +667,9 @@ 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,
@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp)
cp->tx_tail = tx_tail;
+ netdev_completed_queue(cp->dev, pkts_compl, bytes_compl);
if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
netif_wake_queue(cp->dev);
}
@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
wmb();
}
cp->tx_head = entry;
+
+ netdev_sent_queue(dev, skb->len);
netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
entry, skb->len);
if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp)
cp->rx_tail = 0;
cp->tx_head = cp->tx_tail = 0;
+
+ netdev_reset_queue(cp->dev);
}
static void cp_reset_hw (struct cp_private *cp)
@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp)
static inline void cp_start_hw (struct cp_private *cp)
{
+ dma_addr_t ring_dma;
+
cpw16(CpCmd, cp->cpcmd);
+
+ /*
+ * These (at least TxRingAddr) need to be configured after the
+ * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33
+ * (C+ Command Register) recommends that these and more be configured
+ * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware
+ * it's been observed that the TxRingAddr is actually reset to garbage
+ * when C+ mode Tx is enabled in CpCmd.
+ */
+ cpw32_f(HiTxRingAddr, 0);
+ cpw32_f(HiTxRingAddr + 4, 0);
+
+ ring_dma = cp->ring_dma;
+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+ /*
+ * Strictly speaking, the datasheet says this should be enabled
+ * *before* setting the descriptor addresses. But what, then, would
+ * prevent it from doing DMA to random unconfigured addresses?
+ * This variant appears to work fine.
+ */
cpw8(Cmd, RxOn | TxOn);
+
+ netdev_reset_queue(cp->dev);
}
static void cp_enable_irq(struct cp_private *cp)
@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp)
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
- dma_addr_t ring_dma;
cp_reset_hw(cp);
@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_private *cp)
cpw8(Config5, cpr8(Config5) & PMEStatus);
- cpw32_f(HiTxRingAddr, 0);
- cpw32_f(HiTxRingAddr + 4, 0);
-
- ring_dma = cp->ring_dma;
- cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
- cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
cpw16(MultiIntr, 0);
cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1197,18 +1224,16 @@ static void cp_tx_timeout(struct net_device *dev)
cp_clean_rings(cp);
rc = cp_init_rings(cp);
cp_start_hw(cp);
+ cp_enable_irq(cp);
netif_wake_queue(dev);
spin_unlock_irqrestore(&cp->lock, flags);
}
-#ifdef BROKEN
static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
struct cp_private *cp = netdev_priv(dev);
- int rc;
- unsigned long flags;
/* check for invalid MTU, according to hardware limits */
if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
@@ -1221,22 +1246,12 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
- spin_lock_irqsave(&cp->lock, flags);
-
- cp_stop_hw(cp); /* stop h/w and free rings */
- cp_clean_rings(cp);
-
+ /* network IS up, close it, reset MTU, and come up again. */
+ cp_close(dev);
dev->mtu = new_mtu;
- cp_set_rxbufsize(cp); /* set new rx buf size */
-
- rc = cp_init_rings(cp); /* realloc and restart h/w */
- cp_start_hw(cp);
-
- spin_unlock_irqrestore(&cp->lock, flags);
-
- return rc;
+ cp_set_rxbufsize(cp);
+ return cp_open(dev);
}
-#endif /* BROKEN */
static const char mii_2_8139_map[8] = {
BasicModeCtrl,
@@ -1812,9 +1827,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_start_xmit = cp_start_xmit,
.ndo_tx_timeout = cp_tx_timeout,
.ndo_set_features = cp_set_features,
-#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 3ed7add23c12..5dc161630127 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -228,7 +228,7 @@ typedef enum {
static const struct {
const char *name;
u32 hw_flags;
-} board_info[] __devinitconst = {
+} board_info[] = {
{ "RealTek RTL8139", RTL8139_CAPS },
{ "RealTek RTL8129", RTL8129_CAPS },
};
@@ -748,7 +748,7 @@ static void rtl8139_chip_reset (void __iomem *ioaddr)
}
-static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
+static struct net_device *rtl8139_init_board(struct pci_dev *pdev)
{
struct device *d = &pdev->dev;
void __iomem *ioaddr;
@@ -935,8 +935,8 @@ static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_set_features = rtl8139_set_features,
};
-static int __devinit rtl8139_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int rtl8139_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev = NULL;
struct rtl8139_private *tp;
@@ -1103,7 +1103,7 @@ err_out:
}
-static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
+static void rtl8139_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct rtl8139_private *tp = netdev_priv(dev);
@@ -1141,7 +1141,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
-static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+static int read_eeprom(void __iomem *ioaddr, int location, int addr_len)
{
int i;
unsigned retval = 0;
@@ -2652,7 +2652,7 @@ static struct pci_driver rtl8139_pci_driver = {
.name = DRV_NAME,
.id_table = rtl8139_pci_tbl,
.probe = rtl8139_init_one,
- .remove = __devexit_p(rtl8139_remove_one),
+ .remove = rtl8139_remove_one,
#ifdef CONFIG_PM
.suspend = rtl8139_suspend,
.resume = rtl8139_resume,
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index e02f04d7f3ad..9f2d416de750 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -175,8 +175,7 @@ struct net_local {
unsigned int tx_unit_busy:1;
unsigned char re_tx, /* Number of packet retransmissions. */
addr_mode, /* Current Rx filter e.g. promiscuous, etc. */
- pac_cnt_in_tx_buf,
- chip_type;
+ pac_cnt_in_tx_buf;
};
/* This code, written by wwc@super.org, resets the adapter every
@@ -339,7 +338,6 @@ static int __init atp_probe1(long ioaddr)
write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
lp = netdev_priv(dev);
- lp->chip_type = RTL8002;
lp->addr_mode = CMR2h_Normal;
spin_lock_init(&lp->lock);
@@ -852,7 +850,7 @@ net_close(struct net_device *dev)
* Set or clear the multicast filter for this adapter.
*/
-static void set_rx_mode_8002(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
long ioaddr = dev->base_addr;
@@ -864,58 +862,6 @@ static void set_rx_mode_8002(struct net_device *dev)
write_reg_high(ioaddr, CMR2, lp->addr_mode);
}
-static void set_rx_mode_8012(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */
- int i;
-
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- new_mode = CMR2h_PROMISC;
- } else if ((netdev_mc_count(dev) > 1000) ||
- (dev->flags & IFF_ALLMULTI)) {
- /* Too many to filter perfectly -- accept all multicasts. */
- memset(mc_filter, 0xff, sizeof(mc_filter));
- new_mode = CMR2h_Normal;
- } else {
- struct netdev_hw_addr *ha;
-
- memset(mc_filter, 0, sizeof(mc_filter));
- netdev_for_each_mc_addr(ha, dev) {
- int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
- mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
- }
- new_mode = CMR2h_Normal;
- }
- lp->addr_mode = new_mode;
- write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */
- for (i = 0; i < 8; i++)
- write_reg_byte(ioaddr, i, mc_filter[i]);
- if (net_debug > 2 || 1) {
- lp->addr_mode = 1;
- printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to",
- dev->name, lp->addr_mode);
- for (i = 0; i < 8; i++)
- printk(" %2.2x", mc_filter[i]);
- printk(".\n");
- }
-
- write_reg_high(ioaddr, CMR2, lp->addr_mode);
- write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- if (lp->chip_type == RTL8002)
- return set_rx_mode_8002(dev);
- else
- return set_rx_mode_8012(dev);
-}
-
-
static int __init atp_init_module(void) {
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s", version);
diff --git a/drivers/net/ethernet/realtek/atp.h b/drivers/net/ethernet/realtek/atp.h
index 0edc642c2c2f..040b13739947 100644
--- a/drivers/net/ethernet/realtek/atp.h
+++ b/drivers/net/ethernet/realtek/atp.h
@@ -16,8 +16,6 @@ struct rx_header {
#define PAR_STATUS 1
#define PAR_CONTROL 2
-enum chip_type { RTL8002, RTL8012 };
-
#define Ctrl_LNibRead 0x08 /* LP_PSELECP */
#define Ctrl_HNibRead 0
#define Ctrl_LNibWrite 0x08 /* LP_PSELECP */
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 927aa33d4349..ed96f309bca8 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -78,24 +78,18 @@ static const int multicast_filter_limit = 32;
#define MAX_READ_REQUEST_SHIFT 12
#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
-#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
#define R8169_REGS_SIZE 256
#define R8169_NAPI_WEIGHT 64
#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
-#define RX_BUF_SIZE 1536 /* Rx Buffer size */
#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
#define RTL8169_TX_TIMEOUT (6*HZ)
#define RTL8169_PHY_TIMEOUT (10*HZ)
-#define RTL_EEPROM_SIG cpu_to_le32(0x8129)
-#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff)
-#define RTL_EEPROM_SIG_ADDR 0x0000
-
/* write/read MMIO register */
#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
@@ -456,6 +450,7 @@ enum rtl8168_registers {
#define PWM_EN (1 << 22)
#define RXDV_GATED_EN (1 << 19)
#define EARLY_TALLY_EN (1 << 16)
+#define FORCE_CLK (1 << 15) /* force clock request */
};
enum rtl_register_content {
@@ -519,6 +514,7 @@ enum rtl_register_content {
PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */
+ ClkReqEn = (1 << 7), /* Clock Request Enable */
MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
PCI_Clock_66MHz = 0x01,
PCI_Clock_33MHz = 0x00,
@@ -539,6 +535,7 @@ enum rtl_register_content {
Spi_en = (1 << 3),
LanWake = (1 << 1), /* LanWake enable/disable */
PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
+ ASPM_en = (1 << 0), /* ASPM enable */
/* TBICSR p.28 */
TBIReset = 0x80000000,
@@ -687,6 +684,7 @@ enum features {
RTL_FEATURE_WOL = (1 << 0),
RTL_FEATURE_MSI = (1 << 1),
RTL_FEATURE_GMII = (1 << 2),
+ RTL_FEATURE_FW_LOADED = (1 << 3),
};
struct rtl8169_counters {
@@ -1816,8 +1814,7 @@ static int rtl8169_set_features(struct net_device *dev,
}
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
- struct sk_buff *skb)
+static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
{
return (vlan_tx_tag_present(skb)) ?
TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
@@ -2394,8 +2391,10 @@ static void rtl_apply_firmware(struct rtl8169_private *tp)
struct rtl_fw *rtl_fw = tp->rtl_fw;
/* TODO: release firmware once rtl_phy_write_fw signals failures. */
- if (!IS_ERR_OR_NULL(rtl_fw))
+ if (!IS_ERR_OR_NULL(rtl_fw)) {
rtl_phy_write_fw(tp, rtl_fw);
+ tp->features |= RTL_FEATURE_FW_LOADED;
+ }
}
static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -2406,6 +2405,31 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
rtl_apply_firmware(tp);
}
+static void r810x_aldps_disable(struct rtl8169_private *tp)
+{
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_writephy(tp, 0x18, 0x0310);
+ msleep(100);
+}
+
+static void r810x_aldps_enable(struct rtl8169_private *tp)
+{
+ if (!(tp->features & RTL_FEATURE_FW_LOADED))
+ return;
+
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_writephy(tp, 0x18, 0x8310);
+}
+
+static void r8168_aldps_enable_1(struct rtl8169_private *tp)
+{
+ if (!(tp->features & RTL_FEATURE_FW_LOADED))
+ return;
+
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
+}
+
static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3096,6 +3120,23 @@ static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x0d, 0x0000);
}
+static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
+{
+ const u16 w[] = {
+ addr[0] | (addr[1] << 8),
+ addr[2] | (addr[3] << 8),
+ addr[4] | (addr[5] << 8)
+ };
+ const struct exgmac_reg e[] = {
+ { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
+ { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
+ { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
+ { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
+ };
+
+ rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
+}
+
static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3178,6 +3219,11 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ r8168_aldps_enable_1(tp);
+
+ /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
+ rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
}
static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
@@ -3250,6 +3296,8 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x05, 0x8b85);
rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ r8168_aldps_enable_1(tp);
}
static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3257,6 +3305,8 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
rtl_apply_firmware(tp);
rtl8168f_hw_phy_config(tp);
+
+ r8168_aldps_enable_1(tp);
}
static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
@@ -3354,6 +3404,8 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ r8168_aldps_enable_1(tp);
}
static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3439,21 +3491,19 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
};
/* Disable ALDPS before ram code */
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_writephy(tp, 0x18, 0x0310);
- msleep(100);
+ r810x_aldps_disable(tp);
rtl_apply_firmware(tp);
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ r810x_aldps_enable(tp);
}
static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
{
/* Disable ALDPS before setting firmware */
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_writephy(tp, 0x18, 0x0310);
- msleep(20);
+ r810x_aldps_disable(tp);
rtl_apply_firmware(tp);
@@ -3463,6 +3513,8 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x10, 0x401f);
rtl_writephy(tp, 0x19, 0x7030);
rtl_writephy(tp, 0x1f, 0x0000);
+
+ r810x_aldps_enable(tp);
}
static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -3475,9 +3527,7 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
};
/* Disable ALDPS before ram code */
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_writephy(tp, 0x18, 0x0310);
- msleep(100);
+ r810x_aldps_disable(tp);
rtl_apply_firmware(tp);
@@ -3485,6 +3535,8 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+ r810x_aldps_enable(tp);
}
static void rtl_hw_phy_config(struct net_device *dev)
@@ -3708,33 +3760,19 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
{
void __iomem *ioaddr = tp->mmio_addr;
- u32 high;
- u32 low;
-
- low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
- high = addr[4] | (addr[5] << 8);
rtl_lock_work(tp);
RTL_W8(Cfg9346, Cfg9346_Unlock);
- RTL_W32(MAC4, high);
+ RTL_W32(MAC4, addr[4] | addr[5] << 8);
RTL_R32(MAC4);
- RTL_W32(MAC0, low);
+ RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
RTL_R32(MAC0);
- if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
- const struct exgmac_reg e[] = {
- { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
- { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
- { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
- { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
- low >> 16 },
- };
-
- rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
- }
+ if (tp->mac_version == RTL_GIGA_MAC_VER_34)
+ rtl_rar_exgmac_set(tp, addr);
RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -3796,7 +3834,7 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
}
}
-static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
+static void rtl_init_mdio_ops(struct rtl8169_private *tp)
{
struct mdio_ops *ops = &tp->mdio_ops;
@@ -4048,7 +4086,7 @@ static void rtl_pll_power_up(struct rtl8169_private *tp)
rtl_generic_op(tp, tp->pll_power_ops.up);
}
-static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
+static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
{
struct pll_power_ops *ops = &tp->pll_power_ops;
@@ -4242,7 +4280,7 @@ static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
}
-static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
{
struct jumbo_ops *ops = &tp->jumbo_ops;
@@ -4683,7 +4721,7 @@ static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
RTL_R32(CSIDR) : ~0;
}
-static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
+static void rtl_init_csi_ops(struct rtl8169_private *tp)
{
struct csi_ops *ops = &tp->csi_ops;
@@ -5015,8 +5053,6 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
RTL_W8(MaxTxPacketSize, EarlySize);
- rtl_disable_clock_request(pdev);
-
RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
@@ -5025,7 +5061,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
- RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+ RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
}
static void rtl_hw_start_8168f(struct rtl8169_private *tp)
@@ -5050,13 +5087,12 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
RTL_W8(MaxTxPacketSize, EarlySize);
- rtl_disable_clock_request(pdev);
-
RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
- RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
- RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+ RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
+ RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
}
static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
@@ -5113,8 +5149,10 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
- RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+ RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
RTL_W8(MaxTxPacketSize, EarlySize);
+ RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
@@ -5330,6 +5368,9 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+ RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+ RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
}
@@ -5355,6 +5396,9 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+ RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+ RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
@@ -5376,7 +5420,10 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
/* Force LAN exit from ASPM if Rx/Tx are not idle */
RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
- RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
+ RTL_W32(MISC,
+ (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
+ RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+ RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
}
@@ -5774,7 +5821,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
tp->tx_skb[entry].len = len;
txd->addr = cpu_to_le64(mapping);
- opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
+ opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
opts[0] = DescOwn;
rtl8169_tso_csum(tp, skb, opts);
@@ -6569,7 +6616,7 @@ static void rtl_shutdown(struct pci_dev *pdev)
pm_runtime_put_noidle(d);
}
-static void __devexit rtl_remove_one(struct pci_dev *pdev)
+static void rtl_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
@@ -6689,7 +6736,7 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond)
return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
}
-static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
+static void rtl_hw_init_8168g(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
u32 data;
@@ -6723,7 +6770,7 @@ static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
return;
}
-static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
+static void rtl_hw_initialize(struct rtl8169_private *tp)
{
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_40:
@@ -6736,7 +6783,7 @@ static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
}
}
-static int __devinit
+static int
rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
@@ -6987,20 +7034,9 @@ static struct pci_driver rtl8169_pci_driver = {
.name = MODULENAME,
.id_table = rtl8169_pci_tbl,
.probe = rtl_init_one,
- .remove = __devexit_p(rtl_remove_one),
+ .remove = rtl_remove_one,
.shutdown = rtl_shutdown,
.driver.pm = RTL8169_PM_OPS,
};
-static int __init rtl8169_init_module(void)
-{
- return pci_register_driver(&rtl8169_pci_driver);
-}
-
-static void __exit rtl8169_cleanup_module(void)
-{
- pci_unregister_driver(&rtl8169_pci_driver);
-}
-
-module_init(rtl8169_init_module);
-module_exit(rtl8169_cleanup_module);
+module_pci_driver(rtl8169_pci_driver);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index c8bfea0524dd..3d705862bd7d 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2286,7 +2286,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
for (i = 0; i < PHY_MAX_ADDR; i++)
mdp->mii_bus->irq[i] = PHY_POLL;
- /* regist mdio bus */
+ /* register mdio bus */
ret = mdiobus_register(mdp->mii_bus);
if (ret)
goto out_free_irq;
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 2ed3ab4b3c2d..72fc57dd084d 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -954,7 +954,7 @@ static struct net_device_stats *s6gmac_stats(struct net_device *dev)
return st;
}
-static int __devinit s6gmac_probe(struct platform_device *pdev)
+static int s6gmac_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct s6gmac *pd;
@@ -1030,7 +1030,7 @@ errirq:
return res;
}
-static int __devexit s6gmac_remove(struct platform_device *pdev)
+static int s6gmac_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
if (dev) {
@@ -1046,7 +1046,7 @@ static int __devexit s6gmac_remove(struct platform_device *pdev)
static struct platform_driver s6gmac_driver = {
.probe = s6gmac_probe,
- .remove = __devexit_p(s6gmac_remove),
+ .remove = s6gmac_remove,
.driver = {
.name = "s6gmac",
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index 6a40dd03a32f..3aca57853ed4 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -67,7 +67,7 @@
#include <asm/ecard.h>
#include <asm/io.h>
-static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
+static char version[] = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
#include "ether3.h"
@@ -194,7 +194,7 @@ static inline void ether3_ledon(struct net_device *dev)
* Read the ethernet address string from the on board rom.
* This is an ascii string!!!
*/
-static int __devinit
+static int
ether3_addr(char *addr, struct expansion_card *ec)
{
struct in_chunk_dir cd;
@@ -219,7 +219,7 @@ ether3_addr(char *addr, struct expansion_card *ec)
/* --------------------------------------------------------------------------- */
-static int __devinit
+static int
ether3_ramtest(struct net_device *dev, unsigned char byte)
{
unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
@@ -268,7 +268,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte)
/* ------------------------------------------------------------------------------- */
-static int __devinit ether3_init_2(struct net_device *dev)
+static int ether3_init_2(struct net_device *dev)
{
int i;
@@ -399,12 +399,6 @@ ether3_probe_bus_16(struct net_device *dev, int val)
static int
ether3_open(struct net_device *dev)
{
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
return -EAGAIN;
@@ -748,7 +742,7 @@ static void ether3_tx(struct net_device *dev)
}
}
-static void __devinit ether3_banner(void)
+static void ether3_banner(void)
{
static unsigned version_printed = 0;
@@ -767,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __devinit
+static int
ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
{
const struct ether3_data *data = id->data;
@@ -864,7 +858,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit ether3_remove(struct expansion_card *ec)
+static void ether3_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
@@ -894,7 +888,7 @@ static const struct ecard_id ether3_ids[] = {
static struct ecard_driver ether3_driver = {
.probe = ether3_probe,
- .remove = __devexit_p(ether3_remove),
+ .remove = ether3_remove,
.id_table = ether3_ids,
.drv = {
.name = "ether3",
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 4d15bf413bdc..0fde9ca28269 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -721,7 +721,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit sgiseeq_probe(struct platform_device *pdev)
+static int sgiseeq_probe(struct platform_device *pdev)
{
struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
struct hpc3_regs *hpcregs = pd->hpc;
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 25906c1d1b15..435b4f1e3488 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -1,10 +1,11 @@
config SFC
tristate "Solarflare SFC4000/SFC9000-family support"
- depends on PCI && INET
+ depends on PCI
select MDIO
select CRC32
select I2C
select I2C_ALGOBIT
+ select PTP_1588_CLOCK
---help---
This driver supports 10-gigabit Ethernet cards based on
the Solarflare SFC4000 and SFC9000-family controllers.
@@ -34,10 +35,3 @@ config SFC_SRIOV
This enables support for the SFC9000 I/O Virtualization
features, allowing accelerated network performance in
virtualized environments.
-config SFC_PTP
- bool "Solarflare SFC9000-family PTP support"
- depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m)
- default y
- ---help---
- This enables support for the Precision Time Protocol (PTP)
- on SFC9000-family NICs
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index e11f2ecf69d9..945bf06e69ef 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -2,9 +2,8 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
falcon_xmac.o mcdi_mac.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
tenxpress.o txc43128_phy.o falcon_boards.o \
- mcdi.o mcdi_phy.o mcdi_mon.o
+ mcdi.o mcdi_phy.o mcdi_mon.o ptp.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
-sfc-$(CONFIG_SFC_PTP) += ptp.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 4f86d0cd516a..bf57b3cb16ab 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -106,8 +106,8 @@ static struct workqueue_struct *reset_workqueue;
*
* This is only used in MSI-X interrupt mode
*/
-static unsigned int separate_tx_channels;
-module_param(separate_tx_channels, uint, 0444);
+static bool separate_tx_channels;
+module_param(separate_tx_channels, bool, 0444);
MODULE_PARM_DESC(separate_tx_channels,
"Use separate channels for TX and RX");
@@ -160,8 +160,8 @@ static unsigned int rss_cpus;
module_param(rss_cpus, uint, 0444);
MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
-static int phy_flash_cfg;
-module_param(phy_flash_cfg, int, 0644);
+static bool phy_flash_cfg;
+module_param(phy_flash_cfg, bool, 0644);
MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
static unsigned irq_adapt_low_thresh = 8000;
@@ -2279,7 +2279,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
RESET_TYPE(method));
- netif_device_detach(efx->net_dev);
+ efx_device_detach_sync(efx);
efx_reset_down(efx, method);
rc = efx->type->reset(efx, method);
@@ -2669,8 +2669,8 @@ static int efx_pci_probe_main(struct efx_nic *efx)
* transmission; this is left to the first time one of the network
* interfaces is brought up (i.e. efx_net_open).
*/
-static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *entry)
+static int efx_pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *entry)
{
struct net_device *net_dev;
struct efx_nic *efx;
@@ -2758,7 +2758,7 @@ static int efx_pm_freeze(struct device *dev)
if (efx->state != STATE_DISABLED) {
efx->state = STATE_UNINIT;
- netif_device_detach(efx->net_dev);
+ efx_device_detach_sync(efx);
efx_stop_all(efx);
efx_stop_interrupts(efx, false);
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index f11170bc48bf..50247dfe8f57 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -163,4 +163,17 @@ extern void efx_link_status_changed(struct efx_nic *efx);
extern void efx_link_set_advertising(struct efx_nic *efx, u32);
extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
+static inline void efx_device_detach_sync(struct efx_nic *efx)
+{
+ struct net_device *dev = efx->net_dev;
+
+ /* Lock/freeze all TX queues so that we can be sure the
+ * TX scheduler is stopped when we're done and before
+ * netif_device_present() becomes false.
+ */
+ netif_tx_lock(dev);
+ netif_device_detach(dev);
+ netif_tx_unlock(dev);
+}
+
#endif /* EFX_EFX_H */
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 90f078eff8e6..8e61cd06f66a 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -816,6 +816,9 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
/* MAC address mask including only MC flag */
static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
+#define IP4_ADDR_FULL_MASK ((__force __be32)~0)
+#define PORT_FULL_MASK ((__force __be16)~0)
+
static int efx_ethtool_get_class_rule(struct efx_nic *efx,
struct ethtool_rx_flow_spec *rule)
{
@@ -865,12 +868,12 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
&spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
&ip_entry->ip4src, &ip_entry->psrc);
EFX_WARN_ON_PARANOID(rc);
- ip_mask->ip4src = ~0;
- ip_mask->psrc = ~0;
+ ip_mask->ip4src = IP4_ADDR_FULL_MASK;
+ ip_mask->psrc = PORT_FULL_MASK;
}
rule->flow_type = (proto == IPPROTO_TCP) ? TCP_V4_FLOW : UDP_V4_FLOW;
- ip_mask->ip4dst = ~0;
- ip_mask->pdst = ~0;
+ ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
+ ip_mask->pdst = PORT_FULL_MASK;
return rc;
}
@@ -971,7 +974,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
/* Check for unsupported extensions */
if ((rule->flow_type & FLOW_EXT) &&
- (rule->m_ext.vlan_etype | rule->m_ext.data[0] |
+ (rule->m_ext.vlan_etype || rule->m_ext.data[0] ||
rule->m_ext.data[1]))
return -EINVAL;
@@ -986,16 +989,16 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
IPPROTO_TCP : IPPROTO_UDP);
/* Must match all of destination, */
- if ((__force u32)~ip_mask->ip4dst |
- (__force u16)~ip_mask->pdst)
+ if (!(ip_mask->ip4dst == IP4_ADDR_FULL_MASK &&
+ ip_mask->pdst == PORT_FULL_MASK))
return -EINVAL;
/* all or none of source, */
- if ((ip_mask->ip4src | ip_mask->psrc) &&
- ((__force u32)~ip_mask->ip4src |
- (__force u16)~ip_mask->psrc))
+ if ((ip_mask->ip4src || ip_mask->psrc) &&
+ !(ip_mask->ip4src == IP4_ADDR_FULL_MASK &&
+ ip_mask->psrc == PORT_FULL_MASK))
return -EINVAL;
/* and nothing else */
- if (ip_mask->tos | rule->m_ext.vlan_tci)
+ if (ip_mask->tos || rule->m_ext.vlan_tci)
return -EINVAL;
if (ip_mask->ip4src)
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 12b573a8e82b..49bcd196e10d 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -1792,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.remove_port = falcon_remove_port,
.handle_global_event = falcon_handle_global_event,
.prepare_flush = falcon_prepare_flush,
+ .finish_flush = efx_port_dummy_op_void,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
.stop_stats = falcon_stop_nic_stats,
@@ -1834,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.remove_port = falcon_remove_port,
.handle_global_event = falcon_handle_global_event,
.prepare_flush = falcon_prepare_flush,
+ .finish_flush = efx_port_dummy_op_void,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
.stop_stats = falcon_stop_nic_stats,
diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h
index 751d1ec112cc..96759aee1c6c 100644
--- a/drivers/net/ethernet/sfc/io.h
+++ b/drivers/net/ethernet/sfc/io.h
@@ -22,22 +22,21 @@
*
* Notes on locking strategy:
*
- * Most CSRs are 128-bit (oword) and therefore cannot be read or
- * written atomically. Access from the host is buffered by the Bus
- * Interface Unit (BIU). Whenever the host reads from the lowest
- * address of such a register, or from the address of a different such
- * register, the BIU latches the register's value. Subsequent reads
- * from higher addresses of the same register will read the latched
- * value. Whenever the host writes part of such a register, the BIU
- * collects the written value and does not write to the underlying
- * register until all 4 dwords have been written. A similar buffering
- * scheme applies to host access to the NIC's 64-bit SRAM.
+ * Many CSRs are very wide and cannot be read or written atomically.
+ * Writes from the host are buffered by the Bus Interface Unit (BIU)
+ * up to 128 bits. Whenever the host writes part of such a register,
+ * the BIU collects the written value and does not write to the
+ * underlying register until all 4 dwords have been written. A
+ * similar buffering scheme applies to host access to the NIC's 64-bit
+ * SRAM.
*
- * Access to different CSRs and 64-bit SRAM words must be serialised,
- * since interleaved access can result in lost writes or lost
- * information from read-to-clear fields. We use efx_nic::biu_lock
- * for this. (We could use separate locks for read and write, but
- * this is not normally a performance bottleneck.)
+ * Writes to different CSRs and 64-bit SRAM words must be serialised,
+ * since interleaved access can result in lost writes. We use
+ * efx_nic::biu_lock for this.
+ *
+ * We also serialise reads from 128-bit CSRs and SRAM with the same
+ * spinlock. This may not be necessary, but it doesn't really matter
+ * as there are no such reads on the fast path.
*
* The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are
* 128-bit but are special-cased in the BIU to avoid the need for
@@ -204,20 +203,6 @@ static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
}
-/* Write a 32-bit CSR forming part of a table, or 32-bit SRAM */
-static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value,
- unsigned int reg, unsigned int index)
-{
- efx_writed(efx, value, reg + index * sizeof(efx_oword_t));
-}
-
-/* Read a 32-bit CSR forming part of a table, or 32-bit SRAM */
-static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value,
- unsigned int reg, unsigned int index)
-{
- efx_readd(efx, value, reg + index * sizeof(efx_dword_t));
-}
-
/* Page-mapped register block size */
#define EFX_PAGE_BLOCK_SIZE 0x2000
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index aea43cbd0520..0095ce95150b 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -22,7 +22,7 @@
**************************************************************************
*/
-#define MCDI_RPC_TIMEOUT 10 /*seconds */
+#define MCDI_RPC_TIMEOUT (10 * HZ)
#define MCDI_PDU(efx) \
(efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
@@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
static int efx_mcdi_poll(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
- unsigned int time, finish;
+ unsigned long time, finish;
unsigned int respseq, respcmd, error;
unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
unsigned int rc, spins;
@@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
* and poll once a jiffy (approximately)
*/
spins = TICK_USEC;
- finish = get_seconds() + MCDI_RPC_TIMEOUT;
+ finish = jiffies + MCDI_RPC_TIMEOUT;
while (1) {
if (spins != 0) {
@@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
schedule_timeout_uninterruptible(1);
}
- time = get_seconds();
+ time = jiffies;
rmb();
efx_readd(efx, &reg, pdu);
@@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
break;
- if (time >= finish)
+ if (time_after(time, finish))
return -ETIMEDOUT;
}
@@ -207,7 +207,9 @@ out:
return 0;
}
-/* Test and clear MC-rebooted flag for this port/function */
+/* Test and clear MC-rebooted flag for this port/function; reset
+ * software state as necessary.
+ */
int efx_mcdi_poll_reboot(struct efx_nic *efx)
{
unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
@@ -223,6 +225,11 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx)
if (value == 0)
return 0;
+ /* MAC statistics have been cleared on the NIC; clear our copy
+ * so that efx_update_diff_stat() can continue to work.
+ */
+ memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
+
EFX_ZERO_DWORD(reg);
efx_writed(efx, &reg, addr);
@@ -250,7 +257,7 @@ static int efx_mcdi_await_completion(struct efx_nic *efx)
if (wait_event_timeout(
mcdi->wq,
atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
- msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0)
+ MCDI_RPC_TIMEOUT) == 0)
return -ETIMEDOUT;
/* Check if efx_mcdi_set_mode() switched us back to polled completions.
@@ -1216,7 +1223,7 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx)
rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid,
count * sizeof(*qid), NULL, 0, NULL);
- WARN_ON(rc > 0);
+ WARN_ON(rc < 0);
kfree(qid);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 576a31091165..2d756c1d7142 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -200,6 +200,7 @@ struct efx_tx_queue {
/* Members shared between paths and sometimes updated */
unsigned int empty_read_count ____cacheline_aligned_in_smp;
#define EFX_EMPTY_COUNT_VALID 0x80000000
+ atomic_t flush_outstanding;
};
/**
@@ -868,9 +869,7 @@ struct efx_nic {
struct work_struct peer_work;
#endif
-#ifdef CONFIG_SFC_PTP
struct efx_ptp_data *ptp_data;
-#endif
/* The following fields may be written more often */
@@ -909,6 +908,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @remove_port: Free resources allocated by probe_port()
* @handle_global_event: Handle a "global" event (may be %NULL)
* @prepare_flush: Prepare the hardware for flushing the DMA queues
+ * @finish_flush: Clean up after flushing the DMA queues
* @update_stats: Update statistics not provided by event handling
* @start_stats: Start the regular fetching of statistics
* @stop_stats: Stop the regular fetching of statistics
@@ -956,6 +956,7 @@ struct efx_nic_type {
void (*remove_port)(struct efx_nic *efx);
bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
void (*prepare_flush)(struct efx_nic *efx);
+ void (*finish_flush)(struct efx_nic *efx);
void (*update_stats)(struct efx_nic *efx);
void (*start_stats)(struct efx_nic *efx);
void (*stop_stats)(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index aab7cacb2e34..0ad790cc473c 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -73,6 +73,8 @@
_EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \
(_tx_queue)->queue)
+static void efx_magic_event(struct efx_channel *channel, u32 magic);
+
/**************************************************************************
*
* Solarstorm hardware access
@@ -255,9 +257,6 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
buffer->entries = len / EFX_BUF_SIZE;
BUG_ON(buffer->dma_addr & (EFX_BUF_SIZE - 1));
- /* All zeros is a potentially valid event so memset to 0xff */
- memset(buffer->addr, 0xff, len);
-
/* Select new buffer ID */
buffer->index = efx->next_buffer_table;
efx->next_buffer_table += buffer->entries;
@@ -494,6 +493,9 @@ static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t tx_flush_descq;
+ WARN_ON(atomic_read(&tx_queue->flush_outstanding));
+ atomic_set(&tx_queue->flush_outstanding, 1);
+
EFX_POPULATE_OWORD_2(tx_flush_descq,
FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
@@ -669,6 +671,47 @@ static bool efx_flush_wake(struct efx_nic *efx)
&& atomic_read(&efx->rxq_flush_pending) > 0));
}
+static bool efx_check_tx_flush_complete(struct efx_nic *efx)
+{
+ bool i = true;
+ efx_oword_t txd_ptr_tbl;
+ struct efx_channel *channel;
+ struct efx_tx_queue *tx_queue;
+
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ efx_reado_table(efx, &txd_ptr_tbl,
+ FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue);
+ if (EFX_OWORD_FIELD(txd_ptr_tbl,
+ FRF_AZ_TX_DESCQ_FLUSH) ||
+ EFX_OWORD_FIELD(txd_ptr_tbl,
+ FRF_AZ_TX_DESCQ_EN)) {
+ netif_dbg(efx, hw, efx->net_dev,
+ "flush did not complete on TXQ %d\n",
+ tx_queue->queue);
+ i = false;
+ } else if (atomic_cmpxchg(&tx_queue->flush_outstanding,
+ 1, 0)) {
+ /* The flush is complete, but we didn't
+ * receive a flush completion event
+ */
+ netif_dbg(efx, hw, efx->net_dev,
+ "flush complete on TXQ %d, so drain "
+ "the queue\n", tx_queue->queue);
+ /* Don't need to increment drain_pending as it
+ * has already been incremented for the queues
+ * which did not drain
+ */
+ efx_magic_event(channel,
+ EFX_CHANNEL_MAGIC_TX_DRAIN(
+ tx_queue));
+ }
+ }
+ }
+
+ return i;
+}
+
/* Flush all the transmit queues, and continue flushing receive queues until
* they're all flushed. Wait for the DRAIN events to be recieved so that there
* are no more RX and TX events left on any channel. */
@@ -680,7 +723,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
struct efx_tx_queue *tx_queue;
int rc = 0;
- efx->fc_disable++;
efx->type->prepare_flush(efx);
efx_for_each_channel(channel, efx) {
@@ -730,7 +772,8 @@ int efx_nic_flush_queues(struct efx_nic *efx)
timeout);
}
- if (atomic_read(&efx->drain_pending)) {
+ if (atomic_read(&efx->drain_pending) &&
+ !efx_check_tx_flush_complete(efx)) {
netif_err(efx, hw, efx->net_dev, "failed to flush %d queues "
"(rx %d+%d)\n", atomic_read(&efx->drain_pending),
atomic_read(&efx->rxq_flush_outstanding),
@@ -742,7 +785,7 @@ int efx_nic_flush_queues(struct efx_nic *efx)
atomic_set(&efx->rxq_flush_outstanding, 0);
}
- efx->fc_disable--;
+ efx->type->finish_flush(efx);
return rc;
}
@@ -766,8 +809,13 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
channel->eventq_read_ptr & channel->eventq_mask);
- efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
- channel->channel);
+
+ /* For Falcon A1, EVQ_RPTR_KER is documented as having a step size
+ * of 4 bytes, but it is really 16 bytes just like later revisions.
+ */
+ efx_writed(efx, &reg,
+ efx->type->evq_rptr_tbl_base +
+ FR_BZ_EVQ_RPTR_STEP * channel->channel);
}
/* Use HW to insert a SW defined event */
@@ -1017,9 +1065,10 @@ efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) {
tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES,
qid % EFX_TXQ_TYPES);
-
- efx_magic_event(tx_queue->channel,
- EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
+ if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
+ efx_magic_event(tx_queue->channel,
+ EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
+ }
}
}
@@ -1565,7 +1614,9 @@ void efx_nic_push_rx_indir_table(struct efx_nic *efx)
for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
efx->rx_indir_table[i]);
- efx_writed_table(efx, &dword, FR_BZ_RX_INDIRECTION_TBL, i);
+ efx_writed(efx, &dword,
+ FR_BZ_RX_INDIRECTION_TBL +
+ FR_BZ_RX_INDIRECTION_TBL_STEP * i);
}
}
@@ -2029,15 +2080,15 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
for (i = 0; i < table->rows; i++) {
switch (table->step) {
- case 4: /* 32-bit register or SRAM */
- efx_readd_table(efx, buf, table->offset, i);
+ case 4: /* 32-bit SRAM */
+ efx_readd(efx, buf, table->offset + 4 * i);
break;
case 8: /* 64-bit SRAM */
efx_sram_readq(efx,
efx->membase + table->offset,
buf, i);
break;
- case 16: /* 128-bit register */
+ case 16: /* 128-bit-readable register */
efx_reado_table(efx, buf, table->offset, i);
break;
case 32: /* 128-bit register, interleaved */
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 438cef11f727..1b0003323498 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -252,7 +252,6 @@ extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
bool spoofchk);
struct ethtool_ts_info;
-#ifdef CONFIG_SFC_PTP
extern void efx_ptp_probe(struct efx_nic *efx);
extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
extern int efx_ptp_get_ts_info(struct net_device *net_dev,
@@ -260,31 +259,6 @@ extern int efx_ptp_get_ts_info(struct net_device *net_dev,
extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
-#else
-static inline void efx_ptp_probe(struct efx_nic *efx) {}
-static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
-{
- return -EOPNOTSUPP;
-}
-static inline int efx_ptp_get_ts_info(struct net_device *net_dev,
- struct ethtool_ts_info *ts_info)
-{
- ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
- SOF_TIMESTAMPING_RX_SOFTWARE);
- ts_info->phc_index = -1;
-
- return 0;
-}
-static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
- return false;
-}
-static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
- return NETDEV_TX_OK;
-}
-static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {}
-#endif
extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
@@ -370,6 +344,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
/* Global Resources */
extern int efx_nic_flush_queues(struct efx_nic *efx);
+extern void siena_prepare_flush(struct efx_nic *efx);
+extern void siena_finish_flush(struct efx_nic *efx);
extern void falcon_start_nic_stats(struct efx_nic *efx);
extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern void falcon_setup_xaui(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 9e0ad1b75c33..d780a0d096b4 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -187,7 +187,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
struct efx_nic *efx = rx_queue->efx;
struct efx_rx_buffer *rx_buf;
struct page *page;
- void *page_addr;
struct efx_rx_page_state *state;
dma_addr_t dma_addr;
unsigned index, count;
@@ -207,12 +206,10 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
__free_pages(page, efx->rx_buffer_order);
return -EIO;
}
- page_addr = page_address(page);
- state = page_addr;
+ state = page_address(page);
state->refcnt = 0;
state->dma_addr = dma_addr;
- page_addr += sizeof(struct efx_rx_page_state);
dma_addr += sizeof(struct efx_rx_page_state);
split:
@@ -230,7 +227,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
/* Use the second half of the page */
get_page(page);
dma_addr += (PAGE_SIZE >> 1);
- page_addr += (PAGE_SIZE >> 1);
++count;
goto split;
}
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index ce72ae4f399f..2069f51b2aa9 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -373,7 +373,7 @@ static void efx_iterate_state(struct efx_nic *efx)
/* saddr set later and used as incrementing count */
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
- payload->ip.check = htons(0xdead);
+ payload->ip.check = (__force __sum16) htons(0xdead);
payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
@@ -722,7 +722,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
/* Detach the device so the kernel doesn't transmit during the
* loopback test and the watchdog timeout doesn't fire.
*/
- netif_device_detach(efx->net_dev);
+ efx_device_detach_sync(efx);
if (efx->type->test_chip) {
rc_reset = efx->type->test_chip(efx, tests);
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 84b41bf08a38..ba40f67e4f05 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -127,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx)
efx_nic_free_buffer(efx, &efx->stats_buffer);
}
+void siena_prepare_flush(struct efx_nic *efx)
+{
+ if (efx->fc_disable++ == 0)
+ efx_mcdi_set_mac(efx);
+}
+
+void siena_finish_flush(struct efx_nic *efx)
+{
+ if (--efx->fc_disable == 0)
+ efx_mcdi_set_mac(efx);
+}
+
static const struct efx_nic_register_test siena_register_tests[] = {
{ FR_AZ_ADR_REGION,
EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
@@ -158,7 +170,7 @@ static const struct efx_nic_register_test siena_register_tests[] = {
static int siena_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
{
- enum reset_type reset_method = reset_method;
+ enum reset_type reset_method = RESET_TYPE_ALL;
int rc, rc2;
efx_reset_down(efx, reset_method);
@@ -659,7 +671,8 @@ const struct efx_nic_type siena_a0_nic_type = {
.reset = siena_reset_hw,
.probe_port = siena_probe_port,
.remove_port = siena_remove_port,
- .prepare_flush = efx_port_dummy_op_void,
+ .prepare_flush = siena_prepare_flush,
+ .finish_flush = siena_finish_flush,
.update_stats = siena_update_nic_stats,
.start_stats = siena_start_nic_stats,
.stop_stats = siena_stop_nic_stats,
diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
index d49b53dc2a50..90f8d1604f5f 100644
--- a/drivers/net/ethernet/sfc/siena_sriov.c
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -695,8 +695,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
return VFDI_RC_ENOMEM;
rtnl_lock();
- if (efx->fc_disable++ == 0)
- efx_mcdi_set_mac(efx);
+ siena_prepare_flush(efx);
rtnl_unlock();
/* Flush all the initialized queues */
@@ -733,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
}
rtnl_lock();
- if (--efx->fc_disable == 0)
- efx_mcdi_set_mac(efx);
+ siena_finish_flush(efx);
rtnl_unlock();
/* Irrespective of success/failure, fini the queues */
@@ -995,7 +993,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer)
FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
efx_writeo_table(efx, &reg, FR_BZ_EVQ_PTR_TBL, abs_evq);
EFX_POPULATE_DWORD_1(ptr, FRF_AZ_EVQ_RPTR, 0);
- efx_writed_table(efx, &ptr, FR_BZ_EVQ_RPTR, abs_evq);
+ efx_writed(efx, &ptr, FR_BZ_EVQ_RPTR + FR_BZ_EVQ_RPTR_STEP * abs_evq);
mutex_unlock(&vf->status_lock);
}
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 3e5519a0acc7..dc171b4961e4 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1143,7 +1143,7 @@ static int ioc3_is_menet(struct pci_dev *pdev)
* Can't use UPF_IOREMAP as the whole of IOC3 resources have already been
* registered.
*/
-static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
+static void ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
{
#define COSMISC_CONSTANT 6
@@ -1169,7 +1169,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
serial8250_register_8250_port(&port);
}
-static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
+static void ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
{
/*
* We need to recognice and treat the fourth MENET serial as it
@@ -1229,8 +1229,7 @@ static const struct net_device_ops ioc3_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit ioc3_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned int sw_physid1, sw_physid2;
struct net_device *dev = NULL;
@@ -1368,7 +1367,7 @@ out:
return err;
}
-static void __devexit ioc3_remove_one (struct pci_dev *pdev)
+static void ioc3_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct ioc3_private *ip = netdev_priv(dev);
@@ -1396,7 +1395,7 @@ static struct pci_driver ioc3_driver = {
.name = "ioc3-eth",
.id_table = ioc3_pci_tbl,
.probe = ioc3_probe,
- .remove = __devexit_p(ioc3_remove_one),
+ .remove = ioc3_remove_one,
};
static int __init ioc3_init_module(void)
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index 53efe7c7b1c0..79ad9c94a21b 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -825,7 +825,7 @@ static const struct net_device_ops meth_netdev_ops = {
/*
* The init function.
*/
-static int __devinit meth_probe(struct platform_device *pdev)
+static int meth_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct meth_private *priv;
diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
index 32e55664df6e..b2315324cc6d 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -1395,8 +1395,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
#endif
};
-static int __devinit sc92031_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int err;
void __iomem* port_base;
@@ -1489,7 +1488,7 @@ out_enable_device:
return err;
}
-static void __devexit sc92031_remove(struct pci_dev *pdev)
+static void sc92031_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct sc92031_priv *priv = netdev_priv(dev);
@@ -1574,7 +1573,7 @@ static struct pci_driver sc92031_pci_driver = {
.name = SC92031_NAME,
.id_table = sc92031_pci_device_id_table,
.probe = sc92031_probe,
- .remove = __devexit_p(sc92031_remove),
+ .remove = sc92031_remove,
.suspend = sc92031_suspend,
.resume = sc92031_resume,
};
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index d8166012b7d4..9a9c379420d1 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -415,7 +415,7 @@ static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
return mdio_read(ioaddr, phy_id, reg);
}
-static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
+static u16 sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
{
u16 data = 0xffff;
unsigned int i;
@@ -1379,7 +1379,7 @@ static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
* Identify and set current phy if found one,
* return error if it failed to found.
*/
-static int __devinit sis190_mii_probe(struct net_device *dev)
+static int sis190_mii_probe(struct net_device *dev)
{
struct sis190_private *tp = netdev_priv(dev);
struct mii_if_info *mii_if = &tp->mii_if;
@@ -1451,7 +1451,7 @@ static void sis190_release_board(struct pci_dev *pdev)
free_netdev(dev);
}
-static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
+static struct net_device *sis190_init_board(struct pci_dev *pdev)
{
struct sis190_private *tp;
struct net_device *dev;
@@ -1573,8 +1573,8 @@ static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
}
-static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
- struct net_device *dev)
+static int sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+ struct net_device *dev)
{
struct sis190_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
@@ -1615,10 +1615,10 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
* APC CMOS RAM is accessed through ISA bridge.
* MAC address is read into @net_dev->dev_addr.
*/
-static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
- struct net_device *dev)
+static int sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
+ struct net_device *dev)
{
- static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 };
+ static const u16 ids[] = { 0x0965, 0x0966, 0x0968 };
struct sis190_private *tp = netdev_priv(dev);
struct pci_dev *isa_bridge;
u8 reg, tmp8;
@@ -1693,8 +1693,7 @@ static inline void sis190_init_rxfilter(struct net_device *dev)
SIS_PCI_COMMIT();
}
-static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
- struct net_device *dev)
+static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
{
int rc;
@@ -1845,8 +1844,8 @@ static const struct net_device_ops sis190_netdev_ops = {
#endif
};
-static int __devinit sis190_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int sis190_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int printed_version = 0;
struct sis190_private *tp;
@@ -1916,7 +1915,7 @@ err_release_board:
goto out;
}
-static void __devexit sis190_remove_one(struct pci_dev *pdev)
+static void sis190_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct sis190_private *tp = netdev_priv(dev);
@@ -1932,7 +1931,7 @@ static struct pci_driver sis190_pci_driver = {
.name = DRV_NAME,
.id_table = sis190_pci_tbl,
.probe = sis190_init_one,
- .remove = __devexit_p(sis190_remove_one),
+ .remove = sis190_remove_one,
};
static int __init sis190_init_module(void)
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index edf5edb13140..5bffd9749a58 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -81,7 +81,7 @@
#define SIS900_MODULE_NAME "sis900"
#define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
-static const char version[] __devinitconst =
+static const char version[] =
KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
static int max_interrupt_work = 40;
@@ -251,7 +251,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
* @net_dev->perm_addr.
*/
-static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int sis900_get_mac_addr(struct pci_dev *pci_dev,
+ struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
void __iomem *ioaddr = sis_priv->ioaddr;
@@ -287,8 +288,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* @net_dev->perm_addr.
*/
-static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
- struct net_device *net_dev)
+static int sis630e_get_mac_addr(struct pci_dev *pci_dev,
+ struct net_device *net_dev)
{
struct pci_dev *isa_bridge = NULL;
u8 reg;
@@ -330,8 +331,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
* @net_dev->dev_addr and @net_dev->perm_addr.
*/
-static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
- struct net_device *net_dev)
+static int sis635_get_mac_addr(struct pci_dev *pci_dev,
+ struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
void __iomem *ioaddr = sis_priv->ioaddr;
@@ -377,8 +378,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
* MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
*/
-static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
- struct net_device *net_dev)
+static int sis96x_get_mac_addr(struct pci_dev *pci_dev,
+ struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
void __iomem *ioaddr = sis_priv->ioaddr;
@@ -433,8 +434,8 @@ static const struct net_device_ops sis900_netdev_ops = {
* ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
*/
-static int __devinit sis900_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static int sis900_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
{
struct sis900_private *sis_priv;
struct net_device *net_dev;
@@ -605,7 +606,7 @@ err_out_cleardev:
* return error if it failed to found.
*/
-static int __devinit sis900_mii_probe(struct net_device * net_dev)
+static int sis900_mii_probe(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
const char *dev_name = pci_name(sis_priv->pci_dev);
@@ -824,7 +825,7 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph
* Note that location is in word (16 bits) unit
*/
-static u16 __devinit read_eeprom(void __iomem *ioaddr, int location)
+static u16 read_eeprom(void __iomem *ioaddr, int location)
{
u32 read_cmd = location | EEread;
int i;
@@ -2410,7 +2411,7 @@ static void sis900_reset(struct net_device *net_dev)
* remove and release SiS900 net device
*/
-static void __devexit sis900_remove(struct pci_dev *pci_dev)
+static void sis900_remove(struct pci_dev *pci_dev)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct sis900_private *sis_priv = netdev_priv(net_dev);
@@ -2496,7 +2497,7 @@ static struct pci_driver sis900_pci_driver = {
.name = SIS900_MODULE_NAME,
.id_table = sis900_pci_tbl,
.probe = sis900_probe,
- .remove = __devexit_p(sis900_remove),
+ .remove = sis900_remove,
#ifdef CONFIG_PM
.suspend = sis900_suspend,
.resume = sis900_resume,
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index d01e59c348ad..03b256af7ed5 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -90,9 +90,9 @@ static int rx_copybreak;
#include <asm/byteorder.h>
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
-static char version2[] __devinitdata =
+static char version2[] =
" (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -318,8 +318,7 @@ static const struct net_device_ops epic_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit epic_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int epic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int card_idx = -1;
void __iomem *ioaddr;
@@ -569,7 +568,7 @@ static inline void epic_napi_irq_on(struct net_device *dev,
ew32(INTMASK, ep->irq_mask | EpicNapiEvent);
}
-static int __devinit read_eeprom(struct epic_private *ep, int location)
+static int read_eeprom(struct epic_private *ep, int location)
{
void __iomem *ioaddr = ep->ioaddr;
int i;
@@ -1524,7 +1523,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
-static void __devexit epic_remove_one(struct pci_dev *pdev)
+static void epic_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct epic_private *ep = netdev_priv(dev);
@@ -1577,7 +1576,7 @@ static struct pci_driver epic_driver = {
.name = DRV_NAME,
.id_table = epic_pci_tbl,
.probe = epic_init_one,
- .remove = __devexit_p(epic_remove_one),
+ .remove = epic_remove_one,
#ifdef CONFIG_PM
.suspend = epic_suspend,
.resume = epic_resume,
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 8d15f7a74b45..59a6f88da867 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1400,16 +1400,6 @@ smc911x_open(struct net_device *dev)
DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
- /*
- * Check that the address is valid. If its not, refuse
- * to bring the device up. The user must specify an
- * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
- */
- if (!is_valid_ether_addr(dev->dev_addr)) {
- PRINTK("%s: no valid ethernet hw addr\n", __func__);
- return -EINVAL;
- }
-
/* reset the hardware */
smc911x_reset(dev);
@@ -1722,7 +1712,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = {
* This routine has a simple purpose -- make the SMC chip generate an
* interrupt, so an auto-detect routine can detect it, and find the IRQ,
*/
-static int __devinit smc911x_findirq(struct net_device *dev)
+static int smc911x_findirq(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int timeout = 20;
@@ -1800,7 +1790,7 @@ static const struct net_device_ops smc911x_netdev_ops = {
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __devinit smc911x_probe(struct net_device *dev)
+static int smc911x_probe(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int i, retval;
@@ -2040,7 +2030,7 @@ err_out:
* 0 --> there is a device
* anything else, error
*/
-static int __devinit smc911x_drv_probe(struct platform_device *pdev)
+static int smc911x_drv_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct resource *res;
@@ -2115,7 +2105,7 @@ out:
return ret;
}
-static int __devexit smc911x_drv_remove(struct platform_device *pdev)
+static int smc911x_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc911x_local *lp = netdev_priv(ndev);
@@ -2186,7 +2176,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
static struct platform_driver smc911x_driver = {
.probe = smc911x_drv_probe,
- .remove = __devexit_p(smc911x_drv_remove),
+ .remove = smc911x_drv_remove,
.suspend = smc911x_drv_suspend,
.resume = smc911x_drv_resume,
.driver = {
diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h
index 3269292efecc..d51261ba4642 100644
--- a/drivers/net/ethernet/smsc/smc911x.h
+++ b/drivers/net/ethernet/smsc/smc911x.h
@@ -159,12 +159,12 @@ static inline void SMC_insl(struct smc911x_local *lp, int reg,
void __iomem *ioaddr = lp->base + reg;
if (lp->cfg.flags & SMC911X_USE_32BIT) {
- readsl(ioaddr, addr, count);
+ ioread32_rep(ioaddr, addr, count);
return;
}
if (lp->cfg.flags & SMC911X_USE_16BIT) {
- readsw(ioaddr, addr, count * 2);
+ ioread16_rep(ioaddr, addr, count * 2);
return;
}
@@ -177,12 +177,12 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
void __iomem *ioaddr = lp->base + reg;
if (lp->cfg.flags & SMC911X_USE_32BIT) {
- writesl(ioaddr, addr, count);
+ iowrite32_rep(ioaddr, addr, count);
return;
}
if (lp->cfg.flags & SMC911X_USE_16BIT) {
- writesw(ioaddr, addr, count * 2);
+ iowrite16_rep(ioaddr, addr, count * 2);
return;
}
@@ -196,14 +196,14 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
writew(v & 0xFFFF, (lp)->base + (r)); \
writew(v >> 16, (lp)->base + (r) + 2); \
} while (0)
-#define SMC_insl(lp, r, p, l) readsw((short*)((lp)->base + (r)), p, l*2)
-#define SMC_outsl(lp, r, p, l) writesw((short*)((lp)->base + (r)), p, l*2)
+#define SMC_insl(lp, r, p, l) ioread16_rep((short*)((lp)->base + (r)), p, l*2)
+#define SMC_outsl(lp, r, p, l) iowrite16_rep((short*)((lp)->base + (r)), p, l*2)
#elif SMC_USE_32BIT
#define SMC_inl(lp, r) readl((lp)->base + (r))
#define SMC_outl(v, lp, r) writel(v, (lp)->base + (r))
-#define SMC_insl(lp, r, p, l) readsl((int*)((lp)->base + (r)), p, l)
-#define SMC_outsl(lp, r, p, l) writesl((int*)((lp)->base + (r)), p, l)
+#define SMC_insl(lp, r, p, l) ioread32_rep((int*)((lp)->base + (r)), p, l)
+#define SMC_outsl(lp, r, p, l) iowrite32_rep((int*)((lp)->base + (r)), p, l)
#endif /* SMC_USE_16BIT */
#endif /* SMC_DYNAMIC_BUS_CONFIG */
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 318adc935a53..022b45bc14ff 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -1474,16 +1474,6 @@ smc_open(struct net_device *dev)
DBG(2, "%s: %s\n", dev->name, __func__);
- /*
- * Check that the address is valid. If its not, refuse
- * to bring the device up. The user must specify an
- * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
- */
- if (!is_valid_ether_addr(dev->dev_addr)) {
- PRINTK("%s: no valid ethernet hw addr\n", __func__);
- return -EINVAL;
- }
-
/* Setup the default Register Modes */
lp->tcr_cur_mode = TCR_DEFAULT;
lp->rcr_cur_mode = RCR_DEFAULT;
@@ -1789,7 +1779,7 @@ static const struct net_device_ops smc_netdev_ops = {
* I just deleted auto_irq.c, since it was never built...
* --jgarzik
*/
-static int __devinit smc_findirq(struct smc_local *lp)
+static int smc_findirq(struct smc_local *lp)
{
void __iomem *ioaddr = lp->base;
int timeout = 20;
@@ -1863,8 +1853,8 @@ static int __devinit smc_findirq(struct smc_local *lp)
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
- unsigned long irq_flags)
+static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ unsigned long irq_flags)
{
struct smc_local *lp = netdev_priv(dev);
static int version_printed = 0;
@@ -2211,7 +2201,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
* 0 --> there is a device
* anything else, error
*/
-static int __devinit smc_drv_probe(struct platform_device *pdev)
+static int smc_drv_probe(struct platform_device *pdev)
{
struct smc91x_platdata *pd = pdev->dev.platform_data;
struct smc_local *lp;
@@ -2324,7 +2314,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit smc_drv_remove(struct platform_device *pdev)
+static int smc_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc_local *lp = netdev_priv(ndev);
@@ -2407,7 +2397,7 @@ static struct dev_pm_ops smc_drv_pm_ops = {
static struct platform_driver smc_driver = {
.probe = smc_drv_probe,
- .remove = __devexit_p(smc_drv_remove),
+ .remove = smc_drv_remove,
.driver = {
.name = CARDNAME,
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 5f53fbbf67be..370e13dde115 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -286,16 +286,16 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
#define SMC_IO_SHIFT (lp->io_shift)
-#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_insw(a, r, p, l) readsw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
-#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_inb(a, r) ioread8((a) + (r))
+#define SMC_inw(a, r) ioread16((a) + (r))
+#define SMC_inl(a, r) ioread32((a) + (r))
+#define SMC_outb(v, a, r) iowrite8(v, (a) + (r))
+#define SMC_outw(v, a, r) iowrite16(v, (a) + (r))
+#define SMC_outl(v, a, r) iowrite32(v, (a) + (r))
+#define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l)
+#define SMC_insl(a, r, p, l) ioread32_rep((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) iowrite32_rep((a) + (r), p, l)
#define RPC_LSA_DEFAULT RPC_LED_100_10
#define RPC_LSB_DEFAULT RPC_LED_TX_RX
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index c53c0f4e2ce3..4616bf27d515 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -253,7 +253,7 @@ smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
}
if (pdata->config.flags & SMSC911X_USE_32BIT) {
- writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
+ iowrite32_rep(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
goto out;
}
@@ -285,7 +285,7 @@ smsc911x_tx_writefifo_shift(struct smsc911x_data *pdata, unsigned int *buf,
}
if (pdata->config.flags & SMSC911X_USE_32BIT) {
- writesl(pdata->ioaddr + __smsc_shift(pdata,
+ iowrite32_rep(pdata->ioaddr + __smsc_shift(pdata,
TX_DATA_FIFO), buf, wordcount);
goto out;
}
@@ -319,7 +319,7 @@ smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
}
if (pdata->config.flags & SMSC911X_USE_32BIT) {
- readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
+ ioread32_rep(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
goto out;
}
@@ -351,7 +351,7 @@ smsc911x_rx_readfifo_shift(struct smsc911x_data *pdata, unsigned int *buf,
}
if (pdata->config.flags & SMSC911X_USE_32BIT) {
- readsl(pdata->ioaddr + __smsc_shift(pdata,
+ ioread32_rep(pdata->ioaddr + __smsc_shift(pdata,
RX_DATA_FIFO), buf, wordcount);
goto out;
}
@@ -1031,8 +1031,8 @@ static int smsc911x_mii_probe(struct net_device *dev)
return 0;
}
-static int __devinit smsc911x_mii_init(struct platform_device *pdev,
- struct net_device *dev)
+static int smsc911x_mii_init(struct platform_device *pdev,
+ struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
int err = -ENXIO, i;
@@ -1463,11 +1463,6 @@ static int smsc911x_open(struct net_device *dev)
return -EAGAIN;
}
- if (!is_valid_ether_addr(dev->dev_addr)) {
- SMSC_WARN(pdata, hw, "dev_addr is not a valid MAC address");
- return -EADDRNOTAVAIL;
- }
-
/* Reset the LAN911x */
if (smsc911x_soft_reset(pdata)) {
SMSC_WARN(pdata, hw, "soft reset failed");
@@ -2092,7 +2087,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
};
/* copies the current mac address from hardware to dev->dev_addr */
-static void __devinit smsc911x_read_mac_address(struct net_device *dev)
+static void smsc911x_read_mac_address(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
@@ -2107,7 +2102,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
}
/* Initializing private device structures, only called from probe */
-static int __devinit smsc911x_init(struct net_device *dev)
+static int smsc911x_init(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
unsigned int byte_test, mask;
@@ -2244,7 +2239,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
return 0;
}
-static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
+static int smsc911x_drv_remove(struct platform_device *pdev)
{
struct net_device *dev;
struct smsc911x_data *pdata;
@@ -2301,9 +2296,8 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
};
#ifdef CONFIG_OF
-static int __devinit smsc911x_probe_config_dt(
- struct smsc911x_platform_config *config,
- struct device_node *np)
+static int smsc911x_probe_config_dt(struct smsc911x_platform_config *config,
+ struct device_node *np)
{
const char *mac;
u32 width = 0;
@@ -2351,7 +2345,7 @@ static inline int smsc911x_probe_config_dt(
}
#endif /* CONFIG_OF */
-static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+static int smsc911x_drv_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct net_device *dev;
@@ -2589,7 +2583,7 @@ MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
- .remove = __devexit_p(smsc911x_drv_remove),
+ .remove = smsc911x_drv_remove,
.driver = {
.name = SMSC_CHIPNAME,
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index 1fcd914ec39b..3c586585e1b3 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -1577,7 +1577,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
#endif /* CONFIG_NET_POLL_CONTROLLER */
};
-static int __devinit
+static int
smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *dev;
@@ -1702,7 +1702,7 @@ out_0:
return -ENODEV;
}
-static void __devexit smsc9420_remove(struct pci_dev *pdev)
+static void smsc9420_remove(struct pci_dev *pdev)
{
struct net_device *dev;
struct smsc9420_pdata *pd;
@@ -1736,7 +1736,7 @@ static struct pci_driver smsc9420_driver = {
.name = DRV_NAME,
.id_table = smsc9420_id_table,
.probe = smsc9420_probe,
- .remove = __devexit_p(smsc9420_remove),
+ .remove = smsc9420_remove,
#ifdef CONFIG_PM
.suspend = smsc9420_suspend,
.resume = smsc9420_resume,
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 9f448279e12a..1164930a40a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -54,31 +54,6 @@ config STMMAC_DA
By default, the DMA arbitration scheme is based on Round-robin
(rx:tx priority is 1:1).
-config STMMAC_TIMER
- bool "STMMAC Timer optimisation"
- default n
- depends on RTC_HCTOSYS_DEVICE
- ---help---
- Use an external timer for mitigating the number of network
- interrupts. Currently, for SH architectures, it is possible
- to use the TMU channel 2 and the SH-RTC device.
-
-choice
- prompt "Select Timer device"
- depends on STMMAC_TIMER
-
-config STMMAC_TMU_TIMER
- bool "TMU channel 2"
- depends on CPU_SH4
- ---help---
-
-config STMMAC_RTC_TIMER
- bool "Real time clock"
- depends on RTC_CLASS
- ---help---
-
-endchoice
-
choice
prompt "Select the DMA TX/RX descriptor operating modes"
depends on STMMAC_ETH
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index bc965ac9e025..c8e8ea60ac19 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,5 +1,4 @@
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
-stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 719be3912aa9..186d14806122 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -48,6 +48,10 @@
#define CHIP_DBG(fmt, args...) do { } while (0)
#endif
+/* Synopsys Core versions */
+#define DWMAC_CORE_3_40 0x34
+#define DWMAC_CORE_3_50 0x35
+
#undef FRAME_FILTER_DEBUG
/* #define FRAME_FILTER_DEBUG */
@@ -81,7 +85,7 @@ struct stmmac_extra_stats {
unsigned long rx_missed_cntr;
unsigned long rx_overflow_cntr;
unsigned long rx_vlan;
- /* Tx/Rx IRQ errors */
+ /* Tx/Rx IRQ error info */
unsigned long tx_undeflow_irq;
unsigned long tx_process_stopped_irq;
unsigned long tx_jabber_irq;
@@ -91,18 +95,23 @@ struct stmmac_extra_stats {
unsigned long rx_watchdog_irq;
unsigned long tx_early_irq;
unsigned long fatal_bus_error_irq;
- /* Extra info */
+ /* Tx/Rx IRQ Events */
+ unsigned long rx_early_irq;
unsigned long threshold;
unsigned long tx_pkt_n;
unsigned long rx_pkt_n;
- unsigned long poll_n;
- unsigned long sched_timer_n;
unsigned long normal_irq_n;
+ unsigned long rx_normal_irq_n;
+ unsigned long napi_poll;
+ unsigned long tx_normal_irq_n;
+ unsigned long tx_clean;
+ unsigned long tx_reset_ic_bit;
+ unsigned long irq_receive_pmt_irq_n;
+ /* MMC info */
unsigned long mmc_tx_irq_n;
unsigned long mmc_rx_irq_n;
unsigned long mmc_rx_csum_offload_irq_n;
/* EEE */
- unsigned long irq_receive_pmt_irq_n;
unsigned long irq_tx_path_in_lpi_mode_n;
unsigned long irq_tx_path_exit_lpi_mode_n;
unsigned long irq_rx_path_in_lpi_mode_n;
@@ -162,6 +171,15 @@ struct stmmac_extra_stats {
#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */
#define DEFAULT_DMA_PBL 8
+/* Max/Min RI Watchdog Timer count value */
+#define MAX_DMA_RIWT 0xff
+#define MIN_DMA_RIWT 0x20
+/* Tx coalesce parameters */
+#define STMMAC_COAL_TX_TIMER 40000
+#define STMMAC_MAX_COAL_TX_TICK 100000
+#define STMMAC_TX_MAX_FRAMES 256
+#define STMMAC_TX_FRAMES 64
+
enum rx_frame_status { /* IPC status */
good_frame = 0,
discard_frame = 1,
@@ -169,10 +187,11 @@ enum rx_frame_status { /* IPC status */
llc_snap = 4,
};
-enum tx_dma_irq_status {
- tx_hard_error = 1,
- tx_hard_error_bump_tc = 2,
- handle_tx_rx = 3,
+enum dma_irq_status {
+ tx_hard_error = 0x1,
+ tx_hard_error_bump_tc = 0x2,
+ handle_rx = 0x4,
+ handle_tx = 0x8,
};
enum core_specific_irq_mask {
@@ -296,6 +315,8 @@ struct stmmac_dma_ops {
struct stmmac_extra_stats *x);
/* If supported then get the optional core features */
unsigned int (*get_hw_feature) (void __iomem *ioaddr);
+ /* Program the HW RX Watchdog */
+ void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
};
struct stmmac_ops {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 0e4cacedc1f0..7ad56afd6324 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -230,8 +230,5 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
-/* Synopsys Core versions */
-#define DWMAC_CORE_3_40 0x34
-
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 033500090f55..bf83c03bfd06 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -174,6 +174,11 @@ static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
return readl(ioaddr + DMA_HW_FEATURE);
}
+static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
+{
+ writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+}
+
const struct stmmac_dma_ops dwmac1000_dma_ops = {
.init = dwmac1000_dma_init,
.dump_regs = dwmac1000_dump_dma_regs,
@@ -187,4 +192,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
.stop_rx = dwmac_dma_stop_rx,
.dma_interrupt = dwmac_dma_interrupt,
.get_hw_feature = dwmac1000_get_hw_feature,
+ .rx_watchdog = dwmac1000_rx_watchdog,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index e49c9a0fd6ff..ab4896ecac1c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -35,7 +35,10 @@
#define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */
#define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */
#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
-#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */
+/* Rx watchdog register */
+#define DMA_RX_WATCHDOG 0x00001024
+/* AXI Bus Mode */
+#define DMA_AXI_BUS_MODE 0x00001028
#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */
#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */
#define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */
@@ -77,8 +80,6 @@
#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
-#define DMA_STATUS_GMI 0x08000000
-#define DMA_STATUS_GLI 0x04000000
#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 4e0e18a44fcc..491d7e930603 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -204,16 +204,28 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
}
}
/* TX/RX NORMAL interrupts */
- if (intr_status & DMA_STATUS_NIS) {
+ if (likely(intr_status & DMA_STATUS_NIS)) {
x->normal_irq_n++;
- if (likely((intr_status & DMA_STATUS_RI) ||
- (intr_status & (DMA_STATUS_TI))))
- ret = handle_tx_rx;
+ if (likely(intr_status & DMA_STATUS_RI)) {
+ u32 value = readl(ioaddr + DMA_INTR_ENA);
+ /* to schedule NAPI on real RIE event. */
+ if (likely(value & DMA_INTR_ENA_RIE)) {
+ x->rx_normal_irq_n++;
+ ret |= handle_rx;
+ }
+ }
+ if (likely(intr_status & DMA_STATUS_TI)) {
+ x->tx_normal_irq_n++;
+ ret |= handle_tx;
+ }
+ if (unlikely(intr_status & DMA_STATUS_ERI))
+ x->rx_early_irq++;
}
/* Optional hardware blocks, interrupts should be disabled */
if (unlikely(intr_status &
(DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 7d51a65ab099..023a4fb4efa5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -24,16 +24,13 @@
#define __STMMAC_H__
#define STMMAC_RESOURCE_NAME "stmmaceth"
-#define DRV_MODULE_VERSION "March_2012"
+#define DRV_MODULE_VERSION "Nov_2012"
#include <linux/clk.h>
#include <linux/stmmac.h>
#include <linux/phy.h>
#include <linux/pci.h>
#include "common.h"
-#ifdef CONFIG_STMMAC_TIMER
-#include "stmmac_timer.h"
-#endif
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
@@ -77,9 +74,6 @@ struct stmmac_priv {
spinlock_t tx_lock;
int wolopts;
int wol_irq;
-#ifdef CONFIG_STMMAC_TIMER
- struct stmmac_timer *tm;
-#endif
struct plat_stmmacenet_data *plat;
struct stmmac_counters mmc;
struct dma_features dma_cap;
@@ -93,6 +87,12 @@ struct stmmac_priv {
int eee_enabled;
int eee_active;
int tx_lpi_timer;
+ struct timer_list txtimer;
+ u32 tx_count_frames;
+ u32 tx_coal_frames;
+ u32 tx_coal_timer;
+ int use_riwt;
+ u32 rx_riwt;
};
extern int phyaddr;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 76fd61aa005f..1372ce210b58 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -76,7 +76,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(rx_missed_cntr),
STMMAC_STAT(rx_overflow_cntr),
STMMAC_STAT(rx_vlan),
- /* Tx/Rx IRQ errors */
+ /* Tx/Rx IRQ error info */
STMMAC_STAT(tx_undeflow_irq),
STMMAC_STAT(tx_process_stopped_irq),
STMMAC_STAT(tx_jabber_irq),
@@ -86,18 +86,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(rx_watchdog_irq),
STMMAC_STAT(tx_early_irq),
STMMAC_STAT(fatal_bus_error_irq),
- /* Extra info */
+ /* Tx/Rx IRQ Events */
+ STMMAC_STAT(rx_early_irq),
STMMAC_STAT(threshold),
STMMAC_STAT(tx_pkt_n),
STMMAC_STAT(rx_pkt_n),
- STMMAC_STAT(poll_n),
- STMMAC_STAT(sched_timer_n),
- STMMAC_STAT(normal_irq_n),
STMMAC_STAT(normal_irq_n),
+ STMMAC_STAT(rx_normal_irq_n),
+ STMMAC_STAT(napi_poll),
+ STMMAC_STAT(tx_normal_irq_n),
+ STMMAC_STAT(tx_clean),
+ STMMAC_STAT(tx_reset_ic_bit),
+ STMMAC_STAT(irq_receive_pmt_irq_n),
+ /* MMC info */
STMMAC_STAT(mmc_tx_irq_n),
STMMAC_STAT(mmc_rx_irq_n),
STMMAC_STAT(mmc_rx_csum_offload_irq_n),
- STMMAC_STAT(irq_receive_pmt_irq_n),
+ /* EEE */
STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
@@ -519,6 +524,87 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
return phy_ethtool_set_eee(priv->phydev, edata);
}
+static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
+{
+ unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+ if (!clk)
+ return 0;
+
+ return (usec * (clk / 1000000)) / 256;
+}
+
+static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
+{
+ unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+ if (!clk)
+ return 0;
+
+ return (riwt * 256) / (clk / 1000000);
+}
+
+static int stmmac_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ ec->tx_coalesce_usecs = priv->tx_coal_timer;
+ ec->tx_max_coalesced_frames = priv->tx_coal_frames;
+
+ if (priv->use_riwt)
+ ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv);
+
+ return 0;
+}
+
+static int stmmac_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ec)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ unsigned int rx_riwt;
+
+ /* Check not supported parameters */
+ if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) ||
+ (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
+ (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
+ (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) ||
+ (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) ||
+ (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) ||
+ (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) ||
+ (ec->rx_max_coalesced_frames_high) ||
+ (ec->tx_max_coalesced_frames_irq) ||
+ (ec->stats_block_coalesce_usecs) ||
+ (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval))
+ return -EOPNOTSUPP;
+
+ if (ec->rx_coalesce_usecs == 0)
+ return -EINVAL;
+
+ if ((ec->tx_coalesce_usecs == 0) &&
+ (ec->tx_max_coalesced_frames == 0))
+ return -EINVAL;
+
+ if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) ||
+ (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
+ return -EINVAL;
+
+ rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv);
+
+ if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT))
+ return -EINVAL;
+ else if (!priv->use_riwt)
+ return -EOPNOTSUPP;
+
+ /* Only copy relevant parameters, ignore all others. */
+ priv->tx_coal_frames = ec->tx_max_coalesced_frames;
+ priv->tx_coal_timer = ec->tx_coalesce_usecs;
+ priv->rx_riwt = rx_riwt;
+ priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt);
+
+ return 0;
+}
+
static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -539,6 +625,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.set_eee = stmmac_ethtool_op_set_eee,
.get_sset_count = stmmac_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_coalesce = stmmac_get_coalesce,
+ .set_coalesce = stmmac_set_coalesce,
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c6cdbc4eb05e..542edbcd92c7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -115,16 +115,6 @@ static int tc = TC_DEFAULT;
module_param(tc, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(tc, "DMA threshold control value");
-/* Pay attention to tune this parameter; take care of both
- * hardware capability and network stabitily/performance impact.
- * Many tests showed that ~4ms latency seems to be good enough. */
-#ifdef CONFIG_STMMAC_TIMER
-#define DEFAULT_PERIODIC_RATE 256
-static int tmrate = DEFAULT_PERIODIC_RATE;
-module_param(tmrate, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)");
-#endif
-
#define DMA_BUFFER_SIZE BUF_SIZE_2KiB
static int buf_sz = DMA_BUFFER_SIZE;
module_param(buf_sz, int, S_IRUGO | S_IWUSR);
@@ -147,6 +137,8 @@ static int stmmac_init_fs(struct net_device *dev);
static void stmmac_exit_fs(void);
#endif
+#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+
/**
* stmmac_verify_args - verify the driver parameters.
* Description: it verifies if some wrong parameter is passed to the driver.
@@ -536,12 +528,6 @@ static void init_dma_desc_rings(struct net_device *dev)
else
bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
-#ifdef CONFIG_STMMAC_TIMER
- /* Disable interrupts on completion for the reception if timer is on */
- if (likely(priv->tm->enable))
- dis_ic = 1;
-#endif
-
DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
txsize, rxsize, bfsize);
@@ -617,6 +603,8 @@ static void init_dma_desc_rings(struct net_device *dev)
priv->dirty_tx = 0;
priv->cur_tx = 0;
+ if (priv->use_riwt)
+ dis_ic = 1;
/* Clear the Rx/Tx descriptors */
priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
priv->hw->desc->init_tx_desc(priv->dma_tx, txsize);
@@ -704,16 +692,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
}
/**
- * stmmac_tx:
- * @priv: private driver structure
+ * stmmac_tx_clean:
+ * @priv: private data pointer
* Description: it reclaims resources after transmission completes.
*/
-static void stmmac_tx(struct stmmac_priv *priv)
+static void stmmac_tx_clean(struct stmmac_priv *priv)
{
unsigned int txsize = priv->dma_tx_size;
spin_lock(&priv->tx_lock);
+ priv->xstats.tx_clean++;
+
while (priv->dirty_tx != priv->cur_tx) {
int last;
unsigned int entry = priv->dirty_tx % txsize;
@@ -773,69 +763,16 @@ static void stmmac_tx(struct stmmac_priv *priv)
spin_unlock(&priv->tx_lock);
}
-static inline void stmmac_enable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
- if (likely(priv->tm->enable))
- priv->tm->timer_start(tmrate);
- else
-#endif
- priv->hw->dma->enable_dma_irq(priv->ioaddr);
-}
-
-static inline void stmmac_disable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
- if (likely(priv->tm->enable))
- priv->tm->timer_stop();
- else
-#endif
- priv->hw->dma->disable_dma_irq(priv->ioaddr);
-}
-
-static int stmmac_has_work(struct stmmac_priv *priv)
-{
- unsigned int has_work = 0;
- int rxret, tx_work = 0;
-
- rxret = priv->hw->desc->get_rx_owner(priv->dma_rx +
- (priv->cur_rx % priv->dma_rx_size));
-
- if (priv->dirty_tx != priv->cur_tx)
- tx_work = 1;
-
- if (likely(!rxret || tx_work))
- has_work = 1;
-
- return has_work;
-}
-
-static inline void _stmmac_schedule(struct stmmac_priv *priv)
+static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
{
- if (likely(stmmac_has_work(priv))) {
- stmmac_disable_irq(priv);
- napi_schedule(&priv->napi);
- }
+ priv->hw->dma->enable_dma_irq(priv->ioaddr);
}
-#ifdef CONFIG_STMMAC_TIMER
-void stmmac_schedule(struct net_device *dev)
+static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
{
- struct stmmac_priv *priv = netdev_priv(dev);
-
- priv->xstats.sched_timer_n++;
-
- _stmmac_schedule(priv);
+ priv->hw->dma->disable_dma_irq(priv->ioaddr);
}
-static void stmmac_no_timer_started(unsigned int x)
-{;
-};
-
-static void stmmac_no_timer_stopped(void)
-{;
-};
-#endif
/**
* stmmac_tx_err:
@@ -858,16 +795,18 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
netif_wake_queue(priv->dev);
}
-
static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
int status;
status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
- if (likely(status == handle_tx_rx))
- _stmmac_schedule(priv);
-
- else if (unlikely(status == tx_hard_error_bump_tc)) {
+ if (likely((status & handle_rx)) || (status & handle_tx)) {
+ if (likely(napi_schedule_prep(&priv->napi))) {
+ stmmac_disable_dma_irq(priv);
+ __napi_schedule(&priv->napi);
+ }
+ }
+ if (unlikely(status & tx_hard_error_bump_tc)) {
/* Try to bump up the dma threshold on this failure */
if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
tc += 64;
@@ -983,7 +922,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
/* Alternate (enhanced) DESC mode*/
priv->dma_cap.enh_desc =
(hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
-
}
return hw_cap;
@@ -1025,6 +963,38 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
}
/**
+ * stmmac_tx_timer:
+ * @data: data pointer
+ * Description:
+ * This is the timer handler to directly invoke the stmmac_tx_clean.
+ */
+static void stmmac_tx_timer(unsigned long data)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *)data;
+
+ stmmac_tx_clean(priv);
+}
+
+/**
+ * stmmac_tx_timer:
+ * @priv: private data structure
+ * Description:
+ * This inits the transmit coalesce parameters: i.e. timer rate,
+ * timer handler and default threshold used for enabling the
+ * interrupt on completion bit.
+ */
+static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+{
+ priv->tx_coal_frames = STMMAC_TX_FRAMES;
+ priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
+ init_timer(&priv->txtimer);
+ priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
+ priv->txtimer.data = (unsigned long)priv;
+ priv->txtimer.function = stmmac_tx_timer;
+ add_timer(&priv->txtimer);
+}
+
+/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
* Description:
@@ -1038,23 +1008,6 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
-#ifdef CONFIG_STMMAC_TIMER
- priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
- if (unlikely(priv->tm == NULL))
- return -ENOMEM;
-
- priv->tm->freq = tmrate;
-
- /* Test if the external timer can be actually used.
- * In case of failure continue without timer. */
- if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
- pr_warning("stmmaceth: cannot attach the external timer.\n");
- priv->tm->freq = 0;
- priv->tm->timer_start = stmmac_no_timer_started;
- priv->tm->timer_stop = stmmac_no_timer_stopped;
- } else
- priv->tm->enable = 1;
-#endif
clk_prepare_enable(priv->stmmac_clk);
stmmac_check_ether_addr(priv);
@@ -1141,10 +1094,6 @@ static int stmmac_open(struct net_device *dev)
priv->hw->dma->start_tx(priv->ioaddr);
priv->hw->dma->start_rx(priv->ioaddr);
-#ifdef CONFIG_STMMAC_TIMER
- priv->tm->timer_start(tmrate);
-#endif
-
/* Dump DMA/MAC registers */
if (netif_msg_hw(priv)) {
priv->hw->mac->dump_regs(priv->ioaddr);
@@ -1157,6 +1106,13 @@ static int stmmac_open(struct net_device *dev)
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
priv->eee_enabled = stmmac_eee_init(priv);
+ stmmac_init_tx_coalesce(priv);
+
+ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+ priv->rx_riwt = MAX_DMA_RIWT;
+ priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
+ }
+
napi_enable(&priv->napi);
netif_start_queue(dev);
@@ -1170,9 +1126,6 @@ open_error_wolirq:
free_irq(dev->irq, dev);
open_error:
-#ifdef CONFIG_STMMAC_TIMER
- kfree(priv->tm);
-#endif
if (priv->phydev)
phy_disconnect(priv->phydev);
@@ -1203,14 +1156,10 @@ static int stmmac_release(struct net_device *dev)
netif_stop_queue(dev);
-#ifdef CONFIG_STMMAC_TIMER
- /* Stop and release the timer */
- stmmac_close_ext_timer();
- if (priv->tm != NULL)
- kfree(priv->tm);
-#endif
napi_disable(&priv->napi);
+ del_timer_sync(&priv->txtimer);
+
/* Free the IRQ lines */
free_irq(dev->irq, dev);
if (priv->wol_irq != dev->irq)
@@ -1273,11 +1222,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef STMMAC_XMIT_DEBUG
if ((skb->len > ETH_FRAME_LEN) || nfrags)
- pr_info("stmmac xmit:\n"
- "\tskb addr %p - len: %d - nopaged_len: %d\n"
- "\tn_frags: %d - ip_summed: %d - %s gso\n",
- skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
- !skb_is_gso(skb) ? "isn't" : "is");
+ pr_debug("stmmac xmit: [entry %d]\n"
+ "\tskb addr %p - len: %d - nopaged_len: %d\n"
+ "\tn_frags: %d - ip_summed: %d - %s gso\n"
+ "\ttx_count_frames %d\n", entry,
+ skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
+ !skb_is_gso(skb) ? "isn't" : "is",
+ priv->tx_count_frames);
#endif
csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
@@ -1287,9 +1238,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef STMMAC_XMIT_DEBUG
if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
- pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
- "\t\tn_frags: %d, ip_summed: %d\n",
- skb->len, nopaged_len, nfrags, skb->ip_summed);
+ pr_debug("\tskb len: %d, nopaged_len: %d,\n"
+ "\t\tn_frags: %d, ip_summed: %d\n",
+ skb->len, nopaged_len, nfrags, skb->ip_summed);
#endif
priv->tx_skbuff[entry] = skb;
@@ -1320,16 +1271,24 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
wmb();
}
- /* Interrupt on completition only for the latest segment */
+ /* Finalize the latest segment. */
priv->hw->desc->close_tx_desc(desc);
-#ifdef CONFIG_STMMAC_TIMER
- /* Clean IC while using timer */
- if (likely(priv->tm->enable))
- priv->hw->desc->clear_tx_ic(desc);
-#endif
-
wmb();
+ /* According to the coalesce parameter the IC bit for the latest
+ * segment could be reset and the timer re-started to invoke the
+ * stmmac_tx function. This approach takes care about the fragments.
+ */
+ priv->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames > priv->tx_count_frames) {
+ priv->hw->desc->clear_tx_ic(desc);
+ priv->xstats.tx_reset_ic_bit++;
+ TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry,
+ priv->tx_count_frames);
+ mod_timer(&priv->txtimer,
+ STMMAC_COAL_TIMER(priv->tx_coal_timer));
+ } else
+ priv->tx_count_frames = 0;
/* To avoid raise condition */
priv->hw->desc->set_tx_owner(first);
@@ -1471,14 +1430,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif
skb->protocol = eth_type_trans(skb, priv->dev);
- if (unlikely(!priv->plat->rx_coe)) {
- /* No RX COE for old mac10/100 devices */
+ if (unlikely(!priv->plat->rx_coe))
skb_checksum_none_assert(skb);
- netif_receive_skb(skb);
- } else {
+ else
skb->ip_summed = CHECKSUM_UNNECESSARY;
- napi_gro_receive(&priv->napi, skb);
- }
+
+ napi_gro_receive(&priv->napi, skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
@@ -1500,21 +1457,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
* @budget : maximum number of packets that the current CPU can receive from
* all interfaces.
* Description :
- * This function implements the the reception process.
- * Also it runs the TX completion thread
+ * To look at the incoming frames and clear the tx resources.
*/
static int stmmac_poll(struct napi_struct *napi, int budget)
{
struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
int work_done = 0;
- priv->xstats.poll_n++;
- stmmac_tx(priv);
- work_done = stmmac_rx(priv, budget);
+ priv->xstats.napi_poll++;
+ stmmac_tx_clean(priv);
+ work_done = stmmac_rx(priv, budget);
if (work_done < budget) {
napi_complete(napi);
- stmmac_enable_irq(priv);
+ stmmac_enable_dma_irq(priv);
}
return work_done;
}
@@ -1523,7 +1479,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
* stmmac_tx_timeout
* @dev : Pointer to net device structure
* Description: this function is called when a packet transmission fails to
- * complete within a reasonable tmrate. The driver will mark the error in the
+ * complete within a reasonable time. The driver will mark the error in the
* netdev structure and arrange for the device to be reset to a sane state
* in order to transmit a new packet.
*/
@@ -2050,6 +2006,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
+ /* Rx Watchdog is available in the COREs newer than the 3.40.
+ * In some case, for example on bugged HW this feature
+ * has to be disable and this can be done by passing the
+ * riwt_off field from the platform.
+ */
+ if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
+ priv->use_riwt = 1;
+ pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+ }
+
netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
spin_lock_init(&priv->lock);
@@ -2141,11 +2107,9 @@ int stmmac_suspend(struct net_device *ndev)
netif_device_detach(ndev);
netif_stop_queue(ndev);
-#ifdef CONFIG_STMMAC_TIMER
- priv->tm->timer_stop();
- if (likely(priv->tm->enable))
+ if (priv->use_riwt)
dis_ic = 1;
-#endif
+
napi_disable(&priv->napi);
/* Stop TX/RX DMA */
@@ -2196,10 +2160,6 @@ int stmmac_resume(struct net_device *ndev)
priv->hw->dma->start_tx(priv->ioaddr);
priv->hw->dma->start_rx(priv->ioaddr);
-#ifdef CONFIG_STMMAC_TIMER
- if (likely(priv->tm->enable))
- priv->tm->timer_start(tmrate);
-#endif
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -2295,11 +2255,6 @@ static int __init stmmac_cmdline_opt(char *str)
} else if (!strncmp(opt, "eee_timer:", 6)) {
if (kstrtoint(opt + 10, 0, &eee_timer))
goto err;
-#ifdef CONFIG_STMMAC_TIMER
- } else if (!strncmp(opt, "tmrate:", 7)) {
- if (kstrtoint(opt + 7, 0, &tmrate))
- goto err;
-#endif
}
}
return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 1f069b0f6af5..064eaac9616f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -61,8 +61,8 @@ static void stmmac_default_data(void)
* matches the device. The probe functions returns zero when the driver choose
* to take "ownership" of the device or an error code(-ve no) otherwise.
*/
-static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int stmmac_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
int ret = 0;
void __iomem *addr = NULL;
@@ -130,7 +130,7 @@ err_out_req_reg_failed:
* Description: this function calls the main to free the net resources
* and releases the PCI resources.
*/
-static void __devexit stmmac_pci_remove(struct pci_dev *pdev)
+static void stmmac_pci_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -182,7 +182,7 @@ struct pci_driver stmmac_pci_driver = {
.name = STMMAC_RESOURCE_NAME,
.id_table = stmmac_id_table,
.probe = stmmac_pci_probe,
- .remove = __devexit_p(stmmac_pci_remove),
+ .remove = stmmac_pci_remove,
#ifdef CONFIG_PM
.suspend = stmmac_pci_suspend,
.resume = stmmac_pci_resume,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index ed112b55ae7f..b43d68b40e50 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -29,9 +29,9 @@
#include "stmmac.h"
#ifdef CONFIG_OF
-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
- struct plat_stmmacenet_data *plat,
- const char **mac)
+static int stmmac_probe_config_dt(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ const char **mac)
{
struct device_node *np = pdev->dev.of_node;
@@ -59,9 +59,9 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
return 0;
}
#else
-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
- struct plat_stmmacenet_data *plat,
- const char **mac)
+static int stmmac_probe_config_dt(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ const char **mac)
{
return -ENOSYS;
}
@@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
* the necessary resources and invokes the main to init
* the net device, register the mdio bus etc.
*/
-static int __devinit stmmac_pltfr_probe(struct platform_device *pdev)
+static int stmmac_pltfr_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
deleted file mode 100644
index 4ccd4e2977b7..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*******************************************************************************
- STMMAC external timer support.
-
- Copyright (C) 2007-2009 STMicroelectronics Ltd
-
- 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, write to the Free Software Foundation, Inc.,
- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
- The full GNU General Public License is included in this distribution in
- the file called "COPYING".
-
- Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include "stmmac_timer.h"
-
-static void stmmac_timer_handler(void *data)
-{
- struct net_device *dev = (struct net_device *)data;
-
- stmmac_schedule(dev);
-}
-
-#define STMMAC_TIMER_MSG(timer, freq) \
-printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
-
-#if defined(CONFIG_STMMAC_RTC_TIMER)
-#include <linux/rtc.h>
-static struct rtc_device *stmmac_rtc;
-static rtc_task_t stmmac_task;
-
-static void stmmac_rtc_start(unsigned int new_freq)
-{
- rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq);
- rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1);
-}
-
-static void stmmac_rtc_stop(void)
-{
- rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
- stmmac_task.private_data = dev;
- stmmac_task.func = stmmac_timer_handler;
-
- stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
- if (stmmac_rtc == NULL) {
- pr_err("open rtc device failed\n");
- return -ENODEV;
- }
-
- rtc_irq_register(stmmac_rtc, &stmmac_task);
-
- /* Periodic mode is not supported */
- if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
- pr_err("set periodic failed\n");
- rtc_irq_unregister(stmmac_rtc, &stmmac_task);
- rtc_class_close(stmmac_rtc);
- return -1;
- }
-
- STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
-
- tm->timer_start = stmmac_rtc_start;
- tm->timer_stop = stmmac_rtc_stop;
-
- return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
- rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
- rtc_irq_unregister(stmmac_rtc, &stmmac_task);
- rtc_class_close(stmmac_rtc);
- return 0;
-}
-
-#elif defined(CONFIG_STMMAC_TMU_TIMER)
-#include <linux/clk.h>
-#define TMU_CHANNEL "tmu2_clk"
-static struct clk *timer_clock;
-
-static void stmmac_tmu_start(unsigned int new_freq)
-{
- clk_set_rate(timer_clock, new_freq);
- clk_prepare_enable(timer_clock);
-}
-
-static void stmmac_tmu_stop(void)
-{
- clk_disable_unprepare(timer_clock);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
- timer_clock = clk_get(NULL, TMU_CHANNEL);
-
- if (IS_ERR(timer_clock))
- return -1;
-
- if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
- timer_clock = NULL;
- return -1;
- }
-
- STMMAC_TIMER_MSG("TMU2", tm->freq);
- tm->timer_start = stmmac_tmu_start;
- tm->timer_stop = stmmac_tmu_stop;
-
- return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
- clk_disable_unprepare(timer_clock);
- tmu2_unregister_user();
- clk_put(timer_clock);
- return 0;
-}
-#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
deleted file mode 100644
index aea9b14cdfbe..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- STMMAC external timer Header File.
-
- Copyright (C) 2007-2009 STMicroelectronics Ltd
-
- 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, write to the Free Software Foundation, Inc.,
- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
- The full GNU General Public License is included in this distribution in
- the file called "COPYING".
-
- Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-#ifndef __STMMAC_TIMER_H__
-#define __STMMAC_TIMER_H__
-
-struct stmmac_timer {
- void (*timer_start) (unsigned int new_freq);
- void (*timer_stop) (void);
- unsigned int freq;
- unsigned int enable;
-};
-
-/* Open the HW timer device and return 0 in case of success */
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm);
-/* Stop the timer and release it */
-int stmmac_close_ext_timer(void);
-/* Function used for scheduling task within the stmmac */
-void stmmac_schedule(struct net_device *dev);
-
-#if defined(CONFIG_STMMAC_TMU_TIMER)
-extern int tmu2_register_user(void *fnt, void *data);
-extern void tmu2_unregister_user(void);
-#endif
-
-#endif /* __STMMAC_TIMER_H__ */
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index c8251be104d6..4c682a3d0424 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -185,7 +185,7 @@
#define CAS_RESET_SPARE 3
#endif
-static char version[] __devinitdata =
+static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
@@ -222,7 +222,7 @@ static int link_transition_timeout;
-static u16 link_modes[] __devinitdata = {
+static u16 link_modes[] = {
BMCR_ANENABLE, /* 0 : autoneg */
0, /* 1 : 10bt half duplex */
BMCR_SPEED100, /* 2 : 100bt half duplex */
@@ -4820,7 +4820,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
* only subordinate device and we can tweak the bridge settings to
* reflect that fact.
*/
-static void __devinit cas_program_bridge(struct pci_dev *cas_pdev)
+static void cas_program_bridge(struct pci_dev *cas_pdev)
{
struct pci_dev *pdev = cas_pdev->bus->self;
u32 val;
@@ -4916,8 +4916,7 @@ static const struct net_device_ops cas_netdev_ops = {
#endif
};
-static int __devinit cas_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int cas_version_printed = 0;
unsigned long casreg_len;
@@ -5175,7 +5174,7 @@ err_out_disable_pdev:
return -ENODEV;
}
-static void __devexit cas_remove_one(struct pci_dev *pdev)
+static void cas_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct cas *cp;
@@ -5273,7 +5272,7 @@ static struct pci_driver cas_driver = {
.name = DRV_MODULE_NAME,
.id_table = cas_pci_tbl,
.probe = cas_init_one,
- .remove = __devexit_p(cas_remove_one),
+ .remove = cas_remove_one,
#ifdef CONFIG_PM
.suspend = cas_suspend,
.resume = cas_resume
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 275b430aeb75..a0bdf0779466 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -38,7 +38,7 @@
#define DRV_MODULE_VERSION "1.1"
#define DRV_MODULE_RELDATE "Apr 22, 2010"
-static char version[] __devinitdata =
+static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@@ -7977,7 +7977,7 @@ static int niu_set_ldg_sid(struct niu *np, int ldg, int func, int vector)
return 0;
}
-static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
+static int niu_pci_eeprom_read(struct niu *np, u32 addr)
{
u64 frame, frame_base = (ESPC_PIO_STAT_READ_START |
(addr << ESPC_PIO_STAT_ADDR_SHIFT));
@@ -8020,7 +8020,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
return (frame & ESPC_PIO_STAT_DATA) >> ESPC_PIO_STAT_DATA_SHIFT;
}
-static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
+static int niu_pci_eeprom_read16(struct niu *np, u32 off)
{
int err = niu_pci_eeprom_read(np, off);
u16 val;
@@ -8036,7 +8036,7 @@ static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
return val;
}
-static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
+static int niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
{
int err = niu_pci_eeprom_read(np, off);
u16 val;
@@ -8054,10 +8054,8 @@ static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
return val;
}
-static int __devinit niu_pci_vpd_get_propname(struct niu *np,
- u32 off,
- char *namebuf,
- int namebuf_len)
+static int niu_pci_vpd_get_propname(struct niu *np, u32 off, char *namebuf,
+ int namebuf_len)
{
int i;
@@ -8075,7 +8073,7 @@ static int __devinit niu_pci_vpd_get_propname(struct niu *np,
return i + 1;
}
-static void __devinit niu_vpd_parse_version(struct niu *np)
+static void niu_vpd_parse_version(struct niu *np)
{
struct niu_vpd *vpd = &np->vpd;
int len = strlen(vpd->version) + 1;
@@ -8102,8 +8100,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np)
}
/* ESPC_PIO_EN_ENABLE must be set */
-static int __devinit niu_pci_vpd_scan_props(struct niu *np,
- u32 start, u32 end)
+static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
{
unsigned int found_mask = 0;
#define FOUND_MASK_MODEL 0x00000001
@@ -8189,7 +8186,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np,
}
/* ESPC_PIO_EN_ENABLE must be set */
-static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
+static void niu_pci_vpd_fetch(struct niu *np, u32 start)
{
u32 offset;
int err;
@@ -8224,7 +8221,7 @@ static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
}
/* ESPC_PIO_EN_ENABLE must be set */
-static u32 __devinit niu_pci_vpd_offset(struct niu *np)
+static u32 niu_pci_vpd_offset(struct niu *np)
{
u32 start = 0, end = ESPC_EEPROM_SIZE, ret;
int err;
@@ -8279,8 +8276,7 @@ static u32 __devinit niu_pci_vpd_offset(struct niu *np)
return 0;
}
-static int __devinit niu_phy_type_prop_decode(struct niu *np,
- const char *phy_prop)
+static int niu_phy_type_prop_decode(struct niu *np, const char *phy_prop)
{
if (!strcmp(phy_prop, "mif")) {
/* 1G copper, MII */
@@ -8334,7 +8330,7 @@ static int niu_pci_vpd_get_nports(struct niu *np)
return ports;
}
-static void __devinit niu_pci_vpd_validate(struct niu *np)
+static void niu_pci_vpd_validate(struct niu *np)
{
struct net_device *dev = np->dev;
struct niu_vpd *vpd = &np->vpd;
@@ -8380,7 +8376,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len);
}
-static int __devinit niu_pci_probe_sprom(struct niu *np)
+static int niu_pci_probe_sprom(struct niu *np)
{
struct net_device *dev = np->dev;
int len, i;
@@ -8538,7 +8534,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
return 0;
}
-static int __devinit niu_get_and_validate_port(struct niu *np)
+static int niu_get_and_validate_port(struct niu *np)
{
struct niu_parent *parent = np->parent;
@@ -8572,10 +8568,8 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
return 0;
}
-static int __devinit phy_record(struct niu_parent *parent,
- struct phy_probe_info *p,
- int dev_id_1, int dev_id_2, u8 phy_port,
- int type)
+static int phy_record(struct niu_parent *parent, struct phy_probe_info *p,
+ int dev_id_1, int dev_id_2, u8 phy_port, int type)
{
u32 id = (dev_id_1 << 16) | dev_id_2;
u8 idx;
@@ -8611,7 +8605,7 @@ static int __devinit phy_record(struct niu_parent *parent,
return 0;
}
-static int __devinit port_has_10g(struct phy_probe_info *p, int port)
+static int port_has_10g(struct phy_probe_info *p, int port)
{
int i;
@@ -8627,7 +8621,7 @@ static int __devinit port_has_10g(struct phy_probe_info *p, int port)
return 0;
}
-static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
+static int count_10g_ports(struct phy_probe_info *p, int *lowest)
{
int port, cnt;
@@ -8644,7 +8638,7 @@ static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
return cnt;
}
-static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
+static int count_1g_ports(struct phy_probe_info *p, int *lowest)
{
*lowest = 32;
if (p->cur[PHY_TYPE_MII])
@@ -8653,7 +8647,7 @@ static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
return p->cur[PHY_TYPE_MII];
}
-static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
+static void niu_n2_divide_channels(struct niu_parent *parent)
{
int num_ports = parent->num_ports;
int i;
@@ -8669,8 +8663,8 @@ static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
}
}
-static void __devinit niu_divide_channels(struct niu_parent *parent,
- int num_10g, int num_1g)
+static void niu_divide_channels(struct niu_parent *parent,
+ int num_10g, int num_1g)
{
int num_ports = parent->num_ports;
int rx_chans_per_10g, rx_chans_per_1g;
@@ -8731,8 +8725,8 @@ static void __devinit niu_divide_channels(struct niu_parent *parent,
}
}
-static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
- int num_10g, int num_1g)
+static void niu_divide_rdc_groups(struct niu_parent *parent,
+ int num_10g, int num_1g)
{
int i, num_ports = parent->num_ports;
int rdc_group, rdc_groups_per_port;
@@ -8776,9 +8770,8 @@ static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
}
}
-static int __devinit fill_phy_probe_info(struct niu *np,
- struct niu_parent *parent,
- struct phy_probe_info *info)
+static int fill_phy_probe_info(struct niu *np, struct niu_parent *parent,
+ struct phy_probe_info *info)
{
unsigned long flags;
int port, err;
@@ -8819,7 +8812,7 @@ static int __devinit fill_phy_probe_info(struct niu *np,
return err;
}
-static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
+static int walk_phys(struct niu *np, struct niu_parent *parent)
{
struct phy_probe_info *info = &parent->phy_probe_info;
int lowest_10g, lowest_1g;
@@ -8948,7 +8941,7 @@ unknown_vg_1g_port:
return -EINVAL;
}
-static int __devinit niu_probe_ports(struct niu *np)
+static int niu_probe_ports(struct niu *np)
{
struct niu_parent *parent = np->parent;
int err, i;
@@ -8969,7 +8962,7 @@ static int __devinit niu_probe_ports(struct niu *np)
return 0;
}
-static int __devinit niu_classifier_swstate_init(struct niu *np)
+static int niu_classifier_swstate_init(struct niu *np)
{
struct niu_classifier *cp = &np->clas;
@@ -8981,7 +8974,7 @@ static int __devinit niu_classifier_swstate_init(struct niu *np)
return fflp_early_init(np);
}
-static void __devinit niu_link_config_init(struct niu *np)
+static void niu_link_config_init(struct niu *np)
{
struct niu_link_config *lp = &np->link_config;
@@ -9006,7 +8999,7 @@ static void __devinit niu_link_config_init(struct niu *np)
#endif
}
-static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
+static int niu_init_mac_ipp_pcs_base(struct niu *np)
{
switch (np->port) {
case 0:
@@ -9045,7 +9038,7 @@ static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
return 0;
}
-static void __devinit niu_try_msix(struct niu *np, u8 *ldg_num_map)
+static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
{
struct msix_entry msi_vec[NIU_NUM_LDG];
struct niu_parent *parent = np->parent;
@@ -9084,7 +9077,7 @@ retry:
np->num_ldg = num_irqs;
}
-static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
+static int niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
{
#ifdef CONFIG_SPARC64
struct platform_device *op = np->op;
@@ -9108,7 +9101,7 @@ static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
#endif
}
-static int __devinit niu_ldg_init(struct niu *np)
+static int niu_ldg_init(struct niu *np)
{
struct niu_parent *parent = np->parent;
u8 ldg_num_map[NIU_NUM_LDG];
@@ -9225,13 +9218,13 @@ static int __devinit niu_ldg_init(struct niu *np)
return 0;
}
-static void __devexit niu_ldg_free(struct niu *np)
+static void niu_ldg_free(struct niu *np)
{
if (np->flags & NIU_FLAGS_MSIX)
pci_disable_msix(np->pdev);
}
-static int __devinit niu_get_of_props(struct niu *np)
+static int niu_get_of_props(struct niu *np)
{
#ifdef CONFIG_SPARC64
struct net_device *dev = np->dev;
@@ -9300,7 +9293,7 @@ static int __devinit niu_get_of_props(struct niu *np)
#endif
}
-static int __devinit niu_get_invariants(struct niu *np)
+static int niu_get_invariants(struct niu *np)
{
int err, have_props;
u32 offset;
@@ -9479,9 +9472,8 @@ static struct device_attribute niu_parent_attributes[] = {
{}
};
-static struct niu_parent * __devinit niu_new_parent(struct niu *np,
- union niu_parent_id *id,
- u8 ptype)
+static struct niu_parent *niu_new_parent(struct niu *np,
+ union niu_parent_id *id, u8 ptype)
{
struct platform_device *plat_dev;
struct niu_parent *p;
@@ -9544,9 +9536,8 @@ fail_unregister:
return NULL;
}
-static struct niu_parent * __devinit niu_get_parent(struct niu *np,
- union niu_parent_id *id,
- u8 ptype)
+static struct niu_parent *niu_get_parent(struct niu *np,
+ union niu_parent_id *id, u8 ptype)
{
struct niu_parent *p, *tmp;
int port = np->port;
@@ -9662,7 +9653,7 @@ static const struct niu_ops niu_pci_ops = {
.unmap_single = niu_pci_unmap_single,
};
-static void __devinit niu_driver_version(void)
+static void niu_driver_version(void)
{
static int niu_version_printed;
@@ -9670,10 +9661,10 @@ static void __devinit niu_driver_version(void)
pr_info("%s", version);
}
-static struct net_device * __devinit niu_alloc_and_init(
- struct device *gen_dev, struct pci_dev *pdev,
- struct platform_device *op, const struct niu_ops *ops,
- u8 port)
+static struct net_device *niu_alloc_and_init(struct device *gen_dev,
+ struct pci_dev *pdev,
+ struct platform_device *op,
+ const struct niu_ops *ops, u8 port)
{
struct net_device *dev;
struct niu *np;
@@ -9714,14 +9705,14 @@ static const struct net_device_ops niu_netdev_ops = {
.ndo_change_mtu = niu_change_mtu,
};
-static void __devinit niu_assign_netdev_ops(struct net_device *dev)
+static void niu_assign_netdev_ops(struct net_device *dev)
{
dev->netdev_ops = &niu_netdev_ops;
dev->ethtool_ops = &niu_ethtool_ops;
dev->watchdog_timeo = NIU_TX_TIMEOUT;
}
-static void __devinit niu_device_announce(struct niu *np)
+static void niu_device_announce(struct niu *np)
{
struct net_device *dev = np->dev;
@@ -9750,14 +9741,14 @@ static void __devinit niu_device_announce(struct niu *np)
}
}
-static void __devinit niu_set_basic_features(struct net_device *dev)
+static void niu_set_basic_features(struct net_device *dev)
{
dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH;
dev->features |= dev->hw_features | NETIF_F_RXCSUM;
}
-static int __devinit niu_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int niu_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
union niu_parent_id parent_id;
struct net_device *dev;
@@ -9895,7 +9886,7 @@ err_out_disable_pdev:
return err;
}
-static void __devexit niu_pci_remove_one(struct pci_dev *pdev)
+static void niu_pci_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -9980,7 +9971,7 @@ static struct pci_driver niu_pci_driver = {
.name = DRV_MODULE_NAME,
.id_table = niu_pci_tbl,
.probe = niu_pci_init_one,
- .remove = __devexit_p(niu_pci_remove_one),
+ .remove = niu_pci_remove_one,
.suspend = niu_suspend,
.resume = niu_resume,
};
@@ -10044,7 +10035,7 @@ static const struct niu_ops niu_phys_ops = {
.unmap_single = niu_phys_unmap_single,
};
-static int __devinit niu_of_probe(struct platform_device *op)
+static int niu_of_probe(struct platform_device *op)
{
union niu_parent_id parent_id;
struct net_device *dev;
@@ -10158,7 +10149,7 @@ err_out:
return err;
}
-static int __devexit niu_of_remove(struct platform_device *op)
+static int niu_of_remove(struct platform_device *op)
{
struct net_device *dev = dev_get_drvdata(&op->dev);
@@ -10211,7 +10202,7 @@ static struct platform_driver niu_of_driver = {
.of_match_table = niu_match,
},
.probe = niu_of_probe,
- .remove = __devexit_p(niu_of_remove),
+ .remove = niu_of_remove,
};
#endif /* CONFIG_SPARC64 */
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index c9c977bf02ac..be82f6d13c51 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -1074,8 +1074,8 @@ static const struct net_device_ops bigmac_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit bigmac_ether_init(struct platform_device *op,
- struct platform_device *qec_op)
+static int bigmac_ether_init(struct platform_device *op,
+ struct platform_device *qec_op)
{
static int version_printed;
struct net_device *dev;
@@ -1233,7 +1233,7 @@ fail_and_cleanup:
/* QEC can be the parent of either QuadEthernet or a BigMAC. We want
* the latter.
*/
-static int __devinit bigmac_sbus_probe(struct platform_device *op)
+static int bigmac_sbus_probe(struct platform_device *op)
{
struct device *parent = op->dev.parent;
struct platform_device *qec_op;
@@ -1243,7 +1243,7 @@ static int __devinit bigmac_sbus_probe(struct platform_device *op)
return bigmac_ether_init(op, qec_op);
}
-static int __devexit bigmac_sbus_remove(struct platform_device *op)
+static int bigmac_sbus_remove(struct platform_device *op)
{
struct bigmac *bp = dev_get_drvdata(&op->dev);
struct device *parent = op->dev.parent;
@@ -1286,7 +1286,7 @@ static struct platform_driver bigmac_sbus_driver = {
.of_match_table = bigmac_sbus_match,
},
.probe = bigmac_sbus_probe,
- .remove = __devexit_p(bigmac_sbus_remove),
+ .remove = bigmac_sbus_remove,
};
module_platform_driver(bigmac_sbus_driver);
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 6c8695ec7cb9..5f3f9d52757d 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -77,7 +77,7 @@
#define DRV_VERSION "1.0"
#define DRV_AUTHOR "David S. Miller <davem@redhat.com>"
-static char version[] __devinitdata =
+static char version[] =
DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
MODULE_AUTHOR(DRV_AUTHOR);
@@ -2763,7 +2763,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
}
#endif /* not Sparc and not PPC */
-static int __devinit gem_get_device_address(struct gem *gp)
+static int gem_get_device_address(struct gem *gp)
{
#if defined(CONFIG_SPARC) || defined(CONFIG_PPC_PMAC)
struct net_device *dev = gp->dev;
@@ -2827,8 +2827,7 @@ static const struct net_device_ops gem_netdev_ops = {
#endif
};
-static int __devinit gem_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned long gemreg_base, gemreg_len;
struct net_device *dev;
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 73f341b8befb..a1bff49a8155 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2499,7 +2499,7 @@ static int hme_version_printed;
*
* Return NULL on failure.
*/
-static struct quattro * __devinit quattro_sbus_find(struct platform_device *child)
+static struct quattro *quattro_sbus_find(struct platform_device *child)
{
struct device *parent = child->dev.parent;
struct platform_device *op;
@@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void)
#endif /* CONFIG_SBUS */
#ifdef CONFIG_PCI
-static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
+static struct quattro *quattro_pci_find(struct pci_dev *pdev)
{
struct pci_dev *bdev = pdev->bus->self;
struct quattro *qp;
@@ -2623,7 +2623,7 @@ static const struct net_device_ops hme_netdev_ops = {
};
#ifdef CONFIG_SBUS
-static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
+static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
{
struct device_node *dp = op->dev.of_node, *sbus_dp;
struct quattro *qp = NULL;
@@ -2927,8 +2927,8 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
}
#endif /* !(CONFIG_SPARC) */
-static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int happy_meal_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct quattro *qp = NULL;
#ifdef CONFIG_SPARC
@@ -3162,7 +3162,7 @@ err_out:
return err;
}
-static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
+static void happy_meal_pci_remove(struct pci_dev *pdev)
{
struct happy_meal *hp = dev_get_drvdata(&pdev->dev);
struct net_device *net_dev = hp->dev;
@@ -3190,7 +3190,7 @@ static struct pci_driver hme_pci_driver = {
.name = "hme",
.id_table = happymeal_pci_ids,
.probe = happy_meal_pci_probe,
- .remove = __devexit_p(happy_meal_pci_remove),
+ .remove = happy_meal_pci_remove,
};
static int __init happy_meal_pci_init(void)
@@ -3216,7 +3216,7 @@ static void happy_meal_pci_exit(void)
#ifdef CONFIG_SBUS
static const struct of_device_id hme_sbus_match[];
-static int __devinit hme_sbus_probe(struct platform_device *op)
+static int hme_sbus_probe(struct platform_device *op)
{
const struct of_device_id *match;
struct device_node *dp = op->dev.of_node;
@@ -3234,7 +3234,7 @@ static int __devinit hme_sbus_probe(struct platform_device *op)
return happy_meal_sbus_probe_one(op, is_qfe);
}
-static int __devexit hme_sbus_remove(struct platform_device *op)
+static int hme_sbus_remove(struct platform_device *op)
{
struct happy_meal *hp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = hp->dev;
@@ -3284,7 +3284,7 @@ static struct platform_driver hme_sbus_driver = {
.of_match_table = hme_sbus_match,
},
.probe = hme_sbus_probe,
- .remove = __devexit_p(hme_sbus_remove),
+ .remove = hme_sbus_remove,
};
static int __init happy_meal_sbus_init(void)
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index aeded7ff1c8f..1dcee6915843 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -744,7 +744,7 @@ static void qec_init_once(struct sunqec *qecp, struct platform_device *op)
qecp->gregs + GLOB_RSIZE);
}
-static u8 __devinit qec_get_burst(struct device_node *dp)
+static u8 qec_get_burst(struct device_node *dp)
{
u8 bsizes, bsizes_more;
@@ -764,7 +764,7 @@ static u8 __devinit qec_get_burst(struct device_node *dp)
return bsizes;
}
-static struct sunqec * __devinit get_qec(struct platform_device *child)
+static struct sunqec *get_qec(struct platform_device *child)
{
struct platform_device *op = to_platform_device(child->dev.parent);
struct sunqec *qecp;
@@ -830,7 +830,7 @@ static const struct net_device_ops qec_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit qec_ether_init(struct platform_device *op)
+static int qec_ether_init(struct platform_device *op)
{
static unsigned version_printed;
struct net_device *dev;
@@ -929,12 +929,12 @@ fail:
return res;
}
-static int __devinit qec_sbus_probe(struct platform_device *op)
+static int qec_sbus_probe(struct platform_device *op)
{
return qec_ether_init(op);
}
-static int __devexit qec_sbus_remove(struct platform_device *op)
+static int qec_sbus_remove(struct platform_device *op)
{
struct sunqe *qp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = qp->dev;
@@ -971,7 +971,7 @@ static struct platform_driver qec_sbus_driver = {
.of_match_table = qec_sbus_match,
},
.probe = qec_sbus_probe,
- .remove = __devexit_p(qec_sbus_remove),
+ .remove = qec_sbus_remove,
};
static int __init qec_init(void)
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index a108db35924e..e1b895530827 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -25,7 +25,7 @@
#define DRV_MODULE_VERSION "1.0"
#define DRV_MODULE_RELDATE "June 25, 2007"
-static char version[] __devinitdata =
+static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_DESCRIPTION("Sun LDOM virtual network driver");
@@ -937,7 +937,7 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
}
}
-static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+static int vnet_port_alloc_tx_bufs(struct vnet_port *port)
{
struct vio_dring_state *dr;
unsigned long len;
@@ -1019,7 +1019,7 @@ static const struct net_device_ops vnet_ops = {
.ndo_start_xmit = vnet_start_xmit,
};
-static struct vnet * __devinit vnet_new(const u64 *local_mac)
+static struct vnet *vnet_new(const u64 *local_mac)
{
struct net_device *dev;
struct vnet *vp;
@@ -1067,7 +1067,7 @@ err_out_free_dev:
return ERR_PTR(err);
}
-static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
+static struct vnet *vnet_find_or_create(const u64 *local_mac)
{
struct vnet *iter, *vp;
@@ -1088,7 +1088,7 @@ static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
static const char *local_mac_prop = "local-mac-address";
-static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp,
+static struct vnet *vnet_find_parent(struct mdesc_handle *hp,
u64 port_node)
{
const u64 *local_mac = NULL;
@@ -1125,15 +1125,14 @@ static struct vio_driver_ops vnet_vio_ops = {
.handshake_complete = vnet_handshake_complete,
};
-static void __devinit print_version(void)
+static void print_version(void)
{
printk_once(KERN_INFO "%s", version);
}
const char *remote_macaddr_prop = "remote-mac-address";
-static int __devinit vnet_port_probe(struct vio_dev *vdev,
- const struct vio_device_id *id)
+static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
struct mdesc_handle *hp;
struct vnet_port *port;
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 6ce9edd95c04..1e4d743ff03e 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1914,7 +1914,7 @@ static const struct net_device_ops bdx_netdev_ops = {
*/
/* TBD: netif_msg should be checked and implemented. I disable it for now */
-static int __devinit
+static int
bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *ndev;
@@ -2427,7 +2427,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
-static void __devexit bdx_remove(struct pci_dev *pdev)
+static void bdx_remove(struct pci_dev *pdev)
{
struct pci_nic *nic = pci_get_drvdata(pdev);
struct net_device *ndev;
@@ -2458,7 +2458,7 @@ static struct pci_driver bdx_pci_driver = {
.name = BDX_DRV_NAME,
.id_table = bdx_pci_tbl,
.probe = bdx_probe,
- .remove = __devexit_p(bdx_remove),
+ .remove = bdx_remove,
};
/*
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 2c41894d5472..4426151d4ac9 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -60,6 +60,15 @@ config TI_CPSW
To compile this driver as a module, choose M here: the module
will be called cpsw.
+config TI_CPTS
+ boolean "TI Common Platform Time Sync (CPTS) Support"
+ depends on TI_CPSW
+ select PTP_1588_CLOCK
+ ---help---
+ This driver supports the Common Platform Time Sync unit of
+ the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
+ and Layer 2 packets, and the driver offers a PTP Hardware Clock.
+
config TLAN
tristate "TI ThunderLAN support"
depends on (PCI || EISA)
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index 91bd8bba78ff..c65148e8aa1d 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw_ale.o cpsw.o
+ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 860c2526f08d..d9625f62b026 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1110,7 +1110,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
static int external_switch;
-static int __devinit cpmac_probe(struct platform_device *pdev)
+static int cpmac_probe(struct platform_device *pdev)
{
int rc, phy_id;
char mdio_bus_id[MII_BUS_ID_SIZE];
@@ -1204,7 +1204,7 @@ fail:
return rc;
}
-static int __devexit cpmac_remove(struct platform_device *pdev)
+static int cpmac_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_netdev(dev);
@@ -1216,10 +1216,10 @@ static struct platform_driver cpmac_driver = {
.driver.name = "cpmac",
.driver.owner = THIS_MODULE,
.probe = cpmac_probe,
- .remove = __devexit_p(cpmac_remove),
+ .remove = cpmac_remove,
};
-int __devinit cpmac_init(void)
+int cpmac_init(void)
{
u32 mask;
int i, res;
@@ -1290,7 +1290,7 @@ fail_alloc:
return res;
}
-void __devexit cpmac_exit(void)
+void cpmac_exit(void)
{
platform_driver_unregister(&cpmac_driver);
mdiobus_unregister(cpmac_mii);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df55e2403746..40aff684aa23 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -24,6 +24,7 @@
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
#include <linux/phy.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
@@ -35,6 +36,7 @@
#include <linux/platform_data/cpsw.h>
#include "cpsw_ale.h"
+#include "cpts.h"
#include "davinci_cpdma.h"
#define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \
@@ -70,10 +72,37 @@ do { \
dev_notice(priv->dev, format, ## __VA_ARGS__); \
} while (0)
+#define ALE_ALL_PORTS 0x7
+
#define CPSW_MAJOR_VERSION(reg) (reg >> 8 & 0x7)
#define CPSW_MINOR_VERSION(reg) (reg & 0xff)
#define CPSW_RTL_VERSION(reg) ((reg >> 11) & 0x1f)
+#define CPSW_VERSION_1 0x19010a
+#define CPSW_VERSION_2 0x19010c
+
+#define HOST_PORT_NUM 0
+#define SLIVER_SIZE 0x40
+
+#define CPSW1_HOST_PORT_OFFSET 0x028
+#define CPSW1_SLAVE_OFFSET 0x050
+#define CPSW1_SLAVE_SIZE 0x040
+#define CPSW1_CPDMA_OFFSET 0x100
+#define CPSW1_STATERAM_OFFSET 0x200
+#define CPSW1_CPTS_OFFSET 0x500
+#define CPSW1_ALE_OFFSET 0x600
+#define CPSW1_SLIVER_OFFSET 0x700
+
+#define CPSW2_HOST_PORT_OFFSET 0x108
+#define CPSW2_SLAVE_OFFSET 0x200
+#define CPSW2_SLAVE_SIZE 0x100
+#define CPSW2_CPDMA_OFFSET 0x800
+#define CPSW2_STATERAM_OFFSET 0xa00
+#define CPSW2_CPTS_OFFSET 0xc00
+#define CPSW2_ALE_OFFSET 0xd00
+#define CPSW2_SLIVER_OFFSET 0xd80
+#define CPSW2_BD_OFFSET 0x2000
+
#define CPDMA_RXTHRESH 0x0c0
#define CPDMA_RXFREE 0x0e0
#define CPDMA_TXHDP 0x00
@@ -81,21 +110,6 @@ do { \
#define CPDMA_TXCP 0x40
#define CPDMA_RXCP 0x60
-#define cpsw_dma_regs(base, offset) \
- (void __iomem *)((base) + (offset))
-#define cpsw_dma_rxthresh(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_RXTHRESH)
-#define cpsw_dma_rxfree(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_RXFREE)
-#define cpsw_dma_txhdp(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_TXHDP)
-#define cpsw_dma_rxhdp(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_RXHDP)
-#define cpsw_dma_txcp(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_TXCP)
-#define cpsw_dma_rxcp(base, offset) \
- (void __iomem *)((base) + (offset) + CPDMA_RXCP)
-
#define CPSW_POLL_WEIGHT 64
#define CPSW_MIN_PACKET_SIZE 60
#define CPSW_MAX_PACKET_SIZE (1500 + 14 + 4 + 4)
@@ -129,7 +143,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE;
module_param(rx_packet_max, int, 0);
MODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)");
-struct cpsw_ss_regs {
+struct cpsw_wr_regs {
u32 id_ver;
u32 soft_reset;
u32 control;
@@ -140,26 +154,98 @@ struct cpsw_ss_regs {
u32 misc_en;
};
-struct cpsw_regs {
+struct cpsw_ss_regs {
u32 id_ver;
u32 control;
u32 soft_reset;
u32 stat_port_en;
u32 ptype;
+ u32 soft_idle;
+ u32 thru_rate;
+ u32 gap_thresh;
+ u32 tx_start_wds;
+ u32 flow_control;
+ u32 vlan_ltype;
+ u32 ts_ltype;
+ u32 dlr_ltype;
};
-struct cpsw_slave_regs {
- u32 max_blks;
- u32 blk_cnt;
- u32 flow_thresh;
- u32 port_vlan;
- u32 tx_pri_map;
- u32 ts_ctl;
- u32 ts_seq_ltype;
- u32 ts_vlan;
- u32 sa_lo;
- u32 sa_hi;
-};
+/* CPSW_PORT_V1 */
+#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */
+#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */
+#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */
+#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */
+#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW1_TS_CTL 0x14 /* Time Sync Control */
+#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */
+#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */
+
+/* CPSW_PORT_V2 */
+#define CPSW2_CONTROL 0x00 /* Control Register */
+#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */
+#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */
+#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */
+#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */
+#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */
+
+/* CPSW_PORT_V1 and V2 */
+#define SA_LO 0x20 /* CPGMAC_SL Source Address Low */
+#define SA_HI 0x24 /* CPGMAC_SL Source Address High */
+#define SEND_PERCENT 0x28 /* Transmit Queue Send Percentages */
+
+/* CPSW_PORT_V2 only */
+#define RX_DSCP_PRI_MAP0 0x30 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP1 0x34 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP2 0x38 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP3 0x3c /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP4 0x40 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP5 0x44 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP6 0x48 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP7 0x4c /* Rx DSCP Priority to Rx Packet Mapping */
+
+/* Bit definitions for the CPSW2_CONTROL register */
+#define PASS_PRI_TAGGED (1<<24) /* Pass Priority Tagged */
+#define VLAN_LTYPE2_EN (1<<21) /* VLAN LTYPE 2 enable */
+#define VLAN_LTYPE1_EN (1<<20) /* VLAN LTYPE 1 enable */
+#define DSCP_PRI_EN (1<<16) /* DSCP Priority Enable */
+#define TS_320 (1<<14) /* Time Sync Dest Port 320 enable */
+#define TS_319 (1<<13) /* Time Sync Dest Port 319 enable */
+#define TS_132 (1<<12) /* Time Sync Dest IP Addr 132 enable */
+#define TS_131 (1<<11) /* Time Sync Dest IP Addr 131 enable */
+#define TS_130 (1<<10) /* Time Sync Dest IP Addr 130 enable */
+#define TS_129 (1<<9) /* Time Sync Dest IP Addr 129 enable */
+#define TS_BIT8 (1<<8) /* ts_ttl_nonzero? */
+#define TS_ANNEX_D_EN (1<<4) /* Time Sync Annex D enable */
+#define TS_LTYPE2_EN (1<<3) /* Time Sync LTYPE 2 enable */
+#define TS_LTYPE1_EN (1<<2) /* Time Sync LTYPE 1 enable */
+#define TS_TX_EN (1<<1) /* Time Sync Transmit Enable */
+#define TS_RX_EN (1<<0) /* Time Sync Receive Enable */
+
+#define CTRL_TS_BITS \
+ (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \
+ TS_ANNEX_D_EN | TS_LTYPE1_EN)
+
+#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN)
+#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN)
+#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN)
+
+/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */
+#define TS_SEQ_ID_OFFSET_SHIFT (16) /* Time Sync Sequence ID Offset */
+#define TS_SEQ_ID_OFFSET_MASK (0x3f)
+#define TS_MSG_TYPE_EN_SHIFT (0) /* Time Sync Message Type Enable */
+#define TS_MSG_TYPE_EN_MASK (0xffff)
+
+/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
+#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3))
+
+/* Bit definitions for the CPSW1_TS_CTL register */
+#define CPSW_V1_TS_RX_EN BIT(0)
+#define CPSW_V1_TS_TX_EN BIT(4)
+#define CPSW_V1_MSG_TYPE_OFS 16
+
+/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */
+#define CPSW_V1_SEQ_ID_OFS_SHIFT 16
struct cpsw_host_regs {
u32 max_blks;
@@ -185,7 +271,7 @@ struct cpsw_sliver_regs {
};
struct cpsw_slave {
- struct cpsw_slave_regs __iomem *regs;
+ void __iomem *regs;
struct cpsw_sliver_regs __iomem *sliver;
int slave_num;
u32 mac_control;
@@ -193,19 +279,30 @@ struct cpsw_slave {
struct phy_device *phy;
};
+static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
+{
+ return __raw_readl(slave->regs + offset);
+}
+
+static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
+{
+ __raw_writel(val, slave->regs + offset);
+}
+
struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
struct resource *cpsw_res;
- struct resource *cpsw_ss_res;
+ struct resource *cpsw_wr_res;
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
- struct cpsw_regs __iomem *regs;
- struct cpsw_ss_regs __iomem *ss_regs;
+ struct cpsw_ss_regs __iomem *regs;
+ struct cpsw_wr_regs __iomem *wr_regs;
struct cpsw_host_regs __iomem *host_port_regs;
u32 msg_enable;
+ u32 version;
struct net_device_stats stats;
int rx_packet_max;
int host_port;
@@ -218,6 +315,7 @@ struct cpsw_priv {
/* snapshot of IRQ numbers */
u32 irqs_table[4];
u32 num_irqs;
+ struct cpts cpts;
};
#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
@@ -228,10 +326,34 @@ struct cpsw_priv {
(func)((priv)->slaves + idx, ##arg); \
} while (0)
+static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (ndev->flags & IFF_PROMISC) {
+ /* Enable promiscuous mode */
+ dev_err(priv->dev, "Ignoring Promiscuous mode\n");
+ return;
+ }
+
+ /* Clear all mcast from ALE */
+ cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
+
+ if (!netdev_mc_empty(ndev)) {
+ struct netdev_hw_addr *ha;
+
+ /* program multicast address list into ALE register */
+ netdev_for_each_mc_addr(ha, ndev) {
+ cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
+ ALE_ALL_PORTS << priv->host_port, 0, 0);
+ }
+ }
+}
+
static void cpsw_intr_enable(struct cpsw_priv *priv)
{
- __raw_writel(0xFF, &priv->ss_regs->tx_en);
- __raw_writel(0xFF, &priv->ss_regs->rx_en);
+ __raw_writel(0xFF, &priv->wr_regs->tx_en);
+ __raw_writel(0xFF, &priv->wr_regs->rx_en);
cpdma_ctlr_int_ctrl(priv->dma, true);
return;
@@ -239,8 +361,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
static void cpsw_intr_disable(struct cpsw_priv *priv)
{
- __raw_writel(0, &priv->ss_regs->tx_en);
- __raw_writel(0, &priv->ss_regs->rx_en);
+ __raw_writel(0, &priv->wr_regs->tx_en);
+ __raw_writel(0, &priv->wr_regs->rx_en);
cpdma_ctlr_int_ctrl(priv->dma, false);
return;
@@ -254,6 +376,7 @@ void cpsw_tx_handler(void *token, int len, int status)
if (unlikely(netif_queue_stopped(ndev)))
netif_start_queue(ndev);
+ cpts_tx_timestamp(&priv->cpts, skb);
priv->stats.tx_packets++;
priv->stats.tx_bytes += len;
dev_kfree_skb_any(skb);
@@ -274,6 +397,7 @@ void cpsw_rx_handler(void *token, int len, int status)
}
if (likely(status >= 0)) {
skb_put(skb, len);
+ cpts_rx_timestamp(&priv->cpts, skb);
skb->protocol = eth_type_trans(skb, ndev);
netif_receive_skb(skb);
priv->stats.rx_bytes += len;
@@ -359,8 +483,8 @@ static inline void soft_reset(const char *module, void __iomem *reg)
static void cpsw_set_slave_mac(struct cpsw_slave *slave,
struct cpsw_priv *priv)
{
- __raw_writel(mac_hi(priv->mac_addr), &slave->regs->sa_hi);
- __raw_writel(mac_lo(priv->mac_addr), &slave->regs->sa_lo);
+ slave_write(slave, mac_hi(priv->mac_addr), SA_HI);
+ slave_write(slave, mac_lo(priv->mac_addr), SA_LO);
}
static void _cpsw_adjust_link(struct cpsw_slave *slave,
@@ -446,7 +570,15 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
/* setup priority mapping */
__raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map);
- __raw_writel(TX_PRIORITY_MAPPING, &slave->regs->tx_pri_map);
+
+ switch (priv->version) {
+ case CPSW_VERSION_1:
+ slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP);
+ break;
+ case CPSW_VERSION_2:
+ slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP);
+ break;
+ }
/* setup max packet size, and mac address */
__raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen);
@@ -505,7 +637,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
pm_runtime_get_sync(&priv->pdev->dev);
- reg = __raw_readl(&priv->regs->id_ver);
+ reg = priv->version;
dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n",
CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg),
@@ -566,12 +698,12 @@ static int cpsw_ndo_stop(struct net_device *ndev)
struct cpsw_priv *priv = netdev_priv(ndev);
cpsw_info(priv, ifdown, "shutting down cpsw device\n");
- cpsw_intr_disable(priv);
- cpdma_ctlr_int_ctrl(priv->dma, false);
- cpdma_ctlr_stop(priv->dma);
netif_stop_queue(priv->ndev);
napi_disable(&priv->napi);
netif_carrier_off(priv->ndev);
+ cpsw_intr_disable(priv);
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+ cpdma_ctlr_stop(priv->dma);
cpsw_ale_stop(priv->ale);
for_each_slave(priv, cpsw_slave_stop, priv);
pm_runtime_put_sync(&priv->pdev->dev);
@@ -592,6 +724,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ skb_tx_timestamp(skb);
+
ret = cpdma_chan_submit(priv->txch, skb, skb->data,
skb->len, GFP_KERNEL);
if (unlikely(ret != 0)) {
@@ -629,6 +766,129 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
}
+#ifdef CONFIG_TI_CPTS
+
+static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
+{
+ struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+ u32 ts_en, seq_id;
+
+ if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+ slave_write(slave, 0, CPSW1_TS_CTL);
+ return;
+ }
+
+ seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
+ ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
+
+ if (priv->cpts.tx_enable)
+ ts_en |= CPSW_V1_TS_TX_EN;
+
+ if (priv->cpts.rx_enable)
+ ts_en |= CPSW_V1_TS_RX_EN;
+
+ slave_write(slave, ts_en, CPSW1_TS_CTL);
+ slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE);
+}
+
+static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
+{
+ struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+ u32 ctrl, mtype;
+
+ ctrl = slave_read(slave, CPSW2_CONTROL);
+ ctrl &= ~CTRL_ALL_TS_MASK;
+
+ if (priv->cpts.tx_enable)
+ ctrl |= CTRL_TX_TS_BITS;
+
+ if (priv->cpts.rx_enable)
+ ctrl |= CTRL_RX_TS_BITS;
+
+ mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
+
+ slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE);
+ slave_write(slave, ctrl, CPSW2_CONTROL);
+ __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
+}
+
+static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+ struct cpsw_priv *priv = netdev_priv(dev);
+ struct cpts *cpts = &priv->cpts;
+ struct hwtstamp_config cfg;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ cpts->tx_enable = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ cpts->tx_enable = 1;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ cpts->rx_enable = 0;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ return -ERANGE;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ cpts->rx_enable = 1;
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (priv->version) {
+ case CPSW_VERSION_1:
+ cpsw_hwtstamp_v1(priv);
+ break;
+ case CPSW_VERSION_2:
+ cpsw_hwtstamp_v2(priv);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ 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)
+{
+ if (!netif_running(dev))
+ return -EINVAL;
+
+#ifdef CONFIG_TI_CPTS
+ if (cmd == SIOCSHWTSTAMP)
+ return cpsw_hwtstamp_ioctl(dev, req);
+#endif
+ return -ENOTSUPP;
+}
+
static void cpsw_ndo_tx_timeout(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
@@ -669,10 +929,12 @@ static const struct net_device_ops cpsw_netdev_ops = {
.ndo_stop = cpsw_ndo_stop,
.ndo_start_xmit = cpsw_ndo_start_xmit,
.ndo_change_rx_flags = cpsw_ndo_change_rx_flags,
+ .ndo_do_ioctl = cpsw_ndo_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = cpsw_ndo_tx_timeout,
.ndo_get_stats = cpsw_ndo_get_stats,
+ .ndo_set_rx_mode = cpsw_ndo_set_rx_mode,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
@@ -699,22 +961,56 @@ static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
priv->msg_enable = value;
}
+static int cpsw_get_ts_info(struct net_device *ndev,
+ struct ethtool_ts_info *info)
+{
+#ifdef CONFIG_TI_CPTS
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = priv->cpts.phc_index;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+#else
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+ info->phc_index = -1;
+ info->tx_types = 0;
+ info->rx_filters = 0;
+#endif
+ return 0;
+}
+
static const struct ethtool_ops cpsw_ethtool_ops = {
.get_drvinfo = cpsw_get_drvinfo,
.get_msglevel = cpsw_get_msglevel,
.set_msglevel = cpsw_set_msglevel,
.get_link = ethtool_op_get_link,
+ .get_ts_info = cpsw_get_ts_info,
};
-static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
+static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
+ u32 slave_reg_ofs, u32 sliver_reg_ofs)
{
void __iomem *regs = priv->regs;
int slave_num = slave->slave_num;
struct cpsw_slave_data *data = priv->data.slave_data + slave_num;
slave->data = data;
- slave->regs = regs + data->slave_reg_ofs;
- slave->sliver = regs + data->sliver_reg_ofs;
+ slave->regs = regs + slave_reg_ofs;
+ slave->sliver = regs + sliver_reg_ofs;
}
static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -734,49 +1030,40 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->slaves = prop;
- data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
- data->slaves, GFP_KERNEL);
- if (!data->slave_data) {
- pr_err("Could not allocate slave memory.\n");
- return -EINVAL;
- }
-
- data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
-
- if (of_property_read_u32(node, "cpdma_channels", &prop)) {
- pr_err("Missing cpdma_channels property in the DT.\n");
+ if (of_property_read_u32(node, "cpts_active_slave", &prop)) {
+ pr_err("Missing cpts_active_slave property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
- data->channels = prop;
+ data->cpts_active_slave = prop;
- if (of_property_read_u32(node, "host_port_no", &prop)) {
- pr_err("Missing host_port_no property in the DT.\n");
+ if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
+ pr_err("Missing cpts_clock_mult property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
- data->host_port_num = prop;
+ data->cpts_clock_mult = prop;
- if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
- pr_err("Missing cpdma_reg_ofs property in the DT.\n");
+ if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
+ pr_err("Missing cpts_clock_shift property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
- data->cpdma_reg_ofs = prop;
+ data->cpts_clock_shift = prop;
- if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
- pr_err("Missing cpdma_sram_ofs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
+ data->slaves, GFP_KERNEL);
+ if (!data->slave_data) {
+ pr_err("Could not allocate slave memory.\n");
+ return -EINVAL;
}
- data->cpdma_sram_ofs = prop;
- if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
- pr_err("Missing ale_reg_ofs property in the DT.\n");
+ if (of_property_read_u32(node, "cpdma_channels", &prop)) {
+ pr_err("Missing cpdma_channels property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
- data->ale_reg_ofs = prop;
+ data->channels = prop;
if (of_property_read_u32(node, "ale_entries", &prop)) {
pr_err("Missing ale_entries property in the DT.\n");
@@ -785,27 +1072,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->ale_entries = prop;
- if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
- pr_err("Missing host_port_reg_ofs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
- }
- data->host_port_reg_ofs = prop;
-
- if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
- pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
- }
- data->hw_stats_reg_ofs = prop;
-
- if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
- pr_err("Missing bd_ram_ofs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
- }
- data->bd_ram_ofs = prop;
-
if (of_property_read_u32(node, "bd_ram_size", &prop)) {
pr_err("Missing bd_ram_size property in the DT.\n");
ret = -EINVAL;
@@ -827,33 +1093,34 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
- for_each_child_of_node(node, slave_node) {
+ /*
+ * Populate all the child nodes here...
+ */
+ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+ /* We do not want to force this, as in some cases may not have child */
+ if (ret)
+ pr_warn("Doesn't have any child node\n");
+
+ for_each_node_by_name(slave_node, "slave") {
struct cpsw_slave_data *slave_data = data->slave_data + i;
- const char *phy_id = NULL;
const void *mac_addr = NULL;
-
- if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
+ u32 phyid;
+ int lenp;
+ const __be32 *parp;
+ struct device_node *mdio_node;
+ struct platform_device *mdio;
+
+ parp = of_get_property(slave_node, "phy_id", &lenp);
+ if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
pr_err("Missing slave[%d] phy_id property\n", i);
ret = -EINVAL;
goto error_ret;
}
- slave_data->phy_id = phy_id;
-
- if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
- pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
- ret = -EINVAL;
- goto error_ret;
- }
- slave_data->slave_reg_ofs = prop;
-
- if (of_property_read_u32(slave_node, "sliver_reg_ofs",
- &prop)) {
- pr_err("Missing slave[%d] sliver_reg_ofs property\n",
- i);
- ret = -EINVAL;
- goto error_ret;
- }
- slave_data->sliver_reg_ofs = prop;
+ mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
+ phyid = be32_to_cpup(parp+1);
+ mdio = of_find_device_by_node(mdio_node);
+ snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+ PHY_ID_FMT, mdio->name, phyid);
mac_addr = of_get_mac_address(slave_node);
if (mac_addr)
@@ -869,15 +1136,16 @@ error_ret:
return ret;
}
-static int __devinit cpsw_probe(struct platform_device *pdev)
+static int cpsw_probe(struct platform_device *pdev)
{
struct cpsw_platform_data *data = pdev->dev.platform_data;
struct net_device *ndev;
struct cpsw_priv *priv;
struct cpdma_params dma_params;
struct cpsw_ale_params ale_params;
- void __iomem *regs;
+ void __iomem *ss_regs, *wr_regs;
struct resource *res;
+ u32 slave_offset, sliver_offset, slave_size;
int ret = 0, i, k = 0;
ndev = alloc_etherdev(sizeof(struct cpsw_priv));
@@ -895,6 +1163,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->rx_packet_max = max(rx_packet_max, 128);
+ /*
+ * This may be required here for child devices.
+ */
+ pm_runtime_enable(&pdev->dev);
+
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
@@ -921,7 +1194,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
- pm_runtime_enable(&pdev->dev);
priv->clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "fck is not found\n");
@@ -935,63 +1207,86 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
ret = -ENOENT;
goto clean_clk_ret;
}
-
if (!request_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res), ndev->name)) {
dev_err(priv->dev, "failed request i/o region\n");
ret = -ENXIO;
goto clean_clk_ret;
}
-
- regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
- if (!regs) {
+ ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
+ if (!ss_regs) {
dev_err(priv->dev, "unable to map i/o region\n");
goto clean_cpsw_iores_ret;
}
- priv->regs = regs;
- priv->host_port = data->host_port_num;
- priv->host_port_regs = regs + data->host_port_reg_ofs;
+ priv->regs = ss_regs;
+ priv->version = __raw_readl(&priv->regs->id_ver);
+ priv->host_port = HOST_PORT_NUM;
- priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!priv->cpsw_ss_res) {
+ priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!priv->cpsw_wr_res) {
dev_err(priv->dev, "error getting i/o resource\n");
ret = -ENOENT;
- goto clean_clk_ret;
+ goto clean_iomap_ret;
}
-
- if (!request_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res), ndev->name)) {
+ if (!request_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res), ndev->name)) {
dev_err(priv->dev, "failed request i/o region\n");
ret = -ENXIO;
- goto clean_clk_ret;
+ goto clean_iomap_ret;
}
-
- regs = ioremap(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
- if (!regs) {
+ wr_regs = ioremap(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
+ if (!wr_regs) {
dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_ss_iores_ret;
+ goto clean_cpsw_wr_iores_ret;
}
- priv->ss_regs = regs;
-
- for_each_slave(priv, cpsw_slave_init, priv);
+ priv->wr_regs = wr_regs;
memset(&dma_params, 0, sizeof(dma_params));
+ memset(&ale_params, 0, sizeof(ale_params));
+
+ switch (priv->version) {
+ case CPSW_VERSION_1:
+ priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
+ priv->cpts.reg = ss_regs + CPSW1_CPTS_OFFSET;
+ dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET;
+ dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET;
+ ale_params.ale_regs = ss_regs + CPSW1_ALE_OFFSET;
+ slave_offset = CPSW1_SLAVE_OFFSET;
+ slave_size = CPSW1_SLAVE_SIZE;
+ sliver_offset = CPSW1_SLIVER_OFFSET;
+ dma_params.desc_mem_phys = 0;
+ break;
+ case CPSW_VERSION_2:
+ priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
+ priv->cpts.reg = ss_regs + CPSW2_CPTS_OFFSET;
+ dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET;
+ dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET;
+ ale_params.ale_regs = ss_regs + CPSW2_ALE_OFFSET;
+ slave_offset = CPSW2_SLAVE_OFFSET;
+ slave_size = CPSW2_SLAVE_SIZE;
+ sliver_offset = CPSW2_SLIVER_OFFSET;
+ dma_params.desc_mem_phys =
+ (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+ break;
+ default:
+ dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
+ ret = -ENODEV;
+ goto clean_cpsw_wr_iores_ret;
+ }
+ for (i = 0; i < priv->data.slaves; i++) {
+ struct cpsw_slave *slave = &priv->slaves[i];
+ cpsw_slave_init(slave, priv, slave_offset, sliver_offset);
+ slave_offset += slave_size;
+ sliver_offset += SLIVER_SIZE;
+ }
+
dma_params.dev = &pdev->dev;
- dma_params.dmaregs = cpsw_dma_regs((u32)priv->regs,
- data->cpdma_reg_ofs);
- dma_params.rxthresh = cpsw_dma_rxthresh((u32)priv->regs,
- data->cpdma_reg_ofs);
- dma_params.rxfree = cpsw_dma_rxfree((u32)priv->regs,
- data->cpdma_reg_ofs);
- dma_params.txhdp = cpsw_dma_txhdp((u32)priv->regs,
- data->cpdma_sram_ofs);
- dma_params.rxhdp = cpsw_dma_rxhdp((u32)priv->regs,
- data->cpdma_sram_ofs);
- dma_params.txcp = cpsw_dma_txcp((u32)priv->regs,
- data->cpdma_sram_ofs);
- dma_params.rxcp = cpsw_dma_rxcp((u32)priv->regs,
- data->cpdma_sram_ofs);
+ dma_params.rxthresh = dma_params.dmaregs + CPDMA_RXTHRESH;
+ dma_params.rxfree = dma_params.dmaregs + CPDMA_RXFREE;
+ dma_params.rxhdp = dma_params.txhdp + CPDMA_RXHDP;
+ dma_params.txcp = dma_params.txhdp + CPDMA_TXCP;
+ dma_params.rxcp = dma_params.txhdp + CPDMA_RXCP;
dma_params.num_chan = data->channels;
dma_params.has_soft_reset = true;
@@ -999,16 +1294,13 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
dma_params.desc_mem_size = data->bd_ram_size;
dma_params.desc_align = 16;
dma_params.has_ext_regs = true;
- dma_params.desc_mem_phys = data->no_bd_ram ? 0 :
- (u32 __force)priv->cpsw_res->start + data->bd_ram_ofs;
- dma_params.desc_hw_addr = data->hw_ram_addr ?
- data->hw_ram_addr : dma_params.desc_mem_phys ;
+ dma_params.desc_hw_addr = dma_params.desc_mem_phys;
priv->dma = cpdma_ctlr_create(&dma_params);
if (!priv->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_iomap_ret;
+ goto clean_wr_iomap_ret;
}
priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -1022,10 +1314,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
goto clean_dma_ret;
}
- memset(&ale_params, 0, sizeof(ale_params));
ale_params.dev = &ndev->dev;
- ale_params.ale_regs = (void *)((u32)priv->regs) +
- ((u32)data->ale_reg_ofs);
ale_params.ale_ageout = ale_ageout;
ale_params.ale_entries = data->ale_entries;
ale_params.ale_ports = data->slaves;
@@ -1072,6 +1361,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
goto clean_irq_ret;
}
+ if (cpts_register(&pdev->dev, &priv->cpts,
+ data->cpts_clock_mult, data->cpts_clock_shift))
+ dev_err(priv->dev, "error registering cpts device\n");
+
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
priv->cpsw_res->start, ndev->irq);
@@ -1085,11 +1378,13 @@ clean_dma_ret:
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
+clean_wr_iomap_ret:
+ iounmap(priv->wr_regs);
+clean_cpsw_wr_iores_ret:
+ release_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
clean_iomap_ret:
iounmap(priv->regs);
-clean_cpsw_ss_iores_ret:
- release_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
clean_cpsw_iores_ret:
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
@@ -1103,7 +1398,7 @@ clean_ndev_ret:
return ret;
}
-static int __devexit cpsw_remove(struct platform_device *pdev)
+static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
@@ -1111,6 +1406,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
pr_info("removing device");
platform_set_drvdata(pdev, NULL);
+ cpts_unregister(&priv->cpts);
free_irq(ndev->irq, priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
@@ -1119,8 +1415,9 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
iounmap(priv->regs);
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
- release_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
+ iounmap(priv->wr_regs);
+ release_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
clk_put(priv->clk);
kfree(priv->slaves);
@@ -1170,7 +1467,7 @@ static struct platform_driver cpsw_driver = {
.of_match_table = of_match_ptr(cpsw_of_mtable),
},
.probe = cpsw_probe,
- .remove = __devexit_p(cpsw_remove),
+ .remove = cpsw_remove,
};
static int __init cpsw_init(void)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index ca0d48a7e508..0e9ccc2cf91f 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -20,6 +20,7 @@
#include <linux/io.h>
#include <linux/stat.h>
#include <linux/sysfs.h>
+#include <linux/etherdevice.h>
#include "cpsw_ale.h"
@@ -211,10 +212,34 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
mask &= ~port_mask;
/* free if only remaining port is host port */
- if (mask == BIT(ale->params.ale_ports))
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
- else
+ if (mask)
cpsw_ale_set_port_mask(ale_entry, mask);
+ else
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+}
+
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int ret, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ ret = cpsw_ale_get_entry_type(ale_entry);
+ if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
+ continue;
+
+ if (cpsw_ale_get_mcast(ale_entry)) {
+ u8 addr[6];
+
+ cpsw_ale_get_addr(ale_entry, addr);
+ if (!is_broadcast_ether_addr(addr))
+ cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
+ }
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ }
+ return 0;
}
static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index a95b37beb02d..2bd09cbce522 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -80,6 +80,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
new file mode 100644
index 000000000000..337766738eca
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -0,0 +1,427 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@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.
+ *
+ * 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/err.h>
+#include <linux/if.h>
+#include <linux/hrtimer.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_classify.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+
+#include <plat/clock.h>
+
+#include "cpts.h"
+
+#ifdef CONFIG_TI_CPTS
+
+static struct sock_filter ptp_filter[] = {
+ PTP_FILTER
+};
+
+#define cpts_read32(c, r) __raw_readl(&c->reg->r)
+#define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r)
+
+static int event_expired(struct cpts_event *event)
+{
+ return time_after(jiffies, event->tmo);
+}
+
+static int event_type(struct cpts_event *event)
+{
+ return (event->high >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
+}
+
+static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low)
+{
+ u32 r = cpts_read32(cpts, intstat_raw);
+
+ if (r & TS_PEND_RAW) {
+ *high = cpts_read32(cpts, event_high);
+ *low = cpts_read32(cpts, event_low);
+ cpts_write32(cpts, EVENT_POP, event_pop);
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * Returns zero if matching event type was found.
+ */
+static int cpts_fifo_read(struct cpts *cpts, int match)
+{
+ int i, type = -1;
+ u32 hi, lo;
+ struct cpts_event *event;
+
+ for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
+ if (cpts_fifo_pop(cpts, &hi, &lo))
+ break;
+ if (list_empty(&cpts->pool)) {
+ pr_err("cpts: event pool is empty\n");
+ return -1;
+ }
+ event = list_first_entry(&cpts->pool, struct cpts_event, list);
+ event->tmo = jiffies + 2;
+ event->high = hi;
+ event->low = lo;
+ type = event_type(event);
+ switch (type) {
+ case CPTS_EV_PUSH:
+ case CPTS_EV_RX:
+ case CPTS_EV_TX:
+ list_del_init(&event->list);
+ list_add_tail(&event->list, &cpts->events);
+ break;
+ case CPTS_EV_ROLL:
+ case CPTS_EV_HALF:
+ case CPTS_EV_HW:
+ break;
+ default:
+ pr_err("cpts: unkown event type\n");
+ break;
+ }
+ if (type == match)
+ break;
+ }
+ return type == match ? 0 : -1;
+}
+
+static cycle_t cpts_systim_read(const struct cyclecounter *cc)
+{
+ u64 val = 0;
+ struct cpts_event *event;
+ struct list_head *this, *next;
+ struct cpts *cpts = container_of(cc, struct cpts, cc);
+
+ cpts_write32(cpts, TS_PUSH, ts_push);
+ if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
+ pr_err("cpts: unable to obtain a time stamp\n");
+
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ if (event_type(event) == CPTS_EV_PUSH) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ val = event->low;
+ break;
+ }
+ }
+
+ return val;
+}
+
+/* PTP clock operations */
+
+static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ u64 adj;
+ u32 diff, mult;
+ int neg_adj = 0;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ mult = cpts->cc_mult;
+ adj = mult;
+ adj *= ppb;
+ diff = div_u64(adj, 1000000000ULL);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+
+ timecounter_read(&cpts->tc);
+
+ cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
+
+static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ s64 now;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ now = timecounter_read(&cpts->tc);
+ now += delta;
+ timecounter_init(&cpts->tc, &cpts->cc, now);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
+
+static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ ns = timecounter_read(&cpts->tc);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+static int cpts_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ u64 ns;
+ unsigned long flags;
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ timecounter_init(&cpts->tc, &cpts->cc, ns);
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return 0;
+}
+
+static int cpts_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info cpts_info = {
+ .owner = THIS_MODULE,
+ .name = "CTPS timer",
+ .max_adj = 1000000,
+ .n_ext_ts = 0,
+ .pps = 0,
+ .adjfreq = cpts_ptp_adjfreq,
+ .adjtime = cpts_ptp_adjtime,
+ .gettime = cpts_ptp_gettime,
+ .settime = cpts_ptp_settime,
+ .enable = cpts_ptp_enable,
+};
+
+static void cpts_overflow_check(struct work_struct *work)
+{
+ struct timespec ts;
+ struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
+
+ cpts_write32(cpts, CPTS_EN, control);
+ cpts_write32(cpts, TS_PEND_EN, int_enable);
+ cpts_ptp_gettime(&cpts->info, &ts);
+ pr_debug("cpts overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
+ schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+}
+
+#define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk"
+
+static void cpts_clk_init(struct cpts *cpts)
+{
+ cpts->refclk = clk_get(NULL, CPTS_REF_CLOCK_NAME);
+ if (IS_ERR(cpts->refclk)) {
+ pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME);
+ cpts->refclk = NULL;
+ return;
+ }
+ clk_enable(cpts->refclk);
+ cpts->freq = cpts->refclk->recalc(cpts->refclk);
+}
+
+static void cpts_clk_release(struct cpts *cpts)
+{
+ clk_disable(cpts->refclk);
+ clk_put(cpts->refclk);
+}
+
+static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
+ u16 ts_seqid, u8 ts_msgtype)
+{
+ u16 *seqid;
+ unsigned int offset;
+ u8 *msgtype, *data = skb->data;
+
+ switch (ptp_class) {
+ case PTP_CLASS_V1_IPV4:
+ case PTP_CLASS_V2_IPV4:
+ offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+ break;
+ case PTP_CLASS_V1_IPV6:
+ case PTP_CLASS_V2_IPV6:
+ offset = OFF_PTP6;
+ break;
+ case PTP_CLASS_V2_L2:
+ offset = ETH_HLEN;
+ break;
+ case PTP_CLASS_V2_VLAN:
+ offset = ETH_HLEN + VLAN_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+ return 0;
+
+ if (unlikely(ptp_class & PTP_CLASS_V1))
+ msgtype = data + offset + OFF_PTP_CONTROL;
+ else
+ msgtype = data + offset;
+
+ seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+ return (ts_msgtype == (*msgtype & 0xf) && ts_seqid == ntohs(*seqid));
+}
+
+static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type)
+{
+ u64 ns = 0;
+ struct cpts_event *event;
+ struct list_head *this, *next;
+ unsigned int class = sk_run_filter(skb, ptp_filter);
+ unsigned long flags;
+ u16 seqid;
+ u8 mtype;
+
+ if (class == PTP_CLASS_NONE)
+ return 0;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ cpts_fifo_read(cpts, CPTS_EV_PUSH);
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ if (event_expired(event)) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ continue;
+ }
+ mtype = (event->high >> MESSAGE_TYPE_SHIFT) & MESSAGE_TYPE_MASK;
+ seqid = (event->high >> SEQUENCE_ID_SHIFT) & SEQUENCE_ID_MASK;
+ if (ev_type == event_type(event) &&
+ cpts_match(skb, class, seqid, mtype)) {
+ ns = timecounter_cyc2time(&cpts->tc, event->low);
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ return ns;
+}
+
+void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+ u64 ns;
+ struct skb_shared_hwtstamps *ssh;
+
+ if (!cpts->rx_enable)
+ return;
+ ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
+ if (!ns)
+ return;
+ ssh = skb_hwtstamps(skb);
+ memset(ssh, 0, sizeof(*ssh));
+ ssh->hwtstamp = ns_to_ktime(ns);
+}
+
+void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+ u64 ns;
+ struct skb_shared_hwtstamps ssh;
+
+ if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+ return;
+ ns = cpts_find_ts(cpts, skb, CPTS_EV_TX);
+ if (!ns)
+ return;
+ memset(&ssh, 0, sizeof(ssh));
+ ssh.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &ssh);
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+int cpts_register(struct device *dev, struct cpts *cpts,
+ u32 mult, u32 shift)
+{
+#ifdef CONFIG_TI_CPTS
+ int err, i;
+ unsigned long flags;
+
+ if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+ pr_err("cpts: bad ptp filter\n");
+ return -EINVAL;
+ }
+ cpts->info = cpts_info;
+ cpts->clock = ptp_clock_register(&cpts->info, dev);
+ if (IS_ERR(cpts->clock)) {
+ err = PTR_ERR(cpts->clock);
+ cpts->clock = NULL;
+ return err;
+ }
+ spin_lock_init(&cpts->lock);
+
+ cpts->cc.read = cpts_systim_read;
+ cpts->cc.mask = CLOCKSOURCE_MASK(32);
+ cpts->cc_mult = mult;
+ cpts->cc.mult = mult;
+ cpts->cc.shift = shift;
+
+ INIT_LIST_HEAD(&cpts->events);
+ INIT_LIST_HEAD(&cpts->pool);
+ for (i = 0; i < CPTS_MAX_EVENTS; i++)
+ list_add(&cpts->pool_data[i].list, &cpts->pool);
+
+ cpts_clk_init(cpts);
+ cpts_write32(cpts, CPTS_EN, control);
+ cpts_write32(cpts, TS_PEND_EN, int_enable);
+
+ spin_lock_irqsave(&cpts->lock, flags);
+ timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
+ schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+
+ cpts->phc_index = ptp_clock_index(cpts->clock);
+#endif
+ return 0;
+}
+
+void cpts_unregister(struct cpts *cpts)
+{
+#ifdef CONFIG_TI_CPTS
+ if (cpts->clock) {
+ ptp_clock_unregister(cpts->clock);
+ cancel_delayed_work_sync(&cpts->overflow_work);
+ }
+ if (cpts->refclk)
+ cpts_clk_release(cpts);
+#endif
+}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
new file mode 100644
index 000000000000..e1bba3a496b2
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -0,0 +1,146 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@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.
+ *
+ * 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 _TI_CPTS_H_
+#define _TI_CPTS_H_
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/skbuff.h>
+
+struct cpsw_cpts {
+ u32 idver; /* Identification and version */
+ u32 control; /* Time sync control */
+ u32 res1;
+ u32 ts_push; /* Time stamp event push */
+ u32 ts_load_val; /* Time stamp load value */
+ u32 ts_load_en; /* Time stamp load enable */
+ u32 res2[2];
+ u32 intstat_raw; /* Time sync interrupt status raw */
+ u32 intstat_masked; /* Time sync interrupt status masked */
+ u32 int_enable; /* Time sync interrupt enable */
+ u32 res3;
+ u32 event_pop; /* Event interrupt pop */
+ u32 event_low; /* 32 Bit Event Time Stamp */
+ u32 event_high; /* Event Type Fields */
+};
+
+/* Bit definitions for the IDVER register */
+#define TX_IDENT_SHIFT (16) /* TX Identification Value */
+#define TX_IDENT_MASK (0xffff)
+#define RTL_VER_SHIFT (11) /* RTL Version Value */
+#define RTL_VER_MASK (0x1f)
+#define MAJOR_VER_SHIFT (8) /* Major Version Value */
+#define MAJOR_VER_MASK (0x7)
+#define MINOR_VER_SHIFT (0) /* Minor Version Value */
+#define MINOR_VER_MASK (0xff)
+
+/* Bit definitions for the CONTROL register */
+#define HW4_TS_PUSH_EN (1<<11) /* Hardware push 4 enable */
+#define HW3_TS_PUSH_EN (1<<10) /* Hardware push 3 enable */
+#define HW2_TS_PUSH_EN (1<<9) /* Hardware push 2 enable */
+#define HW1_TS_PUSH_EN (1<<8) /* Hardware push 1 enable */
+#define INT_TEST (1<<1) /* Interrupt Test */
+#define CPTS_EN (1<<0) /* Time Sync Enable */
+
+/*
+ * Definitions for the single bit resisters:
+ * TS_PUSH TS_LOAD_EN INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
+ */
+#define TS_PUSH (1<<0) /* Time stamp event push */
+#define TS_LOAD_EN (1<<0) /* Time Stamp Load */
+#define TS_PEND_RAW (1<<0) /* int read (before enable) */
+#define TS_PEND (1<<0) /* masked interrupt read (after enable) */
+#define TS_PEND_EN (1<<0) /* masked interrupt enable */
+#define EVENT_POP (1<<0) /* writing discards one event */
+
+/* Bit definitions for the EVENT_HIGH register */
+#define PORT_NUMBER_SHIFT (24) /* Indicates Ethernet port or HW pin */
+#define PORT_NUMBER_MASK (0x1f)
+#define EVENT_TYPE_SHIFT (20) /* Time sync event type */
+#define EVENT_TYPE_MASK (0xf)
+#define MESSAGE_TYPE_SHIFT (16) /* PTP message type */
+#define MESSAGE_TYPE_MASK (0xf)
+#define SEQUENCE_ID_SHIFT (0) /* PTP message sequence ID */
+#define SEQUENCE_ID_MASK (0xffff)
+
+enum {
+ CPTS_EV_PUSH, /* Time Stamp Push Event */
+ CPTS_EV_ROLL, /* Time Stamp Rollover Event */
+ CPTS_EV_HALF, /* Time Stamp Half Rollover Event */
+ CPTS_EV_HW, /* Hardware Time Stamp Push Event */
+ CPTS_EV_RX, /* Ethernet Receive Event */
+ CPTS_EV_TX, /* Ethernet Transmit Event */
+};
+
+/* This covers any input clock up to about 500 MHz. */
+#define CPTS_OVERFLOW_PERIOD (HZ * 8)
+
+#define CPTS_FIFO_DEPTH 16
+#define CPTS_MAX_EVENTS 32
+
+struct cpts_event {
+ struct list_head list;
+ unsigned long tmo;
+ u32 high;
+ u32 low;
+};
+
+struct cpts {
+ struct cpsw_cpts __iomem *reg;
+ int tx_enable;
+ int rx_enable;
+#ifdef CONFIG_TI_CPTS
+ struct ptp_clock_info info;
+ struct ptp_clock *clock;
+ spinlock_t lock; /* protects time registers */
+ u32 cc_mult; /* for the nominal frequency */
+ struct cyclecounter cc;
+ struct timecounter tc;
+ struct delayed_work overflow_work;
+ int phc_index;
+ struct clk *refclk;
+ unsigned long freq;
+ struct list_head events;
+ struct list_head pool;
+ struct cpts_event pool_data[CPTS_MAX_EVENTS];
+#endif
+};
+
+#ifdef CONFIG_TI_CPTS
+extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+#else
+static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+#endif
+
+extern int cpts_register(struct device *dev, struct cpts *cpts,
+ u32 mult, u32 shift);
+extern void cpts_unregister(struct cpts *cpts);
+
+#endif
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index fce89a0ab06e..2a3e2c56bc60 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1850,7 +1850,7 @@ static struct emac_platform_data
* resource information from platform init and register a network device
* and allocate resources necessary for driver to perform
*/
-static int __devinit davinci_emac_probe(struct platform_device *pdev)
+static int davinci_emac_probe(struct platform_device *pdev)
{
int rc = 0;
struct resource *res;
@@ -2039,7 +2039,7 @@ no_ndev:
* Called when removing the device driver. We disable clock usage and release
* the resources taken up by the driver and unregister network device
*/
-static int __devexit davinci_emac_remove(struct platform_device *pdev)
+static int davinci_emac_remove(struct platform_device *pdev)
{
struct resource *res;
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -2107,7 +2107,7 @@ static struct platform_driver davinci_emac_driver = {
.of_match_table = of_match_ptr(davinci_emac_of_match),
},
.probe = davinci_emac_probe,
- .remove = __devexit_p(davinci_emac_remove),
+ .remove = davinci_emac_remove,
};
/**
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 51a96dbee9ac..cca25509b039 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -310,7 +310,7 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
}
-static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+static int davinci_mdio_probe(struct platform_device *pdev)
{
struct mdio_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
@@ -416,7 +416,7 @@ bail_out:
return ret;
}
-static int __devexit davinci_mdio_remove(struct platform_device *pdev)
+static int davinci_mdio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct davinci_mdio_data *data = dev_get_drvdata(dev);
@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
u32 ctrl;
spin_lock(&data->lock);
- pm_runtime_put_sync(data->dev);
+ pm_runtime_get_sync(data->dev);
/* restart the scan state machine */
ctrl = __raw_readl(&data->regs->control);
@@ -496,7 +496,7 @@ static struct platform_driver davinci_mdio_driver = {
.of_match_table = of_match_ptr(davinci_mdio_of_mtable),
},
.probe = davinci_mdio_probe,
- .remove = __devexit_p(davinci_mdio_remove),
+ .remove = davinci_mdio_remove,
};
static int __init davinci_mdio_init(void)
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 3e6abf0f2771..22725386c5de 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -300,7 +300,7 @@ these functions are more or less common to all linux network drivers.
**************************************************************/
-static void __devexit tlan_remove_one(struct pci_dev *pdev)
+static void tlan_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct tlan_priv *priv = netdev_priv(dev);
@@ -392,7 +392,7 @@ static struct pci_driver tlan_driver = {
.name = "tlan",
.id_table = tlan_pci_tbl,
.probe = tlan_init_one,
- .remove = __devexit_p(tlan_remove_one),
+ .remove = tlan_remove_one,
.suspend = tlan_suspend,
.resume = tlan_resume,
};
@@ -434,7 +434,7 @@ err_out_pci_free:
}
-static int __devinit tlan_init_one(struct pci_dev *pdev,
+static int tlan_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
return tlan_probe1(pdev, -1, -1, 0, ent);
@@ -460,9 +460,8 @@ static int __devinit tlan_init_one(struct pci_dev *pdev,
*
**************************************************************/
-static int __devinit tlan_probe1(struct pci_dev *pdev,
- long ioaddr, int irq, int rev,
- const struct pci_device_id *ent)
+static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 5ee82a77723b..e321d0b6fc88 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -234,10 +234,9 @@ static void gelic_card_free_chain(struct gelic_card *card,
*
* returns 0 on success, <0 on failure
*/
-static int __devinit gelic_card_init_chain(struct gelic_card *card,
- struct gelic_descr_chain *chain,
- struct gelic_descr *start_descr,
- int no)
+static int gelic_card_init_chain(struct gelic_card *card,
+ struct gelic_descr_chain *chain,
+ struct gelic_descr *start_descr, int no)
{
int i;
struct gelic_descr *descr;
@@ -428,7 +427,7 @@ rewind:
*
* returns 0 on success, < 0 on failure
*/
-static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card)
+static int gelic_card_alloc_rx_skbs(struct gelic_card *card)
{
struct gelic_descr_chain *chain;
int ret;
@@ -1468,8 +1467,8 @@ static const struct net_device_ops gelic_netdevice_ops = {
*
* fills out function pointers in the net_device structure
*/
-static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
- struct napi_struct *napi)
+static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
+ struct napi_struct *napi)
{
netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
/* NAPI */
@@ -1489,8 +1488,7 @@ static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
* gelic_ether_setup_netdev initializes the net_device structure
* and register it.
**/
-int __devinit gelic_net_setup_netdev(struct net_device *netdev,
- struct gelic_card *card)
+int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
{
int status;
u64 v1, v2;
@@ -1542,7 +1540,7 @@ int __devinit gelic_net_setup_netdev(struct net_device *netdev,
* the card and net_device structures are linked to each other
*/
#define GELIC_ALIGN (32)
-static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev)
+static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
{
struct gelic_card *card;
struct gelic_port *port;
@@ -1593,7 +1591,7 @@ static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **ne
return card;
}
-static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
+static void gelic_card_get_vlan_info(struct gelic_card *card)
{
u64 v1, v2;
int status;
@@ -1667,7 +1665,7 @@ static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
/**
* ps3_gelic_driver_probe - add a device to the control of this driver
*/
-static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
+static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
{
struct gelic_card *card;
struct net_device *netdev;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 961c8321451f..d568af1eb4f4 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
if (rsn)
*buf++ = WLAN_EID_RSN;
else
- *buf++ = WLAN_EID_GENERIC;
+ *buf++ = WLAN_EID_VENDOR_SPECIFIC;
/* length filed; set later */
buf++;
@@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
break;
switch (item_id) {
- case WLAN_EID_GENERIC:
+ case WLAN_EID_VENDOR_SPECIFIC:
if ((OUI_LEN + 1 <= item_len) &&
!memcmp(pos, wpa_oui, OUI_LEN) &&
pos[OUI_LEN] == 0x01) {
@@ -2305,7 +2305,7 @@ static const struct iw_handler_def gelic_wl_wext_handler_def = {
.get_wireless_stats = gelic_wl_get_wireless_stats,
};
-static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
+static struct net_device *gelic_wl_alloc(struct gelic_card *card)
{
struct net_device *netdev;
struct gelic_port *port;
@@ -2582,7 +2582,7 @@ static const struct ethtool_ops gelic_wl_ethtool_ops = {
.get_link = gelic_wl_get_link,
};
-static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
+static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
{
struct gelic_wl_info *wl;
wl = port_wl(netdev_priv(netdev));
@@ -2598,7 +2598,7 @@ static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
/*
* driver probe/remove
*/
-int __devinit gelic_wl_driver_probe(struct gelic_card *card)
+int gelic_wl_driver_probe(struct gelic_card *card)
{
int ret;
struct net_device *netdev;
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index c1ebfe9efcb3..f1b91fd7e41c 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2492,7 +2492,7 @@ out_disable_dev:
* spider_net_probe initializes pdev and registers a net_device
* structure for it. After that, the device can be ifconfig'ed up
**/
-static int __devinit
+static int
spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int err = -EIO;
@@ -2531,7 +2531,7 @@ out:
* spider_net_remove is called to remove the device and unregisters the
* net_device
**/
-static void __devexit
+static void
spider_net_remove(struct pci_dev *pdev)
{
struct net_device *netdev;
@@ -2559,7 +2559,7 @@ static struct pci_driver spider_net_driver = {
.name = spider_net_driver_name,
.id_table = spider_net_pci_tbl,
.probe = spider_net_probe,
- .remove = __devexit_p(spider_net_remove)
+ .remove = spider_net_remove
};
/**
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 651a70c55e6e..9819349eaa1e 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -60,7 +60,7 @@ enum tc35815_chiptype {
/* indexed by tc35815_chiptype, above */
static const struct {
const char *name;
-} chip_info[] __devinitdata = {
+} chip_info[] = {
{ "TOSHIBA TC35815CF 10/100BaseTX" },
{ "TOSHIBA TC35815 with Wake on LAN" },
{ "TOSHIBA TC35815/TX4939" },
@@ -719,7 +719,7 @@ err_out:
* should provide a "tc35815-mac" device with a MAC address in its
* platform_data.
*/
-static int __devinit tc35815_mac_match(struct device *dev, void *data)
+static int tc35815_mac_match(struct device *dev, void *data)
{
struct platform_device *plat_dev = to_platform_device(dev);
struct pci_dev *pci_dev = data;
@@ -727,7 +727,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data)
return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
}
-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+static int tc35815_read_plat_dev_addr(struct net_device *dev)
{
struct tc35815_local *lp = netdev_priv(dev);
struct device *pd = bus_find_device(&platform_bus_type, NULL,
@@ -741,13 +741,13 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
return -ENODEV;
}
#else
-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+static int tc35815_read_plat_dev_addr(struct net_device *dev)
{
return -ENODEV;
}
#endif
-static int __devinit tc35815_init_dev_addr(struct net_device *dev)
+static int tc35815_init_dev_addr(struct net_device *dev)
{
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
@@ -785,8 +785,8 @@ static const struct net_device_ops tc35815_netdev_ops = {
#endif
};
-static int __devinit tc35815_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int tc35815_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
void __iomem *ioaddr = NULL;
struct net_device *dev;
@@ -878,7 +878,7 @@ err_out:
}
-static void __devexit tc35815_remove_one(struct pci_dev *pdev)
+static void tc35815_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct tc35815_local *lp = netdev_priv(dev);
@@ -2198,7 +2198,7 @@ static struct pci_driver tc35815_pci_driver = {
.name = MODNAME,
.id_table = tc35815_pci_tbl,
.probe = tc35815_init_one,
- .remove = __devexit_p(tc35815_remove_one),
+ .remove = tc35815_remove_one,
#ifdef CONFIG_PM
.suspend = tc35815_suspend,
.resume = tc35815_resume,
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 0459c096629f..7992b3e05d3d 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -113,7 +113,7 @@ static const int multicast_filter_limit = 32;
#include <linux/dmi.h>
/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
"v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker";
/* This driver was written to use PCI memory space. Some early versions
@@ -657,7 +657,7 @@ static void enable_mmio(long pioaddr, u32 quirks)
* Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
* (plus 0x6C for Rhine-I/II)
*/
-static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
+static void rhine_reload_eeprom(long pioaddr, struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
@@ -823,7 +823,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
return work_done;
}
-static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
+static void rhine_hw_init(struct net_device *dev, long pioaddr)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -856,8 +856,7 @@ static const struct net_device_ops rhine_netdev_ops = {
#endif
};
-static int __devinit rhine_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct rhine_private *rp;
@@ -2232,7 +2231,7 @@ static int rhine_close(struct net_device *dev)
}
-static void __devexit rhine_remove_one(struct pci_dev *pdev)
+static void rhine_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
@@ -2359,7 +2358,7 @@ static struct pci_driver rhine_driver = {
.name = DRV_NAME,
.id_table = rhine_pci_tbl,
.probe = rhine_init_one,
- .remove = __devexit_p(rhine_remove_one),
+ .remove = rhine_remove_one,
.shutdown = rhine_shutdown,
.driver.pm = RHINE_PM_OPS,
};
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index a46c19859683..1bc7f9fd2583 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table);
* Given a chip identifier return a suitable description. Returns
* a pointer a static string valid while the driver is loaded.
*/
-static const char __devinit *get_chip_name(enum chip_type chip_id)
+static const char *get_chip_name(enum chip_type chip_id)
{
int i;
for (i = 0; chip_info_table[i].name != NULL; i++)
@@ -392,7 +392,7 @@ static const char __devinit *get_chip_name(enum chip_type chip_id)
* unload for each active device that is present. Disconnects
* the device from the network layer and frees all the resources
*/
-static void __devexit velocity_remove1(struct pci_dev *pdev)
+static void velocity_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct velocity_info *vptr = netdev_priv(dev);
@@ -421,7 +421,8 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
+static void velocity_set_int_opt(int *opt, int val, int min, int max, int def,
+ char *name, const char *devname)
{
if (val == -1)
*opt = def;
@@ -449,7 +450,8 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max,
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
+static void velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag,
+ char *name, const char *devname)
{
(*opt) &= (~flag);
if (val == -1)
@@ -474,7 +476,8 @@ static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag
* Turn the module and command options into a single structure
* for the current device
*/
-static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
+static void velocity_get_options(struct velocity_opt *opts, int index,
+ const char *devname)
{
velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
@@ -2627,9 +2630,8 @@ static const struct net_device_ops velocity_netdev_ops = {
* Set up the initial velocity_info struct for the device that has been
* discovered.
*/
-static void __devinit velocity_init_info(struct pci_dev *pdev,
- struct velocity_info *vptr,
- const struct velocity_info_tbl *info)
+static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
+ const struct velocity_info_tbl *info)
{
memset(vptr, 0, sizeof(struct velocity_info));
@@ -2648,7 +2650,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
* Retrieve the PCI configuration space data that interests us from
* the kernel PCI layer
*/
-static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
+static int velocity_get_pci_info(struct velocity_info *vptr,
+ struct pci_dev *pdev)
{
vptr->rev_id = pdev->revision;
@@ -2685,7 +2688,7 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
* Print per driver data as the kernel driver finds Velocity
* hardware
*/
-static void __devinit velocity_print_info(struct velocity_info *vptr)
+static void velocity_print_info(struct velocity_info *vptr)
{
struct net_device *dev = vptr->dev;
@@ -2709,7 +2712,8 @@ static u32 velocity_get_link(struct net_device *dev)
* Configure a discovered adapter from scratch. Return a negative
* errno error code on failure paths.
*/
-static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int velocity_found1(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int first = 1;
struct net_device *dev;
@@ -3108,7 +3112,7 @@ static struct pci_driver velocity_driver = {
.name = VELOCITY_NAME,
.id_table = velocity_id_table,
.probe = velocity_found1,
- .remove = __devexit_p(velocity_remove1),
+ .remove = velocity_remove1,
#ifdef CONFIG_PM
.suspend = velocity_suspend,
.resume = velocity_resume,
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 2c08bf6e7bf3..352383890326 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -580,8 +580,6 @@ static int w5100_open(struct net_device *ndev)
struct w5100_priv *priv = netdev_priv(ndev);
netif_info(priv, ifup, ndev, "enabling\n");
- if (!is_valid_ether_addr(ndev->dev_addr))
- return -EINVAL;
w5100_hw_start(priv);
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -623,7 +621,7 @@ static const struct net_device_ops w5100_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit w5100_hw_probe(struct platform_device *pdev)
+static int w5100_hw_probe(struct platform_device *pdev)
{
struct wiznet_platform_data *data = pdev->dev.platform_data;
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -698,7 +696,7 @@ static int __devinit w5100_hw_probe(struct platform_device *pdev)
return 0;
}
-static int __devinit w5100_probe(struct platform_device *pdev)
+static int w5100_probe(struct platform_device *pdev)
{
struct w5100_priv *priv;
struct net_device *ndev;
@@ -741,7 +739,7 @@ err_register:
return err;
}
-static int __devexit w5100_remove(struct platform_device *pdev)
+static int w5100_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct w5100_priv *priv = netdev_priv(ndev);
@@ -801,7 +799,7 @@ static struct platform_driver w5100_driver = {
.pm = &w5100_pm_ops,
},
.probe = w5100_probe,
- .remove = __devexit_p(w5100_remove),
+ .remove = w5100_remove,
};
module_platform_driver(w5100_driver);
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 88943d90c765..9d1d986f8d40 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -500,8 +500,6 @@ static int w5300_open(struct net_device *ndev)
struct w5300_priv *priv = netdev_priv(ndev);
netif_info(priv, ifup, ndev, "enabling\n");
- if (!is_valid_ether_addr(ndev->dev_addr))
- return -EINVAL;
w5300_hw_start(priv);
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -543,7 +541,7 @@ static const struct net_device_ops w5300_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static int __devinit w5300_hw_probe(struct platform_device *pdev)
+static int w5300_hw_probe(struct platform_device *pdev)
{
struct wiznet_platform_data *data = pdev->dev.platform_data;
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -610,7 +608,7 @@ static int __devinit w5300_hw_probe(struct platform_device *pdev)
return 0;
}
-static int __devinit w5300_probe(struct platform_device *pdev)
+static int w5300_probe(struct platform_device *pdev)
{
struct w5300_priv *priv;
struct net_device *ndev;
@@ -653,7 +651,7 @@ err_register:
return err;
}
-static int __devexit w5300_remove(struct platform_device *pdev)
+static int w5300_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct w5300_priv *priv = netdev_priv(ndev);
@@ -713,7 +711,7 @@ static struct platform_driver w5300_driver = {
.pm = &w5300_pm_ops,
},
.probe = w5300_probe,
- .remove = __devexit_p(w5300_remove),
+ .remove = w5300_remove,
};
module_platform_driver(w5300_driver);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index f8e351880119..aad909d793d7 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1002,7 +1002,7 @@ static const struct ethtool_ops temac_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
-static int __devinit temac_of_probe(struct platform_device *op)
+static int temac_of_probe(struct platform_device *op)
{
struct device_node *np;
struct temac_local *lp;
@@ -1144,7 +1144,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
return rc;
}
-static int __devexit temac_of_remove(struct platform_device *op)
+static int temac_of_remove(struct platform_device *op)
{
struct net_device *ndev = dev_get_drvdata(&op->dev);
struct temac_local *lp = netdev_priv(ndev);
@@ -1163,7 +1163,7 @@ static int __devexit temac_of_remove(struct platform_device *op)
return 0;
}
-static struct of_device_id temac_of_match[] __devinitdata = {
+static struct of_device_id temac_of_match[] = {
{ .compatible = "xlnx,xps-ll-temac-1.01.b", },
{ .compatible = "xlnx,xps-ll-temac-2.00.a", },
{ .compatible = "xlnx,xps-ll-temac-2.02.a", },
@@ -1174,7 +1174,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match);
static struct platform_driver temac_of_driver = {
.probe = temac_of_probe,
- .remove = __devexit_p(temac_of_remove),
+ .remove = temac_of_remove,
.driver = {
.owner = THIS_MODULE,
.name = "xilinx_temac",
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index a788501e978e..d9f69b82cc4f 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -48,7 +48,7 @@
#define AXIENET_REGS_N 32
/* Match table for of_platform binding */
-static struct of_device_id axienet_of_match[] __devinitdata = {
+static struct of_device_id axienet_of_match[] = {
{ .compatible = "xlnx,axi-ethernet-1.00.a", },
{ .compatible = "xlnx,axi-ethernet-1.01.a", },
{ .compatible = "xlnx,axi-ethernet-2.01.a", },
@@ -1482,7 +1482,7 @@ static void axienet_dma_err_handler(unsigned long data)
* device. Parses through device tree and populates fields of
* axienet_local. It registers the Ethernet device.
*/
-static int __devinit axienet_of_probe(struct platform_device *op)
+static int axienet_of_probe(struct platform_device *op)
{
__be32 *p;
int size, ret = 0;
@@ -1632,7 +1632,7 @@ nodev:
return ret;
}
-static int __devexit axienet_of_remove(struct platform_device *op)
+static int axienet_of_remove(struct platform_device *op)
{
struct net_device *ndev = dev_get_drvdata(&op->dev);
struct axienet_local *lp = netdev_priv(ndev);
@@ -1656,7 +1656,7 @@ static int __devexit axienet_of_remove(struct platform_device *op)
static struct platform_driver axienet_of_driver = {
.probe = axienet_of_probe,
- .remove = __devexit_p(axienet_of_remove),
+ .remove = axienet_of_remove,
.driver = {
.owner = THIS_MODULE,
.name = "xilinx_axienet",
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 77cfe5110318..919b983114e9 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1107,7 +1107,7 @@ static struct net_device_ops xemaclite_netdev_ops;
* Return: 0, if the driver is bound to the Emaclite device, or
* a negative error if there is failure.
*/
-static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
+static int xemaclite_of_probe(struct platform_device *ofdev)
{
struct resource r_irq; /* Interrupt resources */
struct resource r_mem; /* IO mem resources */
@@ -1229,7 +1229,7 @@ error2:
*
* Return: 0, always.
*/
-static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
+static int xemaclite_of_remove(struct platform_device *of_dev)
{
struct device *dev = &of_dev->dev;
struct net_device *ndev = dev_get_drvdata(dev);
@@ -1280,7 +1280,7 @@ static struct net_device_ops xemaclite_netdev_ops = {
};
/* Match table for OF platform binding */
-static struct of_device_id xemaclite_of_match[] __devinitdata = {
+static struct of_device_id xemaclite_of_match[] = {
{ .compatible = "xlnx,opb-ethernetlite-1.01.a", },
{ .compatible = "xlnx,opb-ethernetlite-1.01.b", },
{ .compatible = "xlnx,xps-ethernetlite-1.00.a", },
@@ -1298,7 +1298,7 @@ static struct platform_driver xemaclite_of_driver = {
.of_match_table = xemaclite_of_match,
},
.probe = xemaclite_of_probe,
- .remove = __devexit_p(xemaclite_of_remove),
+ .remove = xemaclite_of_remove,
};
module_platform_driver(xemaclite_of_driver);
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 477d6729b17f..d3ebb73277be 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1379,7 +1379,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit eth_init_one(struct platform_device *pdev)
+static int eth_init_one(struct platform_device *pdev)
{
struct port *port;
struct net_device *dev;
@@ -1480,7 +1480,7 @@ err_free:
return err;
}
-static int __devexit eth_remove_one(struct platform_device *pdev)
+static int eth_remove_one(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct port *port = netdev_priv(dev);
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index 6695a1dadf4e..502c8ff1d985 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -228,7 +228,7 @@
#define DRV_VERSION "v1.10"
#define DRV_RELDATE "2006/12/14"
-static char version[] __devinitdata =
+static char version[] =
DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
" Lawrence V. Stefani and others\n";
@@ -515,7 +515,7 @@ static const struct net_device_ops dfx_netdev_ops = {
* initialized and the board resources are read and stored in
* the device structure.
*/
-static int __devinit dfx_register(struct device *bdev)
+static int dfx_register(struct device *bdev)
{
static int version_disp;
int dfx_bus_pci = DFX_BUS_PCI(bdev);
@@ -663,7 +663,7 @@ err_out:
* enabled yet.
*/
-static void __devinit dfx_bus_init(struct net_device *dev)
+static void dfx_bus_init(struct net_device *dev)
{
DFX_board_t *bp = netdev_priv(dev);
struct device *bdev = bp->bus_dev;
@@ -809,7 +809,7 @@ static void __devinit dfx_bus_init(struct net_device *dev)
* Interrupts are disabled at the adapter bus-specific logic.
*/
-static void __devexit dfx_bus_uninit(struct net_device *dev)
+static void dfx_bus_uninit(struct net_device *dev)
{
DFX_board_t *bp = netdev_priv(dev);
struct device *bdev = bp->bus_dev;
@@ -866,7 +866,7 @@ static void __devexit dfx_bus_uninit(struct net_device *dev)
* None
*/
-static void __devinit dfx_bus_config_check(DFX_board_t *bp)
+static void dfx_bus_config_check(DFX_board_t *bp)
{
struct device __maybe_unused *bdev = bp->bus_dev;
int dfx_bus_eisa = DFX_BUS_EISA(bdev);
@@ -962,9 +962,8 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
* returning from this routine.
*/
-static int __devinit dfx_driver_init(struct net_device *dev,
- const char *print_name,
- resource_size_t bar_start)
+static int dfx_driver_init(struct net_device *dev, const char *print_name,
+ resource_size_t bar_start)
{
DFX_board_t *bp = netdev_priv(dev);
struct device *bdev = bp->bus_dev;
@@ -3579,7 +3578,7 @@ static void dfx_xmt_flush( DFX_board_t *bp )
* Device structures for FDDI adapters (fddi0, fddi1, etc) are
* freed.
*/
-static void __devexit dfx_unregister(struct device *bdev)
+static void dfx_unregister(struct device *bdev)
{
struct net_device *dev = dev_get_drvdata(bdev);
DFX_board_t *bp = netdev_priv(dev);
@@ -3619,13 +3618,12 @@ static void __devexit dfx_unregister(struct device *bdev)
}
-static int __devinit __maybe_unused dfx_dev_register(struct device *);
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
+static int __maybe_unused dfx_dev_register(struct device *);
+static int __maybe_unused dfx_dev_unregister(struct device *);
#ifdef CONFIG_PCI
-static int __devinit dfx_pci_register(struct pci_dev *,
- const struct pci_device_id *);
-static void __devexit dfx_pci_unregister(struct pci_dev *);
+static int dfx_pci_register(struct pci_dev *, const struct pci_device_id *);
+static void dfx_pci_unregister(struct pci_dev *);
static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
@@ -3637,16 +3635,16 @@ static struct pci_driver dfx_pci_driver = {
.name = "defxx",
.id_table = dfx_pci_table,
.probe = dfx_pci_register,
- .remove = __devexit_p(dfx_pci_unregister),
+ .remove = dfx_pci_unregister,
};
-static __devinit int dfx_pci_register(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int dfx_pci_register(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
return dfx_register(&pdev->dev);
}
-static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
+static void dfx_pci_unregister(struct pci_dev *pdev)
{
dfx_unregister(&pdev->dev);
}
@@ -3668,7 +3666,7 @@ static struct eisa_driver dfx_eisa_driver = {
.name = "defxx",
.bus = &eisa_bus_type,
.probe = dfx_dev_register,
- .remove = __devexit_p(dfx_dev_unregister),
+ .remove = dfx_dev_unregister,
},
};
#endif /* CONFIG_EISA */
@@ -3689,12 +3687,12 @@ static struct tc_driver dfx_tc_driver = {
.name = "defxx",
.bus = &tc_bus_type,
.probe = dfx_dev_register,
- .remove = __devexit_p(dfx_dev_unregister),
+ .remove = dfx_dev_unregister,
},
};
#endif /* CONFIG_TC */
-static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
+static int __maybe_unused dfx_dev_register(struct device *dev)
{
int status;
@@ -3704,7 +3702,7 @@ static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
return status;
}
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
+static int __maybe_unused dfx_dev_unregister(struct device *dev)
{
put_device(dev);
dfx_unregister(dev);
@@ -3712,7 +3710,7 @@ static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
}
-static int __devinit dfx_init(void)
+static int dfx_init(void)
{
int status;
@@ -3724,7 +3722,7 @@ static int __devinit dfx_init(void)
return status;
}
-static void __devexit dfx_cleanup(void)
+static void dfx_cleanup(void)
{
tc_unregister_driver(&dfx_tc_driver);
eisa_driver_unregister(&dfx_eisa_driver);
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index 3d9a4596a423..d5bd563ac131 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -321,7 +321,7 @@ err_out1:
/*
* Called for each adapter board from pci_unregister_driver
*/
-static void __devexit skfp_remove_one(struct pci_dev *pdev)
+static void skfp_remove_one(struct pci_dev *pdev)
{
struct net_device *p = pci_get_drvdata(pdev);
struct s_smc *lp = netdev_priv(p);
@@ -2243,7 +2243,7 @@ static struct pci_driver skfddi_pci_driver = {
.name = "skfddi",
.id_table = skfddi_pci_tbl,
.probe = skfp_init_one,
- .remove = __devexit_p(skfp_remove_one),
+ .remove = skfp_remove_one,
};
static int __init skfd_init(void)
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
index d4719632ffc6..e5b19b056909 100644
--- a/drivers/net/hippi/rrunner.c
+++ b/drivers/net/hippi/rrunner.c
@@ -61,7 +61,7 @@ MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
MODULE_LICENSE("GPL");
-static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
+static char version[] = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
static const struct net_device_ops rr_netdev_ops = {
@@ -88,8 +88,7 @@ static const struct net_device_ops rr_netdev_ops = {
* stack will need to know about I/O vectors or something similar.
*/
-static int __devinit rr_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
static int version_disp;
@@ -221,7 +220,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
return ret;
}
-static void __devexit rr_remove_one (struct pci_dev *pdev)
+static void rr_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rr_private *rr = netdev_priv(dev);
@@ -503,7 +502,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv,
}
-static int __devinit rr_init(struct net_device *dev)
+static int rr_init(struct net_device *dev)
{
struct rr_private *rrpriv;
struct rr_regs __iomem *regs;
@@ -1681,7 +1680,7 @@ static struct pci_driver rr_driver = {
.name = "rrunner",
.id_table = rr_pci_tbl,
.probe = rr_init_one,
- .remove = __devexit_p(rr_remove_one),
+ .remove = rr_remove_one,
};
static int __init rr_init_module(void)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 928148cc3220..2b657d4d63a8 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -363,11 +363,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
rndis_pkt = &msg->msg.pkt;
- /*
- * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
- * netvsc packet (ie TotalDataBufferLength != MessageLength)
- */
-
/* Remove the rndis header and pass it back up the stack */
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
@@ -610,8 +605,11 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
return -EBUSY;
} else {
set_complete = &request->response_msg.msg.set_complete;
- if (set_complete->status != RNDIS_STATUS_SUCCESS)
+ if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+ netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+ set_complete->status);
ret = -EINVAL;
+ }
}
cleanup:
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index ba753d87a32f..a4a62e170ec0 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -778,7 +778,7 @@ static int at86rf230_fill_data(struct spi_device *spi)
return 0;
}
-static int __devinit at86rf230_probe(struct spi_device *spi)
+static int at86rf230_probe(struct spi_device *spi)
{
struct ieee802154_dev *dev;
struct at86rf230_local *lp;
@@ -920,7 +920,7 @@ err_fill:
return rc;
}
-static int __devexit at86rf230_remove(struct spi_device *spi)
+static int at86rf230_remove(struct spi_device *spi)
{
struct at86rf230_local *lp = spi_get_drvdata(spi);
@@ -947,7 +947,7 @@ static struct spi_driver at86rf230_driver = {
.owner = THIS_MODULE,
},
.probe = at86rf230_probe,
- .remove = __devexit_p(at86rf230_remove),
+ .remove = at86rf230_remove,
.suspend = at86rf230_suspend,
.resume = at86rf230_resume,
};
diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
index 7d39add7d467..1e9cb0bbf62c 100644
--- a/drivers/net/ieee802154/fakehard.c
+++ b/drivers/net/ieee802154/fakehard.c
@@ -354,7 +354,7 @@ static void ieee802154_fake_setup(struct net_device *dev)
}
-static int __devinit ieee802154fake_probe(struct platform_device *pdev)
+static int ieee802154fake_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct fakehard_priv *priv;
@@ -412,7 +412,7 @@ out:
return err;
}
-static int __devexit ieee802154fake_remove(struct platform_device *pdev)
+static int ieee802154fake_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_netdev(dev);
@@ -423,7 +423,7 @@ static struct platform_device *ieee802154fake_dev;
static struct platform_driver ieee802154fake_driver = {
.probe = ieee802154fake_probe,
- .remove = __devexit_p(ieee802154fake_remove),
+ .remove = ieee802154fake_remove,
.driver = {
.name = "ieee802154hardmac",
.owner = THIS_MODULE,
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index e7456fcd0913..b8d22173925d 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -221,7 +221,7 @@ static void fakelb_del(struct fakelb_dev_priv *priv)
ieee802154_free_device(priv->dev);
}
-static int __devinit fakelb_probe(struct platform_device *pdev)
+static int fakelb_probe(struct platform_device *pdev)
{
struct fakelb_priv *priv;
struct fakelb_dev_priv *dp;
@@ -253,7 +253,7 @@ err_alloc:
return err;
}
-static int __devexit fakelb_remove(struct platform_device *pdev)
+static int fakelb_remove(struct platform_device *pdev)
{
struct fakelb_priv *priv = platform_get_drvdata(pdev);
struct fakelb_dev_priv *dp, *temp;
@@ -269,7 +269,7 @@ static struct platform_device *ieee802154fake_dev;
static struct platform_driver ieee802154fake_driver = {
.probe = fakelb_probe,
- .remove = __devexit_p(fakelb_remove),
+ .remove = fakelb_remove,
.driver = {
.name = "ieee802154fakelb",
.owner = THIS_MODULE,
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index ed7521693980..3f2c7aaf28c4 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -618,7 +618,7 @@ out:
enable_irq(devrec->spi->irq);
}
-static int __devinit mrf24j40_probe(struct spi_device *spi)
+static int mrf24j40_probe(struct spi_device *spi)
{
int ret = -ENOMEM;
u8 val;
@@ -711,7 +711,7 @@ err_devrec:
return ret;
}
-static int __devexit mrf24j40_remove(struct spi_device *spi)
+static int mrf24j40_remove(struct spi_device *spi)
{
struct mrf24j40 *devrec = dev_get_drvdata(&spi->dev);
@@ -746,7 +746,7 @@ static struct spi_driver mrf24j40_driver = {
},
.id_table = mrf24j40_ids,
.probe = mrf24j40_probe,
- .remove = __devexit_p(mrf24j40_remove),
+ .remove = mrf24j40_remove,
};
static int __init mrf24j40_init(void)
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index e09417df8f39..b5151e4ced61 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -760,7 +760,7 @@ static const struct net_device_ops au1k_irda_netdev_ops = {
.ndo_do_ioctl = au1k_irda_ioctl,
};
-static int __devinit au1k_irda_net_init(struct net_device *dev)
+static int au1k_irda_net_init(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
struct db_dest *pDB, *pDBfree;
@@ -849,7 +849,7 @@ out1:
return retval;
}
-static int __devinit au1k_irda_probe(struct platform_device *pdev)
+static int au1k_irda_probe(struct platform_device *pdev)
{
struct au1k_private *aup;
struct net_device *dev;
@@ -921,7 +921,7 @@ out:
return err;
}
-static int __devexit au1k_irda_remove(struct platform_device *pdev)
+static int au1k_irda_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct au1k_private *aup = netdev_priv(dev);
@@ -949,7 +949,7 @@ static struct platform_driver au1k_irda_driver = {
.owner = THIS_MODULE,
},
.probe = au1k_irda_probe,
- .remove = __devexit_p(au1k_irda_remove),
+ .remove = au1k_irda_remove,
};
static int __init au1k_irda_load(void)
diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c
index c6a0299aa9f9..fed4a05d55c7 100644
--- a/drivers/net/irda/bfin_sir.c
+++ b/drivers/net/irda/bfin_sir.c
@@ -31,7 +31,7 @@ static void turnaround_delay(unsigned long last_jif, int mtt)
schedule_timeout_uninterruptible(ticks);
}
-static void __devinit bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
+static void bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
{
int i;
struct resource *res;
@@ -688,7 +688,7 @@ static const struct net_device_ops bfin_sir_ndo = {
.ndo_get_stats = bfin_sir_stats,
};
-static int __devinit bfin_sir_probe(struct platform_device *pdev)
+static int bfin_sir_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct bfin_sir_self *self;
@@ -775,7 +775,7 @@ err_mem_0:
return err;
}
-static int __devexit bfin_sir_remove(struct platform_device *pdev)
+static int bfin_sir_remove(struct platform_device *pdev)
{
struct bfin_sir_port *sir_port;
struct net_device *dev = NULL;
@@ -798,7 +798,7 @@ static int __devexit bfin_sir_remove(struct platform_device *pdev)
static struct platform_driver bfin_ir_driver = {
.probe = bfin_sir_probe,
- .remove = __devexit_p(bfin_sir_remove),
+ .remove = bfin_sir_remove,
.suspend = bfin_sir_suspend,
.resume = bfin_sir_resume,
.driver = {
diff --git a/drivers/net/irda/ep7211-sir.c b/drivers/net/irda/ep7211-sir.c
index f83c5b881d2d..5fe1f4dd3369 100644
--- a/drivers/net/irda/ep7211-sir.c
+++ b/drivers/net/irda/ep7211-sir.c
@@ -1,52 +1,18 @@
/*
- * IR port driver for the Cirrus Logic EP7211 processor.
+ * IR port driver for the Cirrus Logic CLPS711X processors
*
* Copyright 2001, Blue Mug Inc. All rights reserved.
* Copyright 2007, Samuel Ortiz <samuel@sortiz.org>
*/
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <net/irda/irda.h>
-#include <net/irda/irda_device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
-#include <asm/io.h>
#include <mach/hardware.h>
#include "sir-dev.h"
-#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
-#define MAX_DELAY 10000 /* 1 ms */
-
-static int ep7211_open(struct sir_dev *dev);
-static int ep7211_close(struct sir_dev *dev);
-static int ep7211_change_speed(struct sir_dev *dev, unsigned speed);
-static int ep7211_reset(struct sir_dev *dev);
-
-static struct dongle_driver ep7211 = {
- .owner = THIS_MODULE,
- .driver_name = "EP7211 IR driver",
- .type = IRDA_EP7211_DONGLE,
- .open = ep7211_open,
- .close = ep7211_close,
- .reset = ep7211_reset,
- .set_speed = ep7211_change_speed,
-};
-
-static int __init ep7211_sir_init(void)
-{
- return irda_register_dongle(&ep7211);
-}
-
-static void __exit ep7211_sir_cleanup(void)
-{
- irda_unregister_dongle(&ep7211);
-}
-
-static int ep7211_open(struct sir_dev *dev)
+static int clps711x_dongle_open(struct sir_dev *dev)
{
unsigned int syscon;
@@ -58,7 +24,7 @@ static int ep7211_open(struct sir_dev *dev)
return 0;
}
-static int ep7211_close(struct sir_dev *dev)
+static int clps711x_dongle_close(struct sir_dev *dev)
{
unsigned int syscon;
@@ -70,20 +36,35 @@ static int ep7211_close(struct sir_dev *dev)
return 0;
}
-static int ep7211_change_speed(struct sir_dev *dev, unsigned speed)
+static struct dongle_driver clps711x_dongle = {
+ .owner = THIS_MODULE,
+ .driver_name = "EP7211 IR driver",
+ .type = IRDA_EP7211_DONGLE,
+ .open = clps711x_dongle_open,
+ .close = clps711x_dongle_close,
+};
+
+static int clps711x_sir_probe(struct platform_device *pdev)
{
- return 0;
+ return irda_register_dongle(&clps711x_dongle);
}
-static int ep7211_reset(struct sir_dev *dev)
+static int clps711x_sir_remove(struct platform_device *pdev)
{
- return 0;
+ return irda_unregister_dongle(&clps711x_dongle);
}
+static struct platform_driver clps711x_sir_driver = {
+ .driver = {
+ .name = "sir-clps711x",
+ .owner = THIS_MODULE,
+ },
+ .probe = clps711x_sir_probe,
+ .remove = clps711x_sir_remove,
+};
+module_platform_driver(clps711x_sir_driver);
+
MODULE_AUTHOR("Samuel Ortiz <samuel@sortiz.org>");
MODULE_DESCRIPTION("EP7211 IR dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */
-
-module_init(ep7211_sir_init);
-module_exit(ep7211_sir_cleanup);
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
index 4b746d9bd8e7..9448587de453 100644
--- a/drivers/net/irda/sh_irda.c
+++ b/drivers/net/irda/sh_irda.c
@@ -33,11 +33,7 @@
#define DRIVER_NAME "sh_irda"
-#if defined(CONFIG_ARCH_SH7367) || defined(CONFIG_ARCH_SH7377)
-#define __IRDARAM_LEN 0x13FF
-#else
#define __IRDARAM_LEN 0x1039
-#endif
#define IRTMR 0x1F00 /* Transfer mode */
#define IRCFR 0x1F02 /* Configuration */
@@ -757,7 +753,7 @@ static const struct net_device_ops sh_irda_ndo = {
************************************************************************/
-static int __devinit sh_irda_probe(struct platform_device *pdev)
+static int sh_irda_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct sh_irda_self *self;
@@ -829,7 +825,7 @@ exit:
return err;
}
-static int __devexit sh_irda_remove(struct platform_device *pdev)
+static int sh_irda_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct sh_irda_self *self = netdev_priv(ndev);
@@ -866,7 +862,7 @@ static const struct dev_pm_ops sh_irda_pm_ops = {
static struct platform_driver sh_irda_driver = {
.probe = sh_irda_probe,
- .remove = __devexit_p(sh_irda_remove),
+ .remove = sh_irda_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &sh_irda_pm_ops,
diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c
index 624ac1939e85..24aefcd84065 100644
--- a/drivers/net/irda/sh_sir.c
+++ b/drivers/net/irda/sh_sir.c
@@ -705,7 +705,7 @@ static const struct net_device_ops sh_sir_ndo = {
************************************************************************/
-static int __devinit sh_sir_probe(struct platform_device *pdev)
+static int sh_sir_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct sh_sir_self *self;
@@ -783,7 +783,7 @@ exit:
return err;
}
-static int __devexit sh_sir_remove(struct platform_device *pdev)
+static int sh_sir_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct sh_sir_self *self = netdev_priv(ndev);
@@ -803,7 +803,7 @@ static int __devexit sh_sir_remove(struct platform_device *pdev)
static struct platform_driver sh_sir_driver = {
.probe = sh_sir_probe,
- .remove = __devexit_p(sh_sir_remove),
+ .remove = sh_sir_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index a926813ee91d..5290952b60c2 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -376,8 +376,8 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
static int pnp_driver_registered;
#ifdef CONFIG_PNP
-static int __devinit smsc_ircc_pnp_probe(struct pnp_dev *dev,
- const struct pnp_device_id *dev_id)
+static int smsc_ircc_pnp_probe(struct pnp_dev *dev,
+ const struct pnp_device_id *dev_id)
{
unsigned int firbase, sirbase;
u8 dma, irq;
@@ -515,7 +515,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {
* Try to open driver instance
*
*/
-static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
{
struct smsc_ircc_cb *self;
struct net_device *dev;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 1a89fd459dd5..f9033c6a888c 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -77,7 +77,7 @@ static int dongle_id = 0; /* default: probe */
module_param(dongle_id, int, 0);
/* Some prototypes */
-static int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+static int via_ircc_open(struct pci_dev *pdev, chipio_t *info,
unsigned int id);
static int via_ircc_dma_receive(struct via_ircc_cb *self);
static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
@@ -102,8 +102,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase);
static void hwreset(struct via_ircc_cb *self);
static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase);
static int upload_rxdata(struct via_ircc_cb *self, int iobase);
-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);
-static void __devexit via_remove_one (struct pci_dev *pdev);
+static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id);
+static void via_remove_one(struct pci_dev *pdev);
/* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */
static void iodelay(int udelay)
@@ -132,7 +132,7 @@ static struct pci_driver via_driver = {
.name = VIA_MODULE_NAME,
.id_table = via_pci_tbl,
.probe = via_init_one,
- .remove = __devexit_p(via_remove_one),
+ .remove = via_remove_one,
};
@@ -156,7 +156,7 @@ static int __init via_ircc_init(void)
return 0;
}
-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id)
+static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
{
int rc;
u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1;
@@ -286,8 +286,7 @@ static const struct net_device_ops via_ircc_fir_ops = {
* Open driver instance
*
*/
-static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
- unsigned int id)
+static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id)
{
struct net_device *dev;
struct via_ircc_cb *self;
@@ -424,7 +423,7 @@ static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
* Close driver instance
*
*/
-static void __devexit via_remove_one(struct pci_dev *pdev)
+static void via_remove_one(struct pci_dev *pdev)
{
struct via_ircc_cb *self = pci_get_drvdata(pdev);
int iobase;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 9021d0131727..2f99f8881dfc 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -1627,7 +1627,7 @@ static int vlsi_irda_init(struct net_device *ndev)
/**************************************************************/
-static int __devinit
+static int
vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *ndev;
@@ -1699,7 +1699,7 @@ out:
return -ENODEV;
}
-static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
+static void vlsi_irda_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
vlsi_irda_dev_t *idev;
@@ -1832,7 +1832,7 @@ static struct pci_driver vlsi_irda_driver = {
.name = drivername,
.id_table = vlsi_irda_table,
.probe = vlsi_irda_probe,
- .remove = __devexit_p(vlsi_irda_remove),
+ .remove = vlsi_irda_remove,
#ifdef CONFIG_PM
.suspend = vlsi_irda_suspend,
.resume = vlsi_irda_resume,
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index b3321129a83c..6989ebe2bc79 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -56,6 +56,10 @@ static char config[MAX_PARAM_LENGTH];
module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
+static bool oops_only = false;
+module_param(oops_only, bool, 0600);
+MODULE_PARM_DESC(oops_only, "Only log oops messages");
+
#ifndef MODULE
static int __init option_setup(char *opt)
{
@@ -683,6 +687,8 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
struct netconsole_target *nt;
const char *tmp;
+ if (oops_only && !oops_in_progress)
+ return;
/* Avoid taking lock and disabling interrupts unnecessarily */
if (list_empty(&target_list))
return;
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 81c7bc010dd8..383e8338ad86 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -150,18 +150,24 @@ static struct phy_driver dm91xx_driver[] = {
.name = "Davicom DM9161E",
.phy_id_mask = 0x0ffffff0,
.features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
.config_init = dm9161_config_init,
.config_aneg = dm9161_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = dm9161_ack_interrupt,
+ .config_intr = dm9161_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = 0x0181b8a0,
.name = "Davicom DM9161A",
.phy_id_mask = 0x0ffffff0,
.features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
.config_init = dm9161_config_init,
.config_aneg = dm9161_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = dm9161_ack_interrupt,
+ .config_intr = dm9161_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = 0x00181b80,
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 24e05c43bff8..7490b6c866e6 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -48,6 +48,21 @@
#define CAL_TRIGGER 7
#define PER_TRIGGER 6
+#define MII_DP83640_MICR 0x11
+#define MII_DP83640_MISR 0x12
+
+#define MII_DP83640_MICR_OE 0x1
+#define MII_DP83640_MICR_IE 0x2
+
+#define MII_DP83640_MISR_RHF_INT_EN 0x01
+#define MII_DP83640_MISR_FHF_INT_EN 0x02
+#define MII_DP83640_MISR_ANC_INT_EN 0x04
+#define MII_DP83640_MISR_DUP_INT_EN 0x08
+#define MII_DP83640_MISR_SPD_INT_EN 0x10
+#define MII_DP83640_MISR_LINK_INT_EN 0x20
+#define MII_DP83640_MISR_ED_INT_EN 0x40
+#define MII_DP83640_MISR_LQ_INT_EN 0x80
+
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
@@ -1043,6 +1058,65 @@ static void dp83640_remove(struct phy_device *phydev)
kfree(dp83640);
}
+static int dp83640_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_DP83640_MISR);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int dp83640_config_intr(struct phy_device *phydev)
+{
+ int micr;
+ int misr;
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ misr = phy_read(phydev, MII_DP83640_MISR);
+ if (misr < 0)
+ return misr;
+ misr |=
+ (MII_DP83640_MISR_ANC_INT_EN |
+ MII_DP83640_MISR_DUP_INT_EN |
+ MII_DP83640_MISR_SPD_INT_EN |
+ MII_DP83640_MISR_LINK_INT_EN);
+ err = phy_write(phydev, MII_DP83640_MISR, misr);
+ if (err < 0)
+ return err;
+
+ micr = phy_read(phydev, MII_DP83640_MICR);
+ if (micr < 0)
+ return micr;
+ micr |=
+ (MII_DP83640_MICR_OE |
+ MII_DP83640_MICR_IE);
+ return phy_write(phydev, MII_DP83640_MICR, micr);
+ } else {
+ micr = phy_read(phydev, MII_DP83640_MICR);
+ if (micr < 0)
+ return micr;
+ micr &=
+ ~(MII_DP83640_MICR_OE |
+ MII_DP83640_MICR_IE);
+ err = phy_write(phydev, MII_DP83640_MICR, micr);
+ if (err < 0)
+ return err;
+
+ misr = phy_read(phydev, MII_DP83640_MISR);
+ if (misr < 0)
+ return misr;
+ misr &=
+ ~(MII_DP83640_MISR_ANC_INT_EN |
+ MII_DP83640_MISR_DUP_INT_EN |
+ MII_DP83640_MISR_SPD_INT_EN |
+ MII_DP83640_MISR_LINK_INT_EN);
+ return phy_write(phydev, MII_DP83640_MISR, misr);
+ }
+}
+
static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
{
struct dp83640_private *dp83640 = phydev->priv;
@@ -1253,11 +1327,13 @@ static struct phy_driver dp83640_driver = {
.phy_id_mask = 0xfffffff0,
.name = "NatSemi DP83640",
.features = PHY_BASIC_FEATURES,
- .flags = 0,
+ .flags = PHY_HAS_INTERRUPT,
.probe = dp83640_probe,
.remove = dp83640_remove,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .ack_interrupt = dp83640_ack_interrupt,
+ .config_intr = dp83640_config_intr,
.ts_info = dp83640_ts_info,
.hwtstamp = dp83640_hwtstamp,
.rxtstamp = dp83640_rxtstamp,
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 2ed1140df3e9..27274986ab56 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -103,9 +103,9 @@ static struct mdiobb_ops mdio_gpio_ops = {
.get_mdio_data = mdio_get,
};
-static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
- struct mdio_gpio_platform_data *pdata,
- int bus_id)
+static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
+ struct mdio_gpio_platform_data *pdata,
+ int bus_id)
{
struct mii_bus *new_bus;
struct mdio_gpio_info *bitbang;
@@ -173,7 +173,7 @@ static void mdio_gpio_bus_deinit(struct device *dev)
kfree(bitbang);
}
-static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+static void mdio_gpio_bus_destroy(struct device *dev)
{
struct mii_bus *bus = dev_get_drvdata(dev);
@@ -181,7 +181,7 @@ static void __devexit mdio_gpio_bus_destroy(struct device *dev)
mdio_gpio_bus_deinit(dev);
}
-static int __devinit mdio_gpio_probe(struct platform_device *pdev)
+static int mdio_gpio_probe(struct platform_device *pdev)
{
struct mdio_gpio_platform_data *pdata;
struct mii_bus *new_bus;
@@ -213,7 +213,7 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit mdio_gpio_remove(struct platform_device *pdev)
+static int mdio_gpio_remove(struct platform_device *pdev)
{
mdio_gpio_bus_destroy(&pdev->dev);
@@ -227,7 +227,7 @@ static struct of_device_id mdio_gpio_of_match[] = {
static struct platform_driver mdio_gpio_driver = {
.probe = mdio_gpio_probe,
- .remove = __devexit_p(mdio_gpio_remove),
+ .remove = mdio_gpio_remove,
.driver = {
.name = "mdio-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index eefe49e8713c..0c9accb1c14f 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -49,7 +49,7 @@ static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
return 0;
}
-static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+static int mdio_mux_gpio_probe(struct platform_device *pdev)
{
enum of_gpio_flags f;
struct mdio_mux_gpio_state *s;
@@ -104,7 +104,7 @@ err:
return r;
}
-static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
+static int mdio_mux_gpio_remove(struct platform_device *pdev)
{
struct mdio_mux_gpio_state *s = pdev->dev.platform_data;
mdio_mux_uninit(s->mux_handle);
@@ -130,7 +130,7 @@ static struct platform_driver mdio_mux_gpio_driver = {
.of_match_table = mdio_mux_gpio_match,
},
.probe = mdio_mux_gpio_probe,
- .remove = __devexit_p(mdio_mux_gpio_remove),
+ .remove = mdio_mux_gpio_remove,
};
module_platform_driver(mdio_mux_gpio_driver);
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 9061ba622ac4..9733bd239a86 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -67,7 +67,7 @@ static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
return 0;
}
-static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
+static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
{
struct device_node *np2, *np = pdev->dev.of_node;
struct mdio_mux_mmioreg_state *s;
@@ -137,7 +137,7 @@ static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mdio_mux_mmioreg_remove(struct platform_device *pdev)
+static int mdio_mux_mmioreg_remove(struct platform_device *pdev)
{
struct mdio_mux_mmioreg_state *s = dev_get_platdata(&pdev->dev);
@@ -161,7 +161,7 @@ static struct platform_driver mdio_mux_mmioreg_driver = {
.of_match_table = mdio_mux_mmioreg_match,
},
.probe = mdio_mux_mmioreg_probe,
- .remove = __devexit_p(mdio_mux_mmioreg_remove),
+ .remove = mdio_mux_mmioreg_remove,
};
module_platform_driver(mdio_mux_mmioreg_driver);
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index d4015aa663e6..09297fe05ae5 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -96,7 +96,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
return 0;
}
-static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
+static int octeon_mdiobus_probe(struct platform_device *pdev)
{
struct octeon_mdiobus *bus;
struct resource *res_mem;
@@ -159,7 +159,7 @@ fail:
return err;
}
-static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
+static int octeon_mdiobus_remove(struct platform_device *pdev)
{
struct octeon_mdiobus *bus;
union cvmx_smix_en smi_en;
@@ -188,7 +188,7 @@ static struct platform_driver octeon_mdiobus_driver = {
.of_match_table = octeon_mdiobus_match,
},
.probe = octeon_mdiobus_probe,
- .remove = __devexit_p(octeon_mdiobus_remove),
+ .remove = octeon_mdiobus_remove,
};
void octeon_mdiobus_force_mod_depencency(void)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index c1ef3000ea60..044b5326459f 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -431,10 +431,24 @@ static struct dev_pm_ops mdio_bus_pm_ops = {
#endif /* CONFIG_PM */
+static ssize_t
+phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct phy_device *phydev = to_phy_device(dev);
+
+ return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
+}
+
+static struct device_attribute mdio_dev_attrs[] = {
+ __ATTR_RO(phy_id),
+ __ATTR_NULL
+};
+
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
.pm = MDIO_BUS_PM_OPS,
+ .dev_attrs = mdio_dev_attrs,
};
EXPORT_SYMBOL(mdio_bus_type);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2165d5fdb8c0..b983596abcbb 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -127,6 +127,39 @@ static int ks8051_config_init(struct phy_device *phydev)
return 0;
}
+#define KSZ8873MLL_GLOBAL_CONTROL_4 0x06
+#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4)
+int ksz8873mll_read_status(struct phy_device *phydev)
+{
+ int regval;
+
+ /* dummy read */
+ regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+ regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+ if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
+ phydev->duplex = DUPLEX_HALF;
+ else
+ phydev->duplex = DUPLEX_FULL;
+
+ if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
+ phydev->speed = SPEED_10;
+ else
+ phydev->speed = SPEED_100;
+
+ phydev->link = 1;
+ phydev->pause = phydev->asym_pause = 0;
+
+ return 0;
+}
+
+static int ksz8873mll_config_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -204,6 +237,16 @@ static struct phy_driver ksphy_driver[] = {
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr,
.driver = { .owner = THIS_MODULE, },
+}, {
+ .phy_id = PHY_ID_KSZ8873MLL,
+ .phy_id_mask = 0x00fffff0,
+ .name = "Micrel KSZ8873MLL Switch",
+ .features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
+ .flags = PHY_HAS_MAGICANEG,
+ .config_init = kszphy_config_init,
+ .config_aneg = ksz8873mll_config_aneg,
+ .read_status = ksz8873mll_read_status,
+ .driver = { .owner = THIS_MODULE, },
} };
static int __init ksphy_init(void)
@@ -232,6 +275,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
{ PHY_ID_KSZ8021, 0x00ffffff },
{ PHY_ID_KSZ8041, 0x00fffff0 },
{ PHY_ID_KSZ8051, 0x00fffff0 },
+ { PHY_ID_KSZ8873MLL, 0x00fffff0 },
{ }
};
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 88e3991464e7..11f34813e23f 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -43,7 +43,31 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
static int smsc_phy_config_init(struct phy_device *phydev)
{
- int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
+ if (rc < 0)
+ return rc;
+
+ /* If the SMSC PHY is in power down mode, then set it
+ * in all capable mode before using it.
+ */
+ if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
+ int timeout = 50000;
+
+ /* set "all capable" mode and reset the phy */
+ rc |= MII_LAN83C185_MODE_ALL;
+ phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
+ phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+ /* wait end of reset (max 500 ms) */
+ do {
+ udelay(10);
+ if (timeout-- == 0)
+ return -1;
+ rc = phy_read(phydev, MII_BMCR);
+ } while (rc & BMCR_RESET);
+ }
+
+ rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
return rc;
@@ -56,35 +80,52 @@ static int smsc_phy_config_init(struct phy_device *phydev)
return smsc_phy_ack_interrupt (phydev);
}
-static int lan87xx_config_init(struct phy_device *phydev)
+static int lan911x_config_init(struct phy_device *phydev)
{
- /*
- * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
- * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
- * to a bug on the chip.
- *
- * When the system is powered on with the network cable being
- * disconnected all the way until after ifconfig ethX up is
- * issued for the LAN port with this PHY, connecting the cable
- * afterwards does not cause LINK change detection, while the
- * expected behavior is the Link UP being detected.
- */
- int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
- if (rc < 0)
- return rc;
-
- rc &= ~MII_LAN83C185_EDPWRDOWN;
-
- rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
- if (rc < 0)
- return rc;
-
return smsc_phy_ack_interrupt(phydev);
}
-static int lan911x_config_init(struct phy_device *phydev)
+/*
+ * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
+ * other in order to set the ENERGYON bit and exit EDPD mode. If a link partner
+ * does send the pulses within this interval, the PHY will remained powered
+ * down.
+ *
+ * This workaround will manually toggle the PHY on/off upon calls to read_status
+ * in order to generate link test pulses if the link is down. If a link partner
+ * is present, it will respond to the pulses, which will cause the ENERGYON bit
+ * to be set and will cause the EDPD mode to be exited.
+ */
+static int lan87xx_read_status(struct phy_device *phydev)
{
- return smsc_phy_ack_interrupt(phydev);
+ int err = genphy_read_status(phydev);
+
+ if (!phydev->link) {
+ /* Disable EDPD to wake up PHY */
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc & ~MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+
+ /* Sleep 64 ms to allow ~5 link test pulses to be sent */
+ msleep(64);
+
+ /* Re-enable EDPD */
+ rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc | MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+ }
+
+ return err;
}
static struct phy_driver smsc_phy_driver[] = {
@@ -187,8 +228,8 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .config_init = lan87xx_config_init,
+ .read_status = lan87xx_read_status,
+ .config_init = smsc_phy_config_init,
/* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt,
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index 1c3abce78b6a..41eb8ffeb53d 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -264,7 +264,7 @@ static struct bin_attribute ks8995_registers_attr = {
/* ------------------------------------------------------------------------ */
-static int __devinit ks8995_probe(struct spi_device *spi)
+static int ks8995_probe(struct spi_device *spi)
{
struct ks8995_switch *ks;
struct ks8995_pdata *pdata;
@@ -332,7 +332,7 @@ err_drvdata:
return err;
}
-static int __devexit ks8995_remove(struct spi_device *spi)
+static int ks8995_remove(struct spi_device *spi)
{
struct ks8995_data *ks8995;
@@ -353,7 +353,7 @@ static struct spi_driver ks8995_driver = {
.owner = THIS_MODULE,
},
.probe = ks8995_probe,
- .remove = __devexit_p(ks8995_remove),
+ .remove = ks8995_remove,
};
static int __init ks8995_init(void)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index eb3f5cefeba3..0b2706abe3e3 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1034,7 +1034,7 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
-struct rtnl_link_stats64*
+static struct rtnl_link_stats64*
ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
{
struct ppp *ppp = netdev_priv(dev);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 58f13adaa549..ae7cd7f3656d 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -608,7 +608,7 @@ static int bcm5421_poll_link(struct mii_phy* phy)
if ( mode == BCM54XX_COPPER)
return genmii_poll_link(phy);
- /* try to find out wether we have a link */
+ /* try to find out whether we have a link */
phy_write(phy, MII_NCONFIG, 0x2000);
phy_reg = phy_read(phy, MII_NCONFIG);
@@ -634,7 +634,7 @@ static int bcm5421_read_link(struct mii_phy* phy)
phy->speed = SPEED_1000;
- /* find out wether we are running half- or full duplex */
+ /* find out whether we are running half- or full duplex */
phy_write(phy, MII_NCONFIG, 0x2000);
phy_reg = phy_read(phy, MII_NCONFIG);
@@ -681,7 +681,7 @@ static int bcm5461_poll_link(struct mii_phy* phy)
if ( mode == BCM54XX_COPPER)
return genmii_poll_link(phy);
- /* find out wether we have a link */
+ /* find out whether we have a link */
phy_write(phy, MII_NCONFIG, 0x7000);
phy_reg = phy_read(phy, MII_NCONFIG);
@@ -710,7 +710,7 @@ static int bcm5461_read_link(struct mii_phy* phy)
phy->speed = SPEED_1000;
- /* find out wether we are running half- or full duplex */
+ /* find out whether we are running half- or full duplex */
phy_write(phy, MII_NCONFIG, 0x7000);
phy_reg = phy_read(phy, MII_NCONFIG);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 0873cdcf39be..2ac2164a1e39 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -68,7 +68,6 @@
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
#include <net/sock.h>
-#include <net/cls_cgroup.h>
#include <asm/uaccess.h>
@@ -110,16 +109,56 @@ struct tap_filter {
unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN];
};
+/* 1024 is probably a high enough limit: modern hypervisors seem to support on
+ * the order of 100-200 CPUs so this leaves us some breathing space if we want
+ * to match a queue per guest CPU.
+ */
+#define MAX_TAP_QUEUES 1024
+
+#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)
+ * 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
+ * this).
+ *
+ * RCU usage:
+ * The tun_file and tun_struct are loosely coupled, the pointer from one to the
+ * other can only be read while rcu_read_lock or rtnl_lock is held.
+ */
struct tun_file {
- atomic_t count;
- struct tun_struct *tun;
+ struct sock sk;
+ struct socket socket;
+ struct socket_wq wq;
+ struct tun_struct __rcu *tun;
struct net *net;
+ struct fasync_struct *fasync;
+ /* only used for fasnyc */
+ unsigned int flags;
+ u16 queue_index;
+};
+
+struct tun_flow_entry {
+ struct hlist_node hash_link;
+ struct rcu_head rcu;
+ struct tun_struct *tun;
+
+ u32 rxhash;
+ int queue_index;
+ unsigned long updated;
};
-struct tun_sock;
+#define TUN_NUM_FLOW_ENTRIES 1024
+/* Since the socket were moved to tun_file, to preserve the behavior of persist
+ * device, socket filter, sndbuf and vnet header size were restore when the
+ * file were attached to a persist device.
+ */
struct tun_struct {
- struct tun_file *tfile;
+ struct tun_file __rcu *tfiles[MAX_TAP_QUEUES];
+ unsigned int numqueues;
unsigned int flags;
kuid_t owner;
kgid_t group;
@@ -128,88 +167,349 @@ struct tun_struct {
netdev_features_t set_features;
#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
NETIF_F_TSO6|NETIF_F_UFO)
- struct fasync_struct *fasync;
-
- struct tap_filter txflt;
- struct socket socket;
- struct socket_wq wq;
int vnet_hdr_sz;
-
+ int sndbuf;
+ struct tap_filter txflt;
+ struct sock_fprog fprog;
+ /* protected by rtnl lock */
+ bool filter_attached;
#ifdef TUN_DEBUG
int debug;
#endif
+ spinlock_t lock;
+ struct kmem_cache *flow_cache;
+ struct hlist_head flows[TUN_NUM_FLOW_ENTRIES];
+ struct timer_list flow_gc_timer;
+ unsigned long ageing_time;
};
-struct tun_sock {
- struct sock sk;
- struct tun_struct *tun;
-};
+static inline u32 tun_hashfn(u32 rxhash)
+{
+ return rxhash & 0x3ff;
+}
-static inline struct tun_sock *tun_sk(struct sock *sk)
+static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash)
{
- return container_of(sk, struct tun_sock, sk);
+ struct tun_flow_entry *e;
+ struct hlist_node *n;
+
+ hlist_for_each_entry_rcu(e, n, head, hash_link) {
+ if (e->rxhash == rxhash)
+ return e;
+ }
+ return NULL;
}
-static int tun_attach(struct tun_struct *tun, struct file *file)
+static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
+ struct hlist_head *head,
+ u32 rxhash, u16 queue_index)
{
- struct tun_file *tfile = file->private_data;
- int err;
+ struct tun_flow_entry *e = kmem_cache_alloc(tun->flow_cache,
+ GFP_ATOMIC);
+ if (e) {
+ tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n",
+ rxhash, queue_index);
+ e->updated = jiffies;
+ e->rxhash = rxhash;
+ e->queue_index = queue_index;
+ e->tun = tun;
+ hlist_add_head_rcu(&e->hash_link, head);
+ }
+ return e;
+}
- ASSERT_RTNL();
+static void tun_flow_free(struct rcu_head *head)
+{
+ struct tun_flow_entry *e
+ = container_of(head, struct tun_flow_entry, rcu);
+ kmem_cache_free(e->tun->flow_cache, e);
+}
- netif_tx_lock_bh(tun->dev);
+static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
+{
+ tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n",
+ e->rxhash, e->queue_index);
+ hlist_del_rcu(&e->hash_link);
+ call_rcu(&e->rcu, tun_flow_free);
+}
- err = -EINVAL;
- if (tfile->tun)
- goto out;
+static void tun_flow_flush(struct tun_struct *tun)
+{
+ int i;
- err = -EBUSY;
- if (tun->tfile)
- goto out;
+ spin_lock_bh(&tun->lock);
+ for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+ struct tun_flow_entry *e;
+ struct hlist_node *h, *n;
- err = 0;
- tfile->tun = tun;
- tun->tfile = tfile;
- tun->socket.file = file;
- netif_carrier_on(tun->dev);
- dev_hold(tun->dev);
- sock_hold(tun->socket.sk);
- atomic_inc(&tfile->count);
+ hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link)
+ tun_flow_delete(tun, e);
+ }
+ spin_unlock_bh(&tun->lock);
+}
-out:
- netif_tx_unlock_bh(tun->dev);
- return err;
+static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index)
+{
+ int i;
+
+ spin_lock_bh(&tun->lock);
+ for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+ struct tun_flow_entry *e;
+ struct hlist_node *h, *n;
+
+ hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+ if (e->queue_index == queue_index)
+ tun_flow_delete(tun, e);
+ }
+ }
+ spin_unlock_bh(&tun->lock);
}
-static void __tun_detach(struct tun_struct *tun)
+static void tun_flow_cleanup(unsigned long data)
{
- /* Detach from net device */
- netif_tx_lock_bh(tun->dev);
- netif_carrier_off(tun->dev);
- tun->tfile = NULL;
- netif_tx_unlock_bh(tun->dev);
+ struct tun_struct *tun = (struct tun_struct *)data;
+ unsigned long delay = tun->ageing_time;
+ unsigned long next_timer = jiffies + delay;
+ unsigned long count = 0;
+ int i;
- /* Drop read queue */
- skb_queue_purge(&tun->socket.sk->sk_receive_queue);
+ tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n");
+
+ spin_lock_bh(&tun->lock);
+ for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+ struct tun_flow_entry *e;
+ struct hlist_node *h, *n;
+
+ hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+ unsigned long this_timer;
+ count++;
+ this_timer = e->updated + delay;
+ if (time_before_eq(this_timer, jiffies))
+ tun_flow_delete(tun, e);
+ else if (time_before(this_timer, next_timer))
+ next_timer = this_timer;
+ }
+ }
- /* Drop the extra count on the net device */
- dev_put(tun->dev);
+ if (count)
+ mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer));
+ spin_unlock_bh(&tun->lock);
}
-static void tun_detach(struct tun_struct *tun)
+static void tun_flow_update(struct tun_struct *tun, struct sk_buff *skb,
+ u16 queue_index)
+{
+ struct hlist_head *head;
+ struct tun_flow_entry *e;
+ unsigned long delay = tun->ageing_time;
+ u32 rxhash = skb_get_rxhash(skb);
+
+ if (!rxhash)
+ return;
+ else
+ head = &tun->flows[tun_hashfn(rxhash)];
+
+ rcu_read_lock();
+
+ if (tun->numqueues == 1)
+ goto unlock;
+
+ e = tun_flow_find(head, rxhash);
+ if (likely(e)) {
+ /* TODO: keep queueing to old queue until it's empty? */
+ e->queue_index = queue_index;
+ e->updated = jiffies;
+ } else {
+ spin_lock_bh(&tun->lock);
+ if (!tun_flow_find(head, rxhash))
+ tun_flow_create(tun, head, rxhash, queue_index);
+
+ if (!timer_pending(&tun->flow_gc_timer))
+ mod_timer(&tun->flow_gc_timer,
+ round_jiffies_up(jiffies + delay));
+ spin_unlock_bh(&tun->lock);
+ }
+
+unlock:
+ rcu_read_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
+ * 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
+ * hope the rxq no. may help here.
+ */
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct tun_flow_entry *e;
+ u32 txq = 0;
+ u32 numqueues = 0;
+
+ rcu_read_lock();
+ numqueues = tun->numqueues;
+
+ txq = skb_get_rxhash(skb);
+ if (txq) {
+ e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
+ if (e)
+ txq = e->queue_index;
+ else
+ /* use multiply and shift instead of expensive divide */
+ txq = ((u64)txq * numqueues) >> 32;
+ } else if (likely(skb_rx_queue_recorded(skb))) {
+ txq = skb_get_rx_queue(skb);
+ while (unlikely(txq >= numqueues))
+ txq -= numqueues;
+ }
+
+ rcu_read_unlock();
+ return txq;
+}
+
+static inline bool tun_not_capable(struct tun_struct *tun)
+{
+ const struct cred *cred = current_cred();
+ struct net *net = dev_net(tun->dev);
+
+ return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
+ (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
+ !ns_capable(net->user_ns, CAP_NET_ADMIN);
+}
+
+static void tun_set_real_num_queues(struct tun_struct *tun)
+{
+ netif_set_real_num_tx_queues(tun->dev, tun->numqueues);
+ netif_set_real_num_rx_queues(tun->dev, tun->numqueues);
+}
+
+static void __tun_detach(struct tun_file *tfile, bool clean)
+{
+ struct tun_file *ntfile;
+ struct tun_struct *tun;
+ struct net_device *dev;
+
+ tun = rcu_dereference_protected(tfile->tun,
+ lockdep_rtnl_is_held());
+ if (tun) {
+ u16 index = tfile->queue_index;
+ BUG_ON(index >= tun->numqueues);
+ dev = tun->dev;
+
+ rcu_assign_pointer(tun->tfiles[index],
+ tun->tfiles[tun->numqueues - 1]);
+ rcu_assign_pointer(tfile->tun, NULL);
+ ntfile = rcu_dereference_protected(tun->tfiles[index],
+ lockdep_rtnl_is_held());
+ ntfile->queue_index = index;
+
+ --tun->numqueues;
+ sock_put(&tfile->sk);
+
+ synchronize_net();
+ tun_flow_delete_by_queue(tun, tun->numqueues + 1);
+ /* Drop read queue */
+ skb_queue_purge(&tfile->sk.sk_receive_queue);
+ tun_set_real_num_queues(tun);
+
+ if (tun->numqueues == 0 && !(tun->flags & TUN_PERSIST))
+ if (dev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(dev);
+ }
+
+ if (clean) {
+ BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
+ &tfile->socket.flags));
+ sk_release_kernel(&tfile->sk);
+ }
+}
+
+static void tun_detach(struct tun_file *tfile, bool clean)
{
rtnl_lock();
- __tun_detach(tun);
+ __tun_detach(tfile, clean);
rtnl_unlock();
}
+static void tun_detach_all(struct net_device *dev)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct tun_file *tfile;
+ int i, n = tun->numqueues;
+
+ for (i = 0; i < n; i++) {
+ tfile = rcu_dereference_protected(tun->tfiles[i],
+ lockdep_rtnl_is_held());
+ BUG_ON(!tfile);
+ wake_up_all(&tfile->wq.wait);
+ rcu_assign_pointer(tfile->tun, NULL);
+ --tun->numqueues;
+ }
+ BUG_ON(tun->numqueues != 0);
+
+ synchronize_net();
+ for (i = 0; i < n; i++) {
+ tfile = rcu_dereference_protected(tun->tfiles[i],
+ lockdep_rtnl_is_held());
+ /* Drop read queue */
+ skb_queue_purge(&tfile->sk.sk_receive_queue);
+ sock_put(&tfile->sk);
+ }
+}
+
+static int tun_attach(struct tun_struct *tun, struct file *file)
+{
+ struct tun_file *tfile = file->private_data;
+ int err;
+
+ err = -EINVAL;
+ if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+ goto out;
+
+ err = -EBUSY;
+ if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1)
+ goto out;
+
+ err = -E2BIG;
+ if (tun->numqueues == MAX_TAP_QUEUES)
+ goto out;
+
+ err = 0;
+
+ /* Re-attach the filter to presist device */
+ if (tun->filter_attached == true) {
+ err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+ if (!err)
+ goto out;
+ }
+ tfile->queue_index = tun->numqueues;
+ rcu_assign_pointer(tfile->tun, tun);
+ rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+ sock_hold(&tfile->sk);
+ tun->numqueues++;
+
+ tun_set_real_num_queues(tun);
+
+ /* device is allowed to go away first, so no need to hold extra
+ * refcnt.
+ */
+
+out:
+ return err;
+}
+
static struct tun_struct *__tun_get(struct tun_file *tfile)
{
- struct tun_struct *tun = NULL;
+ struct tun_struct *tun;
- if (atomic_inc_not_zero(&tfile->count))
- tun = tfile->tun;
+ rcu_read_lock();
+ tun = rcu_dereference(tfile->tun);
+ if (tun)
+ dev_hold(tun->dev);
+ rcu_read_unlock();
return tun;
}
@@ -221,10 +521,7 @@ static struct tun_struct *tun_get(struct file *file)
static void tun_put(struct tun_struct *tun)
{
- struct tun_file *tfile = tun->tfile;
-
- if (atomic_dec_and_test(&tfile->count))
- tun_detach(tfile->tun);
+ dev_put(tun->dev);
}
/* TAP filtering */
@@ -344,38 +641,20 @@ static const struct ethtool_ops tun_ethtool_ops;
/* Net device detach from fd. */
static void tun_net_uninit(struct net_device *dev)
{
- struct tun_struct *tun = netdev_priv(dev);
- struct tun_file *tfile = tun->tfile;
-
- /* Inform the methods they need to stop using the dev.
- */
- if (tfile) {
- wake_up_all(&tun->wq.wait);
- if (atomic_dec_and_test(&tfile->count))
- __tun_detach(tun);
- }
-}
-
-static void tun_free_netdev(struct net_device *dev)
-{
- struct tun_struct *tun = netdev_priv(dev);
-
- BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags));
-
- sk_release_kernel(tun->socket.sk);
+ tun_detach_all(dev);
}
/* Net device open. */
static int tun_net_open(struct net_device *dev)
{
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
return 0;
}
/* Net device close. */
static int tun_net_close(struct net_device *dev)
{
- netif_stop_queue(dev);
+ netif_tx_stop_all_queues(dev);
return 0;
}
@@ -383,38 +662,36 @@ static int tun_net_close(struct net_device *dev)
static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
+ int txq = skb->queue_mapping;
+ struct tun_file *tfile;
- tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+ rcu_read_lock();
+ tfile = rcu_dereference(tun->tfiles[txq]);
/* Drop packet if interface is not attached */
- if (!tun->tfile)
+ if (txq >= tun->numqueues)
goto drop;
+ tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+
+ BUG_ON(!tfile);
+
/* Drop if the filter does not like it.
* This is a noop if the filter is disabled.
* Filter can be enabled only for the TAP devices. */
if (!check_filter(&tun->txflt, skb))
goto drop;
- if (tun->socket.sk->sk_filter &&
- sk_filter(tun->socket.sk, skb))
+ if (tfile->socket.sk->sk_filter &&
+ sk_filter(tfile->socket.sk, skb))
goto drop;
- if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {
- if (!(tun->flags & TUN_ONE_QUEUE)) {
- /* Normal queueing mode. */
- /* Packet scheduler handles dropping of further packets. */
- netif_stop_queue(dev);
-
- /* We won't see all dropped packets individually, so overrun
- * error is more appropriate. */
- dev->stats.tx_fifo_errors++;
- } else {
- /* Single queue mode.
- * Driver handles dropping of all packets itself. */
- goto drop;
- }
- }
+ /* Limit the number of packets queued by dividing txq length with the
+ * number of queues.
+ */
+ if (skb_queue_len(&tfile->socket.sk->sk_receive_queue)
+ >= dev->tx_queue_len / tun->numqueues)
+ goto drop;
/* Orphan the skb - required as we might hang on to it
* for indefinite time. */
@@ -423,18 +700,22 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
skb_orphan(skb);
/* Enqueue packet */
- skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
+ skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
/* Notify and wake up reader process */
- if (tun->flags & TUN_FASYNC)
- kill_fasync(&tun->fasync, SIGIO, POLL_IN);
- wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
+ if (tfile->flags & TUN_FASYNC)
+ kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
+ wake_up_interruptible_poll(&tfile->wq.wait, POLLIN |
POLLRDNORM | POLLRDBAND);
+
+ rcu_read_unlock();
return NETDEV_TX_OK;
drop:
dev->stats.tx_dropped++;
+ skb_tx_error(skb);
kfree_skb(skb);
+ rcu_read_unlock();
return NETDEV_TX_OK;
}
@@ -490,6 +771,7 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_start_xmit = tun_net_xmit,
.ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features,
+ .ndo_select_queue = tun_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
@@ -505,11 +787,43 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_rx_mode = tun_net_mclist,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_select_queue = tun_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
};
+static int tun_flow_init(struct tun_struct *tun)
+{
+ int i;
+
+ tun->flow_cache = kmem_cache_create("tun_flow_cache",
+ sizeof(struct tun_flow_entry), 0, 0,
+ NULL);
+ if (!tun->flow_cache)
+ return -ENOMEM;
+
+ for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++)
+ INIT_HLIST_HEAD(&tun->flows[i]);
+
+ tun->ageing_time = TUN_FLOW_EXPIRE;
+ setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun);
+ mod_timer(&tun->flow_gc_timer,
+ round_jiffies_up(jiffies + tun->ageing_time));
+
+ return 0;
+}
+
+static void tun_flow_uninit(struct tun_struct *tun)
+{
+ del_timer_sync(&tun->flow_gc_timer);
+ tun_flow_flush(tun);
+
+ /* Wait for completion of call_rcu()'s */
+ rcu_barrier();
+ kmem_cache_destroy(tun->flow_cache);
+}
+
/* Initialize net device. */
static void tun_net_init(struct net_device *dev)
{
@@ -535,6 +849,7 @@ static void tun_net_init(struct net_device *dev)
/* Ethernet TAP Device */
ether_setup(dev);
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
eth_hw_addr_random(dev);
@@ -546,7 +861,7 @@ static void tun_net_init(struct net_device *dev)
/* Character device part */
/* Poll */
-static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
+static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
@@ -556,11 +871,11 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
if (!tun)
return POLLERR;
- sk = tun->socket.sk;
+ sk = tfile->socket.sk;
tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
- poll_wait(file, &tun->wq.wait, wait);
+ poll_wait(file, &tfile->wq.wait, wait);
if (!skb_queue_empty(&sk->sk_receive_queue))
mask |= POLLIN | POLLRDNORM;
@@ -579,16 +894,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
/* prepad is the amount to reserve at front. len is length after that.
* linear is a hint as to how much to copy (usually headers). */
-static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
size_t prepad, size_t len,
size_t linear, int noblock)
{
- struct sock *sk = tun->socket.sk;
+ struct sock *sk = tfile->socket.sk;
struct sk_buff *skb;
int err;
- sock_update_classid(sk);
-
/* Under a page? Don't bother with paged skb. */
if (prepad + len < PAGE_SIZE || !linear)
linear = len;
@@ -685,9 +998,9 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
}
/* Get packet from user space buffer */
-static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
- const struct iovec *iv, size_t total_len,
- size_t count, int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
+ void *msg_control, const struct iovec *iv,
+ size_t total_len, size_t count, int noblock)
{
struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
struct sk_buff *skb;
@@ -757,7 +1070,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
} else
copylen = len;
- skb = tun_alloc_skb(tun, align, copylen, gso.hdr_len, noblock);
+ skb = tun_alloc_skb(tfile, align, copylen, gso.hdr_len, noblock);
if (IS_ERR(skb)) {
if (PTR_ERR(skb) != -EAGAIN)
tun->dev->stats.rx_dropped++;
@@ -854,6 +1167,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
tun->dev->stats.rx_packets++;
tun->dev->stats.rx_bytes += len;
+ tun_flow_update(tun, skb, tfile->queue_index);
return total_len;
}
@@ -862,6 +1176,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
{
struct file *file = iocb->ki_filp;
struct tun_struct *tun = tun_get(file);
+ struct tun_file *tfile = file->private_data;
ssize_t result;
if (!tun)
@@ -869,8 +1184,8 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count);
- result = tun_get_user(tun, NULL, iv, iov_length(iv, count), count,
- file->f_flags & O_NONBLOCK);
+ result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count),
+ count, file->f_flags & O_NONBLOCK);
tun_put(tun);
return result;
@@ -878,6 +1193,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
/* Put packet to the user space buffer */
static ssize_t tun_put_user(struct tun_struct *tun,
+ struct tun_file *tfile,
struct sk_buff *skb,
const struct iovec *iv, int len)
{
@@ -957,7 +1273,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
return total;
}
-static ssize_t tun_do_read(struct tun_struct *tun,
+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)
{
@@ -965,15 +1281,15 @@ static ssize_t tun_do_read(struct tun_struct *tun,
struct sk_buff *skb;
ssize_t ret = 0;
- tun_debug(KERN_INFO, tun, "tun_chr_read\n");
+ tun_debug(KERN_INFO, tun, "tun_do_read\n");
if (unlikely(!noblock))
- add_wait_queue(&tun->wq.wait, &wait);
+ add_wait_queue(&tfile->wq.wait, &wait);
while (len) {
current->state = TASK_INTERRUPTIBLE;
/* Read frames from the queue */
- if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
+ if (!(skb = skb_dequeue(&tfile->socket.sk->sk_receive_queue))) {
if (noblock) {
ret = -EAGAIN;
break;
@@ -991,16 +1307,15 @@ static ssize_t tun_do_read(struct tun_struct *tun,
schedule();
continue;
}
- netif_wake_queue(tun->dev);
- ret = tun_put_user(tun, skb, iv, len);
+ ret = tun_put_user(tun, tfile, skb, iv, len);
kfree_skb(skb);
break;
}
current->state = TASK_RUNNING;
if (unlikely(!noblock))
- remove_wait_queue(&tun->wq.wait, &wait);
+ remove_wait_queue(&tfile->wq.wait, &wait);
return ret;
}
@@ -1021,13 +1336,22 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
goto out;
}
- ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
+ ret = tun_do_read(tun, tfile, iocb, iv, len,
+ file->f_flags & O_NONBLOCK);
ret = min_t(ssize_t, ret, len);
out:
tun_put(tun);
return ret;
}
+static void tun_free_netdev(struct net_device *dev)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+
+ tun_flow_uninit(tun);
+ free_netdev(dev);
+}
+
static void tun_setup(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
@@ -1056,7 +1380,7 @@ static struct rtnl_link_ops tun_link_ops __read_mostly = {
static void tun_sock_write_space(struct sock *sk)
{
- struct tun_struct *tun;
+ struct tun_file *tfile;
wait_queue_head_t *wqueue;
if (!sock_writeable(sk))
@@ -1070,37 +1394,46 @@ static void tun_sock_write_space(struct sock *sk)
wake_up_interruptible_sync_poll(wqueue, POLLOUT |
POLLWRNORM | POLLWRBAND);
- tun = tun_sk(sk)->tun;
- kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
-}
-
-static void tun_sock_destruct(struct sock *sk)
-{
- free_netdev(tun_sk(sk)->tun->dev);
+ tfile = container_of(sk, struct tun_file, sk);
+ kill_fasync(&tfile->fasync, SIGIO, POLL_OUT);
}
static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len)
{
- struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
- return tun_get_user(tun, m->msg_control, m->msg_iov, total_len,
- m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+ int ret;
+ struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+ struct tun_struct *tun = __tun_get(tfile);
+
+ if (!tun)
+ return -EBADFD;
+ ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len,
+ m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+ tun_put(tun);
+ return ret;
}
+
static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len,
int flags)
{
- struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
+ struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+ struct tun_struct *tun = __tun_get(tfile);
int ret;
+
+ if (!tun)
+ return -EBADFD;
+
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
return -EINVAL;
- ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
+ ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
flags & MSG_DONTWAIT);
if (ret > total_len) {
m->msg_flags |= MSG_TRUNC;
ret = flags & MSG_TRUNC ? ret : total_len;
}
+ tun_put(tun);
return ret;
}
@@ -1121,7 +1454,7 @@ static const struct proto_ops tun_socket_ops = {
static struct proto tun_proto = {
.name = "tun",
.owner = THIS_MODULE,
- .obj_size = sizeof(struct tun_sock),
+ .obj_size = sizeof(struct tun_file),
};
static int tun_flags(struct tun_struct *tun)
@@ -1136,12 +1469,18 @@ static int tun_flags(struct tun_struct *tun)
if (tun->flags & TUN_NO_PI)
flags |= IFF_NO_PI;
+ /* This flag has no real effect. We track the value for backwards
+ * compatibility.
+ */
if (tun->flags & TUN_ONE_QUEUE)
flags |= IFF_ONE_QUEUE;
if (tun->flags & TUN_VNET_HDR)
flags |= IFF_VNET_HDR;
+ if (tun->flags & TUN_TAP_MQ)
+ flags |= IFF_MULTI_QUEUE;
+
return flags;
}
@@ -1178,15 +1517,13 @@ static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
{
- struct sock *sk;
struct tun_struct *tun;
+ struct tun_file *tfile = file->private_data;
struct net_device *dev;
int err;
dev = __dev_get_by_name(net, ifr->ifr_name);
if (dev) {
- const struct cred *cred = current_cred();
-
if (ifr->ifr_flags & IFF_TUN_EXCL)
return -EBUSY;
if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
@@ -1196,11 +1533,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
else
return -EINVAL;
- if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
- (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
- !capable(CAP_NET_ADMIN))
+ if (tun_not_capable(tun))
return -EPERM;
- err = security_tun_dev_attach(tun->socket.sk);
+ err = security_tun_dev_attach(tfile->socket.sk);
if (err < 0)
return err;
@@ -1212,7 +1547,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
char *name;
unsigned long flags = 0;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
err = security_tun_dev_create();
if (err < 0)
@@ -1233,8 +1568,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
if (*ifr->ifr_name)
name = ifr->ifr_name;
- dev = alloc_netdev(sizeof(struct tun_struct), name,
- tun_setup);
+ dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
+ tun_setup,
+ MAX_TAP_QUEUES, MAX_TAP_QUEUES);
if (!dev)
return -ENOMEM;
@@ -1246,46 +1582,38 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->flags = flags;
tun->txflt.count = 0;
tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
- set_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags);
-
- err = -ENOMEM;
- sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
- if (!sk)
- goto err_free_dev;
- sk_change_net(sk, net);
- tun->socket.wq = &tun->wq;
- init_waitqueue_head(&tun->wq.wait);
- tun->socket.ops = &tun_socket_ops;
- sock_init_data(&tun->socket, sk);
- sk->sk_write_space = tun_sock_write_space;
- sk->sk_sndbuf = INT_MAX;
- sock_set_flag(sk, SOCK_ZEROCOPY);
+ tun->filter_attached = false;
+ tun->sndbuf = tfile->socket.sk->sk_sndbuf;
- tun_sk(sk)->tun = tun;
+ spin_lock_init(&tun->lock);
- security_tun_dev_post_create(sk);
+ security_tun_dev_post_create(&tfile->sk);
tun_net_init(dev);
+ err = tun_flow_init(tun);
+ if (err < 0)
+ goto err_free_dev;
+
dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
TUN_USER_FEATURES;
dev->features = dev->hw_features;
+ err = tun_attach(tun, file);
+ if (err < 0)
+ goto err_free_dev;
+
err = register_netdevice(tun->dev);
if (err < 0)
- goto err_free_sk;
+ goto err_free_dev;
if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
device_create_file(&tun->dev->dev, &dev_attr_owner) ||
device_create_file(&tun->dev->dev, &dev_attr_group))
pr_err("Failed to create tun sysfs files\n");
- sk->sk_destruct = tun_sock_destruct;
-
- err = tun_attach(tun, file);
- if (err < 0)
- goto failed;
+ netif_carrier_on(tun->dev);
}
tun_debug(KERN_INFO, tun, "tun_set_iff\n");
@@ -1295,6 +1623,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
else
tun->flags &= ~TUN_NO_PI;
+ /* This flag has no real effect. We track the value for backwards
+ * compatibility.
+ */
if (ifr->ifr_flags & IFF_ONE_QUEUE)
tun->flags |= TUN_ONE_QUEUE;
else
@@ -1305,24 +1636,26 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
else
tun->flags &= ~TUN_VNET_HDR;
+ if (ifr->ifr_flags & IFF_MULTI_QUEUE)
+ tun->flags |= TUN_TAP_MQ;
+ else
+ tun->flags &= ~TUN_TAP_MQ;
+
/* Make sure persistent devices do not get stuck in
* xoff state.
*/
if (netif_running(tun->dev))
- netif_wake_queue(tun->dev);
+ netif_tx_wake_all_queues(tun->dev);
strcpy(ifr->ifr_name, tun->dev->name);
return 0;
- err_free_sk:
- tun_free_netdev(dev);
err_free_dev:
free_netdev(dev);
- failed:
return err;
}
-static int tun_get_iff(struct net *net, struct tun_struct *tun,
+static void tun_get_iff(struct net *net, struct tun_struct *tun,
struct ifreq *ifr)
{
tun_debug(KERN_INFO, tun, "tun_get_iff\n");
@@ -1331,7 +1664,6 @@ static int tun_get_iff(struct net *net, struct tun_struct *tun,
ifr->ifr_flags = tun_flags(tun);
- return 0;
}
/* This is like a cut-down ethtool ops, except done via tun fd so no
@@ -1373,13 +1705,91 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
return 0;
}
+static void tun_detach_filter(struct tun_struct *tun, int n)
+{
+ int i;
+ struct tun_file *tfile;
+
+ for (i = 0; i < n; i++) {
+ tfile = rcu_dereference_protected(tun->tfiles[i],
+ lockdep_rtnl_is_held());
+ sk_detach_filter(tfile->socket.sk);
+ }
+
+ tun->filter_attached = false;
+}
+
+static int tun_attach_filter(struct tun_struct *tun)
+{
+ int i, ret = 0;
+ struct tun_file *tfile;
+
+ for (i = 0; i < tun->numqueues; i++) {
+ tfile = rcu_dereference_protected(tun->tfiles[i],
+ lockdep_rtnl_is_held());
+ ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+ if (ret) {
+ tun_detach_filter(tun, i);
+ return ret;
+ }
+ }
+
+ tun->filter_attached = true;
+ return ret;
+}
+
+static void tun_set_sndbuf(struct tun_struct *tun)
+{
+ struct tun_file *tfile;
+ int i;
+
+ for (i = 0; i < tun->numqueues; i++) {
+ tfile = rcu_dereference_protected(tun->tfiles[i],
+ lockdep_rtnl_is_held());
+ tfile->socket.sk->sk_sndbuf = tun->sndbuf;
+ }
+}
+
+static int tun_set_queue(struct file *file, struct ifreq *ifr)
+{
+ struct tun_file *tfile = file->private_data;
+ struct tun_struct *tun;
+ struct net_device *dev;
+ int ret = 0;
+
+ rtnl_lock();
+
+ if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
+ dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
+ if (!dev) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ tun = netdev_priv(dev);
+ if (dev->netdev_ops != &tap_netdev_ops &&
+ dev->netdev_ops != &tun_netdev_ops)
+ ret = -EINVAL;
+ else if (tun_not_capable(tun))
+ ret = -EPERM;
+ else
+ ret = tun_attach(tun, file);
+ } else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
+ __tun_detach(tfile, false);
+ else
+ ret = -EINVAL;
+
+unlock:
+ rtnl_unlock();
+ return ret;
+}
+
static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
unsigned long arg, int ifreq_len)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
void __user* argp = (void __user*)arg;
- struct sock_fprog fprog;
struct ifreq ifr;
kuid_t owner;
kgid_t group;
@@ -1387,7 +1797,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
int vnet_hdr_sz;
int ret;
- if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
+ if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
if (copy_from_user(&ifr, argp, ifreq_len))
return -EFAULT;
} else {
@@ -1398,10 +1808,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
* This is needed because we never checked for invalid flags on
* TUNSETIFF. */
return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
- IFF_VNET_HDR,
+ IFF_VNET_HDR | IFF_MULTI_QUEUE,
(unsigned int __user*)argp);
- }
+ } else if (cmd == TUNSETQUEUE)
+ return tun_set_queue(file, &ifr);
+ ret = 0;
rtnl_lock();
tun = __tun_get(tfile);
@@ -1422,14 +1834,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
if (!tun)
goto unlock;
- tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
+ tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd);
ret = 0;
switch (cmd) {
case TUNGETIFF:
- ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
- if (ret)
- break;
+ tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
if (copy_to_user(argp, &ifr, ifreq_len))
ret = -EFAULT;
@@ -1444,11 +1854,16 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
break;
case TUNSETPERSIST:
- /* Disable/Enable persist mode */
- if (arg)
+ /* Disable/Enable persist mode. Keep an extra reference to the
+ * module to prevent the module being unprobed.
+ */
+ if (arg) {
tun->flags |= TUN_PERSIST;
- else
+ __module_get(THIS_MODULE);
+ } else {
tun->flags &= ~TUN_PERSIST;
+ module_put(THIS_MODULE);
+ }
tun_debug(KERN_INFO, tun, "persist %s\n",
arg ? "enabled" : "disabled");
@@ -1462,7 +1877,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
break;
}
tun->owner = owner;
- tun_debug(KERN_INFO, tun, "owner set to %d\n",
+ tun_debug(KERN_INFO, tun, "owner set to %u\n",
from_kuid(&init_user_ns, tun->owner));
break;
@@ -1474,7 +1889,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
break;
}
tun->group = group;
- tun_debug(KERN_INFO, tun, "group set to %d\n",
+ tun_debug(KERN_INFO, tun, "group set to %u\n",
from_kgid(&init_user_ns, tun->group));
break;
@@ -1526,7 +1941,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
break;
case TUNGETSNDBUF:
- sndbuf = tun->socket.sk->sk_sndbuf;
+ sndbuf = tfile->socket.sk->sk_sndbuf;
if (copy_to_user(argp, &sndbuf, sizeof(sndbuf)))
ret = -EFAULT;
break;
@@ -1537,7 +1952,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
break;
}
- tun->socket.sk->sk_sndbuf = sndbuf;
+ tun->sndbuf = sndbuf;
+ tun_set_sndbuf(tun);
break;
case TUNGETVNETHDRSZ:
@@ -1565,10 +1981,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
break;
ret = -EFAULT;
- if (copy_from_user(&fprog, argp, sizeof(fprog)))
+ if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog)))
break;
- ret = sk_attach_filter(&fprog, tun->socket.sk);
+ ret = tun_attach_filter(tun);
break;
case TUNDETACHFILTER:
@@ -1576,7 +1992,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
ret = -EINVAL;
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
break;
- ret = sk_detach_filter(tun->socket.sk);
+ ret = 0;
+ tun_detach_filter(tun, tun->numqueues);
break;
default:
@@ -1628,27 +2045,21 @@ static long tun_chr_compat_ioctl(struct file *file,
static int tun_chr_fasync(int fd, struct file *file, int on)
{
- struct tun_struct *tun = tun_get(file);
+ struct tun_file *tfile = file->private_data;
int ret;
- if (!tun)
- return -EBADFD;
-
- tun_debug(KERN_INFO, tun, "tun_chr_fasync %d\n", on);
-
- if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
+ if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0)
goto out;
if (on) {
ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
if (ret)
goto out;
- tun->flags |= TUN_FASYNC;
+ tfile->flags |= TUN_FASYNC;
} else
- tun->flags &= ~TUN_FASYNC;
+ tfile->flags &= ~TUN_FASYNC;
ret = 0;
out:
- tun_put(tun);
return ret;
}
@@ -1658,44 +2069,39 @@ static int tun_chr_open(struct inode *inode, struct file * file)
DBG1(KERN_INFO, "tunX: tun_chr_open\n");
- tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+ tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL,
+ &tun_proto);
if (!tfile)
return -ENOMEM;
- atomic_set(&tfile->count, 0);
- tfile->tun = NULL;
+ rcu_assign_pointer(tfile->tun, NULL);
tfile->net = get_net(current->nsproxy->net_ns);
+ tfile->flags = 0;
+
+ rcu_assign_pointer(tfile->socket.wq, &tfile->wq);
+ init_waitqueue_head(&tfile->wq.wait);
+
+ tfile->socket.file = file;
+ tfile->socket.ops = &tun_socket_ops;
+
+ sock_init_data(&tfile->socket, &tfile->sk);
+ sk_change_net(&tfile->sk, tfile->net);
+
+ tfile->sk.sk_write_space = tun_sock_write_space;
+ tfile->sk.sk_sndbuf = INT_MAX;
+
file->private_data = tfile;
+ set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
+
return 0;
}
static int tun_chr_close(struct inode *inode, struct file *file)
{
struct tun_file *tfile = file->private_data;
- struct tun_struct *tun;
-
- tun = __tun_get(tfile);
- if (tun) {
- struct net_device *dev = tun->dev;
-
- tun_debug(KERN_INFO, tun, "tun_chr_close\n");
-
- __tun_detach(tun);
-
- /* If desirable, unregister the netdevice. */
- if (!(tun->flags & TUN_PERSIST)) {
- rtnl_lock();
- if (dev->reg_state == NETREG_REGISTERED)
- unregister_netdevice(dev);
- rtnl_unlock();
- }
- }
+ struct net *net = tfile->net;
- tun = tfile->tun;
- if (tun)
- sock_put(tun->socket.sk);
-
- put_net(tfile->net);
- kfree(tfile);
+ tun_detach(tfile, true);
+ put_net(net);
return 0;
}
@@ -1822,14 +2228,13 @@ static void tun_cleanup(void)
* holding a reference to the file for as long as the socket is in use. */
struct socket *tun_get_socket(struct file *file)
{
- struct tun_struct *tun;
+ struct tun_file *tfile;
if (file->f_op != &tun_fops)
return ERR_PTR(-EINVAL);
- tun = tun_get(file);
- if (!tun)
+ tfile = file->private_data;
+ if (!tfile)
return ERR_PTR(-EBADFD);
- tun_put(tun);
- return &tun->socket;
+ return &tfile->socket;
}
EXPORT_SYMBOL_GPL(tun_get_socket);
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index c1ae76968f47..ef976215b649 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -219,6 +219,24 @@ config USB_NET_CDC_NCM
* ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
* Ericsson F5521gw Mobile Broadband Module
+config USB_NET_CDC_MBIM
+ tristate "CDC MBIM support"
+ depends on USB_USBNET
+ select USB_WDM
+ select USB_NET_CDC_NCM
+ help
+ This driver provides support for CDC MBIM (Mobile Broadband
+ Interface Model) devices. The CDC MBIM specification is
+ available from <http://www.usb.org/>.
+
+ MBIM devices require configuration using the management
+ protocol defined by the MBIM specification. This driver
+ provides unfiltered access to the MBIM control channel
+ through the associated /dev/cdc-wdmx character device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cdc_mbim.
+
config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
@@ -230,6 +248,8 @@ config USB_NET_DM9601
config USB_NET_SMSC75XX
tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
depends on USB_USBNET
+ select BITREVERSE
+ select CRC16
select CRC32
help
This option adds support for SMSC LAN95XX based USB 2.0
@@ -238,6 +258,8 @@ config USB_NET_SMSC75XX
config USB_NET_SMSC95XX
tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
depends on USB_USBNET
+ select BITREVERSE
+ select CRC16
select CRC32
help
This option adds support for SMSC LAN95XX based USB 2.0
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index bf063008c1af..478691326f37 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -31,4 +31,5 @@ obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o
obj-$(CONFIG_USB_NET_CDC_NCM) += cdc_ncm.o
obj-$(CONFIG_USB_VL600) += lg-vl600.o
obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
+obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 774d9ce2dafc..50d167330d38 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -25,121 +25,30 @@
int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
- void *buf;
- int err = -ENOMEM;
-
- netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
-
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- goto out;
-
- err = usb_control_msg(
- dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- buf,
- size,
- USB_CTRL_GET_TIMEOUT);
- if (err == size)
- memcpy(data, buf, size);
- else if (err >= 0)
- err = -EINVAL;
- kfree(buf);
+ int ret;
+ ret = usbnet_read_cmd(dev, cmd,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, data, size);
-out:
- return err;
+ if (ret != size && ret >= 0)
+ return -EINVAL;
+ return ret;
}
int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
- void *buf = NULL;
- int err = -ENOMEM;
-
- netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
-
- if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
- if (!buf)
- goto out;
- }
-
- err = usb_control_msg(
- dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- buf,
- size,
- USB_CTRL_SET_TIMEOUT);
- kfree(buf);
-
-out:
- return err;
-}
-
-static void asix_async_cmd_callback(struct urb *urb)
-{
- struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
- int status = urb->status;
-
- if (status < 0)
- printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
- status);
-
- kfree(req);
- usb_free_urb(urb);
+ return usbnet_write_cmd(dev, cmd,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, data, size);
}
void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
- struct usb_ctrlrequest *req;
- int status;
- struct urb *urb;
-
- netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
- return;
- }
-
- req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
- if (!req) {
- netdev_err(dev->net, "Failed to allocate memory for control request\n");
- usb_free_urb(urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- req->bRequest = cmd;
- req->wValue = cpu_to_le16(value);
- req->wIndex = cpu_to_le16(index);
- req->wLength = cpu_to_le16(size);
-
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, size,
- asix_async_cmd_callback, req);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status < 0) {
- netdev_err(dev->net, "Error submitting the control message: status=%d\n",
- status);
- kfree(req);
- usb_free_urb(urb);
- }
+ usbnet_write_cmd_async(dev, cmd,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, data, size);
}
int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 33ab824773c5..7a6e758f48e7 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -64,6 +64,16 @@ static void asix_status(struct usbnet *dev, struct urb *urb)
}
}
+static void asix_set_netdev_dev_addr(struct usbnet *dev, u8 *addr)
+{
+ if (is_valid_ether_addr(addr)) {
+ memcpy(dev->net->dev_addr, addr, ETH_ALEN);
+ } else {
+ netdev_info(dev->net, "invalid hw address, using random\n");
+ eth_hw_addr_random(dev->net);
+ }
+}
+
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
static u32 asix_get_phyid(struct usbnet *dev)
{
@@ -225,7 +235,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
ret);
goto out;
}
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ asix_set_netdev_dev_addr(dev, buf);
/* Initialize MII structure */
dev->mii.dev = dev->net;
@@ -423,7 +434,8 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
return ret;
}
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ asix_set_netdev_dev_addr(dev, buf);
/* Initialize MII structure */
dev->mii.dev = dev->net;
@@ -777,7 +789,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
return ret;
}
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ asix_set_netdev_dev_addr(dev, buf);
/* Initialize MII structure */
dev->mii.dev = dev->net;
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
new file mode 100644
index 000000000000..42f51c71ec1f
--- /dev/null
+++ b/drivers/net/usb/cdc_mbim.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2012 Smith Micro Software, Inc.
+ * Copyright (c) 2012 Bjørn Mork <bjorn@mork.no>
+ *
+ * This driver is based on and reuse most of cdc_ncm, which is
+ * Copyright (C) ST-Ericsson 2010-2012
+ *
+ * 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc-wdm.h>
+#include <linux/usb/cdc_ncm.h>
+
+/* driver specific data - must match cdc_ncm usage */
+struct cdc_mbim_state {
+ struct cdc_ncm_ctx *ctx;
+ atomic_t pmcount;
+ struct usb_driver *subdriver;
+ struct usb_interface *control;
+ struct usb_interface *data;
+};
+
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int cdc_mbim_manage_power(struct usbnet *dev, int on)
+{
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ int rv = 0;
+
+ dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+
+ if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
+ /* need autopm_get/put here to ensure the usbcore sees the new value */
+ rv = usb_autopm_get_interface(dev->intf);
+ if (rv < 0)
+ goto err;
+ dev->intf->needs_remote_wakeup = on;
+ usb_autopm_put_interface(dev->intf);
+ }
+err:
+ return rv;
+}
+
+static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ /* can be called while disconnecting */
+ if (!dev)
+ return 0;
+
+ return cdc_mbim_manage_power(dev, status);
+}
+
+
+static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct cdc_ncm_ctx *ctx;
+ struct usb_driver *subdriver = ERR_PTR(-ENODEV);
+ int ret = -ENODEV;
+ u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+ struct cdc_mbim_state *info = (void *)&dev->data;
+
+ /* see if interface supports MBIM alternate setting */
+ if (intf->num_altsetting == 2) {
+ if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+ usb_set_interface(dev->udev,
+ intf->cur_altsetting->desc.bInterfaceNumber,
+ CDC_NCM_COMM_ALTSETTING_MBIM);
+ data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
+ }
+
+ /* Probably NCM, defer for cdc_ncm_bind */
+ if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+ goto err;
+
+ ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
+ if (ret)
+ goto err;
+
+ ctx = info->ctx;
+
+ /* The MBIM descriptor and the status endpoint are required */
+ if (ctx->mbim_desc && dev->status)
+ subdriver = usb_cdc_wdm_register(ctx->control,
+ &dev->status->desc,
+ le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
+ cdc_mbim_wdm_manage_power);
+ if (IS_ERR(subdriver)) {
+ ret = PTR_ERR(subdriver);
+ cdc_ncm_unbind(dev, intf);
+ goto err;
+ }
+
+ /* can't let usbnet use the interrupt endpoint */
+ dev->status = NULL;
+ info->subdriver = subdriver;
+
+ /* MBIM cannot do ARP */
+ dev->net->flags |= IFF_NOARP;
+
+ /* no need to put the VLAN tci in the packet headers */
+ dev->net->features |= NETIF_F_HW_VLAN_TX;
+err:
+ return ret;
+}
+
+static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ struct cdc_ncm_ctx *ctx = info->ctx;
+
+ /* disconnect subdriver from control interface */
+ if (info->subdriver && info->subdriver->disconnect)
+ info->subdriver->disconnect(ctx->control);
+ info->subdriver = NULL;
+
+ /* let NCM unbind clean up both control and data interface */
+ cdc_ncm_unbind(dev, intf);
+}
+
+
+static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ struct sk_buff *skb_out;
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ struct cdc_ncm_ctx *ctx = info->ctx;
+ __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
+ u16 tci = 0;
+ u8 *c;
+
+ if (!ctx)
+ goto error;
+
+ if (skb) {
+ if (skb->len <= sizeof(ETH_HLEN))
+ goto error;
+
+ /* mapping VLANs to MBIM sessions:
+ * no tag => IPS session <0>
+ * 1 - 255 => IPS session <vlanid>
+ * 256 - 511 => DSS session <vlanid - 256>
+ * 512 - 4095 => unsupported, drop
+ */
+ vlan_get_tag(skb, &tci);
+
+ switch (tci & 0x0f00) {
+ case 0x0000: /* VLAN ID 0 - 255 */
+ /* verify that datagram is IPv4 or IPv6 */
+ skb_reset_mac_header(skb);
+ switch (eth_hdr(skb)->h_proto) {
+ case htons(ETH_P_IP):
+ case htons(ETH_P_IPV6):
+ break;
+ default:
+ goto error;
+ }
+ c = (u8 *)&sign;
+ c[3] = tci;
+ break;
+ case 0x0100: /* VLAN ID 256 - 511 */
+ sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
+ c = (u8 *)&sign;
+ c[3] = tci;
+ break;
+ default:
+ netif_err(dev, tx_err, dev->net,
+ "unsupported tci=0x%04x\n", tci);
+ goto error;
+ }
+ skb_pull(skb, ETH_HLEN);
+ }
+
+ spin_lock_bh(&ctx->mtx);
+ skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign);
+ spin_unlock_bh(&ctx->mtx);
+ return skb_out;
+
+error:
+ if (skb)
+ dev_kfree_skb_any(skb);
+
+ return NULL;
+}
+
+static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
+{
+ __be16 proto = htons(ETH_P_802_3);
+ struct sk_buff *skb = NULL;
+
+ if (tci < 256) { /* IPS session? */
+ if (len < sizeof(struct iphdr))
+ goto err;
+
+ switch (*buf & 0xf0) {
+ case 0x40:
+ proto = htons(ETH_P_IP);
+ break;
+ case 0x60:
+ proto = htons(ETH_P_IPV6);
+ break;
+ default:
+ goto err;
+ }
+ }
+
+ skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN);
+ if (!skb)
+ goto err;
+
+ /* add an ethernet header */
+ skb_put(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ eth_hdr(skb)->h_proto = proto;
+ memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+ /* add datagram */
+ memcpy(skb_put(skb, len), buf, len);
+
+ /* map MBIM session to VLAN */
+ if (tci)
+ vlan_put_tag(skb, tci);
+err:
+ return skb;
+}
+
+static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+ struct sk_buff *skb;
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ struct cdc_ncm_ctx *ctx = info->ctx;
+ int len;
+ int nframes;
+ int x;
+ int offset;
+ struct usb_cdc_ncm_ndp16 *ndp16;
+ struct usb_cdc_ncm_dpe16 *dpe16;
+ int ndpoffset;
+ int loopcount = 50; /* arbitrary max preventing infinite loop */
+ u8 *c;
+ u16 tci;
+
+ ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+ if (ndpoffset < 0)
+ goto error;
+
+next_ndp:
+ nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+ if (nframes < 0)
+ goto error;
+
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+ switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
+ case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
+ c = (u8 *)&ndp16->dwSignature;
+ tci = c[3];
+ break;
+ case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
+ c = (u8 *)&ndp16->dwSignature;
+ tci = c[3] + 256;
+ break;
+ default:
+ netif_dbg(dev, rx_err, dev->net,
+ "unsupported NDP signature <0x%08x>\n",
+ le32_to_cpu(ndp16->dwSignature));
+ goto err_ndp;
+
+ }
+
+ dpe16 = ndp16->dpe16;
+ for (x = 0; x < nframes; x++, dpe16++) {
+ offset = le16_to_cpu(dpe16->wDatagramIndex);
+ len = le16_to_cpu(dpe16->wDatagramLength);
+
+ /*
+ * CDC NCM ch. 3.7
+ * All entries after first NULL entry are to be ignored
+ */
+ if ((offset == 0) || (len == 0)) {
+ if (!x)
+ goto err_ndp; /* empty NTB */
+ break;
+ }
+
+ /* sanity checking */
+ if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
+ netif_dbg(dev, rx_err, dev->net,
+ "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
+ x, offset, len, skb_in);
+ if (!x)
+ goto err_ndp;
+ break;
+ } else {
+ skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
+ if (!skb)
+ goto error;
+ usbnet_skb_return(dev, skb);
+ }
+ }
+err_ndp:
+ /* are there more NDPs to process? */
+ ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+ if (ndpoffset && loopcount--)
+ goto next_ndp;
+
+ return 1;
+error:
+ return 0;
+}
+
+static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ int ret = 0;
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ struct cdc_ncm_ctx *ctx = info->ctx;
+
+ if (ctx == NULL) {
+ ret = -1;
+ goto error;
+ }
+
+ ret = usbnet_suspend(intf, message);
+ if (ret < 0)
+ goto error;
+
+ if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
+ ret = info->subdriver->suspend(intf, message);
+ if (ret < 0)
+ usbnet_resume(intf);
+
+error:
+ return ret;
+}
+
+static int cdc_mbim_resume(struct usb_interface *intf)
+{
+ int ret = 0;
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct cdc_mbim_state *info = (void *)&dev->data;
+ struct cdc_ncm_ctx *ctx = info->ctx;
+ bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
+
+ if (callsub)
+ ret = info->subdriver->resume(intf);
+ if (ret < 0)
+ goto err;
+ ret = usbnet_resume(intf);
+ if (ret < 0 && callsub && info->subdriver->suspend)
+ info->subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+ return ret;
+}
+
+static const struct driver_info cdc_mbim_info = {
+ .description = "CDC MBIM",
+ .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+ .bind = cdc_mbim_bind,
+ .unbind = cdc_mbim_unbind,
+ .manage_power = cdc_mbim_manage_power,
+ .rx_fixup = cdc_mbim_rx_fixup,
+ .tx_fixup = cdc_mbim_tx_fixup,
+};
+
+static const struct usb_device_id mbim_devs[] = {
+ /* This duplicate NCM entry is intentional. MBIM devices can
+ * be disguised as NCM by default, and this is necessary to
+ * allow us to bind the correct driver_info to such devices.
+ *
+ * bind() will sort out this for us, selecting the correct
+ * entry and reject the other
+ */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&cdc_mbim_info,
+ },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&cdc_mbim_info,
+ },
+ {
+ },
+};
+MODULE_DEVICE_TABLE(usb, mbim_devs);
+
+static struct usb_driver cdc_mbim_driver = {
+ .name = "cdc_mbim",
+ .id_table = mbim_devs,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = cdc_mbim_suspend,
+ .resume = cdc_mbim_resume,
+ .reset_resume = cdc_mbim_resume,
+ .supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
+};
+module_usb_driver(cdc_mbim_driver);
+
+MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
+MODULE_DESCRIPTION("USB CDC MBIM host driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 74fab1a40156..d38bc20a60e2 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -51,90 +51,10 @@
#include <linux/atomic.h>
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc.h>
+#include <linux/usb/cdc_ncm.h>
#define DRIVER_VERSION "14-Mar-2012"
-/* CDC NCM subclass 3.2.1 */
-#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10
-
-/* Maximum NTB length */
-#define CDC_NCM_NTB_MAX_SIZE_TX 32768 /* bytes */
-#define CDC_NCM_NTB_MAX_SIZE_RX 32768 /* bytes */
-
-/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
-#define CDC_NCM_MIN_DATAGRAM_SIZE 1514 /* bytes */
-
-#define CDC_NCM_MIN_TX_PKT 512 /* bytes */
-
-/* Default value for MaxDatagramSize */
-#define CDC_NCM_MAX_DATAGRAM_SIZE 8192 /* bytes */
-
-/*
- * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
- * the last NULL entry.
- */
-#define CDC_NCM_DPT_DATAGRAMS_MAX 40
-
-/* Restart the timer, if amount of datagrams is less than given value */
-#define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3
-#define CDC_NCM_TIMER_PENDING_CNT 2
-#define CDC_NCM_TIMER_INTERVAL (400UL * NSEC_PER_USEC)
-
-/* The following macro defines the minimum header space */
-#define CDC_NCM_MIN_HDR_SIZE \
- (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
- (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
-
-struct cdc_ncm_data {
- struct usb_cdc_ncm_nth16 nth16;
- struct usb_cdc_ncm_ndp16 ndp16;
- struct usb_cdc_ncm_dpe16 dpe16[CDC_NCM_DPT_DATAGRAMS_MAX + 1];
-};
-
-struct cdc_ncm_ctx {
- struct cdc_ncm_data tx_ncm;
- struct usb_cdc_ncm_ntb_parameters ncm_parm;
- struct hrtimer tx_timer;
- struct tasklet_struct bh;
-
- const struct usb_cdc_ncm_desc *func_desc;
- const struct usb_cdc_header_desc *header_desc;
- const struct usb_cdc_union_desc *union_desc;
- const struct usb_cdc_ether_desc *ether_desc;
-
- struct net_device *netdev;
- struct usb_device *udev;
- struct usb_host_endpoint *in_ep;
- struct usb_host_endpoint *out_ep;
- struct usb_host_endpoint *status_ep;
- struct usb_interface *intf;
- struct usb_interface *control;
- struct usb_interface *data;
-
- struct sk_buff *tx_curr_skb;
- struct sk_buff *tx_rem_skb;
-
- spinlock_t mtx;
- atomic_t stop;
-
- u32 tx_timer_pending;
- u32 tx_curr_offset;
- u32 tx_curr_last_offset;
- u32 tx_curr_frame_num;
- u32 rx_speed;
- u32 tx_speed;
- u32 rx_max;
- u32 tx_max;
- u32 max_datagram_size;
- u16 tx_max_datagrams;
- u16 tx_remainder;
- u16 tx_modulus;
- u16 tx_ndp_modulus;
- u16 tx_seq;
- u16 rx_seq;
- u16 connected;
-};
-
static void cdc_ncm_txpath_bh(unsigned long param);
static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -158,17 +78,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
u8 flags;
u8 iface_no;
int err;
+ int eth_hlen;
u16 ntb_fmt_supported;
+ u32 min_dgram_size;
+ u32 min_hdr_size;
+ struct usbnet *dev = netdev_priv(ctx->netdev);
iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
- err = usb_control_msg(ctx->udev,
- usb_rcvctrlpipe(ctx->udev, 0),
- USB_CDC_GET_NTB_PARAMETERS,
- USB_TYPE_CLASS | USB_DIR_IN
- | USB_RECIP_INTERFACE,
- 0, iface_no, &ctx->ncm_parm,
- sizeof(ctx->ncm_parm), 10000);
+ err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS,
+ USB_TYPE_CLASS | USB_DIR_IN
+ |USB_RECIP_INTERFACE,
+ 0, iface_no, &ctx->ncm_parm,
+ sizeof(ctx->ncm_parm));
if (err < 0) {
pr_debug("failed GET_NTB_PARAMETERS\n");
return 1;
@@ -184,10 +106,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
- if (ctx->func_desc != NULL)
+ eth_hlen = ETH_HLEN;
+ min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+ min_hdr_size = CDC_NCM_MIN_HDR_SIZE;
+ if (ctx->mbim_desc != NULL) {
+ flags = ctx->mbim_desc->bmNetworkCapabilities;
+ eth_hlen = 0;
+ min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
+ min_hdr_size = 0;
+ } else if (ctx->func_desc != NULL) {
flags = ctx->func_desc->bmNetworkCapabilities;
- else
+ } else {
flags = 0;
+ }
pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
"wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
@@ -215,49 +146,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
/* inform device about NTB input size changes */
if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+ __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
- if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
- struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
-
- ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
- if (!ndp_in_sz) {
- err = -ENOMEM;
- goto size_err;
- }
-
- err = usb_control_msg(ctx->udev,
- usb_sndctrlpipe(ctx->udev, 0),
- USB_CDC_SET_NTB_INPUT_SIZE,
- USB_TYPE_CLASS | USB_DIR_OUT
- | USB_RECIP_INTERFACE,
- 0, iface_no, ndp_in_sz, 8, 1000);
- kfree(ndp_in_sz);
- } else {
- __le32 *dwNtbInMaxSize;
- dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
- GFP_KERNEL);
- if (!dwNtbInMaxSize) {
- err = -ENOMEM;
- goto size_err;
- }
- *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
-
- err = usb_control_msg(ctx->udev,
- usb_sndctrlpipe(ctx->udev, 0),
- USB_CDC_SET_NTB_INPUT_SIZE,
- USB_TYPE_CLASS | USB_DIR_OUT
- | USB_RECIP_INTERFACE,
- 0, iface_no, dwNtbInMaxSize, 4, 1000);
- kfree(dwNtbInMaxSize);
- }
-size_err:
+ err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE,
+ USB_TYPE_CLASS | USB_DIR_OUT
+ | USB_RECIP_INTERFACE,
+ 0, iface_no, &dwNtbInMaxSize, 4);
if (err < 0)
pr_debug("Setting NTB Input Size failed\n");
}
/* verify maximum size of transmitted NTB in bytes */
if ((ctx->tx_max <
- (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+ (min_hdr_size + min_dgram_size)) ||
(ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
pr_debug("Using default maximum transmit length=%d\n",
CDC_NCM_NTB_MAX_SIZE_TX);
@@ -299,93 +200,85 @@ size_err:
}
/* adjust TX-remainder according to NCM specification. */
- ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
- (ctx->tx_modulus - 1));
+ ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
+ (ctx->tx_modulus - 1));
/* additional configuration */
/* set CRC Mode */
if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
- err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
- USB_CDC_SET_CRC_MODE,
- USB_TYPE_CLASS | USB_DIR_OUT
- | USB_RECIP_INTERFACE,
- USB_CDC_NCM_CRC_NOT_APPENDED,
- iface_no, NULL, 0, 1000);
+ err = usbnet_write_cmd(dev, USB_CDC_SET_CRC_MODE,
+ USB_TYPE_CLASS | USB_DIR_OUT
+ | USB_RECIP_INTERFACE,
+ USB_CDC_NCM_CRC_NOT_APPENDED,
+ iface_no, NULL, 0);
if (err < 0)
pr_debug("Setting CRC mode off failed\n");
}
/* set NTB format, if both formats are supported */
if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
- err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
- USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS
- | USB_DIR_OUT | USB_RECIP_INTERFACE,
- USB_CDC_NCM_NTB16_FORMAT,
- iface_no, NULL, 0, 1000);
+ err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+ USB_TYPE_CLASS | USB_DIR_OUT
+ | USB_RECIP_INTERFACE,
+ USB_CDC_NCM_NTB16_FORMAT,
+ iface_no, NULL, 0);
if (err < 0)
pr_debug("Setting NTB format to 16-bit failed\n");
}
- ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+ ctx->max_datagram_size = min_dgram_size;
/* set Max Datagram Size (MTU) */
if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
- __le16 *max_datagram_size;
- u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
-
- max_datagram_size = kzalloc(sizeof(*max_datagram_size),
- GFP_KERNEL);
- if (!max_datagram_size) {
- err = -ENOMEM;
+ __le16 max_datagram_size;
+ u16 eth_max_sz;
+ if (ctx->ether_desc != NULL)
+ eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+ else if (ctx->mbim_desc != NULL)
+ eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+ else
goto max_dgram_err;
- }
- err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
- USB_CDC_GET_MAX_DATAGRAM_SIZE,
- USB_TYPE_CLASS | USB_DIR_IN
- | USB_RECIP_INTERFACE,
- 0, iface_no, max_datagram_size,
- 2, 1000);
+ err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
+ USB_TYPE_CLASS | USB_DIR_IN
+ | USB_RECIP_INTERFACE,
+ 0, iface_no, &max_datagram_size, 2);
if (err < 0) {
pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
- CDC_NCM_MIN_DATAGRAM_SIZE);
+ min_dgram_size);
} else {
ctx->max_datagram_size =
- le16_to_cpu(*max_datagram_size);
+ le16_to_cpu(max_datagram_size);
/* Check Eth descriptor value */
if (ctx->max_datagram_size > eth_max_sz)
ctx->max_datagram_size = eth_max_sz;
if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
- ctx->max_datagram_size =
- CDC_NCM_MAX_DATAGRAM_SIZE;
+ ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
- if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
- ctx->max_datagram_size =
- CDC_NCM_MIN_DATAGRAM_SIZE;
+ if (ctx->max_datagram_size < min_dgram_size)
+ ctx->max_datagram_size = min_dgram_size;
/* if value changed, update device */
if (ctx->max_datagram_size !=
- le16_to_cpu(*max_datagram_size)) {
- err = usb_control_msg(ctx->udev,
- usb_sndctrlpipe(ctx->udev, 0),
+ le16_to_cpu(max_datagram_size)) {
+ err = usbnet_write_cmd(dev,
USB_CDC_SET_MAX_DATAGRAM_SIZE,
USB_TYPE_CLASS | USB_DIR_OUT
| USB_RECIP_INTERFACE,
0,
- iface_no, max_datagram_size,
- 2, 1000);
+ iface_no, &max_datagram_size,
+ 2);
if (err < 0)
pr_debug("SET_MAX_DGRAM_SIZE failed\n");
}
}
- kfree(max_datagram_size);
}
max_dgram_err:
- if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
- ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+ if (ctx->netdev->mtu != (ctx->max_datagram_size - eth_hlen))
+ ctx->netdev->mtu = ctx->max_datagram_size - eth_hlen;
return 0;
}
@@ -451,7 +344,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
.nway_reset = usbnet_nway_reset,
};
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
{
struct cdc_ncm_ctx *ctx;
struct usb_driver *driver;
@@ -525,6 +418,13 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
break;
+ case USB_CDC_MBIM_TYPE:
+ if (buf[0] < sizeof(*(ctx->mbim_desc)))
+ break;
+
+ ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
+ break;
+
default:
break;
}
@@ -537,7 +437,7 @@ advance:
/* check if we got everything */
if ((ctx->control == NULL) || (ctx->data == NULL) ||
- (ctx->ether_desc == NULL) || (ctx->control != intf))
+ ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
goto error;
/* claim data interface, if different from control */
@@ -559,7 +459,7 @@ advance:
goto error2;
/* configure data interface */
- temp = usb_set_interface(dev->udev, iface_no, 1);
+ temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
if (temp)
goto error2;
@@ -576,11 +476,13 @@ advance:
usb_set_intfdata(ctx->control, dev);
usb_set_intfdata(ctx->intf, dev);
- temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
- if (temp)
- goto error2;
+ if (ctx->ether_desc) {
+ temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
+ if (temp)
+ goto error2;
+ dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+ }
- dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
dev->in = usb_rcvbulkpipe(dev->udev,
ctx->in_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
@@ -589,13 +491,6 @@ advance:
dev->status = ctx->status_ep;
dev->rx_urb_size = ctx->rx_max;
- /*
- * We should get an event when network connection is "connected" or
- * "disconnected". Set network connection in "disconnected" state
- * (carrier is OFF) during attach, so the IP network stack does not
- * start IPv6 negotiation and more.
- */
- netif_carrier_off(dev->net);
ctx->tx_speed = ctx->rx_speed = 0;
return 0;
@@ -609,8 +504,9 @@ error:
dev_info(&dev->udev->dev, "bind() failure\n");
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
-static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
+void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
{
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
struct usb_driver *driver = driver_of(intf);
@@ -644,52 +540,121 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
usb_set_intfdata(ctx->intf, NULL);
cdc_ncm_free(ctx);
}
+EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
-static void cdc_ncm_zero_fill(u8 *ptr, u32 first, u32 end, u32 max)
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
- if (first >= max)
- return;
- if (first >= end)
- return;
- if (end > max)
- end = max;
- memset(ptr + first, 0, end - first);
+ int ret;
+
+ /* The MBIM spec defines a NCM compatible default altsetting,
+ * which we may have matched:
+ *
+ * "Functions that implement both NCM 1.0 and MBIM (an
+ * “NCM/MBIM function”) according to this recommendation
+ * shall provide two alternate settings for the
+ * Communication Interface. Alternate setting 0, and the
+ * associated class and endpoint descriptors, shall be
+ * constructed according to the rules given for the
+ * Communication Interface in section 5 of [USBNCM10].
+ * Alternate setting 1, and the associated class and
+ * endpoint descriptors, shall be constructed according to
+ * the rules given in section 6 (USB Device Model) of this
+ * specification."
+ *
+ * Do not bind to such interfaces, allowing cdc_mbim to handle
+ * them
+ */
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+ if ((intf->num_altsetting == 2) &&
+ !usb_set_interface(dev->udev,
+ intf->cur_altsetting->desc.bInterfaceNumber,
+ CDC_NCM_COMM_ALTSETTING_MBIM) &&
+ cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+ return -ENODEV;
+#endif
+
+ /* NCM data altsetting is always 1 */
+ ret = cdc_ncm_bind_common(dev, intf, 1);
+
+ /*
+ * We should get an event when network connection is "connected" or
+ * "disconnected". Set network connection in "disconnected" state
+ * (carrier is OFF) during attach, so the IP network stack does not
+ * start IPv6 negotiation and more.
+ */
+ netif_carrier_off(dev->net);
+ return ret;
}
-static struct sk_buff *
-cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
+static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
{
+ size_t align = ALIGN(skb->len, modulus) - skb->len + remainder;
+
+ if (skb->len + align > max)
+ align = max - skb->len;
+ if (align && skb_tailroom(skb) >= align)
+ memset(skb_put(skb, align), 0, align);
+}
+
+/* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
+ * allocating a new one within skb
+ */
+static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+{
+ struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+ struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
+ size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
+
+ /* follow the chain of NDPs, looking for a match */
+ while (ndpoffset) {
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
+ if (ndp16->dwSignature == sign)
+ return ndp16;
+ ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+ }
+
+ /* align new NDP */
+ cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+
+ /* verify that there is room for the NDP and the datagram (reserve) */
+ if ((ctx->tx_max - skb->len - reserve) < CDC_NCM_NDP_SIZE)
+ return NULL;
+
+ /* link to it */
+ if (ndp16)
+ ndp16->wNextNdpIndex = cpu_to_le16(skb->len);
+ else
+ nth16->wNdpIndex = cpu_to_le16(skb->len);
+
+ /* push a new empty NDP */
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, CDC_NCM_NDP_SIZE), 0, CDC_NCM_NDP_SIZE);
+ ndp16->dwSignature = sign;
+ ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
+ return ndp16;
+}
+
+struct sk_buff *
+cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign)
+{
+ struct usb_cdc_ncm_nth16 *nth16;
+ struct usb_cdc_ncm_ndp16 *ndp16;
struct sk_buff *skb_out;
- u32 rem;
- u32 offset;
- u32 last_offset;
- u16 n = 0, index;
+ u16 n = 0, index, ndplen;
u8 ready2send = 0;
/* if there is a remaining skb, it gets priority */
- if (skb != NULL)
+ if (skb != NULL) {
swap(skb, ctx->tx_rem_skb);
- else
+ swap(sign, ctx->tx_rem_sign);
+ } else {
ready2send = 1;
-
- /*
- * +----------------+
- * | skb_out |
- * +----------------+
- * ^ offset
- * ^ last_offset
- */
+ }
/* check if we are resuming an OUT skb */
- if (ctx->tx_curr_skb != NULL) {
- /* pop variables */
- skb_out = ctx->tx_curr_skb;
- offset = ctx->tx_curr_offset;
- last_offset = ctx->tx_curr_last_offset;
- n = ctx->tx_curr_frame_num;
+ skb_out = ctx->tx_curr_skb;
- } else {
- /* reset variables */
+ /* allocate a new OUT skb */
+ if (!skb_out) {
skb_out = alloc_skb((ctx->tx_max + 1), GFP_ATOMIC);
if (skb_out == NULL) {
if (skb != NULL) {
@@ -698,35 +663,21 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
}
goto exit_no_skb;
}
+ /* fill out the initial 16-bit NTB header */
+ nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+ nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+ nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
+ nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
- /* make room for NTH and NDP */
- offset = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
- ctx->tx_ndp_modulus) +
- sizeof(struct usb_cdc_ncm_ndp16) +
- (ctx->tx_max_datagrams + 1) *
- sizeof(struct usb_cdc_ncm_dpe16);
-
- /* store last valid offset before alignment */
- last_offset = offset;
- /* align first Datagram offset correctly */
- offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
- /* zero buffer till the first IP datagram */
- cdc_ncm_zero_fill(skb_out->data, 0, offset, offset);
- n = 0;
+ /* count total number of frames in this NTB */
ctx->tx_curr_frame_num = 0;
}
- for (; n < ctx->tx_max_datagrams; n++) {
- /* check if end of transmit buffer is reached */
- if (offset >= ctx->tx_max) {
- ready2send = 1;
- break;
- }
- /* compute maximum buffer size */
- rem = ctx->tx_max - offset;
-
+ for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
+ /* send any remaining skb first */
if (skb == NULL) {
skb = ctx->tx_rem_skb;
+ sign = ctx->tx_rem_sign;
ctx->tx_rem_skb = NULL;
/* check for end of skb */
@@ -734,7 +685,14 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
break;
}
- if (skb->len > rem) {
+ /* get the appropriate NDP for this skb */
+ ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+
+ /* align beginning of next frame */
+ cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
+
+ /* check if we had enough room left for both NDP and frame */
+ if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
if (n == 0) {
/* won't fit, MTU problem? */
dev_kfree_skb_any(skb);
@@ -747,31 +705,30 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
ctx->netdev->stats.tx_dropped++;
}
ctx->tx_rem_skb = skb;
+ ctx->tx_rem_sign = sign;
skb = NULL;
ready2send = 1;
}
break;
}
- memcpy(((u8 *)skb_out->data) + offset, skb->data, skb->len);
-
- ctx->tx_ncm.dpe16[n].wDatagramLength = cpu_to_le16(skb->len);
- ctx->tx_ncm.dpe16[n].wDatagramIndex = cpu_to_le16(offset);
-
- /* update offset */
- offset += skb->len;
-
- /* store last valid offset before alignment */
- last_offset = offset;
-
- /* align offset correctly */
- offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+ /* calculate frame number withing this NDP */
+ ndplen = le16_to_cpu(ndp16->wLength);
+ index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
- /* zero padding */
- cdc_ncm_zero_fill(skb_out->data, last_offset, offset,
- ctx->tx_max);
+ /* OK, add this skb */
+ ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+ ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+ ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+ memcpy(skb_put(skb_out, skb->len), skb->data, skb->len);
dev_kfree_skb_any(skb);
skb = NULL;
+
+ /* send now if this NDP is full */
+ if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
+ ready2send = 1;
+ break;
+ }
}
/* free up any dangling skb */
@@ -787,16 +744,12 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
/* wait for more frames */
/* push variables */
ctx->tx_curr_skb = skb_out;
- ctx->tx_curr_offset = offset;
- ctx->tx_curr_last_offset = last_offset;
goto exit_no_skb;
} else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
/* wait for more frames */
/* push variables */
ctx->tx_curr_skb = skb_out;
- ctx->tx_curr_offset = offset;
- ctx->tx_curr_last_offset = last_offset;
/* set the pending count */
if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
@@ -807,75 +760,24 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
/* variables will be reset at next call */
}
- /* check for overflow */
- if (last_offset > ctx->tx_max)
- last_offset = ctx->tx_max;
-
- /* revert offset */
- offset = last_offset;
-
/*
* If collected data size is less or equal CDC_NCM_MIN_TX_PKT bytes,
* we send buffers as it is. If we get more data, it would be more
* efficient for USB HS mobile device with DMA engine to receive a full
* size NTB, than canceling DMA transfer and receiving a short packet.
*/
- if (offset > CDC_NCM_MIN_TX_PKT)
- offset = ctx->tx_max;
-
- /* final zero padding */
- cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);
-
- /* store last offset */
- last_offset = offset;
-
- if (((last_offset < ctx->tx_max) && ((last_offset %
- le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) ||
- (((last_offset == ctx->tx_max) && ((ctx->tx_max %
- le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) &&
- (ctx->tx_max < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)))) {
- /* force short packet */
- *(((u8 *)skb_out->data) + last_offset) = 0;
- last_offset++;
- }
-
- /* zero the rest of the DPEs plus the last NULL entry */
- for (; n <= CDC_NCM_DPT_DATAGRAMS_MAX; n++) {
- ctx->tx_ncm.dpe16[n].wDatagramLength = 0;
- ctx->tx_ncm.dpe16[n].wDatagramIndex = 0;
- }
+ if (skb_out->len > CDC_NCM_MIN_TX_PKT)
+ /* final zero padding */
+ memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len);
- /* fill out 16-bit NTB header */
- ctx->tx_ncm.nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
- ctx->tx_ncm.nth16.wHeaderLength =
- cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
- ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
- ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
- index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
- ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
-
- memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
- ctx->tx_seq++;
-
- /* fill out 16-bit NDP table */
- ctx->tx_ncm.ndp16.dwSignature =
- cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN);
- rem = sizeof(ctx->tx_ncm.ndp16) + ((ctx->tx_curr_frame_num + 1) *
- sizeof(struct usb_cdc_ncm_dpe16));
- ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
- ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
-
- memcpy(((u8 *)skb_out->data) + index,
- &(ctx->tx_ncm.ndp16),
- sizeof(ctx->tx_ncm.ndp16));
+ /* do we need to prevent a ZLP? */
+ if (((skb_out->len % le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0) &&
+ (skb_out->len < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)) && skb_tailroom(skb_out))
+ *skb_put(skb_out, 1) = 0; /* force short packet */
- memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
- &(ctx->tx_ncm.dpe16),
- (ctx->tx_curr_frame_num + 1) *
- sizeof(struct usb_cdc_ncm_dpe16));
-
- /* set frame length */
- skb_put(skb_out, last_offset);
+ /* set final frame length */
+ nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+ nth16->wBlockLength = cpu_to_le16(skb_out->len);
/* return skb */
ctx->tx_curr_skb = NULL;
@@ -888,6 +790,7 @@ exit_no_skb:
cdc_ncm_tx_timeout_start(ctx);
return NULL;
}
+EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
{
@@ -922,6 +825,8 @@ static void cdc_ncm_txpath_bh(unsigned long param)
netif_tx_lock_bh(ctx->netdev);
usbnet_start_xmit(NULL, ctx->netdev);
netif_tx_unlock_bh(ctx->netdev);
+ } else {
+ spin_unlock_bh(&ctx->mtx);
}
}
@@ -942,7 +847,7 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
goto error;
spin_lock_bh(&ctx->mtx);
- skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
+ skb_out = cdc_ncm_fill_tx_frame(ctx, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
spin_unlock_bh(&ctx->mtx);
return skb_out;
@@ -953,17 +858,12 @@ error:
return NULL;
}
-static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+/* verify NTB header and return offset of first NDP, or negative error */
+int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
{
- struct sk_buff *skb;
- struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
- int len;
- int nframes;
- int x;
- int offset;
struct usb_cdc_ncm_nth16 *nth16;
- struct usb_cdc_ncm_ndp16 *ndp16;
- struct usb_cdc_ncm_dpe16 *dpe16;
+ int len;
+ int ret = -EINVAL;
if (ctx == NULL)
goto error;
@@ -997,20 +897,23 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
}
ctx->rx_seq = le16_to_cpu(nth16->wSequence);
- len = le16_to_cpu(nth16->wNdpIndex);
- if ((len + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
- pr_debug("invalid DPT16 index <%u>\n",
- le16_to_cpu(nth16->wNdpIndex));
- goto error;
- }
+ ret = le16_to_cpu(nth16->wNdpIndex);
+error:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
- ndp16 = (struct usb_cdc_ncm_ndp16 *)(((u8 *)skb_in->data) + len);
+/* verify NDP header and return number of datagrams, or negative error */
+int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
+{
+ struct usb_cdc_ncm_ndp16 *ndp16;
+ int ret = -EINVAL;
- if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
- pr_debug("invalid DPT16 signature <%u>\n",
- le32_to_cpu(ndp16->dwSignature));
+ if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
+ pr_debug("invalid NDP offset <%u>\n", ndpoffset);
goto error;
}
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
pr_debug("invalid DPT16 length <%u>\n",
@@ -1018,20 +921,52 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
goto error;
}
- nframes = ((le16_to_cpu(ndp16->wLength) -
+ ret = ((le16_to_cpu(ndp16->wLength) -
sizeof(struct usb_cdc_ncm_ndp16)) /
sizeof(struct usb_cdc_ncm_dpe16));
- nframes--; /* we process NDP entries except for the last one */
-
- len += sizeof(struct usb_cdc_ncm_ndp16);
+ ret--; /* we process NDP entries except for the last one */
- if ((len + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
+ if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
skb_in->len) {
- pr_debug("Invalid nframes = %d\n", nframes);
- goto error;
+ pr_debug("Invalid nframes = %d\n", ret);
+ ret = -EINVAL;
}
- dpe16 = (struct usb_cdc_ncm_dpe16 *)(((u8 *)skb_in->data) + len);
+error:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
+
+static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+ struct sk_buff *skb;
+ struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+ int len;
+ int nframes;
+ int x;
+ int offset;
+ struct usb_cdc_ncm_ndp16 *ndp16;
+ struct usb_cdc_ncm_dpe16 *dpe16;
+ int ndpoffset;
+ int loopcount = 50; /* arbitrary max preventing infinite loop */
+
+ ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+ if (ndpoffset < 0)
+ goto error;
+
+next_ndp:
+ nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+ if (nframes < 0)
+ goto error;
+
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+ if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+ pr_debug("invalid DPT16 signature <%u>\n",
+ le32_to_cpu(ndp16->dwSignature));
+ goto err_ndp;
+ }
+ dpe16 = ndp16->dpe16;
for (x = 0; x < nframes; x++, dpe16++) {
offset = le16_to_cpu(dpe16->wDatagramIndex);
@@ -1043,7 +978,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
*/
if ((offset == 0) || (len == 0)) {
if (!x)
- goto error; /* empty NTB */
+ goto err_ndp; /* empty NTB */
break;
}
@@ -1054,7 +989,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
"offset[%u]=%u, length=%u, skb=%p\n",
x, offset, len, skb_in);
if (!x)
- goto error;
+ goto err_ndp;
break;
} else {
@@ -1067,6 +1002,12 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
usbnet_skb_return(dev, skb);
}
}
+err_ndp:
+ /* are there more NDPs to process? */
+ ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+ if (ndpoffset && loopcount--)
+ goto next_ndp;
+
return 1;
error:
return 0;
@@ -1131,7 +1072,7 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
* USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
* sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
*/
- ctx->connected = event->wValue;
+ ctx->connected = le16_to_cpu(event->wValue);
printk(KERN_INFO KBUILD_MODNAME ": %s: network connection:"
" %sconnected\n",
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index e0433ce6ced7..3f554c1149f3 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -56,27 +56,12 @@
static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
{
- void *buf;
- int err = -ENOMEM;
-
- netdev_dbg(dev->net, "dm_read() reg=0x%02x length=%d\n", reg, length);
-
- buf = kmalloc(length, GFP_KERNEL);
- if (!buf)
- goto out;
-
- err = usb_control_msg(dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- DM_READ_REGS,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
- if (err == length)
- memcpy(data, buf, length);
- else if (err >= 0)
+ int err;
+ err = usbnet_read_cmd(dev, DM_READ_REGS,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, reg, data, length);
+ if(err != length && err >= 0)
err = -EINVAL;
- kfree(buf);
-
- out:
return err;
}
@@ -87,91 +72,29 @@ static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
{
- void *buf = NULL;
- int err = -ENOMEM;
-
- netdev_dbg(dev->net, "dm_write() reg=0x%02x, length=%d\n", reg, length);
+ int err;
+ err = usbnet_write_cmd(dev, DM_WRITE_REGS,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, reg, data, length);
- if (data) {
- buf = kmemdup(data, length, GFP_KERNEL);
- if (!buf)
- goto out;
- }
-
- err = usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- DM_WRITE_REGS,
- USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
- 0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
- kfree(buf);
if (err >= 0 && err < length)
err = -EINVAL;
- out:
return err;
}
static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
{
- netdev_dbg(dev->net, "dm_write_reg() reg=0x%02x, value=0x%02x\n",
- reg, value);
- return usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- DM_WRITE_REG,
- USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
- value, reg, NULL, 0, USB_CTRL_SET_TIMEOUT);
-}
-
-static void dm_write_async_callback(struct urb *urb)
-{
- struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
- int status = urb->status;
-
- if (status < 0)
- printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n",
- status);
-
- kfree(req);
- usb_free_urb(urb);
+ return usbnet_write_cmd(dev, DM_WRITE_REGS,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, reg, NULL, 0);
}
static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value,
u16 length, void *data)
{
- struct usb_ctrlrequest *req;
- struct urb *urb;
- int status;
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- netdev_err(dev->net, "Error allocating URB in dm_write_async_helper!\n");
- return;
- }
-
- req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
- if (!req) {
- netdev_err(dev->net, "Failed to allocate memory for control request\n");
- usb_free_urb(urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- req->bRequest = length ? DM_WRITE_REGS : DM_WRITE_REG;
- req->wValue = cpu_to_le16(value);
- req->wIndex = cpu_to_le16(reg);
- req->wLength = cpu_to_le16(length);
-
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, length,
- dm_write_async_callback, req);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status < 0) {
- netdev_err(dev->net, "Error submitting the control message: status=%d\n",
- status);
- kfree(req);
- usb_free_urb(urb);
- }
+ usbnet_write_cmd_async(dev, DM_WRITE_REGS,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, reg, data, length);
}
static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c
index 8de641713d5f..ace9e74ffbdd 100644
--- a/drivers/net/usb/int51x1.c
+++ b/drivers/net/usb/int51x1.c
@@ -116,23 +116,8 @@ static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev,
return skb;
}
-static void int51x1_async_cmd_callback(struct urb *urb)
-{
- struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
- int status = urb->status;
-
- if (status < 0)
- dev_warn(&urb->dev->dev, "async callback failed with %d\n", status);
-
- kfree(req);
- usb_free_urb(urb);
-}
-
static void int51x1_set_multicast(struct net_device *netdev)
{
- struct usb_ctrlrequest *req;
- int status;
- struct urb *urb;
struct usbnet *dev = netdev_priv(netdev);
u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
@@ -149,40 +134,9 @@ static void int51x1_set_multicast(struct net_device *netdev)
netdev_dbg(dev->net, "receive own packets only\n");
}
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- netdev_warn(dev->net, "Error allocating URB\n");
- return;
- }
-
- req = kmalloc(sizeof(*req), GFP_ATOMIC);
- if (!req) {
- netdev_warn(dev->net, "Error allocating control msg\n");
- goto out;
- }
-
- req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- req->bRequest = SET_ETHERNET_PACKET_FILTER;
- req->wValue = cpu_to_le16(filter);
- req->wIndex = 0;
- req->wLength = 0;
-
- usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
- (void *)req, NULL, 0,
- int51x1_async_cmd_callback,
- (void *)req);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status < 0) {
- netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
- status);
- goto out1;
- }
- return;
-out1:
- kfree(req);
-out:
- usb_free_urb(urb);
+ usbnet_write_cmd_async(dev, SET_ETHERNET_PACKET_FILTER,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ filter, 0, NULL, 0);
}
static const struct net_device_ops int51x1_netdev_ops = {
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index cc7e72010ac3..3f3f566afa0b 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -124,93 +124,20 @@ static const char driver_name[] = "MOSCHIP usb-ethernet driver";
static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
{
- struct usb_device *xdev = dev->udev;
- int ret;
- void *buffer;
-
- buffer = kmalloc(size, GFP_NOIO);
- if (buffer == NULL)
- return -ENOMEM;
-
- ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ,
- MCS7830_RD_BMREQ, 0x0000, index, buffer,
- size, MCS7830_CTRL_TIMEOUT);
- memcpy(data, buffer, size);
- kfree(buffer);
-
- return ret;
+ return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
+ 0x0000, index, data, size);
}
static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
{
- struct usb_device *xdev = dev->udev;
- int ret;
- void *buffer;
-
- buffer = kmemdup(data, size, GFP_NOIO);
- if (buffer == NULL)
- return -ENOMEM;
-
- ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ,
- MCS7830_WR_BMREQ, 0x0000, index, buffer,
- size, MCS7830_CTRL_TIMEOUT);
- kfree(buffer);
- return ret;
-}
-
-static void mcs7830_async_cmd_callback(struct urb *urb)
-{
- struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
- int status = urb->status;
-
- if (status < 0)
- printk(KERN_DEBUG "%s() failed with %d\n",
- __func__, status);
-
- kfree(req);
- usb_free_urb(urb);
+ return usbnet_write_cmd(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+ 0x0000, index, data, size);
}
static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
{
- struct usb_ctrlrequest *req;
- int ret;
- struct urb *urb;
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- dev_dbg(&dev->udev->dev,
- "Error allocating URB in write_cmd_async!\n");
- return;
- }
-
- req = kmalloc(sizeof *req, GFP_ATOMIC);
- if (!req) {
- dev_err(&dev->udev->dev,
- "Failed to allocate memory for control request\n");
- goto out;
- }
- req->bRequestType = MCS7830_WR_BMREQ;
- req->bRequest = MCS7830_WR_BREQ;
- req->wValue = 0;
- req->wIndex = cpu_to_le16(index);
- req->wLength = cpu_to_le16(size);
-
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, size,
- mcs7830_async_cmd_callback, req);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- dev_err(&dev->udev->dev,
- "Error submitting the control message: ret=%d\n", ret);
- goto out;
- }
- return;
-out:
- kfree(req);
- usb_free_urb(urb);
+ usbnet_write_cmd_async(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+ 0x0000, index, data, size);
}
static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr)
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
index c062a3e8295c..93e0716a118c 100644
--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -109,13 +109,11 @@ struct nc_trailer {
static int
nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
{
- int status = usb_control_msg(dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, regnum,
- retval_ptr, sizeof *retval_ptr,
- USB_CTRL_GET_TIMEOUT);
+ int status = usbnet_read_cmd(dev, req,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
+ 0, regnum, retval_ptr,
+ sizeof *retval_ptr);
if (status > 0)
status = 0;
if (!status)
@@ -133,13 +131,9 @@ nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
static void
nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
{
- usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- req,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, regnum,
- NULL, 0, // data is in setup packet
- USB_CTRL_SET_TIMEOUT);
+ usbnet_write_cmd(dev, req,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, regnum, NULL, 0);
}
static inline void
@@ -288,37 +282,34 @@ static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
static int net1080_reset(struct usbnet *dev)
{
u16 usbctl, status, ttl;
- u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+ u16 vp;
int retval;
- if (!vp)
- return -ENOMEM;
-
// nc_dump_registers(dev);
- if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
+ if ((retval = nc_register_read(dev, REG_STATUS, &vp)) < 0) {
netdev_dbg(dev->net, "can't read %s-%s status: %d\n",
dev->udev->bus->bus_name, dev->udev->devpath, retval);
goto done;
}
- status = *vp;
+ status = vp;
nc_dump_status(dev, status);
- if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
+ if ((retval = nc_register_read(dev, REG_USBCTL, &vp)) < 0) {
netdev_dbg(dev->net, "can't read USBCTL, %d\n", retval);
goto done;
}
- usbctl = *vp;
+ usbctl = vp;
nc_dump_usbctl(dev, usbctl);
nc_register_write(dev, REG_USBCTL,
USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
- if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
+ if ((retval = nc_register_read(dev, REG_TTL, &vp)) < 0) {
netdev_dbg(dev->net, "can't read TTL, %d\n", retval);
goto done;
}
- ttl = *vp;
+ ttl = vp;
// nc_dump_ttl(dev, ttl);
nc_register_write(dev, REG_TTL,
@@ -331,7 +322,6 @@ static int net1080_reset(struct usbnet *dev)
retval = 0;
done:
- kfree(vp);
return retval;
}
@@ -339,13 +329,10 @@ static int net1080_check_connect(struct usbnet *dev)
{
int retval;
u16 status;
- u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+ u16 vp;
- if (!vp)
- return -ENOMEM;
- retval = nc_register_read(dev, REG_STATUS, vp);
- status = *vp;
- kfree(vp);
+ retval = nc_register_read(dev, REG_STATUS, &vp);
+ status = vp;
if (retval != 0) {
netdev_dbg(dev->net, "net1080_check_conn read - %d\n", retval);
return retval;
@@ -355,59 +342,22 @@ static int net1080_check_connect(struct usbnet *dev)
return 0;
}
-static void nc_flush_complete(struct urb *urb)
-{
- kfree(urb->context);
- usb_free_urb(urb);
-}
-
static void nc_ensure_sync(struct usbnet *dev)
{
- dev->frame_errors++;
- if (dev->frame_errors > 5) {
- struct urb *urb;
- struct usb_ctrlrequest *req;
- int status;
-
- /* Send a flush */
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb)
- return;
-
- req = kmalloc(sizeof *req, GFP_ATOMIC);
- if (!req) {
- usb_free_urb(urb);
- return;
- }
+ if (++dev->frame_errors <= 5)
+ return;
- req->bRequestType = USB_DIR_OUT
- | USB_TYPE_VENDOR
- | USB_RECIP_DEVICE;
- req->bRequest = REQUEST_REGISTER;
- req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS
- | USBCTL_FLUSH_OTHER);
- req->wIndex = cpu_to_le16(REG_USBCTL);
- req->wLength = cpu_to_le16(0);
-
- /* queue an async control request, we don't need
- * to do anything when it finishes except clean up.
- */
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (unsigned char *) req,
- NULL, 0,
- nc_flush_complete, req);
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status) {
- kfree(req);
- usb_free_urb(urb);
- return;
- }
+ if (usbnet_write_cmd_async(dev, REQUEST_REGISTER,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
+ USBCTL_FLUSH_THIS |
+ USBCTL_FLUSH_OTHER,
+ REG_USBCTL, NULL, 0))
+ return;
- netif_dbg(dev, rx_err, dev->net,
- "flush net1080; too many framing errors\n");
- dev->frame_errors = 0;
- }
+ netif_dbg(dev, rx_err, dev->net,
+ "flush net1080; too many framing errors\n");
+ dev->frame_errors = 0;
}
static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
index 4584b9a805b3..0fcc8e65a068 100644
--- a/drivers/net/usb/plusb.c
+++ b/drivers/net/usb/plusb.c
@@ -71,13 +71,10 @@
static inline int
pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
{
- return usb_control_msg(dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- val, index,
- NULL, 0,
- USB_CTRL_GET_TIMEOUT);
+ return usbnet_read_cmd(dev, req,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
+ val, index, NULL, 0);
}
static inline int
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index c27d27701aee..18dd4257ab17 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -311,10 +311,9 @@ static int sierra_net_send_cmd(struct usbnet *dev,
struct sierra_net_data *priv = sierra_net_get_private(dev);
int status;
- status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_CDC_SEND_ENCAPSULATED_COMMAND,
- USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0,
- priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT);
+ status = usbnet_write_cmd(dev, USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
+ 0, priv->ifnum, cmd, cmdlen);
if (status != cmdlen && status != -ENODEV)
netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status);
@@ -340,7 +339,7 @@ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix);
priv->tx_hdr_template[0] = 0x3F;
priv->tx_hdr_template[1] = ctx_ix;
- *((u16 *)&priv->tx_hdr_template[2]) =
+ *((__be16 *)&priv->tx_hdr_template[2]) =
cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID);
}
@@ -632,32 +631,22 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
{
int result = 0;
- u16 *attrdata;
-
- attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
- if (!attrdata)
- return -ENOMEM;
-
- result = usb_control_msg(
- dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- /* _u8 vendor specific request */
- SWI_USB_REQUEST_GET_FW_ATTR,
- USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */
- 0x0000, /* __u16 value not used */
- 0x0000, /* __u16 index not used */
- attrdata, /* char *data */
- sizeof(*attrdata), /* __u16 size */
- USB_CTRL_SET_TIMEOUT); /* int timeout */
-
- if (result < 0) {
- kfree(attrdata);
+ __le16 attrdata;
+
+ result = usbnet_read_cmd(dev,
+ /* _u8 vendor specific request */
+ SWI_USB_REQUEST_GET_FW_ATTR,
+ USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */
+ 0x0000, /* __u16 value not used */
+ 0x0000, /* __u16 index not used */
+ &attrdata, /* char *data */
+ sizeof(attrdata) /* __u16 size */
+ );
+
+ if (result < 0)
return -EIO;
- }
-
- *datap = le16_to_cpu(*attrdata);
- kfree(attrdata);
+ *datap = le16_to_cpu(attrdata);
return result;
}
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index b77ae76f4aa8..251a3354a4b0 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -26,6 +26,8 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
#include <linux/slab.h>
@@ -52,16 +54,15 @@
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define RXW_PADDING 2
-#define SUPPORTED_WAKE (WAKE_MAGIC)
+#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+ WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
-#define check_warn(ret, fmt, args...) \
- ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
-
-#define check_warn_return(ret, fmt, args...) \
- ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
-
-#define check_warn_goto_done(ret, fmt, args...) \
- ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
+#define SUSPEND_SUSPEND0 (0x01)
+#define SUSPEND_SUSPEND1 (0x02)
+#define SUSPEND_SUSPEND2 (0x04)
+#define SUSPEND_SUSPEND3 (0x08)
+#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
struct smsc75xx_priv {
struct usbnet *dev;
@@ -71,6 +72,7 @@ struct smsc75xx_priv {
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
struct work_struct set_multicast;
+ u8 suspend_flags;
};
struct usb_context {
@@ -82,96 +84,99 @@ static bool turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
-static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
- u32 *data)
+static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
{
- u32 *buf = kmalloc(4, GFP_KERNEL);
+ u32 buf;
int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
BUG_ON(!dev);
- if (!buf)
- return -ENOMEM;
-
- ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
- USB_VENDOR_REQUEST_READ_REGISTER,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+ if (!in_pm)
+ fn = usbnet_read_cmd;
+ else
+ fn = usbnet_read_cmd_nopm;
+ ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
if (unlikely(ret < 0))
- netdev_warn(dev->net,
- "Failed to read reg index 0x%08x: %d", index, ret);
+ netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+ index, ret);
- le32_to_cpus(buf);
- *data = *buf;
- kfree(buf);
+ le32_to_cpus(&buf);
+ *data = buf;
return ret;
}
-static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
- u32 data)
+static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data, int in_pm)
{
- u32 *buf = kmalloc(4, GFP_KERNEL);
+ u32 buf;
int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
BUG_ON(!dev);
- if (!buf)
- return -ENOMEM;
-
- *buf = data;
- cpu_to_le32s(buf);
+ if (!in_pm)
+ fn = usbnet_write_cmd;
+ else
+ fn = usbnet_write_cmd_nopm;
- ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_VENDOR_REQUEST_WRITE_REGISTER,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+ buf = data;
+ cpu_to_le32s(&buf);
+ ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
if (unlikely(ret < 0))
- netdev_warn(dev->net,
- "Failed to write reg index 0x%08x: %d", index, ret);
-
- kfree(buf);
+ netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+ index, ret);
return ret;
}
-static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index,
+ u32 *data)
{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
-
- cpu_to_le32s(&feature);
-
- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+ return __smsc75xx_read_reg(dev, index, data, 1);
}
-static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index,
+ u32 data)
{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
+ return __smsc75xx_write_reg(dev, index, data, 1);
+}
- cpu_to_le32s(&feature);
+static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data)
+{
+ return __smsc75xx_read_reg(dev, index, data, 0);
+}
- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data)
+{
+ return __smsc75xx_write_reg(dev, index, data, 0);
}
/* Loop until the read is completed with timeout
* called with phy_mutex held */
-static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
+static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
+ int in_pm)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
- ret = smsc75xx_read_reg(dev, MII_ACCESS, &val);
- check_warn_return(ret, "Error reading MII_ACCESS");
+ ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_ACCESS\n");
+ return ret;
+ }
if (!(val & MII_ACCESS_BUSY))
return 0;
@@ -180,7 +185,8 @@ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
return -EIO;
}
-static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+ int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -189,8 +195,11 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc75xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read");
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_read\n");
+ goto done;
+ }
/* set the address, index & direction (read from PHY) */
phy_id &= dev->mii.phy_id_mask;
@@ -198,14 +207,23 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_READ | MII_ACCESS_BUSY;
- ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
- check_warn_goto_done(ret, "Error writing MII_ACCESS");
+ ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_ACCESS\n");
+ goto done;
+ }
- ret = smsc75xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
+ goto done;
+ }
- ret = smsc75xx_read_reg(dev, MII_DATA, &val);
- check_warn_goto_done(ret, "Error reading MII_DATA");
+ ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_DATA\n");
+ goto done;
+ }
ret = (u16)(val & 0xFFFF);
@@ -214,8 +232,8 @@ done:
return ret;
}
-static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
- int regval)
+static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
+ int idx, int regval, int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -224,12 +242,18 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc75xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write");
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_write\n");
+ goto done;
+ }
val = regval;
- ret = smsc75xx_write_reg(dev, MII_DATA, val);
- check_warn_goto_done(ret, "Error writing MII_DATA");
+ ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_DATA\n");
+ goto done;
+ }
/* set the address, index & direction (write to PHY) */
phy_id &= dev->mii.phy_id_mask;
@@ -237,16 +261,45 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_WRITE | MII_ACCESS_BUSY;
- ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
- check_warn_goto_done(ret, "Error writing MII_ACCESS");
+ ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_ACCESS\n");
+ goto done;
+ }
- ret = smsc75xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
+ goto done;
+ }
done:
mutex_unlock(&dev->phy_mutex);
}
+static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+ int idx)
+{
+ return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+ int idx, int regval)
+{
+ __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+ return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+ int regval)
+{
+ __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
static int smsc75xx_wait_eeprom(struct usbnet *dev)
{
unsigned long start_time = jiffies;
@@ -255,7 +308,10 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
do {
ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
- check_warn_return(ret, "Error reading E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_CMD\n");
+ return ret;
+ }
if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
break;
@@ -263,7 +319,7 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
} while (!time_after(jiffies, start_time + HZ));
if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
- netdev_warn(dev->net, "EEPROM read operation timeout");
+ netdev_warn(dev->net, "EEPROM read operation timeout\n");
return -EIO;
}
@@ -278,7 +334,10 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
do {
ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
- check_warn_return(ret, "Error reading E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_CMD\n");
+ return ret;
+ }
if (!(val & E2P_CMD_BUSY))
return 0;
@@ -286,7 +345,7 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
udelay(40);
} while (!time_after(jiffies, start_time + HZ));
- netdev_warn(dev->net, "EEPROM is busy");
+ netdev_warn(dev->net, "EEPROM is busy\n");
return -EIO;
}
@@ -306,14 +365,20 @@ static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
for (i = 0; i < length; i++) {
val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_CMD\n");
+ return ret;
+ }
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
return ret;
ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
- check_warn_return(ret, "Error reading E2P_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_DATA\n");
+ return ret;
+ }
data[i] = val & 0xFF;
offset++;
@@ -338,7 +403,10 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Issue write/erase enable command */
val = E2P_CMD_BUSY | E2P_CMD_EWEN;
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_CMD\n");
+ return ret;
+ }
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
@@ -349,12 +417,18 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Fill data register */
val = data[i];
ret = smsc75xx_write_reg(dev, E2P_DATA, val);
- check_warn_return(ret, "Error writing E2P_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_DATA\n");
+ return ret;
+ }
/* Send "write" command */
val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_CMD\n");
+ return ret;
+ }
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
@@ -373,7 +447,10 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
for (i = 0; i < 100; i++) {
u32 dp_sel;
ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
- check_warn_return(ret, "Error reading DP_SEL");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading DP_SEL\n");
+ return ret;
+ }
if (dp_sel & DP_SEL_DPRDY)
return 0;
@@ -381,7 +458,7 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
udelay(40);
}
- netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out");
+ netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out\n");
return -EIO;
}
@@ -396,28 +473,49 @@ static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
mutex_lock(&pdata->dataport_mutex);
ret = smsc75xx_dataport_wait_not_busy(dev);
- check_warn_goto_done(ret, "smsc75xx_dataport_write busy on entry");
+ if (ret < 0) {
+ netdev_warn(dev->net, "smsc75xx_dataport_write busy on entry\n");
+ goto done;
+ }
ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
- check_warn_goto_done(ret, "Error reading DP_SEL");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading DP_SEL\n");
+ goto done;
+ }
dp_sel &= ~DP_SEL_RSEL;
dp_sel |= ram_select;
ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
- check_warn_goto_done(ret, "Error writing DP_SEL");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing DP_SEL\n");
+ goto done;
+ }
for (i = 0; i < length; i++) {
ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
- check_warn_goto_done(ret, "Error writing DP_ADDR");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing DP_ADDR\n");
+ goto done;
+ }
ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
- check_warn_goto_done(ret, "Error writing DP_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing DP_DATA\n");
+ goto done;
+ }
ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE);
- check_warn_goto_done(ret, "Error writing DP_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing DP_CMD\n");
+ goto done;
+ }
ret = smsc75xx_dataport_wait_not_busy(dev);
- check_warn_goto_done(ret, "smsc75xx_dataport_write timeout");
+ if (ret < 0) {
+ netdev_warn(dev->net, "smsc75xx_dataport_write timeout\n");
+ goto done;
+ }
}
done:
@@ -438,14 +536,15 @@ static void smsc75xx_deferred_multicast_write(struct work_struct *param)
struct usbnet *dev = pdata->dev;
int ret;
- netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x",
- pdata->rfe_ctl);
+ netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
+ pdata->rfe_ctl);
smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN,
DP_SEL_VHF_HASH_LEN, pdata->multicast_hash_table);
ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
- check_warn(ret, "Error writing RFE_CRL");
+ if (ret < 0)
+ netdev_warn(dev->net, "Error writing RFE_CRL\n");
}
static void smsc75xx_set_multicast(struct net_device *netdev)
@@ -465,15 +564,15 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
pdata->multicast_hash_table[i] = 0;
if (dev->net->flags & IFF_PROMISC) {
- netif_dbg(dev, drv, dev->net, "promiscuous mode enabled");
+ netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU;
} else if (dev->net->flags & IFF_ALLMULTI) {
- netif_dbg(dev, drv, dev->net, "receive all multicast enabled");
+ netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF;
} else if (!netdev_mc_empty(dev->net)) {
struct netdev_hw_addr *ha;
- netif_dbg(dev, drv, dev->net, "receive multicast hash filter");
+ netif_dbg(dev, drv, dev->net, "receive multicast hash filter\n");
pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF;
@@ -483,7 +582,7 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
(1 << (bitnum % 32));
}
} else {
- netif_dbg(dev, drv, dev->net, "receive own packets only");
+ netif_dbg(dev, drv, dev->net, "receive own packets only\n");
pdata->rfe_ctl |= RFE_CTL_DPF;
}
@@ -511,18 +610,24 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex,
if (cap & FLOW_CTRL_RX)
flow |= FLOW_RX_FCEN;
- netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s",
- (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
- (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+ netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
+ (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+ (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
} else {
- netif_dbg(dev, link, dev->net, "half duplex");
+ netif_dbg(dev, link, dev->net, "half duplex\n");
}
ret = smsc75xx_write_reg(dev, FLOW, flow);
- check_warn_return(ret, "Error writing FLOW");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing FLOW\n");
+ return ret;
+ }
ret = smsc75xx_write_reg(dev, FCT_FLOW, fct_flow);
- check_warn_return(ret, "Error writing FCT_FLOW");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing FCT_FLOW\n");
+ return ret;
+ }
return 0;
}
@@ -539,16 +644,18 @@ static int smsc75xx_link_reset(struct usbnet *dev)
PHY_INT_SRC_CLEAR_ALL);
ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
- check_warn_return(ret, "Error writing INT_STS");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing INT_STS\n");
+ return ret;
+ }
mii_check_media(mii, 1, 1);
mii_ethtool_gset(&dev->mii, &ecmd);
lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
- netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x"
- " rmtadv: %04x", ethtool_cmd_speed(&ecmd),
- ecmd.duplex, lcladv, rmtadv);
+ netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
+ ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
}
@@ -558,21 +665,21 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb)
u32 intdata;
if (urb->actual_length != 4) {
- netdev_warn(dev->net,
- "unexpected urb length %d", urb->actual_length);
+ netdev_warn(dev->net, "unexpected urb length %d\n",
+ urb->actual_length);
return;
}
memcpy(&intdata, urb->transfer_buffer, 4);
le32_to_cpus(&intdata);
- netif_dbg(dev, link, dev->net, "intdata: 0x%08X", intdata);
+ netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
if (intdata & INT_ENP_PHY_INT)
usbnet_defer_kevent(dev, EVENT_LINK_RESET);
else
- netdev_warn(dev->net,
- "unexpected interrupt, intdata=0x%08X", intdata);
+ netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+ intdata);
}
static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net)
@@ -596,8 +703,8 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
struct usbnet *dev = netdev_priv(netdev);
if (ee->magic != LAN75XX_EEPROM_MAGIC) {
- netdev_warn(dev->net,
- "EEPROM: magic value mismatch: 0x%x", ee->magic);
+ netdev_warn(dev->net, "EEPROM: magic value mismatch: 0x%x\n",
+ ee->magic);
return -EINVAL;
}
@@ -619,9 +726,15 @@ static int smsc75xx_ethtool_set_wol(struct net_device *net,
{
struct usbnet *dev = netdev_priv(net);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ int ret;
pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
- return 0;
+
+ ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+ if (ret < 0)
+ netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
+
+ return ret;
}
static const struct ethtool_ops smsc75xx_ethtool_ops = {
@@ -657,14 +770,14 @@ static void smsc75xx_init_mac_address(struct usbnet *dev)
if (is_valid_ether_addr(dev->net->dev_addr)) {
/* eeprom values are valid so use them */
netif_dbg(dev, ifup, dev->net,
- "MAC address read from EEPROM");
+ "MAC address read from EEPROM\n");
return;
}
}
/* no eeprom, or eeprom values are invalid. generate random MAC */
eth_hw_addr_random(dev->net);
- netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr");
+ netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
}
static int smsc75xx_set_mac_address(struct usbnet *dev)
@@ -674,19 +787,29 @@ static int smsc75xx_set_mac_address(struct usbnet *dev)
u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
int ret = smsc75xx_write_reg(dev, RX_ADDRH, addr_hi);
- check_warn_return(ret, "Failed to write RX_ADDRH: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write RX_ADDRH: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_write_reg(dev, RX_ADDRL, addr_lo);
- check_warn_return(ret, "Failed to write RX_ADDRL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write RX_ADDRL: %d\n", ret);
+ return ret;
+ }
addr_hi |= ADDR_FILTX_FB_VALID;
ret = smsc75xx_write_reg(dev, ADDR_FILTX, addr_hi);
- check_warn_return(ret, "Failed to write ADDR_FILTX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write ADDR_FILTX: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, addr_lo);
- check_warn_return(ret, "Failed to write ADDR_FILTX+4: %d", ret);
+ if (ret < 0)
+ netdev_warn(dev->net, "Failed to write ADDR_FILTX+4: %d\n", ret);
- return 0;
+ return ret;
}
static int smsc75xx_phy_initialize(struct usbnet *dev)
@@ -708,12 +831,15 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
do {
msleep(10);
bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
- check_warn_return(bmcr, "Error reading MII_BMCR");
+ if (bmcr < 0) {
+ netdev_warn(dev->net, "Error reading MII_BMCR\n");
+ return bmcr;
+ }
timeout++;
} while ((bmcr & BMCR_RESET) && (timeout < 100));
if (timeout >= 100) {
- netdev_warn(dev->net, "timeout on PHY Reset");
+ netdev_warn(dev->net, "timeout on PHY Reset\n");
return -EIO;
}
@@ -725,14 +851,18 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
/* read and write to clear phy interrupt status */
ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
- check_warn_return(ret, "Error reading PHY_INT_SRC");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ return ret;
+ }
+
smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
PHY_INT_MASK_DEFAULT);
mii_nway_restart(&dev->mii);
- netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+ netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
return 0;
}
@@ -743,14 +873,20 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
bool rxenabled;
ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
- check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+ return ret;
+ }
rxenabled = ((buf & MAC_RX_RXEN) != 0);
if (rxenabled) {
buf &= ~MAC_RX_RXEN;
ret = smsc75xx_write_reg(dev, MAC_RX, buf);
- check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+ return ret;
+ }
}
/* add 4 to size for FCS */
@@ -758,12 +894,18 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE);
ret = smsc75xx_write_reg(dev, MAC_RX, buf);
- check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+ return ret;
+ }
if (rxenabled) {
buf |= MAC_RX_RXEN;
ret = smsc75xx_write_reg(dev, MAC_RX, buf);
- check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+ return ret;
+ }
}
return 0;
@@ -774,7 +916,10 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
struct usbnet *dev = netdev_priv(netdev);
int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
- check_warn_return(ret, "Failed to set mac rx frame length");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to set mac rx frame length\n");
+ return ret;
+ }
return usbnet_change_mtu(netdev, new_mtu);
}
@@ -799,19 +944,26 @@ static int smsc75xx_set_features(struct net_device *netdev,
/* it's racing here! */
ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
- check_warn_return(ret, "Error writing RFE_CTL");
+ if (ret < 0)
+ netdev_warn(dev->net, "Error writing RFE_CTL\n");
- return 0;
+ return ret;
}
-static int smsc75xx_wait_ready(struct usbnet *dev)
+static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm)
{
int timeout = 0;
do {
u32 buf;
- int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
- check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+ int ret;
+
+ ret = __smsc75xx_read_reg(dev, PMT_CTL, &buf, in_pm);
+
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+ return ret;
+ }
if (buf & PMT_CTL_DEV_RDY)
return 0;
@@ -820,7 +972,7 @@ static int smsc75xx_wait_ready(struct usbnet *dev)
timeout++;
} while (timeout < 100);
- netdev_warn(dev->net, "timeout waiting for device ready");
+ netdev_warn(dev->net, "timeout waiting for device ready\n");
return -EIO;
}
@@ -830,79 +982,112 @@ static int smsc75xx_reset(struct usbnet *dev)
u32 buf;
int ret = 0, timeout;
- netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+ netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset\n");
- ret = smsc75xx_wait_ready(dev);
- check_warn_return(ret, "device not ready in smsc75xx_reset");
+ ret = smsc75xx_wait_ready(dev, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "device not ready in smsc75xx_reset\n");
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
buf |= HW_CFG_LRST;
ret = smsc75xx_write_reg(dev, HW_CFG, buf);
- check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+ return ret;
+ }
timeout = 0;
do {
msleep(10);
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
timeout++;
} while ((buf & HW_CFG_LRST) && (timeout < 100));
if (timeout >= 100) {
- netdev_warn(dev->net, "timeout on completion of Lite Reset");
+ netdev_warn(dev->net, "timeout on completion of Lite Reset\n");
return -EIO;
}
- netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY");
+ netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY\n");
ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
- check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+ return ret;
+ }
buf |= PMT_CTL_PHY_RST;
ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
- check_warn_return(ret, "Failed to write PMT_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret);
+ return ret;
+ }
timeout = 0;
do {
msleep(10);
ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
- check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+ return ret;
+ }
timeout++;
} while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
if (timeout >= 100) {
- netdev_warn(dev->net, "timeout waiting for PHY Reset");
+ netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
return -EIO;
}
- netif_dbg(dev, ifup, dev->net, "PHY reset complete");
-
- smsc75xx_init_mac_address(dev);
+ netif_dbg(dev, ifup, dev->net, "PHY reset complete\n");
ret = smsc75xx_set_mac_address(dev);
- check_warn_return(ret, "Failed to set mac address");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to set mac address\n");
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "MAC Address: %pM", dev->net->dev_addr);
+ netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+ dev->net->dev_addr);
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+ buf);
buf |= HW_CFG_BIR;
ret = smsc75xx_write_reg(dev, HW_CFG, buf);
- check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after "
- "writing HW_CFG_BIR: 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR: 0x%08x\n",
+ buf);
if (!turbo_mode) {
buf = 0;
@@ -915,99 +1100,157 @@ static int smsc75xx_reset(struct usbnet *dev)
dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
}
- netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld",
- (ulong)dev->rx_urb_size);
+ netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+ (ulong)dev->rx_urb_size);
ret = smsc75xx_write_reg(dev, BURST_CAP, buf);
- check_warn_return(ret, "Failed to write BURST_CAP: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, BURST_CAP, &buf);
- check_warn_return(ret, "Failed to read BURST_CAP: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net,
- "Read Value from BURST_CAP after writing: 0x%08x", buf);
+ "Read Value from BURST_CAP after writing: 0x%08x\n", buf);
ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
- check_warn_return(ret, "Failed to write BULK_IN_DLY: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, BULK_IN_DLY, &buf);
- check_warn_return(ret, "Failed to read BULK_IN_DLY: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net,
- "Read Value from BULK_IN_DLY after writing: 0x%08x", buf);
+ "Read Value from BULK_IN_DLY after writing: 0x%08x\n", buf);
if (turbo_mode) {
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
buf |= (HW_CFG_MEF | HW_CFG_BCE);
ret = smsc75xx_write_reg(dev, HW_CFG, buf);
- check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
}
/* set FIFO sizes */
buf = (MAX_RX_FIFO_SIZE - 512) / 512;
ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, buf);
- check_warn_return(ret, "Failed to write FCT_RX_FIFO_END: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FCT_RX_FIFO_END: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x\n", buf);
buf = (MAX_TX_FIFO_SIZE - 512) / 512;
ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, buf);
- check_warn_return(ret, "Failed to write FCT_TX_FIFO_END: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FCT_TX_FIFO_END: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x\n", buf);
ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
- check_warn_return(ret, "Failed to write INT_STS: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, ID_REV, &buf);
- check_warn_return(ret, "Failed to read ID_REV: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", buf);
ret = smsc75xx_read_reg(dev, E2P_CMD, &buf);
- check_warn_return(ret, "Failed to read E2P_CMD: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read E2P_CMD: %d\n", ret);
+ return ret;
+ }
/* only set default GPIO/LED settings if no EEPROM is detected */
if (!(buf & E2P_CMD_LOADED)) {
ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
- check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read LED_GPIO_CFG: %d\n", ret);
+ return ret;
+ }
buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
- check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
+ return ret;
+ }
}
ret = smsc75xx_write_reg(dev, FLOW, 0);
- check_warn_return(ret, "Failed to write FLOW: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_write_reg(dev, FCT_FLOW, 0);
- check_warn_return(ret, "Failed to write FCT_FLOW: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FCT_FLOW: %d\n", ret);
+ return ret;
+ }
/* Don't need rfe_ctl_lock during initialisation */
ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
- check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
+ return ret;
+ }
pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF;
ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
- check_warn_return(ret, "Failed to write RFE_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write RFE_CTL: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
- check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl);
+ netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x\n",
+ pdata->rfe_ctl);
/* Enable or disable checksum offload engines */
smsc75xx_set_features(dev->net, dev->net->features);
@@ -1015,69 +1258,111 @@ static int smsc75xx_reset(struct usbnet *dev)
smsc75xx_set_multicast(dev->net);
ret = smsc75xx_phy_initialize(dev);
- check_warn_return(ret, "Failed to initialize PHY: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to initialize PHY: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, INT_EP_CTL, &buf);
- check_warn_return(ret, "Failed to read INT_EP_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
+ return ret;
+ }
/* enable PHY interrupts */
buf |= INT_ENP_PHY_INT;
ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
- check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
+ return ret;
+ }
/* allow mac to detect speed and duplex from phy */
ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
- check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
+ return ret;
+ }
buf |= (MAC_CR_ADD | MAC_CR_ASD);
ret = smsc75xx_write_reg(dev, MAC_CR, buf);
- check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
- check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_TX: %d\n", ret);
+ return ret;
+ }
buf |= MAC_TX_TXEN;
ret = smsc75xx_write_reg(dev, MAC_TX, buf);
- check_warn_return(ret, "Failed to write MAC_TX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_TX: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x\n", buf);
ret = smsc75xx_read_reg(dev, FCT_TX_CTL, &buf);
- check_warn_return(ret, "Failed to read FCT_TX_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read FCT_TX_CTL: %d\n", ret);
+ return ret;
+ }
buf |= FCT_TX_CTL_EN;
ret = smsc75xx_write_reg(dev, FCT_TX_CTL, buf);
- check_warn_return(ret, "Failed to write FCT_TX_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FCT_TX_CTL: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
- check_warn_return(ret, "Failed to set max rx frame length");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to set max rx frame length\n");
+ return ret;
+ }
ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
- check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+ return ret;
+ }
buf |= MAC_RX_RXEN;
ret = smsc75xx_write_reg(dev, MAC_RX, buf);
- check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x\n", buf);
ret = smsc75xx_read_reg(dev, FCT_RX_CTL, &buf);
- check_warn_return(ret, "Failed to read FCT_RX_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read FCT_RX_CTL: %d\n", ret);
+ return ret;
+ }
buf |= FCT_RX_CTL_EN;
ret = smsc75xx_write_reg(dev, FCT_RX_CTL, buf);
- check_warn_return(ret, "Failed to write FCT_RX_CTL: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FCT_RX_CTL: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x", buf);
+ netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x\n", buf);
- netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0");
+ netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0\n");
return 0;
}
@@ -1102,14 +1387,17 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
ret = usbnet_get_endpoints(dev, intf);
- check_warn_return(ret, "usbnet_get_endpoints failed: %d", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
+ return ret;
+ }
dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc75xx_priv),
GFP_KERNEL);
pdata = (struct smsc75xx_priv *)(dev->data[0]);
if (!pdata) {
- netdev_warn(dev->net, "Unable to allocate smsc75xx_priv");
+ netdev_warn(dev->net, "Unable to allocate smsc75xx_priv\n");
return -ENOMEM;
}
@@ -1132,8 +1420,20 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM;
+ ret = smsc75xx_wait_ready(dev, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "device not ready in smsc75xx_bind\n");
+ return ret;
+ }
+
+ smsc75xx_init_mac_address(dev);
+
/* Init all registers */
ret = smsc75xx_reset(dev);
+ if (ret < 0) {
+ netdev_warn(dev->net, "smsc75xx_reset error %d\n", ret);
+ return ret;
+ }
dev->net->netdev_ops = &smsc75xx_netdev_ops;
dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
@@ -1147,172 +1447,647 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
{
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
if (pdata) {
- netif_dbg(dev, ifdown, dev->net, "free pdata");
+ netif_dbg(dev, ifdown, dev->net, "free pdata\n");
kfree(pdata);
pdata = NULL;
dev->data[0] = 0;
}
}
+static u16 smsc_crc(const u8 *buffer, size_t len)
+{
+ return bitrev16(crc16(0xFFFF, buffer, len));
+}
+
+static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
+ u32 wuf_mask1)
+{
+ int cfg_base = WUF_CFGX + filter * 4;
+ int mask_base = WUF_MASKX + filter * 16;
+ int ret;
+
+ ret = smsc75xx_write_reg(dev, cfg_base, wuf_cfg);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_CFGX\n");
+ return ret;
+ }
+
+ ret = smsc75xx_write_reg(dev, mask_base, wuf_mask1);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+ return ret;
+ }
+
+ ret = smsc75xx_write_reg(dev, mask_base + 4, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+ return ret;
+ }
+
+ ret = smsc75xx_write_reg(dev, mask_base + 8, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+ return ret;
+ }
+
+ ret = smsc75xx_write_reg(dev, mask_base + 12, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend0(struct usbnet *dev)
+{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
+
+ val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
+ val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND0;
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend1(struct usbnet *dev)
+{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_1;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ /* clear wol status, enable energy detection */
+ val &= ~PMT_CTL_WUPS;
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND1;
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend2(struct usbnet *dev)
+{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_2;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND2;
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend3(struct usbnet *dev)
+{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading FCT_RX_CTL\n");
+ return ret;
+ }
+
+ if (val & FCT_RX_CTL_RXUSED) {
+ netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n");
+ return -EBUSY;
+ }
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ /* clear wol status */
+ val &= ~PMT_CTL_WUPS;
+ val |= PMT_CTL_WUPS_WOL;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND3;
+
+ return 0;
+}
+
+static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+ /* read to clear */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ return ret;
+ }
+
+ /* enable interrupt source */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
+ return ret;
+ }
+
+ ret |= mask;
+
+ smsc75xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+ return 0;
+}
+
+static int smsc75xx_link_ok_nopm(struct usbnet *dev)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ /* first, a dummy read, needed to latch some MII phys */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ return ret;
+ }
+
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ return ret;
+ }
+
+ return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up)
+{
+ int ret;
+
+ if (!netif_running(dev->net)) {
+ /* interface is ifconfig down so fully power down hw */
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
+ return smsc75xx_enter_suspend2(dev);
+ }
+
+ if (!link_up) {
+ /* link is down so enter EDPD mode */
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+
+ /* enable PHY wakeup events for if cable is attached */
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_ANEG_COMP);
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ return ret;
+ }
+
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+ return smsc75xx_enter_suspend1(dev);
+ }
+
+ /* enable PHY wakeup events so we remote wakeup if cable is pulled */
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_LINK_DOWN);
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ return ret;
+ }
+
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+ return smsc75xx_enter_suspend3(dev);
+}
+
static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val, link_up;
int ret;
- u32 val;
ret = usbnet_suspend(intf, message);
- check_warn_return(ret, "usbnet_suspend error");
+ if (ret < 0) {
+ netdev_warn(dev->net, "usbnet_suspend error\n");
+ return ret;
+ }
- /* if no wol options set, enter lowest power SUSPEND2 mode */
- if (!(pdata->wolopts & SUPPORTED_WAKE)) {
- netdev_info(dev->net, "entering SUSPEND2 mode");
+ if (pdata->suspend_flags) {
+ netdev_warn(dev->net, "error during last resume\n");
+ pdata->suspend_flags = 0;
+ }
+
+ /* determine if link is up using only _nopm functions */
+ link_up = smsc75xx_link_ok_nopm(dev);
+
+ if (message.event == PM_EVENT_AUTO_SUSPEND) {
+ ret = smsc75xx_autosuspend(dev, link_up);
+ goto done;
+ }
+
+ /* if we get this far we're not autosuspending */
+ /* if no wol options set, or if link is down and we're not waking on
+ * PHY activity, enter lowest power SUSPEND2 mode
+ */
+ if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+ !(link_up || (pdata->wolopts & WAKE_PHY))) {
+ netdev_info(dev->net, "entering SUSPEND2 mode\n");
/* disable energy detect (link up) & wake up events */
- ret = smsc75xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
val &= ~(WUCSR_MPEN | WUCSR_WUEN);
- ret = smsc75xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ goto done;
+ }
val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ goto done;
+ }
- /* enter suspend2 mode */
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ ret = smsc75xx_enter_suspend2(dev);
+ goto done;
+ }
- val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
- val |= PMT_CTL_SUS_MODE_2;
+ if (pdata->wolopts & WAKE_PHY) {
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ goto done;
+ }
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ /* if link is down then configure EDPD and enter SUSPEND1,
+ * otherwise enter SUSPEND0 below
+ */
+ if (!link_up) {
+ struct mii_if_info *mii = &dev->mii;
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+
+ /* enable energy detect power-down mode */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
+ PHY_MODE_CTRL_STS);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
+ goto done;
+ }
- return 0;
+ ret |= MODE_CTRL_STS_EDPWRDOWN;
+
+ smsc75xx_mdio_write_nopm(dev->net, mii->phy_id,
+ PHY_MODE_CTRL_STS, ret);
+
+ /* enter SUSPEND1 mode */
+ ret = smsc75xx_enter_suspend1(dev);
+ goto done;
+ }
}
- if (pdata->wolopts & WAKE_MAGIC) {
- /* clear any pending magic packet status */
- ret = smsc75xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
+ int i, filter = 0;
- val |= WUCSR_MPR;
+ /* disable all filters */
+ for (i = 0; i < WUF_NUM; i++) {
+ ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUF_CFGX\n");
+ goto done;
+ }
+ }
- ret = smsc75xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
- }
+ if (pdata->wolopts & WAKE_MCAST) {
+ const u8 mcast[] = {0x01, 0x00, 0x5E};
+ netdev_info(dev->net, "enabling multicast detection\n");
- /* enable/disable magic packup wake */
- ret = smsc75xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
+ | smsc_crc(mcast, 3);
+ ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing wakeup filter\n");
+ goto done;
+ }
+ }
- if (pdata->wolopts & WAKE_MAGIC) {
- netdev_info(dev->net, "enabling magic packet wakeup");
- val |= WUCSR_MPEN;
+ if (pdata->wolopts & WAKE_ARP) {
+ const u8 arp[] = {0x08, 0x06};
+ netdev_info(dev->net, "enabling ARP detection\n");
+
+ val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
+ | smsc_crc(arp, 2);
+ ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing wakeup filter\n");
+ goto done;
+ }
+ }
+
+ /* clear any pending pattern match packet status */
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
+
+ val |= WUCSR_WUFR;
+
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
+
+ netdev_info(dev->net, "enabling packet match detection\n");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
+
+ val |= WUCSR_WUEN;
+
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
} else {
- netdev_info(dev->net, "disabling magic packet wakeup");
- val &= ~WUCSR_MPEN;
+ netdev_info(dev->net, "disabling packet match detection\n");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
+
+ val &= ~WUCSR_WUEN;
+
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
}
- ret = smsc75xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ /* disable magic, bcast & unicast wakeup sources */
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
- /* enable wol wakeup source */
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
- val |= PMT_CTL_WOL_EN;
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ if (pdata->wolopts & WAKE_PHY) {
+ netdev_info(dev->net, "enabling PHY wakeup\n");
- /* enable receiver */
- ret = smsc75xx_read_reg(dev, MAC_RX, &val);
- check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ goto done;
+ }
- val |= MAC_RX_RXEN;
+ /* clear wol status, enable energy detection */
+ val &= ~PMT_CTL_WUPS;
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
- ret = smsc75xx_write_reg(dev, MAC_RX, val);
- check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ goto done;
+ }
+ }
- /* some wol options are enabled, so enter SUSPEND0 */
- netdev_info(dev->net, "entering SUSPEND0 mode");
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "enabling magic packet wakeup\n");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ /* clear any pending magic packet status */
+ val |= WUCSR_MPR | WUCSR_MPEN;
- val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST));
- val |= PMT_CTL_SUS_MODE_0;
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
+ }
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ if (pdata->wolopts & WAKE_BCAST) {
+ netdev_info(dev->net, "enabling broadcast detection\n");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
- /* clear wol status */
- val &= ~PMT_CTL_WUPS;
- val |= PMT_CTL_WUPS_WOL;
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
- /* read back PMT_CTL */
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
+ }
- smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ if (pdata->wolopts & WAKE_UCAST) {
+ netdev_info(dev->net, "enabling unicast detection\n");
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
- return 0;
+ val |= WUCSR_WUFR | WUCSR_PFDA_EN;
+
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
+ }
+
+ /* enable receiver to enable frame reception */
+ ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+ goto done;
+ }
+
+ val |= MAC_RX_RXEN;
+
+ ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+ goto done;
+ }
+
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode\n");
+ ret = smsc75xx_enter_suspend0(dev);
+
+done:
+ if (ret)
+ usbnet_resume(intf);
+ return ret;
}
static int smsc75xx_resume(struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u8 suspend_flags = pdata->suspend_flags;
int ret;
u32 val;
- if (pdata->wolopts & WAKE_MAGIC) {
- netdev_info(dev->net, "resuming from SUSPEND0");
+ netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
- smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ /* do this first to ensure it's cleared even in error case */
+ pdata->suspend_flags = 0;
- /* Disable magic packup wake */
- ret = smsc75xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ if (suspend_flags & SUSPEND_ALLMODES) {
+ /* Disable wakeup sources */
+ ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ return ret;
+ }
- val &= ~WUCSR_MPEN;
+ val &= ~(WUCSR_WUEN | WUCSR_MPEN | WUCSR_PFDA_EN
+ | WUCSR_BCST_EN);
- ret = smsc75xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ return ret;
+ }
/* clear wake-up status */
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
val &= ~PMT_CTL_WOL_EN;
val |= PMT_CTL_WUPS;
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
- } else {
- netdev_info(dev->net, "resuming from SUSPEND2");
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
+ }
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ if (suspend_flags & SUSPEND_SUSPEND2) {
+ netdev_info(dev->net, "resuming from SUSPEND2\n");
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PMT_CTL\n");
+ return ret;
+ }
val |= PMT_CTL_PHY_PWRUP;
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PMT_CTL\n");
+ return ret;
+ }
}
- ret = smsc75xx_wait_ready(dev);
- check_warn_return(ret, "device not ready in smsc75xx_resume");
+ ret = smsc75xx_wait_ready(dev, 1);
+ if (ret < 0) {
+ netdev_warn(dev->net, "device not ready in smsc75xx_resume\n");
+ return ret;
+ }
return usbnet_resume(intf);
}
@@ -1352,7 +2127,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
netif_dbg(dev, rx_err, dev->net,
- "Error rx_cmd_a=0x%08x", rx_cmd_a);
+ "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
dev->net->stats.rx_errors++;
dev->net->stats.rx_dropped++;
@@ -1364,7 +2139,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
/* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
if (unlikely(size > (ETH_FRAME_LEN + 12))) {
netif_dbg(dev, rx_err, dev->net,
- "size err rx_cmd_a=0x%08x", rx_cmd_a);
+ "size err rx_cmd_a=0x%08x\n",
+ rx_cmd_a);
return 0;
}
@@ -1381,7 +2157,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
ax_skb = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!ax_skb)) {
- netdev_warn(dev->net, "Error allocating skb");
+ netdev_warn(dev->net, "Error allocating skb\n");
return 0;
}
@@ -1406,7 +2182,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
if (unlikely(skb->len < 0)) {
- netdev_warn(dev->net, "invalid rx length<0 %d", skb->len);
+ netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
return 0;
}
@@ -1454,6 +2230,12 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
return skb;
}
+static int smsc75xx_manage_power(struct usbnet *dev, int on)
+{
+ dev->intf->needs_remote_wakeup = on;
+ return 0;
+}
+
static const struct driver_info smsc75xx_info = {
.description = "smsc75xx USB 2.0 Gigabit Ethernet",
.bind = smsc75xx_bind,
@@ -1463,6 +2245,7 @@ static const struct driver_info smsc75xx_info = {
.rx_fixup = smsc75xx_rx_fixup,
.tx_fixup = smsc75xx_tx_fixup,
.status = smsc75xx_status,
+ .manage_power = smsc75xx_manage_power,
.flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
@@ -1490,6 +2273,7 @@ static struct usb_driver smsc75xx_driver = {
.reset_resume = smsc75xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
+ .supports_autosuspend = 1,
};
module_usb_driver(smsc75xx_driver);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 362cb8cfeb92..9b736701f854 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -26,6 +26,8 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
#include <linux/slab.h>
@@ -46,16 +48,12 @@
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
#define SMSC95XX_TX_OVERHEAD_CSUM (12)
-#define SUPPORTED_WAKE (WAKE_MAGIC)
+#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+ WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
-#define check_warn(ret, fmt, args...) \
- ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
-
-#define check_warn_return(ret, fmt, args...) \
- ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
-
-#define check_warn_goto_done(ret, fmt, args...) \
- ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
+#define FEATURE_8_WAKEUP_FILTERS (0x01)
+#define FEATURE_PHY_NLP_CROSSOVER (0x02)
+#define FEATURE_AUTOSUSPEND (0x04)
struct smsc95xx_priv {
u32 mac_cr;
@@ -63,105 +61,107 @@ struct smsc95xx_priv {
u32 hash_lo;
u32 wolopts;
spinlock_t mac_cr_lock;
-};
-
-struct usb_context {
- struct usb_ctrlrequest req;
- struct usbnet *dev;
+ u8 features;
};
static bool turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
-static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
- u32 *data)
+static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
{
- u32 *buf = kmalloc(4, GFP_KERNEL);
+ u32 buf;
int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
BUG_ON(!dev);
- if (!buf)
- return -ENOMEM;
-
- ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
- USB_VENDOR_REQUEST_READ_REGISTER,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+ if (!in_pm)
+ fn = usbnet_read_cmd;
+ else
+ fn = usbnet_read_cmd_nopm;
+ ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
if (unlikely(ret < 0))
- netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index);
+ netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+ index, ret);
- le32_to_cpus(buf);
- *data = *buf;
- kfree(buf);
+ le32_to_cpus(&buf);
+ *data = buf;
return ret;
}
-static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
- u32 data)
+static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data, int in_pm)
{
- u32 *buf = kmalloc(4, GFP_KERNEL);
+ u32 buf;
int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
BUG_ON(!dev);
- if (!buf)
- return -ENOMEM;
-
- *buf = data;
- cpu_to_le32s(buf);
+ if (!in_pm)
+ fn = usbnet_write_cmd;
+ else
+ fn = usbnet_write_cmd_nopm;
- ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_VENDOR_REQUEST_WRITE_REGISTER,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+ buf = data;
+ cpu_to_le32s(&buf);
+ ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+ | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, &buf, 4);
if (unlikely(ret < 0))
- netdev_warn(dev->net, "Failed to write register index 0x%08x\n", index);
-
- kfree(buf);
+ netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+ index, ret);
return ret;
}
-static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc95xx_read_reg_nopm(struct usbnet *dev, u32 index,
+ u32 *data)
{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
-
- cpu_to_le32s(&feature);
-
- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+ return __smsc95xx_read_reg(dev, index, data, 1);
}
-static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc95xx_write_reg_nopm(struct usbnet *dev, u32 index,
+ u32 data)
{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
+ return __smsc95xx_write_reg(dev, index, data, 1);
+}
- cpu_to_le32s(&feature);
+static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data)
+{
+ return __smsc95xx_read_reg(dev, index, data, 0);
+}
- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data)
+{
+ return __smsc95xx_write_reg(dev, index, data, 0);
}
/* Loop until the read is completed with timeout
* called with phy_mutex held */
-static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
+static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
+ int in_pm)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
- ret = smsc95xx_read_reg(dev, MII_ADDR, &val);
- check_warn_return(ret, "Error reading MII_ACCESS");
+ ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_ACCESS\n");
+ return ret;
+ }
+
if (!(val & MII_BUSY_))
return 0;
} while (!time_after(jiffies, start_time + HZ));
@@ -169,7 +169,8 @@ static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
return -EIO;
}
-static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+ int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -178,21 +179,33 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc95xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read");
+ ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n");
+ goto done;
+ }
/* set the address, index & direction (read from PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
- ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
- check_warn_goto_done(ret, "Error writing MII_ADDR");
+ ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_ADDR\n");
+ goto done;
+ }
- ret = smsc95xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+ ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
+ goto done;
+ }
- ret = smsc95xx_read_reg(dev, MII_DATA, &val);
- check_warn_goto_done(ret, "Error reading MII_DATA");
+ ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_DATA\n");
+ goto done;
+ }
ret = (u16)(val & 0xFFFF);
@@ -201,8 +214,8 @@ done:
return ret;
}
-static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
- int regval)
+static void __smsc95xx_mdio_write(struct net_device *netdev, int phy_id,
+ int idx, int regval, int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -211,27 +224,62 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc95xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write");
+ ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n");
+ goto done;
+ }
val = regval;
- ret = smsc95xx_write_reg(dev, MII_DATA, val);
- check_warn_goto_done(ret, "Error writing MII_DATA");
+ ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_DATA\n");
+ goto done;
+ }
/* set the address, index & direction (write to PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
- ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
- check_warn_goto_done(ret, "Error writing MII_ADDR");
+ ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MII_ADDR\n");
+ goto done;
+ }
- ret = smsc95xx_phy_wait_not_busy(dev);
- check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+ ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
+ goto done;
+ }
done:
mutex_unlock(&dev->phy_mutex);
}
+static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+ int idx)
+{
+ return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+ int idx, int regval)
+{
+ __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+ return __smsc95xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+ int regval)
+{
+ __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
{
unsigned long start_time = jiffies;
@@ -240,7 +288,11 @@ static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
do {
ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
- check_warn_return(ret, "Error reading E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_CMD\n");
+ return ret;
+ }
+
if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
break;
udelay(40);
@@ -262,7 +314,10 @@ static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
do {
ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
- check_warn_return(ret, "Error reading E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_CMD\n");
+ return ret;
+ }
if (!(val & E2P_CMD_BUSY_))
return 0;
@@ -290,14 +345,20 @@ static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
for (i = 0; i < length; i++) {
val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
ret = smsc95xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_CMD\n");
+ return ret;
+ }
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
return ret;
ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
- check_warn_return(ret, "Error reading E2P_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading E2P_DATA\n");
+ return ret;
+ }
data[i] = val & 0xFF;
offset++;
@@ -322,7 +383,10 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Issue write/erase enable command */
val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
ret = smsc95xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_DATA\n");
+ return ret;
+ }
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
@@ -333,12 +397,18 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Fill data register */
val = data[i];
ret = smsc95xx_write_reg(dev, E2P_DATA, val);
- check_warn_return(ret, "Error writing E2P_DATA");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_DATA\n");
+ return ret;
+ }
/* Send "write" command */
val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
ret = smsc95xx_write_reg(dev, E2P_CMD, val);
- check_warn_return(ret, "Error writing E2P_CMD");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing E2P_CMD\n");
+ return ret;
+ }
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
@@ -350,60 +420,24 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
return 0;
}
-static void smsc95xx_async_cmd_callback(struct urb *urb)
-{
- struct usb_context *usb_context = urb->context;
- struct usbnet *dev = usb_context->dev;
- int status = urb->status;
-
- check_warn(status, "async callback failed with %d\n", status);
-
- kfree(usb_context);
- usb_free_urb(urb);
-}
-
static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
- u32 *data)
+ u32 data)
{
- struct usb_context *usb_context;
- int status;
- struct urb *urb;
const u16 size = 4;
+ u32 buf;
+ int ret;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- netdev_warn(dev->net, "Error allocating URB\n");
- return -ENOMEM;
- }
-
- usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC);
- if (usb_context == NULL) {
- netdev_warn(dev->net, "Error allocating control msg\n");
- usb_free_urb(urb);
- return -ENOMEM;
- }
-
- usb_context->req.bRequestType =
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER;
- usb_context->req.wValue = 00;
- usb_context->req.wIndex = cpu_to_le16(index);
- usb_context->req.wLength = cpu_to_le16(size);
-
- usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
- (void *)&usb_context->req, data, size,
- smsc95xx_async_cmd_callback,
- (void *)usb_context);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status < 0) {
- netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
- status);
- kfree(usb_context);
- usb_free_urb(urb);
- }
+ buf = data;
+ cpu_to_le32s(&buf);
- return status;
+ ret = usbnet_write_cmd_async(dev, USB_VENDOR_REQUEST_WRITE_REGISTER,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
+ 0, index, &buf, size);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error write async cmd, sts=%d\n",
+ ret);
+ return ret;
}
/* returns hash bit number for given MAC address
@@ -460,14 +494,17 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
/* Initiate async writes, as we can't wait for completion here */
- ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
- check_warn(ret, "failed to initiate async write to HASHH");
+ ret = smsc95xx_write_reg_async(dev, HASHH, pdata->hash_hi);
+ if (ret < 0)
+ netdev_warn(dev->net, "failed to initiate async write to HASHH\n");
- ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
- check_warn(ret, "failed to initiate async write to HASHL");
+ ret = smsc95xx_write_reg_async(dev, HASHL, pdata->hash_lo);
+ if (ret < 0)
+ netdev_warn(dev->net, "failed to initiate async write to HASHL\n");
- ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
- check_warn(ret, "failed to initiate async write to MAC_CR");
+ ret = smsc95xx_write_reg_async(dev, MAC_CR, pdata->mac_cr);
+ if (ret < 0)
+ netdev_warn(dev->net, "failed to initiate async write to MAC_CR\n");
}
static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
@@ -476,7 +513,10 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
u32 flow, afc_cfg = 0;
int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
- check_warn_return(ret, "Error reading AFC_CFG");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading AFC_CFG\n");
+ return ret;
+ }
if (duplex == DUPLEX_FULL) {
u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
@@ -501,12 +541,16 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
}
ret = smsc95xx_write_reg(dev, FLOW, flow);
- check_warn_return(ret, "Error writing FLOW");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing FLOW\n");
+ return ret;
+ }
ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
- check_warn_return(ret, "Error writing AFC_CFG");
+ if (ret < 0)
+ netdev_warn(dev->net, "Error writing AFC_CFG\n");
- return 0;
+ return ret;
}
static int smsc95xx_link_reset(struct usbnet *dev)
@@ -520,10 +564,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
/* clear interrupt status */
ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
- check_warn_return(ret, "Error reading PHY_INT_SRC");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ return ret;
+ }
ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
- check_warn_return(ret, "Error writing INT_STS");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing INT_STS\n");
+ return ret;
+ }
mii_check_media(mii, 1, 1);
mii_ethtool_gset(&dev->mii, &ecmd);
@@ -545,12 +595,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
- check_warn_return(ret, "Error writing MAC_CR");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing MAC_CR\n");
+ return ret;
+ }
ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
- check_warn_return(ret, "Error updating PHY flow control");
+ if (ret < 0)
+ netdev_warn(dev->net, "Error updating PHY flow control\n");
- return 0;
+ return ret;
}
static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
@@ -584,7 +638,10 @@ static int smsc95xx_set_features(struct net_device *netdev,
int ret;
ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
- check_warn_return(ret, "Failed to read COE_CR: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret);
+ return ret;
+ }
if (features & NETIF_F_HW_CSUM)
read_buf |= Tx_COE_EN_;
@@ -597,7 +654,10 @@ static int smsc95xx_set_features(struct net_device *netdev,
read_buf &= ~Rx_COE_EN_;
ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
- check_warn_return(ret, "Failed to write COE_CR: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
return 0;
@@ -635,7 +695,7 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
static int smsc95xx_ethtool_getregslen(struct net_device *netdev)
{
/* all smsc95xx registers */
- return COE_CR - ID_REV + 1;
+ return COE_CR - ID_REV + sizeof(u32);
}
static void
@@ -677,9 +737,15 @@ static int smsc95xx_ethtool_set_wol(struct net_device *net,
{
struct usbnet *dev = netdev_priv(net);
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ int ret;
pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
- return 0;
+
+ ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+ if (ret < 0)
+ netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
+
+ return ret;
}
static const struct ethtool_ops smsc95xx_ethtool_ops = {
@@ -734,12 +800,16 @@ static int smsc95xx_set_mac_address(struct usbnet *dev)
int ret;
ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
- check_warn_return(ret, "Failed to write ADDRL: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
- check_warn_return(ret, "Failed to write ADDRH: %d\n", ret);
+ if (ret < 0)
+ netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret);
- return 0;
+ return ret;
}
/* starts the TX path */
@@ -755,17 +825,21 @@ static int smsc95xx_start_tx_path(struct usbnet *dev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
- check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
+ return ret;
+ }
/* Enable Tx at SCSRs */
ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
- check_warn_return(ret, "Failed to write TX_CFG: %d\n", ret);
+ if (ret < 0)
+ netdev_warn(dev->net, "Failed to write TX_CFG: %d\n", ret);
- return 0;
+ return ret;
}
/* Starts the Receive path */
-static int smsc95xx_start_rx_path(struct usbnet *dev)
+static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
unsigned long flags;
@@ -775,10 +849,11 @@ static int smsc95xx_start_rx_path(struct usbnet *dev)
pdata->mac_cr |= MAC_CR_RXEN_;
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
- ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
- check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
+ ret = __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
+ if (ret < 0)
+ netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
- return 0;
+ return ret;
}
static int smsc95xx_phy_initialize(struct usbnet *dev)
@@ -813,7 +888,10 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
/* read to clear */
ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
- check_warn_return(ret, "Failed to read PHY_INT_SRC during init");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read PHY_INT_SRC during init\n");
+ return ret;
+ }
smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
PHY_INT_MASK_DEFAULT_);
@@ -832,13 +910,19 @@ static int smsc95xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
- check_warn_return(ret, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
+ return ret;
+ }
timeout = 0;
do {
msleep(10);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
timeout++;
} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
@@ -848,13 +932,19 @@ static int smsc95xx_reset(struct usbnet *dev)
}
ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
- check_warn_return(ret, "Failed to write PM_CTRL: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret);
+ return ret;
+ }
timeout = 0;
do {
msleep(10);
ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
- check_warn_return(ret, "Failed to read PM_CTRL: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret);
+ return ret;
+ }
timeout++;
} while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
@@ -867,22 +957,32 @@ static int smsc95xx_reset(struct usbnet *dev)
if (ret < 0)
return ret;
- netif_dbg(dev, ifup, dev->net,
- "MAC Address: %pM\n", dev->net->dev_addr);
+ netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+ dev->net->dev_addr);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net,
- "Read Value from HW_CFG : 0x%08x\n", read_buf);
+ netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+ read_buf);
read_buf |= HW_CFG_BIR_;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- check_warn_return(ret, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
+
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
read_buf);
@@ -898,34 +998,49 @@ static int smsc95xx_reset(struct usbnet *dev)
dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
}
- netif_dbg(dev, ifup, dev->net,
- "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
+ netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+ (ulong)dev->rx_urb_size);
ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
- check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
- check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net,
"Read Value from BURST_CAP after writing: 0x%08x\n",
read_buf);
ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
- check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
- check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net,
"Read Value from BULK_IN_DLY after writing: 0x%08x\n",
read_buf);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
- netif_dbg(dev, ifup, dev->net,
- "Read Value from HW_CFG: 0x%08x\n", read_buf);
+ netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n",
+ read_buf);
if (turbo_mode)
read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
@@ -936,66 +1051,111 @@ static int smsc95xx_reset(struct usbnet *dev)
read_buf |= NET_IP_ALIGN << 9;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
- check_warn_return(ret, "Failed to write INT_STS: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
- check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
/* Configure GPIO pins as LED outputs */
write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
LED_GPIO_CFG_FDX_LED;
ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
- check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
+ return ret;
+ }
/* Init Tx */
ret = smsc95xx_write_reg(dev, FLOW, 0);
- check_warn_return(ret, "Failed to write FLOW: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
- check_warn_return(ret, "Failed to write AFC_CFG: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret);
+ return ret;
+ }
/* Don't need mac_cr_lock during initialisation */
ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
- check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
+ return ret;
+ }
/* Init Rx */
/* Set Vlan */
ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
- check_warn_return(ret, "Failed to write VLAN1: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write VLAN1: %d\n", ret);
+ return ret;
+ }
/* Enable or disable checksum offload engines */
ret = smsc95xx_set_features(dev->net, dev->net->features);
- check_warn_return(ret, "Failed to set checksum offload features");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to set checksum offload features\n");
+ return ret;
+ }
smsc95xx_set_multicast(dev->net);
ret = smsc95xx_phy_initialize(dev);
- check_warn_return(ret, "Failed to init PHY");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to init PHY\n");
+ return ret;
+ }
ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
- check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
+ return ret;
+ }
/* enable PHY interrupts */
read_buf |= INT_EP_CTL_PHY_INT_;
ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
- check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
+ return ret;
+ }
ret = smsc95xx_start_tx_path(dev);
- check_warn_return(ret, "Failed to start TX path");
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to start TX path\n");
+ return ret;
+ }
- ret = smsc95xx_start_rx_path(dev);
- check_warn_return(ret, "Failed to start RX path");
+ ret = smsc95xx_start_rx_path(dev, 0);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to start RX path\n");
+ return ret;
+ }
netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
return 0;
@@ -1017,12 +1177,16 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
{
struct smsc95xx_priv *pdata = NULL;
+ u32 val;
int ret;
printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
ret = usbnet_get_endpoints(dev, intf);
- check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret);
+ if (ret < 0) {
+ netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
+ return ret;
+ }
dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
GFP_KERNEL);
@@ -1047,6 +1211,22 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
/* Init all registers */
ret = smsc95xx_reset(dev);
+ /* detect device revision as different features may be available */
+ ret = smsc95xx_read_reg(dev, ID_REV, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+ return ret;
+ }
+ val >>= 16;
+
+ if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
+ (val == ID_REV_CHIP_ID_89530_) || (val == ID_REV_CHIP_ID_9730_))
+ pdata->features = (FEATURE_8_WAKEUP_FILTERS |
+ FEATURE_PHY_NLP_CROSSOVER |
+ FEATURE_AUTOSUSPEND);
+ else if (val == ID_REV_CHIP_ID_9512_)
+ pdata->features = FEATURE_8_WAKEUP_FILTERS;
+
dev->net->netdev_ops = &smsc95xx_netdev_ops;
dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
@@ -1066,113 +1246,448 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
}
}
+static u32 smsc_crc(const u8 *buffer, size_t len, int filter)
+{
+ u32 crc = bitrev16(crc16(0xFFFF, buffer, len));
+ return crc << ((filter % 2) * 16);
+}
+
+static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+ /* read to clear */
+ ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+ return ret;
+ }
+
+ /* enable interrupt source */
+ ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
+ return ret;
+ }
+
+ ret |= mask;
+
+ smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+ return 0;
+}
+
+static int smsc95xx_link_ok_nopm(struct usbnet *dev)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ /* first, a dummy read, needed to latch some MII phys */
+ ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ return ret;
+ }
+
+ ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading MII_BMSR\n");
+ return ret;
+ }
+
+ return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc95xx_enter_suspend0(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ return ret;
+ }
+
+ val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
+ val |= PM_CTL_SUS_MODE_0;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ return ret;
+ }
+
+ /* clear wol status */
+ val &= ~PM_CTL_WUPS_;
+ val |= PM_CTL_WUPS_WOL_;
+
+ /* enable energy detection */
+ if (pdata->wolopts & WAKE_PHY)
+ val |= PM_CTL_WUPS_ED_;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ return ret;
+ }
+
+ /* read back PM_CTRL */
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+
+ return ret;
+}
+
+static int smsc95xx_enter_suspend1(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ struct mii_if_info *mii = &dev->mii;
+ u32 val;
+ int ret;
+
+ /* reconfigure link pulse detection timing for
+ * compatibility with non-standard link partners
+ */
+ if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
+ smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_EDPD_CONFIG,
+ PHY_EDPD_CONFIG_DEFAULT);
+
+ /* enable energy detect power-down mode */
+ ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
+ return ret;
+ }
+
+ ret |= MODE_CTRL_STS_EDPWRDOWN_;
+
+ smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS, ret);
+
+ /* enter SUSPEND1 mode */
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ return ret;
+ }
+
+ val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+ val |= PM_CTL_SUS_MODE_1;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ return ret;
+ }
+
+ /* clear wol status, enable energy detection */
+ val &= ~PM_CTL_WUPS_;
+ val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+
+ return ret;
+}
+
+static int smsc95xx_enter_suspend2(struct usbnet *dev)
+{
+ u32 val;
+ int ret;
+
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ return ret;
+ }
+
+ val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+ val |= PM_CTL_SUS_MODE_2;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+
+ return ret;
+}
+
static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u32 val, link_up;
int ret;
- u32 val;
ret = usbnet_suspend(intf, message);
- check_warn_return(ret, "usbnet_suspend error");
+ if (ret < 0) {
+ netdev_warn(dev->net, "usbnet_suspend error\n");
+ return ret;
+ }
- /* if no wol options set, enter lowest power SUSPEND2 mode */
- if (!(pdata->wolopts & SUPPORTED_WAKE)) {
- netdev_info(dev->net, "entering SUSPEND2 mode");
+ /* determine if link is up using only _nopm functions */
+ link_up = smsc95xx_link_ok_nopm(dev);
+
+ /* if no wol options set, or if link is down and we're not waking on
+ * PHY activity, enter lowest power SUSPEND2 mode
+ */
+ if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+ !(link_up || (pdata->wolopts & WAKE_PHY))) {
+ netdev_info(dev->net, "entering SUSPEND2 mode\n");
/* disable energy detect (link up) & wake up events */
- ret = smsc95xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
- ret = smsc95xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ goto done;
+ }
val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ goto done;
+ }
- /* enter suspend2 mode */
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
+ ret = smsc95xx_enter_suspend2(dev);
+ goto done;
+ }
- val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
- val |= PM_CTL_SUS_MODE_2;
+ if (pdata->wolopts & WAKE_PHY) {
+ ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+ (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
+ if (ret < 0) {
+ netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+ goto done;
+ }
+
+ /* if link is down then configure EDPD and enter SUSPEND1,
+ * otherwise enter SUSPEND0 below
+ */
+ if (!link_up) {
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+ ret = smsc95xx_enter_suspend1(dev);
+ goto done;
+ }
+ }
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
+ if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+ u32 *filter_mask = kzalloc(sizeof(u32) * 32, GFP_KERNEL);
+ u32 command[2];
+ u32 offset[2];
+ u32 crc[4];
+ int wuff_filter_count =
+ (pdata->features & FEATURE_8_WAKEUP_FILTERS) ?
+ LAN9500A_WUFF_NUM : LAN9500_WUFF_NUM;
+ int i, filter = 0;
+
+ if (!filter_mask) {
+ netdev_warn(dev->net, "Unable to allocate filter_mask\n");
+ ret = -ENOMEM;
+ goto done;
+ }
- return 0;
+ memset(command, 0, sizeof(command));
+ memset(offset, 0, sizeof(offset));
+ memset(crc, 0, sizeof(crc));
+
+ if (pdata->wolopts & WAKE_BCAST) {
+ const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ netdev_info(dev->net, "enabling broadcast detection\n");
+ filter_mask[filter * 4] = 0x003F;
+ filter_mask[filter * 4 + 1] = 0x00;
+ filter_mask[filter * 4 + 2] = 0x00;
+ filter_mask[filter * 4 + 3] = 0x00;
+ command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+ offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+ crc[filter/2] |= smsc_crc(bcast, 6, filter);
+ filter++;
+ }
+
+ if (pdata->wolopts & WAKE_MCAST) {
+ const u8 mcast[] = {0x01, 0x00, 0x5E};
+ netdev_info(dev->net, "enabling multicast detection\n");
+ filter_mask[filter * 4] = 0x0007;
+ filter_mask[filter * 4 + 1] = 0x00;
+ filter_mask[filter * 4 + 2] = 0x00;
+ filter_mask[filter * 4 + 3] = 0x00;
+ command[filter/4] |= 0x09UL << ((filter % 4) * 8);
+ offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+ crc[filter/2] |= smsc_crc(mcast, 3, filter);
+ filter++;
+ }
+
+ if (pdata->wolopts & WAKE_ARP) {
+ const u8 arp[] = {0x08, 0x06};
+ netdev_info(dev->net, "enabling ARP detection\n");
+ filter_mask[filter * 4] = 0x0003;
+ filter_mask[filter * 4 + 1] = 0x00;
+ filter_mask[filter * 4 + 2] = 0x00;
+ filter_mask[filter * 4 + 3] = 0x00;
+ command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+ offset[filter/4] |= 0x0C << ((filter % 4) * 8);
+ crc[filter/2] |= smsc_crc(arp, 2, filter);
+ filter++;
+ }
+
+ if (pdata->wolopts & WAKE_UCAST) {
+ netdev_info(dev->net, "enabling unicast detection\n");
+ filter_mask[filter * 4] = 0x003F;
+ filter_mask[filter * 4 + 1] = 0x00;
+ filter_mask[filter * 4 + 2] = 0x00;
+ filter_mask[filter * 4 + 3] = 0x00;
+ command[filter/4] |= 0x01UL << ((filter % 4) * 8);
+ offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+ crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
+ filter++;
+ }
+
+ for (i = 0; i < (wuff_filter_count * 4); i++) {
+ ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUFF\n");
+ kfree(filter_mask);
+ goto done;
+ }
+ }
+ kfree(filter_mask);
+
+ for (i = 0; i < (wuff_filter_count / 4); i++) {
+ ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUFF\n");
+ goto done;
+ }
+ }
+
+ for (i = 0; i < (wuff_filter_count / 4); i++) {
+ ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUFF\n");
+ goto done;
+ }
+ }
+
+ for (i = 0; i < (wuff_filter_count / 2); i++) {
+ ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUFF\n");
+ goto done;
+ }
+ }
+
+ /* clear any pending pattern match packet status */
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
+
+ val |= WUCSR_WUFR_;
+
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
}
if (pdata->wolopts & WAKE_MAGIC) {
/* clear any pending magic packet status */
- ret = smsc95xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
+ }
val |= WUCSR_MPR_;
- ret = smsc95xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
+ }
+
+ /* enable/disable wakeup sources */
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ goto done;
}
- /* enable/disable magic packup wake */
- ret = smsc95xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+ netdev_info(dev->net, "enabling pattern match wakeup\n");
+ val |= WUCSR_WAKE_EN_;
+ } else {
+ netdev_info(dev->net, "disabling pattern match wakeup\n");
+ val &= ~WUCSR_WAKE_EN_;
+ }
if (pdata->wolopts & WAKE_MAGIC) {
- netdev_info(dev->net, "enabling magic packet wakeup");
+ netdev_info(dev->net, "enabling magic packet wakeup\n");
val |= WUCSR_MPEN_;
} else {
- netdev_info(dev->net, "disabling magic packet wakeup");
+ netdev_info(dev->net, "disabling magic packet wakeup\n");
val &= ~WUCSR_MPEN_;
}
- ret = smsc95xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ goto done;
+ }
/* enable wol wakeup source */
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ goto done;
+ }
val |= PM_CTL_WOL_EN_;
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
-
- /* enable receiver */
- smsc95xx_start_rx_path(dev);
-
- /* some wol options are enabled, so enter SUSPEND0 */
- netdev_info(dev->net, "entering SUSPEND0 mode");
-
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
-
- val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
- val |= PM_CTL_SUS_MODE_0;
-
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
+ /* phy energy detect wakeup source */
+ if (pdata->wolopts & WAKE_PHY)
+ val |= PM_CTL_ED_EN_;
- /* clear wol status */
- val &= ~PM_CTL_WUPS_;
- val |= PM_CTL_WUPS_WOL_;
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ goto done;
+ }
- /* read back PM_CTRL */
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
+ /* enable receiver to enable frame reception */
+ smsc95xx_start_rx_path(dev, 1);
- smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode\n");
+ ret = smsc95xx_enter_suspend0(dev);
- return 0;
+done:
+ if (ret)
+ usbnet_resume(intf);
+ return ret;
}
static int smsc95xx_resume(struct usb_interface *intf)
@@ -1184,33 +1699,44 @@ static int smsc95xx_resume(struct usb_interface *intf)
BUG_ON(!dev);
- if (pdata->wolopts & WAKE_MAGIC) {
- smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
- /* Disable magic packup wake */
- ret = smsc95xx_read_reg(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR");
+ if (pdata->wolopts) {
+ /* clear wake-up sources */
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading WUCSR\n");
+ return ret;
+ }
- val &= ~WUCSR_MPEN_;
+ val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
- ret = smsc95xx_write_reg(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR");
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing WUCSR\n");
+ return ret;
+ }
/* clear wake-up status */
- ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
- check_warn_return(ret, "Error reading PM_CTRL");
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error reading PM_CTRL\n");
+ return ret;
+ }
val &= ~PM_CTL_WOL_EN_;
val |= PM_CTL_WUPS_;
- ret = smsc95xx_write_reg(dev, PM_CTRL, val);
- check_warn_return(ret, "Error writing PM_CTRL");
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0) {
+ netdev_warn(dev->net, "Error writing PM_CTRL\n");
+ return ret;
+ }
}
- return usbnet_resume(intf);
- check_warn_return(ret, "usbnet_resume error");
+ ret = usbnet_resume(intf);
+ if (ret < 0)
+ netdev_warn(dev->net, "usbnet_resume error\n");
- return 0;
+ return ret;
}
static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h
index 2ff9815aa27c..f360ee372554 100644
--- a/drivers/net/usb/smsc95xx.h
+++ b/drivers/net/usb/smsc95xx.h
@@ -53,6 +53,11 @@
#define ID_REV_CHIP_ID_MASK_ (0xFFFF0000)
#define ID_REV_CHIP_REV_MASK_ (0x0000FFFF)
#define ID_REV_CHIP_ID_9500_ (0x9500)
+#define ID_REV_CHIP_ID_9500A_ (0x9E00)
+#define ID_REV_CHIP_ID_9512_ (0xEC00)
+#define ID_REV_CHIP_ID_9530_ (0x9530)
+#define ID_REV_CHIP_ID_89530_ (0x9E08)
+#define ID_REV_CHIP_ID_9730_ (0x9730)
#define INT_STS (0x08)
#define INT_STS_TX_STOP_ (0x00020000)
@@ -203,8 +208,11 @@
#define VLAN2 (0x124)
#define WUFF (0x128)
+#define LAN9500_WUFF_NUM (4)
+#define LAN9500A_WUFF_NUM (8)
#define WUCSR (0x12C)
+#define WUCSR_WFF_PTR_RST_ (0x80000000)
#define WUCSR_GUE_ (0x00000200)
#define WUCSR_WUFR_ (0x00000040)
#define WUCSR_MPR_ (0x00000020)
@@ -218,6 +226,23 @@
/* Vendor-specific PHY Definitions */
+/* EDPD NLP / crossover time configuration (LAN9500A only) */
+#define PHY_EDPD_CONFIG (16)
+#define PHY_EDPD_CONFIG_TX_NLP_EN_ ((u16)0x8000)
+#define PHY_EDPD_CONFIG_TX_NLP_1000_ ((u16)0x0000)
+#define PHY_EDPD_CONFIG_TX_NLP_768_ ((u16)0x2000)
+#define PHY_EDPD_CONFIG_TX_NLP_512_ ((u16)0x4000)
+#define PHY_EDPD_CONFIG_TX_NLP_256_ ((u16)0x6000)
+#define PHY_EDPD_CONFIG_RX_1_NLP_ ((u16)0x1000)
+#define PHY_EDPD_CONFIG_RX_NLP_64_ ((u16)0x0000)
+#define PHY_EDPD_CONFIG_RX_NLP_256_ ((u16)0x0400)
+#define PHY_EDPD_CONFIG_RX_NLP_512_ ((u16)0x0800)
+#define PHY_EDPD_CONFIG_RX_NLP_1000_ ((u16)0x0C00)
+#define PHY_EDPD_CONFIG_EXT_CROSSOVER_ ((u16)0x0001)
+#define PHY_EDPD_CONFIG_DEFAULT (PHY_EDPD_CONFIG_TX_NLP_EN_ | \
+ PHY_EDPD_CONFIG_TX_NLP_768_ | \
+ PHY_EDPD_CONFIG_RX_1_NLP_)
+
/* Mode Control/Status Register */
#define PHY_MODE_CTRL_STS (17)
#define MODE_CTRL_STS_EDPWRDOWN_ ((u16)0x2000)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index edb81ed06950..c04110ba677f 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1616,6 +1616,202 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
EXPORT_SYMBOL(usbnet_device_suggests_idle);
/*-------------------------------------------------------------------------*/
+static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, void *data, u16 size)
+{
+ void *buf = NULL;
+ int err = -ENOMEM;
+
+ netdev_dbg(dev->net, "usbnet_read_cmd cmd=0x%02x reqtype=%02x"
+ " value=0x%04x index=0x%04x size=%d\n",
+ cmd, reqtype, value, index, size);
+
+ if (data) {
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ goto out;
+ }
+
+ err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ cmd, reqtype, value, index, buf, size,
+ USB_CTRL_GET_TIMEOUT);
+ if (err > 0 && err <= size)
+ memcpy(data, buf, err);
+ kfree(buf);
+out:
+ return err;
+}
+
+static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data,
+ u16 size)
+{
+ void *buf = NULL;
+ int err = -ENOMEM;
+
+ netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+ " value=0x%04x index=0x%04x size=%d\n",
+ cmd, reqtype, value, index, size);
+
+ if (data) {
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ goto out;
+ }
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ cmd, reqtype, value, index, buf, size,
+ USB_CTRL_SET_TIMEOUT);
+ kfree(buf);
+
+out:
+ return err;
+}
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, void *data, u16 size)
+{
+ int ret;
+
+ if (usb_autopm_get_interface(dev->intf) < 0)
+ return -ENODEV;
+ ret = __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+ data, size);
+ usb_autopm_put_interface(dev->intf);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd);
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data, u16 size)
+{
+ int ret;
+
+ if (usb_autopm_get_interface(dev->intf) < 0)
+ return -ENODEV;
+ ret = __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+ data, size);
+ usb_autopm_put_interface(dev->intf);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, void *data, u16 size)
+{
+ return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+ data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data,
+ u16 size)
+{
+ return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+ data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
+
+static void usbnet_async_cmd_cb(struct urb *urb)
+{
+ struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+ int status = urb->status;
+
+ if (status < 0)
+ dev_dbg(&urb->dev->dev, "%s failed with %d",
+ __func__, status);
+
+ kfree(req);
+ usb_free_urb(urb);
+}
+
+/*
+ * The caller must make sure that device can't be put into suspend
+ * state until the control URB completes.
+ */
+int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data, u16 size)
+{
+ struct usb_ctrlrequest *req = NULL;
+ struct urb *urb;
+ int err = -ENOMEM;
+ void *buf = NULL;
+
+ netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+ " value=0x%04x index=0x%04x size=%d\n",
+ cmd, reqtype, value, index, size);
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(dev->net, "Error allocating URB in"
+ " %s!\n", __func__);
+ goto fail;
+ }
+
+ if (data) {
+ buf = kmemdup(data, size, GFP_ATOMIC);
+ if (!buf) {
+ netdev_err(dev->net, "Error allocating buffer"
+ " in %s!\n", __func__);
+ goto fail_free;
+ }
+ }
+
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+ if (!req) {
+ netdev_err(dev->net, "Failed to allocate memory for %s\n",
+ __func__);
+ goto fail_free_buf;
+ }
+
+ req->bRequestType = reqtype;
+ req->bRequest = cmd;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
+
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (void *)req, buf, size,
+ usbnet_async_cmd_cb, req);
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ netdev_err(dev->net, "Error submitting the control"
+ " message: status=%d\n", err);
+ goto fail_free;
+ }
+ return 0;
+
+fail_free_buf:
+ kfree(buf);
+fail_free:
+ kfree(req);
+ usb_free_urb(urb);
+fail:
+ return err;
+
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
+/*-------------------------------------------------------------------------*/
static int __init usbnet_init(void)
{
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index e522ff70444c..95814d9747ef 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -264,6 +264,7 @@ static void veth_setup(struct net_device *dev)
ether_setup(dev);
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
dev->netdev_ops = &veth_netdev_ops;
dev->ethtool_ops = &veth_ethtool_ops;
@@ -339,7 +340,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
if (IS_ERR(net))
return PTR_ERR(net);
- peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp);
+ peer = rtnl_create_link(net, ifname, &veth_link_ops, tbp);
if (IS_ERR(peer)) {
put_net(net);
return PTR_ERR(peer);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cbf8b0625352..68d64f0313ea 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -51,15 +51,51 @@ struct virtnet_stats {
u64 rx_packets;
};
+/* Internal representation of a send virtqueue */
+struct send_queue {
+ /* Virtqueue associated with this send _queue */
+ struct virtqueue *vq;
+
+ /* TX: fragments + linear part + virtio header */
+ struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+ /* Name of the send queue: output.$index */
+ char name[40];
+};
+
+/* Internal representation of a receive virtqueue */
+struct receive_queue {
+ /* Virtqueue associated with this receive_queue */
+ struct virtqueue *vq;
+
+ struct napi_struct napi;
+
+ /* Number of input buffers, and max we've ever had. */
+ unsigned int num, max;
+
+ /* Chain pages by the private ptr. */
+ struct page *pages;
+
+ /* RX: fragments + linear part + virtio header */
+ struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+ /* Name of this receive queue: input.$index */
+ char name[40];
+};
+
struct virtnet_info {
struct virtio_device *vdev;
- struct virtqueue *rvq, *svq, *cvq;
+ struct virtqueue *cvq;
struct net_device *dev;
- struct napi_struct napi;
+ struct send_queue *sq;
+ struct receive_queue *rq;
unsigned int status;
- /* Number of input buffers, and max we've ever had. */
- unsigned int num, max;
+ /* Max # of queue pairs supported by the device */
+ u16 max_queue_pairs;
+
+ /* # of queue pairs currently used by the driver */
+ u16 curr_queue_pairs;
/* I like... big packets and I cannot lie! */
bool big_packets;
@@ -67,6 +103,9 @@ struct virtnet_info {
/* Host will merge rx buffers for big packets (shake it! shake it!) */
bool mergeable_rx_bufs;
+ /* Has control virtqueue */
+ bool has_cvq;
+
/* enable config space updates */
bool config_enable;
@@ -82,12 +121,8 @@ struct virtnet_info {
/* Lock for config space updates */
struct mutex config_lock;
- /* Chain pages by the private ptr. */
- struct page *pages;
-
- /* fragments + linear part + virtio header */
- struct scatterlist rx_sg[MAX_SKB_FRAGS + 2];
- struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
+ /* Does the affinity hint is set for virtqueues? */
+ bool affinity_hint_set;
};
struct skb_vnet_hdr {
@@ -108,6 +143,29 @@ struct padded_vnet_hdr {
char padding[6];
};
+/* Converting between virtqueue no. and kernel tx/rx queue no.
+ * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
+ */
+static int vq2txq(struct virtqueue *vq)
+{
+ return (virtqueue_get_queue_index(vq) - 1) / 2;
+}
+
+static int txq2vq(int txq)
+{
+ return txq * 2 + 1;
+}
+
+static int vq2rxq(struct virtqueue *vq)
+{
+ return virtqueue_get_queue_index(vq) / 2;
+}
+
+static int rxq2vq(int rxq)
+{
+ return rxq * 2;
+}
+
static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
{
return (struct skb_vnet_hdr *)skb->cb;
@@ -117,22 +175,22 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
* private is used to chain pages for big packets, put the whole
* most recent used list in the beginning for reuse
*/
-static void give_pages(struct virtnet_info *vi, struct page *page)
+static void give_pages(struct receive_queue *rq, struct page *page)
{
struct page *end;
- /* Find end of list, sew whole thing into vi->pages. */
+ /* Find end of list, sew whole thing into vi->rq.pages. */
for (end = page; end->private; end = (struct page *)end->private);
- end->private = (unsigned long)vi->pages;
- vi->pages = page;
+ end->private = (unsigned long)rq->pages;
+ rq->pages = page;
}
-static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
{
- struct page *p = vi->pages;
+ struct page *p = rq->pages;
if (p) {
- vi->pages = (struct page *)p->private;
+ rq->pages = (struct page *)p->private;
/* clear private here, it is used to chain pages */
p->private = 0;
} else
@@ -140,15 +198,15 @@ static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
return p;
}
-static void skb_xmit_done(struct virtqueue *svq)
+static void skb_xmit_done(struct virtqueue *vq)
{
- struct virtnet_info *vi = svq->vdev->priv;
+ struct virtnet_info *vi = vq->vdev->priv;
/* Suppress further interrupts. */
- virtqueue_disable_cb(svq);
+ virtqueue_disable_cb(vq);
/* We were probably waiting for more output buffers. */
- netif_wake_queue(vi->dev);
+ netif_wake_subqueue(vi->dev, vq2txq(vq));
}
static void set_skb_frag(struct sk_buff *skb, struct page *page,
@@ -167,9 +225,10 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page,
}
/* Called from bottom half context */
-static struct sk_buff *page_to_skb(struct virtnet_info *vi,
+static struct sk_buff *page_to_skb(struct receive_queue *rq,
struct page *page, unsigned int len)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
struct sk_buff *skb;
struct skb_vnet_hdr *hdr;
unsigned int copy, hdr_len, offset;
@@ -212,8 +271,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
* the case of a broken device.
*/
if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) {
- if (net_ratelimit())
- pr_debug("%s: too much data\n", skb->dev->name);
+ net_dbg_ratelimited("%s: too much data\n", skb->dev->name);
dev_kfree_skb(skb);
return NULL;
}
@@ -225,12 +283,12 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
}
if (page)
- give_pages(vi, page);
+ give_pages(rq, page);
return skb;
}
-static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
+static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb)
{
struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
struct page *page;
@@ -244,7 +302,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
skb->dev->stats.rx_length_errors++;
return -EINVAL;
}
- page = virtqueue_get_buf(vi->rvq, &len);
+ page = virtqueue_get_buf(rq->vq, &len);
if (!page) {
pr_debug("%s: rx error: %d buffers missing\n",
skb->dev->name, hdr->mhdr.num_buffers);
@@ -257,14 +315,15 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
set_skb_frag(skb, page, 0, &len);
- --vi->num;
+ --rq->num;
}
return 0;
}
-static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
+static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
{
- struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_info *vi = rq->vq->vdev->priv;
+ struct net_device *dev = vi->dev;
struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
struct sk_buff *skb;
struct page *page;
@@ -274,7 +333,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
pr_debug("%s: short packet %i\n", dev->name, len);
dev->stats.rx_length_errors++;
if (vi->mergeable_rx_bufs || vi->big_packets)
- give_pages(vi, buf);
+ give_pages(rq, buf);
else
dev_kfree_skb(buf);
return;
@@ -286,14 +345,14 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
skb_trim(skb, len);
} else {
page = buf;
- skb = page_to_skb(vi, page, len);
+ skb = page_to_skb(rq, page, len);
if (unlikely(!skb)) {
dev->stats.rx_dropped++;
- give_pages(vi, page);
+ give_pages(rq, page);
return;
}
if (vi->mergeable_rx_bufs)
- if (receive_mergeable(vi, skb)) {
+ if (receive_mergeable(rq, skb)) {
dev_kfree_skb(skb);
return;
}
@@ -333,9 +392,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
default:
- if (net_ratelimit())
- printk(KERN_WARNING "%s: bad gso type %u.\n",
- dev->name, hdr->hdr.gso_type);
+ net_warn_ratelimited("%s: bad gso type %u.\n",
+ dev->name, hdr->hdr.gso_type);
goto frame_err;
}
@@ -344,9 +402,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
skb_shinfo(skb)->gso_size = hdr->hdr.gso_size;
if (skb_shinfo(skb)->gso_size == 0) {
- if (net_ratelimit())
- printk(KERN_WARNING "%s: zero gso size.\n",
- dev->name);
+ net_warn_ratelimited("%s: zero gso size.\n", dev->name);
goto frame_err;
}
@@ -363,8 +419,9 @@ frame_err:
dev_kfree_skb(skb);
}
-static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
struct sk_buff *skb;
struct skb_vnet_hdr *hdr;
int err;
@@ -376,77 +433,77 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
skb_put(skb, MAX_PACKET_LEN);
hdr = skb_vnet_hdr(skb);
- sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr);
+ sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr);
- skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
+ skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
+ err = virtqueue_add_buf(rq->vq, rq->sg, 0, 2, skb, gfp);
if (err < 0)
dev_kfree_skb(skb);
return err;
}
-static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp)
{
struct page *first, *list = NULL;
char *p;
int i, err, offset;
- /* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */
+ /* page in rq->sg[MAX_SKB_FRAGS + 1] is list tail */
for (i = MAX_SKB_FRAGS + 1; i > 1; --i) {
- first = get_a_page(vi, gfp);
+ first = get_a_page(rq, gfp);
if (!first) {
if (list)
- give_pages(vi, list);
+ give_pages(rq, list);
return -ENOMEM;
}
- sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE);
+ sg_set_buf(&rq->sg[i], page_address(first), PAGE_SIZE);
/* chain new page in list head to match sg */
first->private = (unsigned long)list;
list = first;
}
- first = get_a_page(vi, gfp);
+ first = get_a_page(rq, gfp);
if (!first) {
- give_pages(vi, list);
+ give_pages(rq, list);
return -ENOMEM;
}
p = page_address(first);
- /* vi->rx_sg[0], vi->rx_sg[1] share the same page */
- /* a separated vi->rx_sg[0] for virtio_net_hdr only due to QEMU bug */
- sg_set_buf(&vi->rx_sg[0], p, sizeof(struct virtio_net_hdr));
+ /* rq->sg[0], rq->sg[1] share the same page */
+ /* a separated rq->sg[0] for virtio_net_hdr only due to QEMU bug */
+ sg_set_buf(&rq->sg[0], p, sizeof(struct virtio_net_hdr));
- /* vi->rx_sg[1] for data packet, from offset */
+ /* rq->sg[1] for data packet, from offset */
offset = sizeof(struct padded_vnet_hdr);
- sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset);
+ sg_set_buf(&rq->sg[1], p + offset, PAGE_SIZE - offset);
/* chain first in list head */
first->private = (unsigned long)list;
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+ err = virtqueue_add_buf(rq->vq, rq->sg, 0, MAX_SKB_FRAGS + 2,
first, gfp);
if (err < 0)
- give_pages(vi, first);
+ give_pages(rq, first);
return err;
}
-static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp)
{
struct page *page;
int err;
- page = get_a_page(vi, gfp);
+ page = get_a_page(rq, gfp);
if (!page)
return -ENOMEM;
- sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
+ sg_init_one(rq->sg, page_address(page), PAGE_SIZE);
- err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
+ err = virtqueue_add_buf(rq->vq, rq->sg, 0, 1, page, gfp);
if (err < 0)
- give_pages(vi, page);
+ give_pages(rq, page);
return err;
}
@@ -458,97 +515,108 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
* before we're receiving packets, or from refill_work which is
* careful to disable receiving (using napi_disable).
*/
-static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
+static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
int err;
bool oom;
do {
if (vi->mergeable_rx_bufs)
- err = add_recvbuf_mergeable(vi, gfp);
+ err = add_recvbuf_mergeable(rq, gfp);
else if (vi->big_packets)
- err = add_recvbuf_big(vi, gfp);
+ err = add_recvbuf_big(rq, gfp);
else
- err = add_recvbuf_small(vi, gfp);
+ err = add_recvbuf_small(rq, gfp);
oom = err == -ENOMEM;
if (err < 0)
break;
- ++vi->num;
+ ++rq->num;
} while (err > 0);
- if (unlikely(vi->num > vi->max))
- vi->max = vi->num;
- virtqueue_kick(vi->rvq);
+ if (unlikely(rq->num > rq->max))
+ rq->max = rq->num;
+ virtqueue_kick(rq->vq);
return !oom;
}
static void skb_recv_done(struct virtqueue *rvq)
{
struct virtnet_info *vi = rvq->vdev->priv;
+ struct receive_queue *rq = &vi->rq[vq2rxq(rvq)];
+
/* Schedule NAPI, Suppress further interrupts if successful. */
- if (napi_schedule_prep(&vi->napi)) {
+ if (napi_schedule_prep(&rq->napi)) {
virtqueue_disable_cb(rvq);
- __napi_schedule(&vi->napi);
+ __napi_schedule(&rq->napi);
}
}
-static void virtnet_napi_enable(struct virtnet_info *vi)
+static void virtnet_napi_enable(struct receive_queue *rq)
{
- napi_enable(&vi->napi);
+ napi_enable(&rq->napi);
/* If all buffers were filled by other side before we napi_enabled, we
* won't get another interrupt, so process any outstanding packets
* now. virtnet_poll wants re-enable the queue, so we disable here.
* We synchronize against interrupts via NAPI_STATE_SCHED */
- if (napi_schedule_prep(&vi->napi)) {
- virtqueue_disable_cb(vi->rvq);
+ if (napi_schedule_prep(&rq->napi)) {
+ virtqueue_disable_cb(rq->vq);
local_bh_disable();
- __napi_schedule(&vi->napi);
+ __napi_schedule(&rq->napi);
local_bh_enable();
}
}
static void refill_work(struct work_struct *work)
{
- struct virtnet_info *vi;
+ struct virtnet_info *vi =
+ container_of(work, struct virtnet_info, refill.work);
bool still_empty;
+ int i;
- vi = container_of(work, struct virtnet_info, refill.work);
- napi_disable(&vi->napi);
- still_empty = !try_fill_recv(vi, GFP_KERNEL);
- virtnet_napi_enable(vi);
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ struct receive_queue *rq = &vi->rq[i];
- /* In theory, this can happen: if we don't get any buffers in
- * we will *never* try to fill again. */
- if (still_empty)
- schedule_delayed_work(&vi->refill, HZ/2);
+ napi_disable(&rq->napi);
+ still_empty = !try_fill_recv(rq, GFP_KERNEL);
+ virtnet_napi_enable(rq);
+
+ /* In theory, this can happen: if we don't get any buffers in
+ * we will *never* try to fill again.
+ */
+ if (still_empty)
+ schedule_delayed_work(&vi->refill, HZ/2);
+ }
}
static int virtnet_poll(struct napi_struct *napi, int budget)
{
- struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
+ struct receive_queue *rq =
+ container_of(napi, struct receive_queue, napi);
+ struct virtnet_info *vi = rq->vq->vdev->priv;
void *buf;
unsigned int len, received = 0;
again:
while (received < budget &&
- (buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
- receive_buf(vi->dev, buf, len);
- --vi->num;
+ (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
+ receive_buf(rq, buf, len);
+ --rq->num;
received++;
}
- if (vi->num < vi->max / 2) {
- if (!try_fill_recv(vi, GFP_ATOMIC))
+ if (rq->num < rq->max / 2) {
+ if (!try_fill_recv(rq, GFP_ATOMIC))
schedule_delayed_work(&vi->refill, 0);
}
/* Out of packets? */
if (received < budget) {
napi_complete(napi);
- if (unlikely(!virtqueue_enable_cb(vi->rvq)) &&
+ if (unlikely(!virtqueue_enable_cb(rq->vq)) &&
napi_schedule_prep(napi)) {
- virtqueue_disable_cb(vi->rvq);
+ virtqueue_disable_cb(rq->vq);
__napi_schedule(napi);
goto again;
}
@@ -557,13 +625,29 @@ again:
return received;
}
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static int virtnet_open(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int i;
+
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ /* Make sure we have some buffers: if oom use wq. */
+ if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+ schedule_delayed_work(&vi->refill, 0);
+ virtnet_napi_enable(&vi->rq[i]);
+ }
+
+ return 0;
+}
+
+static unsigned int free_old_xmit_skbs(struct send_queue *sq)
{
struct sk_buff *skb;
unsigned int len, tot_sgs = 0;
+ struct virtnet_info *vi = sq->vq->vdev->priv;
struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
- while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
+ while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
pr_debug("Sent skb %p\n", skb);
u64_stats_update_begin(&stats->tx_syncp);
@@ -577,10 +661,11 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
return tot_sgs;
}
-static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
+static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
{
struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+ struct virtnet_info *vi = sq->vq->vdev->priv;
pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
@@ -615,44 +700,47 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
/* Encode metadata header at front. */
if (vi->mergeable_rx_bufs)
- sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr);
+ sg_set_buf(sq->sg, &hdr->mhdr, sizeof hdr->mhdr);
else
- sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
+ sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr);
- hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
- return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+ hdr->num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
+ return virtqueue_add_buf(sq->vq, sq->sg, hdr->num_sg,
0, skb, GFP_ATOMIC);
}
static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
+ int qnum = skb_get_queue_mapping(skb);
+ struct send_queue *sq = &vi->sq[qnum];
int capacity;
/* Free up any pending old buffers before queueing new ones. */
- free_old_xmit_skbs(vi);
+ free_old_xmit_skbs(sq);
/* Try to transmit */
- capacity = xmit_skb(vi, skb);
+ capacity = xmit_skb(sq, skb);
/* This can happen with OOM and indirect buffers. */
if (unlikely(capacity < 0)) {
if (likely(capacity == -ENOMEM)) {
if (net_ratelimit())
dev_warn(&dev->dev,
- "TX queue failure: out of memory\n");
+ "TXQ (%d) failure: out of memory\n",
+ qnum);
} else {
dev->stats.tx_fifo_errors++;
if (net_ratelimit())
dev_warn(&dev->dev,
- "Unexpected TX queue failure: %d\n",
- capacity);
+ "Unexpected TXQ (%d) failure: %d\n",
+ qnum, capacity);
}
dev->stats.tx_dropped++;
kfree_skb(skb);
return NETDEV_TX_OK;
}
- virtqueue_kick(vi->svq);
+ virtqueue_kick(sq->vq);
/* Don't wait up for transmitted skbs to be freed. */
skb_orphan(skb);
@@ -661,13 +749,13 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Apparently nice girls don't return TX_BUSY; stop the queue
* before it gets out of hand. Naturally, this wastes entries. */
if (capacity < 2+MAX_SKB_FRAGS) {
- netif_stop_queue(dev);
- if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
+ netif_stop_subqueue(dev, qnum);
+ if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
/* More just got used, free them then recheck. */
- capacity += free_old_xmit_skbs(vi);
+ capacity += free_old_xmit_skbs(sq);
if (capacity >= 2+MAX_SKB_FRAGS) {
- netif_start_queue(dev);
- virtqueue_disable_cb(vi->svq);
+ netif_start_subqueue(dev, qnum);
+ virtqueue_disable_cb(sq->vq);
}
}
}
@@ -734,23 +822,13 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
static void virtnet_netpoll(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
+ int i;
- napi_schedule(&vi->napi);
+ for (i = 0; i < vi->curr_queue_pairs; i++)
+ napi_schedule(&vi->rq[i].napi);
}
#endif
-static int virtnet_open(struct net_device *dev)
-{
- struct virtnet_info *vi = netdev_priv(dev);
-
- /* Make sure we have some buffers: if oom use wq. */
- if (!try_fill_recv(vi, GFP_KERNEL))
- schedule_delayed_work(&vi->refill, 0);
-
- virtnet_napi_enable(vi);
- return 0;
-}
-
/*
* Send command via the control virtqueue and check status. Commands
* supported by the hypervisor, as indicated by feature bits, should
@@ -806,13 +884,39 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
rtnl_unlock();
}
+static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
+{
+ struct scatterlist sg;
+ struct virtio_net_ctrl_mq s;
+ struct net_device *dev = vi->dev;
+
+ if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
+ return 0;
+
+ s.virtqueue_pairs = 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, 1, 0)){
+ dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n",
+ queue_pairs);
+ return -EINVAL;
+ } else
+ vi->curr_queue_pairs = queue_pairs;
+
+ return 0;
+}
+
static int virtnet_close(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
+ int i;
/* Make sure refill_work doesn't re-enable napi! */
cancel_delayed_work_sync(&vi->refill);
- napi_disable(&vi->napi);
+
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ napi_disable(&vi->rq[i].napi);
return 0;
}
@@ -919,16 +1023,43 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
return 0;
}
+static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
+{
+ int i;
+
+ /* In multiqueue mode, when the number of cpu is equal to the number of
+ * queue pairs, we let the queue pairs to be private to one cpu by
+ * setting the affinity hint to eliminate the contention.
+ */
+ if ((vi->curr_queue_pairs == 1 ||
+ vi->max_queue_pairs != num_online_cpus()) && set) {
+ if (vi->affinity_hint_set)
+ set = false;
+ else
+ return;
+ }
+
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ int cpu = set ? i : -1;
+ virtqueue_set_affinity(vi->rq[i].vq, cpu);
+ virtqueue_set_affinity(vi->sq[i].vq, cpu);
+ }
+
+ if (set)
+ vi->affinity_hint_set = true;
+ else
+ vi->affinity_hint_set = false;
+}
+
static void virtnet_get_ringparam(struct net_device *dev,
struct ethtool_ringparam *ring)
{
struct virtnet_info *vi = netdev_priv(dev);
- ring->rx_max_pending = virtqueue_get_vring_size(vi->rvq);
- ring->tx_max_pending = virtqueue_get_vring_size(vi->svq);
+ ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+ ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
ring->rx_pending = ring->rx_max_pending;
ring->tx_pending = ring->tx_max_pending;
-
}
@@ -944,10 +1075,53 @@ static void virtnet_get_drvinfo(struct net_device *dev,
}
+/* TODO: Eliminate OOO packets during switching */
+static int virtnet_set_channels(struct net_device *dev,
+ struct ethtool_channels *channels)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ u16 queue_pairs = channels->combined_count;
+ int err;
+
+ /* We don't support separate rx/tx channels.
+ * We don't allow setting 'other' channels.
+ */
+ if (channels->rx_count || channels->tx_count || channels->other_count)
+ return -EINVAL;
+
+ if (queue_pairs > vi->max_queue_pairs)
+ return -EINVAL;
+
+ err = virtnet_set_queues(vi, queue_pairs);
+ if (!err) {
+ netif_set_real_num_tx_queues(dev, queue_pairs);
+ netif_set_real_num_rx_queues(dev, queue_pairs);
+
+ virtnet_set_affinity(vi, true);
+ }
+
+ return err;
+}
+
+static void virtnet_get_channels(struct net_device *dev,
+ struct ethtool_channels *channels)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+
+ channels->combined_count = vi->curr_queue_pairs;
+ channels->max_combined = vi->max_queue_pairs;
+ channels->max_other = 0;
+ channels->rx_count = 0;
+ channels->tx_count = 0;
+ channels->other_count = 0;
+}
+
static const struct ethtool_ops virtnet_ethtool_ops = {
.get_drvinfo = virtnet_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ringparam = virtnet_get_ringparam,
+ .set_channels = virtnet_set_channels,
+ .get_channels = virtnet_get_channels,
};
#define MIN_MTU 68
@@ -961,6 +1135,21 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+/* To avoid contending a lock hold by a vcpu who would exit to host, select the
+ * txq based on the processor id.
+ * TODO: handle cpu hotplug.
+ */
+static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+ smp_processor_id();
+
+ while (unlikely(txq >= dev->real_num_tx_queues))
+ txq -= dev->real_num_tx_queues;
+
+ return txq;
+}
+
static const struct net_device_ops virtnet_netdev = {
.ndo_open = virtnet_open,
.ndo_stop = virtnet_close,
@@ -972,6 +1161,7 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
+ .ndo_select_queue = virtnet_select_queue,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll,
#endif
@@ -1007,10 +1197,10 @@ static void virtnet_config_changed_work(struct work_struct *work)
if (vi->status & VIRTIO_NET_S_LINK_UP) {
netif_carrier_on(vi->dev);
- netif_wake_queue(vi->dev);
+ netif_tx_wake_all_queues(vi->dev);
} else {
netif_carrier_off(vi->dev);
- netif_stop_queue(vi->dev);
+ netif_tx_stop_all_queues(vi->dev);
}
done:
mutex_unlock(&vi->config_lock);
@@ -1023,41 +1213,203 @@ static void virtnet_config_changed(struct virtio_device *vdev)
schedule_work(&vi->config_work);
}
-static int init_vqs(struct virtnet_info *vi)
+static void virtnet_free_queues(struct virtnet_info *vi)
{
- struct virtqueue *vqs[3];
- vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
- const char *names[] = { "input", "output", "control" };
- int nvqs, err;
+ kfree(vi->rq);
+ kfree(vi->sq);
+}
- /* We expect two virtqueues, receive then send,
- * and optionally control. */
- nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
+static void free_receive_bufs(struct virtnet_info *vi)
+{
+ int i;
- err = vi->vdev->config->find_vqs(vi->vdev, nvqs, vqs, callbacks, names);
- if (err)
- return err;
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ while (vi->rq[i].pages)
+ __free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0);
+ }
+}
- vi->rvq = vqs[0];
- vi->svq = vqs[1];
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+ void *buf;
+ int i;
- if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
- vi->cvq = vqs[2];
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ struct virtqueue *vq = vi->sq[i].vq;
+ while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+ dev_kfree_skb(buf);
+ }
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ struct virtqueue *vq = vi->rq[i].vq;
+
+ while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
+ if (vi->mergeable_rx_bufs || vi->big_packets)
+ give_pages(&vi->rq[i], buf);
+ else
+ dev_kfree_skb(buf);
+ --vi->rq[i].num;
+ }
+ BUG_ON(vi->rq[i].num != 0);
+ }
+}
+
+static void virtnet_del_vqs(struct virtnet_info *vi)
+{
+ struct virtio_device *vdev = vi->vdev;
+
+ virtnet_set_affinity(vi, false);
+
+ vdev->config->del_vqs(vdev);
+
+ virtnet_free_queues(vi);
+}
+
+static int virtnet_find_vqs(struct virtnet_info *vi)
+{
+ vq_callback_t **callbacks;
+ struct virtqueue **vqs;
+ int ret = -ENOMEM;
+ int i, total_vqs;
+ const char **names;
+
+ /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
+ * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
+ * possible control vq.
+ */
+ total_vqs = vi->max_queue_pairs * 2 +
+ virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ);
+
+ /* Allocate space for find_vqs parameters */
+ vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL);
+ if (!vqs)
+ goto err_vq;
+ callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL);
+ if (!callbacks)
+ goto err_callback;
+ names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL);
+ if (!names)
+ goto err_names;
+
+ /* Parameters for control virtqueue, if any */
+ if (vi->has_cvq) {
+ callbacks[total_vqs - 1] = NULL;
+ names[total_vqs - 1] = "control";
+ }
+
+ /* Allocate/initialize parameters for send/receive virtqueues */
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ callbacks[rxq2vq(i)] = skb_recv_done;
+ callbacks[txq2vq(i)] = skb_xmit_done;
+ sprintf(vi->rq[i].name, "input.%d", i);
+ sprintf(vi->sq[i].name, "output.%d", i);
+ names[rxq2vq(i)] = vi->rq[i].name;
+ names[txq2vq(i)] = vi->sq[i].name;
+ }
+
+ ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
+ names);
+ if (ret)
+ goto err_find;
+
+ if (vi->has_cvq) {
+ vi->cvq = vqs[total_vqs - 1];
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
vi->dev->features |= NETIF_F_HW_VLAN_FILTER;
}
+
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ vi->rq[i].vq = vqs[rxq2vq(i)];
+ vi->sq[i].vq = vqs[txq2vq(i)];
+ }
+
+ kfree(names);
+ kfree(callbacks);
+ kfree(vqs);
+
+ return 0;
+
+err_find:
+ kfree(names);
+err_names:
+ kfree(callbacks);
+err_callback:
+ kfree(vqs);
+err_vq:
+ return ret;
+}
+
+static int virtnet_alloc_queues(struct virtnet_info *vi)
+{
+ int i;
+
+ vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL);
+ if (!vi->sq)
+ goto err_sq;
+ vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL);
+ if (!vi->rq)
+ goto err_rq;
+
+ INIT_DELAYED_WORK(&vi->refill, refill_work);
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ vi->rq[i].pages = NULL;
+ netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
+ napi_weight);
+
+ sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
+ sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg));
+ }
+
return 0;
+
+err_rq:
+ kfree(vi->sq);
+err_sq:
+ return -ENOMEM;
+}
+
+static int init_vqs(struct virtnet_info *vi)
+{
+ int ret;
+
+ /* Allocate send & receive queues */
+ ret = virtnet_alloc_queues(vi);
+ if (ret)
+ goto err;
+
+ ret = virtnet_find_vqs(vi);
+ if (ret)
+ goto err_free;
+
+ virtnet_set_affinity(vi, true);
+ return 0;
+
+err_free:
+ virtnet_free_queues(vi);
+err:
+ return ret;
}
static int virtnet_probe(struct virtio_device *vdev)
{
- int err;
+ int i, err;
struct net_device *dev;
struct virtnet_info *vi;
+ u16 max_queue_pairs;
+
+ /* Find if host supports multiqueue virtio_net device */
+ err = virtio_config_val(vdev, VIRTIO_NET_F_MQ,
+ offsetof(struct virtio_net_config,
+ max_virtqueue_pairs), &max_queue_pairs);
+
+ /* We need at least 2 queue's */
+ if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
+ max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
+ !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
+ max_queue_pairs = 1;
/* Allocate ourselves a network device with room for our info */
- dev = alloc_etherdev(sizeof(struct virtnet_info));
+ dev = alloc_etherdev_mq(sizeof(struct virtnet_info), max_queue_pairs);
if (!dev)
return -ENOMEM;
@@ -1103,22 +1455,17 @@ static int virtnet_probe(struct virtio_device *vdev)
/* Set up our device-specific information */
vi = netdev_priv(dev);
- netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight);
vi->dev = dev;
vi->vdev = vdev;
vdev->priv = vi;
- vi->pages = NULL;
vi->stats = alloc_percpu(struct virtnet_stats);
err = -ENOMEM;
if (vi->stats == NULL)
goto free;
- INIT_DELAYED_WORK(&vi->refill, refill_work);
mutex_init(&vi->config_lock);
vi->config_enable = true;
INIT_WORK(&vi->config_work, virtnet_config_changed_work);
- sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
- sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
/* If we can receive ANY GSO packets, we must allocate large ones. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
@@ -1129,10 +1476,21 @@ static int virtnet_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
vi->mergeable_rx_bufs = true;
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
+ vi->has_cvq = true;
+
+ /* Use single tx/rx queue pair as default */
+ vi->curr_queue_pairs = 1;
+ vi->max_queue_pairs = max_queue_pairs;
+
+ /* Allocate/initialize the rx/tx queues, and invoke find_vqs */
err = init_vqs(vi);
if (err)
goto free_stats;
+ netif_set_real_num_tx_queues(dev, 1);
+ netif_set_real_num_rx_queues(dev, 1);
+
err = register_netdev(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
@@ -1140,12 +1498,15 @@ static int virtnet_probe(struct virtio_device *vdev)
}
/* Last of all, set up some receive buffers. */
- try_fill_recv(vi, GFP_KERNEL);
-
- /* If we didn't even get one input buffer, we're useless. */
- if (vi->num == 0) {
- err = -ENOMEM;
- goto unregister;
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ try_fill_recv(&vi->rq[i], GFP_KERNEL);
+
+ /* If we didn't even get one input buffer, we're useless. */
+ if (vi->rq[i].num == 0) {
+ free_unused_bufs(vi);
+ err = -ENOMEM;
+ goto free_recv_bufs;
+ }
}
/* Assume link up if device can't report link status,
@@ -1158,13 +1519,17 @@ static int virtnet_probe(struct virtio_device *vdev)
netif_carrier_on(dev);
}
- pr_debug("virtnet: registered device %s\n", dev->name);
+ pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
+ dev->name, max_queue_pairs);
+
return 0;
-unregister:
+free_recv_bufs:
+ free_receive_bufs(vi);
unregister_netdev(dev);
free_vqs:
- vdev->config->del_vqs(vdev);
+ cancel_delayed_work_sync(&vi->refill);
+ virtnet_del_vqs(vi);
free_stats:
free_percpu(vi->stats);
free:
@@ -1172,28 +1537,6 @@ free:
return err;
}
-static void free_unused_bufs(struct virtnet_info *vi)
-{
- void *buf;
- while (1) {
- buf = virtqueue_detach_unused_buf(vi->svq);
- if (!buf)
- break;
- dev_kfree_skb(buf);
- }
- while (1) {
- buf = virtqueue_detach_unused_buf(vi->rvq);
- if (!buf)
- break;
- if (vi->mergeable_rx_bufs || vi->big_packets)
- give_pages(vi, buf);
- else
- dev_kfree_skb(buf);
- --vi->num;
- }
- BUG_ON(vi->num != 0);
-}
-
static void remove_vq_common(struct virtnet_info *vi)
{
vi->vdev->config->reset(vi->vdev);
@@ -1201,13 +1544,12 @@ static void remove_vq_common(struct virtnet_info *vi)
/* Free unused buffers in both send and recv, if any. */
free_unused_bufs(vi);
- vi->vdev->config->del_vqs(vi->vdev);
+ free_receive_bufs(vi);
- while (vi->pages)
- __free_pages(get_a_page(vi, GFP_KERNEL), 0);
+ virtnet_del_vqs(vi);
}
-static void __devexit virtnet_remove(struct virtio_device *vdev)
+static void virtnet_remove(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
@@ -1230,6 +1572,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
static int virtnet_freeze(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
+ int i;
/* Prevent config work handler from accessing the device */
mutex_lock(&vi->config_lock);
@@ -1240,7 +1583,10 @@ static int virtnet_freeze(struct virtio_device *vdev)
cancel_delayed_work_sync(&vi->refill);
if (netif_running(vi->dev))
- napi_disable(&vi->napi);
+ for (i = 0; i < vi->max_queue_pairs; i++) {
+ napi_disable(&vi->rq[i].napi);
+ netif_napi_del(&vi->rq[i].napi);
+ }
remove_vq_common(vi);
@@ -1252,24 +1598,28 @@ static int virtnet_freeze(struct virtio_device *vdev)
static int virtnet_restore(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
- int err;
+ int err, i;
err = init_vqs(vi);
if (err)
return err;
if (netif_running(vi->dev))
- virtnet_napi_enable(vi);
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ virtnet_napi_enable(&vi->rq[i]);
netif_device_attach(vi->dev);
- if (!try_fill_recv(vi, GFP_KERNEL))
- schedule_delayed_work(&vi->refill, 0);
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+ schedule_delayed_work(&vi->refill, 0);
mutex_lock(&vi->config_lock);
vi->config_enable = true;
mutex_unlock(&vi->config_lock);
+ virtnet_set_queues(vi, vi->curr_queue_pairs);
+
return 0;
}
#endif
@@ -1287,7 +1637,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
- VIRTIO_NET_F_GUEST_ANNOUNCE,
+ VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
};
static struct virtio_driver virtio_net_driver = {
@@ -1297,7 +1647,7 @@ static struct virtio_driver virtio_net_driver = {
.driver.owner = THIS_MODULE,
.id_table = id_table,
.probe = virtnet_probe,
- .remove = __devexit_p(virtnet_remove),
+ .remove = virtnet_remove,
.config_changed = virtnet_config_changed,
#ifdef CONFIG_PM
.freeze = virtnet_freeze,
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 0ae1bcc6da73..dc8913c6238c 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1094,10 +1094,10 @@ vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
- BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
- return vmxnet3_tq_xmit(skb,
- &adapter->tx_queue[skb->queue_mapping],
- adapter, netdev);
+ BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
+ return vmxnet3_tq_xmit(skb,
+ &adapter->tx_queue[skb->queue_mapping],
+ adapter, netdev);
}
@@ -1243,8 +1243,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
skb_reserve(new_skb, NET_IP_ALIGN);
rbi->skb = new_skb;
rbi->dma_addr = pci_map_single(adapter->pdev,
- rbi->skb->data, rbi->len,
- PCI_DMA_FROMDEVICE);
+ rbi->skb->data, rbi->len,
+ PCI_DMA_FROMDEVICE);
rxd->addr = cpu_to_le64(rbi->dma_addr);
rxd->len = rbi->len;
@@ -1331,14 +1331,14 @@ rcd_done:
/* if needed, update the register */
if (unlikely(rq->shared->updateRxProd)) {
VMXNET3_WRITE_BAR0_REG(adapter,
- rxprod_reg[ring_idx] + rq->qid * 8,
- ring->next2fill);
+ rxprod_reg[ring_idx] + rq->qid * 8,
+ ring->next2fill);
rq->uncommitted[ring_idx] = 0;
}
vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
vmxnet3_getRxComp(rcd,
- &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
+ &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
}
return num_rxd;
@@ -1922,7 +1922,7 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
free_irq(adapter->pdev->irq, adapter->netdev);
break;
default:
- BUG_ON(true);
+ BUG();
}
}
@@ -2885,7 +2885,7 @@ vmxnet3_reset_work(struct work_struct *data)
}
-static int __devinit
+static int
vmxnet3_probe_device(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -2949,11 +2949,11 @@ vmxnet3_probe_device(struct pci_dev *pdev,
spin_lock_init(&adapter->cmd_lock);
adapter->shared = pci_alloc_consistent(adapter->pdev,
- sizeof(struct Vmxnet3_DriverShared),
- &adapter->shared_pa);
+ sizeof(struct Vmxnet3_DriverShared),
+ &adapter->shared_pa);
if (!adapter->shared) {
printk(KERN_ERR "Failed to allocate memory for %s\n",
- pci_name(pdev));
+ pci_name(pdev));
err = -ENOMEM;
goto err_alloc_shared;
}
@@ -2964,16 +2964,16 @@ vmxnet3_probe_device(struct pci_dev *pdev,
size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
adapter->tqd_start = pci_alloc_consistent(adapter->pdev, size,
- &adapter->queue_desc_pa);
+ &adapter->queue_desc_pa);
if (!adapter->tqd_start) {
printk(KERN_ERR "Failed to allocate memory for %s\n",
- pci_name(pdev));
+ pci_name(pdev));
err = -ENOMEM;
goto err_alloc_queue_desc;
}
adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start +
- adapter->num_tx_queues);
+ adapter->num_tx_queues);
adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
if (adapter->pm_conf == NULL) {
@@ -3019,7 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
adapter->dev_number = atomic_read(&devices_found);
- adapter->share_intr = irq_share_mode;
+ adapter->share_intr = irq_share_mode;
if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE &&
adapter->num_tx_queues != adapter->num_rx_queues)
adapter->share_intr = VMXNET3_INTR_DONTSHARE;
@@ -3065,7 +3065,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
if (err) {
printk(KERN_ERR "Failed to register adapter %s\n",
- pci_name(pdev));
+ pci_name(pdev));
goto err_register;
}
@@ -3096,7 +3096,7 @@ err_alloc_shared:
}
-static void __devexit
+static void
vmxnet3_remove_device(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3302,7 +3302,7 @@ static struct pci_driver vmxnet3_driver = {
.name = vmxnet3_driver_name,
.id_table = vmxnet3_pciid_table,
.probe = vmxnet3_probe_device,
- .remove = __devexit_p(vmxnet3_remove_device),
+ .remove = vmxnet3_remove_device,
#ifdef CONFIG_PM
.driver.pm = &vmxnet3_pm_ops,
#endif
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8b5c61917076..3b3fdf648ea7 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -29,6 +29,8 @@
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/hash.h>
+#include <net/arp.h>
+#include <net/ndisc.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/udp.h>
@@ -110,18 +112,23 @@ struct vxlan_dev {
__u16 port_max;
__u8 tos; /* TOS override */
__u8 ttl;
- bool learn;
+ u32 flags; /* VXLAN_F_* below */
unsigned long age_interval;
struct timer_list age_timer;
spinlock_t hash_lock;
unsigned int addrcnt;
unsigned int addrmax;
- unsigned int addrexceeded;
struct hlist_head fdb_head[FDB_HASH_SIZE];
};
+#define VXLAN_F_LEARN 0x01
+#define VXLAN_F_PROXY 0x02
+#define VXLAN_F_RSC 0x04
+#define VXLAN_F_L2MISS 0x08
+#define VXLAN_F_L3MISS 0x10
+
/* salt for hash table */
static u32 vxlan_salt __read_mostly;
@@ -155,6 +162,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
struct nda_cacheinfo ci;
struct nlmsghdr *nlh;
struct ndmsg *ndm;
+ bool send_ip, send_eth;
nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
if (nlh == NULL)
@@ -162,16 +170,24 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
ndm = nlmsg_data(nlh);
memset(ndm, 0, sizeof(*ndm));
- ndm->ndm_family = AF_BRIDGE;
+
+ send_eth = send_ip = true;
+
+ if (type == RTM_GETNEIGH) {
+ ndm->ndm_family = AF_INET;
+ send_ip = fdb->remote_ip != 0;
+ send_eth = !is_zero_ether_addr(fdb->eth_addr);
+ } else
+ ndm->ndm_family = AF_BRIDGE;
ndm->ndm_state = fdb->state;
ndm->ndm_ifindex = vxlan->dev->ifindex;
ndm->ndm_flags = NTF_SELF;
ndm->ndm_type = NDA_DST;
- if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
+ if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
goto nla_put_failure;
- if (nla_put_be32(skb, NDA_DST, fdb->remote_ip))
+ if (send_ip && nla_put_be32(skb, NDA_DST, fdb->remote_ip))
goto nla_put_failure;
ci.ndm_used = jiffies_to_clock_t(now - fdb->used);
@@ -223,6 +239,29 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
}
+static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_fdb f;
+
+ memset(&f, 0, sizeof f);
+ f.state = NUD_STALE;
+ f.remote_ip = ipa; /* goes to NDA_DST */
+
+ vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
+static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
+{
+ struct vxlan_fdb f;
+
+ memset(&f, 0, sizeof f);
+ f.state = NUD_STALE;
+ memcpy(f.eth_addr, eth_addr, ETH_ALEN);
+
+ vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
/* Hash Ethernet address */
static u32 eth_hash(const unsigned char *addr)
{
@@ -552,6 +591,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
goto drop;
}
+ skb_reset_mac_header(skb);
+
/* Re-examine inner Ethernet packet */
oip = ip_hdr(skb);
skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -561,12 +602,22 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
vxlan->dev->dev_addr) == 0)
goto drop;
- if (vxlan->learn)
+ if (vxlan->flags & VXLAN_F_LEARN)
vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source);
__skb_tunnel_rx(skb, vxlan->dev);
skb_reset_network_header(skb);
- skb->ip_summed = CHECKSUM_NONE;
+
+ /* If the NIC driver gave us an encapsulated packet with
+ * CHECKSUM_UNNECESSARY and Rx checksum feature is enabled,
+ * leave the CHECKSUM_UNNECESSARY, the device checksummed it
+ * for us. Otherwise force the upper layers to verify it.
+ */
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY || !skb->encapsulation ||
+ !(vxlan->dev->features & NETIF_F_RXCSUM))
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb->encapsulation = 0;
err = IP_ECN_decapsulate(oip, skb);
if (unlikely(err)) {
@@ -600,6 +651,117 @@ drop:
return 0;
}
+static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct arphdr *parp;
+ u8 *arpptr, *sha;
+ __be32 sip, tip;
+ struct neighbour *n;
+
+ if (dev->flags & IFF_NOARP)
+ goto out;
+
+ if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
+ dev->stats.tx_dropped++;
+ goto out;
+ }
+ parp = arp_hdr(skb);
+
+ if ((parp->ar_hrd != htons(ARPHRD_ETHER) &&
+ parp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+ parp->ar_pro != htons(ETH_P_IP) ||
+ parp->ar_op != htons(ARPOP_REQUEST) ||
+ parp->ar_hln != dev->addr_len ||
+ parp->ar_pln != 4)
+ goto out;
+ arpptr = (u8 *)parp + sizeof(struct arphdr);
+ sha = arpptr;
+ arpptr += dev->addr_len; /* sha */
+ memcpy(&sip, arpptr, sizeof(sip));
+ arpptr += sizeof(sip);
+ arpptr += dev->addr_len; /* tha */
+ memcpy(&tip, arpptr, sizeof(tip));
+
+ if (ipv4_is_loopback(tip) ||
+ ipv4_is_multicast(tip))
+ goto out;
+
+ n = neigh_lookup(&arp_tbl, &tip, dev);
+
+ if (n) {
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_fdb *f;
+ struct sk_buff *reply;
+
+ if (!(n->nud_state & NUD_CONNECTED)) {
+ neigh_release(n);
+ goto out;
+ }
+
+ f = vxlan_find_mac(vxlan, n->ha);
+ if (f && f->remote_ip == 0) {
+ /* bridge-local neighbor */
+ neigh_release(n);
+ goto out;
+ }
+
+ reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+ n->ha, sha);
+
+ neigh_release(n);
+
+ skb_reset_mac_header(reply);
+ __skb_pull(reply, skb_network_offset(reply));
+ reply->ip_summed = CHECKSUM_UNNECESSARY;
+ reply->pkt_type = PACKET_HOST;
+
+ if (netif_rx_ni(reply) == NET_RX_DROP)
+ dev->stats.rx_dropped++;
+ } else if (vxlan->flags & VXLAN_F_L3MISS)
+ vxlan_ip_miss(dev, tip);
+out:
+ consume_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct neighbour *n;
+ struct iphdr *pip;
+
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
+ return false;
+
+ n = NULL;
+ switch (ntohs(eth_hdr(skb)->h_proto)) {
+ case ETH_P_IP:
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ return false;
+ pip = ip_hdr(skb);
+ n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
+ break;
+ default:
+ return false;
+ }
+
+ if (n) {
+ bool diff;
+
+ diff = compare_ether_addr(eth_hdr(skb)->h_dest, n->ha) != 0;
+ if (diff) {
+ memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+ dev->addr_len);
+ memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
+ }
+ neigh_release(n);
+ return diff;
+ } else if (vxlan->flags & VXLAN_F_L3MISS)
+ vxlan_ip_miss(dev, pip->daddr);
+ return false;
+}
+
/* Extract dsfield from inner protocol */
static inline u8 vxlan_get_dsfield(const struct iphdr *iph,
const struct sk_buff *skb)
@@ -622,22 +784,6 @@ static inline u8 vxlan_ecn_encap(u8 tos,
return INET_ECN_encapsulate(tos, inner);
}
-static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
-{
- const struct ethhdr *eth = (struct ethhdr *) skb->data;
- const struct vxlan_fdb *f;
-
- if (is_multicast_ether_addr(eth->h_dest))
- return vxlan->gaddr;
-
- f = vxlan_find_mac(vxlan, eth->h_dest);
- if (f)
- return f->remote_ip;
- else
- return vxlan->gaddr;
-
-}
-
static void vxlan_sock_free(struct sk_buff *skb)
{
sock_put(skb->sk);
@@ -684,6 +830,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
struct vxlan_dev *vxlan = netdev_priv(dev);
struct rtable *rt;
const struct iphdr *old_iph;
+ struct ethhdr *eth;
struct iphdr *iph;
struct vxlanhdr *vxh;
struct udphdr *uh;
@@ -694,10 +841,55 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
__be16 df = 0;
__u8 tos, ttl;
int err;
+ bool did_rsc = false;
+ const struct vxlan_fdb *f;
+
+ skb_reset_mac_header(skb);
+ eth = eth_hdr(skb);
- dst = vxlan_find_dst(vxlan, skb);
- if (!dst)
+ if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
+ return arp_reduce(dev, skb);
+ else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
+ did_rsc = route_shortcircuit(dev, skb);
+
+ f = vxlan_find_mac(vxlan, eth->h_dest);
+ if (f == NULL) {
+ did_rsc = false;
+ dst = vxlan->gaddr;
+ if (!dst && (vxlan->flags & VXLAN_F_L2MISS) &&
+ !is_multicast_ether_addr(eth->h_dest))
+ vxlan_fdb_miss(vxlan, eth->h_dest);
+ } else
+ dst = f->remote_ip;
+
+ if (!dst) {
+ if (did_rsc) {
+ __skb_pull(skb, skb_network_offset(skb));
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->pkt_type = PACKET_HOST;
+
+ /* short-circuited back to local bridge */
+ if (netif_rx(skb) == NET_RX_SUCCESS) {
+ struct vxlan_stats *stats =
+ this_cpu_ptr(vxlan->stats);
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_packets++;
+ stats->tx_bytes += pkt_len;
+ u64_stats_update_end(&stats->syncp);
+ } else {
+ dev->stats.tx_errors++;
+ dev->stats.tx_aborted_errors++;
+ }
+ return NETDEV_TX_OK;
+ }
goto drop;
+ }
+
+ if (!skb->encapsulation) {
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+ }
/* Need space for new headers (invalidates iph ptr) */
if (skb_cow_head(skb, VXLAN_HEADROOM))
@@ -769,8 +961,9 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
vxlan_set_owner(dev, skb);
- /* See __IPTUNNEL_XMIT */
- skb->ip_summed = CHECKSUM_NONE;
+ /* See iptunnel_xmit() */
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ skb->ip_summed = CHECKSUM_NONE;
ip_select_ident(iph, &rt->dst, NULL);
err = ip_local_out(skb);
@@ -991,6 +1184,10 @@ static void vxlan_setup(struct net_device *dev)
dev->tx_queue_len = 0;
dev->features |= NETIF_F_LLTX;
dev->features |= NETIF_F_NETNS_LOCAL;
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ dev->features |= NETIF_F_RXCSUM;
+
+ dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
spin_lock_init(&vxlan->hash_lock);
@@ -1020,6 +1217,10 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
[IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
[IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) },
+ [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
+ [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
+ [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
+ [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1111,14 +1312,29 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (data[IFLA_VXLAN_TOS])
vxlan->tos = nla_get_u8(data[IFLA_VXLAN_TOS]);
+ if (data[IFLA_VXLAN_TTL])
+ vxlan->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
+
if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING]))
- vxlan->learn = true;
+ vxlan->flags |= VXLAN_F_LEARN;
if (data[IFLA_VXLAN_AGEING])
vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
else
vxlan->age_interval = FDB_AGE_DEFAULT;
+ if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY]))
+ vxlan->flags |= VXLAN_F_PROXY;
+
+ if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC]))
+ vxlan->flags |= VXLAN_F_RSC;
+
+ if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS]))
+ vxlan->flags |= VXLAN_F_L2MISS;
+
+ if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS]))
+ vxlan->flags |= VXLAN_F_L3MISS;
+
if (data[IFLA_VXLAN_LIMIT])
vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
@@ -1155,6 +1371,10 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_PROXY */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_RSC */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L2MISS */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L3MISS */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
@@ -1183,7 +1403,15 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) ||
- nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) ||
+ nla_put_u8(skb, IFLA_VXLAN_LEARNING,
+ !!(vxlan->flags & VXLAN_F_LEARN)) ||
+ nla_put_u8(skb, IFLA_VXLAN_PROXY,
+ !!(vxlan->flags & VXLAN_F_PROXY)) ||
+ nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) ||
+ nla_put_u8(skb, IFLA_VXLAN_L2MISS,
+ !!(vxlan->flags & VXLAN_F_L2MISS)) ||
+ nla_put_u8(skb, IFLA_VXLAN_L3MISS,
+ !!(vxlan->flags & VXLAN_F_L3MISS)) ||
nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) ||
nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
goto nla_put_failure;
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index eac709bed7ae..df70248e2fda 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -52,9 +52,9 @@ endif
quiet_cmd_build_wanxlfw = BLD FW $@
cmd_build_wanxlfw = \
- $(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
+ $(CPP) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
$(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
- hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
+ hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static const u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
$(obj)/wanxlfw.inc: $(src)/wanxlfw.S
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index ef36cafd44b7..851dc7b7e8b0 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -707,8 +707,7 @@ static void dscc4_free1(struct pci_dev *pdev)
kfree(ppriv);
}
-static int __devinit dscc4_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct dscc4_pci_priv *priv;
struct dscc4_dev_priv *dpriv;
@@ -1968,7 +1967,7 @@ err_out:
return -ENOMEM;
}
-static void __devexit dscc4_remove_one(struct pci_dev *pdev)
+static void dscc4_remove_one(struct pci_dev *pdev)
{
struct dscc4_pci_priv *ppriv;
struct dscc4_dev_priv *root;
@@ -2053,7 +2052,7 @@ static struct pci_driver dscc4_driver = {
.name = DRV_NAME,
.id_table = dscc4_pci_tbl,
.probe = dscc4_init_one,
- .remove = __devexit_p(dscc4_remove_one),
+ .remove = dscc4_remove_one,
};
module_pci_driver(dscc4_driver);
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index b6271325f803..56941d6547eb 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -2361,7 +2361,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
* via a printk and leave the corresponding interface and all that follow
* disabled.
*/
-static char *type_strings[] __devinitdata = {
+static char *type_strings[] = {
"no hardware", /* Should never be seen */
"FarSync T2P",
"FarSync T4P",
@@ -2371,7 +2371,7 @@ static char *type_strings[] __devinitdata = {
"FarSync TE1"
};
-static void __devinit
+static void
fst_init_card(struct fst_card_info *card)
{
int i;
@@ -2415,7 +2415,7 @@ static const struct net_device_ops fst_ops = {
* Initialise card when detected.
* Returns 0 to indicate success, or errno otherwise.
*/
-static int __devinit
+static int
fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int no_of_cards_added = 0;
@@ -2615,7 +2615,7 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/*
* Cleanup and close down a card
*/
-static void __devexit
+static void
fst_remove_one(struct pci_dev *pdev)
{
struct fst_card_info *card;
@@ -2652,7 +2652,7 @@ static struct pci_driver fst_driver = {
.name = FST_NAME,
.id_table = fst_pci_dev_id,
.probe = fst_add_one,
- .remove = __devexit_p(fst_remove_one),
+ .remove = fst_remove_one,
.suspend = NULL,
.resume = NULL,
};
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
index cf4903355a34..62f01b74cbd6 100644
--- a/drivers/net/wan/hd64570.c
+++ b/drivers/net/wan/hd64570.c
@@ -676,8 +676,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef NEED_DETECT_RAM
-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
- u32 ramsize)
+static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize)
{
/* Round RAM size to 32 bits, fill from end to start */
u32 i = ramsize &= ~3;
@@ -705,7 +704,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
#endif /* NEED_DETECT_RAM */
-static void __devinit sca_init(card_t *card, int wait_states)
+static void sca_init(card_t *card, int wait_states)
{
sca_out(wait_states, WCRL, card); /* Wait Control */
sca_out(wait_states, WCRM, card);
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
index e2779faa6c4f..6269a09c7369 100644
--- a/drivers/net/wan/hd64572.c
+++ b/drivers/net/wan/hd64572.c
@@ -605,8 +605,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
}
-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
- u32 ramsize)
+static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize)
{
/* Round RAM size to 32 bits, fill from end to start */
u32 i = ramsize &= ~3;
@@ -625,7 +624,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
}
-static void __devinit sca_init(card_t *card, int wait_states)
+static void sca_init(card_t *card, int wait_states)
{
sca_out(wait_states, WCRL, card); /* Wait Control */
sca_out(wait_states, WCRM, card);
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 760776b3d66c..fc9d11d74d60 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1326,7 +1326,7 @@ static const struct net_device_ops hss_hdlc_ops = {
.ndo_do_ioctl = hss_hdlc_ioctl,
};
-static int __devinit hss_init_one(struct platform_device *pdev)
+static int hss_init_one(struct platform_device *pdev)
{
struct port *port;
struct net_device *dev;
@@ -1377,7 +1377,7 @@ err_free:
return err;
}
-static int __devexit hss_remove_one(struct platform_device *pdev)
+static int hss_remove_one(struct platform_device *pdev)
{
struct port *port = platform_get_drvdata(pdev);
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index f5d533a706ea..7ef435bab425 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -816,8 +816,7 @@ static const struct net_device_ops lmc_ops = {
.ndo_get_stats = lmc_get_stats,
};
-static int __devinit lmc_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
lmc_softc_t *sc;
struct net_device *dev;
@@ -986,7 +985,7 @@ err_req_io:
/*
* Called from pci when removing module.
*/
-static void __devexit lmc_remove_one(struct pci_dev *pdev)
+static void lmc_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -1733,7 +1732,7 @@ static struct pci_driver lmc_driver = {
.name = "lmc",
.id_table = lmc_pci_tbl,
.probe = lmc_init_one,
- .remove = __devexit_p(lmc_remove_one),
+ .remove = lmc_remove_one,
};
module_pci_driver(lmc_driver);
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index 5fe246e060d7..53efc57fcace 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -297,8 +297,8 @@ static const struct net_device_ops pc300_ops = {
.ndo_do_ioctl = pc300_ioctl,
};
-static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int pc300_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
card_t *card;
u32 __iomem *p;
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index 9659fcaa34ed..ddbce54040e2 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -276,8 +276,8 @@ static const struct net_device_ops pci200_ops = {
.ndo_do_ioctl = pci200_ioctl,
};
-static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int pci200_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
card_t *card;
u32 __iomem *p;
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index feb7541b33fb..6a24a5a70cc7 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -557,8 +557,8 @@ static const struct net_device_ops wanxl_ops = {
.ndo_get_stats = wanxl_get_stats,
};
-static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int wanxl_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
card_t *card;
u32 ramsize, stat;
diff --git a/drivers/net/wan/wanxlfw.S b/drivers/net/wan/wanxlfw.S
index 73aae2bf2f1c..21565d59ec7b 100644
--- a/drivers/net/wan/wanxlfw.S
+++ b/drivers/net/wan/wanxlfw.S
@@ -35,6 +35,7 @@
*/
#include <linux/hdlc.h>
+#include <linux/hdlc/ioctl.h>
#include "wanxl.h"
/* memory addresses and offsets */
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index 4b66ab1d0e5c..6702da838b0e 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -209,6 +209,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val)
result = i2400m_reset(i2400m, rt);
if (result >= 0)
result = 0;
+ break;
default:
result = -EINVAL;
}
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 154a4965be4f..3d339e04efb7 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1761,7 +1761,7 @@ static const struct ieee80211_ops adm8211_ops = {
.get_tsf = adm8211_get_tsft
};
-static int __devinit adm8211_probe(struct pci_dev *pdev,
+static int adm8211_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ieee80211_hw *dev;
@@ -1935,7 +1935,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
}
-static void __devexit adm8211_remove(struct pci_dev *pdev)
+static void adm8211_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct adm8211_priv *priv;
@@ -1985,7 +1985,7 @@ static struct pci_driver adm8211_driver = {
.name = "adm8211",
.id_table = adm8211_pci_id_table,
.probe = adm8211_probe,
- .remove = __devexit_p(adm8211_remove),
+ .remove = adm8211_remove,
#ifdef CONFIG_PM
.suspend = adm8211_suspend,
.resume = adm8211_resume,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 3cd05a7173f6..53295418f576 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -78,7 +78,7 @@ static struct pci_driver airo_driver = {
.name = DRV_NAME,
.id_table = card_ids,
.probe = airo_pci_probe,
- .remove = __devexit_p(airo_pci_remove),
+ .remove = airo_pci_remove,
.suspend = airo_pci_suspend,
.resume = airo_pci_resume,
};
@@ -5584,7 +5584,7 @@ static void timer_func( struct net_device *dev ) {
}
#ifdef CONFIG_PCI
-static int __devinit airo_pci_probe(struct pci_dev *pdev,
+static int airo_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pent)
{
struct net_device *dev;
@@ -5606,7 +5606,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
return 0;
}
-static void __devexit airo_pci_remove(struct pci_dev *pdev)
+static void airo_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -7433,7 +7433,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
num_null_ies++;
break;
- case WLAN_EID_GENERIC:
+ case WLAN_EID_VENDOR_SPECIFIC:
if (ie[1] >= 4 &&
ie[2] == 0x00 &&
ie[3] == 0x50 &&
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 99b9ddf21273..77fa4286e5e9 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -379,7 +379,7 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
manifest_sync_timeout);
if (!size) {
- dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
+ dev_err(&udev->dev, "FW buffer length invalid!\n");
return -EINVAL;
}
@@ -391,8 +391,8 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
if (need_dfu_state) {
ret = at76_dfu_get_state(udev, &dfu_state);
if (ret < 0) {
- dev_printk(KERN_ERR, &udev->dev,
- "cannot get DFU state: %d\n", ret);
+ dev_err(&udev->dev,
+ "cannot get DFU state: %d\n", ret);
goto exit;
}
need_dfu_state = 0;
@@ -407,9 +407,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
dfu_timeout = at76_get_timeout(&dfu_stat_buf);
need_dfu_state = 0;
} else
- dev_printk(KERN_ERR, &udev->dev,
- "at76_dfu_get_status returned %d\n",
- ret);
+ dev_err(&udev->dev,
+ "at76_dfu_get_status returned %d\n",
+ ret);
break;
case STATE_DFU_DOWNLOAD_BUSY:
@@ -438,9 +438,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
blockno++;
if (ret != bsize)
- dev_printk(KERN_ERR, &udev->dev,
- "at76_load_int_fw_block "
- "returned %d\n", ret);
+ dev_err(&udev->dev,
+ "at76_load_int_fw_block returned %d\n",
+ ret);
need_dfu_state = 1;
break;
@@ -1255,8 +1255,7 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
- dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
- op_mode);
+ dev_err(&udev->dev, "unexpected opmode %d\n", op_mode);
return -EINVAL;
}
@@ -1275,9 +1274,9 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
size, bsize, blockno);
ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
if (ret != bsize) {
- dev_printk(KERN_ERR, &udev->dev,
- "loading %dth firmware block failed: %d\n",
- blockno, ret);
+ dev_err(&udev->dev,
+ "loading %dth firmware block failed: %d\n",
+ blockno, ret);
goto exit;
}
buf += bsize;
@@ -1293,8 +1292,8 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
exit:
kfree(block);
if (ret < 0)
- dev_printk(KERN_ERR, &udev->dev,
- "downloading external firmware failed: %d\n", ret);
+ dev_err(&udev->dev,
+ "downloading external firmware failed: %d\n", ret);
return ret;
}
@@ -1308,8 +1307,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
need_remap ? 0 : 2 * HZ);
if (ret < 0) {
- dev_printk(KERN_ERR, &udev->dev,
- "downloading internal fw failed with %d\n", ret);
+ dev_err(&udev->dev,
+ "downloading internal fw failed with %d\n", ret);
goto exit;
}
@@ -1319,8 +1318,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
if (need_remap) {
ret = at76_remap(udev);
if (ret < 0) {
- dev_printk(KERN_ERR, &udev->dev,
- "sending REMAP failed with %d\n", ret);
+ dev_err(&udev->dev,
+ "sending REMAP failed with %d\n", ret);
goto exit;
}
}
@@ -1555,11 +1554,10 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
if (ret < 0) {
- dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
- fwe->fwname);
- dev_printk(KERN_ERR, &udev->dev,
- "you may need to download the firmware from "
- "http://developer.berlios.de/projects/at76c503a/\n");
+ dev_err(&udev->dev, "firmware %s not found!\n",
+ fwe->fwname);
+ dev_err(&udev->dev,
+ "you may need to download the firmware from http://developer.berlios.de/projects/at76c503a/\n");
goto exit;
}
@@ -1567,17 +1565,17 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
fwh = (struct at76_fw_header *)(fwe->fw->data);
if (fwe->fw->size <= sizeof(*fwh)) {
- dev_printk(KERN_ERR, &udev->dev,
- "firmware is too short (0x%zx)\n", fwe->fw->size);
+ dev_err(&udev->dev,
+ "firmware is too short (0x%zx)\n", fwe->fw->size);
goto exit;
}
/* CRC currently not checked */
fwe->board_type = le32_to_cpu(fwh->board_type);
if (fwe->board_type != board_type) {
- dev_printk(KERN_ERR, &udev->dev,
- "board type mismatch, requested %u, got %u\n",
- board_type, fwe->board_type);
+ dev_err(&udev->dev,
+ "board type mismatch, requested %u, got %u\n",
+ board_type, fwe->board_type);
goto exit;
}
@@ -2150,8 +2148,7 @@ static int at76_alloc_urbs(struct at76_priv *priv,
}
if (!ep_in || !ep_out) {
- dev_printk(KERN_ERR, &interface->dev,
- "bulk endpoints missing\n");
+ dev_err(&interface->dev, "bulk endpoints missing\n");
return -ENXIO;
}
@@ -2161,15 +2158,14 @@ static int at76_alloc_urbs(struct at76_priv *priv,
priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!priv->rx_urb || !priv->tx_urb) {
- dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
+ dev_err(&interface->dev, "cannot allocate URB\n");
return -ENOMEM;
}
buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!priv->bulk_out_buffer) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot allocate output buffer\n");
+ dev_err(&interface->dev, "cannot allocate output buffer\n");
return -ENOMEM;
}
@@ -2230,8 +2226,7 @@ static int at76_init_new_device(struct at76_priv *priv,
/* MAC address */
ret = at76_get_hw_config(priv);
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot get MAC address\n");
+ dev_err(&interface->dev, "cannot get MAC address\n");
goto exit;
}
@@ -2358,8 +2353,8 @@ static int at76_probe(struct usb_interface *interface,
we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
if (op_mode == OPMODE_HW_CONFIG_MODE) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot handle a device in HW_CONFIG_MODE\n");
+ dev_err(&interface->dev,
+ "cannot handle a device in HW_CONFIG_MODE\n");
ret = -EBUSY;
goto error;
}
@@ -2371,9 +2366,9 @@ static int at76_probe(struct usb_interface *interface,
"downloading internal firmware\n");
ret = at76_load_internal_fw(udev, fwe);
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "error %d downloading internal firmware\n",
- ret);
+ dev_err(&interface->dev,
+ "error %d downloading internal firmware\n",
+ ret);
goto error;
}
usb_put_dev(udev);
@@ -2408,8 +2403,8 @@ static int at76_probe(struct usb_interface *interface,
/* Re-check firmware version */
ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "error %d getting firmware version\n", ret);
+ dev_err(&interface->dev,
+ "error %d getting firmware version\n", ret);
goto error;
}
}
@@ -2449,7 +2444,7 @@ static void at76_disconnect(struct usb_interface *interface)
wiphy_info(priv->hw->wiphy, "disconnecting\n");
at76_delete_device(priv);
- dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
+ dev_info(&interface->dev, "disconnected\n");
}
/* Structure for registering this driver with the USB subsystem */
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 09602241901b..1a67a4f829fe 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,4 +1,7 @@
-menuconfig ATH_COMMON
+config ATH_COMMON
+ tristate
+
+menuconfig ATH_CARDS
tristate "Atheros Wireless Cards"
depends on CFG80211 && (!UML || BROKEN)
---help---
@@ -14,7 +17,7 @@ menuconfig ATH_COMMON
http://wireless.kernel.org/en/users/Drivers/Atheros
-if ATH_COMMON
+if ATH_CARDS
config ATH_DEBUG
bool "Atheros wireless debugging"
@@ -26,5 +29,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig"
source "drivers/net/wireless/ath/ath9k/Kconfig"
source "drivers/net/wireless/ath/carl9170/Kconfig"
source "drivers/net/wireless/ath/ath6kl/Kconfig"
+source "drivers/net/wireless/ath/ar5523/Kconfig"
endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index d716b748e574..1e18621326dc 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K_HW) += ath9k/
obj-$(CONFIG_CARL9170) += carl9170/
obj-$(CONFIG_ATH6KL) += ath6kl/
+obj-$(CONFIG_AR5523) += ar5523/
obj-$(CONFIG_ATH_COMMON) += ath.o
diff --git a/drivers/net/wireless/ath/ar5523/Kconfig b/drivers/net/wireless/ath/ar5523/Kconfig
new file mode 100644
index 000000000000..0d320cc7769b
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/Kconfig
@@ -0,0 +1,8 @@
+config AR5523
+ tristate "Atheros AR5523 wireless driver support"
+ depends on MAC80211 && USB
+ select ATH_COMMON
+ select FW_LOADER
+ ---help---
+ This module add support for AR5523 based USB dongles such as D-Link
+ DWL-G132, Netgear WPN111 and many more.
diff --git a/drivers/net/wireless/ath/ar5523/Makefile b/drivers/net/wireless/ath/ar5523/Makefile
new file mode 100644
index 000000000000..ebf7f3bf0a33
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_AR5523) := ar5523.o
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
new file mode 100644
index 000000000000..7157f7d311c5
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -0,0 +1,1798 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * 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.
+ */
+
+/*
+ * This driver is based on the uath driver written by Damien Bergamini for
+ * OpenBSD, who did black-box analysis of the Windows binary driver to find
+ * out how the hardware works. It contains a lot magic numbers because of
+ * that and only has minimal functionality.
+ */
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "ar5523.h"
+#include "ar5523_hw.h"
+
+/*
+ * Various supported device vendors/products.
+ * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g
+ */
+
+static int ar5523_submit_rx_cmd(struct ar5523 *ar);
+static void ar5523_data_tx_pkt_put(struct ar5523 *ar);
+
+static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr,
+ struct ar5523_tx_cmd *cmd)
+{
+ int dlen, olen;
+ __be32 *rp;
+
+ dlen = be32_to_cpu(hdr->len) - sizeof(*hdr);
+
+ if (dlen < 0) {
+ WARN_ON(1);
+ goto out;
+ }
+
+ ar5523_dbg(ar, "Code = %d len = %d\n", be32_to_cpu(hdr->code) & 0xff,
+ dlen);
+
+ rp = (__be32 *)(hdr + 1);
+ if (dlen >= sizeof(u32)) {
+ olen = be32_to_cpu(rp[0]);
+ dlen -= sizeof(u32);
+ if (olen == 0) {
+ /* convention is 0 =>'s one word */
+ olen = sizeof(u32);
+ }
+ } else
+ olen = 0;
+
+ if (cmd->odata) {
+ if (cmd->olen < olen) {
+ ar5523_err(ar, "olen to small %d < %d\n",
+ cmd->olen, olen);
+ cmd->olen = 0;
+ cmd->res = -EOVERFLOW;
+ } else {
+ cmd->olen = olen;
+ memcpy(cmd->odata, &rp[1], olen);
+ cmd->res = 0;
+ }
+ }
+
+out:
+ complete(&cmd->done);
+}
+
+static void ar5523_cmd_rx_cb(struct urb *urb)
+{
+ struct ar5523 *ar = urb->context;
+ struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+ struct ar5523_cmd_hdr *hdr = ar->rx_cmd_buf;
+ int dlen;
+ u32 code, hdrlen;
+
+ if (urb->status) {
+ if (urb->status != -ESHUTDOWN)
+ ar5523_err(ar, "RX USB error %d.\n", urb->status);
+ goto skip;
+ }
+
+ if (urb->actual_length < sizeof(struct ar5523_cmd_hdr)) {
+ ar5523_err(ar, "RX USB to short.\n");
+ goto skip;
+ }
+
+ ar5523_dbg(ar, "%s code %02x priv %d\n", __func__,
+ be32_to_cpu(hdr->code) & 0xff, hdr->priv);
+
+ code = be32_to_cpu(hdr->code);
+ hdrlen = be32_to_cpu(hdr->len);
+
+ switch (code & 0xff) {
+ default:
+ /* reply to a read command */
+ if (hdr->priv != AR5523_CMD_ID) {
+ ar5523_err(ar, "Unexpected command id: %02x\n",
+ code & 0xff);
+ goto skip;
+ }
+ ar5523_read_reply(ar, hdr, cmd);
+ break;
+
+ case WDCMSG_DEVICE_AVAIL:
+ ar5523_dbg(ar, "WDCMSG_DEVICE_AVAIL\n");
+ cmd->res = 0;
+ cmd->olen = 0;
+ complete(&cmd->done);
+ break;
+
+ case WDCMSG_SEND_COMPLETE:
+ ar5523_dbg(ar, "WDCMSG_SEND_COMPLETE: %d pending\n",
+ atomic_read(&ar->tx_nr_pending));
+ if (!test_bit(AR5523_HW_UP, &ar->flags))
+ ar5523_dbg(ar, "Unexpected WDCMSG_SEND_COMPLETE\n");
+ else {
+ mod_timer(&ar->tx_wd_timer,
+ jiffies + AR5523_TX_WD_TIMEOUT);
+ ar5523_data_tx_pkt_put(ar);
+
+ }
+ break;
+
+ case WDCMSG_TARGET_START:
+ /* This command returns a bogus id so it needs special
+ handling */
+ dlen = hdrlen - sizeof(*hdr);
+ if (dlen != (int)sizeof(u32)) {
+ ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START");
+ return;
+ }
+ memcpy(cmd->odata, hdr + 1, sizeof(u32));
+ cmd->olen = sizeof(u32);
+ cmd->res = 0;
+ complete(&cmd->done);
+ break;
+
+ case WDCMSG_STATS_UPDATE:
+ ar5523_dbg(ar, "WDCMSG_STATS_UPDATE\n");
+ break;
+ }
+
+skip:
+ ar5523_submit_rx_cmd(ar);
+}
+
+static int ar5523_alloc_rx_cmd(struct ar5523 *ar)
+{
+ ar->rx_cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ar->rx_cmd_urb)
+ return -ENOMEM;
+
+ ar->rx_cmd_buf = usb_alloc_coherent(ar->dev, AR5523_MAX_RXCMDSZ,
+ GFP_KERNEL,
+ &ar->rx_cmd_urb->transfer_dma);
+ if (!ar->rx_cmd_buf) {
+ usb_free_urb(ar->rx_cmd_urb);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void ar5523_cancel_rx_cmd(struct ar5523 *ar)
+{
+ usb_kill_urb(ar->rx_cmd_urb);
+}
+
+static void ar5523_free_rx_cmd(struct ar5523 *ar)
+{
+ usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ,
+ ar->rx_cmd_buf, ar->rx_cmd_urb->transfer_dma);
+ usb_free_urb(ar->rx_cmd_urb);
+}
+
+static int ar5523_submit_rx_cmd(struct ar5523 *ar)
+{
+ int error;
+
+ usb_fill_bulk_urb(ar->rx_cmd_urb, ar->dev,
+ ar5523_cmd_rx_pipe(ar->dev), ar->rx_cmd_buf,
+ AR5523_MAX_RXCMDSZ, ar5523_cmd_rx_cb, ar);
+ ar->rx_cmd_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ error = usb_submit_urb(ar->rx_cmd_urb, GFP_ATOMIC);
+ if (error) {
+ if (error != -ENODEV)
+ ar5523_err(ar, "error %d when submitting rx urb\n",
+ error);
+ return error;
+ }
+ return 0;
+}
+
+/*
+ * Command submitted cb
+ */
+static void ar5523_cmd_tx_cb(struct urb *urb)
+{
+ struct ar5523_tx_cmd *cmd = urb->context;
+ struct ar5523 *ar = cmd->ar;
+
+ if (urb->status) {
+ ar5523_err(ar, "Failed to TX command. Status = %d\n",
+ urb->status);
+ cmd->res = urb->status;
+ complete(&cmd->done);
+ return;
+ }
+
+ if (!(cmd->flags & AR5523_CMD_FLAG_READ)) {
+ cmd->res = 0;
+ complete(&cmd->done);
+ }
+}
+
+static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
+ int ilen, void *odata, int olen, int flags)
+{
+ struct ar5523_cmd_hdr *hdr;
+ struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+ int xferlen, error;
+
+ /* always bulk-out a multiple of 4 bytes */
+ xferlen = (sizeof(struct ar5523_cmd_hdr) + ilen + 3) & ~3;
+
+ hdr = (struct ar5523_cmd_hdr *)cmd->buf_tx;
+ memset(hdr, 0, sizeof(struct ar5523_cmd_hdr));
+ hdr->len = cpu_to_be32(xferlen);
+ hdr->code = cpu_to_be32(code);
+ hdr->priv = AR5523_CMD_ID;
+
+ if (flags & AR5523_CMD_FLAG_MAGIC)
+ hdr->magic = cpu_to_be32(1 << 24);
+ memcpy(hdr + 1, idata, ilen);
+
+ cmd->odata = odata;
+ cmd->olen = olen;
+ cmd->flags = flags;
+
+ ar5523_dbg(ar, "do cmd %02x\n", code);
+
+ usb_fill_bulk_urb(cmd->urb_tx, ar->dev, ar5523_cmd_tx_pipe(ar->dev),
+ cmd->buf_tx, xferlen, ar5523_cmd_tx_cb, cmd);
+ cmd->urb_tx->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ error = usb_submit_urb(cmd->urb_tx, GFP_KERNEL);
+ if (error) {
+ ar5523_err(ar, "could not send command 0x%x, error=%d\n",
+ code, error);
+ return error;
+ }
+
+ if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) {
+ cmd->odata = NULL;
+ ar5523_err(ar, "timeout waiting for command %02x reply\n",
+ code);
+ cmd->res = -ETIMEDOUT;
+ }
+ return cmd->res;
+}
+
+static int ar5523_cmd_write(struct ar5523 *ar, u32 code, const void *data,
+ int len, int flags)
+{
+ flags &= ~AR5523_CMD_FLAG_READ;
+ return ar5523_cmd(ar, code, data, len, NULL, 0, flags);
+}
+
+static int ar5523_cmd_read(struct ar5523 *ar, u32 code, const void *idata,
+ int ilen, void *odata, int olen, int flags)
+{
+ flags |= AR5523_CMD_FLAG_READ;
+ return ar5523_cmd(ar, code, idata, ilen, odata, olen, flags);
+}
+
+static int ar5523_config(struct ar5523 *ar, u32 reg, u32 val)
+{
+ struct ar5523_write_mac write;
+ int error;
+
+ write.reg = cpu_to_be32(reg);
+ write.len = cpu_to_be32(0); /* 0 = single write */
+ *(__be32 *)write.data = cpu_to_be32(val);
+
+ error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write,
+ 3 * sizeof(u32), 0);
+ if (error != 0)
+ ar5523_err(ar, "could not write register 0x%02x\n", reg);
+ return error;
+}
+
+static int ar5523_config_multi(struct ar5523 *ar, u32 reg, const void *data,
+ int len)
+{
+ struct ar5523_write_mac write;
+ int error;
+
+ write.reg = cpu_to_be32(reg);
+ write.len = cpu_to_be32(len);
+ memcpy(write.data, data, len);
+
+ /* properly handle the case where len is zero (reset) */
+ error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write,
+ (len == 0) ? sizeof(u32) : 2 * sizeof(u32) + len, 0);
+ if (error != 0)
+ ar5523_err(ar, "could not write %d bytes to register 0x%02x\n",
+ len, reg);
+ return error;
+}
+
+static int ar5523_get_status(struct ar5523 *ar, u32 which, void *odata,
+ int olen)
+{
+ int error;
+ __be32 which_be;
+
+ which_be = cpu_to_be32(which);
+ error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_STATUS,
+ &which_be, sizeof(which_be), odata, olen, AR5523_CMD_FLAG_MAGIC);
+ if (error != 0)
+ ar5523_err(ar, "could not read EEPROM offset 0x%02x\n", which);
+ return error;
+}
+
+static int ar5523_get_capability(struct ar5523 *ar, u32 cap, u32 *val)
+{
+ int error;
+ __be32 cap_be, val_be;
+
+ cap_be = cpu_to_be32(cap);
+ error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY, &cap_be,
+ sizeof(cap_be), &val_be, sizeof(__be32),
+ AR5523_CMD_FLAG_MAGIC);
+ if (error != 0) {
+ ar5523_err(ar, "could not read capability %u\n", cap);
+ return error;
+ }
+ *val = be32_to_cpu(val_be);
+ return error;
+}
+
+static int ar5523_get_devcap(struct ar5523 *ar)
+{
+#define GETCAP(x) do { \
+ error = ar5523_get_capability(ar, x, &cap); \
+ if (error != 0) \
+ return error; \
+ ar5523_info(ar, "Cap: " \
+ "%s=0x%08x\n", #x, cap); \
+} while (0)
+ int error;
+ u32 cap;
+
+ /* collect device capabilities */
+ GETCAP(CAP_TARGET_VERSION);
+ GETCAP(CAP_TARGET_REVISION);
+ GETCAP(CAP_MAC_VERSION);
+ GETCAP(CAP_MAC_REVISION);
+ GETCAP(CAP_PHY_REVISION);
+ GETCAP(CAP_ANALOG_5GHz_REVISION);
+ GETCAP(CAP_ANALOG_2GHz_REVISION);
+
+ GETCAP(CAP_REG_DOMAIN);
+ GETCAP(CAP_REG_CAP_BITS);
+ GETCAP(CAP_WIRELESS_MODES);
+ GETCAP(CAP_CHAN_SPREAD_SUPPORT);
+ GETCAP(CAP_COMPRESS_SUPPORT);
+ GETCAP(CAP_BURST_SUPPORT);
+ GETCAP(CAP_FAST_FRAMES_SUPPORT);
+ GETCAP(CAP_CHAP_TUNING_SUPPORT);
+ GETCAP(CAP_TURBOG_SUPPORT);
+ GETCAP(CAP_TURBO_PRIME_SUPPORT);
+ GETCAP(CAP_DEVICE_TYPE);
+ GETCAP(CAP_WME_SUPPORT);
+ GETCAP(CAP_TOTAL_QUEUES);
+ GETCAP(CAP_CONNECTION_ID_MAX);
+
+ GETCAP(CAP_LOW_5GHZ_CHAN);
+ GETCAP(CAP_HIGH_5GHZ_CHAN);
+ GETCAP(CAP_LOW_2GHZ_CHAN);
+ GETCAP(CAP_HIGH_2GHZ_CHAN);
+ GETCAP(CAP_TWICE_ANTENNAGAIN_5G);
+ GETCAP(CAP_TWICE_ANTENNAGAIN_2G);
+
+ GETCAP(CAP_CIPHER_AES_CCM);
+ GETCAP(CAP_CIPHER_TKIP);
+ GETCAP(CAP_MIC_TKIP);
+ return 0;
+}
+
+static int ar5523_set_ledsteady(struct ar5523 *ar, int lednum, int ledmode)
+{
+ struct ar5523_cmd_ledsteady led;
+
+ led.lednum = cpu_to_be32(lednum);
+ led.ledmode = cpu_to_be32(ledmode);
+
+ ar5523_dbg(ar, "set %s led %s (steady)\n",
+ (lednum == UATH_LED_LINK) ? "link" : "activity",
+ ledmode ? "on" : "off");
+ return ar5523_cmd_write(ar, WDCMSG_SET_LED_STEADY, &led, sizeof(led),
+ 0);
+}
+
+static int ar5523_set_rxfilter(struct ar5523 *ar, u32 bits, u32 op)
+{
+ struct ar5523_cmd_rx_filter rxfilter;
+
+ rxfilter.bits = cpu_to_be32(bits);
+ rxfilter.op = cpu_to_be32(op);
+
+ ar5523_dbg(ar, "setting Rx filter=0x%x flags=0x%x\n", bits, op);
+ return ar5523_cmd_write(ar, WDCMSG_RX_FILTER, &rxfilter,
+ sizeof(rxfilter), 0);
+}
+
+static int ar5523_reset_tx_queues(struct ar5523 *ar)
+{
+ __be32 qid = cpu_to_be32(0);
+
+ ar5523_dbg(ar, "resetting Tx queue\n");
+ return ar5523_cmd_write(ar, WDCMSG_RELEASE_TX_QUEUE,
+ &qid, sizeof(qid), 0);
+}
+
+static int ar5523_set_chan(struct ar5523 *ar)
+{
+ struct ieee80211_conf *conf = &ar->hw->conf;
+
+ struct ar5523_cmd_reset reset;
+
+ memset(&reset, 0, sizeof(reset));
+ reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ);
+ reset.flags |= cpu_to_be32(UATH_CHAN_OFDM);
+ reset.freq = cpu_to_be32(conf->channel->center_freq);
+ reset.maxrdpower = cpu_to_be32(50); /* XXX */
+ reset.channelchange = cpu_to_be32(1);
+ reset.keeprccontent = cpu_to_be32(0);
+
+ ar5523_dbg(ar, "set chan flags 0x%x freq %d\n",
+ be32_to_cpu(reset.flags),
+ conf->channel->center_freq);
+ return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0);
+}
+
+static int ar5523_queue_init(struct ar5523 *ar)
+{
+ struct ar5523_cmd_txq_setup qinfo;
+
+ ar5523_dbg(ar, "setting up Tx queue\n");
+ qinfo.qid = cpu_to_be32(0);
+ qinfo.len = cpu_to_be32(sizeof(qinfo.attr));
+ qinfo.attr.priority = cpu_to_be32(0); /* XXX */
+ qinfo.attr.aifs = cpu_to_be32(3);
+ qinfo.attr.logcwmin = cpu_to_be32(4);
+ qinfo.attr.logcwmax = cpu_to_be32(10);
+ qinfo.attr.bursttime = cpu_to_be32(0);
+ qinfo.attr.mode = cpu_to_be32(0);
+ qinfo.attr.qflags = cpu_to_be32(1); /* XXX? */
+ return ar5523_cmd_write(ar, WDCMSG_SETUP_TX_QUEUE, &qinfo,
+ sizeof(qinfo), 0);
+}
+
+static int ar5523_switch_chan(struct ar5523 *ar)
+{
+ int error;
+
+ error = ar5523_set_chan(ar);
+ if (error) {
+ ar5523_err(ar, "could not set chan, error %d\n", error);
+ goto out_err;
+ }
+
+ /* reset Tx rings */
+ error = ar5523_reset_tx_queues(ar);
+ if (error) {
+ ar5523_err(ar, "could not reset Tx queues, error %d\n",
+ error);
+ goto out_err;
+ }
+ /* set Tx rings WME properties */
+ error = ar5523_queue_init(ar);
+ if (error)
+ ar5523_err(ar, "could not init wme, error %d\n", error);
+
+out_err:
+ return error;
+}
+
+static void ar5523_rx_data_put(struct ar5523 *ar,
+ struct ar5523_rx_data *data)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+ list_move(&data->list, &ar->rx_data_free);
+ spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+}
+
+static void ar5523_data_rx_cb(struct urb *urb)
+{
+ struct ar5523_rx_data *data = urb->context;
+ struct ar5523 *ar = data->ar;
+ struct ar5523_rx_desc *desc;
+ struct ar5523_chunk *chunk;
+ struct ieee80211_hw *hw = ar->hw;
+ struct ieee80211_rx_status *rx_status;
+ u32 rxlen;
+ int usblen = urb->actual_length;
+ int hdrlen, pad;
+
+ ar5523_dbg(ar, "%s\n", __func__);
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (urb->status != -ESHUTDOWN)
+ ar5523_err(ar, "%s: USB err: %d\n", __func__,
+ urb->status);
+ goto skip;
+ }
+
+ if (usblen < AR5523_MIN_RXBUFSZ) {
+ ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen);
+ goto skip;
+ }
+
+ chunk = (struct ar5523_chunk *) data->skb->data;
+
+ if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) ||
+ chunk->seqnum != 0) {
+ ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n",
+ chunk->seqnum, chunk->flags,
+ be16_to_cpu(chunk->length));
+ goto skip;
+ }
+
+ /* Rx descriptor is located at the end, 32-bit aligned */
+ desc = (struct ar5523_rx_desc *)
+ (data->skb->data + usblen - sizeof(struct ar5523_rx_desc));
+
+ rxlen = be32_to_cpu(desc->len);
+ if (rxlen > ar->rxbufsz) {
+ ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n",
+ be32_to_cpu(desc->len));
+ goto skip;
+ }
+
+ if (!rxlen) {
+ ar5523_dbg(ar, "RX: rxlen is 0\n");
+ goto skip;
+ }
+
+ if (be32_to_cpu(desc->status) != 0) {
+ ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n",
+ be32_to_cpu(desc->status), be32_to_cpu(desc->len));
+ goto skip;
+ }
+
+ skb_reserve(data->skb, sizeof(*chunk));
+ skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc));
+
+ hdrlen = ieee80211_get_hdrlen_from_skb(data->skb);
+ if (!IS_ALIGNED(hdrlen, 4)) {
+ ar5523_dbg(ar, "eek, alignment workaround activated\n");
+ pad = ALIGN(hdrlen, 4) - hdrlen;
+ memmove(data->skb->data + pad, data->skb->data, hdrlen);
+ skb_pull(data->skb, pad);
+ skb_put(data->skb, pad);
+ }
+
+ rx_status = IEEE80211_SKB_RXCB(data->skb);
+ memset(rx_status, 0, sizeof(*rx_status));
+ rx_status->freq = be32_to_cpu(desc->channel);
+ rx_status->band = hw->conf.channel->band;
+ rx_status->signal = -95 + be32_to_cpu(desc->rssi);
+
+ ieee80211_rx_irqsafe(hw, data->skb);
+ data->skb = NULL;
+
+skip:
+ if (data->skb) {
+ dev_kfree_skb_irq(data->skb);
+ data->skb = NULL;
+ }
+
+ ar5523_rx_data_put(ar, data);
+ if (atomic_inc_return(&ar->rx_data_free_cnt) >=
+ AR5523_RX_DATA_REFILL_COUNT &&
+ test_bit(AR5523_HW_UP, &ar->flags))
+ queue_work(ar->wq, &ar->rx_refill_work);
+}
+
+static void ar5523_rx_refill_work(struct work_struct *work)
+{
+ struct ar5523 *ar = container_of(work, struct ar5523, rx_refill_work);
+ struct ar5523_rx_data *data;
+ unsigned long flags;
+ int error;
+
+ ar5523_dbg(ar, "%s\n", __func__);
+ do {
+ spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+
+ if (!list_empty(&ar->rx_data_free))
+ data = (struct ar5523_rx_data *) ar->rx_data_free.next;
+ else
+ data = NULL;
+ spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+
+ if (!data)
+ goto done;
+
+ data->skb = alloc_skb(ar->rxbufsz, GFP_KERNEL);
+ if (!data->skb) {
+ ar5523_err(ar, "could not allocate rx skbuff\n");
+ return;
+ }
+
+ usb_fill_bulk_urb(data->urb, ar->dev,
+ ar5523_data_rx_pipe(ar->dev), data->skb->data,
+ ar->rxbufsz, ar5523_data_rx_cb, data);
+
+ spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+ list_move(&data->list, &ar->rx_data_used);
+ spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+ atomic_dec(&ar->rx_data_free_cnt);
+
+ error = usb_submit_urb(data->urb, GFP_KERNEL);
+ if (error) {
+ kfree_skb(data->skb);
+ if (error != -ENODEV)
+ ar5523_err(ar, "Err sending rx data urb %d\n",
+ error);
+ ar5523_rx_data_put(ar, data);
+ atomic_inc(&ar->rx_data_free_cnt);
+ return;
+ }
+
+ } while (true);
+done:
+ return;
+}
+
+static void ar5523_cancel_rx_bufs(struct ar5523 *ar)
+{
+ struct ar5523_rx_data *data;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+ if (!list_empty(&ar->rx_data_used))
+ data = (struct ar5523_rx_data *) ar->rx_data_used.next;
+ else
+ data = NULL;
+ spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+
+ if (!data)
+ break;
+
+ usb_kill_urb(data->urb);
+ list_move(&data->list, &ar->rx_data_free);
+ atomic_inc(&ar->rx_data_free_cnt);
+ } while (data);
+}
+
+static void ar5523_free_rx_bufs(struct ar5523 *ar)
+{
+ struct ar5523_rx_data *data;
+
+ ar5523_cancel_rx_bufs(ar);
+ while (!list_empty(&ar->rx_data_free)) {
+ data = (struct ar5523_rx_data *) ar->rx_data_free.next;
+ list_del(&data->list);
+ usb_free_urb(data->urb);
+ }
+}
+
+static int ar5523_alloc_rx_bufs(struct ar5523 *ar)
+{
+ int i;
+
+ for (i = 0; i < AR5523_RX_DATA_COUNT; i++) {
+ struct ar5523_rx_data *data = &ar->rx_data[i];
+
+ data->ar = ar;
+ data->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!data->urb) {
+ ar5523_err(ar, "could not allocate rx data urb\n");
+ goto err;
+ }
+ list_add_tail(&data->list, &ar->rx_data_free);
+ atomic_inc(&ar->rx_data_free_cnt);
+ }
+ return 0;
+
+err:
+ ar5523_free_rx_bufs(ar);
+ return -ENOMEM;
+}
+
+static void ar5523_data_tx_pkt_put(struct ar5523 *ar)
+{
+ atomic_dec(&ar->tx_nr_total);
+ if (!atomic_dec_return(&ar->tx_nr_pending)) {
+ del_timer(&ar->tx_wd_timer);
+ wake_up(&ar->tx_flush_waitq);
+ }
+
+ if (atomic_read(&ar->tx_nr_total) < AR5523_TX_DATA_RESTART_COUNT) {
+ ar5523_dbg(ar, "restart tx queue\n");
+ ieee80211_wake_queues(ar->hw);
+ }
+}
+
+static void ar5523_data_tx_cb(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ struct ar5523_tx_data *data = (struct ar5523_tx_data *)
+ txi->driver_data;
+ struct ar5523 *ar = data->ar;
+ unsigned long flags;
+
+ ar5523_dbg(ar, "data tx urb completed: %d\n", urb->status);
+
+ spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+ list_del(&data->list);
+ spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+ if (urb->status) {
+ ar5523_dbg(ar, "%s: urb status: %d\n", __func__, urb->status);
+ ar5523_data_tx_pkt_put(ar);
+ ieee80211_free_txskb(ar->hw, skb);
+ } else {
+ skb_pull(skb, sizeof(struct ar5523_tx_desc) + sizeof(__be32));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+ }
+ usb_free_urb(urb);
+}
+
+static void ar5523_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ struct ar5523_tx_data *data = (struct ar5523_tx_data *)
+ txi->driver_data;
+ struct ar5523 *ar = hw->priv;
+ unsigned long flags;
+
+ ar5523_dbg(ar, "tx called\n");
+ if (atomic_inc_return(&ar->tx_nr_total) >= AR5523_TX_DATA_COUNT) {
+ ar5523_dbg(ar, "tx queue full\n");
+ ar5523_dbg(ar, "stop queues (tot %d pend %d)\n",
+ atomic_read(&ar->tx_nr_total),
+ atomic_read(&ar->tx_nr_pending));
+ ieee80211_stop_queues(hw);
+ }
+
+ data->skb = skb;
+
+ spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+ list_add_tail(&data->list, &ar->tx_queue_pending);
+ spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+ ieee80211_queue_work(ar->hw, &ar->tx_work);
+}
+
+static void ar5523_tx_work_locked(struct ar5523 *ar)
+{
+ struct ar5523_tx_data *data;
+ struct ar5523_tx_desc *desc;
+ struct ar5523_chunk *chunk;
+ struct ieee80211_tx_info *txi;
+ struct urb *urb;
+ struct sk_buff *skb;
+ int error = 0, paylen;
+ u32 txqid;
+ unsigned long flags;
+
+ BUILD_BUG_ON(sizeof(struct ar5523_tx_data) >
+ IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
+
+ ar5523_dbg(ar, "%s\n", __func__);
+ do {
+ spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+ if (!list_empty(&ar->tx_queue_pending)) {
+ data = (struct ar5523_tx_data *)
+ ar->tx_queue_pending.next;
+ list_del(&data->list);
+ } else
+ data = NULL;
+ spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+ if (!data)
+ break;
+
+ skb = data->skb;
+ txqid = 0;
+ txi = IEEE80211_SKB_CB(skb);
+ paylen = skb->len;
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ ar5523_err(ar, "Failed to allocate TX urb\n");
+ ieee80211_free_txskb(ar->hw, skb);
+ continue;
+ }
+
+ data->ar = ar;
+ data->urb = urb;
+
+ desc = (struct ar5523_tx_desc *)skb_push(skb, sizeof(*desc));
+ chunk = (struct ar5523_chunk *)skb_push(skb, sizeof(*chunk));
+
+ chunk->seqnum = 0;
+ chunk->flags = UATH_CFLAGS_FINAL;
+ chunk->length = cpu_to_be16(skb->len);
+
+ desc->msglen = cpu_to_be32(skb->len);
+ desc->msgid = AR5523_DATA_ID;
+ desc->buflen = cpu_to_be32(paylen);
+ desc->type = cpu_to_be32(WDCMSG_SEND);
+ desc->flags = cpu_to_be32(UATH_TX_NOTIFY);
+
+ if (test_bit(AR5523_CONNECTED, &ar->flags))
+ desc->connid = cpu_to_be32(AR5523_ID_BSS);
+ else
+ desc->connid = cpu_to_be32(AR5523_ID_BROADCAST);
+
+ if (txi->flags & IEEE80211_TX_CTL_USE_MINRATE)
+ txqid |= UATH_TXQID_MINRATE;
+
+ desc->txqid = cpu_to_be32(txqid);
+
+ urb->transfer_flags = URB_ZERO_PACKET;
+ usb_fill_bulk_urb(urb, ar->dev, ar5523_data_tx_pipe(ar->dev),
+ skb->data, skb->len, ar5523_data_tx_cb, skb);
+
+ spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+ list_add_tail(&data->list, &ar->tx_queue_submitted);
+ spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+ mod_timer(&ar->tx_wd_timer, jiffies + AR5523_TX_WD_TIMEOUT);
+ atomic_inc(&ar->tx_nr_pending);
+
+ ar5523_dbg(ar, "TX Frame (%d pending)\n",
+ atomic_read(&ar->tx_nr_pending));
+ error = usb_submit_urb(urb, GFP_KERNEL);
+ if (error) {
+ ar5523_err(ar, "error %d when submitting tx urb\n",
+ error);
+ spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+ list_del(&data->list);
+ spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+ atomic_dec(&ar->tx_nr_pending);
+ ar5523_data_tx_pkt_put(ar);
+ usb_free_urb(urb);
+ ieee80211_free_txskb(ar->hw, skb);
+ }
+ } while (true);
+}
+
+static void ar5523_tx_work(struct work_struct *work)
+{
+ struct ar5523 *ar = container_of(work, struct ar5523, tx_work);
+
+ ar5523_dbg(ar, "%s\n", __func__);
+ mutex_lock(&ar->mutex);
+ ar5523_tx_work_locked(ar);
+ mutex_unlock(&ar->mutex);
+}
+
+static void ar5523_tx_wd_timer(unsigned long arg)
+{
+ struct ar5523 *ar = (struct ar5523 *) arg;
+
+ ar5523_dbg(ar, "TX watchdog timer triggered\n");
+ ieee80211_queue_work(ar->hw, &ar->tx_wd_work);
+}
+
+static void ar5523_tx_wd_work(struct work_struct *work)
+{
+ struct ar5523 *ar = container_of(work, struct ar5523, tx_wd_work);
+
+ /* Occasionally the TX queues stop responding. The only way to
+ * recover seems to be to reset the dongle.
+ */
+
+ mutex_lock(&ar->mutex);
+ ar5523_err(ar, "TX queue stuck (tot %d pend %d)\n",
+ atomic_read(&ar->tx_nr_total),
+ atomic_read(&ar->tx_nr_pending));
+
+ ar5523_err(ar, "Will restart dongle.\n");
+ ar5523_cmd_write(ar, WDCMSG_TARGET_RESET, NULL, 0, 0);
+ mutex_unlock(&ar->mutex);
+}
+
+static void ar5523_flush_tx(struct ar5523 *ar)
+{
+ ar5523_tx_work_locked(ar);
+
+ /* Don't waste time trying to flush if USB is disconnected */
+ if (test_bit(AR5523_USB_DISCONNECTED, &ar->flags))
+ return;
+ if (!wait_event_timeout(ar->tx_flush_waitq,
+ !atomic_read(&ar->tx_nr_pending), AR5523_FLUSH_TIMEOUT))
+ ar5523_err(ar, "flush timeout (tot %d pend %d)\n",
+ atomic_read(&ar->tx_nr_total),
+ atomic_read(&ar->tx_nr_pending));
+}
+
+static void ar5523_free_tx_cmd(struct ar5523 *ar)
+{
+ struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+
+ usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, cmd->buf_tx,
+ cmd->urb_tx->transfer_dma);
+ usb_free_urb(cmd->urb_tx);
+}
+
+static int ar5523_alloc_tx_cmd(struct ar5523 *ar)
+{
+ struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+
+ cmd->ar = ar;
+ init_completion(&cmd->done);
+
+ cmd->urb_tx = usb_alloc_urb(0, GFP_KERNEL);
+ if (!cmd->urb_tx) {
+ ar5523_err(ar, "could not allocate urb\n");
+ return -ENOMEM;
+ }
+ cmd->buf_tx = usb_alloc_coherent(ar->dev, AR5523_MAX_TXCMDSZ,
+ GFP_KERNEL,
+ &cmd->urb_tx->transfer_dma);
+ if (!cmd->buf_tx) {
+ usb_free_urb(cmd->urb_tx);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
+ * This function is called periodically (every second) when associated to
+ * query device statistics.
+ */
+static void ar5523_stat_work(struct work_struct *work)
+{
+ struct ar5523 *ar = container_of(work, struct ar5523, stat_work.work);
+ int error;
+
+ ar5523_dbg(ar, "%s\n", __func__);
+ mutex_lock(&ar->mutex);
+
+ /*
+ * Send request for statistics asynchronously once a second. This
+ * seems to be important. Throughput is a lot better if this is done.
+ */
+ error = ar5523_cmd_write(ar, WDCMSG_TARGET_GET_STATS, NULL, 0, 0);
+ if (error)
+ ar5523_err(ar, "could not query stats, error %d\n", error);
+ mutex_unlock(&ar->mutex);
+ ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, HZ);
+}
+
+/*
+ * Interface routines to the mac80211 stack.
+ */
+static int ar5523_start(struct ieee80211_hw *hw)
+{
+ struct ar5523 *ar = hw->priv;
+ int error;
+ __be32 val;
+
+ ar5523_dbg(ar, "start called\n");
+
+ mutex_lock(&ar->mutex);
+ val = cpu_to_be32(0);
+ ar5523_cmd_write(ar, WDCMSG_BIND, &val, sizeof(val), 0);
+
+ /* set MAC address */
+ ar5523_config_multi(ar, CFG_MAC_ADDR, &ar->hw->wiphy->perm_addr,
+ ETH_ALEN);
+
+ /* XXX honor net80211 state */
+ ar5523_config(ar, CFG_RATE_CONTROL_ENABLE, 0x00000001);
+ ar5523_config(ar, CFG_DIVERSITY_CTL, 0x00000001);
+ ar5523_config(ar, CFG_ABOLT, 0x0000003f);
+ ar5523_config(ar, CFG_WME_ENABLED, 0x00000000);
+
+ ar5523_config(ar, CFG_SERVICE_TYPE, 1);
+ ar5523_config(ar, CFG_TP_SCALE, 0x00000000);
+ ar5523_config(ar, CFG_TPC_HALF_DBM5, 0x0000003c);
+ ar5523_config(ar, CFG_TPC_HALF_DBM2, 0x0000003c);
+ ar5523_config(ar, CFG_OVERRD_TX_POWER, 0x00000000);
+ ar5523_config(ar, CFG_GMODE_PROTECTION, 0x00000000);
+ ar5523_config(ar, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
+ ar5523_config(ar, CFG_PROTECTION_TYPE, 0x00000000);
+ ar5523_config(ar, CFG_MODE_CTS, 0x00000002);
+
+ error = ar5523_cmd_read(ar, WDCMSG_TARGET_START, NULL, 0,
+ &val, sizeof(val), AR5523_CMD_FLAG_MAGIC);
+ if (error) {
+ ar5523_dbg(ar, "could not start target, error %d\n", error);
+ goto err;
+ }
+ ar5523_dbg(ar, "WDCMSG_TARGET_START returns handle: 0x%x\n",
+ be32_to_cpu(val));
+
+ ar5523_switch_chan(ar);
+
+ val = cpu_to_be32(TARGET_DEVICE_AWAKE);
+ ar5523_cmd_write(ar, WDCMSG_SET_PWR_MODE, &val, sizeof(val), 0);
+ /* XXX? check */
+ ar5523_cmd_write(ar, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
+
+ set_bit(AR5523_HW_UP, &ar->flags);
+ queue_work(ar->wq, &ar->rx_refill_work);
+
+ /* enable Rx */
+ ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT);
+ ar5523_set_rxfilter(ar,
+ UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+ UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
+ UATH_FILTER_OP_SET);
+
+ ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_ON);
+ ar5523_dbg(ar, "start OK\n");
+
+err:
+ mutex_unlock(&ar->mutex);
+ return error;
+}
+
+static void ar5523_stop(struct ieee80211_hw *hw)
+{
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "stop called\n");
+
+ cancel_delayed_work_sync(&ar->stat_work);
+ mutex_lock(&ar->mutex);
+ clear_bit(AR5523_HW_UP, &ar->flags);
+
+ ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF);
+ ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_OFF);
+
+ ar5523_cmd_write(ar, WDCMSG_TARGET_STOP, NULL, 0, 0);
+
+ del_timer_sync(&ar->tx_wd_timer);
+ cancel_work_sync(&ar->tx_wd_work);
+ cancel_work_sync(&ar->rx_refill_work);
+ ar5523_cancel_rx_bufs(ar);
+ mutex_unlock(&ar->mutex);
+}
+
+static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+ struct ar5523 *ar = hw->priv;
+ int ret;
+
+ ar5523_dbg(ar, "set_rts_threshold called\n");
+ mutex_lock(&ar->mutex);
+
+ ret = ar5523_config(ar, CFG_USER_RTS_THRESHOLD, value);
+
+ mutex_unlock(&ar->mutex);
+ return ret;
+}
+
+static void ar5523_flush(struct ieee80211_hw *hw, bool drop)
+{
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "flush called\n");
+ ar5523_flush_tx(ar);
+}
+
+static int ar5523_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "add interface called\n");
+
+ if (ar->vif) {
+ ar5523_dbg(ar, "invalid add_interface\n");
+ return -EOPNOTSUPP;
+ }
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ ar->vif = vif;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static void ar5523_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "remove interface called\n");
+ ar->vif = NULL;
+}
+
+static int ar5523_hwconfig(struct ieee80211_hw *hw, u32 changed)
+{
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "config called\n");
+ mutex_lock(&ar->mutex);
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ ar5523_dbg(ar, "Do channel switch\n");
+ ar5523_flush_tx(ar);
+ ar5523_switch_chan(ar);
+ }
+ mutex_unlock(&ar->mutex);
+ return 0;
+}
+
+static int ar5523_get_wlan_mode(struct ar5523 *ar,
+ struct ieee80211_bss_conf *bss_conf)
+{
+ struct ieee80211_supported_band *band;
+ int bit;
+ struct ieee80211_sta *sta;
+ u32 sta_rate_set;
+
+ band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
+ if (!sta) {
+ ar5523_info(ar, "STA not found!\n");
+ return WLAN_MODE_11b;
+ }
+ sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+
+ for (bit = 0; bit < band->n_bitrates; bit++) {
+ if (sta_rate_set & 1) {
+ int rate = band->bitrates[bit].bitrate;
+ switch (rate) {
+ case 60:
+ case 90:
+ case 120:
+ case 180:
+ case 240:
+ case 360:
+ case 480:
+ case 540:
+ return WLAN_MODE_11g;
+ }
+ }
+ sta_rate_set >>= 1;
+ }
+ return WLAN_MODE_11b;
+}
+
+static void ar5523_create_rateset(struct ar5523 *ar,
+ struct ieee80211_bss_conf *bss_conf,
+ struct ar5523_cmd_rateset *rs,
+ bool basic)
+{
+ struct ieee80211_supported_band *band;
+ struct ieee80211_sta *sta;
+ int bit, i = 0;
+ u32 sta_rate_set, basic_rate_set;
+
+ sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
+ basic_rate_set = bss_conf->basic_rates;
+ if (!sta) {
+ ar5523_info(ar, "STA not found. Cannot set rates\n");
+ sta_rate_set = bss_conf->basic_rates;
+ } else
+ sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+
+ ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
+
+ band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ for (bit = 0; bit < band->n_bitrates; bit++) {
+ BUG_ON(i >= AR5523_MAX_NRATES);
+ ar5523_dbg(ar, "Considering rate %d : %d\n",
+ band->bitrates[bit].hw_value, sta_rate_set & 1);
+ if (sta_rate_set & 1) {
+ rs->set[i] = band->bitrates[bit].hw_value;
+ if (basic_rate_set & 1 && basic)
+ rs->set[i] |= 0x80;
+ i++;
+ }
+ sta_rate_set >>= 1;
+ basic_rate_set >>= 1;
+ }
+
+ rs->length = i;
+}
+
+static int ar5523_set_basic_rates(struct ar5523 *ar,
+ struct ieee80211_bss_conf *bss)
+{
+ struct ar5523_cmd_rates rates;
+
+ memset(&rates, 0, sizeof(rates));
+ rates.connid = cpu_to_be32(2); /* XXX */
+ rates.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset));
+ ar5523_create_rateset(ar, bss, &rates.rateset, true);
+
+ return ar5523_cmd_write(ar, WDCMSG_SET_BASIC_RATE, &rates,
+ sizeof(rates), 0);
+}
+
+static int ar5523_create_connection(struct ar5523 *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss)
+{
+ struct ar5523_cmd_create_connection create;
+ int wlan_mode;
+
+ memset(&create, 0, sizeof(create));
+ create.connid = cpu_to_be32(2);
+ create.bssid = cpu_to_be32(0);
+ /* XXX packed or not? */
+ create.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset));
+
+ ar5523_create_rateset(ar, bss, &create.connattr.rateset, false);
+
+ wlan_mode = ar5523_get_wlan_mode(ar, bss);
+ create.connattr.wlanmode = cpu_to_be32(wlan_mode);
+
+ return ar5523_cmd_write(ar, WDCMSG_CREATE_CONNECTION, &create,
+ sizeof(create), 0);
+}
+
+static int ar5523_write_associd(struct ar5523 *ar,
+ struct ieee80211_bss_conf *bss)
+{
+ struct ar5523_cmd_set_associd associd;
+
+ memset(&associd, 0, sizeof(associd));
+ associd.defaultrateix = cpu_to_be32(0); /* XXX */
+ associd.associd = cpu_to_be32(bss->aid);
+ associd.timoffset = cpu_to_be32(0x3b); /* XXX */
+ memcpy(associd.bssid, bss->bssid, ETH_ALEN);
+ return ar5523_cmd_write(ar, WDCMSG_WRITE_ASSOCID, &associd,
+ sizeof(associd), 0);
+}
+
+static void ar5523_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss,
+ u32 changed)
+{
+ struct ar5523 *ar = hw->priv;
+ int error;
+
+ ar5523_dbg(ar, "bss_info_changed called\n");
+ mutex_lock(&ar->mutex);
+
+ if (!(changed & BSS_CHANGED_ASSOC))
+ goto out_unlock;
+
+ if (bss->assoc) {
+ error = ar5523_create_connection(ar, vif, bss);
+ if (error) {
+ ar5523_err(ar, "could not create connection\n");
+ goto out_unlock;
+ }
+
+ error = ar5523_set_basic_rates(ar, bss);
+ if (error) {
+ ar5523_err(ar, "could not set negotiated rate set\n");
+ goto out_unlock;
+ }
+
+ error = ar5523_write_associd(ar, bss);
+ if (error) {
+ ar5523_err(ar, "could not set association\n");
+ goto out_unlock;
+ }
+
+ /* turn link LED on */
+ ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_ON);
+ set_bit(AR5523_CONNECTED, &ar->flags);
+ ieee80211_queue_delayed_work(hw, &ar->stat_work, HZ);
+
+ } else {
+ cancel_delayed_work(&ar->stat_work);
+ clear_bit(AR5523_CONNECTED, &ar->flags);
+ ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF);
+ }
+
+out_unlock:
+ mutex_unlock(&ar->mutex);
+
+}
+
+#define AR5523_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+ FIF_ALLMULTI | \
+ FIF_FCSFAIL | \
+ FIF_OTHER_BSS)
+
+static void ar5523_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast)
+{
+ struct ar5523 *ar = hw->priv;
+ u32 filter = 0;
+
+ ar5523_dbg(ar, "configure_filter called\n");
+ mutex_lock(&ar->mutex);
+ ar5523_flush_tx(ar);
+
+ *total_flags &= AR5523_SUPPORTED_FILTERS;
+
+ /* The filters seems strange. UATH_FILTER_RX_BCAST and
+ * UATH_FILTER_RX_MCAST does not result in those frames being RXed.
+ * The only way I have found to get [mb]cast frames seems to be
+ * to set UATH_FILTER_RX_PROM. */
+ filter |= UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+ UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON |
+ UATH_FILTER_RX_PROM;
+
+ ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT);
+ ar5523_set_rxfilter(ar, filter, UATH_FILTER_OP_SET);
+
+ mutex_unlock(&ar->mutex);
+}
+
+static const struct ieee80211_ops ar5523_ops = {
+ .start = ar5523_start,
+ .stop = ar5523_stop,
+ .tx = ar5523_tx,
+ .set_rts_threshold = ar5523_set_rts_threshold,
+ .add_interface = ar5523_add_interface,
+ .remove_interface = ar5523_remove_interface,
+ .config = ar5523_hwconfig,
+ .bss_info_changed = ar5523_bss_info_changed,
+ .configure_filter = ar5523_configure_filter,
+ .flush = ar5523_flush,
+};
+
+static int ar5523_host_available(struct ar5523 *ar)
+{
+ struct ar5523_cmd_host_available setup;
+
+ /* inform target the host is available */
+ setup.sw_ver_major = cpu_to_be32(ATH_SW_VER_MAJOR);
+ setup.sw_ver_minor = cpu_to_be32(ATH_SW_VER_MINOR);
+ setup.sw_ver_patch = cpu_to_be32(ATH_SW_VER_PATCH);
+ setup.sw_ver_build = cpu_to_be32(ATH_SW_VER_BUILD);
+ return ar5523_cmd_read(ar, WDCMSG_HOST_AVAILABLE,
+ &setup, sizeof(setup), NULL, 0, 0);
+}
+
+static int ar5523_get_devstatus(struct ar5523 *ar)
+{
+ u8 macaddr[ETH_ALEN];
+ int error;
+
+ /* retrieve MAC address */
+ error = ar5523_get_status(ar, ST_MAC_ADDR, macaddr, ETH_ALEN);
+ if (error) {
+ ar5523_err(ar, "could not read MAC address\n");
+ return error;
+ }
+
+ SET_IEEE80211_PERM_ADDR(ar->hw, macaddr);
+
+ error = ar5523_get_status(ar, ST_SERIAL_NUMBER,
+ &ar->serial[0], sizeof(ar->serial));
+ if (error) {
+ ar5523_err(ar, "could not read device serial number\n");
+ return error;
+ }
+ return 0;
+}
+
+#define AR5523_SANE_RXBUFSZ 2000
+
+static int ar5523_get_max_rxsz(struct ar5523 *ar)
+{
+ int error;
+ __be32 rxsize;
+
+ /* Get max rx size */
+ error = ar5523_get_status(ar, ST_WDC_TRANSPORT_CHUNK_SIZE, &rxsize,
+ sizeof(rxsize));
+ if (error != 0) {
+ ar5523_err(ar, "could not read max RX size\n");
+ return error;
+ }
+
+ ar->rxbufsz = be32_to_cpu(rxsize);
+
+ if (!ar->rxbufsz || ar->rxbufsz > AR5523_SANE_RXBUFSZ) {
+ ar5523_err(ar, "Bad rxbufsz from device. Using %d instead\n",
+ AR5523_SANE_RXBUFSZ);
+ ar->rxbufsz = AR5523_SANE_RXBUFSZ;
+ }
+
+ ar5523_dbg(ar, "Max RX buf size: %d\n", ar->rxbufsz);
+ return 0;
+}
+
+/*
+ * This is copied from rtl818x, but we should probably move this
+ * to common code as in OpenBSD.
+ */
+static const struct ieee80211_rate ar5523_rates[] = {
+ { .bitrate = 10, .hw_value = 2, },
+ { .bitrate = 20, .hw_value = 4 },
+ { .bitrate = 55, .hw_value = 11, },
+ { .bitrate = 110, .hw_value = 22, },
+ { .bitrate = 60, .hw_value = 12, },
+ { .bitrate = 90, .hw_value = 18, },
+ { .bitrate = 120, .hw_value = 24, },
+ { .bitrate = 180, .hw_value = 36, },
+ { .bitrate = 240, .hw_value = 48, },
+ { .bitrate = 360, .hw_value = 72, },
+ { .bitrate = 480, .hw_value = 96, },
+ { .bitrate = 540, .hw_value = 108, },
+};
+
+static const struct ieee80211_channel ar5523_channels[] = {
+ { .center_freq = 2412 },
+ { .center_freq = 2417 },
+ { .center_freq = 2422 },
+ { .center_freq = 2427 },
+ { .center_freq = 2432 },
+ { .center_freq = 2437 },
+ { .center_freq = 2442 },
+ { .center_freq = 2447 },
+ { .center_freq = 2452 },
+ { .center_freq = 2457 },
+ { .center_freq = 2462 },
+ { .center_freq = 2467 },
+ { .center_freq = 2472 },
+ { .center_freq = 2484 },
+};
+
+static int ar5523_init_modes(struct ar5523 *ar)
+{
+ BUILD_BUG_ON(sizeof(ar->channels) != sizeof(ar5523_channels));
+ BUILD_BUG_ON(sizeof(ar->rates) != sizeof(ar5523_rates));
+
+ memcpy(ar->channels, ar5523_channels, sizeof(ar5523_channels));
+ memcpy(ar->rates, ar5523_rates, sizeof(ar5523_rates));
+
+ ar->band.band = IEEE80211_BAND_2GHZ;
+ ar->band.channels = ar->channels;
+ ar->band.n_channels = ARRAY_SIZE(ar5523_channels);
+ ar->band.bitrates = ar->rates;
+ ar->band.n_bitrates = ARRAY_SIZE(ar5523_rates);
+ ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar->band;
+ return 0;
+}
+
+/*
+ * Load the MIPS R4000 microcode into the device. Once the image is loaded,
+ * the device will detach itself from the bus and reattach later with a new
+ * product Id (a la ezusb).
+ */
+static int ar5523_load_firmware(struct usb_device *dev)
+{
+ struct ar5523_fwblock *txblock, *rxblock;
+ const struct firmware *fw;
+ void *fwbuf;
+ int len, offset;
+ int foolen; /* XXX(hch): handle short transfers */
+ int error = -ENXIO;
+
+ if (request_firmware(&fw, AR5523_FIRMWARE_FILE, &dev->dev)) {
+ dev_err(&dev->dev, "no firmware found: %s\n",
+ AR5523_FIRMWARE_FILE);
+ return -ENOENT;
+ }
+
+ txblock = kmalloc(sizeof(*txblock), GFP_KERNEL);
+ if (!txblock)
+ goto out;
+
+ rxblock = kmalloc(sizeof(*rxblock), GFP_KERNEL);
+ if (!rxblock)
+ goto out_free_txblock;
+
+ fwbuf = kmalloc(AR5523_MAX_FWBLOCK_SIZE, GFP_KERNEL);
+ if (!fwbuf)
+ goto out_free_rxblock;
+
+ memset(txblock, 0, sizeof(struct ar5523_fwblock));
+ txblock->flags = cpu_to_be32(AR5523_WRITE_BLOCK);
+ txblock->total = cpu_to_be32(fw->size);
+
+ offset = 0;
+ len = fw->size;
+ while (len > 0) {
+ int mlen = min(len, AR5523_MAX_FWBLOCK_SIZE);
+
+ txblock->remain = cpu_to_be32(len - mlen);
+ txblock->len = cpu_to_be32(mlen);
+
+ /* send firmware block meta-data */
+ error = usb_bulk_msg(dev, ar5523_cmd_tx_pipe(dev),
+ txblock, sizeof(*txblock), &foolen,
+ AR5523_CMD_TIMEOUT);
+ if (error) {
+ dev_err(&dev->dev,
+ "could not send firmware block info\n");
+ goto out_free_fwbuf;
+ }
+
+ /* send firmware block data */
+ memcpy(fwbuf, fw->data + offset, mlen);
+ error = usb_bulk_msg(dev, ar5523_data_tx_pipe(dev),
+ fwbuf, mlen, &foolen,
+ AR5523_DATA_TIMEOUT);
+ if (error) {
+ dev_err(&dev->dev,
+ "could not send firmware block data\n");
+ goto out_free_fwbuf;
+ }
+
+ /* wait for ack from firmware */
+ error = usb_bulk_msg(dev, ar5523_cmd_rx_pipe(dev),
+ rxblock, sizeof(*rxblock), &foolen,
+ AR5523_CMD_TIMEOUT);
+ if (error) {
+ dev_err(&dev->dev,
+ "could not read firmware answer\n");
+ goto out_free_fwbuf;
+ }
+
+ len -= mlen;
+ offset += mlen;
+ }
+
+ /*
+ * Set the error to -ENXIO to make sure we continue probing for
+ * a driver.
+ */
+ error = -ENXIO;
+
+ out_free_fwbuf:
+ kfree(fwbuf);
+ out_free_rxblock:
+ kfree(rxblock);
+ out_free_txblock:
+ kfree(txblock);
+ out:
+ release_firmware(fw);
+ return error;
+}
+
+static int ar5523_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct ieee80211_hw *hw;
+ struct ar5523 *ar;
+ int error = -ENOMEM;
+
+ /*
+ * Load firmware if the device requires it. This will return
+ * -ENXIO on success and we'll get called back afer the usb
+ * id changes to indicate that the firmware is present.
+ */
+ if (id->driver_info & AR5523_FLAG_PRE_FIRMWARE)
+ return ar5523_load_firmware(dev);
+
+
+ hw = ieee80211_alloc_hw(sizeof(*ar), &ar5523_ops);
+ if (!hw)
+ goto out;
+ SET_IEEE80211_DEV(hw, &intf->dev);
+
+ ar = hw->priv;
+ ar->hw = hw;
+ ar->dev = dev;
+ mutex_init(&ar->mutex);
+
+ INIT_DELAYED_WORK(&ar->stat_work, ar5523_stat_work);
+ init_timer(&ar->tx_wd_timer);
+ setup_timer(&ar->tx_wd_timer, ar5523_tx_wd_timer, (unsigned long) ar);
+ INIT_WORK(&ar->tx_wd_work, ar5523_tx_wd_work);
+ INIT_WORK(&ar->tx_work, ar5523_tx_work);
+ INIT_LIST_HEAD(&ar->tx_queue_pending);
+ INIT_LIST_HEAD(&ar->tx_queue_submitted);
+ spin_lock_init(&ar->tx_data_list_lock);
+ atomic_set(&ar->tx_nr_total, 0);
+ atomic_set(&ar->tx_nr_pending, 0);
+ init_waitqueue_head(&ar->tx_flush_waitq);
+
+ atomic_set(&ar->rx_data_free_cnt, 0);
+ INIT_WORK(&ar->rx_refill_work, ar5523_rx_refill_work);
+ INIT_LIST_HEAD(&ar->rx_data_free);
+ INIT_LIST_HEAD(&ar->rx_data_used);
+ spin_lock_init(&ar->rx_data_list_lock);
+
+ ar->wq = create_singlethread_workqueue("ar5523");
+ if (!ar->wq) {
+ ar5523_err(ar, "Could not create wq\n");
+ goto out_free_ar;
+ }
+
+ error = ar5523_alloc_rx_bufs(ar);
+ if (error) {
+ ar5523_err(ar, "Could not allocate rx buffers\n");
+ goto out_free_wq;
+ }
+
+ error = ar5523_alloc_rx_cmd(ar);
+ if (error) {
+ ar5523_err(ar, "Could not allocate rx command buffers\n");
+ goto out_free_rx_bufs;
+ }
+
+ error = ar5523_alloc_tx_cmd(ar);
+ if (error) {
+ ar5523_err(ar, "Could not allocate tx command buffers\n");
+ goto out_free_rx_cmd;
+ }
+
+ error = ar5523_submit_rx_cmd(ar);
+ if (error) {
+ ar5523_err(ar, "Failed to submit rx cmd\n");
+ goto out_free_tx_cmd;
+ }
+
+ /*
+ * We're now ready to send/receive firmware commands.
+ */
+ error = ar5523_host_available(ar);
+ if (error) {
+ ar5523_err(ar, "could not initialize adapter\n");
+ goto out_cancel_rx_cmd;
+ }
+
+ error = ar5523_get_max_rxsz(ar);
+ if (error) {
+ ar5523_err(ar, "could not get caps from adapter\n");
+ goto out_cancel_rx_cmd;
+ }
+
+ error = ar5523_get_devcap(ar);
+ if (error) {
+ ar5523_err(ar, "could not get caps from adapter\n");
+ goto out_cancel_rx_cmd;
+ }
+
+ error = ar5523_get_devstatus(ar);
+ if (error != 0) {
+ ar5523_err(ar, "could not get device status\n");
+ goto out_cancel_rx_cmd;
+ }
+
+ ar5523_info(ar, "MAC/BBP AR5523, RF AR%c112\n",
+ (id->driver_info & AR5523_FLAG_ABG) ? '5' : '2');
+
+ ar->vif = NULL;
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_HAS_RATE_CONTROL;
+ hw->extra_tx_headroom = sizeof(struct ar5523_tx_desc) +
+ sizeof(struct ar5523_chunk);
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ hw->queues = 1;
+
+ error = ar5523_init_modes(ar);
+ if (error)
+ goto out_cancel_rx_cmd;
+
+ usb_set_intfdata(intf, hw);
+
+ error = ieee80211_register_hw(hw);
+ if (error) {
+ ar5523_err(ar, "could not register device\n");
+ goto out_cancel_rx_cmd;
+ }
+
+ ar5523_info(ar, "Found and initialized AR5523 device\n");
+ return 0;
+
+out_cancel_rx_cmd:
+ ar5523_cancel_rx_cmd(ar);
+out_free_tx_cmd:
+ ar5523_free_tx_cmd(ar);
+out_free_rx_cmd:
+ ar5523_free_rx_cmd(ar);
+out_free_rx_bufs:
+ ar5523_free_rx_bufs(ar);
+out_free_wq:
+ destroy_workqueue(ar->wq);
+out_free_ar:
+ ieee80211_free_hw(hw);
+out:
+ return error;
+}
+
+static void ar5523_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct ar5523 *ar = hw->priv;
+
+ ar5523_dbg(ar, "detaching\n");
+ set_bit(AR5523_USB_DISCONNECTED, &ar->flags);
+
+ ieee80211_unregister_hw(hw);
+
+ ar5523_cancel_rx_cmd(ar);
+ ar5523_free_tx_cmd(ar);
+ ar5523_free_rx_cmd(ar);
+ ar5523_free_rx_bufs(ar);
+
+ destroy_workqueue(ar->wq);
+
+ ieee80211_free_hw(hw);
+ usb_set_intfdata(intf, NULL);
+}
+
+#define AR5523_DEVICE_UG(vendor, device) \
+ { USB_DEVICE((vendor), (device)) }, \
+ { USB_DEVICE((vendor), (device) + 1), \
+ .driver_info = AR5523_FLAG_PRE_FIRMWARE }
+#define AR5523_DEVICE_UX(vendor, device) \
+ { USB_DEVICE((vendor), (device)), \
+ .driver_info = AR5523_FLAG_ABG }, \
+ { USB_DEVICE((vendor), (device) + 1), \
+ .driver_info = AR5523_FLAG_ABG|AR5523_FLAG_PRE_FIRMWARE }
+
+static struct usb_device_id ar5523_id_table[] = {
+ AR5523_DEVICE_UG(0x168c, 0x0001), /* Atheros / AR5523 */
+ AR5523_DEVICE_UG(0x0cf3, 0x0001), /* Atheros2 / AR5523_1 */
+ AR5523_DEVICE_UG(0x0cf3, 0x0003), /* Atheros2 / AR5523_2 */
+ AR5523_DEVICE_UX(0x0cf3, 0x0005), /* Atheros2 / AR5523_3 */
+ AR5523_DEVICE_UG(0x0d8e, 0x7801), /* Conceptronic / AR5523_1 */
+ AR5523_DEVICE_UX(0x0d8e, 0x7811), /* Conceptronic / AR5523_2 */
+ AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */
+ AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */
+ AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */
+ AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */
+ AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */
+ AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108
+ (CyberTAN Technology) */
+ AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */
+ AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */
+ AR5523_DEVICE_UG(0x0d8e, 0x7802), /* Globalsun / AR5523_3 */
+ AR5523_DEVICE_UX(0x0846, 0x4300), /* Netgear / WG111U */
+ AR5523_DEVICE_UG(0x0846, 0x4250), /* Netgear / WG111T */
+ AR5523_DEVICE_UG(0x0846, 0x5f00), /* Netgear / WPN111 */
+ AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1 */
+ AR5523_DEVICE_UX(0x157e, 0x3205), /* Umedia / AR5523_2 */
+ AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / TEW444UBEU */
+ AR5523_DEVICE_UG(0x1435, 0x0826), /* Wistronneweb / AR5523_1 */
+ AR5523_DEVICE_UX(0x1435, 0x0828), /* Wistronneweb / AR5523_2 */
+ AR5523_DEVICE_UG(0x0cde, 0x0012), /* Zcom / AR5523 */
+ AR5523_DEVICE_UG(0x1385, 0x4250), /* Netgear3 / WG111T (2) */
+ AR5523_DEVICE_UG(0x1385, 0x5f00), /* Netgear / WPN111 */
+ AR5523_DEVICE_UG(0x1385, 0x5f02), /* Netgear / WPN111 */
+ { }
+};
+MODULE_DEVICE_TABLE(usb, ar5523_id_table);
+
+static struct usb_driver ar5523_driver = {
+ .name = "ar5523",
+ .id_table = ar5523_id_table,
+ .probe = ar5523_probe,
+ .disconnect = ar5523_disconnect,
+};
+
+module_usb_driver(ar5523_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_FIRMWARE(AR5523_FIRMWARE_FILE);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.h b/drivers/net/wireless/ath/ar5523/ar5523.h
new file mode 100644
index 000000000000..00c6fd346d48
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * 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.
+ */
+
+#define AR5523_FLAG_PRE_FIRMWARE (1 << 0)
+#define AR5523_FLAG_ABG (1 << 1)
+
+#define AR5523_FIRMWARE_FILE "ar5523.bin"
+
+#define AR5523_CMD_TX_PIPE 0x01
+#define AR5523_DATA_TX_PIPE 0x02
+#define AR5523_CMD_RX_PIPE 0x81
+#define AR5523_DATA_RX_PIPE 0x82
+
+#define ar5523_cmd_tx_pipe(dev) \
+ usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE)
+#define ar5523_data_tx_pipe(dev) \
+ usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE)
+#define ar5523_cmd_rx_pipe(dev) \
+ usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE)
+#define ar5523_data_rx_pipe(dev) \
+ usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE)
+
+#define AR5523_DATA_TIMEOUT 10000
+#define AR5523_CMD_TIMEOUT 1000
+
+#define AR5523_TX_DATA_COUNT 8
+#define AR5523_TX_DATA_RESTART_COUNT 2
+#define AR5523_RX_DATA_COUNT 16
+#define AR5523_RX_DATA_REFILL_COUNT 8
+
+#define AR5523_CMD_ID 1
+#define AR5523_DATA_ID 2
+
+#define AR5523_TX_WD_TIMEOUT (HZ * 2)
+#define AR5523_FLUSH_TIMEOUT (HZ * 3)
+
+enum AR5523_flags {
+ AR5523_HW_UP,
+ AR5523_USB_DISCONNECTED,
+ AR5523_CONNECTED
+};
+
+struct ar5523_tx_cmd {
+ struct ar5523 *ar;
+ struct urb *urb_tx;
+ void *buf_tx;
+ void *odata;
+ int olen;
+ int flags;
+ int res;
+ struct completion done;
+};
+
+/* This struct is placed in tx_info->driver_data. It must not be larger
+ * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE.
+ */
+struct ar5523_tx_data {
+ struct list_head list;
+ struct ar5523 *ar;
+ struct sk_buff *skb;
+ struct urb *urb;
+};
+
+struct ar5523_rx_data {
+ struct list_head list;
+ struct ar5523 *ar;
+ struct urb *urb;
+ struct sk_buff *skb;
+};
+
+struct ar5523 {
+ struct usb_device *dev;
+ struct ieee80211_hw *hw;
+
+ unsigned long flags;
+ struct mutex mutex;
+ struct workqueue_struct *wq;
+
+ struct ar5523_tx_cmd tx_cmd;
+
+ struct delayed_work stat_work;
+
+ struct timer_list tx_wd_timer;
+ struct work_struct tx_wd_work;
+ struct work_struct tx_work;
+ struct list_head tx_queue_pending;
+ struct list_head tx_queue_submitted;
+ spinlock_t tx_data_list_lock;
+ wait_queue_head_t tx_flush_waitq;
+
+ /* Queued + Submitted TX frames */
+ atomic_t tx_nr_total;
+
+ /* Submitted TX frames */
+ atomic_t tx_nr_pending;
+
+ void *rx_cmd_buf;
+ struct urb *rx_cmd_urb;
+
+ struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT];
+ spinlock_t rx_data_list_lock;
+ struct list_head rx_data_free;
+ struct list_head rx_data_used;
+ atomic_t rx_data_free_cnt;
+
+ struct work_struct rx_refill_work;
+
+ unsigned int rxbufsz;
+ u8 serial[16];
+
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_supported_band band;
+ struct ieee80211_vif *vif;
+};
+
+/* flags for sending firmware commands */
+#define AR5523_CMD_FLAG_READ (1 << 1)
+#define AR5523_CMD_FLAG_MAGIC (1 << 2)
+
+#define ar5523_dbg(ar, format, arg...) \
+ dev_dbg(&(ar)->dev->dev, format, ## arg)
+
+/* On USB hot-unplug there can be a lot of URBs in flight and they'll all
+ * fail. Instead of dealing with them in every possible place just surpress
+ * any messages on USB disconnect.
+ */
+#define ar5523_err(ar, format, arg...) \
+do { \
+ if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \
+ dev_err(&(ar)->dev->dev, format, ## arg); \
+ } \
+} while (0)
+#define ar5523_info(ar, format, arg...) \
+ dev_info(&(ar)->dev->dev, format, ## arg)
diff --git a/drivers/net/wireless/ath/ar5523/ar5523_hw.h b/drivers/net/wireless/ath/ar5523/ar5523_hw.h
new file mode 100644
index 000000000000..0fe2c803f48f
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523_hw.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * 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.
+ */
+
+/* all fields are big endian */
+struct ar5523_fwblock {
+ __be32 flags;
+#define AR5523_WRITE_BLOCK (1 << 4)
+
+ __be32 len;
+#define AR5523_MAX_FWBLOCK_SIZE 2048
+
+ __be32 total;
+ __be32 remain;
+ __be32 rxtotal;
+ __be32 pad[123];
+} __packed;
+
+#define AR5523_MAX_RXCMDSZ 1024
+#define AR5523_MAX_TXCMDSZ 1024
+
+struct ar5523_cmd_hdr {
+ __be32 len;
+ __be32 code;
+/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */
+/* messages from Host -> Target */
+#define WDCMSG_HOST_AVAILABLE 0x01
+#define WDCMSG_BIND 0x02
+#define WDCMSG_TARGET_RESET 0x03
+#define WDCMSG_TARGET_GET_CAPABILITY 0x04
+#define WDCMSG_TARGET_SET_CONFIG 0x05
+#define WDCMSG_TARGET_GET_STATUS 0x06
+#define WDCMSG_TARGET_GET_STATS 0x07
+#define WDCMSG_TARGET_START 0x08
+#define WDCMSG_TARGET_STOP 0x09
+#define WDCMSG_TARGET_ENABLE 0x0a
+#define WDCMSG_TARGET_DISABLE 0x0b
+#define WDCMSG_CREATE_CONNECTION 0x0c
+#define WDCMSG_UPDATE_CONNECT_ATTR 0x0d
+#define WDCMSG_DELETE_CONNECT 0x0e
+#define WDCMSG_SEND 0x0f
+#define WDCMSG_FLUSH 0x10
+/* messages from Target -> Host */
+#define WDCMSG_STATS_UPDATE 0x11
+#define WDCMSG_BMISS 0x12
+#define WDCMSG_DEVICE_AVAIL 0x13
+#define WDCMSG_SEND_COMPLETE 0x14
+#define WDCMSG_DATA_AVAIL 0x15
+#define WDCMSG_SET_PWR_MODE 0x16
+#define WDCMSG_BMISS_ACK 0x17
+#define WDCMSG_SET_LED_STEADY 0x18
+#define WDCMSG_SET_LED_BLINK 0x19
+/* more messages */
+#define WDCMSG_SETUP_BEACON_DESC 0x1a
+#define WDCMSG_BEACON_INIT 0x1b
+#define WDCMSG_RESET_KEY_CACHE 0x1c
+#define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d
+#define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e
+#define WDCMSG_SET_DECOMP_MASK 0x1f
+#define WDCMSG_SET_REGULATORY_DOMAIN 0x20
+#define WDCMSG_SET_LED_STATE 0x21
+#define WDCMSG_WRITE_ASSOCID 0x22
+#define WDCMSG_SET_STA_BEACON_TIMERS 0x23
+#define WDCMSG_GET_TSF 0x24
+#define WDCMSG_RESET_TSF 0x25
+#define WDCMSG_SET_ADHOC_MODE 0x26
+#define WDCMSG_SET_BASIC_RATE 0x27
+#define WDCMSG_MIB_CONTROL 0x28
+#define WDCMSG_GET_CHANNEL_DATA 0x29
+#define WDCMSG_GET_CUR_RSSI 0x2a
+#define WDCMSG_SET_ANTENNA_SWITCH 0x2b
+#define WDCMSG_USE_SHORT_SLOT_TIME 0x2f
+#define WDCMSG_SET_POWER_MODE 0x30
+#define WDCMSG_SETUP_PSPOLL_DESC 0x31
+#define WDCMSG_SET_RX_MULTICAST_FILTER 0x32
+#define WDCMSG_RX_FILTER 0x33
+#define WDCMSG_PER_CALIBRATION 0x34
+#define WDCMSG_RESET 0x35
+#define WDCMSG_DISABLE 0x36
+#define WDCMSG_PHY_DISABLE 0x37
+#define WDCMSG_SET_TX_POWER_LIMIT 0x38
+#define WDCMSG_SET_TX_QUEUE_PARAMS 0x39
+#define WDCMSG_SETUP_TX_QUEUE 0x3a
+#define WDCMSG_RELEASE_TX_QUEUE 0x3b
+#define WDCMSG_SET_DEFAULT_KEY 0x43
+
+ __u32 priv; /* driver private data,
+ don't care about endianess */
+ __be32 magic;
+ __be32 reserved2[4];
+};
+
+struct ar5523_cmd_host_available {
+ __be32 sw_ver_major;
+ __be32 sw_ver_minor;
+ __be32 sw_ver_patch;
+ __be32 sw_ver_build;
+} __packed;
+
+#define ATH_SW_VER_MAJOR 1
+#define ATH_SW_VER_MINOR 5
+#define ATH_SW_VER_PATCH 0
+#define ATH_SW_VER_BUILD 9999
+
+struct ar5523_chunk {
+ u8 seqnum; /* sequence number for ordering */
+ u8 flags;
+#define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */
+#define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */
+#define UATH_CFLAGS_DEBUG 0x04 /* for debugging */
+ __be16 length; /* chunk size in bytes */
+ /* chunk data follows */
+} __packed;
+
+/*
+ * Message format for a WDCMSG_DATA_AVAIL message from Target to Host.
+ */
+struct ar5523_rx_desc {
+ __be32 len; /* msg length including header */
+ __be32 code; /* WDCMSG_DATA_AVAIL */
+ __be32 gennum; /* generation number */
+ __be32 status; /* start of RECEIVE_INFO */
+#define UATH_STATUS_OK 0
+#define UATH_STATUS_STOP_IN_PROGRESS 1
+#define UATH_STATUS_CRC_ERR 2
+#define UATH_STATUS_PHY_ERR 3
+#define UATH_STATUS_DECRYPT_CRC_ERR 4
+#define UATH_STATUS_DECRYPT_MIC_ERR 5
+#define UATH_STATUS_DECOMP_ERR 6
+#define UATH_STATUS_KEY_ERR 7
+#define UATH_STATUS_ERR 8
+ __be32 tstamp_low; /* low-order 32-bits of rx timestamp */
+ __be32 tstamp_high; /* high-order 32-bits of rx timestamp */
+ __be32 framelen; /* frame length */
+ __be32 rate; /* rx rate code */
+ __be32 antenna;
+ __be32 rssi;
+ __be32 channel;
+ __be32 phyerror;
+ __be32 connix; /* key table ix for bss traffic */
+ __be32 decrypterror;
+ __be32 keycachemiss;
+ __be32 pad; /* XXX? */
+} __packed;
+
+struct ar5523_tx_desc {
+ __be32 msglen;
+ u32 msgid; /* msg id (supplied by host) */
+ __be32 type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */
+ __be32 txqid; /* tx queue id and flags */
+#define UATH_TXQID_MASK 0x0f
+#define UATH_TXQID_MINRATE 0x10 /* use min tx rate */
+#define UATH_TXQID_FF 0x20 /* content is fast frame */
+ __be32 connid; /* tx connection id */
+#define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */
+ __be32 flags; /* non-zero if response desired */
+#define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */
+ __be32 buflen; /* payload length */
+} __packed;
+
+
+#define AR5523_ID_BSS 2
+#define AR5523_ID_BROADCAST 0xffffffff
+
+/* structure for command UATH_CMD_WRITE_MAC */
+struct ar5523_write_mac {
+ __be32 reg;
+ __be32 len;
+ u8 data[32];
+} __packed;
+
+struct ar5523_cmd_rateset {
+ __u8 length;
+#define AR5523_MAX_NRATES 32
+ __u8 set[AR5523_MAX_NRATES];
+};
+
+struct ar5523_cmd_set_associd { /* AR5523_WRITE_ASSOCID */
+ __be32 defaultrateix;
+ __be32 associd;
+ __be32 timoffset;
+ __be32 turboprime;
+ __u8 bssid[6];
+} __packed;
+
+/* structure for command WDCMSG_RESET */
+struct ar5523_cmd_reset {
+ __be32 flags; /* channel flags */
+#define UATH_CHAN_TURBO 0x0100
+#define UATH_CHAN_CCK 0x0200
+#define UATH_CHAN_OFDM 0x0400
+#define UATH_CHAN_2GHZ 0x1000
+#define UATH_CHAN_5GHZ 0x2000
+ __be32 freq; /* channel frequency */
+ __be32 maxrdpower;
+ __be32 cfgctl;
+ __be32 twiceantennareduction;
+ __be32 channelchange;
+ __be32 keeprccontent;
+} __packed;
+
+/* structure for command WDCMSG_SET_BASIC_RATE */
+struct ar5523_cmd_rates {
+ __be32 connid;
+ __be32 keeprccontent;
+ __be32 size;
+ struct ar5523_cmd_rateset rateset;
+} __packed;
+
+enum {
+ WLAN_MODE_NONE = 0,
+ WLAN_MODE_11b,
+ WLAN_MODE_11a,
+ WLAN_MODE_11g,
+ WLAN_MODE_11a_TURBO,
+ WLAN_MODE_11g_TURBO,
+ WLAN_MODE_11a_TURBO_PRIME,
+ WLAN_MODE_11g_TURBO_PRIME,
+ WLAN_MODE_11a_XR,
+ WLAN_MODE_11g_XR,
+};
+
+struct ar5523_cmd_connection_attr {
+ __be32 longpreambleonly;
+ struct ar5523_cmd_rateset rateset;
+ __be32 wlanmode;
+} __packed;
+
+/* structure for command AR5523_CREATE_CONNECTION */
+struct ar5523_cmd_create_connection {
+ __be32 connid;
+ __be32 bssid;
+ __be32 size;
+ struct ar5523_cmd_connection_attr connattr;
+} __packed;
+
+struct ar5523_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */
+ __be32 lednum;
+#define UATH_LED_LINK 0
+#define UATH_LED_ACTIVITY 1
+ __be32 ledmode;
+#define UATH_LED_OFF 0
+#define UATH_LED_ON 1
+} __packed;
+
+struct ar5523_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */
+ __be32 lednum;
+ __be32 ledmode;
+ __be32 blinkrate;
+ __be32 slowmode;
+} __packed;
+
+struct ar5523_cmd_ledstate { /* WDCMSG_SET_LED_STATE */
+ __be32 connected;
+} __packed;
+
+struct ar5523_cmd_txq_attr {
+ __be32 priority;
+ __be32 aifs;
+ __be32 logcwmin;
+ __be32 logcwmax;
+ __be32 bursttime;
+ __be32 mode;
+ __be32 qflags;
+} __packed;
+
+struct ar5523_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */
+ __be32 qid;
+ __be32 len;
+ struct ar5523_cmd_txq_attr attr;
+} __packed;
+
+struct ar5523_cmd_rx_filter { /* WDCMSG_RX_FILTER */
+ __be32 bits;
+#define UATH_FILTER_RX_UCAST 0x00000001
+#define UATH_FILTER_RX_MCAST 0x00000002
+#define UATH_FILTER_RX_BCAST 0x00000004
+#define UATH_FILTER_RX_CONTROL 0x00000008
+#define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */
+#define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */
+#define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */
+#define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */
+#define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */
+#define UATH_FILTER_RX_PROBE_REQ 0x00000800
+ __be32 op;
+#define UATH_FILTER_OP_INIT 0x0
+#define UATH_FILTER_OP_SET 0x1
+#define UATH_FILTER_OP_CLEAR 0x2
+#define UATH_FILTER_OP_TEMP 0x3
+#define UATH_FILTER_OP_RESTORE 0x4
+} __packed;
+
+enum {
+ CFG_NONE, /* Sentinal to indicate "no config" */
+ CFG_REG_DOMAIN, /* Regulatory Domain */
+ CFG_RATE_CONTROL_ENABLE,
+ CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */
+ CFG_HW_TX_RETRIES,
+ CFG_SW_TX_RETRIES,
+ CFG_SLOW_CLOCK_ENABLE,
+ CFG_COMP_PROC,
+ CFG_USER_RTS_THRESHOLD,
+ CFG_XR2NORM_RATE_THRESHOLD,
+ CFG_XRMODE_SWITCH_COUNT,
+ CFG_PROTECTION_TYPE,
+ CFG_BURST_SEQ_THRESHOLD,
+ CFG_ABOLT,
+ CFG_IQ_LOG_COUNT_MAX,
+ CFG_MODE_CTS,
+ CFG_WME_ENABLED,
+ CFG_GPRS_CBR_PERIOD,
+ CFG_SERVICE_TYPE,
+ /* MAC Address to use. Overrides EEPROM */
+ CFG_MAC_ADDR,
+ CFG_DEBUG_EAR,
+ CFG_INIT_REGS,
+ /* An ID for use in error & debug messages */
+ CFG_DEBUG_ID,
+ CFG_COMP_WIN_SZ,
+ CFG_DIVERSITY_CTL,
+ CFG_TP_SCALE,
+ CFG_TPC_HALF_DBM5,
+ CFG_TPC_HALF_DBM2,
+ CFG_OVERRD_TX_POWER,
+ CFG_USE_32KHZ_CLOCK,
+ CFG_GMODE_PROTECTION,
+ CFG_GMODE_PROTECT_RATE_INDEX,
+ CFG_GMODE_NON_ERP_PREAMBLE,
+ CFG_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+ /* Sentinal to indicate "no capability" */
+ CAP_NONE,
+ CAP_ALL, /* ALL capabilities */
+ CAP_TARGET_VERSION,
+ CAP_TARGET_REVISION,
+ CAP_MAC_VERSION,
+ CAP_MAC_REVISION,
+ CAP_PHY_REVISION,
+ CAP_ANALOG_5GHz_REVISION,
+ CAP_ANALOG_2GHz_REVISION,
+ /* Target supports WDC message debug features */
+ CAP_DEBUG_WDCMSG_SUPPORT,
+
+ CAP_REG_DOMAIN,
+ CAP_COUNTRY_CODE,
+ CAP_REG_CAP_BITS,
+
+ CAP_WIRELESS_MODES,
+ CAP_CHAN_SPREAD_SUPPORT,
+ CAP_SLEEP_AFTER_BEACON_BROKEN,
+ CAP_COMPRESS_SUPPORT,
+ CAP_BURST_SUPPORT,
+ CAP_FAST_FRAMES_SUPPORT,
+ CAP_CHAP_TUNING_SUPPORT,
+ CAP_TURBOG_SUPPORT,
+ CAP_TURBO_PRIME_SUPPORT,
+ CAP_DEVICE_TYPE,
+ CAP_XR_SUPPORT,
+ CAP_WME_SUPPORT,
+ CAP_TOTAL_QUEUES,
+ CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */
+
+ CAP_LOW_5GHZ_CHAN,
+ CAP_HIGH_5GHZ_CHAN,
+ CAP_LOW_2GHZ_CHAN,
+ CAP_HIGH_2GHZ_CHAN,
+
+ CAP_MIC_AES_CCM,
+ CAP_MIC_CKIP,
+ CAP_MIC_TKIP,
+ CAP_MIC_TKIP_WME,
+ CAP_CIPHER_AES_CCM,
+ CAP_CIPHER_CKIP,
+ CAP_CIPHER_TKIP,
+
+ CAP_TWICE_ANTENNAGAIN_5G,
+ CAP_TWICE_ANTENNAGAIN_2G,
+};
+
+enum {
+ ST_NONE, /* Sentinal to indicate "no status" */
+ ST_ALL,
+ ST_SERVICE_TYPE,
+ ST_WLAN_MODE,
+ ST_FREQ,
+ ST_BAND,
+ ST_LAST_RSSI,
+ ST_PS_FRAMES_DROPPED,
+ ST_CACHED_DEF_ANT,
+ ST_COUNT_OTHER_RX_ANT,
+ ST_USE_FAST_DIVERSITY,
+ ST_MAC_ADDR,
+ ST_RX_GENERATION_NUM,
+ ST_TX_QUEUE_DEPTH,
+ ST_SERIAL_NUMBER,
+ ST_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+ TARGET_DEVICE_AWAKE,
+ TARGET_DEVICE_SLEEP,
+ TARGET_DEVICE_PWRDN,
+ TARGET_DEVICE_PWRSAVE,
+ TARGET_DEVICE_SUSPEND,
+ TARGET_DEVICE_RESUME,
+};
+
+/* this is in net/ieee80211.h, but that conflicts with the mac80211 headers */
+#define IEEE80211_2ADDR_LEN 16
+
+#define AR5523_MIN_RXBUFSZ \
+ (((sizeof(__be32) + IEEE80211_2ADDR_LEN + \
+ sizeof(struct ar5523_rx_desc)) + 3) & ~3)
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 338c5c42357d..c9f81a388f15 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,6 +1,7 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on (PCI || ATHEROS_AR231X) && MAC80211
+ select ATH_COMMON
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index aec33cc207fd..8e8bcc7a4805 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -236,17 +236,4 @@ static struct platform_driver ath_ahb_driver = {
},
};
-static int __init
-ath5k_ahb_init(void)
-{
- return platform_driver_register(&ath_ahb_driver);
-}
-
-static void __exit
-ath5k_ahb_exit(void)
-{
- platform_driver_unregister(&ath_ahb_driver);
-}
-
-module_init(ath5k_ahb_init);
-module_exit(ath5k_ahb_exit);
+module_platform_driver(ath_ahb_driver);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9f31cfa56cc0..30ca0a60a64c 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -511,8 +511,9 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
ath5k_vif_iter(&iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
- &iter_data);
+ ieee80211_iterate_active_interfaces_atomic(
+ ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath5k_vif_iter, &iter_data);
memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
ah->opmode = iter_data.opmode;
@@ -848,7 +849,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
return;
dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len,
DMA_TO_DEVICE);
- dev_kfree_skb_any(bf->skb);
+ ieee80211_free_txskb(ah->hw, bf->skb);
bf->skb = NULL;
bf->skbaddr = 0;
bf->desc->ds_data = 0;
@@ -1335,20 +1336,9 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
* 15bit only. that means TSF extension has to be done within
* 32768usec (about 32ms). it might be necessary to move this to
* the interrupt handler, like it is done in madwifi.
- *
- * Unfortunately we don't know when the hardware takes the rx
- * timestamp (beginning of phy frame, data frame, end of rx?).
- * The only thing we know is that it is hardware specific...
- * On AR5213 it seems the rx timestamp is at the end of the
- * frame, but I'm not sure.
- *
- * NOTE: mac80211 defines mactime at the beginning of the first
- * data symbol. Since we don't have any time references it's
- * impossible to comply to that. This affects IBSS merge only
- * right now, so it's not too bad...
*/
rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
- rxs->flag |= RX_FLAG_MACTIME_MPDU;
+ rxs->flag |= RX_FLAG_MACTIME_END;
rxs->freq = ah->curchan->center_freq;
rxs->band = ah->curchan->band;
@@ -1575,7 +1565,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
return;
drop_packet:
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
}
static void
@@ -2434,7 +2424,7 @@ static const struct ieee80211_iface_combination if_comb = {
.num_different_channels = 1,
};
-int __devinit
+int
ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = ah->hw;
@@ -2860,7 +2850,7 @@ static void ath5k_reset_work(struct work_struct *work)
mutex_unlock(&ah->lock);
}
-static int __devinit
+static int
ath5k_init(struct ieee80211_hw *hw)
{
@@ -3045,8 +3035,9 @@ ath5k_any_vif_assoc(struct ath5k_hw *ah)
iter_data.need_set_hw_addr = false;
iter_data.found_active = true;
- ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
- &iter_data);
+ ieee80211_iterate_active_interfaces_atomic(
+ ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath5k_vif_iter, &iter_data);
return iter_data.any_assoc;
}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index b9f708a45f4e..f77ef36acf87 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -158,7 +158,7 @@ void ath5k_unregister_leds(struct ath5k_hw *ah)
ath5k_unregister_led(&ah->tx_led);
}
-int __devinit ath5k_init_leds(struct ath5k_hw *ah)
+int ath5k_init_leds(struct ath5k_hw *ah)
{
int ret = 0;
struct ieee80211_hw *hw = ah->hw;
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 7a28538e6e05..4264341533ea 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -62,7 +62,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
u16 qnum = skb_get_queue_mapping(skb);
if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) {
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
return;
}
@@ -452,8 +452,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
iter_data.hw_macaddr = NULL;
iter_data.n_stas = 0;
iter_data.need_set_hw_addr = false;
- ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
- &iter_data);
+ ieee80211_iterate_active_interfaces_atomic(
+ ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath5k_vif_iter, &iter_data);
/* Set up RX Filter */
if (iter_data.n_stas > 1) {
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index dff48fbc63bf..859db7c34f87 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -155,7 +155,7 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
* PCI Initialization *
\********************/
-static int __devinit
+static int
ath5k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -285,7 +285,7 @@ err:
return ret;
}
-static void __devexit
+static void
ath5k_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
@@ -336,7 +336,7 @@ static struct pci_driver ath5k_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = ath5k_pci_id_table,
.probe = ath5k_pci_probe,
- .remove = __devexit_p(ath5k_pci_remove),
+ .remove = ath5k_pci_remove,
.driver.pm = ATH5K_PM_OPS,
};
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 0c2dd4771c36..4084b1076286 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -789,9 +789,9 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
* (I don't think it supports 44MHz) */
/* On 2425 initvals TURBO_SHORT is not present */
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
- turbo = AR5K_PHY_TURBO_MODE |
- (ah->ah_radio == AR5K_RF2425) ? 0 :
- AR5K_PHY_TURBO_SHORT;
+ turbo = AR5K_PHY_TURBO_MODE;
+ if (ah->ah_radio != AR5K_RF2425)
+ turbo |= AR5K_PHY_TURBO_SHORT;
} else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
if (ah->ah_radio == AR5K_RF5413) {
mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e7ed20..26c4b7220859 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
depends on ATH6KL
---help---
Enables debug support
+
+config ATH6KL_REGDOMAIN
+ bool "Atheros ath6kl regdomain support"
+ depends on ATH6KL
+ depends on CFG80211_CERTIFICATION_ONUS
+ ---help---
+ Enabling this makes it possible to change the regdomain in
+ the firmware. This can be only enabled if regulatory requirements
+ are taken into account.
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8cae8886f17d..cab0ec0d5380 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -34,6 +34,7 @@ ath6kl_core-y += main.o
ath6kl_core-y += txrx.o
ath6kl_core-y += wmi.o
ath6kl_core-y += core.o
+ath6kl_core-y += recovery.o
ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 7089f8160ad5..5516a8ccc3c6 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -147,15 +147,15 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
{
struct ath6kl *ar = vif->ar;
- if (ar->state != ATH6KL_STATE_SCHED_SCAN)
+ if (!test_and_clear_bit(SCHED_SCANNING, &vif->flags))
return false;
del_timer_sync(&vif->sched_scan_timer);
- ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
- ATH6KL_HOST_MODE_AWAKE);
+ if (ar->state == ATH6KL_STATE_RECOVERY)
+ return true;
- ar->state = ATH6KL_STATE_ON;
+ ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, false);
return true;
}
@@ -301,7 +301,7 @@ static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
static bool ath6kl_is_wpa_ie(const u8 *pos)
{
- return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
+ return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
pos[2] == 0x00 && pos[3] == 0x50 &&
pos[4] == 0xf2 && pos[5] == 0x01;
}
@@ -369,17 +369,13 @@ static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
{
switch (type) {
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
*nw_type = INFRA_NETWORK;
break;
case NL80211_IFTYPE_ADHOC:
*nw_type = ADHOC_NETWORK;
break;
case NL80211_IFTYPE_AP:
- *nw_type = AP_NETWORK;
- break;
- case NL80211_IFTYPE_P2P_CLIENT:
- *nw_type = INFRA_NETWORK;
- break;
case NL80211_IFTYPE_P2P_GO:
*nw_type = AP_NETWORK;
break;
@@ -1031,30 +1027,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
vif->scan_req = request;
- if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
- ar->fw_capabilities)) {
- /*
- * If capable of doing P2P mgmt operations using
- * station interface, send additional information like
- * supported rates to advertise and xmit rates for
- * probe requests
- */
- ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
- WMI_LONG_SCAN, force_fg_scan,
- false, 0,
- ATH6KL_FG_SCAN_INTERVAL,
- n_channels, channels,
- request->no_cck,
- request->rates);
- } else {
- ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
- WMI_LONG_SCAN, force_fg_scan,
- false, 0,
- ATH6KL_FG_SCAN_INTERVAL,
- n_channels, channels);
- }
+ ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
+ WMI_LONG_SCAN, force_fg_scan,
+ false, 0,
+ ATH6KL_FG_SCAN_INTERVAL,
+ n_channels, channels,
+ request->no_cck,
+ request->rates);
if (ret) {
- ath6kl_err("wmi_startscan_cmd failed\n");
+ ath6kl_err("failed to start scan: %d\n", ret);
vif->scan_req = NULL;
}
@@ -1093,15 +1074,18 @@ out:
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
enum wmi_phy_mode mode)
{
- enum nl80211_channel_type type;
+ struct cfg80211_chan_def chandef;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
"channel switch notify nw_type %d freq %d mode %d\n",
vif->nw_type, freq, mode);
- type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
+ cfg80211_chandef_create(&chandef,
+ ieee80211_get_channel(vif->ar->wiphy, freq),
+ (mode == WMI_11G_HT20) ?
+ NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
- cfg80211_ch_switch_notify(vif->ndev, freq, type);
+ cfg80211_ch_switch_notify(vif->ndev, &chandef);
}
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -1384,11 +1368,8 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return 0;
}
-/*
- * The type nl80211_tx_power_setting replaces the following
- * data type from 2.6.36 onwards
-*/
static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
enum nl80211_tx_power_setting type,
int mbm)
{
@@ -1423,7 +1404,9 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
return 0;
}
-static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
+static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ int *dbm)
{
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif;
@@ -1614,8 +1597,8 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
vif->ssid_len = ibss_param->ssid_len;
memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
- if (ibss_param->channel)
- vif->ch_hint = ibss_param->channel->center_freq;
+ if (ibss_param->chandef.chan)
+ vif->ch_hint = ibss_param->chandef.chan->center_freq;
if (ibss_param->channel_fixed) {
/*
@@ -1889,7 +1872,7 @@ static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
struct cfg80211_wowlan *wow, u32 *filter)
{
int ret, pos;
- u8 mask[WOW_MASK_SIZE];
+ u8 mask[WOW_PATTERN_SIZE];
u16 i;
/* Configure the patterns that we received from the user. */
@@ -2107,33 +2090,16 @@ static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
return ret;
}
-static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+static int ath6kl_wow_suspend_vif(struct ath6kl_vif *vif,
+ struct cfg80211_wowlan *wow, u32 *filter)
{
+ struct ath6kl *ar = vif->ar;
struct in_device *in_dev;
struct in_ifaddr *ifa;
- struct ath6kl_vif *vif;
int ret;
- u32 filter = 0;
u16 i, bmiss_time;
- u8 index = 0;
__be32 ips[MAX_IP_ADDRS];
-
- /* The FW currently can't support multi-vif WoW properly. */
- if (ar->num_vif > 1)
- return -EIO;
-
- vif = ath6kl_vif_first(ar);
- if (!vif)
- return -EIO;
-
- if (!ath6kl_cfg80211_ready(vif))
- return -EIO;
-
- if (!test_bit(CONNECTED, &vif->flags))
- return -ENOTCONN;
-
- if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
- return -EINVAL;
+ u8 index = 0;
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
@@ -2155,7 +2121,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
* the user.
*/
if (wow)
- ret = ath6kl_wow_usr(ar, vif, wow, &filter);
+ ret = ath6kl_wow_usr(ar, vif, wow, filter);
else if (vif->nw_type == AP_NETWORK)
ret = ath6kl_wow_ap(ar, vif);
else
@@ -2190,12 +2156,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return ret;
}
- ar->state = ATH6KL_STATE_SUSPENDING;
-
/* Setup own IP addr for ARP agent. */
in_dev = __in_dev_get_rtnl(vif->ndev);
if (!in_dev)
- goto skip_arp;
+ return 0;
ifa = in_dev->ifa_list;
memset(&ips, 0, sizeof(ips));
@@ -2218,41 +2182,61 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return ret;
}
-skip_arp:
- ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
+ return ret;
+}
+
+static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+{
+ struct ath6kl_vif *first_vif, *vif;
+ int ret = 0;
+ u32 filter = 0;
+ bool connected = false;
+
+ /* enter / leave wow suspend on first vif always */
+ first_vif = ath6kl_vif_first(ar);
+ if (WARN_ON(unlikely(!first_vif)) ||
+ !ath6kl_cfg80211_ready(first_vif))
+ return -EIO;
+
+ if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
+ return -EINVAL;
+
+ /* install filters for each connected vif */
+ spin_lock_bh(&ar->list_lock);
+ list_for_each_entry(vif, &ar->vif_list, list) {
+ if (!test_bit(CONNECTED, &vif->flags) ||
+ !ath6kl_cfg80211_ready(vif))
+ continue;
+ connected = true;
+
+ ret = ath6kl_wow_suspend_vif(vif, wow, &filter);
+ if (ret)
+ break;
+ }
+ spin_unlock_bh(&ar->list_lock);
+
+ if (!connected)
+ return -ENOTCONN;
+ else if (ret)
+ return ret;
+
+ ar->state = ATH6KL_STATE_SUSPENDING;
+
+ ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, first_vif->fw_vif_idx,
ATH6KL_WOW_MODE_ENABLE,
filter,
WOW_HOST_REQ_DELAY);
if (ret)
return ret;
- ret = ath6kl_cfg80211_host_sleep(ar, vif);
- if (ret)
- return ret;
-
- return 0;
+ return ath6kl_cfg80211_host_sleep(ar, first_vif);
}
-static int ath6kl_wow_resume(struct ath6kl *ar)
+static int ath6kl_wow_resume_vif(struct ath6kl_vif *vif)
{
- struct ath6kl_vif *vif;
+ struct ath6kl *ar = vif->ar;
int ret;
- vif = ath6kl_vif_first(ar);
- if (!vif)
- return -EIO;
-
- ar->state = ATH6KL_STATE_RESUMING;
-
- ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
- ATH6KL_HOST_MODE_AWAKE);
- if (ret) {
- ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
- ret);
- ar->state = ATH6KL_STATE_WOW;
- return ret;
- }
-
if (vif->nw_type != AP_NETWORK) {
ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
@@ -2270,13 +2254,11 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
return ret;
}
- ar->state = ATH6KL_STATE_ON;
-
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
- vif->fw_vif_idx, true);
+ vif->fw_vif_idx, true);
if (ret)
return ret;
}
@@ -2286,6 +2268,48 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
return 0;
}
+static int ath6kl_wow_resume(struct ath6kl *ar)
+{
+ struct ath6kl_vif *vif;
+ int ret;
+
+ vif = ath6kl_vif_first(ar);
+ if (WARN_ON(unlikely(!vif)) ||
+ !ath6kl_cfg80211_ready(vif))
+ return -EIO;
+
+ ar->state = ATH6KL_STATE_RESUMING;
+
+ ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+ ATH6KL_HOST_MODE_AWAKE);
+ if (ret) {
+ ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
+ ret);
+ goto cleanup;
+ }
+
+ spin_lock_bh(&ar->list_lock);
+ list_for_each_entry(vif, &ar->vif_list, list) {
+ if (!test_bit(CONNECTED, &vif->flags) ||
+ !ath6kl_cfg80211_ready(vif))
+ continue;
+ ret = ath6kl_wow_resume_vif(vif);
+ if (ret)
+ break;
+ }
+ spin_unlock_bh(&ar->list_lock);
+
+ if (ret)
+ goto cleanup;
+
+ ar->state = ATH6KL_STATE_ON;
+ return 0;
+
+cleanup:
+ ar->state = ATH6KL_STATE_WOW;
+ return ret;
+}
+
static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
{
struct ath6kl_vif *vif;
@@ -2422,13 +2446,6 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
break;
- case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
- /*
- * Nothing needed for schedule scan, firmware is already in
- * wow mode and sleeping most of the time.
- */
- break;
-
default:
break;
}
@@ -2476,9 +2493,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
}
break;
- case ATH6KL_STATE_SCHED_SCAN:
- break;
-
default:
break;
}
@@ -2495,14 +2509,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
{
struct ath6kl *ar = wiphy_priv(wiphy);
+ ath6kl_recovery_suspend(ar);
+
return ath6kl_hif_suspend(ar, wow);
}
static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
{
struct ath6kl *ar = wiphy_priv(wiphy);
+ int err;
- return ath6kl_hif_resume(ar);
+ err = ath6kl_hif_resume(ar);
+ if (err)
+ return err;
+
+ ath6kl_recovery_resume(ar);
+
+ return 0;
}
/*
@@ -2739,6 +2762,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
int res;
int i, ret;
u16 rsn_capab = 0;
+ int inactivity_timeout = 0;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
@@ -2857,7 +2881,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
p.ssid_len = vif->ssid_len;
memcpy(p.ssid, vif->ssid, vif->ssid_len);
p.dot11_auth_mode = vif->dot11_auth_mode;
- p.ch = cpu_to_le16(info->channel->center_freq);
+ p.ch = cpu_to_le16(info->chandef.chan->center_freq);
/* Enable uAPSD support by default */
res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
@@ -2875,14 +2899,22 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
if (info->inactivity_timeout) {
+
+ inactivity_timeout = info->inactivity_timeout;
+
+ if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
+ inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
+ 60);
+
res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx,
- info->inactivity_timeout);
+ inactivity_timeout);
if (res < 0)
return res;
}
- if (ath6kl_set_htcap(vif, info->channel->band,
- info->channel_type != NL80211_CHAN_NO_HT))
+ if (ath6kl_set_htcap(vif, info->chandef.chan->band,
+ cfg80211_get_chandef_type(&info->chandef)
+ != NL80211_CHAN_NO_HT))
return -EIO;
/*
@@ -2898,6 +2930,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
WLAN_EID_RSN, WMI_RSN_IE_CAPB,
(const u8 *) &rsn_capab,
sizeof(rsn_capab));
+ vif->rsn_capab = rsn_capab;
if (res < 0)
return res;
}
@@ -2977,7 +3010,6 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
static int ath6kl_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie)
{
@@ -3136,10 +3168,8 @@ 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,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie)
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie)
{
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
@@ -3211,7 +3241,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
u16 interval;
- int ret;
+ int ret, rssi_thold;
if (ar->state != ATH6KL_STATE_ON)
return -EIO;
@@ -3219,10 +3249,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
if (vif->sme_state != SME_DISCONNECTED)
return -EBUSY;
- /* The FW currently can't support multi-vif WoW properly. */
- if (ar->num_vif > 1)
- return -EIO;
-
ath6kl_cfg80211_scan_complete_event(vif, true);
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
@@ -3244,6 +3270,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
return ret;
}
+ if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+ ar->fw_capabilities)) {
+ if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
+ rssi_thold = 0;
+ else if (request->rssi_thold < -127)
+ rssi_thold = -127;
+ else
+ rssi_thold = request->rssi_thold;
+
+ ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
+ rssi_thold);
+ if (ret) {
+ ath6kl_err("failed to set RSSI threshold for scan\n");
+ return ret;
+ }
+ }
+
/* fw uses seconds, also make sure that it's >0 */
interval = max_t(u16, 1, request->interval / 1000);
@@ -3251,15 +3294,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
interval, interval,
vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
- ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
- ATH6KL_WOW_MODE_ENABLE,
- WOW_FILTER_SSID,
- WOW_HOST_REQ_DELAY);
- if (ret) {
- ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
- return ret;
- }
-
/* this also clears IE in fw if it's not set */
ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
WMI_FRAME_PROBE_REQ,
@@ -3270,17 +3304,13 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
return ret;
}
- ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
- ATH6KL_HOST_MODE_ASLEEP);
- if (ret) {
- ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
- ret);
+ ret = ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, true);
+ if (ret)
return ret;
- }
- ar->state = ATH6KL_STATE_SCHED_SCAN;
+ set_bit(SCHED_SCANNING, &vif->flags);
- return ret;
+ return 0;
}
static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
@@ -3309,6 +3339,27 @@ static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
mask);
}
+static int ath6kl_cfg80211_set_txe_config(struct wiphy *wiphy,
+ struct net_device *dev,
+ u32 rate, u32 pkts, u32 intvl)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct ath6kl_vif *vif = netdev_priv(dev);
+
+ if (vif->nw_type != INFRA_NETWORK ||
+ !test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, ar->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ if (vif->sme_state != SME_CONNECTED)
+ return -ENOTCONN;
+
+ /* save this since the firmware won't report the interval */
+ vif->txe_intvl = intvl;
+
+ return ath6kl_wmi_set_txe_notify(ar->wmi, vif->fw_vif_idx,
+ rate, pkts, intvl);
+}
+
static const struct ieee80211_txrx_stypes
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
@@ -3375,6 +3426,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.sched_scan_start = ath6kl_cfg80211_sscan_start,
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
+ .set_cqm_txe_config = ath6kl_cfg80211_set_txe_config,
};
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3395,16 +3447,22 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
break;
}
- if (test_bit(CONNECTED, &vif->flags) ||
- test_bit(CONNECT_PEND, &vif->flags))
+ if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
+ (test_bit(CONNECTED, &vif->flags) ||
+ test_bit(CONNECT_PEND, &vif->flags)))
ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
vif->sme_state = SME_DISCONNECTED;
clear_bit(CONNECTED, &vif->flags);
clear_bit(CONNECT_PEND, &vif->flags);
+ /* Stop netdev queues, needed during recovery */
+ netif_stop_queue(vif->ndev);
+ netif_carrier_off(vif->ndev);
+
/* disable scanning */
- if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
+ if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
+ ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
ath6kl_warn("failed to disable scan during stop\n");
@@ -3416,7 +3474,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
struct ath6kl_vif *vif;
vif = ath6kl_vif_first(ar);
- if (!vif) {
+ if (!vif && ar->state != ATH6KL_STATE_RECOVERY) {
/* save the current power mode before enabling power save */
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
@@ -3434,6 +3492,56 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
ath6kl_cfg80211_stop(vif);
}
+static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ath6kl *ar = wiphy_priv(wiphy);
+ u32 rates[IEEE80211_NUM_BANDS];
+ int ret, i;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "cfg reg_notify %c%c%s%s initiator %d hint_type %d\n",
+ request->alpha2[0], request->alpha2[1],
+ request->intersect ? " intersect" : "",
+ request->processed ? " processed" : "",
+ request->initiator, request->user_reg_hint_type);
+
+ /*
+ * As firmware is not able intersect regdoms, we can only listen to
+ * cellular hints.
+ */
+ if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE)
+ return -EOPNOTSUPP;
+
+ ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
+ if (ret) {
+ ath6kl_err("failed to set regdomain: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Firmware will apply the regdomain change only after a scan is
+ * issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
+ * changed.
+ */
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ if (wiphy->bands[i])
+ rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
+
+
+ ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
+ false, 0, ATH6KL_FG_SCAN_INTERVAL,
+ 0, NULL, false, rates);
+ if (ret) {
+ ath6kl_err("failed to start scan for a regdomain change: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
{
vif->aggr_cntxt = aggr_init(vif);
@@ -3506,9 +3614,13 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
- if (fw_vif_idx != 0)
+ if (fw_vif_idx != 0) {
ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
0x2;
+ if (test_bit(ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
+ ar->fw_capabilities))
+ ndev->dev_addr[4] ^= 0x80;
+ }
init_netdev(ndev);
@@ -3562,6 +3674,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
BIT(NL80211_IFTYPE_P2P_CLIENT);
}
+ if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
+ test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities)) {
+ wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
+ ar->wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
+ }
+
/* max num of ssids that can be probed during scanning */
wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
@@ -3607,7 +3725,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.ht_supported = false;
}
- if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
+ if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
@@ -3646,12 +3764,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
- if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
+ if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, ar->fw_capabilities))
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
ar->fw_capabilities))
- ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER;
+ ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
ar->wiphy->probe_resp_offload =
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 780f77775a91..e5e70f3a8ca8 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -22,7 +22,6 @@ enum ath6kl_cfg_suspend_mode {
ATH6KL_CFG_SUSPEND_DEEPSLEEP,
ATH6KL_CFG_SUSPEND_CUTPOWER,
ATH6KL_CFG_SUSPEND_WOW,
- ATH6KL_CFG_SUSPEND_SCHED_SCAN,
};
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 82c4dd2a960e..4b46adbe8c92 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -33,6 +33,8 @@ static unsigned int wow_mode;
static unsigned int uart_debug;
static unsigned int ath6kl_p2p;
static unsigned int testmode;
+static unsigned int recovery_enable;
+static unsigned int heart_beat_poll;
module_param(debug_mask, uint, 0644);
module_param(suspend_mode, uint, 0644);
@@ -40,6 +42,12 @@ module_param(wow_mode, uint, 0644);
module_param(uart_debug, uint, 0644);
module_param(ath6kl_p2p, uint, 0644);
module_param(testmode, uint, 0644);
+module_param(recovery_enable, uint, 0644);
+module_param(heart_beat_poll, uint, 0644);
+MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error");
+MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic" \
+ "polling. This also specifies the polling interval in" \
+ "msecs. Set reocvery_enable for this to be effective");
void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
{
@@ -202,6 +210,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, wdev->netdev->name, wdev->netdev, ar);
+ ar->fw_recovery.enable = !!recovery_enable;
+ if (!ar->fw_recovery.enable)
+ return ret;
+
+ if (heart_beat_poll &&
+ test_bit(ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+ ar->fw_capabilities))
+ ar->fw_recovery.hb_poll = heart_beat_poll;
+
+ ath6kl_recovery_init(ar);
+
return ret;
err_rxbuf_cleanup:
@@ -291,6 +310,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
{
ath6kl_hif_power_off(ar);
+ ath6kl_recovery_cleanup(ar);
+
destroy_workqueue(ar->ath6kl_wq);
if (ar->htc_target)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index cec49a31029a..189d8faf8c87 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -115,6 +115,27 @@ enum ath6kl_fw_capability {
*/
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
+ /* Firmware supports filtering BSS results by RSSI */
+ ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+
+ /* FW sets mac_addr[4] ^= 0x80 for newly created interfaces */
+ ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
+
+ /* Firmware supports TX error rate notification */
+ ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
+
+ /* supports WMI_SET_REGDOMAIN_CMDID command */
+ ATH6KL_FW_CAPABILITY_REGDOMAIN,
+
+ /* Firmware supports sched scan decoupled from host sleep */
+ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2,
+
+ /*
+ * Firmware capability for hang detection through heart beat
+ * challenge messages.
+ */
+ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@@ -128,11 +149,15 @@ struct ath6kl_fw_ie {
};
enum ath6kl_hw_flags {
- ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
+ ATH6KL_HW_64BIT_RATES = BIT(0),
+ ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
+ ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
+ ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
+#define ATH6KL_FW_API4_FILE "fw-4.bin"
/* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba
@@ -186,6 +211,13 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
AR6004_HW_1_2_FW_DIR "/bdata.bin"
+/* AR6004 1.3 definitions */
+#define AR6004_HW_1_3_VERSION 0x31c8088a
+#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
+#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
+#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
+#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
+
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)
#define STA_PS_SLEEP BIT(1)
@@ -536,6 +568,7 @@ enum ath6kl_vif_state {
HOST_SLEEP_MODE_CMD_PROCESSED,
NETDEV_MCAST_ALL_ON,
NETDEV_MCAST_ALL_OFF,
+ SCHED_SCANNING,
};
struct ath6kl_vif {
@@ -580,11 +613,13 @@ struct ath6kl_vif {
u16 assoc_bss_beacon_int;
u16 listen_intvl_t;
u16 bmiss_time_t;
+ u32 txe_intvl;
u16 bg_scan_period;
u8 assoc_bss_dtim_period;
struct net_device_stats net_stats;
struct target_stats target_stats;
struct wmi_connect_cmd profile;
+ u16 rsn_capab;
struct list_head mc_filter;
};
@@ -609,6 +644,7 @@ enum ath6kl_dev_state {
SKIP_SCAN,
ROAM_TBL_PEND,
FIRST_BOOT,
+ RECOVERY_CLEANUP,
};
enum ath6kl_state {
@@ -619,7 +655,16 @@ enum ath6kl_state {
ATH6KL_STATE_DEEPSLEEP,
ATH6KL_STATE_CUTPOWER,
ATH6KL_STATE_WOW,
- ATH6KL_STATE_SCHED_SCAN,
+ ATH6KL_STATE_RECOVERY,
+};
+
+/* Fw error recovery */
+#define ATH6KL_HB_RESP_MISS_THRES 5
+
+enum ath6kl_fw_err {
+ ATH6KL_FW_ASSERT,
+ ATH6KL_FW_HB_RESP_FAILURE,
+ ATH6KL_FW_EP_FULL,
};
struct ath6kl {
@@ -679,6 +724,7 @@ struct ath6kl {
struct ath6kl_req_key ap_mode_bkey;
struct sk_buff_head mcastpsq;
u32 want_ch_switch;
+ u16 last_ch;
/*
* FIXME: protects access to mcastpsq but is actually useless as
@@ -764,6 +810,17 @@ struct ath6kl {
bool wiphy_registered;
+ struct ath6kl_fw_recovery {
+ struct work_struct recovery_work;
+ unsigned long err_reason;
+ unsigned long hb_poll;
+ struct timer_list hb_timer;
+ u32 seq_num;
+ bool hb_pending;
+ u8 hb_misscnt;
+ bool enable;
+ } fw_recovery;
+
#ifdef CONFIG_ATH6KL_DEBUG
struct {
struct sk_buff_head fwlog_queue;
@@ -899,4 +956,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
void ath6kl_core_cleanup(struct ath6kl *ar);
void ath6kl_core_destroy(struct ath6kl *ar);
+/* Fw error recovery */
+void ath6kl_init_hw_restart(struct ath6kl *ar);
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie);
+void ath6kl_recovery_init(struct ath6kl *ar);
+void ath6kl_recovery_cleanup(struct ath6kl *ar);
+void ath6kl_recovery_suspend(struct ath6kl *ar);
+void ath6kl_recovery_resume(struct ath6kl *ar);
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 49639d8266c2..f97cd4ead543 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_SUSPEND = BIT(20),
ATH6KL_DBG_USB = BIT(21),
ATH6KL_DBG_USB_BULK = BIT(22),
+ ATH6KL_DBG_RECOVERY = BIT(23),
ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
};
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index 68ed6c2665b7..a6b614421fa4 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
ath6kl_hif_dump_fw_crash(dev->ar);
ath6kl_read_fwlogs(dev->ar);
+ ath6kl_recovery_err_notify(dev->ar, ATH6KL_FW_ASSERT);
return ret;
}
@@ -338,8 +339,7 @@ static int ath6kl_hif_proc_err_intr(struct ath6kl_device *dev)
status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS,
reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
- if (status)
- WARN_ON(1);
+ WARN_ON(status);
return status;
}
@@ -383,8 +383,7 @@ static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS,
reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
- if (status)
- WARN_ON(1);
+ WARN_ON(status);
return status;
}
@@ -695,11 +694,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
- /* usb doesn't support enabling interrupts */
- /* FIXME: remove check once USB support is implemented */
- if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB)
- return 0;
-
status = ath6kl_hif_disable_intrs(dev);
fail_setup:
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index cd0e1ba410d6..fbb78dfe078f 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -2492,7 +2492,8 @@ static int ath6kl_htc_mbox_conn_service(struct htc_target *target,
max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
}
- if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) {
+ if (WARN_ON_ONCE(assigned_ep == ENDPOINT_UNUSED ||
+ assigned_ep >= ENDPOINT_MAX || !max_msg_sz)) {
status = -ENOMEM;
goto fail_tx;
}
@@ -2655,12 +2656,6 @@ static int ath6kl_htc_mbox_wait_target(struct htc_target *target)
struct htc_service_connect_resp resp;
int status;
- /* FIXME: remove once USB support is implemented */
- if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) {
- ath6kl_err("HTC doesn't support USB yet. Patience!\n");
- return -EOPNOTSUPP;
- }
-
/* we should be getting 1 control message that the target is ready */
packet = htc_wait_for_ctrl_msg(target);
@@ -2890,9 +2885,7 @@ static void ath6kl_htc_mbox_cleanup(struct htc_target *target)
{
struct htc_packet *packet, *tmp_packet;
- /* FIXME: remove check once USB support is implemented */
- if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB)
- ath6kl_hif_cleanup_scatter(target->dev->ar);
+ ath6kl_hif_cleanup_scatter(target->dev->ar);
list_for_each_entry_safe(packet, tmp_packet,
&target->free_ctrl_txbuf, list) {
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index f9626c723693..ba6bd497b787 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -374,9 +374,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
packet = list_first_entry(txq,
struct htc_packet,
list);
- list_del(&packet->list);
- /* insert into local queue */
- list_add_tail(&packet->list, &send_queue);
+ /* move to local queue */
+ list_move_tail(&packet->list, &send_queue);
}
/*
@@ -399,11 +398,10 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
* for cleanup */
} else {
/* callback wants to keep this packet,
- * remove from caller's queue */
- list_del(&packet->list);
- /* put it in the send queue */
- list_add_tail(&packet->list,
- &send_queue);
+ * move from caller's queue to the send
+ * queue */
+ list_move_tail(&packet->list,
+ &send_queue);
}
}
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index f90b5db741cf..f21fa322e5ca 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -42,7 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.reserved_ram_size = 6912,
.refclk_hz = 26000000,
.uarttx_pin = 8,
- .flags = 0,
+ .flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
/* hw2.0 needs override address hardcoded */
.app_start_override_addr = 0x944C00,
@@ -68,7 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.refclk_hz = 26000000,
.uarttx_pin = 8,
.testscript_addr = 0x57ef74,
- .flags = 0,
+ .flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
.fw = {
.dir = AR6003_HW_2_1_1_FW_DIR,
@@ -93,7 +93,8 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900,
.refclk_hz = 26000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_FLAG_64BIT_RATES,
+ .flags = ATH6KL_HW_64BIT_RATES |
+ ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = {
.dir = AR6004_HW_1_0_FW_DIR,
@@ -113,8 +114,8 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400,
.refclk_hz = 40000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_FLAG_64BIT_RATES,
-
+ .flags = ATH6KL_HW_64BIT_RATES |
+ ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = {
.dir = AR6004_HW_1_1_FW_DIR,
.fw = AR6004_HW_1_1_FIRMWARE_FILE,
@@ -133,7 +134,8 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00,
.refclk_hz = 40000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_FLAG_64BIT_RATES,
+ .flags = ATH6KL_HW_64BIT_RATES |
+ ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = {
.dir = AR6004_HW_1_2_FW_DIR,
@@ -142,6 +144,28 @@ static const struct ath6kl_hw hw_list[] = {
.fw_board = AR6004_HW_1_2_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
},
+ {
+ .id = AR6004_HW_1_3_VERSION,
+ .name = "ar6004 hw 1.3",
+ .dataset_patch_addr = 0x437860,
+ .app_load_addr = 0x1234,
+ .board_ext_data_addr = 0x437000,
+ .reserved_ram_size = 7168,
+ .board_addr = 0x436400,
+ .refclk_hz = 40000000,
+ .uarttx_pin = 11,
+ .flags = ATH6KL_HW_64BIT_RATES |
+ ATH6KL_HW_AP_INACTIVITY_MINS |
+ ATH6KL_HW_MAP_LP_ENDPOINT,
+
+ .fw = {
+ .dir = AR6004_HW_1_3_FW_DIR,
+ .fw = AR6004_HW_1_3_FIRMWARE_FILE,
+ },
+
+ .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
+ .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
+ },
};
/*
@@ -337,7 +361,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
return -EIO;
- /* connect to Video service, map this to to HI PRI */
+ /* connect to Video service, map this to HI PRI */
connect.svc_id = WMI_DATA_VI_SVC;
if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
return -EIO;
@@ -1088,6 +1112,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if (ret)
return ret;
+ ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
+ if (ret == 0) {
+ ar->fw_api = 4;
+ goto out;
+ }
+
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE);
if (ret == 0) {
ar->fw_api = 3;
@@ -1401,8 +1431,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
return status;
/* WAR to avoid SDIO CRC err */
- if (ar->version.target_ver == AR6003_HW_2_0_VERSION ||
- ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
+ if (ar->hw.flags & ATH6KL_HW_SDIO_CRC_ERROR_WAR) {
ath6kl_err("temporary war to avoid sdio crc error\n");
param = 0x28;
@@ -1520,7 +1549,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
return NULL;
}
-int ath6kl_init_hw_start(struct ath6kl *ar)
+static int __ath6kl_init_hw_start(struct ath6kl *ar)
{
long timeleft;
int ret, i;
@@ -1616,8 +1645,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
goto err_htc_stop;
}
- ar->state = ATH6KL_STATE_ON;
-
return 0;
err_htc_stop:
@@ -1630,7 +1657,18 @@ err_power_off:
return ret;
}
-int ath6kl_init_hw_stop(struct ath6kl *ar)
+int ath6kl_init_hw_start(struct ath6kl *ar)
+{
+ int err;
+
+ err = __ath6kl_init_hw_start(ar);
+ if (err)
+ return err;
+ ar->state = ATH6KL_STATE_ON;
+ return 0;
+}
+
+static int __ath6kl_init_hw_stop(struct ath6kl *ar)
{
int ret;
@@ -1646,11 +1684,37 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
if (ret)
ath6kl_warn("failed to power off hif: %d\n", ret);
- ar->state = ATH6KL_STATE_OFF;
+ return 0;
+}
+int ath6kl_init_hw_stop(struct ath6kl *ar)
+{
+ int err;
+
+ err = __ath6kl_init_hw_stop(ar);
+ if (err)
+ return err;
+ ar->state = ATH6KL_STATE_OFF;
return 0;
}
+void ath6kl_init_hw_restart(struct ath6kl *ar)
+{
+ clear_bit(WMI_READY, &ar->flag);
+
+ ath6kl_cfg80211_stop_all(ar);
+
+ if (__ath6kl_init_hw_stop(ar)) {
+ ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to stop during fw error recovery\n");
+ return;
+ }
+
+ if (__ath6kl_init_hw_start(ar)) {
+ ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
+ return;
+ }
+}
+
/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
{
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index c189e28e86a9..bd50b6b7b492 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -293,13 +293,17 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
}
address = TARG_VTOP(ar->target_type, debug_hdr_addr);
- ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
+ ret = ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
+ if (ret)
+ goto out;
address = TARG_VTOP(ar->target_type,
le32_to_cpu(debug_hdr.dbuf_addr));
firstbuf = address;
dropped = le32_to_cpu(debug_hdr.dropped);
- ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+ ret = ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+ if (ret)
+ goto out;
loop = 100;
@@ -322,7 +326,8 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
address = TARG_VTOP(ar->target_type,
le32_to_cpu(debug_buf.next));
- ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+ ret = ath6kl_diag_read(ar, address, &debug_buf,
+ sizeof(debug_buf));
if (ret)
goto out;
@@ -436,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
break;
}
- if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
- ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+ if (ar->last_ch != channel)
/* we actually don't know the phymode, default to HT20 */
- ath6kl_cfg80211_ch_switch_notify(vif, channel,
- WMI_11G_HT20);
- }
+ ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20);
ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
set_bit(CONNECTED, &vif->flags);
@@ -606,6 +608,18 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
switch (vif->nw_type) {
case AP_NETWORK:
+ /*
+ * reconfigure any saved RSN IE capabilites in the beacon /
+ * probe response to stay in sync with the supplicant.
+ */
+ if (vif->rsn_capab &&
+ test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
+ ar->fw_capabilities))
+ ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
+ WLAN_EID_RSN, WMI_RSN_IE_CAPB,
+ (const u8 *) &vif->rsn_capab,
+ sizeof(vif->rsn_capab));
+
return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
&vif->profile);
default:
@@ -628,6 +642,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
res = ath6kl_commit_ch_switch(vif, channel);
+ /* if channel switch failed, oh well we tried */
+ ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+
if (res)
ath6kl_err("channel switch failed nw_type %d res %d\n",
vif->nw_type, res);
@@ -981,8 +998,25 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
if (vif->nw_type == AP_NETWORK) {
/* disconnect due to other STA vif switching channels */
if (reason == BSS_DISCONNECTED &&
- prot_reason_status == WMI_AP_REASON_STA_ROAM)
+ prot_reason_status == WMI_AP_REASON_STA_ROAM) {
ar->want_ch_switch |= 1 << vif->fw_vif_idx;
+ /* bail back to this channel if STA vif fails connect */
+ ar->last_ch = le16_to_cpu(vif->profile.ch);
+ }
+
+ if (prot_reason_status == WMI_AP_REASON_MAX_STA) {
+ /* send max client reached notification to user space */
+ cfg80211_conn_failed(vif->ndev, bssid,
+ NL80211_CONN_FAIL_MAX_CLIENTS,
+ GFP_KERNEL);
+ }
+
+ if (prot_reason_status == WMI_AP_REASON_ACL) {
+ /* send blocked client notification to user space */
+ cfg80211_conn_failed(vif->ndev, bssid,
+ NL80211_CONN_FAIL_BLOCKED_CLIENT,
+ GFP_KERNEL);
+ }
if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
return;
@@ -1041,6 +1075,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
}
}
+ /* restart disconnected concurrent vifs waiting for new channel */
+ ath6kl_check_ch_switch(ar, ar->last_ch);
+
/* update connect & link status atomically */
spin_lock_bh(&vif->if_lock);
clear_bit(CONNECTED, &vif->flags);
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
new file mode 100644
index 000000000000..3a8d5e97dc8e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -0,0 +1,160 @@
+/*
+ * 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 "core.h"
+#include "cfg80211.h"
+#include "debug.h"
+
+static void ath6kl_recovery_work(struct work_struct *work)
+{
+ struct ath6kl *ar = container_of(work, struct ath6kl,
+ fw_recovery.recovery_work);
+
+ ar->state = ATH6KL_STATE_RECOVERY;
+
+ del_timer_sync(&ar->fw_recovery.hb_timer);
+
+ ath6kl_init_hw_restart(ar);
+
+ ar->state = ATH6KL_STATE_ON;
+ clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
+
+ ar->fw_recovery.err_reason = 0;
+
+ if (ar->fw_recovery.hb_poll)
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
+{
+ if (!ar->fw_recovery.enable)
+ return;
+
+ ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
+ reason);
+
+ set_bit(reason, &ar->fw_recovery.err_reason);
+
+ if (!test_bit(RECOVERY_CLEANUP, &ar->flag) &&
+ ar->state != ATH6KL_STATE_RECOVERY)
+ queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
+{
+ if (cookie == ar->fw_recovery.seq_num)
+ ar->fw_recovery.hb_pending = false;
+}
+
+static void ath6kl_recovery_hb_timer(unsigned long data)
+{
+ struct ath6kl *ar = (struct ath6kl *) data;
+ int err;
+
+ if (test_bit(RECOVERY_CLEANUP, &ar->flag) ||
+ (ar->state == ATH6KL_STATE_RECOVERY))
+ return;
+
+ if (ar->fw_recovery.hb_pending)
+ ar->fw_recovery.hb_misscnt++;
+ else
+ ar->fw_recovery.hb_misscnt = 0;
+
+ if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
+ ar->fw_recovery.hb_misscnt = 0;
+ ar->fw_recovery.seq_num = 0;
+ ar->fw_recovery.hb_pending = false;
+ ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
+ return;
+ }
+
+ ar->fw_recovery.seq_num++;
+ ar->fw_recovery.hb_pending = true;
+
+ err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
+ ar->fw_recovery.seq_num, 0);
+ if (err)
+ ath6kl_warn("Failed to send hb challenge request, err:%d\n",
+ err);
+
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_init(struct ath6kl *ar)
+{
+ struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
+
+ clear_bit(RECOVERY_CLEANUP, &ar->flag);
+ INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
+ recovery->seq_num = 0;
+ recovery->hb_misscnt = 0;
+ ar->fw_recovery.hb_pending = false;
+ ar->fw_recovery.hb_timer.function = ath6kl_recovery_hb_timer;
+ ar->fw_recovery.hb_timer.data = (unsigned long) ar;
+ init_timer_deferrable(&ar->fw_recovery.hb_timer);
+
+ if (ar->fw_recovery.hb_poll)
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_cleanup(struct ath6kl *ar)
+{
+ if (!ar->fw_recovery.enable)
+ return;
+
+ set_bit(RECOVERY_CLEANUP, &ar->flag);
+
+ del_timer_sync(&ar->fw_recovery.hb_timer);
+ cancel_work_sync(&ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_suspend(struct ath6kl *ar)
+{
+ if (!ar->fw_recovery.enable)
+ return;
+
+ ath6kl_recovery_cleanup(ar);
+
+ if (!ar->fw_recovery.err_reason)
+ return;
+
+ /* Process pending fw error detection */
+ ar->fw_recovery.err_reason = 0;
+ WARN_ON(ar->state != ATH6KL_STATE_ON);
+ ar->state = ATH6KL_STATE_RECOVERY;
+ ath6kl_init_hw_restart(ar);
+ ar->state = ATH6KL_STATE_ON;
+}
+
+void ath6kl_recovery_resume(struct ath6kl *ar)
+{
+ if (!ar->fw_recovery.enable)
+ return;
+
+ clear_bit(RECOVERY_CLEANUP, &ar->flag);
+
+ if (!ar->fw_recovery.hb_poll)
+ return;
+
+ ar->fw_recovery.hb_pending = false;
+ ar->fw_recovery.seq_num = 0;
+ ar->fw_recovery.hb_misscnt = 0;
+ mod_timer(&ar->fw_recovery.hb_timer,
+ jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 05b95405f7b5..d111980d44c0 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -709,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
{
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
struct htc_target *target = ar->htc_target;
- int ret;
+ int ret = 0;
bool virt_scat = false;
if (ar_sdio->scatter_enabled)
@@ -844,22 +844,6 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
bool try_deepsleep = false;
int ret;
- if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
- ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
-
- ret = ath6kl_set_sdio_pm_caps(ar);
- if (ret)
- goto cut_pwr;
-
- ret = ath6kl_cfg80211_suspend(ar,
- ATH6KL_CFG_SUSPEND_SCHED_SCAN,
- NULL);
- if (ret)
- goto cut_pwr;
-
- return 0;
- }
-
if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
(!ar->suspend_mode && wow)) {
@@ -942,14 +926,14 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
case ATH6KL_STATE_WOW:
break;
- case ATH6KL_STATE_SCHED_SCAN:
- break;
-
case ATH6KL_STATE_SUSPENDING:
break;
case ATH6KL_STATE_RESUMING:
break;
+
+ case ATH6KL_STATE_RECOVERY:
+ break;
}
ath6kl_cfg80211_resume(ar);
@@ -1462,3 +1446,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 7dfa0fd86d7b..78b369286579 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -288,8 +288,16 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
int status = 0;
struct ath6kl_cookie *cookie = NULL;
- if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW))
+ if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
+ dev_kfree_skb(skb);
return -EACCES;
+ }
+
+ if (WARN_ON_ONCE(eid == ENDPOINT_UNUSED ||
+ eid >= ENDPOINT_MAX)) {
+ status = -EINVAL;
+ goto fail_ctrl_tx;
+ }
spin_lock_bh(&ar->lock);
@@ -591,6 +599,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/
set_bit(WMI_CTRL_EP_FULL, &ar->flag);
ath6kl_err("wmi ctrl ep is full\n");
+ ath6kl_recovery_err_notify(ar, ATH6KL_FW_EP_FULL);
return action;
}
@@ -695,22 +704,31 @@ void ath6kl_tx_complete(struct htc_target *target,
list);
list_del(&packet->list);
+ if (WARN_ON_ONCE(packet->endpoint == ENDPOINT_UNUSED ||
+ packet->endpoint >= ENDPOINT_MAX))
+ continue;
+
ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
- if (!ath6kl_cookie)
- goto fatal;
+ if (WARN_ON_ONCE(!ath6kl_cookie))
+ continue;
status = packet->status;
skb = ath6kl_cookie->skb;
eid = packet->endpoint;
map_no = ath6kl_cookie->map_no;
- if (!skb || !skb->data)
- goto fatal;
+ if (WARN_ON_ONCE(!skb || !skb->data)) {
+ dev_kfree_skb(skb);
+ ath6kl_free_cookie(ar, ath6kl_cookie);
+ continue;
+ }
__skb_queue_tail(&skb_queue, skb);
- if (!status && (packet->act_len != skb->len))
- goto fatal;
+ if (WARN_ON_ONCE(!status && (packet->act_len != skb->len))) {
+ ath6kl_free_cookie(ar, ath6kl_cookie);
+ continue;
+ }
ar->tx_pending[eid]--;
@@ -792,11 +810,6 @@ void ath6kl_tx_complete(struct htc_target *target,
wake_up(&ar->event_wq);
return;
-
-fatal:
- WARN_ON(1);
- spin_unlock_bh(&ar->lock);
- return;
}
void ath6kl_tx_data_cleanup(struct ath6kl *ar)
@@ -885,8 +898,11 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
break;
packet = (struct htc_packet *) skb->head;
- if (!IS_ALIGNED((unsigned long) skb->data, 4))
+ if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
+ size_t len = skb_headlen(skb);
skb->data = PTR_ALIGN(skb->data - 4, 4);
+ skb_set_tail_pointer(skb, len);
+ }
set_htc_rxpkt_info(packet, skb, skb->data,
ATH6KL_BUFFER_SIZE, endpoint);
packet->skb = skb;
@@ -908,8 +924,11 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
return;
packet = (struct htc_packet *) skb->head;
- if (!IS_ALIGNED((unsigned long) skb->data, 4))
+ if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
+ size_t len = skb_headlen(skb);
skb->data = PTR_ALIGN(skb->data - 4, 4);
+ skb_set_tail_pointer(skb, len);
+ }
set_htc_rxpkt_info(packet, skb, skb->data,
ATH6KL_AMSDU_BUFFER_SIZE, 0);
packet->skb = skb;
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 3740c3d6ab88..62bcc0d5bc23 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -185,9 +185,10 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
for (i = 0; i < urb_cnt; i++) {
urb_context = kzalloc(sizeof(struct ath6kl_urb_context),
GFP_KERNEL);
- if (urb_context == NULL)
- /* FIXME: set status to -ENOMEM */
- break;
+ if (urb_context == NULL) {
+ status = -ENOMEM;
+ goto fail_alloc_pipe_resources;
+ }
urb_context->pipe = pipe;
@@ -204,6 +205,7 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
pipe->logical_pipe_num, pipe->usb_pipe_handle,
pipe->urb_alloc);
+fail_alloc_pipe_resources:
return status;
}
@@ -803,7 +805,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
break;
case WMI_DATA_VI_SVC:
- *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
+
+ if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+ *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
+ else
+ *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
/*
* Disable rxdata2 directly, it will be enabled
* if FW enable rxdata2
@@ -811,7 +817,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
break;
case WMI_DATA_VO_SVC:
- *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_HP;
+
+ if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+ *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
+ else
+ *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
/*
* Disable rxdata2 directly, it will be enabled
* if FW enable rxdata2
@@ -1196,7 +1206,14 @@ static struct usb_driver ath6kl_usb_driver = {
static int ath6kl_usb_init(void)
{
- usb_register(&ath6kl_usb_driver);
+ int ret;
+
+ ret = usb_register(&ath6kl_usb_driver);
+ if (ret) {
+ ath6kl_err("usb registration failed: %d\n", ret);
+ return ret;
+ }
+
return 0;
}
@@ -1220,3 +1237,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index c30ab4b11d61..998f8b0f62fd 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
return -EINVAL;
}
id = vif->last_roc_id;
- cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
+ cfg80211_ready_on_channel(&vif->wdev, id, chan,
dur, GFP_ATOMIC);
return 0;
@@ -513,8 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
else
id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
vif->last_cancel_roc_id = 0;
- cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
- NL80211_CHAN_NO_HT, GFP_ATOMIC);
+ cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, GFP_ATOMIC);
return 0;
}
@@ -936,8 +935,12 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
regpair = ath6kl_get_regpair((u16) reg_code);
country = ath6kl_regd_find_country_by_rd((u16) reg_code);
- ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
- regpair->regDmnEnum);
+ if (regpair)
+ ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
+ regpair->regDmnEnum);
+ else
+ ath6kl_warn("Regpair not found reg_code 0x%0x\n",
+ reg_code);
}
if (country && wmi->parent_dev->wiphy_registered) {
@@ -1116,7 +1119,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
* the timer would not ever fire if the scan interval is short
* enough.
*/
- if (ar->state == ATH6KL_STATE_SCHED_SCAN &&
+ if (test_bit(SCHED_SCANNING, &vif->flags) &&
!timer_pending(&vif->sched_scan_timer)) {
mod_timer(&vif->sched_scan_timer, jiffies +
msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY));
@@ -1170,6 +1173,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
rate = RATE_AUTO;
} else {
index = reply->rate_index & 0x7f;
+ if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
+ return -EINVAL;
+
sgi = (reply->rate_index & 0x80) ? 1 : 0;
rate = wmi_rate_tbl[index][sgi];
}
@@ -1531,6 +1537,68 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
return 0;
}
+static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
+ struct ath6kl_vif *vif)
+{
+ struct wmi_txe_notify_event *ev;
+ u32 rate, pkts;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ if (vif->sme_state != SME_CONNECTED)
+ return -ENOTCONN;
+
+ ev = (struct wmi_txe_notify_event *) datap;
+ rate = le32_to_cpu(ev->rate);
+ pkts = le32_to_cpu(ev->pkts);
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "TXE notify event: peer %pM rate %d% pkts %d intvl %ds\n",
+ vif->bssid, rate, pkts, vif->txe_intvl);
+
+ cfg80211_cqm_txe_notify(vif->ndev, vif->bssid, pkts,
+ rate, vif->txe_intvl, GFP_KERNEL);
+
+ return 0;
+}
+
+int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
+ u32 rate, u32 pkts, u32 intvl)
+{
+ struct sk_buff *skb;
+ struct wmi_txe_notify_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_txe_notify_cmd *) skb->data;
+ cmd->rate = cpu_to_le32(rate);
+ cmd->pkts = cpu_to_le32(pkts);
+ cmd->intvl = cpu_to_le32(intvl);
+
+ return ath6kl_wmi_cmd_send(wmi, idx, skb, WMI_SET_TXE_NOTIFY_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi)
+{
+ struct sk_buff *skb;
+ struct wmi_set_rssi_filter_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_rssi_filter_cmd *) skb->data;
+ cmd->rssi = rssi;
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSSI_FILTER_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
struct wmi_snr_threshold_params_cmd *snr_cmd)
{
@@ -1677,8 +1745,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
int ret;
u16 info1;
- if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1))))
+ if (WARN_ON(skb == NULL ||
+ (if_idx > (wmi->parent_dev->vif_max - 1)))) {
+ dev_kfree_skb(skb);
return -EINVAL;
+ }
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
cmd_id, skb->len, sync_flag);
@@ -1833,6 +1904,59 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
return ret;
}
+/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
+ * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
+ * mgmt operations using station interface.
+ */
+static int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
+ enum wmi_scan_type scan_type,
+ u32 force_fgscan, u32 is_legacy,
+ u32 home_dwell_time,
+ u32 force_scan_interval,
+ s8 num_chan, u16 *ch_list)
+{
+ struct sk_buff *skb;
+ struct wmi_start_scan_cmd *sc;
+ s8 size;
+ int i, ret;
+
+ size = sizeof(struct wmi_start_scan_cmd);
+
+ if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
+ return -EINVAL;
+
+ if (num_chan > WMI_MAX_CHANNELS)
+ return -EINVAL;
+
+ if (num_chan)
+ size += sizeof(u16) * (num_chan - 1);
+
+ skb = ath6kl_wmi_get_new_buf(size);
+ if (!skb)
+ return -ENOMEM;
+
+ sc = (struct wmi_start_scan_cmd *) skb->data;
+ sc->scan_type = scan_type;
+ sc->force_fg_scan = cpu_to_le32(force_fgscan);
+ sc->is_legacy = cpu_to_le32(is_legacy);
+ sc->home_dwell_time = cpu_to_le32(home_dwell_time);
+ sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
+ sc->num_ch = num_chan;
+
+ for (i = 0; i < num_chan; i++)
+ sc->ch_list[i] = cpu_to_le16(ch_list[i]);
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+/*
+ * beginscan supports (compared to old startscan) P2P mgmt operations using
+ * station interface, send additional information like supported rates to
+ * advertise and xmit rates for probe requests
+ */
int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
enum wmi_scan_type scan_type,
u32 force_fgscan, u32 is_legacy,
@@ -1848,6 +1972,15 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
int num_rates;
u32 ratemask;
+ if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+ ar->fw_capabilities)) {
+ return ath6kl_wmi_startscan_cmd(wmi, if_idx,
+ scan_type, force_fgscan,
+ is_legacy, home_dwell_time,
+ force_scan_interval,
+ num_chan, ch_list);
+ }
+
size = sizeof(struct wmi_begin_scan_cmd);
if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
@@ -1900,50 +2033,24 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
return ret;
}
-/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
- * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
- * mgmt operations using station interface.
- */
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
- enum wmi_scan_type scan_type,
- u32 force_fgscan, u32 is_legacy,
- u32 home_dwell_time, u32 force_scan_interval,
- s8 num_chan, u16 *ch_list)
+int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable)
{
struct sk_buff *skb;
- struct wmi_start_scan_cmd *sc;
- s8 size;
- int i, ret;
-
- size = sizeof(struct wmi_start_scan_cmd);
-
- if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
- return -EINVAL;
-
- if (num_chan > WMI_MAX_CHANNELS)
- return -EINVAL;
-
- if (num_chan)
- size += sizeof(u16) * (num_chan - 1);
+ struct wmi_enable_sched_scan_cmd *sc;
+ int ret;
- skb = ath6kl_wmi_get_new_buf(size);
+ skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
if (!skb)
return -ENOMEM;
- sc = (struct wmi_start_scan_cmd *) skb->data;
- sc->scan_type = scan_type;
- sc->force_fg_scan = cpu_to_le32(force_fgscan);
- sc->is_legacy = cpu_to_le32(is_legacy);
- sc->home_dwell_time = cpu_to_le32(home_dwell_time);
- sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
- sc->num_ch = num_chan;
-
- for (i = 0; i < num_chan; i++)
- sc->ch_list[i] = cpu_to_le16(ch_list[i]);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "%s scheduled scan on vif %d\n",
+ enable ? "enabling" : "disabling", if_idx);
+ sc = (struct wmi_enable_sched_scan_cmd *) skb->data;
+ sc->enable = enable ? 1 : 0;
- ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+ WMI_ENABLE_SCHED_SCAN_CMDID,
NO_SYNC_WMIFLAG);
-
return ret;
}
@@ -2275,8 +2382,10 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
struct wmi_data_hdr *data_hdr;
int ret;
- if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
+ if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) {
+ dev_kfree_skb(skb);
return -EINVAL;
+ }
skb_push(skb, sizeof(struct wmi_data_hdr));
@@ -2313,10 +2422,8 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
spin_unlock_bh(&wmi->lock);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
- if (!skb) {
- ret = -ENOMEM;
- goto free_skb;
- }
+ if (!skb)
+ return -ENOMEM;
cmd = (struct wmi_sync_cmd *) skb->data;
@@ -2339,7 +2446,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
* then do not send the Synchronize cmd on the control ep
*/
if (ret)
- goto free_skb;
+ goto free_cmd_skb;
/*
* Send sync cmd followed by sync data messages on all
@@ -2349,15 +2456,12 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
NO_SYNC_WMIFLAG);
if (ret)
- goto free_skb;
-
- /* cmd buffer sent, we no longer own it */
- skb = NULL;
+ goto free_data_skb;
for (index = 0; index < num_pri_streams; index++) {
if (WARN_ON(!data_sync_bufs[index].skb))
- break;
+ goto free_data_skb;
ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
data_sync_bufs[index].
@@ -2366,17 +2470,20 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
ep_id, if_idx);
- if (ret)
- break;
-
data_sync_bufs[index].skb = NULL;
+
+ if (ret)
+ goto free_data_skb;
}
-free_skb:
+ return 0;
+
+free_cmd_skb:
/* free up any resources left over (possibly due to an error) */
if (skb)
dev_kfree_skb(skb);
+free_data_skb:
for (index = 0; index < num_pri_streams; index++) {
if (data_sync_bufs[index].skb != NULL) {
dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
@@ -2618,11 +2725,13 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
{
struct sk_buff *skb;
int ret, mode, band;
- u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+ u64 mcsrate, ratemask[ATH6KL_NUM_BANDS];
struct wmi_set_tx_select_rates64_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+ /* only check 2.4 and 5 GHz bands, skip the rest */
+ for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
@@ -2668,11 +2777,13 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
{
struct sk_buff *skb;
int ret, mode, band;
- u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+ u32 mcsrate, ratemask[ATH6KL_NUM_BANDS];
struct wmi_set_tx_select_rates32_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+ /* only check 2.4 and 5 GHz bands, skip the rest */
+ for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
@@ -2716,7 +2827,7 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{
struct ath6kl *ar = wmi->parent_dev;
- if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
+ if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3139,12 +3250,40 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
return ret;
}
+int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
+{
+ struct sk_buff *skb;
+ struct wmi_set_regdomain_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_regdomain_cmd *) skb->data;
+ memcpy(cmd->iso_name, alpha2, 2);
+
+ return ath6kl_wmi_cmd_send(wmi, 0, skb,
+ WMI_SET_REGDOMAIN_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
s32 ath6kl_wmi_get_rate(s8 rate_index)
{
+ u8 sgi = 0;
+
if (rate_index == RATE_AUTO)
return 0;
- return wmi_rate_tbl[(u32) rate_index][0];
+ /* SGI is stored as the MSB of the rate_index */
+ if (rate_index & RATE_INDEX_MSB) {
+ rate_index &= RATE_INDEX_WITHOUT_SGI_MASK;
+ sgi = 1;
+ }
+
+ if (WARN_ON(rate_index > RATE_MCS_7_40))
+ rate_index = RATE_MCS_7_40;
+
+ return wmi_rate_tbl[(u32) rate_index][sgi];
}
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
@@ -3634,6 +3773,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
NO_SYNC_WMIFLAG);
}
+static void ath6kl_wmi_hb_challenge_resp_event(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmix_hb_challenge_resp_cmd *cmd;
+
+ if (len < sizeof(struct wmix_hb_challenge_resp_cmd))
+ return;
+
+ cmd = (struct wmix_hb_challenge_resp_cmd *) datap;
+ ath6kl_recovery_hb_event(wmi->parent_dev,
+ le32_to_cpu(cmd->cookie));
+}
+
static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
{
struct wmix_cmd_hdr *cmd;
@@ -3658,6 +3810,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
switch (id) {
case WMIX_HB_CHALLENGE_RESP_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
+ ath6kl_wmi_hb_challenge_resp_event(wmi, datap, len);
break;
case WMIX_DBGLOG_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
@@ -3750,6 +3903,9 @@ static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
case WMI_RX_ACTION_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
+ case WMI_TXE_NOTIFY_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TXE_NOTIFY_EVENTID\n");
+ return ath6kl_wmi_txe_notify_event_rx(wmi, datap, len, vif);
default:
ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 43339aca585d..98b1755e67f4 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -48,7 +48,7 @@
#define A_BAND_24GHZ 0
#define A_BAND_5GHZ 1
-#define A_NUM_BANDS 2
+#define ATH6KL_NUM_BANDS 2
/* in ms */
#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
@@ -628,6 +628,20 @@ enum wmi_cmd_id {
WMI_SET_MCASTRATE,
WMI_STA_BMISS_ENHANCE_CMDID,
+
+ WMI_SET_REGDOMAIN_CMDID,
+
+ WMI_SET_RSSI_FILTER_CMDID,
+
+ WMI_SET_KEEP_ALIVE_EXT,
+
+ WMI_VOICE_DETECTION_ENABLE_CMDID,
+
+ WMI_SET_TXE_NOTIFY_CMDID,
+
+ WMI_SET_RECOVERY_TEST_PARAMETER_CMDID, /*0xf094*/
+
+ WMI_ENABLE_SCHED_SCAN_CMDID,
};
enum wmi_mgmt_frame_type {
@@ -843,7 +857,7 @@ struct wmi_begin_scan_cmd {
u8 scan_type;
/* Supported rates to advertise in the probe request frames */
- struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS];
+ struct wmi_supp_rates supp_rates[ATH6KL_NUM_BANDS];
/* how many channels follow */
u8 num_ch;
@@ -941,6 +955,11 @@ struct wmi_scan_params_cmd {
__le32 max_dfsch_act_time;
} __packed;
+/* WMI_ENABLE_SCHED_SCAN_CMDID */
+struct wmi_enable_sched_scan_cmd {
+ u8 enable;
+} __packed;
+
/* WMI_SET_BSS_FILTER_CMDID */
enum wmi_bss_filter {
/* no beacons forwarded */
@@ -1032,6 +1051,11 @@ struct wmi_sta_bmiss_enhance_cmd {
u8 enable;
} __packed;
+struct wmi_set_regdomain_cmd {
+ u8 length;
+ u8 iso_name[2];
+} __packed;
+
/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
REC_POWER = 0x01,
@@ -1276,6 +1300,11 @@ struct wmi_snr_threshold_params_cmd {
u8 reserved[3];
} __packed;
+/* Don't report BSSs with signal (RSSI) below this threshold */
+struct wmi_set_rssi_filter_cmd {
+ s8 rssi;
+} __packed;
+
enum wmi_preamble_policy {
WMI_IGNORE_BARKER_IN_ERP = 0,
WMI_FOLLOW_BARKER_IN_ERP,
@@ -1455,6 +1484,20 @@ enum wmi_event_id {
WMI_P2P_CAPABILITIES_EVENTID,
WMI_RX_ACTION_EVENTID,
WMI_P2P_INFO_EVENTID,
+
+ /* WPS Events */
+ WMI_WPS_GET_STATUS_EVENTID,
+ WMI_WPS_PROFILE_EVENTID,
+
+ /* more P2P events */
+ WMI_NOA_INFO_EVENTID,
+ WMI_OPPPS_INFO_EVENTID,
+ WMI_PORT_STATUS_EVENTID,
+
+ /* 802.11w */
+ WMI_GET_RSN_CAP_EVENTID,
+
+ WMI_TXE_NOTIFY_EVENTID,
};
struct wmi_ready_event_2 {
@@ -1749,6 +1792,9 @@ struct rx_stats {
a_sle32 ucast_rate;
} __packed;
+#define RATE_INDEX_WITHOUT_SGI_MASK 0x7f
+#define RATE_INDEX_MSB 0x80
+
struct tkip_ccmp_stats {
__le32 tkip_local_mic_fail;
__le32 tkip_cnter_measures_invoked;
@@ -2019,7 +2065,6 @@ struct wmi_set_ie_cmd {
#define WOW_MAX_FILTERS_PER_LIST 4
#define WOW_PATTERN_SIZE 64
-#define WOW_MASK_SIZE 64
#define MAC_MAX_FILTERS_PER_LIST 4
@@ -2028,7 +2073,7 @@ struct wow_filter {
u8 wow_filter_id;
u8 wow_filter_size;
u8 wow_filter_offset;
- u8 wow_filter_mask[WOW_MASK_SIZE];
+ u8 wow_filter_mask[WOW_PATTERN_SIZE];
u8 wow_filter_pattern[WOW_PATTERN_SIZE];
} __packed;
@@ -2087,6 +2132,19 @@ struct wmi_del_wow_pattern_cmd {
__le16 filter_id;
} __packed;
+/* WMI_SET_TXE_NOTIFY_CMDID */
+struct wmi_txe_notify_cmd {
+ __le32 rate;
+ __le32 pkts;
+ __le32 intvl;
+} __packed;
+
+/* WMI_TXE_NOTIFY_EVENTID */
+struct wmi_txe_notify_event {
+ __le32 rate;
+ __le32 pkts;
+} __packed;
+
/* WMI_SET_AKMP_PARAMS_CMD */
struct wmi_pmkid {
@@ -2505,11 +2563,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
u16 channel);
int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx);
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
- enum wmi_scan_type scan_type,
- u32 force_fgscan, u32 is_legacy,
- u32 home_dwell_time, u32 force_scan_interval,
- s8 num_chan, u16 *ch_list);
int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
enum wmi_scan_type scan_type,
@@ -2517,6 +2570,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
u32 home_dwell_time, u32 force_scan_interval,
s8 num_chan, u16 *ch_list, u32 no_cck,
u32 *rates);
+int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable);
int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
u16 fg_end_sec, u16 bg_sec,
@@ -2592,6 +2646,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
const u8 *mask);
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id);
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
@@ -2600,6 +2655,9 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
u8 *filter, bool add_filter);
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
+int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
+ u32 rate, u32 pkts, u32 intvl);
+int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);
/* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
@@ -2658,6 +2716,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);
void ath6kl_wmi_sscan_timer(unsigned long ptr);
+int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
+
struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
void *ath6kl_wmi_init(struct ath6kl *devt);
void ath6kl_wmi_shutdown(struct wmi *wmi);
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index c7aa6646123e..5fc15bf8be09 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -17,6 +17,7 @@ config ATH9K_BTCOEX_SUPPORT
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on MAC80211
+ select ATH_COMMON
select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index 6f7cf49eff4d..262e1e036fd7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -534,98 +534,98 @@ 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, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
- {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
- {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {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, 0x12000400, 0x12000400},
- {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
- {0x0000a51c, 0x27002223, 0x27002223, 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, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
- {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
- {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
- {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
- {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
- {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
- {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
- {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
- {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
- {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, 0x12800400, 0x12800400},
- {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
- {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
- {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
- {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
- {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
- {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
- {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
- {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
- {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
- {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
- {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
- {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+ {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, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
- {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
- {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
- {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
- {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
- {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
- {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
- {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
- {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
- {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
- {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {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, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
- {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
- {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+ {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},
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 84b558d126ca..8b0d8dcd7625 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
offset_array[i],
REG_READ(ah, offset_array[i]));
+ if (AR_SREV_9565(ah) &&
+ (iCoff == 63 || qCoff == 63 ||
+ iCoff == -63 || qCoff == -63))
+ return;
+
REG_RMW_FIELD(ah, offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
iCoff);
@@ -886,6 +891,74 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
}
+static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
+{
+ int offset[8], total = 0, test;
+ int agc_out, i;
+
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+ AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+ AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
+ if (is_2g)
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+ AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
+ else
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+ AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
+
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+ AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+ AR_PHY_65NM_RXTX2_RXON, 0x0);
+
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ 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
+ 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);
+ test = total + offset[i];
+
+ if (is_2g)
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
+ test);
+ else
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
+ test);
+ udelay(100);
+ agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC_OUT);
+ offset[i] = (agc_out) ? 0 : 1;
+ total += (offset[i] << (i - 1));
+ }
+
+ if (is_2g)
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
+ else
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
+
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+ AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+ AR_PHY_65NM_RXTX2_RXON_OVR, 0);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
+}
+
static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -984,6 +1057,14 @@ skip_tx_iqcal:
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT);
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ ar9003_hw_manual_peak_cal(ah, i,
+ IS_CHAN_2GHZ(chan));
+ }
+ }
}
if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 5bbe5057ba18..562186ca9b52 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -18,6 +18,7 @@
#include "hw.h"
#include "ar9003_phy.h"
#include "ar9003_eeprom.h"
+#include "ar9003_mci.h"
#define COMP_HDR_LEN 4
#define COMP_CKSUM_LEN 2
@@ -41,7 +42,6 @@
static int ar9003_hw_power_interpolate(int32_t x,
int32_t *px, int32_t *py, u_int16_t np);
-
static const struct ar9300_eeprom ar9300_default = {
.eepromVersion = 2,
.templateVersion = 2,
@@ -2987,10 +2987,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
case EEP_RX_MASK:
return pBase->txrxMask & 0xf;
case EEP_PAPRD:
- if (AR_SREV_9462(ah))
- return false;
- if (!ah->config.enable_paprd);
- return false;
return !!(pBase->featureEnable & BIT(5));
case EEP_CHAIN_MASK_REDUCE:
return (pBase->miscConfiguration >> 0x3) & 0x1;
@@ -3005,24 +3001,24 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
}
}
-static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
+static bool ar9300_eeprom_read_byte(struct ath_hw *ah, int address,
u8 *buffer)
{
u16 val;
- if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
+ if (unlikely(!ath9k_hw_nvram_read(ah, address / 2, &val)))
return false;
*buffer = (val >> (8 * (address % 2))) & 0xff;
return true;
}
-static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
+static bool ar9300_eeprom_read_word(struct ath_hw *ah, int address,
u8 *buffer)
{
u16 val;
- if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
+ if (unlikely(!ath9k_hw_nvram_read(ah, address / 2, &val)))
return false;
buffer[0] = val >> 8;
@@ -3048,14 +3044,14 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
* the 16-bit word at that address
*/
if (address % 2 == 0) {
- if (!ar9300_eeprom_read_byte(common, address--, buffer++))
+ if (!ar9300_eeprom_read_byte(ah, address--, buffer++))
goto error;
count--;
}
for (i = 0; i < count / 2; i++) {
- if (!ar9300_eeprom_read_word(common, address, buffer))
+ if (!ar9300_eeprom_read_word(ah, address, buffer))
goto error;
address -= 2;
@@ -3063,7 +3059,7 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
}
if (count % 2)
- if (!ar9300_eeprom_read_byte(common, address, buffer))
+ if (!ar9300_eeprom_read_byte(ah, address, buffer))
goto error;
return true;
@@ -3240,12 +3236,11 @@ static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read,
static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr,
int mdata_size)
{
- struct ath_common *common = ath9k_hw_common(ah);
u16 *data = (u16 *) mptr;
int i;
for (i = 0; i < mdata_size / 2; i++, data++)
- ath9k_hw_nvram_read(common, i, data);
+ ath9k_hw_nvram_read(ah, i, data);
return 0;
}
@@ -3601,7 +3596,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
* SWITCH_TABLE_COM_SPDT_WLAN_IDLE
*/
- if (AR_SREV_9462_20_OR_LATER(ah)) {
+ if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) {
value = ar9003_switch_com_spdt_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
AR_SWITCH_TABLE_COM_SPDT_ALL, value);
@@ -5037,16 +5032,28 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
case CTL_5GHT20:
case CTL_2GHT20:
for (i = ALL_TARGET_HT20_0_8_16;
- i <= ALL_TARGET_HT20_23; i++)
+ i <= ALL_TARGET_HT20_23; i++) {
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
minCtlPower);
+ if (ath9k_hw_mci_is_enabled(ah))
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ ar9003_mci_get_max_txpower(ah,
+ pCtlMode[ctlMode]));
+ }
break;
case CTL_5GHT40:
case CTL_2GHT40:
for (i = ALL_TARGET_HT40_0_8_16;
- i <= ALL_TARGET_HT40_23; i++)
+ i <= ALL_TARGET_HT40_23; i++) {
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
minCtlPower);
+ if (ath9k_hw_mci_is_enabled(ah))
+ pPwrArray[i] =
+ (u8)min((u16)pPwrArray[i],
+ ar9003_mci_get_max_txpower(ah,
+ pCtlMode[ctlMode]));
+ }
break;
default:
break;
@@ -5064,6 +5071,33 @@ static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
}
+static void ar9003_paprd_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *targetPowerValT2)
+{
+ int i;
+
+ if (!ar9003_is_paprd_enabled(ah))
+ return;
+
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_7;
+ else
+ i = ALL_TARGET_HT20_7;
+
+ if (IS_CHAN_2GHZ(chan)) {
+ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) &&
+ !AR_SREV_9462(ah) && !AR_SREV_9565(ah)) {
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_0_8_16;
+ else
+ i = ALL_TARGET_HT20_0_8_16;
+ }
+ }
+
+ ah->paprd_target_power = targetPowerValT2[i];
+}
+
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
@@ -5085,7 +5119,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
*/
ar9003_hw_get_target_power_eeprom(ah, chan, targetPowerValT2);
- if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ if (ar9003_is_paprd_enabled(ah)) {
if (IS_CHAN_2GHZ(chan))
modal_hdr = &eep->modalHeader2G;
else
@@ -5126,7 +5160,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
twiceAntennaReduction,
powerLimit);
- if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ if (ar9003_is_paprd_enabled(ah)) {
for (i = 0; i < ar9300RateSize; i++) {
if ((ah->paprd_ratemask & (1 << i)) &&
(abs(targetPowerValT2[i] -
@@ -5158,19 +5192,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
/* Write target power array to registers */
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
ar9003_hw_calibration_apply(ah, chan->channel);
-
- if (IS_CHAN_2GHZ(chan)) {
- if (IS_CHAN_HT40(chan))
- i = ALL_TARGET_HT40_0_8_16;
- else
- i = ALL_TARGET_HT20_0_8_16;
- } else {
- if (IS_CHAN_HT40(chan))
- i = ALL_TARGET_HT40_7;
- else
- i = ALL_TARGET_HT20_7;
- }
- ah->paprd_target_power = targetPowerValT2[i];
+ ar9003_paprd_set_txpower(ah, chan, targetPowerValT2);
}
static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 41b1a75e6bec..54ba42f4108a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -68,13 +68,13 @@
#define AR9300_BASE_ADDR 0x3ff
#define AR9300_BASE_ADDR_512 0x1ff
-#define AR9300_OTP_BASE 0x14000
-#define AR9300_OTP_STATUS 0x15f18
+#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000)
+#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18)
#define AR9300_OTP_STATUS_TYPE 0x7
#define AR9300_OTP_STATUS_VALID 0x4
#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
#define AR9300_OTP_STATUS_SM_BUSY 0x1
-#define AR9300_OTP_READ_DATA 0x15f1c
+#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c)
enum targetPowerHTRates {
HT_TARGET_RATE_0_8_16,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 1a36fa262639..74fd3977feeb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -35,12 +35,6 @@
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
-#define AR9462_BB_CTX_COEFJ(x) \
- ar9462_##x##_baseband_core_txfir_coeff_japan_2484
-
-#define AR9462_BBC_TXIFR_COEFFJ \
- ar9462_2p0_baseband_core_txfir_coeff_japan_2484
-
if (AR_SREV_9330_11(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -70,6 +64,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p1);
+ /* Japan 2484 Mhz CCK */
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ ar9331_1p1_baseband_core_txfir_coeff_japan_2484);
+
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
@@ -106,6 +104,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p2);
+ /* Japan 2484 Mhz CCK */
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ ar9331_1p2_baseband_core_txfir_coeff_japan_2484);
+
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
@@ -180,6 +182,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485_modes_lowest_ob_db_tx_gain_1_1);
+ /* Japan 2484 Mhz CCK */
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ ar9485_1_1_baseband_core_txfir_coeff_japan_2484);
+
/* Load PCIE SERDES settings from INI */
/* Awake Setting */
@@ -219,19 +225,17 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* Awake -> Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
+ ar9462_pciephy_clkreq_disable_L1_2p0);
/* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
+ ar9462_pciephy_clkreq_disable_L1_2p0);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9462_modes_fast_clock_2p0);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
- AR9462_BB_CTX_COEFJ(2p0));
-
- INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ);
+ ar9462_2p0_baseband_core_txfir_coeff_japan_2484);
} else if (AR_SREV_9550(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -328,9 +332,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9565_1p0_Modes_lowest_ob_db_tx_gain_table);
INIT_INI_ARRAY(&ah->iniPcieSerdes,
- ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
+ ar9565_1p0_pciephy_clkreq_disable_L1);
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
- ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
+ ar9565_1p0_pciephy_clkreq_disable_L1);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9565_1p0_modes_fast_clock);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 44c202ce6c66..8dd069259e7b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -714,7 +714,6 @@ bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
return true;
}
-EXPORT_SYMBOL(ar9003_mci_start_reset);
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata)
@@ -750,6 +749,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
mci_hw->bt_state = MCI_BT_AWAKE;
+ REG_CLR_BIT(ah, AR_PHY_TIMING4,
+ 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
+
if (caldata) {
caldata->done_txiqcal_once = false;
caldata->done_txclcal_once = false;
@@ -759,6 +761,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;
+ REG_SET_BIT(ah, AR_PHY_TIMING4,
+ 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
+
exit:
ar9003_mci_enable_interrupt(ah);
return 0;
@@ -799,6 +804,9 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
+ if (AR_SREV_9565(ah))
+ REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
+
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
@@ -818,7 +826,7 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
- u32 regval;
+ u32 regval, i;
ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
is_full_sleep, is_2g);
@@ -847,11 +855,18 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
- SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
- SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+ if (AR_SREV_9565(ah)) {
+ regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
+ } else {
+ regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+ SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
+ }
REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
@@ -865,9 +880,24 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
- REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1);
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
+ /* Set the time out to 3.125ms (5 BT slots) */
+ REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
+
+ /* concurrent tx priority */
+ if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) {
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+ AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
+ REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+ AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
+ for (i = 0; i < 8; i++)
+ REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f);
+ }
+
regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
@@ -910,6 +940,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
mci->ready = true;
ar9003_mci_prep_interface(ah);
+ if (AR_SREV_9565(ah))
+ REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
+ AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
if (en_int)
ar9003_mci_enable_interrupt(ah);
@@ -1028,7 +1061,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
ar9003_mci_osla_setup(ah, true);
- REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
+
+ if (AR_SREV_9462(ah))
+ REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
} else {
ar9003_mci_send_lna_take(ah, true);
udelay(5);
@@ -1170,7 +1205,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup);
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
- u32 value = 0;
+ u32 value = 0, tsf;
u8 query_type;
switch (state_type) {
@@ -1228,6 +1263,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
break;
case MCI_STATE_RECOVER_RX:
+ tsf = ath9k_hw_gettsf32(ah);
+ if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) {
+ ath_dbg(ath9k_hw_common(ah), MCI,
+ "(MCI) ignore Rx recovery\n");
+ break;
+ }
+ ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n");
+ mci->last_recovery = tsf;
ar9003_mci_prep_interface(ah);
mci->query_bt = true;
mci->need_flush_btinfo = true;
@@ -1426,3 +1469,17 @@ void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
ar9003_mci_send_coex_wlan_channels(ah, true);
}
EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
+
+u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
+{
+ if (!ah->btcoex_hw.mci.concur_tx)
+ goto out;
+
+ if (ctlmode == CTL_2GHT20)
+ return ATH_BTCOEX_HT20_MAX_TXPOWER;
+ else if (ctlmode == CTL_2GHT40)
+ return ATH_BTCOEX_HT40_MAX_TXPOWER;
+
+out:
+ return -1;
+}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
index 2a2d01889613..66d7ab9f920d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
@@ -18,6 +18,7 @@
#define AR9003_MCI_H
#define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
+#define MCI_RECOVERY_DUR_TSF (100 * 1000) /* 100 ms */
/* Default remote BT device MCI COEX version */
#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3
@@ -125,6 +126,7 @@ enum ath_mci_gpm_coex_profile_type {
MCI_GPM_COEX_PROFILE_HID,
MCI_GPM_COEX_PROFILE_BNEP,
MCI_GPM_COEX_PROFILE_VOICE,
+ MCI_GPM_COEX_PROFILE_A2DPVO,
MCI_GPM_COEX_PROFILE_MAX
};
@@ -196,7 +198,6 @@ enum mci_state_type {
MCI_STATE_SEND_WLAN_COEX_VERSION,
MCI_STATE_SEND_VERSION_QUERY,
MCI_STATE_SEND_STATUS_QUERY,
- MCI_STATE_SET_CONCUR_TX_PRI,
MCI_STATE_RECOVER_RX,
MCI_STATE_NEED_FTP_STOMP,
MCI_STATE_DEBUG,
@@ -278,6 +279,7 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
void ar9003_mci_set_power_awake(struct ath_hw *ah);
void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
+u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode);
#else
@@ -324,6 +326,10 @@ static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
{
}
+static inline u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
+{
+ return -1;
+}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
#endif
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 0ed3846f9cbb..09c1f9da67a0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -74,15 +74,23 @@ static int ar9003_get_training_power_2g(struct ath_hw *ah)
unsigned int power, scale, delta;
scale = ar9003_get_paprd_scale_factor(ah, chan);
- power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
- AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
- delta = abs((int) ah->paprd_target_power - (int) power);
- if (delta > scale)
- return -1;
-
- if (delta < 4)
- power -= 4 - delta;
+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ power = ah->paprd_target_power + 2;
+ } else if (AR_SREV_9485(ah)) {
+ power = 25;
+ } else {
+ power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
+ AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
+
+ delta = abs((int) ah->paprd_target_power - (int) power);
+ if (delta > scale)
+ return -1;
+
+ if (delta < 4)
+ power -= 4 - delta;
+ }
return power;
}
@@ -169,6 +177,9 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
ah->paprd_ratemask_ht40);
+ ath_dbg(common, CALIBRATE, "PAPRD HT20 mask: 0x%x, HT40 mask: 0x%x\n",
+ ah->paprd_ratemask, ah->paprd_ratemask_ht40);
+
for (i = 0; i < ah->caps.max_txchains; i++) {
REG_RMW_FIELD(ah, ctrl0[i],
AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
@@ -204,7 +215,20 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
- val = AR_SREV_9462(ah) ? 0x91 : 147;
+
+ if (AR_SREV_9485(ah)) {
+ val = 148;
+ } else {
+ if (IS_CHAN_2GHZ(ah->curchan)) {
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+ val = 145;
+ else
+ val = 147;
+ } else {
+ val = 137;
+ }
+ }
+
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
@@ -215,15 +239,24 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
- if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9550(ah))
+
+ if (AR_SREV_9485(ah) ||
+ AR_SREV_9462(ah) ||
+ AR_SREV_9565(ah) ||
+ AR_SREV_9550(ah) ||
+ AR_SREV_9330(ah) ||
+ AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
- AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
- -3);
+ AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -3);
else
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
- AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
- -6);
- val = AR_SREV_9462(ah) ? -10 : -15;
+ AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6);
+
+ val = -10;
+
+ if (IS_CHAN_2GHZ(ah->curchan) && !AR_SREV_9462(ah) && !AR_SREV_9565(ah))
+ val = -15;
+
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
val);
@@ -262,9 +295,6 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
u32 reg = AR_PHY_TXGAIN_TABLE;
int i;
- memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
- memset(index, 0, sizeof(ah->paprd_gain_table_index));
-
for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
entry[i] = REG_READ(ah, reg);
index[i] = (entry[i] >> 24) & 0xff;
@@ -763,7 +793,7 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
}
EXPORT_SYMBOL(ar9003_paprd_populate_single_table);
-int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
+void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
{
unsigned int i, desired_gain, gain_index;
unsigned int train_power = ah->paprd_training_power;
@@ -781,8 +811,6 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
-
- return 0;
}
EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
@@ -894,7 +922,7 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,
memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
- buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC);
+ buf = kmalloc(2 * 48 * sizeof(u32), GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -945,9 +973,13 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);
bool ar9003_paprd_is_done(struct ath_hw *ah)
{
int paprd_done, agc2_pwr;
+
paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+ if (AR_SREV_9485(ah))
+ goto exit;
+
if (paprd_done == 0x1) {
agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
@@ -963,7 +995,16 @@ bool ar9003_paprd_is_done(struct ath_hw *ah)
if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
paprd_done = 0;
}
-
+exit:
return !!paprd_done;
}
EXPORT_SYMBOL(ar9003_paprd_is_done);
+
+bool ar9003_is_paprd_enabled(struct ath_hw *ah)
+{
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->config.enable_paprd)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(ar9003_is_paprd_enabled);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 759f5f5a7154..ce19c09fa8e8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -784,7 +784,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
if (chan->channel == 2484)
- ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
+ ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 9a48e3d2f231..107956298488 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -32,6 +32,7 @@
#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc)
#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0)
+#define AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
@@ -697,13 +698,6 @@
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
-#define AR_PHY_65NM_CH0_RXTX1 0x16100
-#define AR_PHY_65NM_CH0_RXTX2 0x16104
-#define AR_PHY_65NM_CH1_RXTX1 0x16500
-#define AR_PHY_65NM_CH1_RXTX2 0x16504
-#define AR_PHY_65NM_CH2_RXTX1 0x16900
-#define AR_PHY_65NM_CH2_RXTX2 0x16904
-
#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
#define AR_CH0_TOP2_XPABIASLVL 0xf000
@@ -1151,9 +1145,8 @@
#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000
#define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17
-#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + \
- (AR_SREV_9485(ah) ? \
- 0x580 : 0x490))
+#define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x580 : 0x490))
+
#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001
#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0
#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e
@@ -1169,15 +1162,13 @@
#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000
#define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12
-#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + \
- (AR_SREV_9485(ah) ? \
- 0x584 : 0x494))
+#define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x584 : 0x494))
+
#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF
#define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0
-#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + \
- (AR_SREV_9485(ah) ? \
- 0x588 : 0x498))
+#define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x588 : 0x498))
+
#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f
#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0
#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0
@@ -1193,9 +1184,8 @@
#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000
#define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29
-#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + \
- (AR_SREV_9485(ah) ? \
- 0x58c : 0x49c))
+#define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x58c : 0x49c))
+
#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000
#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16
#define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000
@@ -1214,7 +1204,8 @@
#define AR_PHY_PAPRD_PRE_POST_SCALING 0x3FFFF
#define AR_PHY_PAPRD_PRE_POST_SCALING_S 0
-#define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + 0x4a0)
+#define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x590 : 0x4a0))
+
#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE 0x00000001
#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S 0
#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE 0x00000002
@@ -1228,7 +1219,8 @@
#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR 0x0001fe00
#define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S 9
-#define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + 0x4a4)
+#define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x594 : 0x4a4))
+
#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL 0x0000ffff
#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S 0
#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX 0x001f0000
@@ -1236,7 +1228,8 @@
#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX 0x00600000
#define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S 21
-#define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + 0x4a8)
+#define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + (AR_SREV_9485(ah) ? 0x598 : 0x4a8))
+
#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT 0x000fffff
#define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S 0
@@ -1285,4 +1278,43 @@
#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD 0xFC000000
#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S 26
+/* Manual Peak detector calibration */
+#define AR_PHY_65NM_BASE 0x16000
+#define AR_PHY_65NM_RXRF_GAINSTAGES(i) (AR_PHY_65NM_BASE + \
+ (i * 0x400) + 0x8)
+#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE 0x80000000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE_S 31
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC 0x00000002
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC_S 1
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR 0x70000000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR_S 28
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR 0x03800000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR_S 23
+
+#define AR_PHY_65NM_RXTX2(i) (AR_PHY_65NM_BASE + \
+ (i * 0x400) + 0x104)
+#define AR_PHY_65NM_RXTX2_RXON_OVR 0x00001000
+#define AR_PHY_65NM_RXTX2_RXON_OVR_S 12
+#define AR_PHY_65NM_RXTX2_RXON 0x00000800
+#define AR_PHY_65NM_RXTX2_RXON_S 11
+
+#define AR_PHY_65NM_RXRF_AGC(i) (AR_PHY_65NM_BASE + \
+ (i * 0x400) + 0xc)
+#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE 0x80000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE_S 31
+#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR 0x40000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR_S 30
+#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR 0x20000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR_S 29
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR 0x1E000000
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR_S 25
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR 0x00078000
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR_S 15
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR 0x01F80000
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR_S 19
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR 0x00007e00
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR_S 9
+#define AR_PHY_65NM_RXRF_AGC_AGC_OUT 0x00000004
+#define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S 2
+
#endif /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
index 1d8235e19f0f..f69d292bdc02 100644
--- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
@@ -211,6 +211,8 @@ static const u32 ar9340_1p0_radio_core_40M[][2] = {
{0x0001609c, 0x02566f3a},
{0x000160ac, 0xa4647c00},
{0x000160b0, 0x01885f5a},
+ {0x00008244, 0x0010f400},
+ {0x0000824c, 0x0001e800},
};
#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble
@@ -1273,9 +1275,9 @@ static const u32 ar9340_1p0_mac_core[][2] = {
{0x000081f8, 0x00000000},
{0x000081fc, 0x00000000},
{0x00008240, 0x00100000},
- {0x00008244, 0x0010f424},
+ {0x00008244, 0x0010f3d7},
{0x00008248, 0x00000800},
- {0x0000824c, 0x0001e848},
+ {0x0000824c, 0x0001e7ae},
{0x00008250, 0x00000000},
{0x00008254, 0x00000000},
{0x00008258, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index 58f30f65c6b6..ccc42a71b436 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -78,7 +78,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index fb4497fc7a3d..a3710f3bb90c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -18,7 +18,7 @@
#ifndef INITVALS_9485_H
#define INITVALS_9485_H
-/* AR9485 1.0 */
+/* AR9485 1.1 */
#define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
@@ -31,6 +31,11 @@ static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
/* Addr allmodes */
+ {0x00009e00, 0x037216a0},
+ {0x00009e04, 0x00182020},
+ {0x00009e18, 0x00000000},
+ {0x00009e2c, 0x00004121},
+ {0x00009e44, 0x02282324},
{0x0000a000, 0x00060005},
{0x0000a004, 0x00810080},
{0x0000a008, 0x00830082},
@@ -164,6 +169,11 @@ static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
static const u32 ar9485Modes_high_power_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},
@@ -198,6 +208,22 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+ {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+ {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+ {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -234,9 +260,193 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
};
-#define ar9485Modes_high_ob_db_tx_gain_1_1 ar9485Modes_high_power_tx_gain_1_1
+static const u32 ar9485Modes_high_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, 0xffc63a84, 0xffc63a84},
+ {0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000},
+ {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},
+};
-#define ar9485Modes_low_ob_db_tx_gain_1_1 ar9485Modes_high_ob_db_tx_gain_1_1
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {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},
+};
#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
@@ -245,19 +455,19 @@ static const u32 ar9485_1_1[][2] = {
{0x0000a580, 0x00000000},
{0x0000a584, 0x00000000},
{0x0000a588, 0x00000000},
- {0x0000a58c, 0x00000000},
- {0x0000a590, 0x00000000},
- {0x0000a594, 0x00000000},
- {0x0000a598, 0x00000000},
- {0x0000a59c, 0x00000000},
- {0x0000a5a0, 0x00000000},
- {0x0000a5a4, 0x00000000},
- {0x0000a5a8, 0x00000000},
- {0x0000a5ac, 0x00000000},
- {0x0000a5b0, 0x00000000},
- {0x0000a5b4, 0x00000000},
- {0x0000a5b8, 0x00000000},
- {0x0000a5bc, 0x00000000},
+ {0x0000a58c, 0x01804000},
+ {0x0000a590, 0x02808a02},
+ {0x0000a594, 0x0340ca02},
+ {0x0000a598, 0x0340cd03},
+ {0x0000a59c, 0x0340cd03},
+ {0x0000a5a0, 0x06415304},
+ {0x0000a5a4, 0x04c11905},
+ {0x0000a5a8, 0x06415905},
+ {0x0000a5ac, 0x06415905},
+ {0x0000a5b0, 0x06415905},
+ {0x0000a5b4, 0x06415905},
+ {0x0000a5b8, 0x06415905},
+ {0x0000a5bc, 0x06415905},
};
static const u32 ar9485_1_1_radio_core[][2] = {
@@ -340,7 +550,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
{0x00009880, 0x201fff00},
{0x00009884, 0x00001042},
{0x000098a4, 0x00200400},
- {0x000098b0, 0x52440bbe},
+ {0x000098b0, 0x32840bbe},
{0x000098d0, 0x004b6a8e},
{0x000098d4, 0x00000820},
{0x000098dc, 0x00000000},
@@ -362,7 +572,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
{0x00009d18, 0x00000000},
{0x00009d1c, 0x00000000},
{0x00009e08, 0x0038233c},
- {0x00009e24, 0x9927b515},
+ {0x00009e24, 0x992bb515},
{0x00009e28, 0x12ef0200},
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
@@ -427,7 +637,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
{0x0000a408, 0x0e79e5c6},
{0x0000a40c, 0x00820820},
{0x0000a414, 0x1ce739cf},
- {0x0000a418, 0x2d0019ce},
+ {0x0000a418, 0x2d0021ce},
{0x0000a41c, 0x1ce739ce},
{0x0000a420, 0x000001ce},
{0x0000a424, 0x1ce739ce},
@@ -443,8 +653,8 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
{0x0000a44c, 0x00000001},
{0x0000a450, 0x00010000},
{0x0000a5c4, 0xbfad9d74},
- {0x0000a5c8, 0x0048060a},
- {0x0000a5cc, 0x00000637},
+ {0x0000a5c8, 0x00480605},
+ {0x0000a5cc, 0x00002e37},
{0x0000a760, 0x03020100},
{0x0000a764, 0x09080504},
{0x0000a768, 0x0d0c0b0a},
@@ -464,17 +674,22 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
static const u32 ar9485_common_rx_gain_1_1[][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},
+ {0x00009e00, 0x03721b20},
+ {0x00009e04, 0x00082020},
+ {0x00009e18, 0x0300501e},
+ {0x00009e2c, 0x00002e21},
+ {0x00009e44, 0x02182324},
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
{0x0000a02c, 0x03850384},
{0x0000a030, 0x03890388},
{0x0000a034, 0x038b038a},
@@ -496,15 +711,15 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
{0x0000a074, 0x00000000},
{0x0000a078, 0x00000000},
{0x0000a07c, 0x00000000},
- {0x0000a080, 0x28282828},
- {0x0000a084, 0x28282828},
- {0x0000a088, 0x28282828},
- {0x0000a08c, 0x28282828},
- {0x0000a090, 0x28282828},
- {0x0000a094, 0x21212128},
- {0x0000a098, 0x171c1c1c},
- {0x0000a09c, 0x02020212},
- {0x0000a0a0, 0x00000202},
+ {0x0000a080, 0x18181818},
+ {0x0000a084, 0x18181818},
+ {0x0000a088, 0x18181818},
+ {0x0000a08c, 0x18181818},
+ {0x0000a090, 0x18181818},
+ {0x0000a094, 0x18181818},
+ {0x0000a098, 0x17181818},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
{0x0000a0a4, 0x00000000},
{0x0000a0a8, 0x00000000},
{0x0000a0ac, 0x00000000},
@@ -512,22 +727,22 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
{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},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
{0x0000a100, 0x66006601},
{0x0000a104, 0x661e661f},
{0x0000a108, 0x7703661d},
@@ -636,17 +851,12 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
- {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
- {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
- {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
- {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
@@ -850,4 +1060,6 @@ static const u32 ar9485_1_1_mac_core[][2] = {
{0x000083d0, 0x000301ff},
};
+#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+
#endif /* INITVALS_9485_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
index 843e79f67ff2..0c2ac0c6dc89 100644
--- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
@@ -768,9 +768,9 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
{0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
-static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = {
+static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x18212ede},
+ {0x00018c00, 0x18213ede},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0003780c},
};
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index dfe6a4707fd2..86e26a19efda 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -129,10 +129,10 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_TXMAXTRY 13
#define TID_TO_WME_AC(_tid) \
- ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
- (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
- (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
- WME_AC_VO)
+ ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \
+ IEEE80211_AC_VO)
#define ATH_AGGR_DELIM_SZ 4
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
@@ -259,19 +259,21 @@ struct ath_atx_tid {
};
struct ath_node {
-#ifdef CONFIG_ATH9K_DEBUGFS
- struct list_head list; /* for sc->nodes */
-#endif
+ struct ath_softc *sc;
struct ieee80211_sta *sta; /* station struct we're part of */
struct ieee80211_vif *vif; /* interface with which we're associated */
- struct ath_atx_tid tid[WME_NUM_TID];
- struct ath_atx_ac ac[WME_NUM_AC];
+ struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
+ struct ath_atx_ac ac[IEEE80211_NUM_ACS];
int ps_key;
u16 maxampdu;
u8 mpdudensity;
bool sleeping;
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+ struct dentry *node_stat;
+#endif
};
#define AGGR_CLEANUP BIT(1)
@@ -299,9 +301,9 @@ struct ath_tx {
struct list_head txbuf;
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma txdma;
- struct ath_txq *txq_map[WME_NUM_AC];
- u32 txq_max_pending[WME_NUM_AC];
- u16 max_aggr_framelen[WME_NUM_AC][4][32];
+ struct ath_txq *txq_map[IEEE80211_NUM_ACS];
+ u32 txq_max_pending[IEEE80211_NUM_ACS];
+ u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
};
struct ath_rx_edma {
@@ -437,6 +439,7 @@ void ath9k_set_beacon(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
+#define ATH_ANI_MAX_SKIP_COUNT 10
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
@@ -460,6 +463,12 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
/* BTCOEX */
/**********/
+#define ATH_DUMP_BTCOEX(_s, _val) \
+ do { \
+ len += snprintf(buf + len, size - len, \
+ "%20s : %10d\n", _s, (_val)); \
+ } while (0)
+
enum bt_op_flags {
BT_OP_PRIORITY_DETECTED,
BT_OP_SCAN,
@@ -478,8 +487,10 @@ struct ath_btcoex {
u32 btscan_no_stomp; /* in usec */
u32 duty_cycle;
u32 bt_wait_time;
+ int rssi_count;
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
struct ath_mci_profile mci;
+ u8 stomp_audio;
};
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
@@ -492,6 +503,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
+int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size);
#else
static inline int ath9k_init_btcoex(struct ath_softc *sc)
{
@@ -518,6 +530,10 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
{
}
+static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+ return 0;
+}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
struct ath9k_wow_pattern {
@@ -642,6 +658,7 @@ enum sc_op_flags {
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
#define PS_WAIT_FOR_TX_ACK BIT(3)
#define PS_BEACON_SYNC BIT(4)
+#define PS_WAIT_FOR_ANI BIT(5)
struct ath_rate_table;
@@ -708,9 +725,6 @@ struct ath_softc {
#ifdef CONFIG_ATH9K_DEBUGFS
struct ath9k_debug debug;
- spinlock_t nodes_lock;
- struct list_head nodes; /* basically, stations */
- unsigned int tx_complete_poll_work_seen;
#endif
struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 1b48414dca95..531fffd801a3 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -46,7 +46,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc)
qi.tqi_cwmax = 0;
} else {
/* Adhoc mode; important thing is to use 2x cwmin. */
- txq = sc->tx.txq_map[WME_AC_BE];
+ txq = sc->tx.txq_map[IEEE80211_AC_BE];
ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
qi.tqi_aifs = qi_be.tqi_aifs;
if (ah->slottime == ATH9K_SLOT_TIME_20)
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 419e9a3f2fed..9963b0bf9f72 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -49,6 +49,7 @@ static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX]
{ 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
{ 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
{ 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
+ { 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff }, /* STOMP_AUDIO */
};
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
@@ -195,7 +196,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
ah->btcoex_hw.mci.need_flush_btinfo = false;
ah->btcoex_hw.mci.wlan_cal_seq = 0;
ah->btcoex_hw.mci.wlan_cal_done = 0;
- ah->btcoex_hw.mci.config = 0x2201;
+ ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1;
}
EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci);
@@ -218,27 +219,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
enum ath_stomp_type stomp_type)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+ u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */
+ bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]);
+ const u32 *weight = ar9003_wlan_weights[stomp_type];
+ int i;
- if (AR_SREV_9300_20_OR_LATER(ah)) {
- const u32 *weight = ar9003_wlan_weights[stomp_type];
- int i;
-
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
- if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
- btcoex_hw->mci.stomp_ftp)
- stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
- weight = mci_wlan_weights[stomp_type];
- }
-
- for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
- btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
- btcoex_hw->wlan_weight[i] = weight[i];
- }
- } else {
+ if (!AR_SREV_9300_20_OR_LATER(ah)) {
btcoex_hw->bt_coex_weights =
SM(bt_weight, AR_BTCOEX_BT_WGHT) |
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
+ return;
+ }
+
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ enum ath_stomp_type stype =
+ ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
+ btcoex_hw->mci.stomp_ftp) ?
+ ATH_BTCOEX_STOMP_LOW_FTP : stomp_type;
+ weight = mci_wlan_weights[stype];
}
+
+ for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
+ btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
+ btcoex_hw->wlan_weight[i] = weight[i];
+ if (concur_tx && i) {
+ btcoex_hw->wlan_weight[i] &=
+ ~(0xff << txprio_shift[i-1]);
+ btcoex_hw->wlan_weight[i] |=
+ (btcoex_hw->tx_prio[stomp_type] <<
+ txprio_shift[i-1]);
+ }
+ }
+ /* Last WLAN weight has to be adjusted wrt tx priority */
+ if (concur_tx) {
+ btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
+ btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
+ << txprio_shift[i-1]);
+ }
+
}
EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
@@ -385,3 +404,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
}
}
EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
+
+void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio)
+{
+ struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+ int i;
+
+ for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
+ btcoex->tx_prio[i] = stomp_txprio[i];
+}
+EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio);
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 385197ad79b0..6de26ea5d5fa 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -39,6 +39,9 @@
#define ATH_BTCOEX_RX_WAIT_TIME 100
#define ATH_BTCOEX_STOMP_FTP_THRESH 5
+#define ATH_BTCOEX_HT20_MAX_TXPOWER 0x14
+#define ATH_BTCOEX_HT40_MAX_TXPOWER 0x10
+
#define AR9300_NUM_BT_WEIGHTS 4
#define AR9300_NUM_WLAN_WEIGHTS 4
/* Defines the BT AR_BT_COEX_WGHT used */
@@ -47,6 +50,7 @@ enum ath_stomp_type {
ATH_BTCOEX_STOMP_LOW,
ATH_BTCOEX_STOMP_NONE,
ATH_BTCOEX_STOMP_LOW_FTP,
+ ATH_BTCOEX_STOMP_AUDIO,
ATH_BTCOEX_STOMP_MAX
};
@@ -84,6 +88,8 @@ struct ath9k_hw_mci {
u8 bt_ver_minor;
u8 bt_state;
u8 stomp_ftp;
+ bool concur_tx;
+ u32 last_recovery;
};
struct ath_btcoex_hw {
@@ -98,6 +104,7 @@ struct ath_btcoex_hw {
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
+ u8 tx_prio[ATH_BTCOEX_STOMP_MAX];
};
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
@@ -112,5 +119,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
void ath9k_hw_btcoex_disable(struct ath_hw *ah);
void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
enum ath_stomp_type stomp_type);
+void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio);
#endif
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index e5cceb077574..1e8508530e98 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
if (chan && chan->noisefloor) {
s8 delta = chan->noisefloor -
+ ATH9K_NF_CAL_NOISE_THRESH -
ath9k_hw_get_default_nf(ah, chan);
if (delta > 0)
noise += delta;
@@ -410,6 +411,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
ah->caldata->channel = chan->channel;
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+ ah->caldata->chanmode = chan->chanmode;
h = ah->caldata->nfCalHist;
default_nf = ath9k_hw_get_default_nf(ah, chan);
for (i = 0; i < NUM_NF_READINGS; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 1060c19a5012..60dcb6c22db9 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -21,6 +21,9 @@
#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
+/* Internal noise floor can vary by about 6db depending on the frequency */
+#define ATH9K_NF_CAL_NOISE_THRESH 6
+
#define NUM_NF_READINGS 6
#define ATH9K_NF_CAL_HIST_MAX 5
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index ad14fecc76c6..5f845beeb18b 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -23,18 +23,10 @@
/* Common header for Atheros 802.11n base driver cores */
-#define WME_NUM_TID 16
#define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
-/* These must match mac80211 skb queue mapping numbers */
-#define WME_AC_VO 0
-#define WME_AC_VI 1
-#define WME_AC_BE 2
-#define WME_AC_BK 3
-#define WME_NUM_AC 4
-
#define ATH_RSSI_DUMMY_MARKER 0x127
#define ATH_RSSI_LPF_LEN 10
#define RSSI_LPF_THRESHOLD -20
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 6727b566d294..13ff9edc2401 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -512,62 +512,19 @@ static const struct file_operations fops_interrupt = {
.llseek = default_llseek,
};
-#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
-#define PR(str, elem) \
- do { \
- len += snprintf(buf + len, size - len, \
- "%s%13u%11u%10u%10u\n", str, \
- sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
- sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
- if (len >= size) \
- goto done; \
-} while(0)
-
-#define PRX(str, elem) \
-do { \
- len += snprintf(buf + len, size - len, \
- "%s%13u%11u%10u%10u\n", str, \
- (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \
- (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \
- (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \
- (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \
- if (len >= size) \
- goto done; \
-} while(0)
-
-#define PRQLE(str, elem) \
-do { \
- len += snprintf(buf + len, size - len, \
- "%s%13i%11i%10i%10i\n", str, \
- list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \
- list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \
- list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \
- list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \
- if (len >= size) \
- goto done; \
-} while (0)
-
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *buf;
- unsigned int len = 0, size = 8000;
- int i;
+ unsigned int len = 0, size = 2048;
ssize_t retval = 0;
- char tmp[32];
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x"
- " poll-work-seen: %u\n"
- "%30s %10s%10s%10s\n\n",
- ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
- sc->tx_complete_poll_work_seen,
+ len += sprintf(buf, "%30s %10s%10s%10s\n\n",
"BE", "BK", "VI", "VO");
PR("MPDUs Queued: ", queued);
@@ -587,62 +544,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("DELIM Underrun: ", delim_underrun);
PR("TX-Pkts-All: ", tx_pkts_all);
PR("TX-Bytes-All: ", tx_bytes_all);
- PR("hw-put-tx-buf: ", puttxbuf);
- PR("hw-tx-start: ", txstart);
- PR("hw-tx-proc-desc: ", txprocdesc);
+ PR("HW-put-tx-buf: ", puttxbuf);
+ PR("HW-tx-start: ", txstart);
+ PR("HW-tx-proc-desc: ", txprocdesc);
PR("TX-Failed: ", txfailed);
- len += snprintf(buf + len, size - len,
- "%s%11p%11p%10p%10p\n", "txq-memory-address:",
- sc->tx.txq_map[WME_AC_BE],
- sc->tx.txq_map[WME_AC_BK],
- sc->tx.txq_map[WME_AC_VI],
- sc->tx.txq_map[WME_AC_VO]);
- if (len >= size)
- goto done;
-
- PRX("axq-qnum: ", axq_qnum);
- PRX("axq-depth: ", axq_depth);
- PRX("axq-ampdu_depth: ", axq_ampdu_depth);
- PRX("axq-stopped ", stopped);
- PRX("tx-in-progress ", axq_tx_inprogress);
- PRX("pending-frames ", pending_frames);
- PRX("txq_headidx: ", txq_headidx);
- PRX("txq_tailidx: ", txq_headidx);
-
- PRQLE("axq_q empty: ", axq_q);
- PRQLE("axq_acq empty: ", axq_acq);
- for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
- snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
- PRQLE(tmp, txq_fifo[i]);
- }
-
- /* Print out more detailed queue-info */
- for (i = 0; i <= WME_AC_BK; i++) {
- struct ath_txq *txq = &(sc->tx.txq[i]);
- struct ath_atx_ac *ac;
- struct ath_atx_tid *tid;
- if (len >= size)
- goto done;
- spin_lock_bh(&txq->axq_lock);
- if (!list_empty(&txq->axq_acq)) {
- ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
- list);
- len += snprintf(buf + len, size - len,
- "txq[%i] first-ac: %p sched: %i\n",
- i, ac, ac->sched);
- if (list_empty(&ac->tid_q) || (len >= size))
- goto done_for;
- tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
- list);
- len += snprintf(buf + len, size - len,
- " first-tid: %p sched: %i paused: %i\n",
- tid, tid->sched, tid->paused);
- }
- done_for:
- spin_unlock_bh(&txq->axq_lock);
- }
-done:
if (len > size)
len = size;
@@ -652,62 +558,41 @@ done:
return retval;
}
-static ssize_t read_file_stations(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
+static ssize_t read_file_queues(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
+ struct ath_txq *txq;
char *buf;
- unsigned int len = 0, size = 64000;
- struct ath_node *an = NULL;
+ unsigned int len = 0, size = 1024;
ssize_t retval = 0;
- int q;
+ int i;
+ char *qname[4] = {"VO", "VI", "BE", "BK"};
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- len += snprintf(buf + len, size - len,
- "Stations:\n"
- " tid: addr sched paused buf_q-empty an ac baw\n"
- " ac: addr sched tid_q-empty txq\n");
-
- spin_lock(&sc->nodes_lock);
- list_for_each_entry(an, &sc->nodes, list) {
- unsigned short ma = an->maxampdu;
- if (ma == 0)
- ma = 65535; /* see ath_lookup_rate */
- len += snprintf(buf + len, size - len,
- "iface: %pM sta: %pM max-ampdu: %hu mpdu-density: %uus\n",
- an->vif->addr, an->sta->addr, ma,
- (unsigned int)(an->mpdudensity));
- if (len >= size)
- goto done;
-
- for (q = 0; q < WME_NUM_TID; q++) {
- struct ath_atx_tid *tid = &(an->tid[q]);
- len += snprintf(buf + len, size - len,
- " tid: %p %s %s %i %p %p %hu\n",
- tid, tid->sched ? "sched" : "idle",
- tid->paused ? "paused" : "running",
- skb_queue_empty(&tid->buf_q),
- tid->an, tid->ac, tid->baw_size);
- if (len >= size)
- goto done;
- }
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ txq = sc->tx.txq_map[i];
+ len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
- for (q = 0; q < WME_NUM_AC; q++) {
- struct ath_atx_ac *ac = &(an->ac[q]);
- len += snprintf(buf + len, size - len,
- " ac: %p %s %i %p\n",
- ac, ac->sched ? "sched" : "idle",
- list_empty(&ac->tid_q), ac->txq);
- if (len >= size)
- goto done;
- }
+ ath_txq_lock(sc, txq);
+
+ len += snprintf(buf + len, size - len, "%s: %d ",
+ "qnum", txq->axq_qnum);
+ len += snprintf(buf + len, size - len, "%s: %2d ",
+ "qdepth", txq->axq_depth);
+ len += snprintf(buf + len, size - len, "%s: %2d ",
+ "ampdu-depth", txq->axq_ampdu_depth);
+ len += snprintf(buf + len, size - len, "%s: %3d ",
+ "pending", txq->pending_frames);
+ len += snprintf(buf + len, size - len, "%s: %d\n",
+ "stopped", txq->stopped);
+
+ ath_txq_unlock(sc, txq);
}
-done:
- spin_unlock(&sc->nodes_lock);
if (len > size)
len = size;
@@ -837,6 +722,9 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"%17s: %2d\n", "PLL RX Hang",
sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "MCI Reset",
+ sc->debug.stats.reset[RESET_TYPE_MCI]);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -919,8 +807,8 @@ static const struct file_operations fops_xmit = {
.llseek = default_llseek,
};
-static const struct file_operations fops_stations = {
- .read = read_file_stations,
+static const struct file_operations fops_queues = {
+ .read = read_file_queues,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
@@ -1586,6 +1474,250 @@ static const struct file_operations fops_samps = {
#endif
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ u32 len = 0, size = 1500;
+ char *buf;
+ size_t retval;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ if (!sc->sc_ah->common.btcoex_enabled) {
+ len = snprintf(buf, size, "%s\n",
+ "BTCOEX is disabled");
+ goto exit;
+ }
+
+ len = ath9k_dump_btcoex(sc, buf, size);
+exit:
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_btcoex = {
+ .read = read_file_btcoex,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+#endif
+
+static ssize_t read_file_node_stat(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_node *an = file->private_data;
+ struct ath_softc *sc = an->sc;
+ struct ath_atx_tid *tid;
+ struct ath_atx_ac *ac;
+ struct ath_txq *txq;
+ u32 len = 0, size = 4096;
+ char *buf;
+ size_t retval;
+ int tidno, acno;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ if (!an->sta->ht_cap.ht_supported) {
+ len = snprintf(buf, size, "%s\n",
+ "HT not supported");
+ goto exit;
+ }
+
+ len = snprintf(buf, size, "Max-AMPDU: %d\n",
+ an->maxampdu);
+ len += snprintf(buf + len, size - len, "MPDU Density: %d\n\n",
+ an->mpdudensity);
+
+ len += snprintf(buf + len, size - len,
+ "%2s%7s\n", "AC", "SCHED");
+
+ for (acno = 0, ac = &an->ac[acno];
+ acno < IEEE80211_NUM_ACS; acno++, ac++) {
+ txq = ac->txq;
+ ath_txq_lock(sc, txq);
+ len += snprintf(buf + len, size - len,
+ "%2d%7d\n",
+ acno, ac->sched);
+ ath_txq_unlock(sc, txq);
+ }
+
+ len += snprintf(buf + len, size - len,
+ "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
+ "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
+ "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
+
+ for (tidno = 0, tid = &an->tid[tidno];
+ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+ txq = tid->ac->txq;
+ ath_txq_lock(sc, txq);
+ len += snprintf(buf + len, size - len,
+ "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
+ tid->tidno, tid->seq_start, tid->seq_next,
+ tid->baw_size, tid->baw_head, tid->baw_tail,
+ tid->bar_index, tid->sched, tid->paused);
+ ath_txq_unlock(sc, txq);
+ }
+exit:
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_node_stat = {
+ .read = read_file_node_stat,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir)
+{
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+ an->node_stat = debugfs_create_file("node_stat", S_IRUGO,
+ dir, an, &fops_node_stat);
+}
+
+void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir)
+{
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+ debugfs_remove(an->node_stat);
+}
+
+/* Ethtool support for get-stats */
+
+#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
+static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
+ "tx_pkts_nic",
+ "tx_bytes_nic",
+ "rx_pkts_nic",
+ "rx_bytes_nic",
+ AMKSTR(d_tx_pkts),
+ AMKSTR(d_tx_bytes),
+ AMKSTR(d_tx_mpdus_queued),
+ AMKSTR(d_tx_mpdus_completed),
+ AMKSTR(d_tx_mpdu_xretries),
+ AMKSTR(d_tx_aggregates),
+ AMKSTR(d_tx_ampdus_queued_hw),
+ AMKSTR(d_tx_ampdus_queued_sw),
+ AMKSTR(d_tx_ampdus_completed),
+ AMKSTR(d_tx_ampdu_retries),
+ AMKSTR(d_tx_ampdu_xretries),
+ AMKSTR(d_tx_fifo_underrun),
+ AMKSTR(d_tx_op_exceeded),
+ AMKSTR(d_tx_timer_expiry),
+ AMKSTR(d_tx_desc_cfg_err),
+ AMKSTR(d_tx_data_underrun),
+ AMKSTR(d_tx_delim_underrun),
+ "d_rx_decrypt_crc_err",
+ "d_rx_phy_err",
+ "d_rx_mic_err",
+ "d_rx_pre_delim_crc_err",
+ "d_rx_post_delim_crc_err",
+ "d_rx_decrypt_busy_err",
+
+ "d_rx_phyerr_radar",
+ "d_rx_phyerr_ofdm_timing",
+ "d_rx_phyerr_cck_timing",
+
+};
+#define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats)
+
+void ath9k_get_et_strings(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u32 sset, u8 *data)
+{
+ if (sset == ETH_SS_STATS)
+ memcpy(data, *ath9k_gstrings_stats,
+ sizeof(ath9k_gstrings_stats));
+}
+
+int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, int sset)
+{
+ if (sset == ETH_SS_STATS)
+ return ATH9K_SSTATS_LEN;
+ return 0;
+}
+
+#define AWDATA(elem) \
+ do { \
+ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \
+ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \
+ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \
+ data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \
+ } while (0)
+
+#define AWDATA_RX(elem) \
+ do { \
+ data[i++] = sc->debug.stats.rxstats.elem; \
+ } while (0)
+
+void ath9k_get_et_stats(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct ath_softc *sc = hw->priv;
+ int i = 0;
+
+ data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all);
+ data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all +
+ sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all);
+ AWDATA_RX(rx_pkts_all);
+ AWDATA_RX(rx_bytes_all);
+
+ AWDATA(tx_pkts_all);
+ AWDATA(tx_bytes_all);
+ AWDATA(queued);
+ AWDATA(completed);
+ AWDATA(xretries);
+ AWDATA(a_aggr);
+ AWDATA(a_queued_hw);
+ AWDATA(a_queued_sw);
+ AWDATA(a_completed);
+ AWDATA(a_retries);
+ AWDATA(a_xretries);
+ AWDATA(fifo_underrun);
+ AWDATA(xtxop);
+ AWDATA(timer_exp);
+ AWDATA(desc_cfg_err);
+ AWDATA(data_underrun);
+ AWDATA(delim_underrun);
+
+ AWDATA_RX(decrypt_crc_err);
+ AWDATA_RX(phy_err);
+ AWDATA_RX(mic_err);
+ AWDATA_RX(pre_delim_crc_err);
+ AWDATA_RX(post_delim_crc_err);
+ AWDATA_RX(decrypt_busy_err);
+
+ AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]);
+ AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]);
+ AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]);
+
+ WARN_ON(i != ATH9K_SSTATS_LEN);
+}
+
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1609,16 +1741,16 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_interrupt);
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_xmit);
+ debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_queues);
debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[WME_AC_BK]);
+ &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[WME_AC_BE]);
+ &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[WME_AC_VI]);
+ &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
- &sc->tx.txq_max_pending[WME_AC_VO]);
- debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_stations);
+ &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_misc);
debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
@@ -1658,6 +1790,9 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_ant_diversity);
-
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+ debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_btcoex);
+#endif
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 2ed9785a38fa..375c3b46411e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -41,6 +41,7 @@ enum ath_reset_type {
RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG,
RESET_TYPE_BEACON_STUCK,
+ RESET_TYPE_MCI,
__RESET_TYPE_MAX
};
@@ -178,6 +179,21 @@ struct ath_tx_stats {
u32 txfailed;
};
+/*
+ * Various utility macros to print TX/Queue counters.
+ */
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
+#define TXSTATS sc->debug.stats.txstats
+#define PR(str, elem) \
+ do { \
+ len += snprintf(buf + len, size - len, \
+ "%s%13u%11u%10u%10u\n", str, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
+ } while(0)
+
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
/**
@@ -291,7 +307,22 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq,
unsigned int flags);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
-
+int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, int sset);
+void ath9k_get_et_stats(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ethtool_stats *stats, u64 *data);
+void ath9k_get_et_strings(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u32 sset, u8 *data);
+void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
+void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
#else
#define RX_STAT_INC(c) /* NOP */
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index ea2a6cf7ef23..24877b00cbf4 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -42,10 +42,15 @@ struct radar_types {
#define MIN_PPB_THRESH 50
#define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100)
#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
+/* percentage of pulse width tolerance */
+#define WIDTH_TOLERANCE 5
+#define WIDTH_LOWER(X) ((X*(100-WIDTH_TOLERANCE)+50)/100)
+#define WIDTH_UPPER(X) ((X*(100+WIDTH_TOLERANCE)+50)/100)
#define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \
{ \
- ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE), \
+ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \
+ (PRF2PRI(PMAX) - PRI_TOLERANCE), \
(PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF, \
PPB_THRESH(PPB), PRI_TOLERANCE, \
}
@@ -274,7 +279,7 @@ static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
static struct dfs_pattern_detector default_dpd = {
.exit = dpd_exit,
- .set_domain = dpd_set_domain,
+ .set_dfs_domain = dpd_set_domain,
.add_pulse = dpd_add_pulse,
.region = NL80211_DFS_UNSET,
};
@@ -291,10 +296,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
*dpd = default_dpd;
INIT_LIST_HEAD(&dpd->channel_detectors);
- if (dpd->set_domain(dpd, region))
+ if (dpd->set_dfs_domain(dpd, region))
return dpd;
pr_err("Could not set DFS domain to %d. ", region);
+ kfree(dpd);
return NULL;
}
EXPORT_SYMBOL(dfs_pattern_detector_init);
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
index fd0328a30995..cda52f39f28a 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
@@ -62,7 +62,7 @@ struct radar_detector_specs {
/**
* struct dfs_pattern_detector - DFS pattern detector
* @exit(): destructor
- * @set_domain(): set DFS domain, resets detector lines upon domain changes
+ * @set_dfs_domain(): set DFS domain, resets detector lines upon domain changes
* @add_pulse(): add radar pulse to detector, returns true on detection
* @region: active DFS region, NL80211_DFS_UNSET until set
* @num_radar_types: number of different radar types
@@ -72,7 +72,7 @@ struct radar_detector_specs {
*/
struct dfs_pattern_detector {
void (*exit)(struct dfs_pattern_detector *dpd);
- bool (*set_domain)(struct dfs_pattern_detector *dpd,
+ bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd,
enum nl80211_dfs_regions region);
bool (*add_pulse)(struct dfs_pattern_detector *dpd,
struct pulse_event *pe);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index 0512397a293c..971d770722cf 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -113,9 +113,34 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
}
}
-bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
+static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off,
+ u16 *data)
{
- return common->bus_ops->eeprom_read(common, off, data);
+ u16 *blob_data;
+
+ if (off * sizeof(u16) > ah->eeprom_blob->size)
+ return false;
+
+ blob_data = (u16 *)ah->eeprom_blob->data;
+ *data = blob_data[off];
+ return true;
+}
+
+bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool ret;
+
+ if (ah->eeprom_blob)
+ ret = ath9k_hw_nvram_read_blob(ah, off, data);
+ else
+ ret = common->bus_ops->eeprom_read(common, off, data);
+
+ if (!ret)
+ ath_dbg(common, EEPROM,
+ "unable to read eeprom region at offset %u\n", off);
+
+ return ret;
}
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 319c651fa6c5..40d4f62d0f16 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -663,7 +663,7 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
int16_t targetRight);
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
u16 *indexL, u16 *indexR);
-bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
+bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
int eep_start_loc, int size);
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 7d075105a85d..c2bfd748eed8 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -32,16 +32,12 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
{
- struct ath_common *common = ath9k_hw_common(ah);
u16 *eep_data = (u16 *)&ah->eeprom.map4k;
int addr, eep_start_loc = 64;
for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
- if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
- ath_dbg(common, EEPROM,
- "Unable to read eeprom region\n");
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
return false;
- }
eep_data++;
}
@@ -196,7 +192,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
if (!ath9k_hw_use_flash(ah)) {
- if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index cd742fb944c2..3ae1f3df0637 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -33,18 +33,13 @@ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
{
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
- struct ath_common *common = ath9k_hw_common(ah);
u16 *eep_data;
int addr, eep_start_loc = AR9287_EEP_START_LOC;
eep_data = (u16 *)eep;
for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
- if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
- eep_data)) {
- ath_dbg(common, EEPROM,
- "Unable to read eeprom region\n");
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
return false;
- }
eep_data++;
}
@@ -190,7 +185,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
if (!ath9k_hw_use_flash(ah)) {
- if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index a8ac30a00720..1c25368b3836 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -91,17 +91,13 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
{
- struct ath_common *common = ath9k_hw_common(ah);
u16 *eep_data = (u16 *)&ah->eeprom.def;
int addr, ar5416_eep_start_loc = 0x100;
for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
- if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
- eep_data)) {
- ath_err(ath9k_hw_common(ah),
- "Unable to read eeprom region\n");
+ if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+ eep_data))
return false;
- }
eep_data++;
}
return true;
@@ -271,7 +267,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
bool need_swap = false;
int i, addr, size;
- if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
}
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index d9ed141a053e..4b412aaf4f36 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -187,6 +187,24 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
}
}
+static void ath_mci_ftp_adjust(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_mci_profile *mci = &btcoex->mci;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
+ if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
+ (mci->num_pan || mci->num_other_acl))
+ ah->btcoex_hw.mci.stomp_ftp =
+ (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
+ else
+ ah->btcoex_hw.mci.stomp_ftp = false;
+ btcoex->bt_wait_time = 0;
+ sc->rx.num_pkts = 0;
+ }
+}
+
/*
* This is the master bt coex timer which runs for every
* 45ms, bt traffic will be given priority during 55% of this
@@ -197,41 +215,46 @@ static void ath_btcoex_period_timer(unsigned long data)
struct ath_softc *sc = (struct ath_softc *) data;
struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex;
- struct ath_mci_profile *mci = &btcoex->mci;
+ enum ath_stomp_type stomp_type;
u32 timer_period;
- bool is_btscan;
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
+ btcoex->bt_wait_time += btcoex->btcoex_period;
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
goto skip_hw_wakeup;
}
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ ath9k_mci_update_rssi(sc);
+
ath9k_ps_wakeup(sc);
+
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
ath_detect_bt_priority(sc);
- is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
- btcoex->bt_wait_time += btcoex->btcoex_period;
- if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
- if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
- (mci->num_pan || mci->num_other_acl))
- ah->btcoex_hw.mci.stomp_ftp =
- (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
- else
- ah->btcoex_hw.mci.stomp_ftp = false;
- btcoex->bt_wait_time = 0;
- sc->rx.num_pkts = 0;
- }
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+ ath_mci_ftp_adjust(sc);
spin_lock_bh(&btcoex->btcoex_lock);
- ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
- btcoex->bt_stomp_type);
+ stomp_type = btcoex->bt_stomp_type;
+ timer_period = btcoex->btcoex_no_stomp;
+
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
+ if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
+ stomp_type = ATH_BTCOEX_STOMP_ALL;
+ timer_period = btcoex->btscan_no_stomp;
+ }
+ } else if (btcoex->stomp_audio >= 5) {
+ stomp_type = ATH_BTCOEX_STOMP_AUDIO;
+ btcoex->stomp_audio = 0;
+ }
+ ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
ath9k_hw_btcoex_enable(ah);
+
spin_unlock_bh(&btcoex->btcoex_lock);
/*
@@ -243,17 +266,16 @@ static void ath_btcoex_period_timer(unsigned long data)
if (btcoex->hw_timer_enabled)
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
- timer_period = is_btscan ? btcoex->btscan_no_stomp :
- btcoex->btcoex_no_stomp;
ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
timer_period * 10);
btcoex->hw_timer_enabled = true;
}
ath9k_ps_restore(sc);
+
skip_hw_wakeup:
- timer_period = btcoex->btcoex_period;
- mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
+ mod_timer(&btcoex->period_timer,
+ jiffies + msecs_to_jiffies(btcoex->btcoex_period));
}
/*
@@ -273,9 +295,10 @@ static void ath_btcoex_no_stomp_timer(void *arg)
spin_lock_bh(&btcoex->btcoex_lock);
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
- test_bit(BT_OP_SCAN, &btcoex->op_flags))
+ (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
+ test_bit(BT_OP_SCAN, &btcoex->op_flags)))
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
- else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+ else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
ath9k_hw_btcoex_enable(ah);
@@ -451,7 +474,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
r = ath_init_btcoex_timer(sc);
if (r)
return -1;
- txq = sc->tx.txq_map[WME_AC_BE];
+ txq = sc->tx.txq_map[IEEE80211_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
if (ath9k_hw_mci_is_enabled(ah)) {
@@ -474,4 +497,71 @@ int ath9k_init_btcoex(struct ath_softc *sc)
return 0;
}
+static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_mci_profile *mci = &btcoex->mci;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ u32 len = 0;
+ int i;
+
+ ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci));
+ ATH_DUMP_BTCOEX("MGMT", mci->num_mgmt);
+ ATH_DUMP_BTCOEX("SCO", mci->num_sco);
+ ATH_DUMP_BTCOEX("A2DP", mci->num_a2dp);
+ ATH_DUMP_BTCOEX("HID", mci->num_hid);
+ ATH_DUMP_BTCOEX("PAN", mci->num_pan);
+ ATH_DUMP_BTCOEX("ACL", mci->num_other_acl);
+ ATH_DUMP_BTCOEX("BDR", mci->num_bdr);
+ ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit);
+ ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
+ ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
+ ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
+ ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
+ ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
+ ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count);
+
+ len += snprintf(buf + len, size - len, "BT Weights: ");
+ for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+ len += snprintf(buf + len, size - len, "%08x ",
+ btcoex_hw->bt_weight[i]);
+ len += snprintf(buf + len, size - len, "\n");
+ len += snprintf(buf + len, size - len, "WLAN Weights: ");
+ for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+ len += snprintf(buf + len, size - len, "%08x ",
+ btcoex_hw->wlan_weight[i]);
+ len += snprintf(buf + len, size - len, "\n");
+ len += snprintf(buf + len, size - len, "Tx Priorities: ");
+ for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
+ len += snprintf(buf + len, size - len, "%08x ",
+ btcoex_hw->tx_prio[i]);
+
+ len += snprintf(buf + len, size - len, "\n");
+
+ return len;
+}
+
+static int ath9k_dump_legacy_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ u32 len = 0;
+
+ ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
+ ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
+ ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
+ ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
+
+ return len;
+}
+
+int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ return ath9k_dump_mci_btcoex(sc, buf, size);
+ else
+ return ath9k_dump_legacy_btcoex(sc, buf, size);
+}
+
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index b30596fcf73a..96bfb18078fa 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,7 +331,7 @@ struct ath_tx_stats {
u32 skb_success;
u32 skb_failed;
u32 cab_queued;
- u32 queue_stats[WME_NUM_AC];
+ u32 queue_stats[IEEE80211_NUM_ACS];
};
struct ath_rx_stats {
@@ -493,7 +493,7 @@ struct ath9k_htc_priv {
int beaconq;
int cabq;
- int hwq_map[WME_NUM_AC];
+ int hwq_map[IEEE80211_NUM_ACS];
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
struct ath_btcoex btcoex;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index f42d2eb6af99..d0ce1f5bba10 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -33,7 +33,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
qi.tqi_cwmin = 0;
qi.tqi_cwmax = 0;
} else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
- int qnum = priv->hwq_map[WME_AC_BE];
+ int qnum = priv->hwq_map[IEEE80211_AC_BE];
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
@@ -587,9 +587,9 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
(priv->num_sta_vif > 1) &&
(vif->type == NL80211_IFTYPE_STATION)) {
beacon_configured = false;
- ieee80211_iterate_active_interfaces_atomic(priv->hw,
- ath9k_htc_beacon_iter,
- &beacon_configured);
+ ieee80211_iterate_active_interfaces_atomic(
+ priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_htc_beacon_iter, &beacon_configured);
if (beacon_configured) {
ath_dbg(common, CONFIG,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 3035deb7a0cd..87110de577ef 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -218,16 +218,16 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "BE queued",
- priv->debug.tx_stats.queue_stats[WME_AC_BE]);
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "BK queued",
- priv->debug.tx_stats.queue_stats[WME_AC_BK]);
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "VI queued",
- priv->debug.tx_stats.queue_stats[WME_AC_VI]);
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "VO queued",
- priv->debug.tx_stats.queue_stats[WME_AC_VO]);
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
if (len > sizeof(buf))
len = sizeof(buf);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 0eacfc13c915..105582d6b714 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -207,7 +207,7 @@ void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
ath9k_hw_btcoex_init_3wire(priv->ah);
ath_htc_init_btcoex_work(priv);
- qnum = priv->hwq_map[WME_AC_BE];
+ qnum = priv->hwq_map[IEEE80211_AC_BE];
ath9k_hw_init_btcoex_hw(priv->ah, qnum);
break;
default:
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index d98255eb1b9a..05d5ba66cac3 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -549,20 +549,20 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
goto err;
}
- if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
+ if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) {
ath_err(common, "Unable to setup xmit queue for BE traffic\n");
goto err;
}
- if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
+ if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) {
ath_err(common, "Unable to setup xmit queue for BK traffic\n");
goto err;
}
- if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
+ if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) {
ath_err(common, "Unable to setup xmit queue for VI traffic\n");
goto err;
}
- if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
+ if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) {
ath_err(common, "Unable to setup xmit queue for VO traffic\n");
goto err;
}
@@ -694,6 +694,20 @@ err_hw:
return ret;
}
+static const struct ieee80211_iface_limit if_limits[] = {
+ { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) },
+ { .max = 2, .types = BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
+};
+
+static const struct ieee80211_iface_combination if_comb = {
+ .limits = if_limits,
+ .n_limits = ARRAY_SIZE(if_limits),
+ .max_interfaces = 2,
+ .num_different_channels = 1,
+};
+
static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw)
{
@@ -716,6 +730,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
+ hw->wiphy->iface_combinations = &if_comb;
+ hw->wiphy->n_iface_combinations = 1;
+
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ca78e33ca23e..9c07a8fa5134 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -127,8 +127,9 @@ static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
priv->rearm_ani = false;
priv->reconfig_beacon = false;
- ieee80211_iterate_active_interfaces_atomic(priv->hw,
- ath9k_htc_vif_iter, priv);
+ ieee80211_iterate_active_interfaces_atomic(
+ priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_htc_vif_iter, priv);
if (priv->rearm_ani)
ath9k_htc_start_ani(priv);
@@ -165,8 +166,9 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
- &iter_data);
+ ieee80211_iterate_active_interfaces_atomic(
+ priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_htc_bssid_iter, &iter_data);
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
ath_hw_setbssidmask(common);
@@ -1036,26 +1038,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
- mutex_unlock(&priv->mutex);
- return -ENOBUFS;
- }
-
- if (priv->num_ibss_vif ||
- (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
- ath_err(common, "IBSS coexistence with other modes is not allowed\n");
- mutex_unlock(&priv->mutex);
- return -ENOBUFS;
- }
-
- if (((vif->type == NL80211_IFTYPE_AP) ||
- (vif->type == NL80211_IFTYPE_ADHOC)) &&
- ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) {
- ath_err(common, "Max. number of beaconing interfaces reached\n");
- mutex_unlock(&priv->mutex);
- return -ENOBUFS;
- }
-
ath9k_htc_ps_wakeup(priv);
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
@@ -1164,8 +1146,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
*/
if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
priv->rearm_ani = false;
- ieee80211_iterate_active_interfaces_atomic(priv->hw,
- ath9k_htc_vif_iter, priv);
+ ieee80211_iterate_active_interfaces_atomic(
+ priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_htc_vif_iter, priv);
if (!priv->rearm_ani)
ath9k_htc_stop_ani(priv);
}
@@ -1366,7 +1349,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
struct ath9k_tx_queue_info qi;
int ret = 0, qnum;
- if (queue >= WME_NUM_AC)
+ if (queue >= IEEE80211_NUM_ACS)
return 0;
mutex_lock(&priv->mutex);
@@ -1393,7 +1376,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
}
if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
- (qnum == priv->hwq_map[WME_AC_BE]))
+ (qnum == priv->hwq_map[IEEE80211_AC_BE]))
ath9k_htc_beaconq_config(priv);
out:
ath9k_htc_ps_restore(priv);
@@ -1486,8 +1469,9 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
{
if (priv->num_sta_assoc_vif == 1) {
- ieee80211_iterate_active_interfaces_atomic(priv->hw,
- ath9k_htc_bss_iter, priv);
+ ieee80211_iterate_active_interfaces_atomic(
+ priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_htc_bss_iter, priv);
ath9k_htc_set_bssid(priv);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 06cdcb772d78..b6a5a08810b8 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -21,10 +21,10 @@
/******/
static const int subtype_txq_to_hwq[] = {
- [WME_AC_BE] = ATH_TXQ_AC_BE,
- [WME_AC_BK] = ATH_TXQ_AC_BK,
- [WME_AC_VI] = ATH_TXQ_AC_VI,
- [WME_AC_VO] = ATH_TXQ_AC_VO,
+ [IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
+ [IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
+ [IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
+ [IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
};
#define ATH9K_HTC_INIT_TXQ(subtype) do { \
@@ -41,15 +41,15 @@ int get_hw_qnum(u16 queue, int *hwq_map)
{
switch (queue) {
case 0:
- return hwq_map[WME_AC_VO];
+ return hwq_map[IEEE80211_AC_VO];
case 1:
- return hwq_map[WME_AC_VI];
+ return hwq_map[IEEE80211_AC_VI];
case 2:
- return hwq_map[WME_AC_BE];
+ return hwq_map[IEEE80211_AC_BE];
case 3:
- return hwq_map[WME_AC_BK];
+ return hwq_map[IEEE80211_AC_BK];
default:
- return hwq_map[WME_AC_BE];
+ return hwq_map[IEEE80211_AC_BE];
}
}
@@ -106,20 +106,20 @@ static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
switch (qnum) {
case 0:
- TX_QSTAT_INC(WME_AC_VO);
+ TX_QSTAT_INC(IEEE80211_AC_VO);
epid = priv->data_vo_ep;
break;
case 1:
- TX_QSTAT_INC(WME_AC_VI);
+ TX_QSTAT_INC(IEEE80211_AC_VI);
epid = priv->data_vi_ep;
break;
case 2:
- TX_QSTAT_INC(WME_AC_BE);
+ TX_QSTAT_INC(IEEE80211_AC_BE);
epid = priv->data_be_ep;
break;
case 3:
default:
- TX_QSTAT_INC(WME_AC_BK);
+ TX_QSTAT_INC(IEEE80211_AC_BK);
epid = priv->data_bk_ep;
break;
}
@@ -1082,7 +1082,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
rx_status->freq = hw->conf.channel->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_END;
return true;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1829b445d0b0..7cb787065913 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2153,9 +2153,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
AR_RTC_FORCE_WAKE_EN);
udelay(50);
- if (ath9k_hw_mci_is_enabled(ah))
- ar9003_mci_set_power_awake(ah);
-
for (i = POWER_UP_TIME / 50; i > 0; i--) {
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
if (val == AR_RTC_STATUS_ON)
@@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
return false;
}
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_set_power_awake(ah);
+
REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
return true;
@@ -2561,11 +2561,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
}
- if (AR_SREV_9485_10(ah)) {
- pCap->pcie_lcr_extsync_en = true;
- pCap->pcie_lcr_offset = 0x80;
- }
-
if (ath9k_hw_dfs_tested(ah))
pCap->hw_caps |= ATH9K_HW_CAP_DFS;
@@ -2604,6 +2599,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_WOW_PATTERN_MATCH_DWORD;
}
+ if (AR_SREV_9300_20_OR_LATER(ah) &&
+ ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
+ pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index dbc1b7a4cbfd..7f1a8e91c908 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -20,6 +20,7 @@
#include <linux/if_ether.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/firmware.h>
#include "mac.h"
#include "ani.h"
@@ -247,6 +248,7 @@ enum ath9k_hw_caps {
ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
ATH9K_HW_WOW_PATTERN_MATCH_EXACT = BIT(18),
ATH9K_HW_WOW_PATTERN_MATCH_DWORD = BIT(19),
+ ATH9K_HW_CAP_PAPRD = BIT(20),
};
/*
@@ -273,8 +275,6 @@ struct ath9k_hw_capabilities {
u8 rx_status_len;
u8 tx_desc_len;
u8 txs_len;
- u16 pcie_lcr_offset;
- bool pcie_lcr_extsync_en;
};
struct ath9k_ops_config {
@@ -401,6 +401,7 @@ enum ath9k_int {
struct ath9k_hw_cal_data {
u16 channel;
u32 channelFlags;
+ u32 chanmode;
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
@@ -834,6 +835,7 @@ struct ath_hw {
int coarse_low[5];
int firpwr[5];
enum ath9k_ani_cmd ani_function;
+ u32 ani_skip_count;
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
struct ath_btcoex_hw btcoex_hw;
@@ -875,7 +877,6 @@ struct ath_hw {
struct ar5416IniArray iniModesTxGain;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
- struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray ini_radio_post_sys2ant;
@@ -921,6 +922,8 @@ struct ath_hw {
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
+
+ const struct firmware *eeprom_blob;
};
struct ath_bus_ops {
@@ -928,7 +931,6 @@ struct ath_bus_ops {
void (*read_cachesize)(struct ath_common *common, int *csz);
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
void (*bt_coex_prep)(struct ath_common *common);
- void (*extn_synch_en)(struct ath_common *common);
void (*aspm_init)(struct ath_common *common);
};
@@ -1060,9 +1062,10 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
int chain);
int ar9003_paprd_create_curve(struct ath_hw *ah,
struct ath9k_hw_cal_data *caldata, int chain);
-int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
+void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
int ar9003_paprd_init_table(struct ath_hw *ah);
bool ar9003_paprd_is_done(struct ath_hw *ah);
+bool ar9003_is_paprd_enabled(struct ath_hw *ah);
/* Hardware family op attach helpers */
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index fad3ccd5cd91..f69ef5d48c7b 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -23,6 +23,11 @@
#include "ath9k.h"
+struct ath9k_eeprom_ctx {
+ struct completion complete;
+ struct ath_hw *ah;
+};
+
static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications");
@@ -435,7 +440,7 @@ static int ath9k_init_queues(struct ath_softc *sc)
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
ath_cabq_update(sc);
- for (i = 0; i < WME_NUM_AC; i++) {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
sc->tx.txq_map[i]->mac80211_qnum = i;
sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
@@ -506,6 +511,51 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
}
+static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
+ void *ctx)
+{
+ struct ath9k_eeprom_ctx *ec = ctx;
+
+ if (eeprom_blob)
+ ec->ah->eeprom_blob = eeprom_blob;
+
+ complete(&ec->complete);
+}
+
+static int ath9k_eeprom_request(struct ath_softc *sc, const char *name)
+{
+ struct ath9k_eeprom_ctx ec;
+ struct ath_hw *ah = ah = sc->sc_ah;
+ int err;
+
+ /* try to load the EEPROM content asynchronously */
+ init_completion(&ec.complete);
+ ec.ah = sc->sc_ah;
+
+ err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL,
+ &ec, ath9k_eeprom_request_cb);
+ if (err < 0) {
+ ath_err(ath9k_hw_common(ah),
+ "EEPROM request failed\n");
+ return err;
+ }
+
+ wait_for_completion(&ec.complete);
+
+ if (!ah->eeprom_blob) {
+ ath_err(ath9k_hw_common(ah),
+ "Unable to load EEPROM file %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ath9k_eeprom_release(struct ath_softc *sc)
+{
+ release_firmware(sc->sc_ah->eeprom_blob);
+}
+
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
@@ -563,10 +613,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->sc_pm_lock);
mutex_init(&sc->mutex);
-#ifdef CONFIG_ATH9K_DEBUGFS
- spin_lock_init(&sc->nodes_lock);
- INIT_LIST_HEAD(&sc->nodes);
-#endif
#ifdef CONFIG_ATH9K_MAC_DEBUG
spin_lock_init(&sc->debug.samp_lock);
#endif
@@ -587,6 +633,12 @@ 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)
+ goto err_eeprom;
+ }
+
/* Initializes the hardware for all supported chipsets */
ret = ath9k_hw_init(ah);
if (ret)
@@ -623,7 +675,8 @@ err_btcoex:
err_queues:
ath9k_hw_deinit(ah);
err_hw:
-
+ ath9k_eeprom_release(sc);
+err_eeprom:
kfree(ah);
sc->sc_ah = NULL;
@@ -687,6 +740,7 @@ static const struct ieee80211_iface_combination if_comb = {
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = 2048,
.num_different_channels = 1,
+ .beacon_int_infra_match = true,
};
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
@@ -885,6 +939,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
if (sc->dfs_detector != NULL)
sc->dfs_detector->exit(sc->dfs_detector);
+ ath9k_eeprom_release(sc);
kfree(sc->sc_ah);
sc->sc_ah = NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7b88b9c39ccd..ade3afb21f91 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -27,9 +27,6 @@ void ath_tx_complete_poll_work(struct work_struct *work)
struct ath_txq *txq;
int i;
bool needreset = false;
-#ifdef CONFIG_ATH9K_DEBUGFS
- sc->tx_complete_poll_work_seen++;
-#endif
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i)) {
@@ -182,13 +179,15 @@ void ath_rx_poll(unsigned long data)
static void ath_paprd_activate(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_cal_data *caldata = ah->caldata;
int chain;
- if (!caldata || !caldata->paprd_done)
+ if (!caldata || !caldata->paprd_done) {
+ ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n");
return;
+ }
- ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(ah->txchainmask & BIT(chain)))
@@ -197,8 +196,8 @@ static void ath_paprd_activate(struct ath_softc *sc)
ar9003_paprd_populate_single_table(ah, caldata, chain);
}
+ ath_dbg(common, CALIBRATE, "Activating PAPRD\n");
ar9003_paprd_enable(ah, true);
- ath9k_ps_restore(sc);
}
static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
@@ -211,7 +210,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
int time_left;
memset(&txctl, 0, sizeof(txctl));
- txctl.txq = sc->tx.txq_map[WME_AC_BE];
+ txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
tx_info->band = hw->conf.channel->band;
@@ -256,8 +255,10 @@ void ath_paprd_calibrate(struct work_struct *work)
int len = 1800;
int ret;
- if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
+ if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) {
+ ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n");
return;
+ }
ath9k_ps_wakeup(sc);
@@ -350,8 +351,18 @@ void ath_ani_calibrate(unsigned long data)
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
/* Only calibrate if awake */
- if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+ if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
+ if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ sc->ps_flags |= PS_WAIT_FOR_ANI;
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ }
goto set_timer;
+ }
+ ah->ani_skip_count = 0;
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ sc->ps_flags &= ~PS_WAIT_FOR_ANI;
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
ath9k_ps_wakeup(sc);
@@ -423,11 +434,15 @@ set_timer:
cal_interval = min(cal_interval, (u32)short_cal_interval);
mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
- if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {
- if (!ah->caldata->paprd_done)
+
+ if (ar9003_is_paprd_enabled(ah) && ah->caldata) {
+ if (!ah->caldata->paprd_done) {
ieee80211_queue_work(sc->hw, &sc->paprd_work);
- else if (!ah->paprd_table_write_done)
+ } else if (!ah->paprd_table_write_done) {
+ ath9k_ps_wakeup(sc);
ath_paprd_activate(sc);
+ ath9k_ps_restore(sc);
+ }
}
}
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index dd45edfa6bae..be30a9af1528 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK))) {
+ PS_WAIT_FOR_TX_ACK |
+ PS_WAIT_FOR_ANI))) {
mode = ATH9K_PM_NETWORK_SLEEP;
if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
ath9k_btcoex_stop_gen_timer(sc);
@@ -292,6 +293,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
goto out;
}
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
+ (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+ ath9k_mci_set_txpower(sc, true, false);
+
if (!ath_complete_reset(sc, true))
r = -EIO;
@@ -326,11 +331,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
u8 density;
an = (struct ath_node *)sta->drv_priv;
-#ifdef CONFIG_ATH9K_DEBUGFS
- spin_lock(&sc->nodes_lock);
- list_add(&an->list, &sc->nodes);
- spin_unlock(&sc->nodes_lock);
-#endif
+ an->sc = sc;
an->sta = sta;
an->vif = vif;
@@ -347,13 +348,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an = (struct ath_node *)sta->drv_priv;
-#ifdef CONFIG_ATH9K_DEBUGFS
- spin_lock(&sc->nodes_lock);
- list_del(&an->list);
- spin_unlock(&sc->nodes_lock);
- an->sta = NULL;
-#endif
-
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ath_tx_node_cleanup(sc, an);
}
@@ -489,17 +483,6 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & SCHED_INTR)
sched = true;
-#ifdef CONFIG_PM_SLEEP
- 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");
- atomic_inc(&sc->wow_got_bmiss_intr);
- atomic_dec(&sc->wow_sleep_proc_intr);
- }
- ath_dbg(common, INTERRUPT, "beacon miss interrupt\n");
- }
-#endif
-
/*
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
@@ -518,7 +501,15 @@ irqreturn_t ath_isr(int irq, void *dev)
goto chip_reset;
}
-
+#ifdef CONFIG_PM_SLEEP
+ 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");
+ atomic_inc(&sc->wow_got_bmiss_intr);
+ atomic_dec(&sc->wow_sleep_proc_intr);
+ }
+ }
+#endif
if (status & ATH9K_INT_SWBA)
tasklet_schedule(&sc->bcon_tasklet);
@@ -681,9 +672,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
- if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
- common->bus_ops->extn_synch_en(common);
-
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
@@ -919,8 +907,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
ath9k_vif_iter(iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
- iter_data);
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_vif_iter, iter_data);
}
/* Called with sc->mutex held. */
@@ -970,8 +959,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
if (ah->opmode == NL80211_IFTYPE_STATION &&
old_opmode == NL80211_IFTYPE_AP &&
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
- ieee80211_iterate_active_interfaces_atomic(sc->hw,
- ath9k_sta_vif_iter, sc);
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_sta_vif_iter, sc);
}
}
@@ -1324,7 +1314,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
struct ath9k_tx_queue_info qi;
int ret = 0;
- if (queue >= WME_NUM_AC)
+ if (queue >= IEEE80211_NUM_ACS)
return 0;
txq = sc->tx.txq_map[queue];
@@ -1449,6 +1439,9 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ ath9k_mci_update_wlan_channels(sc, false);
+
ath_dbg(common, CONFIG,
"Primary Station interface: %pM, BSSID: %pM\n",
vif->addr, common->curbssid);
@@ -1497,14 +1490,17 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
}
- ieee80211_iterate_active_interfaces_atomic(sc->hw,
- ath9k_bss_assoc_iter, sc);
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ ath9k_bss_assoc_iter, sc);
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
ah->opmode == NL80211_IFTYPE_STATION) {
memset(common->curbssid, 0, ETH_ALEN);
common->curaid = 0;
ath9k_hw_write_associd(sc->sc_ah);
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ ath9k_mci_update_wlan_channels(sc, true);
}
}
@@ -1887,134 +1883,6 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
-#ifdef CONFIG_ATH9K_DEBUGFS
-
-/* Ethtool support for get-stats */
-
-#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
-static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
- "tx_pkts_nic",
- "tx_bytes_nic",
- "rx_pkts_nic",
- "rx_bytes_nic",
- AMKSTR(d_tx_pkts),
- AMKSTR(d_tx_bytes),
- AMKSTR(d_tx_mpdus_queued),
- AMKSTR(d_tx_mpdus_completed),
- AMKSTR(d_tx_mpdu_xretries),
- AMKSTR(d_tx_aggregates),
- AMKSTR(d_tx_ampdus_queued_hw),
- AMKSTR(d_tx_ampdus_queued_sw),
- AMKSTR(d_tx_ampdus_completed),
- AMKSTR(d_tx_ampdu_retries),
- AMKSTR(d_tx_ampdu_xretries),
- AMKSTR(d_tx_fifo_underrun),
- AMKSTR(d_tx_op_exceeded),
- AMKSTR(d_tx_timer_expiry),
- AMKSTR(d_tx_desc_cfg_err),
- AMKSTR(d_tx_data_underrun),
- AMKSTR(d_tx_delim_underrun),
-
- "d_rx_decrypt_crc_err",
- "d_rx_phy_err",
- "d_rx_mic_err",
- "d_rx_pre_delim_crc_err",
- "d_rx_post_delim_crc_err",
- "d_rx_decrypt_busy_err",
-
- "d_rx_phyerr_radar",
- "d_rx_phyerr_ofdm_timing",
- "d_rx_phyerr_cck_timing",
-
-};
-#define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats)
-
-static void ath9k_get_et_strings(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u32 sset, u8 *data)
-{
- if (sset == ETH_SS_STATS)
- memcpy(data, *ath9k_gstrings_stats,
- sizeof(ath9k_gstrings_stats));
-}
-
-static int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int sset)
-{
- if (sset == ETH_SS_STATS)
- return ATH9K_SSTATS_LEN;
- return 0;
-}
-
-#define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum)
-#define AWDATA(elem) \
- do { \
- data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem; \
- data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem; \
- data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem; \
- data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem; \
- } while (0)
-
-#define AWDATA_RX(elem) \
- do { \
- data[i++] = sc->debug.stats.rxstats.elem; \
- } while (0)
-
-static void ath9k_get_et_stats(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ethtool_stats *stats, u64 *data)
-{
- struct ath_softc *sc = hw->priv;
- int i = 0;
-
- data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_pkts_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_pkts_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_pkts_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_pkts_all);
- data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_bytes_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_bytes_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_bytes_all +
- sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_bytes_all);
- AWDATA_RX(rx_pkts_all);
- AWDATA_RX(rx_bytes_all);
-
- AWDATA(tx_pkts_all);
- AWDATA(tx_bytes_all);
- AWDATA(queued);
- AWDATA(completed);
- AWDATA(xretries);
- AWDATA(a_aggr);
- AWDATA(a_queued_hw);
- AWDATA(a_queued_sw);
- AWDATA(a_completed);
- AWDATA(a_retries);
- AWDATA(a_xretries);
- AWDATA(fifo_underrun);
- AWDATA(xtxop);
- AWDATA(timer_exp);
- AWDATA(desc_cfg_err);
- AWDATA(data_underrun);
- AWDATA(delim_underrun);
-
- AWDATA_RX(decrypt_crc_err);
- AWDATA_RX(phy_err);
- AWDATA_RX(mic_err);
- AWDATA_RX(pre_delim_crc_err);
- AWDATA_RX(post_delim_crc_err);
- AWDATA_RX(decrypt_busy_err);
-
- AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]);
- AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]);
- AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]);
-
- WARN_ON(i != ATH9K_SSTATS_LEN);
-}
-
-/* End of ethtool get-stats functions */
-
-#endif
-
-
#ifdef CONFIG_PM_SLEEP
static void ath9k_wow_map_triggers(struct ath_softc *sc,
@@ -2408,7 +2276,12 @@ struct ieee80211_ops ath9k_ops = {
#ifdef CONFIG_ATH9K_DEBUGFS
.get_et_sset_count = ath9k_get_et_sset_count,
- .get_et_stats = ath9k_get_et_stats,
- .get_et_strings = ath9k_get_et_strings,
+ .get_et_stats = ath9k_get_et_stats,
+ .get_et_strings = ath9k_get_et_strings,
+#endif
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+ .sta_add_debugfs = ath9k_sta_add_debugfs,
+ .sta_remove_debugfs = ath9k_sta_remove_debugfs,
#endif
};
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index ec2d7c807567..5c02702f21e7 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common,
struct ath_mci_profile_info *info)
{
struct ath_mci_profile_info *entry;
+ u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 };
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
(info->type == MCI_GPM_COEX_PROFILE_VOICE))
@@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common,
memcpy(entry, info, 10);
INC_PROF(mci, info);
list_add_tail(&entry->list, &mci->info);
+ if (info->type == MCI_GPM_COEX_PROFILE_VOICE) {
+ if (info->voice_type < sizeof(voice_priority))
+ mci->voice_priority = voice_priority[info->voice_type];
+ else
+ mci->voice_priority = 110;
+ }
return true;
}
@@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
* For single PAN/FTP profile, allocate 35% for BT
* to improve WLAN throughput.
*/
- btcoex->duty_cycle = 35;
+ btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35;
btcoex->btcoex_period = 53;
ath_dbg(common, MCI,
"Single PAN/FTP bt period %d ms dutycycle %d\n",
@@ -200,23 +207,6 @@ skip_tuning:
ath9k_btcoex_timer_resume(sc);
}
-static void ath_mci_wait_btcal_done(struct ath_softc *sc)
-{
- struct ath_hw *ah = sc->sc_ah;
-
- /* Stop tx & rx */
- ieee80211_stop_queues(sc->hw);
- ath_stoprecv(sc);
- ath_drain_all_txq(sc, false);
-
- /* Wait for cal done */
- ar9003_mci_start_reset(ah, ah->curchan);
-
- /* Resume tx & rx */
- ath_startrecv(sc);
- ieee80211_wake_queues(sc->hw);
-}
-
static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
{
struct ath_hw *ah = sc->sc_ah;
@@ -228,7 +218,7 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
case MCI_GPM_BT_CAL_REQ:
if (mci_hw->bt_state == MCI_BT_AWAKE) {
mci_hw->bt_state = MCI_BT_CAL_START;
- ath_mci_wait_btcal_done(sc);
+ ath9k_queue_reset(sc, RESET_TYPE_MCI);
}
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
break;
@@ -250,6 +240,58 @@ static void ath9k_mci_work(struct work_struct *work)
ath_mci_update_scheme(sc);
}
+static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio)
+{
+ if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE])
+ stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio;
+
+ if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL])
+ stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio;
+
+ if ((cur_txprio > ATH_MCI_HI_PRIO) &&
+ (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW]))
+ stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio;
+}
+
+static void ath_mci_set_concur_txprio(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_mci_profile *mci = &btcoex->mci;
+ u8 stomp_txprio[ATH_BTCOEX_STOMP_MAX];
+
+ memset(stomp_txprio, 0, sizeof(stomp_txprio));
+ if (mci->num_mgmt) {
+ stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO;
+ if (!mci->num_pan && !mci->num_other_acl)
+ stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
+ ATH_MCI_INQUIRY_PRIO;
+ } else {
+ u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
+
+ stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
+ stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
+
+ if (mci->num_sco)
+ ath_mci_update_stomp_txprio(mci->voice_priority,
+ stomp_txprio);
+ if (mci->num_other_acl)
+ ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio);
+ if (mci->num_a2dp)
+ ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio);
+ if (mci->num_hid)
+ ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio);
+ if (mci->num_pan)
+ ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio);
+
+ if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff)
+ stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0;
+
+ if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff)
+ stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0;
+ }
+ ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio);
+}
+
static u8 ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info)
{
@@ -281,6 +323,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc,
} else
ath_mci_del_profile(common, mci, entry);
+ ath_mci_set_concur_txprio(sc);
return 1;
}
@@ -314,6 +357,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc,
mci->num_mgmt++;
} while (++i < ATH_MCI_MAX_PROFILE);
+ ath_mci_set_concur_txprio(sc);
if (old_num_mgmt != mci->num_mgmt)
return 1;
@@ -518,6 +562,8 @@ void ath_mci_intr(struct ath_softc *sc)
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM;
while (more_data == MCI_GPM_MORE) {
+ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
+ return;
pgpm = mci->gpm_buf.bf_addr;
offset = ar9003_mci_get_next_gpm_offset(ah, false,
@@ -600,3 +646,130 @@ void ath_mci_enable(struct ath_softc *sc)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
sc->sc_ah->imask |= ATH9K_INT_MCI;
}
+
+void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+ struct ath9k_channel *chan = ah->curchan;
+ u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
+ int i;
+ s16 chan_start, chan_end;
+ u16 wlan_chan;
+
+ if (!chan || !IS_CHAN_2GHZ(chan))
+ return;
+
+ if (allow_all)
+ goto send_wlan_chan;
+
+ wlan_chan = chan->channel - 2402;
+
+ chan_start = wlan_chan - 10;
+ chan_end = wlan_chan + 10;
+
+ if (chan->chanmode == CHANNEL_G_HT40PLUS)
+ chan_end += 20;
+ else if (chan->chanmode == CHANNEL_G_HT40MINUS)
+ chan_start -= 20;
+
+ /* adjust side band */
+ chan_start -= 7;
+ chan_end += 7;
+
+ if (chan_start <= 0)
+ chan_start = 0;
+ if (chan_end >= ATH_MCI_NUM_BT_CHANNELS)
+ chan_end = ATH_MCI_NUM_BT_CHANNELS - 1;
+
+ ath_dbg(ath9k_hw_common(ah), MCI,
+ "WLAN current channel %d mask BT channel %d - %d\n",
+ wlan_chan, chan_start, chan_end);
+
+ for (i = chan_start; i < chan_end; i++)
+ MCI_GPM_CLR_CHANNEL_BIT(&channelmap, i);
+
+send_wlan_chan:
+ /* update and send wlan channels info to BT */
+ for (i = 0; i < 4; i++)
+ mci->wlan_channels[i] = channelmap[i];
+ ar9003_mci_send_wlan_channels(ah);
+ ar9003_mci_state(ah, MCI_STATE_SEND_VERSION_QUERY);
+}
+
+void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+ bool concur_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
+ bool old_concur_tx = mci_hw->concur_tx;
+
+ if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) {
+ mci_hw->concur_tx = false;
+ return;
+ }
+
+ if (!IS_CHAN_2GHZ(ah->curchan))
+ return;
+
+ if (setchannel) {
+ struct ath9k_hw_cal_data *caldata = &sc->caldata;
+ if ((caldata->chanmode == CHANNEL_G_HT40PLUS) &&
+ (ah->curchan->channel > caldata->channel) &&
+ (ah->curchan->channel <= caldata->channel + 20))
+ return;
+ if ((caldata->chanmode == CHANNEL_G_HT40MINUS) &&
+ (ah->curchan->channel < caldata->channel) &&
+ (ah->curchan->channel >= caldata->channel - 20))
+ return;
+ mci_hw->concur_tx = false;
+ } else
+ mci_hw->concur_tx = concur_tx;
+
+ if (old_concur_tx != mci_hw->concur_tx)
+ ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+}
+
+static void ath9k_mci_stomp_audio(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_mci_profile *mci = &btcoex->mci;
+
+ if (!mci->num_sco && !mci->num_a2dp)
+ return;
+
+ if (ah->stats.avgbrssi > 25) {
+ btcoex->stomp_audio = 0;
+ return;
+ }
+
+ btcoex->stomp_audio++;
+}
+void ath9k_mci_update_rssi(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
+
+ ath9k_mci_stomp_audio(sc);
+
+ if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX))
+ return;
+
+ if (ah->stats.avgbrssi >= 40) {
+ if (btcoex->rssi_count < 0)
+ btcoex->rssi_count = 0;
+ if (++btcoex->rssi_count >= ATH_MCI_CONCUR_TX_SWITCH) {
+ btcoex->rssi_count = 0;
+ ath9k_mci_set_txpower(sc, false, true);
+ }
+ } else {
+ if (btcoex->rssi_count > 0)
+ btcoex->rssi_count = 0;
+ if (--btcoex->rssi_count <= -ATH_MCI_CONCUR_TX_SWITCH) {
+ btcoex->rssi_count = 0;
+ ath9k_mci_set_txpower(sc, false, false);
+ }
+ }
+}
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h
index fc14eea034eb..06958837620c 100644
--- a/drivers/net/wireless/ath/ath9k/mci.h
+++ b/drivers/net/wireless/ath/ath9k/mci.h
@@ -32,6 +32,27 @@
#define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\
ATH_MCI_MAX_SCO_PROFILE)
+#define ATH_MCI_INQUIRY_PRIO 62
+#define ATH_MCI_HI_PRIO 60
+#define ATH_MCI_NUM_BT_CHANNELS 79
+#define ATH_MCI_CONCUR_TX_SWITCH 5
+
+#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \
+ do { \
+ if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \
+ *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+ (_bt_chan / 8)) |= (1 << (_bt_chan & 7)); \
+ } \
+ } while (0)
+
+#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \
+ do { \
+ if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \
+ *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+ (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7));\
+ } \
+ } while (0)
+
#define INC_PROF(_mci, _info) do { \
switch (_info->type) { \
case MCI_GPM_COEX_PROFILE_RFCOMM:\
@@ -49,6 +70,7 @@
_mci->num_pan++; \
break; \
case MCI_GPM_COEX_PROFILE_VOICE: \
+ case MCI_GPM_COEX_PROFILE_A2DPVO:\
_mci->num_sco++; \
break; \
default: \
@@ -73,6 +95,7 @@
_mci->num_pan--; \
break; \
case MCI_GPM_COEX_PROFILE_VOICE: \
+ case MCI_GPM_COEX_PROFILE_A2DPVO:\
_mci->num_sco--; \
break; \
default: \
@@ -113,6 +136,7 @@ struct ath_mci_profile {
u8 num_pan;
u8 num_other_acl;
u8 num_bdr;
+ u8 voice_priority;
};
struct ath_mci_buf {
@@ -130,13 +154,25 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci);
int ath_mci_setup(struct ath_softc *sc);
void ath_mci_cleanup(struct ath_softc *sc);
void ath_mci_intr(struct ath_softc *sc);
+void ath9k_mci_update_rssi(struct ath_softc *sc);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
void ath_mci_enable(struct ath_softc *sc);
+void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all);
+void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+ bool concur_tx);
#else
static inline void ath_mci_enable(struct ath_softc *sc)
{
}
+static inline void ath9k_mci_update_wlan_channels(struct ath_softc *sc,
+ bool allow_all)
+{
+}
+static inline void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+ bool concur_tx)
+{
+}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
#endif /* MCI_H*/
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index f088f4bf9a26..7ae73fbd9136 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -96,17 +96,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
return true;
}
-static void ath_pci_extn_synch_enable(struct ath_common *common)
-{
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- struct pci_dev *pdev = to_pci_dev(sc->dev);
- u8 lnkctl;
-
- pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
- lnkctl |= PCI_EXP_LNKCTL_ES;
- pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
-}
-
/* Need to be called after we discover btcoex capabilities */
static void ath_pci_aspm_init(struct ath_common *common)
{
@@ -125,23 +114,23 @@ static void ath_pci_aspm_init(struct ath_common *common)
if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
(AR_SREV_9285(ah))) {
- /* Bluetooth coexistance requires disabling ASPM. */
+ /* Bluetooth coexistence requires disabling ASPM. */
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
- PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
/*
* Both upstream and downstream PCIe components should
* have the same ASPM settings.
*/
pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
- PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
return;
}
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
- if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+ if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
ah->aspm_enabled = true;
/* Initialize PCIe PM and SERDES registers. */
ath9k_hw_configpcipowersave(ah, false);
@@ -153,7 +142,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
.ath_bus_type = ATH_PCI,
.read_cachesize = ath_pci_read_cachesize,
.eeprom_read = ath_pci_eeprom_read,
- .extn_synch_en = ath_pci_extn_synch_enable,
.aspm_init = ath_pci_aspm_init,
};
@@ -299,7 +287,7 @@ static void ath_pci_remove(struct pci_dev *pdev)
pci_release_region(pdev, 0);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ath_pci_suspend(struct device *device)
{
@@ -345,22 +333,15 @@ static int ath_pci_resume(struct device *device)
return 0;
}
-static const struct dev_pm_ops ath9k_pm_ops = {
- .suspend = ath_pci_suspend,
- .resume = ath_pci_resume,
- .freeze = ath_pci_suspend,
- .thaw = ath_pci_resume,
- .poweroff = ath_pci_suspend,
- .restore = ath_pci_resume,
-};
+static SIMPLE_DEV_PM_OPS(ath9k_pm_ops, ath_pci_suspend, ath_pci_resume);
#define ATH9K_PM_OPS (&ath9k_pm_ops)
-#else /* !CONFIG_PM */
+#else /* !CONFIG_PM_SLEEP */
#define ATH9K_PM_OPS NULL
-#endif /* !CONFIG_PM */
+#endif /* !CONFIG_PM_SLEEP */
MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 27ed80b54881..714558d1ba78 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -982,16 +982,6 @@ static void ath_rc_update_per(struct ath_softc *sc,
}
}
-static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
- int xretries, int retries, u8 per)
-{
- struct ath_rc_stats *stats = &rc->rcstats[rix];
-
- stats->xretries += xretries;
- stats->retries += retries;
- stats->per = per;
-}
-
static void ath_rc_update_ht(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
struct ieee80211_tx_info *tx_info,
@@ -1065,14 +1055,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
}
-static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
- struct ath_rc_stats *stats;
-
- stats = &rc->rcstats[final_rate];
- stats->success++;
-}
-
static void ath_rc_tx_status(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
struct sk_buff *skb)
@@ -1350,7 +1332,25 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
}
}
-#ifdef CONFIG_ATH9K_DEBUGFS
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+
+void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+ struct ath_rc_stats *stats;
+
+ stats = &rc->rcstats[final_rate];
+ stats->success++;
+}
+
+void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+ int xretries, int retries, u8 per)
+{
+ struct ath_rc_stats *stats = &rc->rcstats[rix];
+
+ stats->xretries += xretries;
+ stats->retries += retries;
+ stats->per = per;
+}
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1428,10 +1428,17 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
struct dentry *dir)
{
struct ath_rate_priv *rc = priv_sta;
- debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
+ rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO,
+ dir, rc, &fops_rcstat);
+}
+
+static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta)
+{
+ struct ath_rate_priv *rc = priv_sta;
+ debugfs_remove(rc->debugfs_rcstats);
}
-#endif /* CONFIG_ATH9K_DEBUGFS */
+#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
@@ -1476,8 +1483,10 @@ static struct rate_control_ops ath_rate_ops = {
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
.free_sta = ath_rate_free_sta,
-#ifdef CONFIG_ATH9K_DEBUGFS
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
.add_sta_debugfs = ath_rate_add_sta_debugfs,
+ .remove_sta_debugfs = ath_rate_remove_sta_debugfs,
#endif
};
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 268e67dc5fb2..267dbfcfaa96 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -211,10 +211,26 @@ struct ath_rate_priv {
struct ath_rateset neg_ht_rates;
const struct ath_rate_table *rate_table;
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
struct dentry *debugfs_rcstats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+#endif
};
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
+void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+ int xretries, int retries, u8 per);
+#else
+static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+}
+static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+ int xretries, int retries, u8 per)
+{
+}
+#endif
+
#ifdef CONFIG_ATH9K_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 83d16e7ed272..d4df98a938bf 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -976,7 +976,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
rx_status->freq = hw->conf.channel->center_freq;
rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_END;
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
@@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
else
rs.is_mybeacon = false;
- sc->rx.num_pkts++;
+ if (ieee80211_is_data_present(hdr->frame_control) &&
+ !ieee80211_is_qos_nullfunc(hdr->frame_control))
+ sc->rx.num_pkts++;
+
ath_debug_stat_rx(sc, &rs);
/*
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 4e6760f8596d..ad3c82c09177 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -907,10 +907,6 @@
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
-#define AR_SREV_9462_20_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
-
#define AR_SREV_9565(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
@@ -2315,6 +2311,8 @@ enum {
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
#define AR_BTCOEX_WL_LNA 0x1940
#define AR_BTCOEX_RFGAIN_CTRL 0x1944
+#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF
+#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0
#define AR_BTCOEX_CTRL2 0x1948
#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800
@@ -2360,4 +2358,11 @@ enum {
#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3
+#define AR_MCI_MISC 0x1a74
+#define AR_MCI_MISC_HW_FIX_EN 0x00000001
+#define AR_MCI_MISC_HW_FIX_EN_S 0
+#define AR_MCI_DBG_CNT_CTRL 0x1a78
+#define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001
+#define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0
+
#endif
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index a483d518758c..9f8563091bea 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -118,7 +118,7 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
(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_OR_LATER(ah)) {
+ 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);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 741918a2027b..90e48a0fafe5 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -312,7 +312,6 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
}
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
- bf->bf_next = NULL;
list_del(&bf->list);
spin_unlock_bh(&sc->tx.txbuflock);
@@ -1263,7 +1262,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
int tidno;
for (tidno = 0, tid = &an->tid[tidno];
- tidno < WME_NUM_TID; tidno++, tid++) {
+ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
if (!tid->sched)
continue;
@@ -1297,7 +1296,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
int tidno;
for (tidno = 0, tid = &an->tid[tidno];
- tidno < WME_NUM_TID; tidno++, tid++) {
+ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
ac = tid->ac;
txq = ac->txq;
@@ -1354,10 +1353,10 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
struct ath_hw *ah = sc->sc_ah;
struct ath9k_tx_queue_info qi;
static const int subtype_txq_to_hwq[] = {
- [WME_AC_BE] = ATH_TXQ_AC_BE,
- [WME_AC_BK] = ATH_TXQ_AC_BK,
- [WME_AC_VI] = ATH_TXQ_AC_VI,
- [WME_AC_VO] = ATH_TXQ_AC_VO,
+ [IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
+ [IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
+ [IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
+ [IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
};
int axq_qnum, i;
@@ -2319,6 +2318,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
ath_txq_lock(sc, txq);
+ TX_STAT_INC(txq->axq_qnum, txprocdesc);
+
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
ath_txq_unlock(sc, txq);
return;
@@ -2446,7 +2447,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
int tidno, acno;
for (tidno = 0, tid = &an->tid[tidno];
- tidno < WME_NUM_TID;
+ tidno < IEEE80211_NUM_TIDS;
tidno++, tid++) {
tid->an = an;
tid->tidno = tidno;
@@ -2464,7 +2465,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
}
for (acno = 0, ac = &an->ac[acno];
- acno < WME_NUM_AC; acno++, ac++) {
+ acno < IEEE80211_NUM_ACS; acno++, ac++) {
ac->sched = false;
ac->txq = sc->tx.txq_map[acno];
INIT_LIST_HEAD(&ac->tid_q);
@@ -2479,7 +2480,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
int tidno;
for (tidno = 0, tid = &an->tid[tidno];
- tidno < WME_NUM_TID; tidno++, tid++) {
+ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
ac = tid->ac;
txq = ac->txq;
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 267d5dcf82dc..13a204598766 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -1,6 +1,7 @@
config CARL9170
tristate "Linux Community AR9170 802.11n USB support"
depends on USB && MAC80211 && EXPERIMENTAL
+ select ATH_COMMON
select FW_LOADER
select CRC32
help
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 24ac2876a733..aaebecd19e59 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -28,11 +28,6 @@
#include "fwcmd.h"
#include "version.h"
-#define MAKE_STR(symbol) #symbol
-#define TO_STR(symbol) MAKE_STR(symbol)
-#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
-MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
-
static const u8 otus_magic[4] = { OTUS_MAGIC };
static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index e3b1b6e87760..24d75ab94f0d 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
break;
}
} else {
- mac_addr = NULL;
+ /*
+ * Enable monitor mode
+ *
+ * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
+ * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
+ *
+ * When the hardware is in SNIFFER_PROMISC mode,
+ * it generates spurious ACKs for every incoming
+ * frame. This confuses every peer in the
+ * vicinity and the network throughput will suffer
+ * badly.
+ *
+ * Hence, the hardware will be put into station
+ * mode and just the rx filters are disabled.
+ */
+ cam_mode |= AR9170_MAC_CAM_STA;
+ rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+ mac_addr = common->macaddr;
bssid = NULL;
}
rcu_read_unlock();
@@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
if (ar->sniffer_enabled) {
- rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
- sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
}
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index a0b723078547..4684dd989496 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
struct carl9170_rsp *cmd = buf;
struct ieee80211_vif *vif;
- if (carl9170_check_sequence(ar, cmd->hdr.seq))
- return;
-
if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
carl9170_cmd_callback(ar, len, buf);
@@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
return false;
}
+static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len,
+ struct ieee80211_rx_status *status)
+{
+ struct sk_buff *skb;
+
+ /* (driver) frame trap handler
+ *
+ * Because power-saving mode handing has to be implemented by
+ * the driver/firmware. We have to check each incoming beacon
+ * from the associated AP, if there's new data for us (either
+ * broadcast/multicast or unicast) we have to react quickly.
+ *
+ * So, if you have you want to add additional frame trap
+ * handlers, this would be the perfect place!
+ */
+
+ carl9170_ps_beacon(ar, buf, len);
+
+ carl9170_ba_check(ar, buf, len);
+
+ skb = carl9170_rx_copy_data(buf, len);
+ if (!skb)
+ return -ENOMEM;
+
+ memcpy(IEEE80211_SKB_RXCB(skb), status, sizeof(*status));
+ ieee80211_rx(ar->hw, skb);
+ return 0;
+}
+
/*
* If the frame alignment is right (or the kernel has
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
@@ -672,14 +698,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
* mode, and we need to observe the proper ordering,
* this is non-trivial.
*/
-
-static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
{
struct ar9170_rx_head *head;
struct ar9170_rx_macstatus *mac;
struct ar9170_rx_phystatus *phy = NULL;
struct ieee80211_rx_status status;
- struct sk_buff *skb;
int mpdu_len;
u8 mac_status;
@@ -790,19 +814,13 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
if (phy)
carl9170_rx_phy_status(ar, phy, &status);
+ else
+ status.flag |= RX_FLAG_NO_SIGNAL_VAL;
- carl9170_ps_beacon(ar, buf, mpdu_len);
-
- carl9170_ba_check(ar, buf, mpdu_len);
-
- skb = carl9170_rx_copy_data(buf, mpdu_len);
- if (!skb)
+ if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status))
goto drop;
- memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
- ieee80211_rx(ar->hw, skb);
return;
-
drop:
ar->rx_dropped++;
}
@@ -820,6 +838,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
if (unlikely(i > resplen))
break;
+ if (carl9170_check_sequence(ar, cmd->hdr.seq))
+ break;
+
carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
}
@@ -851,7 +872,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
if (i == 12)
carl9170_rx_untie_cmds(ar, buf, len);
else
- carl9170_handle_mpdu(ar, buf, len);
+ carl9170_rx_untie_data(ar, buf, len);
}
static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 84377cf580e0..ef4ec0da6e49 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -1485,6 +1485,13 @@ void carl9170_op_tx(struct ieee80211_hw *hw,
}
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ /* to static code analyzers and reviewers:
+ * mac80211 guarantees that a valid "sta"
+ * reference is present, if a frame is to
+ * be part of an ampdu. Hence any extra
+ * sta == NULL checks are redundant in this
+ * special case.
+ */
run = carl9170_tx_ampdu_queue(ar, sta, skb);
if (run)
carl9170_tx_ampdu(ar);
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 888152ce3eca..307bc0ddff99 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
goto resubmit;
}
+ /*
+ * While the carl9170 firmware does not use this EP, the
+ * firmware loader in the EEPROM unfortunately does.
+ * Therefore we need to be ready to handle out-of-band
+ * responses and traps in case the firmware crashed and
+ * the loader took over again.
+ */
carl9170_handle_command_response(ar, urb->transfer_buffer,
urb->actual_length);
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index 19befb331073..39e8a590d7fc 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -20,8 +20,8 @@
#include "ath.h"
#include "reg.h"
-#define REG_READ (common->ops->read)
-#define REG_WRITE (common->ops->write)
+#define REG_READ (common->ops->read)
+#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
/**
* ath_hw_set_bssid_mask - filter out bssids we listen
@@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common)
{
void *ah = common->ah;
- REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
- REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
+ REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
+ REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
}
EXPORT_SYMBOL(ath_hw_setbssidmask);
@@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
void *ah = common->ah;
/* freeze */
- REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+ REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
/* read */
cycles = REG_READ(ah, AR_CCCNT);
@@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
tx = REG_READ(ah, AR_TFCNT);
/* clear */
- REG_WRITE(ah, 0, AR_CCCNT);
- REG_WRITE(ah, 0, AR_RFCNT);
- REG_WRITE(ah, 0, AR_RCCNT);
- REG_WRITE(ah, 0, AR_TFCNT);
+ REG_WRITE(ah, AR_CCCNT, 0);
+ REG_WRITE(ah, AR_RFCNT, 0);
+ REG_WRITE(ah, AR_RCCNT, 0);
+ REG_WRITE(ah, AR_TFCNT, 0);
/* unfreeze */
- REG_WRITE(ah, 0, AR_MIBC);
+ REG_WRITE(ah, AR_MIBC, 0);
/* update all cycle counters here */
common->cc_ani.cycles += cycles;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 4a4e98f71807..4374079dfc2a 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2963,7 +2963,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
ssid_el_p[1] = priv->SSID_size;
memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
- ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
+ ssid_el_p[3 + priv->SSID_size] = 4; /* len of supported rates */
memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index 51e33b53386e..c1b159ebcffe 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -45,11 +45,11 @@ static struct pci_driver atmel_driver = {
.name = "atmel",
.id_table = card_ids,
.probe = atmel_pci_probe,
- .remove = __devexit_p(atmel_pci_remove),
+ .remove = atmel_pci_remove,
};
-static int __devinit atmel_pci_probe(struct pci_dev *pdev,
+static int atmel_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pent)
{
struct net_device *dev;
@@ -69,7 +69,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev,
return 0;
}
-static void __devexit atmel_pci_remove(struct pci_dev *pdev)
+static void atmel_pci_remove(struct pci_dev *pdev)
{
stop_atmel_card(pci_get_drvdata(pdev));
}
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 777cd74921d7..38bc5a7997ff 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -409,7 +409,10 @@ static inline
struct b43_dmadesc_meta *meta)
{
if (meta->skb) {
- dev_kfree_skb_any(meta->skb);
+ if (ring->tx)
+ ieee80211_free_txskb(ring->dev->wl->hw, meta->skb);
+ else
+ dev_kfree_skb_any(meta->skb);
meta->skb = NULL;
}
}
@@ -1454,7 +1457,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(dev->wl->hw, skb);
err = 0;
goto out;
}
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c5a99c8c8168..16ab280359bd 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3397,7 +3397,7 @@ static void b43_tx_work(struct work_struct *work)
break;
}
if (unlikely(err))
- dev_kfree_skb(skb); /* Drop it */
+ ieee80211_free_txskb(wl->hw, skb);
err = 0;
}
@@ -3419,7 +3419,7 @@ static void b43_op_tx(struct ieee80211_hw *hw,
if (unlikely(skb->len < 2 + 2 + 6)) {
/* Too short, this can't be a valid frame. */
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
return;
}
B43_WARN_ON(skb_shinfo(skb)->nr_frags);
@@ -4229,8 +4229,12 @@ redo:
/* Drain all TX queues. */
for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
- while (skb_queue_len(&wl->tx_queue[queue_num]))
- dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
+ while (skb_queue_len(&wl->tx_queue[queue_num])) {
+ struct sk_buff *skb;
+
+ skb = skb_dequeue(&wl->tx_queue[queue_num]);
+ ieee80211_free_txskb(wl->hw, skb);
+ }
}
b43_mac_suspend(dev);
@@ -4652,7 +4656,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
dev->dev->bdev, true);
break;
#endif
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 714cad649c45..f2ea2ceec8a9 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -60,7 +60,7 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
# define b43_pcmcia_resume NULL
#endif /* CONFIG_PM */
-static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
+static int b43_pcmcia_probe(struct pcmcia_device *dev)
{
struct ssb_bus *ssb;
int err = -ENOMEM;
@@ -110,7 +110,7 @@ out_error:
return err;
}
-static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
+static void b43_pcmcia_remove(struct pcmcia_device *dev)
{
struct ssb_bus *ssb = dev->priv;
@@ -125,7 +125,7 @@ static struct pcmcia_driver b43_pcmcia_driver = {
.name = "b43-pcmcia",
.id_table = b43_pcmcia_tbl,
.probe = b43_pcmcia_probe,
- .remove = __devexit_p(b43_pcmcia_remove),
+ .remove = b43_pcmcia_remove,
.suspend = b43_pcmcia_suspend,
.resume = b43_pcmcia_resume,
};
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 3533ab86bd36..a73ff8c9deb5 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -196,7 +196,7 @@ static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
pack = &(q->packets[i]);
if (pack->skb) {
- dev_kfree_skb_any(pack->skb);
+ ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
pack->skb = NULL;
}
}
@@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(dev->wl->hw, skb);
err = 0;
goto out;
}
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index a54fb2d29089..59a521800694 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -93,7 +93,7 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
sdio->irq_handler = NULL;
}
-static int __devinit b43_sdio_probe(struct sdio_func *func,
+static int b43_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
@@ -171,7 +171,7 @@ out:
return error;
}
-static void __devexit b43_sdio_remove(struct sdio_func *func)
+static void b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
@@ -193,7 +193,7 @@ static struct sdio_driver b43_sdio_driver = {
.name = "b43-sdio",
.id_table = b43_sdio_ids,
.probe = b43_sdio_probe,
- .remove = __devexit_p(b43_sdio_remove),
+ .remove = b43_sdio_remove,
};
int b43_sdio_init(void)
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 136510edf3cf..8cb206a89083 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -796,7 +796,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
status.mactime += mactime;
if (low_mactime_now <= mactime)
status.mactime -= 0x10000;
- status.flag |= RX_FLAG_MACTIME_MPDU;
+ status.flag |= RX_FLAG_MACTIME_START;
}
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index a29da674e69d..482476fdb1f3 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -13,6 +13,7 @@
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
+#include <linux/completion.h>
#include <net/mac80211.h>
@@ -733,6 +734,10 @@ struct b43legacy_wldev {
/* Firmware data */
struct b43legacy_firmware fw;
+ const struct firmware *fwp; /* needed to pass fw pointer */
+
+ /* completion struct for firmware loading */
+ struct completion fw_load_complete;
/* Devicelist in struct b43legacy_wl (all 802.11 cores) */
struct list_head list;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 18e208e3eca1..8c3f70e1a013 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1513,9 +1513,17 @@ static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
"and download the correct firmware (version 3).\n");
}
+static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
+{
+ struct b43legacy_wldev *dev = context;
+
+ dev->fwp = firmware;
+ complete(&dev->fw_load_complete);
+}
+
static int do_request_fw(struct b43legacy_wldev *dev,
const char *name,
- const struct firmware **fw)
+ const struct firmware **fw, bool async)
{
char path[sizeof(modparam_fwpostfix) + 32];
struct b43legacy_fw_header *hdr;
@@ -1528,7 +1536,24 @@ static int do_request_fw(struct b43legacy_wldev *dev,
snprintf(path, ARRAY_SIZE(path),
"b43legacy%s/%s.fw",
modparam_fwpostfix, name);
- err = request_firmware(fw, path, dev->dev->dev);
+ b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
+ if (async) {
+ init_completion(&dev->fw_load_complete);
+ err = request_firmware_nowait(THIS_MODULE, 1, path,
+ dev->dev->dev, GFP_KERNEL,
+ dev, b43legacy_fw_cb);
+ if (err) {
+ b43legacyerr(dev->wl, "Unable to load firmware\n");
+ return err;
+ }
+ /* stall here until fw ready */
+ wait_for_completion(&dev->fw_load_complete);
+ if (!dev->fwp)
+ err = -EINVAL;
+ *fw = dev->fwp;
+ } else {
+ err = request_firmware(fw, path, dev->dev->dev);
+ }
if (err) {
b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
"or load failed.\n", path);
@@ -1580,7 +1605,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
filename = "ucode4";
else
filename = "ucode5";
- err = do_request_fw(dev, filename, &fw->ucode);
+ err = do_request_fw(dev, filename, &fw->ucode, true);
if (err)
goto err_load;
}
@@ -1589,7 +1614,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
filename = "pcm4";
else
filename = "pcm5";
- err = do_request_fw(dev, filename, &fw->pcm);
+ err = do_request_fw(dev, filename, &fw->pcm, false);
if (err)
goto err_load;
}
@@ -1607,7 +1632,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals);
+ err = do_request_fw(dev, filename, &fw->initvals, false);
if (err)
goto err_load;
}
@@ -1627,7 +1652,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals_band);
+ err = do_request_fw(dev, filename, &fw->initvals_band, false);
if (err)
goto err_load;
}
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index b8ffea6f5c64..849a28c80302 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -557,7 +557,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
status.mactime += mactime;
if (low_mactime_now <= mactime)
status.mactime -= 0x10000;
- status.flag |= RX_FLAG_MACTIME_MPDU;
+ status.flag |= RX_FLAG_MACTIME_START;
}
chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index c9d811eb6556..1d92d874ebb6 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -55,13 +55,16 @@ config BRCMFMAC_USB
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
use the driver for an USB wireless card.
-config BRCMISCAN
- bool "Broadcom I-Scan (OBSOLETE)"
- depends on BRCMFMAC
+config BRCM_TRACING
+ bool "Broadcom device tracing"
+ depends on BRCMSMAC || BRCMFMAC
---help---
- This option enables the I-Scan method. By default fullmac uses the
- new E-Scan method which uses less memory in firmware and gives no
- limitation on the number of scan results.
+ If you say Y here, the Broadcom wireless drivers will register
+ with ftrace to dump event information into the trace ringbuffer.
+ Tracing can be enabled at runtime to aid in debugging wireless
+ issues. This option adds a small amount of overhead when tracing
+ is disabled. If unsure, say Y to allow developers to better help
+ you when wireless problems occur.
config BRCMDBG
bool "Broadcom driver debug functions"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 9d5170b6df50..1a6661a9f008 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -24,6 +24,8 @@ ccflags-y += -D__CHECK_ENDIAN__
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += \
wl_cfg80211.o \
+ fwil.o \
+ fweh.o \
dhd_cdc.o \
dhd_common.o \
dhd_linux.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 3b2c4c20e7fc..be35a2f99b1c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -42,7 +42,8 @@
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
{
- struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
brcmf_dbg(INTR, "oob intr triggered\n");
@@ -66,12 +67,11 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
u8 data;
unsigned long flags;
- brcmf_dbg(TRACE, "Entering\n");
+ brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq);
- brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
sdiodev->irq_flags, "brcmf_oob_intr",
- &sdiodev->func[1]->card->dev);
+ &sdiodev->func[1]->dev);
if (ret != 0)
return ret;
spin_lock_init(&sdiodev->irq_en_lock);
@@ -84,6 +84,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
return ret;
sdiodev->irq_wake = true;
+ sdio_claim_host(sdiodev->func[1]);
+
/* must configure SDIO_CCCR_IENx to enable irq */
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
@@ -95,6 +97,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
data |= SDIO_SEPINT_ACT_HI;
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
+ sdio_release_host(sdiodev->func[1]);
+
return 0;
}
@@ -102,14 +106,16 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
+ sdio_claim_host(sdiodev->func[1]);
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+ sdio_release_host(sdiodev->func[1]);
if (sdiodev->irq_wake) {
disable_irq_wake(sdiodev->irq);
sdiodev->irq_wake = false;
}
- free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
+ free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
sdiodev->irq_en = false;
return 0;
@@ -117,7 +123,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
#else /* CONFIG_BRCMFMAC_SDIO_OOB */
static void brcmf_sdio_irqhandler(struct sdio_func *func)
{
- struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+ struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
brcmf_dbg(INTR, "ib intr triggered\n");
@@ -176,7 +183,7 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
} while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
if (err) {
- brcmf_dbg(ERROR, "failed at addr:0x%0x\n",
+ brcmf_err("failed at addr:0x%0x\n",
SBSDIO_FUNC1_SBADDRLOW + i);
break;
}
@@ -238,7 +245,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
} while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
if (ret != 0)
- brcmf_dbg(ERROR, "failed with %d\n", ret);
+ brcmf_err("failed with %d\n", ret);
return ret;
}
@@ -249,9 +256,7 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
- sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
- sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%02x\n", data);
if (ret)
@@ -266,9 +271,7 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
- sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
- sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%08x\n", data);
if (ret)
@@ -283,9 +286,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
- sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
- sdio_release_host(sdiodev->func[1]);
if (ret)
*ret = retval;
@@ -297,9 +298,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
- sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
- sdio_release_host(sdiodev->func[1]);
if (ret)
*ret = retval;
@@ -340,7 +339,7 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
mypkt = brcmu_pkt_buf_get_skb(nbytes);
if (!mypkt) {
- brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
nbytes);
return -EIO;
}
@@ -364,8 +363,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
- sdio_claim_host(sdiodev->func[1]);
-
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err)
@@ -376,8 +373,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
fn, addr, pkt);
done:
- sdio_release_host(sdiodev->func[1]);
-
return err;
}
@@ -391,8 +386,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen);
- sdio_claim_host(sdiodev->func[1]);
-
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err)
@@ -403,8 +396,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
pktq);
done:
- sdio_release_host(sdiodev->func[1]);
-
return err;
}
@@ -417,7 +408,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
mypkt = brcmu_pkt_buf_get_skb(nbytes);
if (!mypkt) {
- brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
nbytes);
return -EIO;
}
@@ -446,8 +437,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
- sdio_claim_host(sdiodev->func[1]);
-
if (bar0 != sdiodev->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
@@ -467,8 +456,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
addr, pkt);
done:
- sdio_release_host(sdiodev->func[1]);
-
return err;
}
@@ -484,7 +471,7 @@ int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
mypkt = brcmu_pkt_buf_get_skb(nbytes);
if (!mypkt) {
- brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
nbytes);
return -EIO;
}
@@ -510,10 +497,8 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
brcmf_dbg(TRACE, "Enter\n");
/* issue abort cmd52 command through F0 */
- sdio_claim_host(sdiodev->func[1]);
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
SDIO_CCCR_ABORT, &t_func);
- sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Exit\n");
return 0;
@@ -530,13 +515,10 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
regs = SI_ENUM_BASE;
- /* Report the BAR, to fix if needed */
- sdiodev->sbwad = SI_ENUM_BASE;
-
/* try to attach to the target device */
sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
if (!sdiodev->bus) {
- brcmf_dbg(ERROR, "device attach failed\n");
+ brcmf_err("device attach failed\n");
ret = -ENODEV;
goto out;
}
@@ -551,6 +533,8 @@ EXPORT_SYMBOL(brcmf_sdio_probe);
int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
{
+ sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+
if (sdiodev->bus) {
brcmf_sdbrcm_disconnect(sdiodev->bus);
sdiodev->bus = NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index c3247d5b3c22..d33e5598611b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -107,15 +107,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
/* Enable Function 2 */
err_ret = sdio_enable_func(sdfunc);
if (err_ret)
- brcmf_dbg(ERROR,
- "enable F2 failed:%d\n",
+ brcmf_err("enable F2 failed:%d\n",
err_ret);
} else {
/* Disable Function 2 */
err_ret = sdio_disable_func(sdfunc);
if (err_ret)
- brcmf_dbg(ERROR,
- "Disable F2 failed:%d\n",
+ brcmf_err("Disable F2 failed:%d\n",
err_ret);
}
}
@@ -129,7 +127,7 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
kfree(sdfunc);
} else if (regaddr < 0xF0) {
- brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
+ brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr);
err_ret = -EPERM;
} else {
sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
@@ -166,7 +164,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
}
if (err_ret)
- brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+ brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
rw ? "write" : "read", func, regaddr, *byte, err_ret);
return err_ret;
@@ -179,7 +177,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
int err_ret = -EIO;
if (func == 0) {
- brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
+ brcmf_err("Only CMD52 allowed to F0\n");
return -EINVAL;
}
@@ -198,7 +196,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
addr, &err_ret);
else
- brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
+ brcmf_err("Invalid nbytes: %d\n", nbytes);
} else { /* CMD52 Read */
if (nbytes == 4)
*word = sdio_readl(sdiodev->func[func], addr, &err_ret);
@@ -206,11 +204,11 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
*word = sdio_readw(sdiodev->func[func], addr,
&err_ret) & 0xFFFF;
else
- brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
+ brcmf_err("Invalid nbytes: %d\n", nbytes);
}
if (err_ret)
- brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
+ brcmf_err("Failed to %s word, Err: 0x%08x\n",
rw ? "write" : "read", err_ret);
return err_ret;
@@ -270,7 +268,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
addr, pkt, pkt_len);
if (err_ret) {
- brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
+ brcmf_err("%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
write ? "TX" : "RX", pkt, SGCount, addr,
pkt_len, err_ret);
} else {
@@ -315,7 +313,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
status = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
addr, pkt, pkt_len);
if (status) {
- brcmf_dbg(ERROR, "%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
+ brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
write ? "TX" : "RX", pkt, addr, pkt_len, status);
} else {
brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n",
@@ -336,7 +334,7 @@ static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
for (i = 0; i < 3; i++) {
regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret);
if (ret != 0)
- brcmf_dbg(ERROR, "Can't read!\n");
+ brcmf_err("Can't read!\n");
*ptr++ = (u8) regdata;
regaddr++;
@@ -372,11 +370,9 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
}
/* Enable Function 1 */
- sdio_claim_host(sdiodev->func[1]);
err_ret = sdio_enable_func(sdiodev->func[1]);
- sdio_release_host(sdiodev->func[1]);
if (err_ret)
- brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
+ brcmf_err("Failed to enable F1 Err: 0x%08x\n", err_ret);
return false;
}
@@ -393,24 +389,23 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
sdiodev->num_funcs = 2;
sdio_claim_host(sdiodev->func[1]);
+
err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
- sdio_release_host(sdiodev->func[1]);
if (err_ret) {
- brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
+ brcmf_err("Failed to set F1 blocksize\n");
goto out;
}
- sdio_claim_host(sdiodev->func[2]);
err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
- sdio_release_host(sdiodev->func[2]);
if (err_ret) {
- brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
+ brcmf_err("Failed to set F2 blocksize\n");
goto out;
}
brcmf_sdioh_enablefuncs(sdiodev);
out:
+ sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Done\n");
return err_ret;
}
@@ -437,7 +432,7 @@ static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
struct brcmf_sdio_oobirq *oobirq_entry;
if (list_empty(&oobirq_lh)) {
- brcmf_dbg(ERROR, "no valid oob irq resource\n");
+ brcmf_err("no valid oob irq resource\n");
return -ENXIO;
}
@@ -459,95 +454,106 @@ static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
static int brcmf_ops_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+ const struct sdio_device_id *id)
{
- int ret = 0;
+ int err;
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
brcmf_dbg(TRACE, "Enter\n");
- brcmf_dbg(TRACE, "func->class=%x\n", func->class);
- brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
- brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
- brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
-
- if (func->num == 1) {
- if (dev_get_drvdata(&func->card->dev)) {
- brcmf_dbg(ERROR, "card private drvdata occupied\n");
- return -ENXIO;
- }
- bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
- if (!bus_if)
- return -ENOMEM;
- sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
- if (!sdiodev) {
- kfree(bus_if);
- return -ENOMEM;
- }
- sdiodev->func[0] = func;
- sdiodev->func[1] = func;
- sdiodev->bus_if = bus_if;
- bus_if->bus_priv.sdio = sdiodev;
- bus_if->type = SDIO_BUS;
- bus_if->align = BRCMF_SDALIGN;
- dev_set_drvdata(&func->card->dev, sdiodev);
-
- atomic_set(&sdiodev->suspend, false);
- init_waitqueue_head(&sdiodev->request_byte_wait);
- init_waitqueue_head(&sdiodev->request_word_wait);
- init_waitqueue_head(&sdiodev->request_chain_wait);
- init_waitqueue_head(&sdiodev->request_buffer_wait);
+ brcmf_dbg(TRACE, "Class=%x\n", func->class);
+ brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
+ brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
+ brcmf_dbg(TRACE, "Function#: %d\n", func->num);
+
+ /* Consume func num 1 but dont do anything with it. */
+ if (func->num == 1)
+ return 0;
+
+ /* Ignore anything but func 2 */
+ if (func->num != 2)
+ return -ENODEV;
+
+ bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
+ if (!bus_if)
+ return -ENOMEM;
+ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+ if (!sdiodev) {
+ kfree(bus_if);
+ return -ENOMEM;
}
- if (func->num == 2) {
- sdiodev = dev_get_drvdata(&func->card->dev);
- if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
- return -ENODEV;
-
- ret = brcmf_sdio_getintrcfg(sdiodev);
- if (ret)
- return ret;
- sdiodev->func[2] = func;
+ sdiodev->func[0] = func->card->sdio_func[0];
+ sdiodev->func[1] = func->card->sdio_func[0];
+ sdiodev->func[2] = func;
- bus_if = sdiodev->bus_if;
- sdiodev->dev = &func->dev;
- dev_set_drvdata(&func->dev, bus_if);
+ sdiodev->bus_if = bus_if;
+ bus_if->bus_priv.sdio = sdiodev;
+ bus_if->align = BRCMF_SDALIGN;
+ dev_set_drvdata(&func->dev, bus_if);
+ dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
+ sdiodev->dev = &sdiodev->func[1]->dev;
- brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
- ret = brcmf_sdio_probe(sdiodev);
+ atomic_set(&sdiodev->suspend, false);
+ init_waitqueue_head(&sdiodev->request_byte_wait);
+ init_waitqueue_head(&sdiodev->request_word_wait);
+ init_waitqueue_head(&sdiodev->request_chain_wait);
+ init_waitqueue_head(&sdiodev->request_buffer_wait);
+ err = brcmf_sdio_getintrcfg(sdiodev);
+ if (err)
+ goto fail;
+
+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
+ err = brcmf_sdio_probe(sdiodev);
+ if (err) {
+ brcmf_err("F2 error, probe failed %d...\n", err);
+ goto fail;
}
+ brcmf_dbg(TRACE, "F2 init completed...\n");
+ return 0;
- return ret;
+fail:
+ dev_set_drvdata(&func->dev, NULL);
+ dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+ kfree(sdiodev);
+ kfree(bus_if);
+ return err;
}
static void brcmf_ops_sdio_remove(struct sdio_func *func)
{
struct brcmf_bus *bus_if;
struct brcmf_sdio_dev *sdiodev;
+
brcmf_dbg(TRACE, "Enter\n");
- brcmf_dbg(INFO, "func->class=%x\n", func->class);
- brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
- brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
- brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
+ brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
+ brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
+ brcmf_dbg(TRACE, "Function: %d\n", func->num);
- if (func->num == 2) {
- bus_if = dev_get_drvdata(&func->dev);
+ if (func->num != 1 && func->num != 2)
+ return;
+
+ bus_if = dev_get_drvdata(&func->dev);
+ if (bus_if) {
sdiodev = bus_if->bus_priv.sdio;
- brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
brcmf_sdio_remove(sdiodev);
- dev_set_drvdata(&func->card->dev, NULL);
- dev_set_drvdata(&func->dev, NULL);
+
+ dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+ dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
+
kfree(bus_if);
kfree(sdiodev);
}
+
+ brcmf_dbg(TRACE, "Exit\n");
}
#ifdef CONFIG_PM_SLEEP
static int brcmf_sdio_suspend(struct device *dev)
{
mmc_pm_flag_t sdio_flags;
- struct sdio_func *func = dev_to_sdio_func(dev);
- struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
int ret = 0;
brcmf_dbg(TRACE, "\n");
@@ -556,13 +562,13 @@ static int brcmf_sdio_suspend(struct device *dev)
sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
- brcmf_dbg(ERROR, "Host can't keep power while suspended\n");
+ brcmf_err("Host can't keep power while suspended\n");
return -EINVAL;
}
ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
if (ret) {
- brcmf_dbg(ERROR, "Failed to set pm_flags\n");
+ brcmf_err("Failed to set pm_flags\n");
return ret;
}
@@ -573,8 +579,8 @@ static int brcmf_sdio_suspend(struct device *dev)
static int brcmf_sdio_resume(struct device *dev)
{
- struct sdio_func *func = dev_to_sdio_func(dev);
- struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
brcmf_sdio_wdtmr_enable(sdiodev, true);
atomic_set(&sdiodev->suspend, false);
@@ -627,7 +633,7 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)
ret = sdio_register_driver(&brcmf_sdmmc_driver);
if (ret)
- brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
+ brcmf_err("sdio_register_driver failed: %d\n", ret);
return ret;
}
@@ -657,7 +663,7 @@ void brcmf_sdio_init(void)
ret = platform_driver_register(&brcmf_sdio_pd);
if (ret)
- brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret);
+ brcmf_err("platform_driver_register failed: %d\n", ret);
}
#else
void brcmf_sdio_exit(void)
@@ -676,6 +682,6 @@ void brcmf_sdio_init(void)
ret = sdio_register_driver(&brcmf_sdmmc_driver);
if (ret)
- brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
+ brcmf_err("sdio_register_driver failed: %d\n", ret);
}
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 17e7ae73e008..fd672bf53867 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -23,6 +23,8 @@
#define BRCMF_VERSION_STR "4.218.248.5"
+#include "fweh.h"
+
/*******************************************************************************
* IO codes that are interpreted by dongle firmware
******************************************************************************/
@@ -38,8 +40,11 @@
#define BRCMF_C_GET_SSID 25
#define BRCMF_C_SET_SSID 26
#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
@@ -58,6 +63,7 @@
#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
@@ -65,6 +71,7 @@
#define BRCMF_C_SET_WSEC 134
#define BRCMF_C_GET_PHY_NOISE 135
#define BRCMF_C_GET_BSS_INFO 136
+#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
@@ -100,29 +107,8 @@
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
-#define BRCMF_SCAN_ACTION_START 1
-#define BRCMF_SCAN_ACTION_CONTINUE 2
-#define WL_SCAN_ACTION_ABORT 3
-
-#define BRCMF_ISCAN_REQ_VERSION 1
-
-/* brcmf_iscan_results status values */
-#define BRCMF_SCAN_RESULTS_SUCCESS 0
-#define BRCMF_SCAN_RESULTS_PARTIAL 1
-#define BRCMF_SCAN_RESULTS_PENDING 2
-#define BRCMF_SCAN_RESULTS_ABORTED 3
-#define BRCMF_SCAN_RESULTS_NO_MEM 4
-
-/* Indicates this key is using soft encrypt */
-#define WL_SOFT_KEY (1 << 0)
/* primary (ie tx) key */
#define BRCMF_PRIMARY_KEY (1 << 1)
-/* Reserved for backward compat */
-#define WL_KF_RES_4 (1 << 4)
-/* Reserved for backward compat */
-#define WL_KF_RES_5 (1 << 5)
-/* Indicates a group key for a IBSS PEER */
-#define WL_IBSS_PEER_GROUP_KEY (1 << 6)
/* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16
@@ -130,10 +116,6 @@
#define DOT11_BSSTYPE_ANY 2
#define DOT11_MAX_DEFAULT_KEYS 4
-#define BRCMF_EVENT_MSG_LINK 0x01
-#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
-#define BRCMF_EVENT_MSG_GROUP 0x04
-
#define BRCMF_ESCAN_REQ_VERSION 1
#define WLC_BSS_RSSI_ON_CHANNEL 0x0002
@@ -141,108 +123,6 @@
#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
#define BRCMF_STA_ASSOC 0x10 /* Associated */
-struct brcmf_event_msg {
- __be16 version;
- __be16 flags;
- __be32 event_type;
- __be32 status;
- __be32 reason;
- __be32 auth_type;
- __be32 datalen;
- u8 addr[ETH_ALEN];
- char ifname[IFNAMSIZ];
- u8 ifidx;
- u8 bsscfgidx;
-} __packed;
-
-struct brcm_ethhdr {
- u16 subtype;
- u16 length;
- u8 version;
- u8 oui[3];
- u16 usr_subtype;
-} __packed;
-
-struct brcmf_event {
- struct ethhdr eth;
- struct brcm_ethhdr hdr;
- struct brcmf_event_msg msg;
-} __packed;
-
-/* event codes sent by the dongle to this driver */
-#define BRCMF_E_SET_SSID 0
-#define BRCMF_E_JOIN 1
-#define BRCMF_E_START 2
-#define BRCMF_E_AUTH 3
-#define BRCMF_E_AUTH_IND 4
-#define BRCMF_E_DEAUTH 5
-#define BRCMF_E_DEAUTH_IND 6
-#define BRCMF_E_ASSOC 7
-#define BRCMF_E_ASSOC_IND 8
-#define BRCMF_E_REASSOC 9
-#define BRCMF_E_REASSOC_IND 10
-#define BRCMF_E_DISASSOC 11
-#define BRCMF_E_DISASSOC_IND 12
-#define BRCMF_E_QUIET_START 13
-#define BRCMF_E_QUIET_END 14
-#define BRCMF_E_BEACON_RX 15
-#define BRCMF_E_LINK 16
-#define BRCMF_E_MIC_ERROR 17
-#define BRCMF_E_NDIS_LINK 18
-#define BRCMF_E_ROAM 19
-#define BRCMF_E_TXFAIL 20
-#define BRCMF_E_PMKID_CACHE 21
-#define BRCMF_E_RETROGRADE_TSF 22
-#define BRCMF_E_PRUNE 23
-#define BRCMF_E_AUTOAUTH 24
-#define BRCMF_E_EAPOL_MSG 25
-#define BRCMF_E_SCAN_COMPLETE 26
-#define BRCMF_E_ADDTS_IND 27
-#define BRCMF_E_DELTS_IND 28
-#define BRCMF_E_BCNSENT_IND 29
-#define BRCMF_E_BCNRX_MSG 30
-#define BRCMF_E_BCNLOST_MSG 31
-#define BRCMF_E_ROAM_PREP 32
-#define BRCMF_E_PFN_NET_FOUND 33
-#define BRCMF_E_PFN_NET_LOST 34
-#define BRCMF_E_RESET_COMPLETE 35
-#define BRCMF_E_JOIN_START 36
-#define BRCMF_E_ROAM_START 37
-#define BRCMF_E_ASSOC_START 38
-#define BRCMF_E_IBSS_ASSOC 39
-#define BRCMF_E_RADIO 40
-#define BRCMF_E_PSM_WATCHDOG 41
-#define BRCMF_E_PROBREQ_MSG 44
-#define BRCMF_E_SCAN_CONFIRM_IND 45
-#define BRCMF_E_PSK_SUP 46
-#define BRCMF_E_COUNTRY_CODE_CHANGED 47
-#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48
-#define BRCMF_E_ICV_ERROR 49
-#define BRCMF_E_UNICAST_DECODE_ERROR 50
-#define BRCMF_E_MULTICAST_DECODE_ERROR 51
-#define BRCMF_E_TRACE 52
-#define BRCMF_E_IF 54
-#define BRCMF_E_RSSI 56
-#define BRCMF_E_PFN_SCAN_COMPLETE 57
-#define BRCMF_E_EXTLOG_MSG 58
-#define BRCMF_E_ACTION_FRAME 59
-#define BRCMF_E_ACTION_FRAME_COMPLETE 60
-#define BRCMF_E_PRE_ASSOC_IND 61
-#define BRCMF_E_PRE_REASSOC_IND 62
-#define BRCMF_E_CHANNEL_ADOPTED 63
-#define BRCMF_E_AP_STARTED 64
-#define BRCMF_E_DFS_AP_STOP 65
-#define BRCMF_E_DFS_AP_RESUME 66
-#define BRCMF_E_RESERVED1 67
-#define BRCMF_E_RESERVED2 68
-#define BRCMF_E_ESCAN_RESULT 69
-#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
-#define BRCMF_E_DCS_REQUEST 73
-
-#define BRCMF_E_FIFO_CREDIT_MAP 74
-
-#define BRCMF_E_LAST 75
-
#define BRCMF_E_STATUS_SUCCESS 0
#define BRCMF_E_STATUS_FAIL 1
#define BRCMF_E_STATUS_TIMEOUT 2
@@ -318,6 +198,12 @@ struct brcmf_event {
#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_DCMD_MEDLEN 1536
+#define BRCMF_DCMD_MAXLEN 8192
+
/* 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.
@@ -397,7 +283,7 @@ struct brcm_rateset_le {
/* # rates in this set */
__le32 count;
/* rates in 500kbps units w/hi bit set if basic */
- u8 rates[WL_NUMRATES];
+ u8 rates[BRCMF_MAXRATES_IN_SET];
};
struct brcmf_ssid {
@@ -446,14 +332,6 @@ struct brcmf_scan_params_le {
__le16 channel_list[1]; /* list of chanspecs */
};
-/* incremental scan struct */
-struct brcmf_iscan_params_le {
- __le32 version;
- __le16 action;
- __le16 scan_duration;
- struct brcmf_scan_params_le params_le;
-};
-
struct brcmf_scan_results {
u32 buflen;
u32 version;
@@ -461,12 +339,6 @@ struct brcmf_scan_results {
struct brcmf_bss_info_le bss_info_le[];
};
-struct brcmf_scan_results_le {
- __le32 buflen;
- __le32 version;
- __le32 count;
-};
-
struct brcmf_escan_params_le {
__le32 version;
__le16 action;
@@ -502,23 +374,6 @@ struct brcmf_join_params {
struct brcmf_assoc_params_le params_le;
};
-/* incremental scan results struct */
-struct brcmf_iscan_results {
- union {
- u32 status;
- __le32 status_le;
- };
- union {
- struct brcmf_scan_results results;
- struct brcmf_scan_results_le results_le;
- };
-};
-
-/* size of brcmf_iscan_results not including variable length array */
-#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
- (sizeof(struct brcmf_scan_results) + \
- offsetof(struct brcmf_iscan_results, results))
-
struct brcmf_wsec_key {
u32 index; /* key index */
u32 len; /* key length */
@@ -615,7 +470,6 @@ struct brcmf_pub {
struct brcmf_bus *bus_if;
struct brcmf_proto *prot;
struct brcmf_cfg80211_info *config;
- struct device *dev; /* fullmac dongle device pointer */
/* Internal brcmf items */
uint hdrlen; /* Total BRCMF header length (proto + bus) */
@@ -623,7 +477,6 @@ struct brcmf_pub {
u8 wme_dp; /* wme discard priority */
/* Dongle media info */
- bool iswl; /* Dongle-resident driver is wl */
unsigned long drv_version; /* Version of dongle-resident driver */
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
@@ -651,26 +504,26 @@ struct brcmf_pub {
int in_suspend; /* flag set to 1 when early suspend called */
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
- /* Pkt filter defination */
- char *pktfilter[100];
- int pktfilter_count;
-
- u8 country_code[BRCM_CNTRY_BUF_SZ];
- char eventmask[BRCMF_EVENTING_MASK_LEN];
-
struct brcmf_if *iflist[BRCMF_MAX_IFS];
struct mutex proto_block;
+ unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
- struct work_struct setmacaddr_work;
- struct work_struct multicast_work;
u8 macvalue[ETH_ALEN];
atomic_t pend_8021x_cnt;
+ wait_queue_head_t pend_8021x_wait;
+
+ struct brcmf_fweh_info fweh;
#ifdef DEBUG
struct dentry *dbgfs_dir;
#endif
};
+struct bcmevent_name {
+ uint event;
+ const char *name;
+};
+
struct brcmf_if_event {
u8 ifidx;
u8 action;
@@ -678,47 +531,54 @@ struct brcmf_if_event {
u8 bssidx;
};
-struct bcmevent_name {
- uint event;
- const char *name;
+/* forward declaration */
+struct brcmf_cfg80211_vif;
+
+/**
+ * struct brcmf_if - interface control information.
+ *
+ * @drvr: points to device related information.
+ * @vif: points to cfg80211 specific interface information.
+ * @ndev: associated network device.
+ * @stats: interface specific network statistics.
+ * @idx: interface index in device firmware.
+ * @bssidx: index of bss associated with this interface.
+ * @mac_addr: assigned mac address.
+ */
+struct brcmf_if {
+ struct brcmf_pub *drvr;
+ struct brcmf_cfg80211_vif *vif;
+ struct net_device *ndev;
+ struct net_device_stats stats;
+ struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
+ int idx;
+ s32 bssidx;
+ u8 mac_addr[ETH_ALEN];
};
-extern const struct bcmevent_name bcmevent_names[];
+static inline s32 brcmf_ndev_bssidx(struct net_device *ndev)
+{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ return ifp->bssidx;
+}
-extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
- char *buf, uint len);
-extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
- char *buf, uint buflen, s32 bssidx);
+extern const struct bcmevent_name bcmevent_names[];
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
-extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
-extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd);
-
/* Return pointer to interface name */
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
/* Query dongle */
extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
+extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len);
-#ifdef DEBUG
-extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
-#endif /* DEBUG */
-
-extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
-extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
- void *pktdata, struct brcmf_event_msg *,
- void **data_ptr);
-
+extern int brcmf_net_attach(struct brcmf_if *ifp);
+extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
+ s32 bssidx, char *name, u8 *mac_addr);
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
-extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
-extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
- int enable, int master_mode);
-
-#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */
-#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */
-#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */
-
#endif /* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 9b8ee19ea55d..dd38b78a9726 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -43,37 +43,90 @@ struct brcmf_bus_dcmd {
struct list_head list;
};
-/* interface structure between common and bus layer */
+/**
+ * struct brcmf_bus_ops - bus callback operations.
+ *
+ * @init: prepare for communication with dongle.
+ * @stop: clear pending frames, disable data flow.
+ * @txdata: send a data frame to the dongle (callee disposes skb).
+ * @txctl: transmit a control request message to dongle.
+ * @rxctl: receive a control response message from dongle.
+ *
+ * This structure provides an abstract interface towards the
+ * bus specific driver. For control messages to common driver
+ * will assure there is only one active transaction.
+ */
+struct brcmf_bus_ops {
+ int (*init)(struct device *dev);
+ void (*stop)(struct device *dev);
+ int (*txdata)(struct device *dev, struct sk_buff *skb);
+ int (*txctl)(struct device *dev, unsigned char *msg, uint len);
+ int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
+};
+
+/**
+ * struct brcmf_bus - interface structure between common and bus layer
+ *
+ * @bus_priv: pointer to private bus device.
+ * @dev: device pointer of bus device.
+ * @drvr: public driver information.
+ * @state: operational state of the bus interface.
+ * @maxctl: maximum size for rxctl request message.
+ * @drvr_up: indicates driver up/down status.
+ * @tx_realloc: number of tx packets realloced for headroom.
+ * @dstats: dongle-based statistical data.
+ * @align: alignment requirement for the bus.
+ * @dcmd_list: bus/device specific dongle initialization commands.
+ */
struct brcmf_bus {
- u8 type; /* bus type */
union {
struct brcmf_sdio_dev *sdio;
struct brcmf_usbdev *usb;
} bus_priv;
- struct brcmf_pub *drvr; /* pointer to driver pub structure brcmf_pub */
+ struct device *dev;
+ struct brcmf_pub *drvr;
enum brcmf_bus_state state;
- uint maxctl; /* Max size rxctl request from proto to bus */
- bool drvr_up; /* Status flag of driver up/down */
- unsigned long tx_realloc; /* Tx packets realloced for headroom */
- struct dngl_stats dstats; /* Stats for dongle-based data */
- u8 align; /* bus alignment requirement */
+ uint maxctl;
+ bool drvr_up;
+ unsigned long tx_realloc;
+ struct dngl_stats dstats;
+ u8 align;
struct list_head dcmd_list;
- /* interface functions pointers */
- /* Stop bus module: clear pending frames, disable data flow */
- void (*brcmf_bus_stop)(struct device *);
- /* Initialize bus module: prepare for communication w/dongle */
- int (*brcmf_bus_init)(struct device *);
- /* Send a data frame to the dongle. Callee disposes of txp. */
- int (*brcmf_bus_txdata)(struct device *, struct sk_buff *);
- /* Send/receive a control message to/from the dongle.
- * Expects caller to enforce a single outstanding transaction.
- */
- int (*brcmf_bus_txctl)(struct device *, unsigned char *, uint);
- int (*brcmf_bus_rxctl)(struct device *, unsigned char *, uint);
+ struct brcmf_bus_ops *ops;
};
/*
+ * callback wrappers
+ */
+static inline int brcmf_bus_init(struct brcmf_bus *bus)
+{
+ return bus->ops->init(bus->dev);
+}
+
+static inline void brcmf_bus_stop(struct brcmf_bus *bus)
+{
+ bus->ops->stop(bus->dev);
+}
+
+static inline int brcmf_bus_txdata(struct brcmf_bus *bus, struct sk_buff *skb)
+{
+ return bus->ops->txdata(bus->dev, skb);
+}
+
+static inline
+int brcmf_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
+{
+ return bus->ops->txctl(bus->dev, msg, len);
+}
+
+static inline
+int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
+{
+ return bus->ops->rxctl(bus->dev, msg, len);
+}
+
+/*
* interface functions from common layer
*/
@@ -85,7 +138,7 @@ extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
struct sk_buff *pkt, int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
-extern void brcmf_rx_frame(struct device *dev, int ifidx,
+extern void brcmf_rx_frame(struct device *dev, u8 ifidx,
struct sk_buff_head *rxlist);
static inline void brcmf_rx_packet(struct device *dev, int ifidx,
struct sk_buff *pkt)
@@ -111,9 +164,6 @@ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
extern int brcmf_bus_start(struct device *dev);
-extern int brcmf_add_if(struct device *dev, int ifidx,
- char *name, u8 *mac_addr);
-
#ifdef CONFIG_BRCMFMAC_SDIO
extern void brcmf_sdio_exit(void);
extern void brcmf_sdio_init(void);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index a5c15cac5e7d..83923553f1ac 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -23,8 +23,6 @@
#include <linux/types.h>
#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <defs.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
@@ -119,9 +117,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
len = CDC_MAX_MSG_SIZE;
/* Send request */
- return drvr->bus_if->brcmf_bus_txctl(drvr->dev,
- (unsigned char *)&prot->msg,
- len);
+ 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)
@@ -130,11 +126,10 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
struct brcmf_proto *prot = drvr->prot;
brcmf_dbg(TRACE, "Enter\n");
-
+ len += sizeof(struct brcmf_proto_cdc_dcmd);
do {
- ret = drvr->bus_if->brcmf_bus_rxctl(drvr->dev,
- (unsigned char *)&prot->msg,
- len + sizeof(struct brcmf_proto_cdc_dcmd));
+ 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);
@@ -181,7 +176,7 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0) {
- brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n",
+ brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n",
ret);
goto done;
}
@@ -198,7 +193,7 @@ retry:
if ((id < prot->reqid) && (++retries < RETRIES))
goto retry;
if (id != prot->reqid) {
- brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_err("%s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
@@ -260,7 +255,7 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
if (id != prot->reqid) {
- brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_err("%s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
@@ -277,76 +272,6 @@ done:
return ret;
}
-int
-brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
- int len)
-{
- struct brcmf_proto *prot = drvr->prot;
- int ret = -1;
-
- if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
- brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
- return ret;
- }
- mutex_lock(&drvr->proto_block);
-
- brcmf_dbg(TRACE, "Enter\n");
-
- if (len > BRCMF_DCMD_MAXLEN)
- goto done;
-
- if (prot->pending == true) {
- brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
- dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd,
- (unsigned long)prot->lastcmd);
- if (dcmd->cmd == BRCMF_C_SET_VAR ||
- dcmd->cmd == BRCMF_C_GET_VAR)
- brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf);
-
- goto done;
- }
-
- prot->pending = true;
- prot->lastcmd = dcmd->cmd;
- if (dcmd->set)
- ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd,
- dcmd->buf, len);
- else {
- ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd,
- dcmd->buf, len);
- if (ret > 0)
- dcmd->used = ret -
- sizeof(struct brcmf_proto_cdc_dcmd);
- }
-
- if (ret >= 0)
- ret = 0;
- else {
- struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
- /* len == needed when set/query fails from dongle */
- dcmd->needed = le32_to_cpu(msg->len);
- }
-
- /* Intercept the wme_dp dongle cmd here */
- if (!ret && dcmd->cmd == BRCMF_C_SET_VAR &&
- !strcmp(dcmd->buf, "wme_dp")) {
- int slen;
- __le32 val = 0;
-
- slen = strlen("wme_dp") + 1;
- if (len >= (int)(slen + sizeof(int)))
- memcpy(&val, (char *)dcmd->buf + slen, sizeof(int));
- drvr->wme_dp = (u8) le32_to_cpu(val);
- }
-
- prot->pending = false;
-
-done:
- mutex_unlock(&drvr->proto_block);
-
- return ret;
-}
-
static bool pkt_sum_needed(struct sk_buff *skb)
{
return skb->ip_summed == CHECKSUM_PARTIAL;
@@ -392,7 +317,7 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
- brcmf_dbg(ERROR, "rx data too short (%d < %d)\n",
+ brcmf_err("rx data too short (%d < %d)\n",
pktbuf->len, BDC_HEADER_LEN);
return -EBADE;
}
@@ -401,13 +326,13 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
*ifidx = BDC_GET_IF_IDX(h);
if (*ifidx >= BRCMF_MAX_IFS) {
- brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx);
+ brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
return -EBADE;
}
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
BDC_PROTO_VER) {
- brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n",
+ brcmf_err("%s: non-BDC packet received, flags 0x%x\n",
brcmf_ifname(drvr, *ifidx), h->flags);
return -EBADE;
}
@@ -436,7 +361,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
- brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n");
+ brcmf_err("struct brcmf_proto is not correctly defined\n");
goto fail;
}
@@ -458,35 +383,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)
drvr->prot = NULL;
}
-int brcmf_proto_init(struct brcmf_pub *drvr)
-{
- int ret = 0;
- char buf[128];
-
- brcmf_dbg(TRACE, "Enter\n");
-
- mutex_lock(&drvr->proto_block);
-
- /* Get the device MAC address */
- strcpy(buf, "cur_etheraddr");
- ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
- buf, sizeof(buf));
- if (ret < 0) {
- mutex_unlock(&drvr->proto_block);
- return ret;
- }
- memcpy(drvr->mac, buf, ETH_ALEN);
-
- mutex_unlock(&drvr->proto_block);
-
- ret = brcmf_c_preinit_dcmds(drvr);
-
- /* Always assumes wl for now */
- drvr->iswl = true;
-
- return ret;
-}
-
void brcmf_proto_stop(struct brcmf_pub *drvr)
{
/* Nothing to do for CDC */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 15c5db5752d1..f8b52e5b941a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -18,28 +18,21 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/sched.h>
#include <linux/netdevice.h>
-#include <asm/unaligned.h>
-#include <defs.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "dhd.h"
#include "dhd_bus.h"
#include "dhd_proto.h"
#include "dhd_dbg.h"
+#include "fwil.h"
-#define BRCM_OUI "\x00\x10\x18"
-#define DOT11_OUI_LEN 3
-#define BCMILCP_BCM_SUBTYPE_EVENT 1
-#define PKTFILTER_BUF_SIZE 2048
+#define PKTFILTER_BUF_SIZE 128
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
-
-#define MSGTRACE_VERSION 1
-
-#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u)
-#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
- offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern)
+#define BRCMF_DEFAULT_BCN_TIMEOUT 3
+#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
+#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
+#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
#ifdef DEBUG
static const char brcmf_version[] =
@@ -50,89 +43,6 @@ static const char brcmf_version[] =
"Dongle Host Driver, version " BRCMF_VERSION_STR;
#endif
-/* Message trace header */
-struct msgtrace_hdr {
- u8 version;
- u8 spare;
- __be16 len; /* Len of the trace */
- __be32 seqnum; /* Sequence number of message. Useful
- * if the messsage has been lost
- * because of DMA error or a bus reset
- * (ex: SDIO Func2)
- */
- __be32 discarded_bytes; /* Number of discarded bytes because of
- trace overflow */
- __be32 discarded_printf; /* Number of discarded printf
- because of trace overflow */
-} __packed;
-
-
-uint
-brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
-{
- uint len;
-
- len = strlen(name) + 1;
-
- if ((len + datalen) > buflen)
- return 0;
-
- strncpy(buf, name, buflen);
-
- /* append data onto the end of the name string */
- if (data && datalen) {
- memcpy(&buf[len], data, datalen);
- len += datalen;
- }
-
- return len;
-}
-
-uint
-brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
- char *buf, uint buflen, s32 bssidx)
-{
- const s8 *prefix = "bsscfg:";
- s8 *p;
- u32 prefixlen;
- u32 namelen;
- u32 iolen;
- __le32 bssidx_le;
-
- if (bssidx == 0)
- return brcmf_c_mkiovar(name, data, datalen, buf, buflen);
-
- prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
- namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */
- iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
-
- if (buflen < 0 || iolen > (u32)buflen) {
- brcmf_dbg(ERROR, "buffer is too short\n");
- return 0;
- }
-
- p = buf;
-
- /* copy prefix, no null */
- memcpy(p, prefix, prefixlen);
- p += prefixlen;
-
- /* copy iovar name including null */
- memcpy(p, name, namelen);
- p += namelen;
-
- /* bss config index as first data */
- bssidx_le = cpu_to_le32(bssidx);
- memcpy(p, &bssidx_le, sizeof(bssidx_le));
- p += sizeof(bssidx_le);
-
- /* parameter buffer follows */
- if (datalen)
- memcpy(p, data, datalen);
-
- return iolen;
-
-}
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
struct sk_buff *pkt, int prec)
@@ -170,7 +80,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
brcmu_pktq_pdeq_tail(q, eprec);
if (p == NULL)
- brcmf_dbg(ERROR, "brcmu_pktq_penq() failed, oldest %d\n",
+ brcmf_err("brcmu_pktq_penq() failed, oldest %d\n",
discard_oldest);
brcmu_pkt_buf_free_skb(p);
@@ -179,415 +89,22 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
/* Enqueue */
p = brcmu_pktq_penq(q, prec, pkt);
if (p == NULL)
- brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n");
+ brcmf_err("brcmu_pktq_penq() failed\n");
return p != NULL;
}
-#ifdef DEBUG
-static void
-brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
-{
- uint i, status, reason;
- bool group = false, flush_txq = false, link = false;
- char *auth_str, *event_name;
- unsigned char *buf;
- char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
- static struct {
- uint event;
- char *event_name;
- } event_names[] = {
- {
- BRCMF_E_SET_SSID, "SET_SSID"}, {
- BRCMF_E_JOIN, "JOIN"}, {
- BRCMF_E_START, "START"}, {
- BRCMF_E_AUTH, "AUTH"}, {
- BRCMF_E_AUTH_IND, "AUTH_IND"}, {
- BRCMF_E_DEAUTH, "DEAUTH"}, {
- BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, {
- BRCMF_E_ASSOC, "ASSOC"}, {
- BRCMF_E_ASSOC_IND, "ASSOC_IND"}, {
- BRCMF_E_REASSOC, "REASSOC"}, {
- BRCMF_E_REASSOC_IND, "REASSOC_IND"}, {
- BRCMF_E_DISASSOC, "DISASSOC"}, {
- BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, {
- BRCMF_E_QUIET_START, "START_QUIET"}, {
- BRCMF_E_QUIET_END, "END_QUIET"}, {
- BRCMF_E_BEACON_RX, "BEACON_RX"}, {
- BRCMF_E_LINK, "LINK"}, {
- BRCMF_E_MIC_ERROR, "MIC_ERROR"}, {
- BRCMF_E_NDIS_LINK, "NDIS_LINK"}, {
- BRCMF_E_ROAM, "ROAM"}, {
- BRCMF_E_TXFAIL, "TXFAIL"}, {
- BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, {
- BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
- BRCMF_E_PRUNE, "PRUNE"}, {
- BRCMF_E_AUTOAUTH, "AUTOAUTH"}, {
- BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, {
- BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
- BRCMF_E_ADDTS_IND, "ADDTS_IND"}, {
- BRCMF_E_DELTS_IND, "DELTS_IND"}, {
- BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, {
- BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, {
- BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
- BRCMF_E_ROAM_PREP, "ROAM_PREP"}, {
- BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
- BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
- BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
- BRCMF_E_JOIN_START, "JOIN_START"}, {
- BRCMF_E_ROAM_START, "ROAM_START"}, {
- BRCMF_E_ASSOC_START, "ASSOC_START"}, {
- BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
- BRCMF_E_RADIO, "RADIO"}, {
- BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
- BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
- BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
- BRCMF_E_PSK_SUP, "PSK_SUP"}, {
- BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
- BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
- BRCMF_E_ICV_ERROR, "ICV_ERROR"}, {
- BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
- BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
- BRCMF_E_TRACE, "TRACE"}, {
- BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, {
- BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
- BRCMF_E_IF, "IF"}, {
- BRCMF_E_RSSI, "RSSI"}, {
- BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
- BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT"}
- };
- uint event_type, flags, auth_type, datalen;
- static u32 seqnum_prev;
- struct msgtrace_hdr hdr;
- u32 nblost;
- char *s, *p;
-
- event_type = be32_to_cpu(event->event_type);
- flags = be16_to_cpu(event->flags);
- status = be32_to_cpu(event->status);
- reason = be32_to_cpu(event->reason);
- auth_type = be32_to_cpu(event->auth_type);
- datalen = be32_to_cpu(event->datalen);
- /* debug dump of event messages */
- sprintf(eabuf, "%pM", event->addr);
-
- event_name = "UNKNOWN";
- for (i = 0; i < ARRAY_SIZE(event_names); i++) {
- if (event_names[i].event == event_type)
- event_name = event_names[i].event_name;
- }
-
- brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type);
- brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
- flags, status, reason, auth_type, eabuf);
-
- if (flags & BRCMF_EVENT_MSG_LINK)
- link = true;
- if (flags & BRCMF_EVENT_MSG_GROUP)
- group = true;
- if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
- flush_txq = true;
-
- switch (event_type) {
- case BRCMF_E_START:
- case BRCMF_E_DEAUTH:
- case BRCMF_E_DISASSOC:
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
- break;
-
- case BRCMF_E_ASSOC_IND:
- case BRCMF_E_REASSOC_IND:
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
- break;
-
- case BRCMF_E_ASSOC:
- case BRCMF_E_REASSOC:
- if (status == BRCMF_E_STATUS_SUCCESS)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n",
- event_name, eabuf);
- else if (status == BRCMF_E_STATUS_TIMEOUT)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n",
- event_name, eabuf);
- else if (status == BRCMF_E_STATUS_FAIL)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
- event_name, eabuf, (int)reason);
- else
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n",
- event_name, eabuf, (int)status);
- break;
-
- case BRCMF_E_DEAUTH_IND:
- case BRCMF_E_DISASSOC_IND:
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n",
- event_name, eabuf, (int)reason);
- break;
-
- case BRCMF_E_AUTH:
- case BRCMF_E_AUTH_IND:
- if (auth_type == WLAN_AUTH_OPEN)
- auth_str = "Open System";
- else if (auth_type == WLAN_AUTH_SHARED_KEY)
- auth_str = "Shared Key";
- else {
- sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
- auth_str = err_msg;
- }
- if (event_type == BRCMF_E_AUTH_IND)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n",
- event_name, eabuf, auth_str);
- else if (status == BRCMF_E_STATUS_SUCCESS)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n",
- event_name, eabuf, auth_str);
- else if (status == BRCMF_E_STATUS_TIMEOUT)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
- event_name, eabuf, auth_str);
- else if (status == BRCMF_E_STATUS_FAIL) {
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
- event_name, eabuf, auth_str, (int)reason);
- }
-
- break;
-
- case BRCMF_E_JOIN:
- case BRCMF_E_ROAM:
- case BRCMF_E_SET_SSID:
- if (status == BRCMF_E_STATUS_SUCCESS)
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n",
- event_name, eabuf);
- else if (status == BRCMF_E_STATUS_FAIL)
- brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name);
- else if (status == BRCMF_E_STATUS_NO_NETWORKS)
- brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n",
- event_name);
- else
- brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n",
- event_name, (int)status);
- break;
-
- case BRCMF_E_BEACON_RX:
- if (status == BRCMF_E_STATUS_SUCCESS)
- brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name);
- else if (status == BRCMF_E_STATUS_FAIL)
- brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name);
- else
- brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n",
- event_name, status);
- break;
-
- case BRCMF_E_LINK:
- brcmf_dbg(EVENT, "MACEVENT: %s %s\n",
- event_name, link ? "UP" : "DOWN");
- break;
-
- case BRCMF_E_MIC_ERROR:
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
- event_name, eabuf, group, flush_txq);
- break;
-
- case BRCMF_E_ICV_ERROR:
- case BRCMF_E_UNICAST_DECODE_ERROR:
- case BRCMF_E_MULTICAST_DECODE_ERROR:
- brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
- break;
-
- case BRCMF_E_TXFAIL:
- brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf);
- break;
-
- case BRCMF_E_SCAN_COMPLETE:
- case BRCMF_E_PMKID_CACHE:
- brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
- break;
-
- case BRCMF_E_ESCAN_RESULT:
- brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
- datalen = 0;
- break;
-
- case BRCMF_E_PFN_NET_FOUND:
- case BRCMF_E_PFN_NET_LOST:
- case BRCMF_E_PFN_SCAN_COMPLETE:
- brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name);
- break;
-
- case BRCMF_E_PSK_SUP:
- case BRCMF_E_PRUNE:
- brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n",
- event_name, (int)status, (int)reason);
- break;
-
- case BRCMF_E_TRACE:
- buf = (unsigned char *) event_data;
- memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
-
- if (hdr.version != MSGTRACE_VERSION) {
- brcmf_dbg(ERROR,
- "MACEVENT: %s [unsupported version --> brcmf"
- " version:%d dongle version:%d]\n",
- event_name, MSGTRACE_VERSION, hdr.version);
- /* Reset datalen to avoid display below */
- datalen = 0;
- break;
- }
-
- /* There are 2 bytes available at the end of data */
- *(buf + sizeof(struct msgtrace_hdr)
- + be16_to_cpu(hdr.len)) = '\0';
-
- if (be32_to_cpu(hdr.discarded_bytes)
- || be32_to_cpu(hdr.discarded_printf))
- brcmf_dbg(ERROR,
- "WLC_E_TRACE: [Discarded traces in dongle -->"
- " discarded_bytes %d discarded_printf %d]\n",
- be32_to_cpu(hdr.discarded_bytes),
- be32_to_cpu(hdr.discarded_printf));
-
- nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
- if (nblost > 0)
- brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum "
- " %d nblost %d\n", be32_to_cpu(hdr.seqnum),
- nblost);
- seqnum_prev = be32_to_cpu(hdr.seqnum);
-
- /* Display the trace buffer. Advance from \n to \n to
- * avoid display big
- * printf (issue with Linux printk )
- */
- p = (char *)&buf[sizeof(struct msgtrace_hdr)];
- while ((s = strstr(p, "\n")) != NULL) {
- *s = '\0';
- pr_debug("%s\n", p);
- p = s + 1;
- }
- pr_debug("%s\n", p);
-
- /* Reset datalen to avoid display below */
- datalen = 0;
- break;
-
- case BRCMF_E_RSSI:
- brcmf_dbg(EVENT, "MACEVENT: %s %d\n",
- event_name, be32_to_cpu(*((__be32 *)event_data)));
- break;
-
- default:
- brcmf_dbg(EVENT,
- "MACEVENT: %s %d, MAC %s, status %d, reason %d, "
- "auth %d\n", event_name, event_type, eabuf,
- (int)status, (int)reason, (int)auth_type);
- break;
- }
-
- /* show any appended data */
- brcmf_dbg_hex_dump(datalen, event_data, datalen, "Received data");
-}
-#endif /* DEBUG */
-
-int
-brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
- struct brcmf_event_msg *event, void **data_ptr)
-{
- /* check whether packet is a BRCM event pkt */
- struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
- struct brcmf_if_event *ifevent;
- char *event_data;
- u32 type, status;
- u16 flags;
- int evlen;
-
- if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
- brcmf_dbg(ERROR, "mismatched OUI, bailing\n");
- return -EBADE;
- }
-
- /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
- if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
- BCMILCP_BCM_SUBTYPE_EVENT) {
- brcmf_dbg(ERROR, "mismatched subtype, bailing\n");
- return -EBADE;
- }
-
- *data_ptr = &pvt_data[1];
- event_data = *data_ptr;
-
- /* memcpy since BRCM event pkt may be unaligned. */
- memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));
-
- type = get_unaligned_be32(&event->event_type);
- flags = get_unaligned_be16(&event->flags);
- status = get_unaligned_be32(&event->status);
- evlen = get_unaligned_be32(&event->datalen) +
- sizeof(struct brcmf_event);
-
- switch (type) {
- case BRCMF_E_IF:
- ifevent = (struct brcmf_if_event *) event_data;
- brcmf_dbg(TRACE, "if event\n");
-
- if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
- if (ifevent->action == BRCMF_E_IF_ADD)
- brcmf_add_if(drvr->dev, ifevent->ifidx,
- event->ifname,
- pvt_data->eth.h_dest);
- else
- brcmf_del_if(drvr, ifevent->ifidx);
- } else {
- brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
- ifevent->ifidx, event->ifname);
- }
-
- /* send up the if event: btamp user needs it */
- *ifidx = brcmf_ifname2idx(drvr, event->ifname);
- break;
-
- /* These are what external supplicant/authenticator wants */
- case BRCMF_E_LINK:
- case BRCMF_E_ASSOC_IND:
- case BRCMF_E_REASSOC_IND:
- case BRCMF_E_DISASSOC_IND:
- case BRCMF_E_MIC_ERROR:
- default:
- /* Fall through: this should get _everything_ */
-
- *ifidx = brcmf_ifname2idx(drvr, event->ifname);
- brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
- type, flags, status);
-
- /* put it back to BRCMF_E_NDIS_LINK */
- if (type == BRCMF_E_NDIS_LINK) {
- u32 temp1;
- __be32 temp2;
-
- temp1 = get_unaligned_be32(&event->event_type);
- brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n",
- temp1);
-
- temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK);
- memcpy((void *)(&pvt_data->msg.event_type), &temp2,
- sizeof(pvt_data->msg.event_type));
- }
- break;
- }
-
-#ifdef DEBUG
- if (BRCMF_EVENT_ON())
- brcmf_c_show_host_event(event, event_data);
-#endif /* DEBUG */
-
- return 0;
-}
-
/* Convert user's input in hex pattern to byte-size mask */
static int brcmf_c_pattern_atoh(char *src, char *dst)
{
int i;
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
- brcmf_dbg(ERROR, "Mask invalid format. Needs to start with 0x\n");
+ brcmf_err("Mask invalid format. Needs to start with 0x\n");
return -EINVAL;
}
src = src + 2; /* Skip past 0x */
if (strlen(src) % 2 != 0) {
- brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n");
+ brcmf_err("Mask invalid format. Length must be even.\n");
return -EINVAL;
}
for (i = 0; *src != '\0'; i++) {
@@ -603,90 +120,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst)
return i;
}
-void
-brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
- int master_mode)
+static void
+brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
+ int master_mode)
{
unsigned long res;
- char *argv[8];
- int i = 0;
- const char *str;
- int buf_len;
- int str_len;
+ char *argv;
char *arg_save = NULL, *arg_org = NULL;
- int rc;
- char buf[128];
+ s32 err;
struct brcmf_pkt_filter_enable_le enable_parm;
- struct brcmf_pkt_filter_enable_le *pkt_filterp;
- __le32 mmode_le;
- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
+ arg_save = kstrdup(arg, GFP_ATOMIC);
if (!arg_save)
goto fail;
arg_org = arg_save;
- memcpy(arg_save, arg, strlen(arg) + 1);
- argv[i] = strsep(&arg_save, " ");
+ argv = strsep(&arg_save, " ");
- i = 0;
- if (NULL == argv[i]) {
- brcmf_dbg(ERROR, "No args provided\n");
+ if (argv == NULL) {
+ brcmf_err("No args provided\n");
goto fail;
}
- str = "pkt_filter_enable";
- str_len = strlen(str);
- strncpy(buf, str, str_len);
- buf[str_len] = '\0';
- buf_len = str_len + 1;
-
- pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1);
-
/* Parse packet filter id. */
enable_parm.id = 0;
- if (!kstrtoul(argv[i], 0, &res))
+ if (!kstrtoul(argv, 0, &res))
enable_parm.id = cpu_to_le32((u32)res);
- /* Parse enable/disable value. */
+ /* Enable/disable the specified filter. */
enable_parm.enable = cpu_to_le32(enable);
- buf_len += sizeof(enable_parm);
- memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
+ err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
+ sizeof(enable_parm));
+ if (err)
+ brcmf_err("Set pkt_filter_enable error (%d)\n", err);
- /* Enable/disable the specified filter. */
- rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
- rc = rc >= 0 ? 0 : rc;
- if (rc)
- brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
- arg, rc);
- else
- brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
-
- /* Contorl the master mode */
- mmode_le = cpu_to_le32(master_mode);
- brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
- sizeof(buf));
- rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf,
- sizeof(buf));
- rc = rc >= 0 ? 0 : rc;
- if (rc)
- brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
- arg, rc);
+ /* Control the master mode */
+ err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
+ if (err)
+ brcmf_err("Set pkt_filter_mode error (%d)\n", err);
fail:
kfree(arg_org);
}
-void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
+static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
{
- const char *str;
- struct brcmf_pkt_filter_le pkt_filter;
- struct brcmf_pkt_filter_le *pkt_filterp;
+ struct brcmf_pkt_filter_le *pkt_filter;
unsigned long res;
int buf_len;
- int str_len;
- int rc;
+ s32 err;
u32 mask_size;
u32 pattern_size;
char *argv[8], *buf = NULL;
@@ -704,104 +188,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
goto fail;
argv[i] = strsep(&arg_save, " ");
- while (argv[i++])
+ while (argv[i]) {
+ i++;
+ if (i >= 8) {
+ brcmf_err("Too many parameters\n");
+ goto fail;
+ }
argv[i] = strsep(&arg_save, " ");
+ }
- i = 0;
- if (NULL == argv[i]) {
- brcmf_dbg(ERROR, "No args provided\n");
+ if (i != 6) {
+ brcmf_err("Not enough args provided %d\n", i);
goto fail;
}
- str = "pkt_filter_add";
- strcpy(buf, str);
- str_len = strlen(str);
- buf_len = str_len + 1;
-
- pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1);
+ pkt_filter = (struct brcmf_pkt_filter_le *)buf;
/* Parse packet filter id. */
- pkt_filter.id = 0;
- if (!kstrtoul(argv[i], 0, &res))
- pkt_filter.id = cpu_to_le32((u32)res);
-
- if (NULL == argv[++i]) {
- brcmf_dbg(ERROR, "Polarity not provided\n");
- goto fail;
- }
+ pkt_filter->id = 0;
+ if (!kstrtoul(argv[0], 0, &res))
+ pkt_filter->id = cpu_to_le32((u32)res);
/* Parse filter polarity. */
- pkt_filter.negate_match = 0;
- if (!kstrtoul(argv[i], 0, &res))
- pkt_filter.negate_match = cpu_to_le32((u32)res);
-
- if (NULL == argv[++i]) {
- brcmf_dbg(ERROR, "Filter type not provided\n");
- goto fail;
- }
+ pkt_filter->negate_match = 0;
+ if (!kstrtoul(argv[1], 0, &res))
+ pkt_filter->negate_match = cpu_to_le32((u32)res);
/* Parse filter type. */
- pkt_filter.type = 0;
- if (!kstrtoul(argv[i], 0, &res))
- pkt_filter.type = cpu_to_le32((u32)res);
-
- if (NULL == argv[++i]) {
- brcmf_dbg(ERROR, "Offset not provided\n");
- goto fail;
- }
+ pkt_filter->type = 0;
+ if (!kstrtoul(argv[2], 0, &res))
+ pkt_filter->type = cpu_to_le32((u32)res);
/* Parse pattern filter offset. */
- pkt_filter.u.pattern.offset = 0;
- if (!kstrtoul(argv[i], 0, &res))
- pkt_filter.u.pattern.offset = cpu_to_le32((u32)res);
-
- if (NULL == argv[++i]) {
- brcmf_dbg(ERROR, "Bitmask not provided\n");
- goto fail;
- }
+ pkt_filter->u.pattern.offset = 0;
+ if (!kstrtoul(argv[3], 0, &res))
+ pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
/* Parse pattern filter mask. */
- mask_size =
- brcmf_c_pattern_atoh
- (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
-
- if (NULL == argv[++i]) {
- brcmf_dbg(ERROR, "Pattern not provided\n");
- goto fail;
- }
+ mask_size = brcmf_c_pattern_atoh(argv[4],
+ (char *)pkt_filter->u.pattern.mask_and_pattern);
/* Parse pattern filter pattern. */
- pattern_size =
- brcmf_c_pattern_atoh(argv[i],
- (char *)&pkt_filterp->u.pattern.
- mask_and_pattern[mask_size]);
+ pattern_size = brcmf_c_pattern_atoh(argv[5],
+ (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
if (mask_size != pattern_size) {
- brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
+ brcmf_err("Mask and pattern not the same size\n");
goto fail;
}
- pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size);
- buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
- buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
- /* Keep-alive attributes are set in local
- * variable (keep_alive_pkt), and
- ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
- ** guarantee that the buffer is properly aligned.
- */
- memcpy((char *)pkt_filterp,
- &pkt_filter,
- BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
-
- rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
- rc = rc >= 0 ? 0 : rc;
+ pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
+ buf_len = offsetof(struct brcmf_pkt_filter_le,
+ u.pattern.mask_and_pattern);
+ buf_len += mask_size + pattern_size;
- if (rc)
- brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
- arg, rc);
- else
- brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
+ err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
+ buf_len);
+ if (err)
+ brcmf_err("Set pkt_filter_add error (%d)\n", err);
fail:
kfree(arg_org);
@@ -809,130 +253,125 @@ fail:
kfree(buf);
}
-static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
- char iovbuf[32];
- int retcode;
- __le32 arp_mode_le;
-
- arp_mode_le = cpu_to_le32(arp_mode);
- brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf,
- sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
- retcode = retcode >= 0 ? 0 : retcode;
- if (retcode)
- brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n",
- arp_mode, retcode);
- else
- brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n",
- arp_mode);
-}
-
-static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
-{
- char iovbuf[32];
- int retcode;
- __le32 arp_enable_le;
-
- arp_enable_le = cpu_to_le32(arp_enable);
-
- brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,
- iovbuf, sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
- retcode = retcode >= 0 ? 0 : retcode;
- if (retcode)
- brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n",
- arp_enable, retcode);
- else
- brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n",
- arp_enable);
-}
-
-int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
-{
- char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
- "event_msgs" + '\0' + bitvec */
- char buf[128], *ptr;
- __le32 roaming_le = cpu_to_le32(1);
- __le32 bcn_timeout_le = cpu_to_le32(3);
- __le32 scan_assoc_time_le = cpu_to_le32(40);
- __le32 scan_unassoc_time_le = cpu_to_le32(40);
- int i;
+ s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+ u8 buf[BRCMF_DCMD_SMLEN];
+ char *ptr;
+ s32 err;
struct brcmf_bus_dcmd *cmdlst;
struct list_head *cur, *q;
- mutex_lock(&drvr->proto_block);
-
- /* Set Country code */
- if (drvr->country_code[0] != 0) {
- if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY,
- drvr->country_code,
- sizeof(drvr->country_code)) < 0)
- brcmf_dbg(ERROR, "country code setting failed\n");
+ /* retreive mac address */
+ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+ sizeof(ifp->mac_addr));
+ if (err < 0) {
+ brcmf_err("Retreiving cur_etheraddr failed, %d\n",
+ err);
+ goto done;
}
+ memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
- ptr = buf;
- brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
- brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
+ strcpy(buf, "ver");
+ err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
+ if (err < 0) {
+ brcmf_err("Retreiving version information failed, %d\n",
+ err);
+ goto done;
+ }
+ ptr = (char *)buf;
strsep(&ptr, "\n");
/* Print fw version info */
- brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
+ brcmf_err("Firmware version = %s\n", buf);
- /* Setup timeout if Beacons are lost and roam is off to report
- link down */
- brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
- sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
+ /*
+ * Setup timeout if Beacons are lost and roam is off to report
+ * link down
+ */
+ err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
+ BRCMF_DEFAULT_BCN_TIMEOUT);
+ if (err) {
+ brcmf_err("bcn_timeout error (%d)\n", err);
+ goto done;
+ }
/* Enable/Disable build-in roaming to allowed ext supplicant to take
- of romaing */
- brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* Setup event_msgs */
- brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));
-
- /* Set and enable ARP offload feature */
- brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
- brcmf_c_arp_offload_enable(drvr, true);
-
- /* Set up pkt filter */
- for (i = 0; i < drvr->pktfilter_count; i++) {
- brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]);
- brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i],
- 0, true);
+ * of romaing
+ */
+ err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+ if (err) {
+ brcmf_err("roam_off error (%d)\n", err);
+ goto done;
+ }
+
+ /* Setup event_msgs, enable E_IF */
+ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
+ BRCMF_EVENTING_MASK_LEN);
+ if (err) {
+ brcmf_err("Get event_msgs error (%d)\n", err);
+ goto done;
+ }
+ setbit(eventmask, BRCMF_E_IF);
+ err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
+ BRCMF_EVENTING_MASK_LEN);
+ if (err) {
+ brcmf_err("Set event_msgs error (%d)\n", err);
+ goto done;
}
+ /* Setup default scan channel time */
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
+ if (err) {
+ brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+ err);
+ goto done;
+ }
+
+ /* Setup default scan unassoc time */
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
+ if (err) {
+ brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+ err);
+ goto done;
+ }
+
+ /* Try to set and enable ARP offload feature, this may fail */
+ err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE);
+ if (err) {
+ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
+ BRCMF_ARPOL_MODE, err);
+ err = 0;
+ } else {
+ err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1);
+ if (err) {
+ brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n",
+ err);
+ err = 0;
+ } else
+ brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n",
+ BRCMF_ARPOL_MODE);
+ }
+
+ /* Setup packet filter */
+ brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
+ 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, &drvr->bus_if->dcmd_list) {
+ 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_c_mkiovar(cmdlst->name, cmdlst->param,
- cmdlst->param_len, iovbuf,
- sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
+ brcmf_fil_iovar_data_set(ifp, cmdlst->name,
+ cmdlst->param,
+ cmdlst->param_len);
}
list_del(cur);
kfree(cmdlst);
}
-
- mutex_unlock(&drvr->proto_block);
-
- return 0;
+done:
+ return err;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 7f89540b56da..57671eddf79d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -14,12 +14,9 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/debugfs.h>
-#include <linux/if_ether.h>
-#include <linux/if.h>
-#include <linux/ieee80211.h>
+#include <linux/netdevice.h>
#include <linux/module.h>
-#include <defs.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "dhd.h"
@@ -46,10 +43,12 @@ void brcmf_debugfs_exit(void)
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
{
+ struct device *dev = drvr->bus_if->dev;
+
if (!root_folder)
return -ENODEV;
- drvr->dbgfs_dir = debugfs_create_dir(dev_name(drvr->dev), root_folder);
+ drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
return PTR_RET(drvr->dbgfs_dir);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index fb508c2256dd..f2ab01cd7966 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -18,7 +18,6 @@
#define _BRCMF_DBG_H_
/* message levels */
-#define BRCMF_ERROR_VAL 0x0001
#define BRCMF_TRACE_VAL 0x0002
#define BRCMF_INFO_VAL 0x0004
#define BRCMF_DATA_VAL 0x0008
@@ -27,27 +26,34 @@
#define BRCMF_HDRS_VAL 0x0040
#define BRCMF_BYTES_VAL 0x0080
#define BRCMF_INTR_VAL 0x0100
-#define BRCMF_GLOM_VAL 0x0400
-#define BRCMF_EVENT_VAL 0x0800
-#define BRCMF_BTA_VAL 0x1000
-#define BRCMF_ISCAN_VAL 0x2000
+#define BRCMF_GLOM_VAL 0x0200
+#define BRCMF_EVENT_VAL 0x0400
+#define BRCMF_BTA_VAL 0x0800
+#define BRCMF_FIL_VAL 0x1000
+#define BRCMF_USB_VAL 0x2000
+#define BRCMF_SCAN_VAL 0x4000
+#define BRCMF_CONN_VAL 0x8000
+
+/* Macro for error messages. net_ratelimit() is used when driver
+ * debugging is not selected. When debugging the driver error
+ * messages are as important as other tracing or even more so.
+ */
+#ifdef CONFIG_BRCMDBG
+#define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__)
+#else
+#define brcmf_err(fmt, ...) \
+ do { \
+ if (net_ratelimit()) \
+ pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+#endif
#if defined(DEBUG)
-#define brcmf_dbg(level, fmt, ...) \
-do { \
- if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \
- if (brcmf_msg_level & BRCMF_##level##_VAL) { \
- if (net_ratelimit()) \
- pr_debug("%s: " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } else { \
- if (brcmf_msg_level & BRCMF_##level##_VAL) { \
- pr_debug("%s: " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
+#define brcmf_dbg(level, fmt, ...) \
+do { \
+ if (brcmf_msg_level & BRCMF_##level##_VAL) \
+ pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
@@ -56,6 +62,7 @@ do { \
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
+#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
#else /* (defined DEBUG) || (defined DEBUG) */
@@ -67,6 +74,7 @@ do { \
#define BRCMF_BYTES_ON() 0
#define BRCMF_GLOM_ON() 0
#define BRCMF_EVENT_ON() 0
+#define BRCMF_FIL_ON() 0
#endif /* defined(DEBUG) */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index d7c76ce9d8cb..74a616b4de8e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -16,27 +16,11 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/hardirq.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
#include <linux/module.h>
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
-#include <defs.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
@@ -45,55 +29,29 @@
#include "dhd_proto.h"
#include "dhd_dbg.h"
#include "wl_cfg80211.h"
+#include "fwil.h"
MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
+MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
MODULE_LICENSE("Dual BSD/GPL");
-
-/* Interface control information */
-struct brcmf_if {
- struct brcmf_pub *drvr; /* back pointer to brcmf_pub */
- /* OS/stack specifics */
- struct net_device *ndev;
- struct net_device_stats stats;
- int idx; /* iface idx in dongle */
- u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
-};
+#define MAX_WAIT_FOR_8021X_TX 50 /* msecs */
/* Error bits */
-int brcmf_msg_level = BRCMF_ERROR_VAL;
+int brcmf_msg_level;
module_param(brcmf_msg_level, int, 0);
-int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name)
-{
- int i = BRCMF_MAX_IFS;
- struct brcmf_if *ifp;
-
- if (name == NULL || *name == '\0')
- return 0;
-
- while (--i > 0) {
- ifp = drvr->iflist[i];
- if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ))
- break;
- }
-
- brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name);
-
- return i; /* default - the primary interface */
-}
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
{
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
- brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx);
+ brcmf_err("ifidx %d out of range\n", ifidx);
return "<if_bad>";
}
if (drvr->iflist[ifidx] == NULL) {
- brcmf_dbg(ERROR, "null i/f %d\n", ifidx);
+ brcmf_err("null i/f %d\n", ifidx);
return "<if_null>";
}
@@ -105,38 +63,33 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
static void _brcmf_set_multicast_list(struct work_struct *work)
{
+ struct brcmf_if *ifp;
struct net_device *ndev;
struct netdev_hw_addr *ha;
- u32 dcmd_value, cnt;
+ u32 cmd_value, cnt;
__le32 cnt_le;
- __le32 dcmd_le_value;
-
- struct brcmf_dcmd dcmd;
char *buf, *bufp;
- uint buflen;
- int ret;
+ u32 buflen;
+ s32 err;
- struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
- multicast_work);
+ brcmf_dbg(TRACE, "enter\n");
- ndev = drvr->iflist[0]->ndev;
- cnt = netdev_mc_count(ndev);
+ ifp = container_of(work, struct brcmf_if, multicast_work);
+ ndev = ifp->ndev;
/* Determine initial value of allmulti flag */
- dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
+ cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
/* Send down the multicast list first. */
-
- buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
- bufp = buf = kmalloc(buflen, GFP_ATOMIC);
- if (!bufp)
+ cnt = netdev_mc_count(ndev);
+ buflen = sizeof(cnt) + (cnt * ETH_ALEN);
+ buf = kmalloc(buflen, GFP_ATOMIC);
+ if (!buf)
return;
-
- strcpy(bufp, "mcast_list");
- bufp += strlen("mcast_list") + 1;
+ bufp = buf;
cnt_le = cpu_to_le32(cnt);
- memcpy(bufp, &cnt_le, sizeof(cnt));
+ memcpy(bufp, &cnt_le, sizeof(cnt_le));
bufp += sizeof(cnt_le);
netdev_for_each_mc_addr(ha, ndev) {
@@ -147,129 +100,66 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
cnt--;
}
- memset(&dcmd, 0, sizeof(dcmd));
- dcmd.cmd = BRCMF_C_SET_VAR;
- dcmd.buf = buf;
- dcmd.len = buflen;
- dcmd.set = true;
-
- ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
- if (ret < 0) {
- brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
- brcmf_ifname(drvr, 0), cnt);
- dcmd_value = cnt ? true : dcmd_value;
+ err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
+ if (err < 0) {
+ brcmf_err("Setting mcast_list failed, %d\n", err);
+ cmd_value = cnt ? true : cmd_value;
}
kfree(buf);
- /* Now send the allmulti setting. This is based on the setting in the
+ /*
+ * Now send the allmulti setting. This is based on the setting in the
* net_device flags, but might be modified above to be turned on if we
* were trying to set some addresses and dongle rejected it...
*/
+ err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
+ if (err < 0)
+ brcmf_err("Setting allmulti failed, %d\n", err);
- buflen = sizeof("allmulti") + sizeof(dcmd_value);
- buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf)
- return;
-
- dcmd_le_value = cpu_to_le32(dcmd_value);
-
- if (!brcmf_c_mkiovar
- ("allmulti", (void *)&dcmd_le_value,
- sizeof(dcmd_le_value), buf, buflen)) {
- brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
- brcmf_ifname(drvr, 0),
- (int)sizeof(dcmd_value), buflen);
- kfree(buf);
- return;
- }
-
- memset(&dcmd, 0, sizeof(dcmd));
- dcmd.cmd = BRCMF_C_SET_VAR;
- dcmd.buf = buf;
- dcmd.len = buflen;
- dcmd.set = true;
-
- ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
- if (ret < 0) {
- brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
- brcmf_ifname(drvr, 0),
- le32_to_cpu(dcmd_le_value));
- }
-
- kfree(buf);
-
- /* Finally, pick up the PROMISC flag as well, like the NIC
- driver does */
-
- dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
- dcmd_le_value = cpu_to_le32(dcmd_value);
-
- memset(&dcmd, 0, sizeof(dcmd));
- dcmd.cmd = BRCMF_C_SET_PROMISC;
- dcmd.buf = &dcmd_le_value;
- dcmd.len = sizeof(dcmd_le_value);
- dcmd.set = true;
-
- ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
- if (ret < 0) {
- brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
- brcmf_ifname(drvr, 0),
- le32_to_cpu(dcmd_le_value));
- }
+ /*Finally, pick up the PROMISC flag */
+ cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
+ if (err < 0)
+ brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
+ err);
}
static void
_brcmf_set_mac_address(struct work_struct *work)
{
- char buf[32];
- struct brcmf_dcmd dcmd;
- int ret;
-
- struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
- setmacaddr_work);
+ struct brcmf_if *ifp;
+ s32 err;
brcmf_dbg(TRACE, "enter\n");
- if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr->macvalue,
- ETH_ALEN, buf, 32)) {
- brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
- brcmf_ifname(drvr, 0));
- return;
- }
- memset(&dcmd, 0, sizeof(dcmd));
- dcmd.cmd = BRCMF_C_SET_VAR;
- dcmd.buf = buf;
- dcmd.len = 32;
- dcmd.set = true;
-
- ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
- if (ret < 0)
- brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
- brcmf_ifname(drvr, 0));
- else
- memcpy(drvr->iflist[0]->ndev->dev_addr,
- drvr->macvalue, ETH_ALEN);
- return;
+ ifp = container_of(work, struct brcmf_if, setmacaddr_work);
+ err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
+ ETH_ALEN);
+ if (err < 0) {
+ brcmf_err("Setting cur_etheraddr failed, %d\n", err);
+ } else {
+ brcmf_dbg(TRACE, "MAC address updated to %pM\n",
+ ifp->mac_addr);
+ memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+ }
}
static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{
struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_pub *drvr = ifp->drvr;
struct sockaddr *sa = (struct sockaddr *)addr;
- memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN);
- schedule_work(&drvr->setmacaddr_work);
+ memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
+ schedule_work(&ifp->setmacaddr_work);
return 0;
}
static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_pub *drvr = ifp->drvr;
- schedule_work(&drvr->multicast_work);
+ schedule_work(&ifp->multicast_work);
}
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
@@ -282,8 +172,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Reject if down */
if (!drvr->bus_if->drvr_up ||
- (drvr->bus_if->state == BRCMF_BUS_DOWN)) {
- brcmf_dbg(ERROR, "xmit rejected drvup=%d state=%d\n",
+ (drvr->bus_if->state != BRCMF_BUS_DATA)) {
+ brcmf_err("xmit rejected drvup=%d state=%d\n",
drvr->bus_if->drvr_up,
drvr->bus_if->state);
netif_stop_queue(ndev);
@@ -291,7 +181,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
if (!drvr->iflist[ifp->idx]) {
- brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
+ brcmf_err("bad ifidx %d\n", ifp->idx);
netif_stop_queue(ndev);
return -ENODEV;
}
@@ -307,7 +197,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
dev_kfree_skb(skb);
skb = skb2;
if (skb == NULL) {
- brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
+ brcmf_err("%s: skb_realloc_headroom failed\n",
brcmf_ifname(drvr, ifp->idx));
ret = -ENOMEM;
goto done;
@@ -329,7 +219,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
/* Use bus module to send data frame */
- ret = drvr->bus_if->brcmf_bus_txdata(drvr->dev, skb);
+ ret = brcmf_bus_txdata(drvr->bus_if, skb);
done:
if (ret)
@@ -360,32 +250,13 @@ void brcmf_txflowblock(struct device *dev, bool state)
}
}
-static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
- void *pktdata, struct brcmf_event_msg *event,
- void **data)
-{
- int bcmerror = 0;
-
- bcmerror = brcmf_c_host_event(drvr, ifidx, pktdata, event, data);
- if (bcmerror != 0)
- return bcmerror;
-
- if (drvr->iflist[*ifidx]->ndev)
- brcmf_cfg80211_event(drvr->iflist[*ifidx]->ndev,
- event, *data);
-
- return bcmerror;
-}
-
-void brcmf_rx_frame(struct device *dev, int ifidx,
+void brcmf_rx_frame(struct device *dev, u8 ifidx,
struct sk_buff_head *skb_list)
{
unsigned char *eth;
uint len;
- void *data;
struct sk_buff *skb, *pnext;
struct brcmf_if *ifp;
- struct brcmf_event_msg event;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
@@ -432,10 +303,7 @@ void brcmf_rx_frame(struct device *dev, int ifidx,
skb_pull(skb, ETH_HLEN);
/* Process special event packets and then discard them */
- if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
- brcmf_host_event(drvr, &ifidx,
- skb_mac_header(skb),
- &event, &data);
+ brcmf_fweh_process_skb(drvr, skb, &ifidx);
if (drvr->iflist[ifidx]) {
ifp = drvr->iflist[ifidx];
@@ -471,9 +339,11 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
- if (type == ETH_P_PAE)
+ if (type == ETH_P_PAE) {
atomic_dec(&drvr->pend_8021x_cnt);
-
+ if (waitqueue_active(&drvr->pend_8021x_wait))
+ wake_up(&drvr->pend_8021x_wait);
+ }
}
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
@@ -497,83 +367,26 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
return &ifp->stats;
}
-/* Retrieve current toe component enables, which are kept
- as a bitmap in toe_ol iovar */
-static int brcmf_toe_get(struct brcmf_pub *drvr, int ifidx, u32 *toe_ol)
-{
- struct brcmf_dcmd dcmd;
- __le32 toe_le;
- char buf[32];
- int ret;
-
- memset(&dcmd, 0, sizeof(dcmd));
-
- dcmd.cmd = BRCMF_C_GET_VAR;
- dcmd.buf = buf;
- dcmd.len = (uint) sizeof(buf);
- dcmd.set = false;
-
- strcpy(buf, "toe_ol");
- ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
- if (ret < 0) {
- /* Check for older dongle image that doesn't support toe_ol */
- if (ret == -EIO) {
- brcmf_dbg(ERROR, "%s: toe not supported by device\n",
- brcmf_ifname(drvr, ifidx));
- return -EOPNOTSUPP;
- }
-
- brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
- brcmf_ifname(drvr, ifidx), ret);
- return ret;
- }
-
- memcpy(&toe_le, buf, sizeof(u32));
- *toe_ol = le32_to_cpu(toe_le);
- return 0;
-}
-
-/* Set current toe component enables in toe_ol iovar,
- and set toe global enable iovar */
-static int brcmf_toe_set(struct brcmf_pub *drvr, int ifidx, u32 toe_ol)
+/*
+ * 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)
{
- struct brcmf_dcmd dcmd;
- char buf[32];
- int ret;
- __le32 toe_le = cpu_to_le32(toe_ol);
-
- memset(&dcmd, 0, sizeof(dcmd));
-
- dcmd.cmd = BRCMF_C_SET_VAR;
- dcmd.buf = buf;
- dcmd.len = (uint) sizeof(buf);
- dcmd.set = true;
-
- /* Set toe_ol as requested */
- strcpy(buf, "toe_ol");
- memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32));
+ s32 err;
- ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
- if (ret < 0) {
- brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
- brcmf_ifname(drvr, ifidx), ret);
- return ret;
+ 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;
}
- /* Enable toe globally only if any components are enabled. */
- toe_le = cpu_to_le32(toe_ol != 0);
-
- strcpy(buf, "toe");
- memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32));
+ err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
+ if (err < 0)
+ brcmf_err("Setting toe failed, %d\n", err);
- ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
- if (ret < 0) {
- brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
- brcmf_ifname(drvr, ifidx), ret);
- return ret;
- }
+ return err;
- return 0;
}
static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
@@ -584,15 +397,16 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
sprintf(info->driver, KBUILD_MODNAME);
sprintf(info->version, "%lu", drvr->drv_version);
- sprintf(info->bus_info, "%s", dev_name(drvr->dev));
+ sprintf(info->bus_info, "%s", dev_name(drvr->bus_if->dev));
}
static const struct ethtool_ops brcmf_ethtool_ops = {
.get_drvinfo = brcmf_ethtool_get_drvinfo,
};
-static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
+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;
@@ -626,15 +440,12 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
/* otherwise, require dongle to be up */
else if (!drvr->bus_if->drvr_up) {
- brcmf_dbg(ERROR, "dongle is not up\n");
+ brcmf_err("dongle is not up\n");
return -ENODEV;
}
-
/* finally, report dongle driver type */
- else if (drvr->iswl)
- sprintf(info.driver, "wl");
else
- sprintf(info.driver, "xx");
+ sprintf(info.driver, "wl");
sprintf(info.version, "%lu", drvr->drv_version);
if (copy_to_user(uaddr, &info, sizeof(info)))
@@ -646,7 +457,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
/* Get toe offload components from dongle */
case ETHTOOL_GRXCSUM:
case ETHTOOL_GTXCSUM:
- ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
+ ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
if (ret < 0)
return ret;
@@ -667,7 +478,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
return -EFAULT;
/* Read the current settings, update and write back */
- ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
+ ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
if (ret < 0)
return ret;
@@ -679,18 +490,16 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
else
toe_cmpnt &= ~csum_dir;
- ret = brcmf_toe_set(drvr, 0, toe_cmpnt);
+ 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)
- drvr->iflist[0]->ndev->features |=
- NETIF_F_IP_CSUM;
+ ifp->ndev->features |= NETIF_F_IP_CSUM;
else
- drvr->iflist[0]->ndev->features &=
- ~NETIF_F_IP_CSUM;
+ ifp->ndev->features &= ~NETIF_F_IP_CSUM;
}
break;
@@ -714,80 +523,23 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
return -1;
if (cmd == SIOCETHTOOL)
- return brcmf_ethtool(drvr, ifr->ifr_data);
+ return brcmf_ethtool(ifp, ifr->ifr_data);
return -EOPNOTSUPP;
}
-/* called only from within this driver. Sends a command to the dongle. */
-s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
-{
- struct brcmf_dcmd dcmd;
- s32 err = 0;
- int buflen = 0;
- bool is_set_key_cmd;
- struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_pub *drvr = ifp->drvr;
-
- memset(&dcmd, 0, sizeof(dcmd));
- dcmd.cmd = cmd;
- dcmd.buf = arg;
- dcmd.len = len;
-
- if (dcmd.buf != NULL)
- buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
-
- /* send to dongle (must be up, and wl) */
- if ((drvr->bus_if->state != BRCMF_BUS_DATA)) {
- brcmf_dbg(ERROR, "DONGLE_DOWN\n");
- err = -EIO;
- goto done;
- }
-
- if (!drvr->iswl) {
- err = -EIO;
- goto done;
- }
-
- /*
- * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and
- * set key CMD to prevent M4 encryption.
- */
- is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) ||
- ((dcmd.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("wsec_key", dcmd.buf, 9))) ||
- ((dcmd.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("bsscfg:wsec_key", dcmd.buf, 15))));
- if (is_set_key_cmd)
- brcmf_netdev_wait_pend8021x(ndev);
-
- err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen);
-
-done:
- if (err > 0)
- err = 0;
-
- return err;
-}
-
-int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd)
-{
- brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n",
- dcmd->cmd, dcmd->buf, dcmd->len);
-
- return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len);
-}
-
static int brcmf_netdev_stop(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;
brcmf_dbg(TRACE, "Enter\n");
- brcmf_cfg80211_down(drvr->config);
+
if (drvr->bus_if->drvr_up == 0)
return 0;
+ brcmf_cfg80211_down(ndev);
+
/* Set state and stop OS transmissions */
drvr->bus_if->drvr_up = false;
netif_stop_queue(ndev);
@@ -802,39 +554,36 @@ static int brcmf_netdev_open(struct net_device *ndev)
struct brcmf_bus *bus_if = drvr->bus_if;
u32 toe_ol;
s32 ret = 0;
- uint up = 0;
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
- if (ifp->idx == 0) { /* do it only for primary eth0 */
- /* If bus is not ready, can't continue */
- if (bus_if->state != BRCMF_BUS_DATA) {
- brcmf_dbg(ERROR, "failed bus is not ready\n");
- return -EAGAIN;
- }
+ /* If bus is not ready, can't continue */
+ if (bus_if->state != BRCMF_BUS_DATA) {
+ brcmf_err("failed bus is not ready\n");
+ return -EAGAIN;
+ }
- atomic_set(&drvr->pend_8021x_cnt, 0);
+ atomic_set(&drvr->pend_8021x_cnt, 0);
- memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
+ memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
- /* Get current TOE mode from dongle */
- if (brcmf_toe_get(drvr, ifp->idx, &toe_ol) >= 0
- && (toe_ol & TOE_TX_CSUM_OL) != 0)
- drvr->iflist[ifp->idx]->ndev->features |=
- NETIF_F_IP_CSUM;
- else
- drvr->iflist[ifp->idx]->ndev->features &=
- ~NETIF_F_IP_CSUM;
- }
+ /* Get current TOE mode from dongle */
+ if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
+ && (toe_ol & TOE_TX_CSUM_OL) != 0)
+ drvr->iflist[ifp->idx]->ndev->features |=
+ NETIF_F_IP_CSUM;
+ else
+ drvr->iflist[ifp->idx]->ndev->features &=
+ ~NETIF_F_IP_CSUM;
/* make sure RF is ready for work */
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
+ brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
/* Allow transmit calls */
netif_start_queue(ndev);
drvr->bus_if->drvr_up = true;
- if (brcmf_cfg80211_up(drvr->config)) {
- brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
+ if (brcmf_cfg80211_up(ndev)) {
+ brcmf_err("failed to bring up cfg80211\n");
return -1;
}
@@ -851,51 +600,41 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};
-static int brcmf_net_attach(struct brcmf_if *ifp)
+static const struct net_device_ops brcmf_netdev_ops_virt = {
+ .ndo_open = brcmf_cfg80211_up,
+ .ndo_stop = brcmf_cfg80211_down,
+ .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
+};
+
+int brcmf_net_attach(struct brcmf_if *ifp)
{
struct brcmf_pub *drvr = ifp->drvr;
struct net_device *ndev;
- u8 temp_addr[ETH_ALEN];
-
- brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
- ndev = drvr->iflist[ifp->idx]->ndev;
- ndev->netdev_ops = &brcmf_netdev_ops_pri;
+ brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
+ ndev = ifp->ndev;
- /*
- * determine mac address to use
- */
- if (is_valid_ether_addr(ifp->mac_addr))
- memcpy(temp_addr, ifp->mac_addr, ETH_ALEN);
+ /* set appropriate operations */
+ if (!ifp->idx)
+ ndev->netdev_ops = &brcmf_netdev_ops_pri;
else
- memcpy(temp_addr, drvr->mac, ETH_ALEN);
-
- if (ifp->idx == 1) {
- brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
- /* ACCESSPOINT INTERFACE CASE */
- temp_addr[0] |= 0X02; /* set bit 2 ,
- - Locally Administered address */
+ ndev->netdev_ops = &brcmf_netdev_ops_virt;
- }
ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
ndev->ethtool_ops = &brcmf_ethtool_ops;
drvr->rxsz = ndev->mtu + ndev->hard_header_len +
drvr->hdrlen;
- memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
-
- /* attach to cfg80211 for primary interface */
- if (!ifp->idx) {
- drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr);
- if (drvr->config == NULL) {
- brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
- goto fail;
- }
- }
+ /* set the mac address */
+ memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
if (register_netdev(ndev) != 0) {
- brcmf_dbg(ERROR, "couldn't register the net device\n");
+ brcmf_err("couldn't register the net device\n");
goto fail;
}
@@ -908,13 +647,12 @@ fail:
return -EBADE;
}
-int
-brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
+struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
+ char *name, u8 *addr_mask)
{
struct brcmf_if *ifp;
struct net_device *ndev;
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_pub *drvr = bus_if->drvr;
+ int i;
brcmf_dbg(TRACE, "idx %d\n", ifidx);
@@ -924,19 +662,24 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
* in case we missed the BRCMF_E_IF_DEL event.
*/
if (ifp) {
- brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+ brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
- netif_stop_queue(ifp->ndev);
- unregister_netdev(ifp->ndev);
- free_netdev(ifp->ndev);
- drvr->iflist[ifidx] = NULL;
+ if (ifidx) {
+ netif_stop_queue(ifp->ndev);
+ unregister_netdev(ifp->ndev);
+ free_netdev(ifp->ndev);
+ drvr->iflist[ifidx] = NULL;
+ } else {
+ brcmf_err("ignore IF event\n");
+ return ERR_PTR(-EINVAL);
+ }
}
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
if (!ndev) {
- brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
- return -ENOMEM;
+ brcmf_err("OOM - alloc_netdev\n");
+ return ERR_PTR(-ENOMEM);
}
ifp = netdev_priv(ndev);
@@ -944,20 +687,19 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
ifp->drvr = drvr;
drvr->iflist[ifidx] = ifp;
ifp->idx = ifidx;
- if (mac_addr != NULL)
- memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
+ ifp->bssidx = bssidx;
- if (brcmf_net_attach(ifp)) {
- brcmf_dbg(ERROR, "brcmf_net_attach failed");
- free_netdev(ifp->ndev);
- drvr->iflist[ifidx] = NULL;
- return -EOPNOTSUPP;
- }
+ INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
- brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
- current->pid, ifp->ndev->name);
+ if (addr_mask != NULL)
+ for (i = 0; i < ETH_ALEN; i++)
+ ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
- return 0;
+ brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
+ current->pid, ifp->ndev->name, ifp->mac_addr);
+
+ return ifp;
}
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
@@ -968,7 +710,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
ifp = drvr->iflist[ifidx];
if (!ifp) {
- brcmf_dbg(ERROR, "Null interface\n");
+ brcmf_err("Null interface\n");
return;
}
if (ifp->ndev) {
@@ -982,6 +724,9 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
netif_stop_queue(ifp->ndev);
}
+ cancel_work_sync(&ifp->setmacaddr_work);
+ cancel_work_sync(&ifp->multicast_work);
+
unregister_netdev(ifp->ndev);
drvr->iflist[ifidx] = NULL;
if (ifidx == 0)
@@ -1008,7 +753,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
drvr->hdrlen = bus_hdrlen;
drvr->bus_if = dev_get_drvdata(dev);
drvr->bus_if->drvr = drvr;
- drvr->dev = dev;
/* create device debugfs folder */
brcmf_debugfs_attach(drvr);
@@ -1016,15 +760,17 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
/* Attach and link in the protocol */
ret = brcmf_proto_attach(drvr);
if (ret != 0) {
- brcmf_dbg(ERROR, "brcmf_prot_attach failed\n");
+ brcmf_err("brcmf_prot_attach failed\n");
goto fail;
}
- INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
- INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
+ /* attach firmware event handler */
+ brcmf_fweh_attach(drvr);
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
+ init_waitqueue_head(&drvr->pend_8021x_wait);
+
return ret;
fail:
@@ -1036,63 +782,53 @@ fail:
int brcmf_bus_start(struct device *dev)
{
int ret = -1;
- /* Room for "event_msgs" + '\0' + bitvec */
- char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_if *ifp;
brcmf_dbg(TRACE, "\n");
/* Bring up the bus */
- ret = bus_if->brcmf_bus_init(dev);
+ ret = brcmf_bus_init(bus_if);
if (ret != 0) {
- brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret);
+ brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
return ret;
}
- brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
- sizeof(iovbuf));
- memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
-
- setbit(drvr->eventmask, BRCMF_E_SET_SSID);
- setbit(drvr->eventmask, BRCMF_E_PRUNE);
- setbit(drvr->eventmask, BRCMF_E_AUTH);
- setbit(drvr->eventmask, BRCMF_E_REASSOC);
- setbit(drvr->eventmask, BRCMF_E_REASSOC_IND);
- setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND);
- setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND);
- setbit(drvr->eventmask, BRCMF_E_DISASSOC);
- setbit(drvr->eventmask, BRCMF_E_JOIN);
- setbit(drvr->eventmask, BRCMF_E_ASSOC_IND);
- setbit(drvr->eventmask, BRCMF_E_PSK_SUP);
- setbit(drvr->eventmask, BRCMF_E_LINK);
- setbit(drvr->eventmask, BRCMF_E_NDIS_LINK);
- setbit(drvr->eventmask, BRCMF_E_MIC_ERROR);
- setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE);
- setbit(drvr->eventmask, BRCMF_E_TXFAIL);
- setbit(drvr->eventmask, BRCMF_E_JOIN_START);
- setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE);
-
-/* enable dongle roaming event */
-
- drvr->pktfilter_count = 1;
- /* Setup filter to allow only unicast */
- drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
-
- /* Bus is ready, do any protocol initialization */
- ret = brcmf_proto_init(drvr);
+ /* add primary networking interface */
+ ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
+ if (IS_ERR(ifp))
+ return PTR_ERR(ifp);
+
+ /* signal bus ready */
+ bus_if->state = BRCMF_BUS_DATA;
+
+ /* Bus is ready, do any initialization */
+ ret = brcmf_c_preinit_dcmds(ifp);
if (ret < 0)
- return ret;
+ goto fail;
- /* add primary networking interface */
- ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac);
+ drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
+ if (drvr->config == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = brcmf_fweh_activate_events(ifp);
if (ret < 0)
+ goto fail;
+
+ ret = brcmf_net_attach(ifp);
+fail:
+ if (ret < 0) {
+ brcmf_err("failed: %d\n", ret);
+ if (drvr->config)
+ brcmf_cfg80211_detach(drvr->config);
+ free_netdev(drvr->iflist[0]->ndev);
+ drvr->iflist[0] = NULL;
return ret;
+ }
- /* signal bus ready */
- bus_if->state = BRCMF_BUS_DATA;
return 0;
}
@@ -1105,7 +841,7 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr)
brcmf_proto_stop(drvr);
/* Stop the bus module */
- drvr->bus_if->brcmf_bus_stop(drvr->dev);
+ brcmf_bus_stop(drvr->bus_if);
}
}
@@ -1117,6 +853,11 @@ void brcmf_detach(struct device *dev)
brcmf_dbg(TRACE, "Enter\n");
+ if (drvr == NULL)
+ return;
+
+ /* stop firmware event handling */
+ brcmf_fweh_detach(drvr);
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
@@ -1126,8 +867,6 @@ void brcmf_detach(struct device *dev)
brcmf_bus_detach(drvr);
if (drvr->prot) {
- cancel_work_sync(&drvr->setmacaddr_work);
- cancel_work_sync(&drvr->multicast_work);
brcmf_proto_detach(drvr);
}
@@ -1141,63 +880,20 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
return atomic_read(&drvr->pend_8021x_cnt);
}
-#define MAX_WAIT_FOR_8021X_TX 10
-
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;
- int timeout = 10 * HZ / 1000;
- int ntimes = MAX_WAIT_FOR_8021X_TX;
- int pend = brcmf_get_pend_8021x_cnt(drvr);
-
- while (ntimes && pend) {
- if (pend) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
- set_current_state(TASK_RUNNING);
- ntimes--;
- }
- pend = brcmf_get_pend_8021x_cnt(drvr);
- }
- return pend;
-}
+ int err;
-#ifdef DEBUG
-int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
-{
- int ret = 0;
- struct file *fp;
- mm_segment_t old_fs;
- loff_t pos = 0;
-
- /* change to KERNEL_DS address limit */
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- /* open file to write */
- fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
- if (!fp) {
- brcmf_dbg(ERROR, "open file error\n");
- ret = -1;
- goto exit;
- }
+ err = wait_event_timeout(drvr->pend_8021x_wait,
+ !brcmf_get_pend_8021x_cnt(drvr),
+ msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
- /* Write buf to file */
- fp->f_op->write(fp, (char __user *)buf, size, &pos);
+ WARN_ON(!err);
-exit:
- /* free buf before return */
- kfree(buf);
- /* close file before return */
- if (fp)
- filp_close(fp, NULL);
- /* restore previous address limit */
- set_fs(old_fs);
-
- return ret;
+ return !err;
}
-#endif /* DEBUG */
static void brcmf_driver_init(struct work_struct *work)
{
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index 6bc4425a8b0f..48fa70302192 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr);
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
extern void brcmf_proto_detach(struct brcmf_pub *drvr);
-/* Initialize protocol: sync w/dongle state.
- * Sets dongle media info (iswl, drv_version, mac address).
- */
-extern int brcmf_proto_init(struct brcmf_pub *drvr);
-
/* Stop protocol: sync w/dongle state. */
extern void brcmf_proto_stop(struct brcmf_pub *drvr);
@@ -41,13 +36,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
struct sk_buff *txp);
-/* Use protocol to issue command to dongle */
-extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
- struct brcmf_dcmd *dcmd, int len);
-
-extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
-
-extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len);
+/* Sets dongle media info (drv_version, mac address). */
+extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 3564686add9a..cf857f1edf8c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -533,9 +533,11 @@ struct brcmf_sdio {
u8 *rxbuf; /* Buffer for receiving control packets */
uint rxblen; /* Allocated length of rxbuf */
u8 *rxctl; /* Aligned pointer into rxbuf */
+ u8 *rxctl_orig; /* pointer for freeing rxctl */
u8 *databuf; /* Buffer for receiving big glom packet */
u8 *dataptr; /* Aligned pointer into databuf */
uint rxlen; /* Length of valid data in buffer */
+ spinlock_t rxctl_lock; /* protection lock for ctrl frame resources */
u8 sdpcm_ver; /* Bus protocol reported by dongle */
@@ -582,8 +584,6 @@ struct brcmf_sdio {
struct list_head dpc_tsklst;
spinlock_t dpc_tl_lock;
- struct semaphore sdsem;
-
const struct firmware *firmware;
u32 fw_ptr;
@@ -614,6 +614,12 @@ static const uint max_roundup = 512;
#define ALIGNMENT 4
+enum brcmf_sdio_frmtype {
+ BRCMF_SDIO_FT_NORMAL,
+ BRCMF_SDIO_FT_SUPER,
+ BRCMF_SDIO_FT_SUB,
+};
+
static void pkt_align(struct sk_buff *p, int len, int align)
{
uint datalign;
@@ -683,7 +689,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
clkreq, &err);
if (err) {
- brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
+ brcmf_err("HT Avail request error: %d\n", err);
return -EBADE;
}
@@ -691,7 +697,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
clkctl = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- brcmf_dbg(ERROR, "HT Avail read error: %d\n", err);
+ brcmf_err("HT Avail read error: %d\n", err);
return -EBADE;
}
@@ -701,7 +707,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
devctl = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- brcmf_dbg(ERROR, "Devctl error setting CA: %d\n",
+ brcmf_err("Devctl error setting CA: %d\n",
err);
return -EBADE;
}
@@ -735,11 +741,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
usleep_range(5000, 10000);
}
if (err) {
- brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
+ brcmf_err("HT Avail request error: %d\n", err);
return -EBADE;
}
if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- brcmf_dbg(ERROR, "HT Avail timeout (%d): clkctl 0x%02x\n",
+ brcmf_err("HT Avail timeout (%d): clkctl 0x%02x\n",
PMU_MAX_TRANSITION_DLY, clkctl);
return -EBADE;
}
@@ -751,7 +757,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
#if defined(DEBUG)
if (!bus->alp_only) {
if (SBSDIO_ALPONLY(clkctl))
- brcmf_dbg(ERROR, "HT Clock should be on\n");
+ brcmf_err("HT Clock should be on\n");
}
#endif /* defined (DEBUG) */
@@ -773,7 +779,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
clkreq, &err);
brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
if (err) {
- brcmf_dbg(ERROR, "Failed access turning clock off: %d\n",
+ brcmf_err("Failed access turning clock off: %d\n",
err);
return -EBADE;
}
@@ -830,7 +836,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
else if (bus->clkstate == CLK_AVAIL)
brcmf_sdbrcm_htclk(bus, false, false);
else
- brcmf_dbg(ERROR, "request for %d -> %d\n",
+ brcmf_err("request for %d -> %d\n",
bus->clkstate, target);
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
break;
@@ -874,7 +880,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
bus->rx_seq);
if (!bus->rxskip)
- brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n");
+ brcmf_err("unexpected NAKHANDLED!\n");
bus->rxskip = false;
intstatus |= I_HMB_FRAME_IND;
@@ -888,7 +894,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
(hmb_data & HMB_DATA_VERSION_MASK) >>
HMB_DATA_VERSION_SHIFT;
if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
- brcmf_dbg(ERROR, "Version mismatch, dongle reports %d, "
+ brcmf_err("Version mismatch, dongle reports %d, "
"expecting %d\n",
bus->sdpcm_ver, SDPCM_PROT_VERSION);
else
@@ -921,7 +927,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
HMB_DATA_FC |
HMB_DATA_FWREADY |
HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
- brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n",
+ brcmf_err("Unknown mailbox data content: 0x%02x\n",
hmb_data);
return intstatus;
@@ -934,7 +940,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
u8 hi, lo;
int err;
- brcmf_dbg(ERROR, "%sterminate frame%s\n",
+ brcmf_err("%sterminate frame%s\n",
abort ? "abort command, " : "",
rtx ? ", send NAK" : "");
@@ -957,14 +963,14 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
break;
if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
- brcmf_dbg(ERROR, "count growing: last 0x%04x now 0x%04x\n",
+ brcmf_err("count growing: last 0x%04x now 0x%04x\n",
lastrbc, (hi << 8) + lo);
}
lastrbc = (hi << 8) + lo;
}
if (!retries)
- brcmf_dbg(ERROR, "count never zeroed: last 0x%04x\n", lastrbc);
+ brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
else
brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
@@ -1031,8 +1037,9 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
}
}
-static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
- struct brcmf_sdio_read *rd)
+static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
+ struct brcmf_sdio_read *rd,
+ enum brcmf_sdio_frmtype type)
{
u16 len, checksum;
u8 rx_seq, fc, tx_seq_max;
@@ -1047,17 +1054,26 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
/* All zero means no more to read */
if (!(len | checksum)) {
bus->rxpending = false;
- return false;
+ return -ENODATA;
}
if ((u16)(~(len ^ checksum))) {
- brcmf_dbg(ERROR, "HW header checksum error\n");
+ brcmf_err("HW header checksum error\n");
bus->sdcnt.rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
- return false;
+ return -EIO;
}
if (len < SDPCM_HDRLEN) {
- brcmf_dbg(ERROR, "HW header length error\n");
- return false;
+ brcmf_err("HW header length error\n");
+ return -EPROTO;
+ }
+ if (type == BRCMF_SDIO_FT_SUPER &&
+ (roundup(len, bus->blocksize) != rd->len)) {
+ brcmf_err("HW superframe header length error\n");
+ return -EPROTO;
+ }
+ if (type == BRCMF_SDIO_FT_SUB && len > rd->len) {
+ brcmf_err("HW subframe header length error\n");
+ return -EPROTO;
}
rd->len = len;
@@ -1071,35 +1087,56 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
* Byte 5: Maximum Sequence number allow for Tx
* Byte 6~7: Reserved
*/
+ if (type == BRCMF_SDIO_FT_SUPER &&
+ SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) {
+ brcmf_err("Glom descriptor found in superframe head\n");
+ rd->len = 0;
+ return -EINVAL;
+ }
rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
- if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) {
- brcmf_dbg(ERROR, "HW header length too long\n");
+ if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
+ type != BRCMF_SDIO_FT_SUPER) {
+ brcmf_err("HW header length too long\n");
bus->sdiodev->bus_if->dstats.rx_errors++;
bus->sdcnt.rx_toolong++;
brcmf_sdbrcm_rxfail(bus, false, false);
rd->len = 0;
- return false;
+ return -EPROTO;
+ }
+ if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) {
+ brcmf_err("Wrong channel for superframe\n");
+ rd->len = 0;
+ return -EINVAL;
+ }
+ if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL &&
+ rd->channel != SDPCM_EVENT_CHANNEL) {
+ brcmf_err("Wrong channel for subframe\n");
+ rd->len = 0;
+ return -EINVAL;
}
rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
- brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq);
+ brcmf_err("seq %d: bad data offset\n", rx_seq);
bus->sdcnt.rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
rd->len = 0;
- return false;
+ return -ENXIO;
}
if (rd->seq_num != rx_seq) {
- brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n",
+ brcmf_err("seq %d: sequence number error, expect %d\n",
rx_seq, rd->seq_num);
bus->sdcnt.rx_badseq++;
rd->seq_num = rx_seq;
}
+ /* no need to check the reset for subframe */
+ if (type == BRCMF_SDIO_FT_SUB)
+ return 0;
rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
/* only warm for NON glom packet */
if (rd->channel != SDPCM_GLOM_CHANNEL)
- brcmf_dbg(ERROR, "seq %d: next length error\n", rx_seq);
+ brcmf_err("seq %d: next length error\n", rx_seq);
rd->len_nxtfrm = 0;
}
fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]);
@@ -1113,12 +1150,12 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
}
tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]);
if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) {
- brcmf_dbg(ERROR, "seq %d: max tx seq number error\n", rx_seq);
+ brcmf_err("seq %d: max tx seq number error\n", rx_seq);
tx_seq_max = bus->tx_seq + 2;
}
bus->tx_max = tx_seq_max;
- return true;
+ return 0;
}
static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
@@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
u16 dlen, totlen;
u8 *dptr, num = 0;
- u16 sublen, check;
+ u16 sublen;
struct sk_buff *pfirst, *pnext;
int errcode;
- u8 chan, seq, doff, sfdoff;
- u8 txmax;
+ u8 doff, sfdoff;
int ifidx = 0;
bool usechain = bus->use_rxchain;
- u16 next_len;
+
+ struct brcmf_sdio_read rd_new;
/* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */
@@ -1149,7 +1186,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
dlen = (u16) (bus->glomd->len);
dptr = bus->glomd->data;
if (!dlen || (dlen & 1)) {
- brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n",
+ brcmf_err("bad glomd len(%d), ignore descriptor\n",
dlen);
dlen = 0;
}
@@ -1161,13 +1198,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
dptr += sizeof(u16);
if ((sublen < SDPCM_HDRLEN) ||
((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
- brcmf_dbg(ERROR, "descriptor len %d bad: %d\n",
+ brcmf_err("descriptor len %d bad: %d\n",
num, sublen);
pnext = NULL;
break;
}
if (sublen % BRCMF_SDALIGN) {
- brcmf_dbg(ERROR, "sublen %d not multiple of %d\n",
+ brcmf_err("sublen %d not multiple of %d\n",
sublen, BRCMF_SDALIGN);
usechain = false;
}
@@ -1184,7 +1221,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 + BRCMF_SDALIGN);
if (pnext == NULL) {
- brcmf_dbg(ERROR, "bcm_pkt_buf_get_skb failed, num %d len %d\n",
+ brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n",
num, sublen);
break;
}
@@ -1235,6 +1272,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
* read directly into the chained packet, or allocate a large
* packet and and copy into the chain.
*/
+ sdio_claim_host(bus->sdiodev->func[1]);
if (usechain) {
errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
bus->sdiodev->sbwad,
@@ -1246,24 +1284,26 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->dataptr, dlen);
sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
if (sublen != dlen) {
- brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
+ brcmf_err("FAILED TO COPY, dlen %d sublen %d\n",
dlen, sublen);
errcode = -1;
}
pnext = NULL;
} else {
- brcmf_dbg(ERROR, "COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
+ brcmf_err("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
dlen);
errcode = -1;
}
+ sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */
if (errcode < 0) {
- brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n",
+ brcmf_err("glom read of %d bytes failed: %d\n",
dlen, errcode);
bus->sdiodev->bus_if->dstats.rx_errors++;
+ sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) {
brcmf_sdbrcm_rxfail(bus, true, true);
} else {
@@ -1272,6 +1312,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus);
}
+ sdio_release_host(bus->sdiodev->func[1]);
return 0;
}
@@ -1279,68 +1320,17 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
pfirst->data, min_t(int, pfirst->len, 48),
"SUPERFRAME:\n");
- /* Validate the superframe header */
- dptr = (u8 *) (pfirst->data);
- sublen = get_unaligned_le16(dptr);
- check = get_unaligned_le16(dptr + sizeof(u16));
-
- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
- seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
- next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
- if ((next_len << 4) > MAX_RX_DATASZ) {
- brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n",
- next_len, seq);
- next_len = 0;
- }
- bus->cur_read.len = next_len << 4;
- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
- txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-
- errcode = 0;
- if ((u16)~(sublen ^ check)) {
- brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
- sublen, check);
- errcode = -1;
- } else if (roundup(sublen, bus->blocksize) != dlen) {
- brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
- sublen, roundup(sublen, bus->blocksize),
- dlen);
- errcode = -1;
- } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
- SDPCM_GLOM_CHANNEL) {
- brcmf_dbg(ERROR, "(superframe): bad channel %d\n",
- SDPCM_PACKET_CHANNEL(
- &dptr[SDPCM_FRAMETAG_LEN]));
- errcode = -1;
- } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
- brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n");
- errcode = -1;
- } else if ((doff < SDPCM_HDRLEN) ||
- (doff > (pfirst->len - SDPCM_HDRLEN))) {
- brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n",
- doff, sublen, pfirst->len, SDPCM_HDRLEN);
- errcode = -1;
- }
-
- /* Check sequence number of superframe SW header */
- if (rxseq != seq) {
- brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n",
- seq, rxseq);
- bus->sdcnt.rx_badseq++;
- rxseq = seq;
- }
-
- /* Check window for sanity */
- if ((u8) (txmax - bus->tx_seq) > 0x40) {
- brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n",
- txmax, bus->tx_seq);
- txmax = bus->tx_seq + 2;
- }
- bus->tx_max = txmax;
+ rd_new.seq_num = rxseq;
+ rd_new.len = dlen;
+ sdio_claim_host(bus->sdiodev->func[1]);
+ errcode = brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
+ BRCMF_SDIO_FT_SUPER);
+ sdio_release_host(bus->sdiodev->func[1]);
+ bus->cur_read.len = rd_new.len_nxtfrm << 4;
/* Remove superframe header, remember offset */
- skb_pull(pfirst, doff);
- sfdoff = doff;
+ skb_pull(pfirst, rd_new.dat_offset);
+ sfdoff = rd_new.dat_offset;
num = 0;
/* Validate all the subframe headers */
@@ -1349,40 +1339,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
if (errcode)
break;
- dptr = (u8 *) (pnext->data);
- dlen = (u16) (pnext->len);
- sublen = get_unaligned_le16(dptr);
- check = get_unaligned_le16(dptr + sizeof(u16));
- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+ rd_new.len = pnext->len;
+ rd_new.seq_num = rxseq++;
+ sdio_claim_host(bus->sdiodev->func[1]);
+ errcode = brcmf_sdio_hdparser(bus, pnext->data, &rd_new,
+ BRCMF_SDIO_FT_SUB);
+ sdio_release_host(bus->sdiodev->func[1]);
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
- dptr, 32, "subframe:\n");
+ pnext->data, 32, "subframe:\n");
- if ((u16)~(sublen ^ check)) {
- brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n",
- num, sublen, check);
- errcode = -1;
- } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
- brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n",
- num, sublen, dlen);
- errcode = -1;
- } else if ((chan != SDPCM_DATA_CHANNEL) &&
- (chan != SDPCM_EVENT_CHANNEL)) {
- brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n",
- num, chan);
- errcode = -1;
- } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
- brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n",
- num, doff, sublen, SDPCM_HDRLEN);
- errcode = -1;
- }
- /* increase the subframe count */
num++;
}
if (errcode) {
/* Terminate frame on error, request
a couple retries */
+ sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) {
/* Restore superframe header space */
skb_push(pfirst, sfdoff);
@@ -1393,6 +1365,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus);
}
+ sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = 0;
return 0;
}
@@ -1402,27 +1375,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
dptr = (u8 *) (pfirst->data);
sublen = get_unaligned_le16(dptr);
- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
- seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
- brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
- num, pfirst, pfirst->data,
- pfirst->len, sublen, chan, seq);
-
- /* precondition: chan == SDPCM_DATA_CHANNEL ||
- chan == SDPCM_EVENT_CHANNEL */
-
- if (rxseq != seq) {
- brcmf_dbg(GLOM, "rx_seq %d, expected %d\n",
- seq, rxseq);
- bus->sdcnt.rx_badseq++;
- rxseq = seq;
- }
- rxseq++;
-
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
- dptr, dlen, "Rx Subframe Data:\n");
+ dptr, pfirst->len,
+ "Rx Subframe Data:\n");
__skb_trim(pfirst, sublen);
skb_pull(pfirst, doff);
@@ -1433,7 +1390,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
continue;
} else if (brcmf_proto_hdrpull(bus->sdiodev->dev,
&ifidx, pfirst) != 0) {
- brcmf_dbg(ERROR, "rx protocol error\n");
+ brcmf_err("rx protocol error\n");
bus->sdiodev->bus_if->dstats.rx_errors++;
skb_unlink(pfirst, &bus->glom);
brcmu_pkt_buf_free_skb(pfirst);
@@ -1449,11 +1406,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
pfirst->prev);
}
/* sent any remaining packets up */
- if (bus->glom.qlen) {
- up(&bus->sdsem);
+ if (bus->glom.qlen)
brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
- down(&bus->sdsem);
- }
bus->sdcnt.rxglomframes++;
bus->sdcnt.rxglompkts += bus->glom.qlen;
@@ -1494,21 +1448,24 @@ static void
brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
{
uint rdlen, pad;
-
+ u8 *buf = NULL, *rbuf;
int sdret;
brcmf_dbg(TRACE, "Enter\n");
- /* Set rxctl for frame (w/optional alignment) */
- bus->rxctl = bus->rxbuf;
- bus->rxctl += BRCMF_FIRSTREAD;
- pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
+ if (bus->rxblen)
+ buf = vzalloc(bus->rxblen);
+ if (!buf) {
+ brcmf_err("no memory for control frame\n");
+ goto done;
+ }
+ rbuf = bus->rxbuf;
+ pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
if (pad)
- bus->rxctl += (BRCMF_SDALIGN - pad);
- bus->rxctl -= BRCMF_FIRSTREAD;
+ rbuf += (BRCMF_SDALIGN - pad);
/* Copy the already-read portion over */
- memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
+ memcpy(buf, hdr, BRCMF_FIRSTREAD);
if (len <= BRCMF_FIRSTREAD)
goto gotpkt;
@@ -1529,7 +1486,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
/* Drop if the read is too big or it exceeds our maximum */
if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
- brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n",
+ brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
rdlen, bus->sdiodev->bus_if->maxctl);
bus->sdiodev->bus_if->dstats.rx_errors++;
brcmf_sdbrcm_rxfail(bus, false, false);
@@ -1537,7 +1494,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
}
if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
- brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
+ brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
len, len - doff, bus->sdiodev->bus_if->maxctl);
bus->sdiodev->bus_if->dstats.rx_errors++;
bus->sdcnt.rx_toolong++;
@@ -1545,30 +1502,40 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
goto done;
}
- /* Read remainder of frame body into the rxctl buffer */
+ /* Read remain of frame body */
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad,
SDIO_FUNC_2,
- F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
+ F2SYNC, rbuf, rdlen);
bus->sdcnt.f2rxdata++;
/* Control frame failures need retransmission */
if (sdret < 0) {
- brcmf_dbg(ERROR, "read %d control bytes failed: %d\n",
+ brcmf_err("read %d control bytes failed: %d\n",
rdlen, sdret);
bus->sdcnt.rxc_errors++;
brcmf_sdbrcm_rxfail(bus, true, true);
goto done;
- }
+ } else
+ memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
gotpkt:
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
- bus->rxctl, len, "RxCtrl:\n");
+ buf, len, "RxCtrl:\n");
/* Point to valid data and indicate its length */
- bus->rxctl += doff;
+ spin_lock_bh(&bus->rxctl_lock);
+ if (bus->rxctl) {
+ brcmf_err("last control frame is being processed.\n");
+ spin_unlock_bh(&bus->rxctl_lock);
+ vfree(buf);
+ goto done;
+ }
+ bus->rxctl = buf + doff;
+ bus->rxctl_orig = buf;
bus->rxlen = len - doff;
+ spin_unlock_bh(&bus->rxctl_lock);
done:
/* Awake any waiters */
@@ -1623,6 +1590,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
rd->len_left = rd->len;
/* read header first for unknow frame length */
+ sdio_claim_host(bus->sdiodev->func[1]);
if (!rd->len) {
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad,
@@ -1631,10 +1599,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
BRCMF_FIRSTREAD);
bus->sdcnt.f2rxhdrs++;
if (sdret < 0) {
- brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n",
+ brcmf_err("RXHEADER FAILED: %d\n",
sdret);
bus->sdcnt.rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true);
+ sdio_release_host(bus->sdiodev->func[1]);
continue;
}
@@ -1642,7 +1611,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
bus->rxhdr, SDPCM_HDRLEN,
"RxHdr:\n");
- if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) {
+ if (brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
+ BRCMF_SDIO_FT_NORMAL)) {
+ sdio_release_host(bus->sdiodev->func[1]);
if (!bus->rxpending)
break;
else
@@ -1658,6 +1629,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
rd->len_nxtfrm = 0;
/* treat all packet as event if we don't know */
rd->channel = SDPCM_EVENT_CHANNEL;
+ sdio_release_host(bus->sdiodev->func[1]);
continue;
}
rd->len_left = rd->len > BRCMF_FIRSTREAD ?
@@ -1671,10 +1643,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
BRCMF_SDALIGN);
if (!pkt) {
/* Give up on data, request rtx of events */
- brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed\n");
+ brcmf_err("brcmu_pkt_buf_get_skb failed\n");
bus->sdiodev->bus_if->dstats.rx_dropped++;
brcmf_sdbrcm_rxfail(bus, false,
RETRYCHAN(rd->channel));
+ sdio_release_host(bus->sdiodev->func[1]);
continue;
}
skb_pull(pkt, head_read);
@@ -1683,14 +1656,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2rxdata++;
+ sdio_release_host(bus->sdiodev->func[1]);
if (sdret < 0) {
- brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
+ brcmf_err("read %d bytes from channel %d failed: %d\n",
rd->len, rd->channel, sdret);
brcmu_pkt_buf_free_skb(pkt);
bus->sdiodev->bus_if->dstats.rx_errors++;
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, true,
RETRYCHAN(rd->channel));
+ sdio_release_host(bus->sdiodev->func[1]);
continue;
}
@@ -1701,20 +1677,24 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
} else {
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
rd_new.seq_num = rd->seq_num;
- if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) {
+ sdio_claim_host(bus->sdiodev->func[1]);
+ if (brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
+ BRCMF_SDIO_FT_NORMAL)) {
rd->len = 0;
brcmu_pkt_buf_free_skb(pkt);
}
bus->sdcnt.rx_readahead_cnt++;
if (rd->len != roundup(rd_new.len, 16)) {
- brcmf_dbg(ERROR, "frame length mismatch:read %d, should be %d\n",
+ brcmf_err("frame length mismatch:read %d, should be %d\n",
rd->len,
roundup(rd_new.len, 16) >> 4);
rd->len = 0;
brcmf_sdbrcm_rxfail(bus, true, true);
+ sdio_release_host(bus->sdiodev->func[1]);
brcmu_pkt_buf_free_skb(pkt);
continue;
}
+ sdio_release_host(bus->sdiodev->func[1]);
rd->len_nxtfrm = rd_new.len_nxtfrm;
rd->channel = rd_new.channel;
rd->dat_offset = rd_new.dat_offset;
@@ -1726,11 +1706,13 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
"RxHdr:\n");
if (rd_new.channel == SDPCM_CONTROL_CHANNEL) {
- brcmf_dbg(ERROR, "readahead on control packet %d?\n",
+ brcmf_err("readahead on control packet %d?\n",
rd_new.seq_num);
/* Force retry w/normal header read */
rd->len = 0;
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, false, true);
+ sdio_release_host(bus->sdiodev->func[1]);
brcmu_pkt_buf_free_skb(pkt);
continue;
}
@@ -1751,9 +1733,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
skb_pull(pkt, SDPCM_HDRLEN);
bus->glomd = pkt;
} else {
- brcmf_dbg(ERROR, "%s: glom superframe w/o "
+ brcmf_err("%s: glom superframe w/o "
"descriptor!\n", __func__);
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, false, false);
+ sdio_release_host(bus->sdiodev->func[1]);
}
/* prepare the descriptor for the next read */
rd->len = rd->len_nxtfrm << 4;
@@ -1778,16 +1762,13 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
continue;
} else if (brcmf_proto_hdrpull(bus->sdiodev->dev, &ifidx,
pkt) != 0) {
- brcmf_dbg(ERROR, "rx protocol error\n");
+ brcmf_err("rx protocol error\n");
brcmu_pkt_buf_free_skb(pkt);
bus->sdiodev->bus_if->dstats.rx_errors++;
continue;
}
- /* Unlock during rx call */
- up(&bus->sdsem);
brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
- down(&bus->sdsem);
}
rxcount = maxframes - rxleft;
@@ -1805,15 +1786,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
}
static void
-brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar)
-{
- up(&bus->sdsem);
- wait_event_interruptible_timeout(bus->ctrl_wait, !*lockvar, HZ * 2);
- down(&bus->sdsem);
- return;
-}
-
-static void
brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
{
if (waitqueue_active(&bus->ctrl_wait))
@@ -1846,7 +1818,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
bus->sdiodev->bus_if->tx_realloc++;
new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
if (!new) {
- brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n",
+ brcmf_err("couldn't allocate new %d-byte packet\n",
pkt->len + BRCMF_SDALIGN);
ret = -ENOMEM;
goto done;
@@ -1914,6 +1886,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
if (len & (ALIGNMENT - 1))
len = roundup(len, ALIGNMENT);
+ sdio_claim_host(bus->sdiodev->func[1]);
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2txdata++;
@@ -1941,15 +1914,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
}
}
+ sdio_release_host(bus->sdiodev->func[1]);
if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
done:
/* restore pkt buffer pointer before calling tx complete routine */
skb_pull(pkt, SDPCM_HDRLEN + pad);
- up(&bus->sdsem);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
- down(&bus->sdsem);
if (free_pkt)
brcmu_pkt_buf_free_skb(pkt);
@@ -1990,9 +1962,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
/* In poll mode, need to check for other events */
if (!bus->intr && cnt) {
/* Check device status, signal pending interrupt */
+ sdio_claim_host(bus->sdiodev->func[1]);
ret = r_sdreg32(bus, &intstatus,
offsetof(struct sdpcmd_regs,
intstatus));
+ sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2txdata++;
if (ret != 0)
break;
@@ -2029,7 +2003,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
bus->watchdog_tsk = NULL;
}
- down(&bus->sdsem);
+ sdio_claim_host(bus->sdiodev->func[1]);
/* Enable clock for device interrupts */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -2050,7 +2024,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
(saveclk | SBSDIO_FORCE_HT), &err);
}
if (err)
- brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
+ brcmf_err("Failed to force clock for F2: err %d\n", err);
/* Turn off the bus (F2), free any pending packets */
brcmf_dbg(INTR, "disable SDIO interrupts\n");
@@ -2063,6 +2037,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
/* Turn off the backplane clock (only) */
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+ sdio_release_host(bus->sdiodev->func[1]);
/* Clear the data packet queues */
brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
@@ -2073,14 +2048,14 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
brcmf_sdbrcm_free_glom(bus);
/* Clear rx control and wake any waiters */
+ spin_lock_bh(&bus->rxctl_lock);
bus->rxlen = 0;
+ spin_unlock_bh(&bus->rxctl_lock);
brcmf_sdbrcm_dcmd_resp_wake(bus);
/* Reset some F2 state stuff */
bus->rxskip = false;
bus->tx_seq = bus->rx_seq = 0;
-
- up(&bus->sdsem);
}
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
@@ -2164,7 +2139,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
brcmf_dbg(TRACE, "Enter\n");
- down(&bus->sdsem);
+ sdio_claim_host(bus->sdiodev->func[1]);
/* If waiting for HTAVAIL, check status */
if (bus->clkstate == CLK_PENDING) {
@@ -2175,7 +2150,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
devctl = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
+ brcmf_err("error reading DEVCTL: %d\n", err);
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
#endif /* DEBUG */
@@ -2184,7 +2159,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
clkctl = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- brcmf_dbg(ERROR, "error reading CSR: %d\n",
+ brcmf_err("error reading CSR: %d\n",
err);
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
@@ -2196,7 +2171,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
devctl = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
+ brcmf_err("error reading DEVCTL: %d\n",
err);
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
@@ -2204,7 +2179,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
devctl, &err);
if (err) {
- brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
+ brcmf_err("error writing DEVCTL: %d\n",
err);
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
@@ -2218,9 +2193,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
/* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) {
atomic_set(&bus->ipend, 0);
- sdio_claim_host(bus->sdiodev->func[1]);
err = brcmf_sdio_intr_rstatus(bus);
- sdio_release_host(bus->sdiodev->func[1]);
}
/* Start with leftover status bits */
@@ -2249,19 +2222,21 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
intstatus |= brcmf_sdbrcm_hostmail(bus);
}
+ sdio_release_host(bus->sdiodev->func[1]);
+
/* Generally don't ask for these, can get CRC errors... */
if (intstatus & I_WR_OOSYNC) {
- brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
+ brcmf_err("Dongle reports WR_OOSYNC\n");
intstatus &= ~I_WR_OOSYNC;
}
if (intstatus & I_RD_OOSYNC) {
- brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n");
+ brcmf_err("Dongle reports RD_OOSYNC\n");
intstatus &= ~I_RD_OOSYNC;
}
if (intstatus & I_SBINT) {
- brcmf_dbg(ERROR, "Dongle reports SBINT\n");
+ brcmf_err("Dongle reports SBINT\n");
intstatus &= ~I_SBINT;
}
@@ -2295,6 +2270,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
(bus->clkstate == CLK_AVAIL)) {
int i;
+ sdio_claim_host(bus->sdiodev->func[1]);
err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
(u32) bus->ctrl_frame_len);
@@ -2328,6 +2304,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
} else {
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
}
+ sdio_release_host(bus->sdiodev->func[1]);
bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus);
}
@@ -2342,7 +2319,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) {
- brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n");
+ brcmf_err("failed backplane access over SDIO, halting operation\n");
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
atomic_set(&bus->intstatus, 0);
} else if (atomic_read(&bus->intstatus) ||
@@ -2357,10 +2334,10 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
if ((bus->clkstate != CLK_PENDING)
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
bus->activity = false;
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ sdio_release_host(bus->sdiodev->func[1]);
}
-
- up(&bus->sdsem);
}
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
@@ -2393,7 +2370,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
skb_pull(pkt, SDPCM_HDRLEN);
brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
brcmu_pkt_buf_free_skb(pkt);
- brcmf_dbg(ERROR, "out of bus->txq !!!\n");
+ brcmf_err("out of bus->txq !!!\n");
ret = -ENOSR;
} else {
ret = 0;
@@ -2443,7 +2420,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
/* Set the backplane window to include the start address */
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
if (bcmerror) {
- brcmf_dbg(ERROR, "window change failed\n");
+ brcmf_err("window change failed\n");
goto xfer_done;
}
@@ -2455,7 +2432,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
sdaddr, data, dsize);
if (bcmerror) {
- brcmf_dbg(ERROR, "membytes transfer failed\n");
+ brcmf_err("membytes transfer failed\n");
break;
}
@@ -2467,7 +2444,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
address);
if (bcmerror) {
- brcmf_dbg(ERROR, "window change failed\n");
+ brcmf_err("window change failed\n");
break;
}
sdaddr = 0;
@@ -2478,7 +2455,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
xfer_done:
/* Return the window to backplane enumeration space for core access */
if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
- brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
+ brcmf_err("FAILED to set window back to 0x%x\n",
bus->sdiodev->sbwad);
sdio_release_host(bus->sdiodev->func[1]);
@@ -2651,11 +2628,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
/* precondition: IS_ALIGNED((unsigned long)frame, 2) */
- /* Need to lock here to protect txseq and SDIO tx calls */
- down(&bus->sdsem);
-
/* Make sure backplane clock is on */
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ sdio_release_host(bus->sdiodev->func[1]);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
*(__le16 *) frame = cpu_to_le16((u16) msglen);
@@ -2678,7 +2654,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
bus->ctrl_frame_buf = frame;
bus->ctrl_frame_len = len;
- brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
+ wait_event_interruptible_timeout(bus->ctrl_wait,
+ !bus->ctrl_frame_stat,
+ msecs_to_jiffies(2000));
if (!bus->ctrl_frame_stat) {
brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
@@ -2697,7 +2675,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
frame, min_t(u16, len, 16), "TxHdr:\n");
do {
+ sdio_claim_host(bus->sdiodev->func[1]);
ret = brcmf_tx_frame(bus, frame, len);
+ sdio_release_host(bus->sdiodev->func[1]);
} while (ret < 0 && retries++ < TXRETRIES);
}
@@ -2707,13 +2687,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
bus->activity = false;
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+ sdio_release_host(bus->sdiodev->func[1]);
} else {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
- up(&bus->sdsem);
-
if (ret)
bus->sdcnt.tx_ctlerrs++;
else
@@ -2743,8 +2723,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
* Read last word in socram to determine
* address of sdpcm_shared structure
*/
+ sdio_claim_host(bus->sdiodev->func[1]);
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
(u8 *)&addr_le, 4);
+ sdio_claim_host(bus->sdiodev->func[1]);
if (rv < 0)
return rv;
@@ -2757,14 +2739,16 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
* NVRAM length at the end of memory should have been overwritten.
*/
if (!brcmf_sdio_valid_shared_address(addr)) {
- brcmf_dbg(ERROR, "invalid sdpcm_shared address 0x%08X\n",
+ brcmf_err("invalid sdpcm_shared address 0x%08X\n",
addr);
return -EINVAL;
}
/* Read hndrte_shared structure */
+ sdio_claim_host(bus->sdiodev->func[1]);
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
sizeof(struct sdpcm_shared_le));
+ sdio_release_host(bus->sdiodev->func[1]);
if (rv < 0)
return rv;
@@ -2778,8 +2762,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
- brcmf_dbg(ERROR,
- "sdpcm_shared version mismatch: dhd %d dongle %d\n",
+ brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n",
SDPCM_SHARED_VERSION,
sh->flags & SDPCM_SHARED_VERSION_MASK);
return -EPROTO;
@@ -2867,12 +2850,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
return 0;
+ sdio_claim_host(bus->sdiodev->func[1]);
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
+ sdio_release_host(bus->sdiodev->func[1]);
if (nbytes < 0)
return nbytes;
@@ -2918,6 +2903,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
return 0;
}
+ sdio_claim_host(bus->sdiodev->func[1]);
if (sh->assert_file_addr != 0) {
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
(u8 *)file, 80);
@@ -2930,6 +2916,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
if (error < 0)
return error;
}
+ sdio_release_host(bus->sdiodev->func[1]);
res = scnprintf(buf, sizeof(buf),
"dongle assert: %s:%d: assert(%s)\n",
@@ -2942,9 +2929,7 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
int error;
struct sdpcm_shared sh;
- down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
- up(&bus->sdsem);
if (error < 0)
return error;
@@ -2952,10 +2937,10 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0)
brcmf_dbg(INFO, "firmware not built with -assert\n");
else if (sh.flags & SDPCM_SHARED_ASSERT)
- brcmf_dbg(ERROR, "assertion in dongle\n");
+ brcmf_err("assertion in dongle\n");
if (sh.flags & SDPCM_SHARED_TRAP)
- brcmf_dbg(ERROR, "firmware trap in dongle\n");
+ brcmf_err("firmware trap in dongle\n");
return 0;
}
@@ -2971,7 +2956,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
if (pos != 0)
return 0;
- down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
if (error < 0)
goto done;
@@ -2988,7 +2972,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
error += nbytes;
*ppos += error;
done:
- up(&bus->sdsem);
return error;
}
@@ -3039,6 +3022,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
int timeleft;
uint rxlen = 0;
bool pending;
+ u8 *buf;
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;
@@ -3048,17 +3032,21 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
/* Wait until control frame is available */
timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
- down(&bus->sdsem);
+ spin_lock_bh(&bus->rxctl_lock);
rxlen = bus->rxlen;
memcpy(msg, bus->rxctl, min(msglen, rxlen));
+ bus->rxctl = NULL;
+ buf = bus->rxctl_orig;
+ bus->rxctl_orig = NULL;
bus->rxlen = 0;
- up(&bus->sdsem);
+ spin_unlock_bh(&bus->rxctl_lock);
+ vfree(buf);
if (rxlen) {
brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
rxlen, msglen);
} else if (timeleft == 0) {
- brcmf_dbg(ERROR, "resumed on timeout\n");
+ brcmf_err("resumed on timeout\n");
brcmf_sdbrcm_checkdied(bus);
} else if (pending) {
brcmf_dbg(CTL, "cancelled\n");
@@ -3109,14 +3097,14 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
nvram_ularray, bus->varsz);
if (bcmerror) {
- brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n",
+ brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
bcmerror, bus->varsz, varaddr);
}
/* Compare the org NVRAM with the one read from RAM */
if (memcmp(bus->vars, nvram_ularray, bus->varsz))
- brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n");
+ brcmf_err("Downloaded NVRAM image is corrupted\n");
else
- brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n");
+ brcmf_err("Download/Upload/Compare of NVRAM ok\n");
kfree(nvram_ularray);
#endif /* DEBUG */
@@ -3174,14 +3162,14 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
}
} else {
if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
- brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n");
+ brcmf_err("SOCRAM core is down after reset?\n");
bcmerror = -EBADE;
goto fail;
}
bcmerror = brcmf_sdbrcm_write_vars(bus);
if (bcmerror) {
- brcmf_dbg(ERROR, "no vars written to RAM\n");
+ brcmf_err("no vars written to RAM\n");
bcmerror = 0;
}
@@ -3221,7 +3209,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
ret = request_firmware(&bus->firmware, BRCMF_SDIO_FW_NAME,
&bus->sdiodev->func[2]->dev);
if (ret) {
- brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret);
+ brcmf_err("Fail to request firmware %d\n", ret);
return ret;
}
bus->fw_ptr = 0;
@@ -3240,7 +3228,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
if (ret) {
- brcmf_dbg(ERROR, "error %d on writing %d membytes at 0x%08x\n",
+ brcmf_err("error %d on writing %d membytes at 0x%08x\n",
ret, MEMBLOCK, offset);
goto err;
}
@@ -3340,7 +3328,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
&bus->sdiodev->func[2]->dev);
if (ret) {
- brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
+ brcmf_err("Fail to request nvram %d\n", ret);
return ret;
}
@@ -3357,23 +3345,23 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
/* Keep arm in reset */
if (brcmf_sdbrcm_download_state(bus, true)) {
- brcmf_dbg(ERROR, "error placing ARM core in reset\n");
+ brcmf_err("error placing ARM core in reset\n");
goto err;
}
/* External image takes precedence if specified */
if (brcmf_sdbrcm_download_code_file(bus)) {
- brcmf_dbg(ERROR, "dongle image file download failed\n");
+ brcmf_err("dongle image file download failed\n");
goto err;
}
/* External nvram takes precedence if specified */
if (brcmf_sdbrcm_download_nvram(bus))
- brcmf_dbg(ERROR, "dongle nvram file download failed\n");
+ brcmf_err("dongle nvram file download failed\n");
/* Take arm out of reset */
if (brcmf_sdbrcm_download_state(bus, false)) {
- brcmf_dbg(ERROR, "error getting out of ARM core reset\n");
+ brcmf_err("error getting out of ARM core reset\n");
goto err;
}
@@ -3388,13 +3376,16 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
{
bool ret;
- /* Download the firmware */
+ sdio_claim_host(bus->sdiodev->func[1]);
+
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+ sdio_release_host(bus->sdiodev->func[1]);
+
return ret;
}
@@ -3423,7 +3414,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
bus->sdcnt.tickcnt = 0;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
- down(&bus->sdsem);
+ sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on, needed to generate F2 interrupt */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -3438,7 +3429,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
(saveclk | SBSDIO_FORCE_HT), &err);
}
if (err) {
- brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
+ brcmf_err("Failed to force clock for F2: err %d\n", err);
goto exit;
}
@@ -3484,7 +3475,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
if (ret == 0) {
ret = brcmf_sdio_intr_register(bus->sdiodev);
if (ret != 0)
- brcmf_dbg(ERROR, "intr register failed:%d\n", ret);
+ brcmf_err("intr register failed:%d\n", ret);
}
/* If we didn't come up, turn off backplane clock */
@@ -3492,7 +3483,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
exit:
- up(&bus->sdsem);
+ sdio_release_host(bus->sdiodev->func[1]);
return ret;
}
@@ -3504,12 +3495,12 @@ void brcmf_sdbrcm_isr(void *arg)
brcmf_dbg(TRACE, "Enter\n");
if (!bus) {
- brcmf_dbg(ERROR, "bus is null pointer, exiting\n");
+ brcmf_err("bus is null pointer, exiting\n");
return;
}
if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
- brcmf_dbg(ERROR, "bus is down. we have nothing to do\n");
+ brcmf_err("bus is down. we have nothing to do\n");
return;
}
/* Count the interrupt call */
@@ -3518,13 +3509,13 @@ void brcmf_sdbrcm_isr(void *arg)
atomic_set(&bus->ipend, 1);
else
if (brcmf_sdio_intr_rstatus(bus)) {
- brcmf_dbg(ERROR, "failed backplane access\n");
+ brcmf_err("failed backplane access\n");
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
/* Disable additional interrupts (is this needed now)? */
if (!bus->intr)
- brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
+ brcmf_err("isr w/o interrupt configured!\n");
brcmf_sdbrcm_adddpctsk(bus);
queue_work(bus->brcmf_wq, &bus->datawork);
@@ -3539,8 +3530,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
brcmf_dbg(TIMER, "Enter\n");
- down(&bus->sdsem);
-
/* Poll period: check device if appropriate. */
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
u32 intstatus = 0;
@@ -3557,9 +3546,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
u8 devpend;
spin_unlock_irqrestore(&bus->dpc_tl_lock,
flags);
+ sdio_claim_host(bus->sdiodev->func[1]);
devpend = brcmf_sdio_regrb(bus->sdiodev,
SDIO_CCCR_INTx,
NULL);
+ sdio_release_host(bus->sdiodev->func[1]);
intstatus =
devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2);
@@ -3584,16 +3575,18 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
}
#ifdef DEBUG
/* Poll for console output periodically */
- if (bus_if->state == BRCMF_BUS_DATA &&
+ if (bus_if && bus_if->state == BRCMF_BUS_DATA &&
bus->console_interval != 0) {
bus->console.count += BRCMF_WD_POLL_MS;
if (bus->console.count >= bus->console_interval) {
bus->console.count -= bus->console_interval;
+ sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
if (brcmf_sdbrcm_readconsole(bus) < 0)
/* stop on error */
bus->console_interval = 0;
+ sdio_release_host(bus->sdiodev->func[1]);
}
}
#endif /* DEBUG */
@@ -3606,13 +3599,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->activity = false;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
} else {
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ sdio_release_host(bus->sdiodev->func[1]);
}
}
}
- up(&bus->sdsem);
-
return (atomic_read(&bus->ipend) > 0);
}
@@ -3707,6 +3700,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
bus->alp_only = true;
+ sdio_claim_host(bus->sdiodev->func[1]);
+
pr_debug("F1 signature read @0x18000000=0x%4x\n",
brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
@@ -3722,18 +3717,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
- brcmf_dbg(ERROR, "ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
+ brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
err, BRCMF_INIT_CLKCTL1, clkctl);
goto fail;
}
if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci, regsva)) {
- brcmf_dbg(ERROR, "brcmf_sdio_chip_attach failed!\n");
+ brcmf_err("brcmf_sdio_chip_attach failed!\n");
goto fail;
}
if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
- brcmf_dbg(ERROR, "unsupported chip: 0x%04x\n", bus->ci->chip);
+ brcmf_err("unsupported chip: 0x%04x\n", bus->ci->chip);
goto fail;
}
@@ -3743,7 +3738,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
/* Get info on the SOCRAM cores... */
bus->ramsize = bus->ci->ramsize;
if (!(bus->ramsize)) {
- brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n");
+ brcmf_err("failed to find SOCRAM memory!\n");
goto fail;
}
@@ -3754,6 +3749,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
+ sdio_release_host(bus->sdiodev->func[1]);
+
brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
/* Locate an appropriately-aligned portion of hdrbuf */
@@ -3769,6 +3766,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
return true;
fail:
+ sdio_release_host(bus->sdiodev->func[1]);
return false;
}
@@ -3776,6 +3774,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
{
brcmf_dbg(TRACE, "Enter\n");
+ sdio_claim_host(bus->sdiodev->func[1]);
+
/* Disable F2 to clear any intermediate frame state on the dongle */
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
SDIO_FUNC_ENABLE_1, NULL);
@@ -3786,6 +3786,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
/* Done with backplane-dependent accesses, can drop clock... */
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+ sdio_release_host(bus->sdiodev->func[1]);
+
/* ...and initialize clock/power states */
bus->clkstate = CLK_SDONLY;
bus->idletime = BRCMF_IDLE_INTERVAL;
@@ -3841,8 +3843,10 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
brcmf_dbg(TRACE, "Enter\n");
if (bus->ci) {
+ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ sdio_release_host(bus->sdiodev->func[1]);
brcmf_sdio_chip_detach(&bus->ci);
if (bus->vars && bus->varsz)
kfree(bus->vars);
@@ -3862,7 +3866,8 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
brcmf_sdio_intr_unregister(bus->sdiodev);
cancel_work_sync(&bus->datawork);
- destroy_workqueue(bus->brcmf_wq);
+ if (bus->brcmf_wq)
+ destroy_workqueue(bus->brcmf_wq);
if (bus->sdiodev->bus_if->drvr) {
brcmf_detach(bus->sdiodev->dev);
@@ -3877,6 +3882,14 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
brcmf_dbg(TRACE, "Disconnected\n");
}
+static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
+ .stop = brcmf_sdbrcm_bus_stop,
+ .init = brcmf_sdbrcm_bus_init,
+ .txdata = brcmf_sdbrcm_bus_txdata,
+ .txctl = brcmf_sdbrcm_bus_txctl,
+ .rxctl = brcmf_sdbrcm_bus_rxctl,
+};
+
void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
{
int ret;
@@ -3904,31 +3917,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->txminmax = BRCMF_TXMINMAX;
bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
+ bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
+ if (bus->brcmf_wq == NULL) {
+ brcmf_err("insufficient memory to create txworkqueue\n");
+ goto fail;
+ }
+
/* attempt to attach to the dongle */
if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
- brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n");
+ brcmf_err("brcmf_sdbrcm_probe_attach failed\n");
goto fail;
}
+ spin_lock_init(&bus->rxctl_lock);
spin_lock_init(&bus->txqlock);
init_waitqueue_head(&bus->ctrl_wait);
init_waitqueue_head(&bus->dcmd_resp_wait);
- bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
- if (bus->brcmf_wq == NULL) {
- brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
- goto fail;
- }
- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
-
/* Set up the watchdog timer */
init_timer(&bus->timer);
bus->timer.data = (unsigned long)bus;
bus->timer.function = brcmf_sdbrcm_watchdog;
- /* Initialize thread based operation and lock */
- sema_init(&bus->sdsem, 1);
-
/* Initialize watchdog thread */
init_completion(&bus->watchdog_wait);
bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
@@ -3942,26 +3953,24 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
spin_lock_init(&bus->dpc_tl_lock);
/* Assign bus interface call back */
- bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop;
- bus->sdiodev->bus_if->brcmf_bus_init = brcmf_sdbrcm_bus_init;
- bus->sdiodev->bus_if->brcmf_bus_txdata = brcmf_sdbrcm_bus_txdata;
- bus->sdiodev->bus_if->brcmf_bus_txctl = brcmf_sdbrcm_bus_txctl;
- bus->sdiodev->bus_if->brcmf_bus_rxctl = brcmf_sdbrcm_bus_rxctl;
+ bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
+ bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
+
/* Attach to the brcmf/OS/network interface */
ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
if (ret != 0) {
- brcmf_dbg(ERROR, "brcmf_attach failed\n");
+ brcmf_err("brcmf_attach failed\n");
goto fail;
}
/* Allocate buffers */
if (!(brcmf_sdbrcm_probe_malloc(bus))) {
- brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n");
+ brcmf_err("brcmf_sdbrcm_probe_malloc failed\n");
goto fail;
}
if (!(brcmf_sdbrcm_probe_init(bus))) {
- brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n");
+ brcmf_err("brcmf_sdbrcm_probe_init failed\n");
goto fail;
}
@@ -3991,10 +4000,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
/* if firmware path present try to download and bring up bus */
ret = brcmf_bus_start(bus->sdiodev->dev);
if (ret != 0) {
- if (ret == -ENOLINK) {
- brcmf_dbg(ERROR, "dongle is not responding\n");
- goto fail;
- }
+ brcmf_err("dongle is not responding\n");
+ goto fail;
}
return bus;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
new file mode 100644
index 000000000000..ba0b22512f12
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2012 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/netdevice.h>
+
+#include "brcmu_wifi.h"
+#include "brcmu_utils.h"
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "fweh.h"
+#include "fwil.h"
+
+/**
+ * struct brcm_ethhdr - broadcom specific ether header.
+ *
+ * @subtype: subtype for this packet.
+ * @length: TODO: length of appended data.
+ * @version: version indication.
+ * @oui: OUI of this packet.
+ * @usr_subtype: subtype for this OUI.
+ */
+struct brcm_ethhdr {
+ __be16 subtype;
+ __be16 length;
+ u8 version;
+ u8 oui[3];
+ __be16 usr_subtype;
+} __packed;
+
+struct brcmf_event_msg_be {
+ __be16 version;
+ __be16 flags;
+ __be32 event_type;
+ __be32 status;
+ __be32 reason;
+ __be32 auth_type;
+ __be32 datalen;
+ u8 addr[ETH_ALEN];
+ char ifname[IFNAMSIZ];
+ u8 ifidx;
+ u8 bsscfgidx;
+} __packed;
+
+/**
+ * struct brcmf_event - contents of broadcom event packet.
+ *
+ * @eth: standard ether header.
+ * @hdr: broadcom specific ether header.
+ * @msg: common part of the actual event message.
+ */
+struct brcmf_event {
+ struct ethhdr eth;
+ struct brcm_ethhdr hdr;
+ struct brcmf_event_msg_be msg;
+} __packed;
+
+/**
+ * struct brcmf_fweh_queue_item - event item on event queue.
+ *
+ * @q: list element for queuing.
+ * @code: event code.
+ * @ifidx: interface index related to this event.
+ * @ifaddr: ethernet address for interface.
+ * @emsg: common parameters of the firmware event message.
+ * @data: event specific data part of the firmware event.
+ */
+struct brcmf_fweh_queue_item {
+ struct list_head q;
+ enum brcmf_fweh_event_code code;
+ u8 ifidx;
+ u8 ifaddr[ETH_ALEN];
+ struct brcmf_event_msg_be emsg;
+ u8 data[0];
+};
+
+/**
+ * struct brcmf_fweh_event_name - code, name mapping entry.
+ */
+struct brcmf_fweh_event_name {
+ enum brcmf_fweh_event_code code;
+ const char *name;
+};
+
+#ifdef DEBUG
+#define BRCMF_ENUM_DEF(id, val) \
+ { val, #id },
+
+/* array for mapping code to event name */
+static struct brcmf_fweh_event_name fweh_event_names[] = {
+ BRCMF_FWEH_EVENT_ENUM_DEFLIST
+};
+#undef BRCMF_ENUM_DEF
+
+/**
+ * brcmf_fweh_event_name() - returns name for given event code.
+ *
+ * @code: code to lookup.
+ */
+static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
+ if (fweh_event_names[i].code == code)
+ return fweh_event_names[i].name;
+ }
+ return "unknown";
+}
+#else
+static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+ return "nodebug";
+}
+#endif
+
+/**
+ * brcmf_fweh_queue_event() - create and queue event.
+ *
+ * @fweh: firmware event handling info.
+ * @event: event queue entry.
+ */
+static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
+ struct brcmf_fweh_queue_item *event)
+{
+ ulong flags;
+
+ spin_lock_irqsave(&fweh->evt_q_lock, flags);
+ list_add_tail(&event->q, &fweh->event_q);
+ spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+ schedule_work(&fweh->event_work);
+}
+
+static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
+ enum brcmf_fweh_event_code code,
+ struct brcmf_event_msg *emsg,
+ void *data)
+{
+ struct brcmf_fweh_info *fweh;
+ int err = -EINVAL;
+
+ if (ifp) {
+ fweh = &ifp->drvr->fweh;
+
+ /* handle the event if valid interface and handler */
+ if (ifp->ndev && fweh->evt_handler[code])
+ err = fweh->evt_handler[code](ifp, emsg, data);
+ else
+ brcmf_err("unhandled event %d ignored\n", code);
+ } else {
+ brcmf_err("no interface object\n");
+ }
+ return err;
+}
+
+/**
+ * brcmf_fweh_handle_if_event() - handle IF event.
+ *
+ * @drvr: driver information object.
+ * @item: queue entry.
+ * @ifpp: interface object (may change upon ADD action).
+ */
+static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
+ struct brcmf_event_msg *emsg,
+ void *data)
+{
+ struct brcmf_if_event *ifevent = data;
+ struct brcmf_if *ifp;
+ int err = 0;
+
+ brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n",
+ ifevent->action, ifevent->ifidx,
+ ifevent->bssidx, ifevent->flags);
+
+ if (ifevent->ifidx >= BRCMF_MAX_IFS) {
+ brcmf_err("invalid interface index: %u\n",
+ ifevent->ifidx);
+ return;
+ }
+
+ ifp = drvr->iflist[ifevent->ifidx];
+
+ if (ifevent->action == BRCMF_E_IF_ADD) {
+ brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+ emsg->addr);
+ ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
+ emsg->ifname, emsg->addr);
+ if (IS_ERR(ifp))
+ return;
+
+ if (!drvr->fweh.evt_handler[BRCMF_E_IF])
+ err = brcmf_net_attach(ifp);
+ }
+
+ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+ if (ifevent->action == BRCMF_E_IF_DEL)
+ brcmf_del_if(drvr, ifevent->ifidx);
+}
+
+/**
+ * brcmf_fweh_dequeue_event() - get event from the queue.
+ *
+ * @fweh: firmware event handling info.
+ */
+static struct brcmf_fweh_queue_item *
+brcmf_fweh_dequeue_event(struct brcmf_fweh_info *fweh)
+{
+ struct brcmf_fweh_queue_item *event = NULL;
+ ulong flags;
+
+ spin_lock_irqsave(&fweh->evt_q_lock, flags);
+ if (!list_empty(&fweh->event_q)) {
+ event = list_first_entry(&fweh->event_q,
+ struct brcmf_fweh_queue_item, q);
+ list_del(&event->q);
+ }
+ spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+
+ return event;
+}
+
+/**
+ * brcmf_fweh_event_worker() - firmware event worker.
+ *
+ * @work: worker object.
+ */
+static void brcmf_fweh_event_worker(struct work_struct *work)
+{
+ struct brcmf_pub *drvr;
+ struct brcmf_if *ifp;
+ struct brcmf_fweh_info *fweh;
+ struct brcmf_fweh_queue_item *event;
+ int err = 0;
+ struct brcmf_event_msg_be *emsg_be;
+ struct brcmf_event_msg emsg;
+
+ fweh = container_of(work, struct brcmf_fweh_info, event_work);
+ drvr = container_of(fweh, struct brcmf_pub, fweh);
+
+ while ((event = brcmf_fweh_dequeue_event(fweh))) {
+ ifp = drvr->iflist[event->ifidx];
+
+ brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
+ brcmf_fweh_event_name(event->code), event->code,
+ event->emsg.ifidx, event->emsg.bsscfgidx,
+ event->emsg.addr);
+
+ /* convert event message */
+ emsg_be = &event->emsg;
+ emsg.version = be16_to_cpu(emsg_be->version);
+ emsg.flags = be16_to_cpu(emsg_be->flags);
+ emsg.event_code = event->code;
+ emsg.status = be32_to_cpu(emsg_be->status);
+ emsg.reason = be32_to_cpu(emsg_be->reason);
+ emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
+ emsg.datalen = be32_to_cpu(emsg_be->datalen);
+ memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
+ memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
+ emsg.ifidx = emsg_be->ifidx;
+ emsg.bsscfgidx = emsg_be->bsscfgidx;
+
+ brcmf_dbg(EVENT, " version %u flags %u status %u reason %u\n",
+ emsg.version, emsg.flags, emsg.status, emsg.reason);
+ brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
+ min_t(u32, emsg.datalen, 64),
+ "event payload, len=%d\n", emsg.datalen);
+
+ /* special handling of interface event */
+ if (event->code == BRCMF_E_IF) {
+ brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
+ goto event_free;
+ }
+
+ err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
+ event->data);
+ if (err) {
+ brcmf_err("event handler failed (%d)\n",
+ event->code);
+ err = 0;
+ }
+event_free:
+ kfree(event);
+ }
+}
+
+/**
+ * brcmf_fweh_attach() - initialize firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_attach(struct brcmf_pub *drvr)
+{
+ struct brcmf_fweh_info *fweh = &drvr->fweh;
+ INIT_WORK(&fweh->event_work, brcmf_fweh_event_worker);
+ spin_lock_init(&fweh->evt_q_lock);
+ INIT_LIST_HEAD(&fweh->event_q);
+}
+
+/**
+ * brcmf_fweh_detach() - cleanup firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_detach(struct brcmf_pub *drvr)
+{
+ struct brcmf_fweh_info *fweh = &drvr->fweh;
+ struct brcmf_if *ifp = drvr->iflist[0];
+ s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+ if (ifp) {
+ /* clear all events */
+ memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN);
+ (void)brcmf_fil_iovar_data_set(ifp, "event_msgs",
+ eventmask,
+ BRCMF_EVENTING_MASK_LEN);
+ }
+ /* cancel the worker */
+ cancel_work_sync(&fweh->event_work);
+ WARN_ON(!list_empty(&fweh->event_q));
+ memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
+}
+
+/**
+ * brcmf_fweh_register() - register handler for given event code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ * @handler: handler for the given event code.
+ */
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+ brcmf_fweh_handler_t handler)
+{
+ if (drvr->fweh.evt_handler[code]) {
+ brcmf_err("event code %d already registered\n", code);
+ return -ENOSPC;
+ }
+ drvr->fweh.evt_handler[code] = handler;
+ brcmf_dbg(TRACE, "event handler registered for %s\n",
+ brcmf_fweh_event_name(code));
+ return 0;
+}
+
+/**
+ * brcmf_fweh_unregister() - remove handler for given code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ */
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+ enum brcmf_fweh_event_code code)
+{
+ brcmf_dbg(TRACE, "event handler cleared for %s\n",
+ brcmf_fweh_event_name(code));
+ drvr->fweh.evt_handler[code] = NULL;
+}
+
+/**
+ * brcmf_fweh_activate_events() - enables firmware events registered.
+ *
+ * @ifp: primary interface object.
+ */
+int brcmf_fweh_activate_events(struct brcmf_if *ifp)
+{
+ int i, err;
+ s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+ for (i = 0; i < BRCMF_E_LAST; i++) {
+ if (ifp->drvr->fweh.evt_handler[i]) {
+ brcmf_dbg(EVENT, "enable event %s\n",
+ brcmf_fweh_event_name(i));
+ setbit(eventmask, i);
+ }
+ }
+
+ /* want to handle IF event as well */
+ brcmf_dbg(EVENT, "enable event IF\n");
+ setbit(eventmask, BRCMF_E_IF);
+
+ err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
+ eventmask, BRCMF_EVENTING_MASK_LEN);
+ if (err)
+ brcmf_err("Set event_msgs error (%d)\n", err);
+
+ return err;
+}
+
+/**
+ * brcmf_fweh_process_event() - process skb as firmware event.
+ *
+ * @drvr: driver information object.
+ * @event_packet: event packet to process.
+ * @ifidx: index of the firmware interface (may change).
+ *
+ * If the packet buffer contains a firmware event message it will
+ * dispatch the event to a registered handler (using worker).
+ */
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+ struct brcmf_event *event_packet, u8 *ifidx)
+{
+ enum brcmf_fweh_event_code code;
+ struct brcmf_fweh_info *fweh = &drvr->fweh;
+ struct brcmf_fweh_queue_item *event;
+ gfp_t alloc_flag = GFP_KERNEL;
+ void *data;
+ u32 datalen;
+
+ /* get event info */
+ code = get_unaligned_be32(&event_packet->msg.event_type);
+ datalen = get_unaligned_be32(&event_packet->msg.datalen);
+ *ifidx = event_packet->msg.ifidx;
+ data = &event_packet[1];
+
+ if (code >= BRCMF_E_LAST)
+ return;
+
+ if (code != BRCMF_E_IF && !fweh->evt_handler[code])
+ return;
+
+ if (in_interrupt())
+ alloc_flag = GFP_ATOMIC;
+
+ event = kzalloc(sizeof(*event) + datalen, alloc_flag);
+ if (!event)
+ return;
+
+ event->code = code;
+ event->ifidx = *ifidx;
+
+ /* use memcpy to get aligned event message */
+ memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
+ memcpy(event->data, data, datalen);
+ memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
+
+ brcmf_fweh_queue_event(fweh, event);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
new file mode 100644
index 000000000000..36901f76a3b5
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2012 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 FWEH_H_
+#define FWEH_H_
+
+#include <asm/unaligned.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+
+/* formward declarations */
+struct brcmf_pub;
+struct brcmf_if;
+struct brcmf_cfg80211_info;
+struct brcmf_event;
+
+/* list of firmware events */
+#define BRCMF_FWEH_EVENT_ENUM_DEFLIST \
+ BRCMF_ENUM_DEF(SET_SSID, 0) \
+ BRCMF_ENUM_DEF(JOIN, 1) \
+ BRCMF_ENUM_DEF(START, 2) \
+ BRCMF_ENUM_DEF(AUTH, 3) \
+ BRCMF_ENUM_DEF(AUTH_IND, 4) \
+ BRCMF_ENUM_DEF(DEAUTH, 5) \
+ BRCMF_ENUM_DEF(DEAUTH_IND, 6) \
+ BRCMF_ENUM_DEF(ASSOC, 7) \
+ BRCMF_ENUM_DEF(ASSOC_IND, 8) \
+ BRCMF_ENUM_DEF(REASSOC, 9) \
+ BRCMF_ENUM_DEF(REASSOC_IND, 10) \
+ BRCMF_ENUM_DEF(DISASSOC, 11) \
+ BRCMF_ENUM_DEF(DISASSOC_IND, 12) \
+ BRCMF_ENUM_DEF(QUIET_START, 13) \
+ BRCMF_ENUM_DEF(QUIET_END, 14) \
+ BRCMF_ENUM_DEF(BEACON_RX, 15) \
+ BRCMF_ENUM_DEF(LINK, 16) \
+ BRCMF_ENUM_DEF(MIC_ERROR, 17) \
+ BRCMF_ENUM_DEF(NDIS_LINK, 18) \
+ BRCMF_ENUM_DEF(ROAM, 19) \
+ BRCMF_ENUM_DEF(TXFAIL, 20) \
+ BRCMF_ENUM_DEF(PMKID_CACHE, 21) \
+ BRCMF_ENUM_DEF(RETROGRADE_TSF, 22) \
+ BRCMF_ENUM_DEF(PRUNE, 23) \
+ BRCMF_ENUM_DEF(AUTOAUTH, 24) \
+ BRCMF_ENUM_DEF(EAPOL_MSG, 25) \
+ BRCMF_ENUM_DEF(SCAN_COMPLETE, 26) \
+ BRCMF_ENUM_DEF(ADDTS_IND, 27) \
+ BRCMF_ENUM_DEF(DELTS_IND, 28) \
+ BRCMF_ENUM_DEF(BCNSENT_IND, 29) \
+ BRCMF_ENUM_DEF(BCNRX_MSG, 30) \
+ BRCMF_ENUM_DEF(BCNLOST_MSG, 31) \
+ BRCMF_ENUM_DEF(ROAM_PREP, 32) \
+ BRCMF_ENUM_DEF(PFN_NET_FOUND, 33) \
+ BRCMF_ENUM_DEF(PFN_NET_LOST, 34) \
+ BRCMF_ENUM_DEF(RESET_COMPLETE, 35) \
+ BRCMF_ENUM_DEF(JOIN_START, 36) \
+ BRCMF_ENUM_DEF(ROAM_START, 37) \
+ BRCMF_ENUM_DEF(ASSOC_START, 38) \
+ BRCMF_ENUM_DEF(IBSS_ASSOC, 39) \
+ BRCMF_ENUM_DEF(RADIO, 40) \
+ BRCMF_ENUM_DEF(PSM_WATCHDOG, 41) \
+ BRCMF_ENUM_DEF(PROBREQ_MSG, 44) \
+ BRCMF_ENUM_DEF(SCAN_CONFIRM_IND, 45) \
+ BRCMF_ENUM_DEF(PSK_SUP, 46) \
+ BRCMF_ENUM_DEF(COUNTRY_CODE_CHANGED, 47) \
+ BRCMF_ENUM_DEF(EXCEEDED_MEDIUM_TIME, 48) \
+ BRCMF_ENUM_DEF(ICV_ERROR, 49) \
+ BRCMF_ENUM_DEF(UNICAST_DECODE_ERROR, 50) \
+ BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
+ BRCMF_ENUM_DEF(TRACE, 52) \
+ BRCMF_ENUM_DEF(IF, 54) \
+ BRCMF_ENUM_DEF(RSSI, 56) \
+ BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
+ BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
+ BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
+ BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
+ BRCMF_ENUM_DEF(PRE_ASSOC_IND, 61) \
+ BRCMF_ENUM_DEF(PRE_REASSOC_IND, 62) \
+ BRCMF_ENUM_DEF(CHANNEL_ADOPTED, 63) \
+ BRCMF_ENUM_DEF(AP_STARTED, 64) \
+ BRCMF_ENUM_DEF(DFS_AP_STOP, 65) \
+ BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
+ BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
+ BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
+ BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
+ BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74)
+
+#define BRCMF_ENUM_DEF(id, val) \
+ BRCMF_E_##id = (val),
+
+/* firmware event codes sent by the dongle */
+enum brcmf_fweh_event_code {
+ BRCMF_FWEH_EVENT_ENUM_DEFLIST
+ BRCMF_E_LAST
+};
+#undef BRCMF_ENUM_DEF
+
+/* flags field values in struct brcmf_event_msg */
+#define BRCMF_EVENT_MSG_LINK 0x01
+#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
+#define BRCMF_EVENT_MSG_GROUP 0x04
+
+/**
+ * definitions for event packet validation.
+ */
+#define BRCMF_EVENT_OUI_OFFSET 19
+#define BRCM_OUI "\x00\x10\x18"
+#define DOT11_OUI_LEN 3
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+
+
+/**
+ * struct brcmf_event_msg - firmware event message.
+ *
+ * @version: version information.
+ * @flags: event flags.
+ * @event_code: firmware event code.
+ * @status: status information.
+ * @reason: reason code.
+ * @auth_type: authentication type.
+ * @datalen: lenght of event data buffer.
+ * @addr: ether address.
+ * @ifname: interface name.
+ * @ifidx: interface index.
+ * @bsscfgidx: bsscfg index.
+ */
+struct brcmf_event_msg {
+ u16 version;
+ u16 flags;
+ u32 event_code;
+ u32 status;
+ u32 reason;
+ s32 auth_type;
+ u32 datalen;
+ u8 addr[ETH_ALEN];
+ char ifname[IFNAMSIZ];
+ u8 ifidx;
+ u8 bsscfgidx;
+};
+
+typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *evtmsg,
+ void *data);
+
+/**
+ * struct brcmf_fweh_info - firmware event handling information.
+ *
+ * @event_work: event worker.
+ * @evt_q_lock: lock for event queue protection.
+ * @event_q: event queue.
+ * @evt_handler: registered event handlers.
+ */
+struct brcmf_fweh_info {
+ struct work_struct event_work;
+ spinlock_t evt_q_lock;
+ struct list_head event_q;
+ int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *evtmsg,
+ void *data);
+};
+
+void brcmf_fweh_attach(struct brcmf_pub *drvr);
+void brcmf_fweh_detach(struct brcmf_pub *drvr);
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+ int (*handler)(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *evtmsg,
+ void *data));
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+ enum brcmf_fweh_event_code code);
+int brcmf_fweh_activate_events(struct brcmf_if *ifp);
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+ struct brcmf_event *event_packet, u8 *ifidx);
+
+static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+ struct sk_buff *skb, u8 *ifidx)
+{
+ struct brcmf_event *event_packet;
+ u8 *data;
+ u16 usr_stype;
+
+ /* only process events when protocol matches */
+ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+ return;
+
+ /* check for BRCM oui match */
+ event_packet = (struct brcmf_event *)skb_mac_header(skb);
+ data = (u8 *)event_packet;
+ data += BRCMF_EVENT_OUI_OFFSET;
+ if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN))
+ return;
+
+ /* final match on usr_subtype */
+ data += DOT11_OUI_LEN;
+ usr_stype = get_unaligned_be16(data);
+ if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
+ return;
+
+ brcmf_fweh_process_event(drvr, event_packet, ifidx);
+}
+
+#endif /* FWEH_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
new file mode 100644
index 000000000000..d8d8b6549dc5
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+/* FWIL is the Firmware Interface Layer. In this module the support functions
+ * are located to set and get variables to and from the firmware.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+
+
+#define MAX_HEX_DUMP_LEN 64
+
+
+static s32
+brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ s32 err;
+
+ if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+ brcmf_err("bus is down. we have nothing to do.\n");
+ return -EIO;
+ }
+
+ if (data != NULL)
+ len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
+ if (set)
+ err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
+ else
+ err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
+ len);
+
+ if (err >= 0)
+ err = 0;
+ else
+ brcmf_err("Failed err=%d\n", err);
+
+ return err;
+}
+
+s32
+brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+ s32 err;
+
+ mutex_lock(&ifp->drvr->proto_block);
+
+ brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
+ mutex_unlock(&ifp->drvr->proto_block);
+
+ return err;
+}
+
+s32
+brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+ s32 err;
+
+ mutex_lock(&ifp->drvr->proto_block);
+ err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
+
+ brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ mutex_unlock(&ifp->drvr->proto_block);
+
+ return err;
+}
+
+
+s32
+brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
+{
+ s32 err;
+ __le32 data_le = cpu_to_le32(data);
+
+ mutex_lock(&ifp->drvr->proto_block);
+ err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
+ mutex_unlock(&ifp->drvr->proto_block);
+
+ return err;
+}
+
+s32
+brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
+{
+ s32 err;
+ __le32 data_le = cpu_to_le32(*data);
+
+ mutex_lock(&ifp->drvr->proto_block);
+ err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
+ mutex_unlock(&ifp->drvr->proto_block);
+ *data = le32_to_cpu(data_le);
+
+ return err;
+}
+
+static u32
+brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
+{
+ u32 len;
+
+ len = strlen(name) + 1;
+
+ if ((len + datalen) > buflen)
+ return 0;
+
+ memcpy(buf, name, len);
+
+ /* append data onto the end of the name string */
+ if (data && datalen)
+ memcpy(&buf[len], data, datalen);
+
+ return len + datalen;
+}
+
+
+s32
+brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+ u32 len)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ s32 err;
+ u32 buflen;
+
+ mutex_lock(&drvr->proto_block);
+
+ brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+ sizeof(drvr->proto_buf));
+ if (buflen) {
+ err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+ buflen, true);
+ } else {
+ err = -EPERM;
+ brcmf_err("Creating iovar failed\n");
+ }
+
+ mutex_unlock(&drvr->proto_block);
+ return err;
+}
+
+s32
+brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+ u32 len)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ s32 err;
+ u32 buflen;
+
+ mutex_lock(&drvr->proto_block);
+
+ buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+ sizeof(drvr->proto_buf));
+ if (buflen) {
+ err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+ buflen, false);
+ if (err == 0)
+ memcpy(data, drvr->proto_buf, len);
+ } else {
+ err = -EPERM;
+ brcmf_err("Creating iovar failed\n");
+ }
+
+ brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ mutex_unlock(&drvr->proto_block);
+ return err;
+}
+
+s32
+brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+ __le32 data_le = cpu_to_le32(data);
+
+ return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
+}
+
+s32
+brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+ __le32 data_le = cpu_to_le32(*data);
+ s32 err;
+
+ err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
+ if (err == 0)
+ *data = le32_to_cpu(data_le);
+ return err;
+}
+
+static u32
+brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
+ u32 buflen)
+{
+ const s8 *prefix = "bsscfg:";
+ s8 *p;
+ u32 prefixlen;
+ u32 namelen;
+ u32 iolen;
+ __le32 bssidx_le;
+
+ if (bssidx == 0)
+ return brcmf_create_iovar(name, data, datalen, buf, buflen);
+
+ prefixlen = strlen(prefix);
+ namelen = strlen(name) + 1; /* lengh of iovar name + null */
+ iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
+
+ if (buflen < iolen) {
+ brcmf_err("buffer is too short\n");
+ return 0;
+ }
+
+ p = buf;
+
+ /* copy prefix, no null */
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+ /* copy iovar name including null */
+ memcpy(p, name, namelen);
+ p += namelen;
+
+ /* bss config index as first data */
+ bssidx_le = cpu_to_le32(bssidx);
+ memcpy(p, &bssidx_le, sizeof(bssidx_le));
+ p += sizeof(bssidx_le);
+
+ /* parameter buffer follows */
+ if (datalen)
+ memcpy(p, data, datalen);
+
+ return iolen;
+}
+
+s32
+brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
+ void *data, u32 len)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ s32 err;
+ u32 buflen;
+
+ mutex_lock(&drvr->proto_block);
+
+ brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
+ drvr->proto_buf, sizeof(drvr->proto_buf));
+ if (buflen) {
+ err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+ buflen, true);
+ } else {
+ err = -EPERM;
+ brcmf_err("Creating bsscfg failed\n");
+ }
+
+ mutex_unlock(&drvr->proto_block);
+ return err;
+}
+
+s32
+brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
+ void *data, u32 len)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ s32 err;
+ u32 buflen;
+
+ mutex_lock(&drvr->proto_block);
+
+ buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
+ drvr->proto_buf, sizeof(drvr->proto_buf));
+ if (buflen) {
+ err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+ buflen, false);
+ if (err == 0)
+ memcpy(data, drvr->proto_buf, len);
+ } else {
+ err = -EPERM;
+ brcmf_err("Creating bsscfg failed\n");
+ }
+ brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
+ brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+ min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+ mutex_unlock(&drvr->proto_block);
+ return err;
+
+}
+
+s32
+brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+ __le32 data_le = cpu_to_le32(data);
+
+ return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
+ sizeof(data_le));
+}
+
+s32
+brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+ __le32 data_le = cpu_to_le32(*data);
+ s32 err;
+
+ err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
+ sizeof(data_le));
+ if (err == 0)
+ *data = le32_to_cpu(data_le);
+ return err;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
new file mode 100644
index 000000000000..16eb8202fb1e
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 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 _fwil_h_
+#define _fwil_h_
+
+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);
+s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
+
+s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+ u32 len);
+s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+ u32 len);
+s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data,
+ u32 len);
+s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data,
+ u32 len);
+s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+#endif /* _fwil_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index 9434440bbc65..b1bb46c49799 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -186,7 +186,7 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
CORE_SB(base, sbtmstatehigh),
NULL);
if (regdata & SSB_TMSHIGH_BUSY)
- brcmf_dbg(ERROR, "core state still busy\n");
+ brcmf_err("core state still busy\n");
regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
NULL);
@@ -438,7 +438,7 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->ramsize = 0x80000;
break;
default:
- brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
+ brcmf_err("chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
}
@@ -456,7 +456,7 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->resetcore = brcmf_sdio_ai_resetcore;
break;
default:
- brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype);
+ brcmf_err("socitype %u not supported\n", ci->socitype);
return -ENODEV;
}
@@ -473,7 +473,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
if (err) {
- brcmf_dbg(ERROR, "error writing for HT off\n");
+ brcmf_err("error writing for HT off\n");
return err;
}
@@ -483,7 +483,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
if ((clkval & ~SBSDIO_AVBITS) != clkset) {
- brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+ brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
clkset, clkval);
return -EACCES;
}
@@ -493,7 +493,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
!SBSDIO_ALPAV(clkval)),
PMU_MAX_TRANSITION_DLY);
if (!SBSDIO_ALPAV(clkval)) {
- brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
+ brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
clkval);
return -EBUSY;
}
@@ -618,7 +618,7 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
str_shift = 11;
break;
default:
- brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
+ brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
brcmf_sdio_chip_name(ci->chip, chn, 8),
ci->chiprev, ci->pmurev);
break;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 7a6dfdc67b6c..914c56fe6c5f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -14,24 +14,12 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
#include <linux/firmware.h>
#include <linux/usb.h>
#include <linux/vmalloc.h>
-#include <net/cfg80211.h>
-#include <defs.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include <dhd_bus.h>
@@ -42,14 +30,11 @@
#define IOCTL_RESP_TIMEOUT 2000
-#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */
-#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */
-#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
+#define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */
+#define BRCMF_USB_RESET_GETVER_LOOP_CNT 10
#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle
has boot up */
-#define BRCMF_USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */
-
#define BRCMF_USB_NRXQ 50
#define BRCMF_USB_NTXQ 50
@@ -70,16 +55,6 @@
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
-enum usbdev_suspend_state {
- USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
- suspend */
- USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be
- * suspended. Wating PM to
- * suspend the device
- */
- USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
-};
-
struct brcmf_usb_image {
struct list_head list;
s8 *fwname;
@@ -100,10 +75,8 @@ struct brcmf_usbdev_info {
struct list_head rx_postq;
struct list_head tx_freeq;
struct list_head tx_postq;
- enum usbdev_suspend_state suspend_state;
uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
- bool activity;
int rx_low_watermark;
int tx_low_watermark;
int tx_high_watermark;
@@ -116,10 +89,6 @@ struct brcmf_usbdev_info {
u8 *image; /* buffer for combine fw and nvram */
int image_len;
- wait_queue_head_t wait;
- bool waitdone;
- int sync_urb_status;
-
struct usb_device *usbdev;
struct device *dev;
@@ -131,7 +100,6 @@ struct brcmf_usbdev_info {
int ctl_urb_status;
int ctl_completed;
wait_queue_head_t ioctl_resp_wait;
- wait_queue_head_t ctrl_wait;
ulong ctl_op;
struct urb *bulk_urb; /* used for FW download */
@@ -176,6 +144,7 @@ static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
static void
brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
{
+ brcmf_dbg(USB, "Enter, status=%d\n", status);
if (unlikely(devinfo == NULL))
return;
@@ -203,6 +172,7 @@ brcmf_usb_ctlread_complete(struct urb *urb)
struct brcmf_usbdev_info *devinfo =
(struct brcmf_usbdev_info *)urb->context;
+ brcmf_dbg(USB, "Enter\n");
devinfo->ctl_urb_actual_length = urb->actual_length;
brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
urb->status);
@@ -214,33 +184,22 @@ brcmf_usb_ctlwrite_complete(struct urb *urb)
struct brcmf_usbdev_info *devinfo =
(struct brcmf_usbdev_info *)urb->context;
+ brcmf_dbg(USB, "Enter\n");
brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
urb->status);
}
-static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
-{
- return 0;
-}
-
static int
brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
{
int ret;
u16 size;
+ brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL || buf == NULL ||
len == 0 || devinfo->ctl_urb == NULL)
return -EINVAL;
- /* If the USB/HSIC bus in sleep state, wake it up */
- if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
- if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
- brcmf_dbg(ERROR, "Could not Resume the bus!\n");
- return -EIO;
- }
-
- devinfo->activity = true;
size = len;
devinfo->ctl_write.wLength = cpu_to_le16p(&size);
devinfo->ctl_urb->transfer_buffer_length = size;
@@ -257,7 +216,7 @@ brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
if (ret < 0)
- brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+ brcmf_err("usb_submit_urb failed %d\n", ret);
return ret;
}
@@ -268,6 +227,7 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
int ret;
u16 size;
+ brcmf_dbg(USB, "Enter\n");
if ((devinfo == NULL) || (buf == NULL) || (len == 0)
|| (devinfo->ctl_urb == NULL))
return -EINVAL;
@@ -290,7 +250,7 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
if (ret < 0)
- brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+ brcmf_err("usb_submit_urb failed %d\n", ret);
return ret;
}
@@ -301,10 +261,9 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
int timeout = 0;
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
- /* TODO: handle suspend/resume */
+ brcmf_dbg(USB, "Enter\n");
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
return -EIO;
- }
if (test_and_set_bit(0, &devinfo->ctl_op))
return -EIO;
@@ -312,14 +271,14 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
devinfo->ctl_completed = false;
err = brcmf_usb_send_ctl(devinfo, buf, len);
if (err) {
- brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
+ brcmf_err("fail %d bytes: %d\n", err, len);
clear_bit(0, &devinfo->ctl_op);
return err;
}
timeout = brcmf_usb_ioctl_resp_wait(devinfo);
clear_bit(0, &devinfo->ctl_op);
if (!timeout) {
- brcmf_dbg(ERROR, "Txctl wait timed out\n");
+ brcmf_err("Txctl wait timed out\n");
err = -EIO;
}
return err;
@@ -331,17 +290,17 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
int timeout = 0;
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
- /* TODO: handle suspend/resume */
+ brcmf_dbg(USB, "Enter\n");
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
return -EIO;
- }
+
if (test_and_set_bit(0, &devinfo->ctl_op))
return -EIO;
devinfo->ctl_completed = false;
err = brcmf_usb_recv_ctl(devinfo, buf, len);
if (err) {
- brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
+ brcmf_err("fail %d bytes: %d\n", err, len);
clear_bit(0, &devinfo->ctl_op);
return err;
}
@@ -349,7 +308,7 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
err = devinfo->ctl_urb_status;
clear_bit(0, &devinfo->ctl_op);
if (!timeout) {
- brcmf_dbg(ERROR, "rxctl wait timed out\n");
+ brcmf_err("rxctl wait timed out\n");
err = -EIO;
}
if (!err)
@@ -397,7 +356,7 @@ brcmf_usbdev_qinit(struct list_head *q, int qsize)
reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC);
if (reqs == NULL) {
- brcmf_dbg(ERROR, "fail to allocate memory!\n");
+ brcmf_err("fail to allocate memory!\n");
return NULL;
}
req = reqs;
@@ -413,7 +372,7 @@ brcmf_usbdev_qinit(struct list_head *q, int qsize)
}
return reqs;
fail:
- brcmf_dbg(ERROR, "fail!\n");
+ brcmf_err("fail!\n");
while (!list_empty(q)) {
req = list_entry(q->next, struct brcmf_usbreq, list);
if (req && req->urb)
@@ -430,7 +389,7 @@ static void brcmf_usb_free_q(struct list_head *q, bool pending)
int i = 0;
list_for_each_entry_safe(req, next, q, list) {
if (!req->urb) {
- brcmf_dbg(ERROR, "bad req\n");
+ brcmf_err("bad req\n");
break;
}
i++;
@@ -459,6 +418,8 @@ static void brcmf_usb_tx_complete(struct urb *urb)
struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
struct brcmf_usbdev_info *devinfo = req->devinfo;
+ brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
+ req->skb);
brcmf_usb_del_fromq(devinfo, req);
if (urb->status == 0)
devinfo->bus_pub.bus->dstats.tx_packets++;
@@ -484,6 +445,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
struct sk_buff *skb;
int ifidx = 0;
+ brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
brcmf_usb_del_fromq(devinfo, req);
skb = req->skb;
req->skb = NULL;
@@ -497,10 +459,10 @@ static void brcmf_usb_rx_complete(struct urb *urb)
return;
}
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
skb_put(skb, urb->actual_length);
if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
- brcmf_dbg(ERROR, "rx protocol error\n");
+ brcmf_err("rx protocol error\n");
brcmu_pkt_buf_free_skb(skb);
devinfo->bus_pub.bus->dstats.rx_errors++;
} else
@@ -550,8 +512,8 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
{
struct brcmf_usbreq *req;
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
- brcmf_dbg(ERROR, "bus is not up\n");
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+ brcmf_err("bus is not up=%d\n", devinfo->bus_pub.state);
return;
}
while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
@@ -564,29 +526,24 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
int old_state;
+ brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n",
+ devinfo->bus_pub.state, state);
if (devinfo->bus_pub.state == state)
return;
old_state = devinfo->bus_pub.state;
- brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
- old_state, state);
-
- /* Don't update state if it's PnP firmware re-download */
- if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
- devinfo->bus_pub.state = state;
-
- if ((old_state == BCMFMAC_USB_STATE_SLEEP)
- && (state == BCMFMAC_USB_STATE_UP)) {
- brcmf_usb_rx_fill_all(devinfo);
- }
+ devinfo->bus_pub.state = state;
/* update state of upper layer */
- if (state == BCMFMAC_USB_STATE_DOWN) {
- brcmf_dbg(INFO, "DBUS is down\n");
+ if (state == BRCMFMAC_USB_STATE_DOWN) {
+ brcmf_dbg(USB, "DBUS is down\n");
bcmf_bus->state = BRCMF_BUS_DOWN;
+ } else if (state == BRCMFMAC_USB_STATE_UP) {
+ brcmf_dbg(USB, "DBUS is up\n");
+ bcmf_bus->state = BRCMF_BUS_DATA;
} else {
- brcmf_dbg(INFO, "DBUS current state=%d\n", state);
+ brcmf_dbg(USB, "DBUS current state=%d\n", state);
}
}
@@ -595,30 +552,32 @@ brcmf_usb_intr_complete(struct urb *urb)
{
struct brcmf_usbdev_info *devinfo =
(struct brcmf_usbdev_info *)urb->context;
- bool killed;
+ int err;
+
+ brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
if (devinfo == NULL)
return;
if (unlikely(urb->status)) {
- if (devinfo->suspend_state ==
- USBOS_SUSPEND_STATE_SUSPEND_PENDING)
- killed = true;
-
- if ((urb->status == -ENOENT && (!killed))
- || urb->status == -ESHUTDOWN ||
- urb->status == -ENODEV) {
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+ if (urb->status == -ENOENT ||
+ urb->status == -ESHUTDOWN ||
+ urb->status == -ENODEV) {
+ brcmf_usb_state_change(devinfo,
+ BRCMFMAC_USB_STATE_DOWN);
}
}
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
- brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
+ brcmf_err("intr cb when DBUS down, ignoring\n");
return;
}
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
- usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
+ err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+ if (err)
+ brcmf_err("usb_submit_urb, err=%d\n", err);
+ }
}
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
@@ -627,16 +586,15 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
struct brcmf_usbreq *req;
int ret;
- if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
- /* TODO: handle suspend/resume */
+ brcmf_dbg(USB, "Enter, skb=%p\n", skb);
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
return -EIO;
- }
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
&devinfo->tx_freecount);
if (!req) {
brcmu_pkt_buf_free_skb(skb);
- brcmf_dbg(ERROR, "no req to send\n");
+ brcmf_err("no req to send\n");
return -ENOMEM;
}
@@ -648,7 +606,7 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (ret) {
- brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
+ brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
brcmf_usb_del_fromq(devinfo, req);
brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL;
@@ -670,25 +628,16 @@ static int brcmf_usb_up(struct device *dev)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
u16 ifnum;
+ int ret;
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
+ brcmf_dbg(USB, "Enter\n");
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
return 0;
- /* If the USB/HSIC bus in sleep state, wake it up */
- if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
- if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
- brcmf_dbg(ERROR, "Could not Resume the bus!\n");
- return -EIO;
- }
- }
- devinfo->activity = true;
-
/* Success, indicate devinfo is fully up */
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
+ brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
if (devinfo->intr_urb) {
- int ret;
-
usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
devinfo->intr_pipe,
&devinfo->intr,
@@ -699,7 +648,7 @@ static int brcmf_usb_up(struct device *dev)
ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
if (ret) {
- brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n",
+ brcmf_err("USB_SUBMIT_URB failed with status %d\n",
ret);
return -EINVAL;
}
@@ -733,14 +682,14 @@ static void brcmf_usb_down(struct device *dev)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+ brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL)
return;
- brcmf_dbg(TRACE, "enter\n");
- if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN)
return;
- brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+ brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
if (devinfo->intr_urb)
usb_kill_urb(devinfo->intr_urb);
@@ -754,34 +703,14 @@ static void brcmf_usb_down(struct device *dev)
brcmf_usb_free_q(&devinfo->rx_postq, true);
}
-static int
-brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time)
-{
- int ret;
- int err = 0;
- int ms = time;
-
- ret = wait_event_interruptible_timeout(devinfo->wait,
- devinfo->waitdone == true, (ms * HZ / 1000));
-
- if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) {
- brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n",
- ret, devinfo->sync_urb_status);
- err = -EINVAL;
- }
- devinfo->waitdone = false;
- return err;
-}
-
static void
brcmf_usb_sync_complete(struct urb *urb)
{
struct brcmf_usbdev_info *devinfo =
(struct brcmf_usbdev_info *)urb->context;
- devinfo->waitdone = true;
- wake_up_interruptible(&devinfo->wait);
- devinfo->sync_urb_status = urb->status;
+ devinfo->ctl_completed = true;
+ brcmf_usb_ioctl_resp_wake(devinfo);
}
static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
@@ -813,18 +742,19 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
(void *) tmpbuf, size,
(usb_complete_t)brcmf_usb_sync_complete, devinfo);
+ devinfo->ctl_completed = false;
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
if (ret < 0) {
- brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+ brcmf_err("usb_submit_urb failed %d\n", ret);
kfree(tmpbuf);
return false;
}
- ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
+ ret = brcmf_usb_ioctl_resp_wait(devinfo);
memcpy(buffer, tmpbuf, buflen);
kfree(tmpbuf);
- return (ret == 0);
+ return ret;
}
static bool
@@ -833,27 +763,25 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
struct bootrom_id_le id;
u32 chipid, chiprev;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL)
return false;
/* Check if firmware downloaded already by querying runtime ID */
id.chip = cpu_to_le32(0xDEAD);
- brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
- sizeof(struct bootrom_id_le));
+ brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
chipid = le32_to_cpu(id.chip);
chiprev = le32_to_cpu(id.chiprev);
if ((chipid & 0x4300) == 0x4300)
- brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
+ brcmf_dbg(USB, "chip %x rev 0x%x\n", chipid, chiprev);
else
- brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
+ brcmf_dbg(USB, "chip %d rev 0x%x\n", chipid, chiprev);
if (chipid == BRCMF_POSTBOOT_ID) {
- brcmf_dbg(INFO, "firmware already downloaded\n");
- brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
- sizeof(struct bootrom_id_le));
+ brcmf_dbg(USB, "firmware already downloaded\n");
+ brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
return false;
} else {
devinfo->bus_pub.devid = chipid;
@@ -866,38 +794,29 @@ static int
brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
{
struct bootrom_id_le id;
- u16 wait = 0, wait_time;
-
- brcmf_dbg(TRACE, "enter\n");
+ u32 loop_cnt;
- if (devinfo == NULL)
- return -EINVAL;
+ brcmf_dbg(USB, "Enter\n");
- /* Give dongle chance to boot */
- wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
- while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
- mdelay(wait_time);
- wait += wait_time;
+ loop_cnt = 0;
+ do {
+ mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
+ loop_cnt++;
id.chip = cpu_to_le32(0xDEAD); /* Get the ID */
- brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
- sizeof(struct bootrom_id_le));
+ brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
break;
- }
+ } while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
- brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
- wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
-
- brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
- sizeof(struct bootrom_id_le));
+ brcmf_dbg(USB, "postboot chip 0x%x/rev 0x%x\n",
+ le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
- /* XXX this wait may not be necessary */
- mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
+ brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
return 0;
} else {
- brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
- wait);
+ brcmf_err("Cannot talk to Dongle. Firmware is not UP, %d ms\n",
+ BRCMF_USB_RESET_GETVER_SPINWAIT * loop_cnt);
return -EINVAL;
}
}
@@ -918,13 +837,14 @@ brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
+ devinfo->ctl_completed = false;
ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
if (ret) {
- brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+ brcmf_err("usb_submit_urb failed %d\n", ret);
return ret;
}
- ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
- return ret;
+ ret = brcmf_usb_ioctl_resp_wait(devinfo);
+ return (ret == 0);
}
static int
@@ -935,7 +855,8 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
struct rdl_state_le state;
u32 rdlstate, rdlbytes;
int err = 0;
- brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
+
+ brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
if (bulkchunk == NULL) {
@@ -952,7 +873,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
/* 2) Check we are in the Waiting state */
if (rdlstate != DL_WAITING) {
- brcmf_dbg(ERROR, "Failed to DL_START\n");
+ brcmf_err("Failed to DL_START\n");
err = -EINVAL;
goto fail;
}
@@ -981,7 +902,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
memcpy(bulkchunk, dlpos, sendlen);
if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk,
sendlen)) {
- brcmf_dbg(ERROR, "send_bulk failed\n");
+ brcmf_err("send_bulk failed\n");
err = -EINVAL;
goto fail;
}
@@ -991,7 +912,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
}
if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
sizeof(struct rdl_state_le))) {
- brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n");
+ brcmf_err("DL_GETSTATE Failed xxxx\n");
err = -EINVAL;
goto fail;
}
@@ -1001,7 +922,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
/* restart if an error is reported */
if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) {
- brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n",
+ brcmf_err("Bad Hdr or Bad CRC state %d\n",
rdlstate);
err = -EINVAL;
goto fail;
@@ -1010,7 +931,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
fail:
kfree(bulkchunk);
- brcmf_dbg(TRACE, "err=%d\n", err);
+ brcmf_dbg(USB, "Exit, err=%d\n", err);
return err;
}
@@ -1018,7 +939,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
{
int err;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL)
return -EINVAL;
@@ -1028,10 +949,10 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
err = brcmf_usb_dl_writeimage(devinfo, fw, len);
if (err == 0)
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;
else
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
- brcmf_dbg(TRACE, "exit: err=%d\n", err);
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;
+ brcmf_dbg(USB, "Exit, err=%d\n", err);
return err;
}
@@ -1040,7 +961,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
{
struct rdl_state_le state;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
if (!devinfo)
return -EINVAL;
@@ -1060,10 +981,10 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
return -ENODEV;
/* The Dongle may go for re-enumeration. */
} else {
- brcmf_dbg(ERROR, "Dongle not runnable\n");
+ brcmf_err("Dongle not runnable\n");
return -EINVAL;
}
- brcmf_dbg(TRACE, "exit\n");
+ brcmf_dbg(USB, "Exit\n");
return 0;
}
@@ -1090,7 +1011,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
int devid, chiprev;
int err;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL)
return -ENODEV;
@@ -1098,13 +1019,13 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
chiprev = devinfo->bus_pub.chiprev;
if (!brcmf_usb_chip_support(devid, chiprev)) {
- brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
+ brcmf_err("unsupported chip %d rev %d\n",
devid, chiprev);
return -EINVAL;
}
if (!devinfo->image) {
- brcmf_dbg(ERROR, "No firmware!\n");
+ brcmf_err("No firmware!\n");
return -ENOENT;
}
@@ -1118,7 +1039,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
{
- brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
+ brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);
/* free the URBS */
brcmf_usb_free_q(&devinfo->rx_freeq, false);
@@ -1153,6 +1074,7 @@ static int check_file(const u8 *headers)
struct trx_header_le *trx;
int actual_len = -1;
+ brcmf_dbg(USB, "Enter\n");
/* Extract trx header */
trx = (struct trx_header_le *) headers;
if (trx->magic != cpu_to_le32(TRX_MAGIC))
@@ -1174,6 +1096,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
struct brcmf_usb_image *fw_image;
int err;
+ brcmf_dbg(USB, "Enter\n");
switch (devinfo->bus_pub.devid) {
case 43143:
fwname = BRCMF_USB_43143_FW_NAME;
@@ -1190,7 +1113,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
return -EINVAL;
break;
}
-
+ brcmf_dbg(USB, "Loading FW %s\n", fwname);
list_for_each_entry(fw_image, &fw_image_list, list) {
if (fw_image->fwname == fwname) {
devinfo->image = fw_image->image;
@@ -1201,11 +1124,11 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
/* fw image not yet loaded. Load it now and add to list */
err = request_firmware(&fw, fwname, devinfo->dev);
if (!fw) {
- brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname);
+ brcmf_err("fail to request firmware %s\n", fwname);
return err;
}
if (check_file(fw->data) < 0) {
- brcmf_dbg(ERROR, "invalid firmware %s\n", fwname);
+ brcmf_err("invalid firmware %s\n", fwname);
return -EINVAL;
}
@@ -1235,10 +1158,13 @@ static
struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
int nrxq, int ntxq)
{
+ brcmf_dbg(USB, "Enter\n");
+
devinfo->bus_pub.nrxq = nrxq;
devinfo->rx_low_watermark = nrxq / 2;
devinfo->bus_pub.devinfo = devinfo;
devinfo->bus_pub.ntxq = ntxq;
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DOWN;
/* flow control when too many tx urbs posted */
devinfo->tx_low_watermark = ntxq / 4;
@@ -1270,25 +1196,24 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->intr_urb) {
- brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n");
+ brcmf_err("usb_alloc_urb (intr) failed\n");
goto error;
}
devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->ctl_urb) {
- brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n");
+ brcmf_err("usb_alloc_urb (ctl) failed\n");
goto error;
}
devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->bulk_urb) {
- brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n");
+ brcmf_err("usb_alloc_urb (bulk) failed\n");
goto error;
}
- init_waitqueue_head(&devinfo->wait);
if (!brcmf_usb_dlneeded(devinfo))
return &devinfo->bus_pub;
- brcmf_dbg(TRACE, "start fw downloading\n");
+ brcmf_dbg(USB, "Start fw downloading\n");
if (brcmf_usb_get_fw(devinfo))
goto error;
@@ -1298,19 +1223,27 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
return &devinfo->bus_pub;
error:
- brcmf_dbg(ERROR, "failed!\n");
+ brcmf_err("failed!\n");
brcmf_usb_detach(devinfo);
return NULL;
}
-static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
- const char *desc, u32 bustype, u32 hdrlen)
+static struct brcmf_bus_ops brcmf_usb_bus_ops = {
+ .txdata = brcmf_usb_tx,
+ .init = brcmf_usb_up,
+ .stop = brcmf_usb_down,
+ .txctl = brcmf_usb_tx_ctlpkt,
+ .rxctl = brcmf_usb_rx_ctlpkt,
+};
+
+static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
{
struct brcmf_bus *bus = NULL;
struct brcmf_usbdev *bus_pub = NULL;
int ret;
struct device *dev = devinfo->dev;
+ brcmf_dbg(USB, "Enter\n");
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
if (!bus_pub)
return -ENODEV;
@@ -1321,26 +1254,22 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
goto fail;
}
+ bus->dev = dev;
bus_pub->bus = bus;
- bus->brcmf_bus_txdata = brcmf_usb_tx;
- bus->brcmf_bus_init = brcmf_usb_up;
- bus->brcmf_bus_stop = brcmf_usb_down;
- bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
- bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
- bus->type = bustype;
bus->bus_priv.usb = bus_pub;
dev_set_drvdata(dev, bus);
+ bus->ops = &brcmf_usb_bus_ops;
/* Attach to the common driver interface */
- ret = brcmf_attach(hdrlen, dev);
+ ret = brcmf_attach(0, dev);
if (ret) {
- brcmf_dbg(ERROR, "dhd_attach failed\n");
+ brcmf_err("brcmf_attach failed\n");
goto fail;
}
ret = brcmf_bus_start(dev);
if (ret) {
- brcmf_dbg(ERROR, "dongle is not responding\n");
+ brcmf_err("dongle is not responding\n");
brcmf_detach(dev);
goto fail;
}
@@ -1358,7 +1287,7 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
{
if (!devinfo)
return;
- brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
+ brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
brcmf_detach(devinfo->dev);
kfree(devinfo->bus_pub.bus);
@@ -1376,7 +1305,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
u8 endpoint_num;
struct brcmf_usbdev_info *devinfo;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
if (devinfo == NULL)
@@ -1415,7 +1344,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
- brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n",
+ brcmf_err("invalid control interface: class %d, subclass %d, proto %d\n",
IFDESC(usb, CONTROL_IF).bInterfaceClass,
IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
@@ -1427,7 +1356,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT) {
- brcmf_dbg(ERROR, "invalid control endpoint %d\n",
+ brcmf_err("invalid control endpoint %d\n",
endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
ret = -1;
goto fail;
@@ -1446,7 +1375,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
endpoint = &IFEPDESC(usb, BULK_IF, ep);
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_BULK) {
- brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep);
+ brcmf_err("invalid data endpoint %d\n", ep);
ret = -1;
goto fail;
}
@@ -1477,11 +1406,11 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
if (usb->speed == USB_SPEED_HIGH)
- brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
+ brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
else
- brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
+ brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
- ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0);
+ ret = brcmf_usb_probe_cb(devinfo);
if (ret)
goto fail;
@@ -1489,7 +1418,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0;
fail:
- brcmf_dbg(ERROR, "failed with errno %d\n", ret);
+ brcmf_err("failed with errno %d\n", ret);
kfree(devinfo);
usb_set_intfdata(intf, NULL);
return ret;
@@ -1501,40 +1430,55 @@ brcmf_usb_disconnect(struct usb_interface *intf)
{
struct brcmf_usbdev_info *devinfo;
- brcmf_dbg(TRACE, "enter\n");
+ brcmf_dbg(USB, "Enter\n");
devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
brcmf_usb_disconnect_cb(devinfo);
kfree(devinfo);
+ brcmf_dbg(USB, "Exit\n");
}
/*
- * only need to signal the bus being down and update the suspend state.
+ * only need to signal the bus being down and update the state.
*/
static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
{
struct usb_device *usb = interface_to_usbdev(intf);
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
- brcmf_dbg(TRACE, "enter\n");
- devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
- devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
+ brcmf_dbg(USB, "Enter\n");
+ devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
+ brcmf_detach(&usb->dev);
return 0;
}
/*
- * mark suspend state active and crank up the bus.
+ * (re-) start the bus.
*/
static int brcmf_usb_resume(struct usb_interface *intf)
{
struct usb_device *usb = interface_to_usbdev(intf);
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
- brcmf_dbg(TRACE, "enter\n");
- devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
- brcmf_bus_start(&usb->dev);
+ brcmf_dbg(USB, "Enter\n");
+ if (!brcmf_attach(0, devinfo->dev))
+ return brcmf_bus_start(&usb->dev);
+
return 0;
}
+static int brcmf_usb_reset_resume(struct usb_interface *intf)
+{
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+ brcmf_dbg(USB, "Enter\n");
+
+ if (!brcmf_usb_fw_download(devinfo))
+ return brcmf_usb_resume(intf);
+
+ return -EIO;
+}
+
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
#define BRCMF_USB_DEVICE_ID_43236 0xbd17
@@ -1554,7 +1498,6 @@ MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
-/* TODO: suspend and resume entries */
static struct usb_driver brcmf_usbdrvr = {
.name = KBUILD_MODNAME,
.probe = brcmf_usb_probe,
@@ -1562,6 +1505,7 @@ static struct usb_driver brcmf_usbdrvr = {
.id_table = brcmf_usb_devid_table,
.suspend = brcmf_usb_suspend,
.resume = brcmf_usb_resume,
+ .reset_resume = brcmf_usb_reset_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
@@ -1579,12 +1523,14 @@ static void brcmf_release_fw(struct list_head *q)
void brcmf_usb_exit(void)
{
+ brcmf_dbg(USB, "Enter\n");
usb_deregister(&brcmf_usbdrvr);
brcmf_release_fw(&fw_image_list);
}
void brcmf_usb_init(void)
{
+ brcmf_dbg(USB, "Enter\n");
INIT_LIST_HEAD(&fw_image_list);
usb_register(&brcmf_usbdrvr);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
index acfa5e89872f..f483a8c9945b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -17,19 +17,11 @@
#define BRCMFMAC_USB_H
enum brcmf_usb_state {
- BCMFMAC_USB_STATE_DL_PENDING,
- BCMFMAC_USB_STATE_DL_DONE,
- BCMFMAC_USB_STATE_UP,
- BCMFMAC_USB_STATE_DOWN,
- BCMFMAC_USB_STATE_PNP_FWDL,
- BCMFMAC_USB_STATE_DISCONNECT,
- BCMFMAC_USB_STATE_SLEEP
-};
-
-enum brcmf_usb_pnp_state {
- BCMFMAC_USB_PNP_DISCONNECT,
- BCMFMAC_USB_PNP_SLEEP,
- BCMFMAC_USB_PNP_RESUME,
+ BRCMFMAC_USB_STATE_DOWN,
+ BRCMFMAC_USB_STATE_DL_FAIL,
+ BRCMFMAC_USB_STATE_DL_DONE,
+ BRCMFMAC_USB_STATE_UP,
+ BRCMFMAC_USB_STATE_SLEEP
};
struct brcmf_stats {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 481345c23ded..1261a9b84e04 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -19,14 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
-#include <linux/if_arp.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#include <linux/bitops.h>
#include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <linux/uaccess.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
@@ -34,7 +27,9 @@
#include <defs.h>
#include <brcmu_wifi.h>
#include "dhd.h"
+#include "dhd_dbg.h"
#include "wl_cfg80211.h"
+#include "fwil.h"
#define BRCMF_SCAN_IE_LEN_MAX 2048
#define BRCMF_PNO_VERSION 2
@@ -48,6 +43,8 @@
#define BRCMF_PNO_SCAN_COMPLETE 1
#define BRCMF_PNO_SCAN_INCOMPLETE 0
+#define BRCMF_IFACE_MAX_CNT 2
+
#define TLV_LEN_OFF 1 /* length offset */
#define TLV_HDR_LEN 2 /* header length */
#define TLV_BODY_OFF 2 /* body offset */
@@ -91,16 +88,11 @@
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-
-static u32 brcmf_dbg_level = WL_DBG_ERR;
-
-static bool check_sys_up(struct wiphy *wiphy)
+static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- if (!test_bit(WL_STATUS_READY, &cfg->status)) {
- WL_INFO("device is not ready : status (%d)\n",
- (int)cfg->status);
+ if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
+ brcmf_dbg(INFO, "device is not ready : status (%lu)\n",
+ vif->sme_state);
return false;
}
return true;
@@ -391,55 +383,29 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
return qdbm;
}
-/* function for reading/writing a single u32 from/to the dongle */
-static int
-brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
-{
- int err;
- __le32 par_le = cpu_to_le32(*par);
-
- err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
- *par = le32_to_cpu(par_le);
-
- return err;
-}
-
-static s32
-brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name,
- void *param, s32 paramlen,
- void *buf, s32 buflen, s32 bssidx)
+static u16 channel_to_chanspec(struct ieee80211_channel *ch)
{
- s32 err = -ENOMEM;
- u32 len;
-
- len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
- buf, buflen, bssidx);
- BUG_ON(!len);
- if (len > 0)
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
- if (err)
- WL_ERR("error (%d)\n", err);
+ u16 chanspec;
- return err;
-}
+ chanspec = ieee80211_frequency_to_channel(ch->center_freq);
+ chanspec &= WL_CHANSPEC_CHAN_MASK;
-static s32
-brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name,
- void *param, s32 paramlen,
- void *buf, s32 buflen, s32 bssidx)
-{
- s32 err = -ENOMEM;
- u32 len;
-
- len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
- buf, buflen, bssidx);
- BUG_ON(!len);
- if (len > 0)
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len);
- if (err)
- WL_ERR("error (%d)\n", err);
+ if (ch->band == IEEE80211_BAND_2GHZ)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
- return err;
+ if (ch->flags & IEEE80211_CHAN_NO_HT40) {
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+ } else {
+ chanspec |= WL_CHANSPEC_BW_40;
+ if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS)
+ chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+ else
+ chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+ }
+ return chanspec;
}
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
@@ -457,21 +423,20 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
}
static int
-send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx,
- struct net_device *ndev, struct brcmf_wsec_key *key)
+send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
{
int err;
struct brcmf_wsec_key_le key_le;
convert_key_from_CPU(key, &key_le);
- err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
- sizeof(key_le),
- cfg->extra_buf,
- WL_EXTRA_BUF_MAX, bssidx);
+ brcmf_netdev_wait_pend8021x(ndev);
+
+ err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
+ sizeof(key_le));
if (err)
- WL_ERR("wsec_key error (%d)\n", err);
+ brcmf_err("wsec_key error (%d)\n", err);
return err;
}
@@ -480,29 +445,30 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_vif *vif = ifp->vif;
s32 infra = 0;
s32 ap = 0;
s32 err = 0;
- WL_TRACE("Enter, ndev=%p, type=%d\n", ndev, type);
+ brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
switch (type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
- WL_ERR("type (%d) : currently we do not support this type\n",
- type);
+ brcmf_err("type (%d) : currently we do not support this type\n",
+ type);
return -EOPNOTSUPP;
case NL80211_IFTYPE_ADHOC:
- cfg->conf->mode = WL_MODE_IBSS;
+ vif->mode = WL_MODE_IBSS;
infra = 0;
break;
case NL80211_IFTYPE_STATION:
- cfg->conf->mode = WL_MODE_BSS;
+ vif->mode = WL_MODE_BSS;
infra = 1;
break;
case NL80211_IFTYPE_AP:
- cfg->conf->mode = WL_MODE_AP;
+ vif->mode = WL_MODE_AP;
ap = 1;
break;
default:
@@ -511,338 +477,41 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
}
if (ap) {
- set_bit(WL_STATUS_AP_CREATING, &cfg->status);
- if (!cfg->ap_info)
- cfg->ap_info = kzalloc(sizeof(*cfg->ap_info),
- GFP_KERNEL);
- if (!cfg->ap_info) {
- err = -ENOMEM;
- goto done;
- }
- WL_INFO("IF Type = AP\n");
+ set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state);
+ brcmf_dbg(INFO, "IF Type = AP\n");
} else {
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);
if (err) {
- WL_ERR("WLC_SET_INFRA error (%d)\n", err);
+ brcmf_err("WLC_SET_INFRA error (%d)\n", err);
err = -EAGAIN;
goto done;
}
- WL_INFO("IF Type = %s\n",
- (cfg->conf->mode == WL_MODE_IBSS) ?
- "Adhoc" : "Infra");
+ brcmf_dbg(INFO, "IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ?
+ "Adhoc" : "Infra");
}
ndev->ieee80211_ptr->iftype = type;
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
-static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
-{
- s8 buf[BRCMF_DCMD_SMLEN];
- u32 len;
- s32 err = 0;
- __le32 val_le;
-
- val_le = cpu_to_le32(val);
- len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
- sizeof(buf));
- BUG_ON(!len);
-
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
- if (err)
- WL_ERR("error (%d)\n", err);
-
- return err;
-}
-
-static s32
-brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
-{
- union {
- s8 buf[BRCMF_DCMD_SMLEN];
- __le32 val;
- } var;
- u32 len;
- u32 data_null;
- s32 err = 0;
-
- len =
- brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
- sizeof(var.buf));
- BUG_ON(!len);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
- if (err)
- WL_ERR("error (%d)\n", err);
-
- *retval = le32_to_cpu(var.val);
-
- return err;
-}
-
-static s32
-brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val,
- s32 bssidx)
-{
- s8 buf[BRCMF_DCMD_SMLEN];
- __le32 val_le;
-
- val_le = cpu_to_le32(val);
-
- return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le,
- sizeof(val_le), buf, sizeof(buf),
- bssidx);
-}
-
-static s32
-brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val,
- s32 bssidx)
-{
- s8 buf[BRCMF_DCMD_SMLEN];
- s32 err;
- __le32 val_le;
-
- memset(buf, 0, sizeof(buf));
- err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf,
- sizeof(buf), bssidx);
- if (err == 0) {
- memcpy(&val_le, buf, sizeof(val_le));
- *val = le32_to_cpu(val_le);
- }
- return err;
-}
-
-
-/*
- * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this
- * should return the ndev matching bssidx.
- */
-static s32
-brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev)
-{
- return 0;
-}
-
static void brcmf_set_mpc(struct net_device *ndev, int mpc)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- if (test_bit(WL_STATUS_READY, &cfg->status)) {
- err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
+ if (check_vif_up(ifp->vif)) {
+ err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
if (err) {
- WL_ERR("fail to set mpc\n");
+ brcmf_err("fail to set mpc\n");
return;
}
- WL_INFO("MPC : %d\n", mpc);
- }
-}
-
-static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
- struct brcmf_ssid *ssid)
-{
- memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
- params_le->bss_type = DOT11_BSSTYPE_ANY;
- params_le->scan_type = 0;
- params_le->channel_num = 0;
- params_le->nprobes = cpu_to_le32(-1);
- params_le->active_time = cpu_to_le32(-1);
- params_le->passive_time = cpu_to_le32(-1);
- params_le->home_time = cpu_to_le32(-1);
- if (ssid && ssid->SSID_len) {
- params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len);
- memcpy(&params_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len);
+ brcmf_dbg(INFO, "MPC : %d\n", mpc);
}
}
-static s32
-brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
- s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 iolen;
-
- iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
- BUG_ON(!iolen);
-
- return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
-}
-
-static s32
-brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
- s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 iolen;
-
- iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
- BUG_ON(!iolen);
-
- return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
-}
-
-static s32
-brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
- struct brcmf_ssid *ssid, u16 action)
-{
- s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
- offsetof(struct brcmf_iscan_params_le, params_le);
- struct brcmf_iscan_params_le *params;
- s32 err = 0;
-
- if (ssid && ssid->SSID_len)
- params_size += sizeof(struct brcmf_ssid);
- params = kzalloc(params_size, GFP_KERNEL);
- if (!params)
- return -ENOMEM;
- BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
-
- brcmf_iscan_prep(&params->params_le, ssid);
-
- params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
- params->action = cpu_to_le16(action);
- params->scan_duration = cpu_to_le16(0);
-
- err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
- iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
- if (err) {
- if (err == -EBUSY)
- WL_INFO("system busy : iscan canceled\n");
- else
- WL_ERR("error (%d)\n", err);
- }
-
- kfree(params);
- return err;
-}
-
-static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
- struct net_device *ndev = cfg_to_ndev(cfg);
- struct brcmf_ssid ssid;
- __le32 passive_scan;
- s32 err = 0;
-
- /* Broadcast scan by default */
- memset(&ssid, 0, sizeof(ssid));
-
- iscan->state = WL_ISCAN_STATE_SCANING;
-
- passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
- err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
- if (err) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- brcmf_set_mpc(ndev, 0);
- cfg->iscan_kickstart = true;
- err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
- if (err) {
- brcmf_set_mpc(ndev, 1);
- cfg->iscan_kickstart = false;
- return err;
- }
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
- return err;
-}
-
-static s32
-brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request,
- struct cfg80211_ssid *this_ssid)
-{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct cfg80211_ssid *ssids;
- struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
- __le32 passive_scan;
- bool iscan_req;
- bool spec_scan;
- s32 err = 0;
- u32 SSID_len;
-
- if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scanning already : status (%lu)\n", cfg->status);
- return -EAGAIN;
- }
- if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) {
- WL_ERR("Scanning being aborted : status (%lu)\n",
- cfg->status);
- return -EAGAIN;
- }
- if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) {
- WL_ERR("Connecting : status (%lu)\n",
- cfg->status);
- return -EAGAIN;
- }
-
- iscan_req = false;
- spec_scan = false;
- if (request) {
- /* scan bss */
- ssids = request->ssids;
- if (cfg->iscan_on && (!ssids || !ssids->ssid_len))
- iscan_req = true;
- } else {
- /* scan in ibss */
- /* we don't do iscan in ibss */
- ssids = this_ssid;
- }
-
- cfg->scan_request = request;
- set_bit(WL_STATUS_SCANNING, &cfg->status);
- if (iscan_req) {
- err = brcmf_do_iscan(cfg);
- if (!err)
- return err;
- else
- goto scan_out;
- } else {
- WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
- ssids->ssid, ssids->ssid_len);
- memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
- SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
- sr->ssid_le.SSID_len = cpu_to_le32(0);
- if (SSID_len) {
- memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
- sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
- spec_scan = true;
- } else {
- WL_SCAN("Broadcast scan\n");
- }
-
- passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
- if (err) {
- WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
- goto scan_out;
- }
- brcmf_set_mpc(ndev, 0);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
- sizeof(sr->ssid_le));
- if (err) {
- if (err == -EBUSY)
- WL_INFO("system busy : scan for \"%s\" "
- "canceled\n", sr->ssid_le.SSID);
- else
- WL_ERR("WLC_SCAN error (%d)\n", err);
-
- brcmf_set_mpc(ndev, 1);
- goto scan_out;
- }
- }
-
- return 0;
-
-scan_out:
- clear_bit(WL_STATUS_SCANNING, &cfg->status);
- cfg->scan_request = NULL;
- return err;
-}
-
static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
struct cfg80211_scan_request *request)
{
@@ -851,12 +520,10 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
s32 i;
s32 offset;
u16 chanspec;
- u16 channel;
- struct ieee80211_channel *req_channel;
char *ptr;
struct brcmf_ssid_le ssid_le;
- memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
+ memset(params_le->bssid, 0xFF, ETH_ALEN);
params_le->bss_type = DOT11_BSSTYPE_ANY;
params_le->scan_type = 0;
params_le->channel_num = 0;
@@ -873,40 +540,20 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
n_ssids = request->n_ssids;
n_channels = request->n_channels;
/* Copy channel array if applicable */
- WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
+ brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
+ n_channels);
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
- chanspec = 0;
- req_channel = request->channels[i];
- channel = ieee80211_frequency_to_channel(
- req_channel->center_freq);
- if (req_channel->band == IEEE80211_BAND_2GHZ)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
-
- if (req_channel->flags & IEEE80211_CHAN_NO_HT40) {
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
- } else {
- chanspec |= WL_CHANSPEC_BW_40;
- if (req_channel->flags &
- IEEE80211_CHAN_NO_HT40PLUS)
- chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
- else
- chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
- }
-
- chanspec |= (channel & WL_CHANSPEC_CHAN_MASK);
- WL_SCAN("Chan : %d, Channel spec: %x\n",
- channel, chanspec);
+ chanspec = channel_to_chanspec(request->channels[i]);
+ brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
+ request->channels[i]->hw_value, chanspec);
params_le->channel_list[i] = cpu_to_le16(chanspec);
}
} else {
- WL_SCAN("Scanning all channels\n");
+ brcmf_dbg(SCAN, "Scanning all channels\n");
}
/* Copy ssid array if applicable */
- WL_SCAN("### List of SSIDs to scan ### %d\n", n_ssids);
+ brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
if (n_ssids > 0) {
offset = offsetof(struct brcmf_scan_params_le, channel_list) +
n_channels * sizeof(u16);
@@ -919,18 +566,19 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
memcpy(ssid_le.SSID, request->ssids[i].ssid,
request->ssids[i].ssid_len);
if (!ssid_le.SSID_len)
- WL_SCAN("%d: Broadcast scan\n", i);
+ brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
else
- WL_SCAN("%d: scan for %s size =%d\n", i,
- ssid_le.SSID, ssid_le.SSID_len);
+ brcmf_dbg(SCAN, "%d: scan for %s size =%d\n",
+ i, ssid_le.SSID, ssid_le.SSID_len);
memcpy(ptr, &ssid_le, sizeof(ssid_le));
ptr += sizeof(ssid_le);
}
} else {
- WL_SCAN("Broadcast scan %p\n", request->ssids);
+ brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
if ((request->ssids) && request->ssids->ssid_len) {
- WL_SCAN("SSID %s len=%d\n", params_le->ssid_le.SSID,
- request->ssids->ssid_len);
+ brcmf_dbg(SCAN, "SSID %s len=%d\n",
+ params_le->ssid_le.SSID,
+ request->ssids->ssid_len);
params_le->ssid_le.SSID_len =
cpu_to_le32(request->ssids->ssid_len);
memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
@@ -952,7 +600,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct cfg80211_scan_request *scan_request;
s32 err = 0;
- WL_SCAN("Enter\n");
+ brcmf_dbg(SCAN, "Enter\n");
/* clear scan request, because the FW abort can cause a second call */
/* to this functon and might cause a double cfg80211_scan_done */
@@ -964,9 +612,9 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
if (fw_abort) {
/* Do a scan abort to stop the driver's scan engine */
- WL_SCAN("ABORT scan in firmware\n");
+ brcmf_dbg(SCAN, "ABORT scan in firmware\n");
memset(&params_le, 0, sizeof(params_le));
- memcpy(params_le.bssid, ether_bcast, ETH_ALEN);
+ memset(params_le.bssid, 0xFF, ETH_ALEN);
params_le.bss_type = DOT11_BSSTYPE_ANY;
params_le.scan_type = 0;
params_le.channel_num = cpu_to_le32(1);
@@ -977,29 +625,29 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
/* Scan is aborted by setting channel_list[0] to -1 */
params_le.channel_list[0] = cpu_to_le16(-1);
/* E-Scan (or anyother type) can be aborted by SCAN */
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &params_le,
- sizeof(params_le));
+ err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
+ &params_le, sizeof(params_le));
if (err)
- WL_ERR("Scan abort failed\n");
+ brcmf_err("Scan abort failed\n");
}
/*
* e-scan can be initiated by scheduled scan
* which takes precedence.
*/
if (cfg->sched_escan) {
- WL_SCAN("scheduled scan completed\n");
+ brcmf_dbg(SCAN, "scheduled scan completed\n");
cfg->sched_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
brcmf_set_mpc(ndev, 1);
} else if (scan_request) {
- WL_SCAN("ESCAN Completed scan: %s\n",
- aborted ? "Aborted" : "Done");
+ brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
+ aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
brcmf_set_mpc(ndev, 1);
}
- if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scan complete while device not scanning\n");
+ if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ brcmf_err("Scan complete while device not scanning\n");
return -EPERM;
}
@@ -1015,7 +663,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
struct brcmf_escan_params_le *params;
s32 err = 0;
- WL_SCAN("E-SCAN START\n");
+ brcmf_dbg(SCAN, "E-SCAN START\n");
if (request != NULL) {
/* Allocate space for populating ssids in struct */
@@ -1036,13 +684,13 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
params->action = cpu_to_le16(action);
params->sync_id = cpu_to_le16(0x1234);
- err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size,
- cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN);
+ err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
+ params, params_size);
if (err) {
if (err == -EBUSY)
- WL_INFO("system busy : escan canceled\n");
+ brcmf_dbg(INFO, "system busy : escan canceled\n");
else
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
}
kfree(params);
@@ -1055,18 +703,18 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
struct net_device *ndev, struct cfg80211_scan_request *request)
{
s32 err;
- __le32 passive_scan;
+ u32 passive_scan;
struct brcmf_scan_results *results;
- WL_SCAN("Enter\n");
+ brcmf_dbg(SCAN, "Enter\n");
cfg->escan_info.ndev = ndev;
cfg->escan_info.wiphy = wiphy;
cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
- passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
+ passive_scan = cfg->active_scan ? 0 : 1;
+ err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan);
if (err) {
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
return err;
}
brcmf_set_mpc(ndev, 0);
@@ -1086,29 +734,29 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids;
- struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
- __le32 passive_scan;
+ struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
+ u32 passive_scan;
bool escan_req;
bool spec_scan;
s32 err;
u32 SSID_len;
- WL_SCAN("START ESCAN\n");
+ brcmf_dbg(SCAN, "START ESCAN\n");
- if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scanning already : status (%lu)\n", cfg->status);
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
return -EAGAIN;
}
- if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) {
- WL_ERR("Scanning being aborted : status (%lu)\n",
- cfg->status);
+ if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
+ brcmf_err("Scanning being aborted: status (%lu)\n",
+ cfg->scan_status);
return -EAGAIN;
}
- if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) {
- WL_ERR("Connecting : status (%lu)\n",
- cfg->status);
+ if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
+ brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
return -EAGAIN;
}
@@ -1128,16 +776,14 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
}
cfg->scan_request = request;
- set_bit(WL_STATUS_SCANNING, &cfg->status);
+ set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
if (escan_req) {
err = brcmf_do_escan(cfg, wiphy, ndev, request);
- if (!err)
- return err;
- else
+ if (err)
goto scan_out;
} else {
- WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
- ssids->ssid, ssids->ssid_len);
+ brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
+ ssids->ssid, ssids->ssid_len);
memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
sr->ssid_le.SSID_len = cpu_to_le32(0);
@@ -1147,24 +793,24 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
spec_scan = true;
} else
- WL_SCAN("Broadcast scan\n");
+ brcmf_dbg(SCAN, "Broadcast scan\n");
- passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
+ passive_scan = cfg->active_scan ? 0 : 1;
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan);
if (err) {
- WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
+ brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
brcmf_set_mpc(ndev, 0);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
- sizeof(sr->ssid_le));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
+ &sr->ssid_le, sizeof(sr->ssid_le));
if (err) {
if (err == -EBUSY)
- WL_INFO("BUSY: scan for \"%s\" canceled\n",
- sr->ssid_le.SSID);
+ brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
+ sr->ssid_le.SSID);
else
- WL_ERR("WLC_SCAN error (%d)\n", err);
+ brcmf_err("WLC_SCAN error (%d)\n", err);
brcmf_set_mpc(ndev, 1);
goto scan_out;
@@ -1174,7 +820,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
return 0;
scan_out:
- clear_bit(WL_STATUS_SCANNING, &cfg->status);
+ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
if (timer_pending(&cfg->escan_timeout))
del_timer_sync(&cfg->escan_timeout);
cfg->scan_request = NULL;
@@ -1182,27 +828,23 @@ scan_out:
}
static s32
-brcmf_cfg80211_scan(struct wiphy *wiphy,
- struct cfg80211_scan_request *request)
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct net_device *ndev = request->wdev->netdev;
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
s32 err = 0;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
- if (!check_sys_up(wiphy))
+ if (!check_vif_up(container_of(request->wdev,
+ struct brcmf_cfg80211_vif, wdev)))
return -EIO;
- if (cfg->iscan_on)
- err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
- else if (cfg->escan_on)
- err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
+ err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
if (err)
- WL_ERR("scan error (%d)\n", err);
+ brcmf_err("scan error (%d)\n", err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1210,9 +852,10 @@ static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
{
s32 err = 0;
- err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
+ rts_threshold);
if (err)
- WL_ERR("Error (%d)\n", err);
+ brcmf_err("Error (%d)\n", err);
return err;
}
@@ -1221,9 +864,10 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
{
s32 err = 0;
- err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
+ frag_threshold);
if (err)
- WL_ERR("Error (%d)\n", err);
+ brcmf_err("Error (%d)\n", err);
return err;
}
@@ -1231,11 +875,11 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
{
s32 err = 0;
- u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
+ u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
- err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
+ err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
if (err) {
- WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
+ brcmf_err("cmd (%d) , error (%d)\n", cmd, err);
return err;
}
return err;
@@ -1245,10 +889,11 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
@@ -1281,7 +926,7 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
}
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1311,28 +956,26 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
join_params->params_le.chanspec_num = cpu_to_le32(1);
- WL_CONN("join_params->params.chanspec_list[0]= %#X,"
- "channel %d, chanspec %#X\n",
- chanspec, ch, chanspec);
+ brcmf_dbg(CONN, "channel %d, chanspec %#X\n", ch, chanspec);
}
}
-static void brcmf_link_down(struct brcmf_cfg80211_info *cfg)
+static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
{
- struct net_device *ndev = NULL;
s32 err = 0;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
- if (cfg->link_up) {
- ndev = cfg_to_ndev(cfg);
- WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
- err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
+ if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
+ brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
+ err = brcmf_fil_cmd_data_set(vif->ifp,
+ BRCMF_C_DISASSOC, NULL, 0);
if (err)
- WL_ERR("WLC_DISASSOC failed (%d)\n", err);
- cfg->link_up = false;
+ brcmf_err("WLC_DISASSOC failed (%d)\n", err);
+ clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
}
- WL_TRACE("Exit\n");
+ clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
+ brcmf_dbg(TRACE, "Exit\n");
}
static s32
@@ -1340,68 +983,71 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ibss_params *params)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_join_params join_params;
size_t join_params_size = 0;
s32 err = 0;
s32 wsec = 0;
s32 bcnprd;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
if (params->ssid)
- WL_CONN("SSID: %s\n", params->ssid);
+ brcmf_dbg(CONN, "SSID: %s\n", params->ssid);
else {
- WL_CONN("SSID: NULL, Not supported\n");
+ brcmf_dbg(CONN, "SSID: NULL, Not supported\n");
return -EOPNOTSUPP;
}
- set_bit(WL_STATUS_CONNECTING, &cfg->status);
+ set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
if (params->bssid)
- WL_CONN("BSSID: %pM\n", params->bssid);
+ brcmf_dbg(CONN, "BSSID: %pM\n", params->bssid);
else
- WL_CONN("No BSSID specified\n");
+ brcmf_dbg(CONN, "No BSSID specified\n");
- if (params->channel)
- WL_CONN("channel: %d\n", params->channel->center_freq);
+ if (params->chandef.chan)
+ brcmf_dbg(CONN, "channel: %d\n",
+ params->chandef.chan->center_freq);
else
- WL_CONN("no channel specified\n");
+ brcmf_dbg(CONN, "no channel specified\n");
if (params->channel_fixed)
- WL_CONN("fixed channel required\n");
+ brcmf_dbg(CONN, "fixed channel required\n");
else
- WL_CONN("no fixed channel required\n");
+ brcmf_dbg(CONN, "no fixed channel required\n");
if (params->ie && params->ie_len)
- WL_CONN("ie len: %d\n", params->ie_len);
+ brcmf_dbg(CONN, "ie len: %d\n", params->ie_len);
else
- WL_CONN("no ie specified\n");
+ brcmf_dbg(CONN, "no ie specified\n");
if (params->beacon_interval)
- WL_CONN("beacon interval: %d\n", params->beacon_interval);
+ brcmf_dbg(CONN, "beacon interval: %d\n",
+ params->beacon_interval);
else
- WL_CONN("no beacon interval specified\n");
+ brcmf_dbg(CONN, "no beacon interval specified\n");
if (params->basic_rates)
- WL_CONN("basic rates: %08X\n", params->basic_rates);
+ brcmf_dbg(CONN, "basic rates: %08X\n", params->basic_rates);
else
- WL_CONN("no basic rates specified\n");
+ brcmf_dbg(CONN, "no basic rates specified\n");
if (params->privacy)
- WL_CONN("privacy required\n");
+ brcmf_dbg(CONN, "privacy required\n");
else
- WL_CONN("no privacy required\n");
+ brcmf_dbg(CONN, "no privacy required\n");
/* Configure Privacy for starter */
if (params->privacy)
wsec |= WEP_ENABLED;
- err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
if (err) {
- WL_ERR("wsec failed (%d)\n", err);
+ brcmf_err("wsec failed (%d)\n", err);
goto done;
}
@@ -1411,9 +1057,9 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
else
bcnprd = 100;
- err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
if (err) {
- WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
+ brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err);
goto done;
}
@@ -1434,17 +1080,17 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
BRCMF_ASSOC_PARAMS_FIXED_SIZE;
memcpy(profile->bssid, params->bssid, ETH_ALEN);
} else {
- memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
+ memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
memset(profile->bssid, 0, ETH_ALEN);
}
/* Channel */
- if (params->channel) {
+ if (params->chandef.chan) {
u32 target_channel;
cfg->channel =
ieee80211_frequency_to_channel(
- params->channel->center_freq);
+ params->chandef.chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
brcmf_ch_to_chanspec(cfg->channel,
@@ -1453,10 +1099,10 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
/* set channel for starter */
target_channel = cfg->channel;
- err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
- &target_channel);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
+ target_channel);
if (err) {
- WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
+ brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err);
goto done;
}
} else
@@ -1465,33 +1111,33 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
cfg->ibss_starter = false;
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
- &join_params, join_params_size);
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+ &join_params, join_params_size);
if (err) {
- WL_ERR("WLC_SET_SSID failed (%d)\n", err);
+ brcmf_err("WLC_SET_SSID failed (%d)\n", err);
goto done;
}
done:
if (err)
- clear_bit(WL_STATUS_CONNECTING, &cfg->status);
- WL_TRACE("Exit\n");
+ clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
static s32
brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
- brcmf_link_down(cfg);
+ brcmf_link_down(ifp->vif);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1499,8 +1145,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
static s32 brcmf_set_wpa_version(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1511,10 +1156,10 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
else
val = WPA_AUTH_DISABLED;
- WL_CONN("setting wpa_auth to 0x%0x\n", val);
- err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val);
if (err) {
- WL_ERR("set wpa_auth failed (%d)\n", err);
+ brcmf_err("set wpa_auth failed (%d)\n", err);
return err;
}
sec = &profile->sec;
@@ -1525,8 +1170,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
static s32 brcmf_set_auth_type(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1534,27 +1178,27 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
switch (sme->auth_type) {
case NL80211_AUTHTYPE_OPEN_SYSTEM:
val = 0;
- WL_CONN("open system\n");
+ brcmf_dbg(CONN, "open system\n");
break;
case NL80211_AUTHTYPE_SHARED_KEY:
val = 1;
- WL_CONN("shared key\n");
+ brcmf_dbg(CONN, "shared key\n");
break;
case NL80211_AUTHTYPE_AUTOMATIC:
val = 2;
- WL_CONN("automatic\n");
+ brcmf_dbg(CONN, "automatic\n");
break;
case NL80211_AUTHTYPE_NETWORK_EAP:
- WL_CONN("network eap\n");
+ brcmf_dbg(CONN, "network eap\n");
default:
val = 2;
- WL_ERR("invalid auth type (%d)\n", sme->auth_type);
+ brcmf_err("invalid auth type (%d)\n", sme->auth_type);
break;
}
- err = brcmf_dev_intvar_set(ndev, "auth", val);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val);
if (err) {
- WL_ERR("set auth failed (%d)\n", err);
+ brcmf_err("set auth failed (%d)\n", err);
return err;
}
sec = &profile->sec;
@@ -1566,8 +1210,7 @@ static s32
brcmf_set_set_cipher(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
s32 pval = 0;
s32 gval = 0;
@@ -1589,8 +1232,8 @@ brcmf_set_set_cipher(struct net_device *ndev,
pval = AES_ENABLED;
break;
default:
- WL_ERR("invalid cipher pairwise (%d)\n",
- sme->crypto.ciphers_pairwise[0]);
+ brcmf_err("invalid cipher pairwise (%d)\n",
+ sme->crypto.ciphers_pairwise[0]);
return -EINVAL;
}
}
@@ -1610,16 +1253,16 @@ brcmf_set_set_cipher(struct net_device *ndev,
gval = AES_ENABLED;
break;
default:
- WL_ERR("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ brcmf_err("invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
}
- WL_CONN("pval (%d) gval (%d)\n", pval, gval);
- err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
+ brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval);
if (err) {
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
return err;
}
@@ -1633,16 +1276,16 @@ brcmf_set_set_cipher(struct net_device *ndev,
static s32
brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
if (sme->crypto.n_akm_suites) {
- err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
+ err = brcmf_fil_iovar_int_get(netdev_priv(ndev),
+ "wpa_auth", &val);
if (err) {
- WL_ERR("could not get wpa_auth (%d)\n", err);
+ brcmf_err("could not get wpa_auth (%d)\n", err);
return err;
}
if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
@@ -1654,8 +1297,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA_AUTH_PSK;
break;
default:
- WL_ERR("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ brcmf_err("invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -1667,16 +1310,17 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA2_AUTH_PSK;
break;
default:
- WL_ERR("invalid cipher group (%d)\n",
- sme->crypto.cipher_group);
+ brcmf_err("invalid cipher group (%d)\n",
+ sme->crypto.cipher_group);
return -EINVAL;
}
}
- WL_CONN("setting wpa_auth to %d\n", val);
- err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
+ err = brcmf_fil_iovar_int_set(netdev_priv(ndev),
+ "wpa_auth", val);
if (err) {
- WL_ERR("could not set wpa_auth (%d)\n", err);
+ brcmf_err("could not set wpa_auth (%d)\n", err);
return err;
}
}
@@ -1690,22 +1334,20 @@ static s32
brcmf_set_sharedkey(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_cfg80211_security *sec;
struct brcmf_wsec_key key;
s32 val;
s32 err = 0;
- s32 bssidx;
- WL_CONN("key len (%d)\n", sme->key_len);
+ brcmf_dbg(CONN, "key len (%d)\n", sme->key_len);
if (sme->key_len == 0)
return 0;
sec = &profile->sec;
- WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
- sec->wpa_versions, sec->cipher_pairwise);
+ brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",
+ sec->wpa_versions, sec->cipher_pairwise);
if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
return 0;
@@ -1718,7 +1360,7 @@ brcmf_set_sharedkey(struct net_device *ndev,
key.len = (u32) sme->key_len;
key.index = (u32) sme->key_idx;
if (key.len > sizeof(key.data)) {
- WL_ERR("Too long key length (%u)\n", key.len);
+ brcmf_err("Too long key length (%u)\n", key.len);
return -EINVAL;
}
memcpy(key.data, sme->key, key.len);
@@ -1731,25 +1373,24 @@ brcmf_set_sharedkey(struct net_device *ndev,
key.algo = CRYPTO_ALGO_WEP128;
break;
default:
- WL_ERR("Invalid algorithm (%d)\n",
- sme->crypto.ciphers_pairwise[0]);
+ brcmf_err("Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]);
return -EINVAL;
}
/* Set the new key/index */
- WL_CONN("key length (%d) key index (%d) algo (%d)\n",
- key.len, key.index, key.algo);
- WL_CONN("key \"%s\"\n", key.data);
- bssidx = brcmf_find_bssidx(cfg, ndev);
- err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+ brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
+ key.len, key.index, key.algo);
+ brcmf_dbg(CONN, "key \"%s\"\n", key.data);
+ err = send_key_to_dongle(ndev, &key);
if (err)
return err;
if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
- WL_CONN("set auth_type to shared key\n");
+ brcmf_dbg(CONN, "set auth_type to shared key\n");
val = WL_AUTH_SHARED_KEY; /* shared key */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx);
+ err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
if (err)
- WL_ERR("set auth failed (%d)\n", err);
+ brcmf_err("set auth failed (%d)\n", err);
}
return err;
}
@@ -1759,7 +1400,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params;
size_t join_params_size;
@@ -1767,54 +1409,54 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
if (!sme->ssid) {
- WL_ERR("Invalid ssid\n");
+ brcmf_err("Invalid ssid\n");
return -EOPNOTSUPP;
}
- set_bit(WL_STATUS_CONNECTING, &cfg->status);
+ set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
if (chan) {
cfg->channel =
ieee80211_frequency_to_channel(chan->center_freq);
- WL_CONN("channel (%d), center_req (%d)\n",
- cfg->channel, chan->center_freq);
+ brcmf_dbg(CONN, "channel (%d), center_req (%d)\n",
+ cfg->channel, chan->center_freq);
} else
cfg->channel = 0;
- WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
+ brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
err = brcmf_set_wpa_version(ndev, sme);
if (err) {
- WL_ERR("wl_set_wpa_version failed (%d)\n", err);
+ brcmf_err("wl_set_wpa_version failed (%d)\n", err);
goto done;
}
err = brcmf_set_auth_type(ndev, sme);
if (err) {
- WL_ERR("wl_set_auth_type failed (%d)\n", err);
+ brcmf_err("wl_set_auth_type failed (%d)\n", err);
goto done;
}
err = brcmf_set_set_cipher(ndev, sme);
if (err) {
- WL_ERR("wl_set_set_cipher failed (%d)\n", err);
+ brcmf_err("wl_set_set_cipher failed (%d)\n", err);
goto done;
}
err = brcmf_set_key_mgmt(ndev, sme);
if (err) {
- WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
+ brcmf_err("wl_set_key_mgmt failed (%d)\n", err);
goto done;
}
err = brcmf_set_sharedkey(ndev, sme);
if (err) {
- WL_ERR("brcmf_set_sharedkey failed (%d)\n", err);
+ brcmf_err("brcmf_set_sharedkey failed (%d)\n", err);
goto done;
}
@@ -1827,23 +1469,23 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
- memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
+ memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
- WL_CONN("ssid \"%s\", len (%d)\n",
- ssid.SSID, ssid.SSID_len);
+ brcmf_dbg(CONN, "ssid \"%s\", len (%d)\n",
+ ssid.SSID, ssid.SSID_len);
brcmf_ch_to_chanspec(cfg->channel,
&join_params, &join_params_size);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
- &join_params, join_params_size);
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+ &join_params, join_params_size);
if (err)
- WL_ERR("WLC_SET_SSID failed (%d)\n", err);
+ brcmf_err("WLC_SET_SSID failed (%d)\n", err);
done:
if (err)
- clear_bit(WL_STATUS_CONNECTING, &cfg->status);
- WL_TRACE("Exit\n");
+ clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1851,44 +1493,43 @@ static s32
brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
u16 reason_code)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_scb_val_le scbval;
s32 err = 0;
- WL_TRACE("Enter. Reason code = %d\n", reason_code);
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter. Reason code = %d\n", reason_code);
+ if (!check_vif_up(ifp->vif))
return -EIO;
- clear_bit(WL_STATUS_CONNECTED, &cfg->status);
+ clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
scbval.val = cpu_to_le32(reason_code);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
- sizeof(struct brcmf_scb_val_le));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
+ &scbval, sizeof(scbval));
if (err)
- WL_ERR("error (%d)\n", err);
-
- cfg->link_up = false;
+ brcmf_err("error (%d)\n", err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
static s32
-brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, s32 mbm)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_if *ifp = netdev_priv(ndev);
u16 txpwrmw;
s32 err = 0;
s32 disable = 0;
s32 dbm = MBM_TO_DBM(mbm);
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
switch (type) {
@@ -1897,7 +1538,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
case NL80211_TX_POWER_LIMITED:
case NL80211_TX_POWER_FIXED:
if (dbm < 0) {
- WL_ERR("TX_POWER_FIXED - dbm is negative\n");
+ brcmf_err("TX_POWER_FIXED - dbm is negative\n");
err = -EINVAL;
goto done;
}
@@ -1905,40 +1546,42 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
}
/* Make sure radio is off or on as far as software is concerned */
disable = WL_RADIO_SW_DISABLE << 16;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
if (err)
- WL_ERR("WLC_SET_RADIO error (%d)\n", err);
+ brcmf_err("WLC_SET_RADIO error (%d)\n", err);
if (dbm > 0xffff)
txpwrmw = 0xffff;
else
txpwrmw = (u16) dbm;
- err = brcmf_dev_intvar_set(ndev, "qtxpower",
- (s32) (brcmf_mw_to_qdbm(txpwrmw)));
+ err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
+ (s32)brcmf_mw_to_qdbm(txpwrmw));
if (err)
- WL_ERR("qtxpower error (%d)\n", err);
+ brcmf_err("qtxpower error (%d)\n", err);
cfg->conf->tx_power = dbm;
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ s32 *dbm)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
s32 txpwrdbm;
u8 result;
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
- err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+ err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
if (err) {
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
goto done;
}
@@ -1946,7 +1589,7 @@ static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
*dbm = (s32) brcmf_qdbm_to_mw(result);
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1954,34 +1597,32 @@ static s32
brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool unicast, bool multicast)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
u32 index;
u32 wsec;
s32 err = 0;
- s32 bssidx;
- WL_TRACE("Enter\n");
- WL_CONN("key index (%d)\n", key_idx);
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+ if (!check_vif_up(ifp->vif))
return -EIO;
- bssidx = brcmf_find_bssidx(cfg, ndev);
- err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+ err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- WL_ERR("WLC_GET_WSEC error (%d)\n", err);
+ brcmf_err("WLC_GET_WSEC error (%d)\n", err);
goto done;
}
if (wsec & WEP_ENABLED) {
/* Just select a new current key */
index = key_idx;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
- &index);
+ err = brcmf_fil_cmd_int_set(ifp,
+ BRCMF_C_SET_KEY_PRIMARY, index);
if (err)
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
}
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -1989,11 +1630,8 @@ static s32
brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_wsec_key key;
- struct brcmf_wsec_key_le key_le;
s32 err = 0;
- s32 bssidx;
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
@@ -2002,20 +1640,19 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
if (!is_multicast_ether_addr(mac_addr))
memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
key.len = (u32) params->key_len;
- bssidx = brcmf_find_bssidx(cfg, ndev);
/* check for key index change */
if (key.len == 0) {
/* key delete */
- err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+ err = send_key_to_dongle(ndev, &key);
if (err)
- WL_ERR("key delete error (%d)\n", err);
+ brcmf_err("key delete error (%d)\n", err);
} else {
if (key.len > sizeof(key.data)) {
- WL_ERR("Invalid key length (%d)\n", key.len);
+ brcmf_err("Invalid key length (%d)\n", key.len);
return -EINVAL;
}
- WL_CONN("Setting the key index %d\n", key.index);
+ brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
memcpy(key.data, params->key, key.len);
if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
@@ -2039,37 +1676,31 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
key.algo = CRYPTO_ALGO_WEP1;
- WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
break;
case WLAN_CIPHER_SUITE_WEP104:
key.algo = CRYPTO_ALGO_WEP128;
- WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
break;
case WLAN_CIPHER_SUITE_TKIP:
key.algo = CRYPTO_ALGO_TKIP;
- WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
key.algo = CRYPTO_ALGO_AES_CCM;
- WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
break;
case WLAN_CIPHER_SUITE_CCMP:
key.algo = CRYPTO_ALGO_AES_CCM;
- WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
break;
default:
- WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
+ brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
return -EINVAL;
}
- convert_key_from_CPU(&key, &key_le);
-
- brcmf_netdev_wait_pend8021x(ndev);
- err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
- sizeof(key_le),
- cfg->extra_buf,
- WL_EXTRA_BUF_MAX, bssidx);
+ err = send_key_to_dongle(ndev, &key);
if (err)
- WL_ERR("wsec_key error (%d)\n", err);
+ brcmf_err("wsec_key error (%d)\n", err);
}
return err;
}
@@ -2079,21 +1710,20 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_wsec_key key;
s32 val;
s32 wsec;
s32 err = 0;
u8 keybuf[8];
- s32 bssidx;
- WL_TRACE("Enter\n");
- WL_CONN("key index (%d)\n", key_idx);
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+ if (!check_vif_up(ifp->vif))
return -EIO;
if (mac_addr) {
- WL_TRACE("Exit");
+ brcmf_dbg(TRACE, "Exit");
return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
}
memset(&key, 0, sizeof(key));
@@ -2102,7 +1732,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
key.index = (u32) key_idx;
if (key.len > sizeof(key.data)) {
- WL_ERR("Too long key length (%u)\n", key.len);
+ brcmf_err("Too long key length (%u)\n", key.len);
err = -EINVAL;
goto done;
}
@@ -2113,59 +1743,58 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
case WLAN_CIPHER_SUITE_WEP40:
key.algo = CRYPTO_ALGO_WEP1;
val = WEP_ENABLED;
- WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
break;
case WLAN_CIPHER_SUITE_WEP104:
key.algo = CRYPTO_ALGO_WEP128;
val = WEP_ENABLED;
- WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
break;
case WLAN_CIPHER_SUITE_TKIP:
- if (cfg->conf->mode != WL_MODE_AP) {
- WL_CONN("Swapping key\n");
+ if (ifp->vif->mode != WL_MODE_AP) {
+ brcmf_dbg(CONN, "Swapping key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
}
key.algo = CRYPTO_ALGO_TKIP;
val = TKIP_ENABLED;
- WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
key.algo = CRYPTO_ALGO_AES_CCM;
val = AES_ENABLED;
- WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
break;
case WLAN_CIPHER_SUITE_CCMP:
key.algo = CRYPTO_ALGO_AES_CCM;
val = AES_ENABLED;
- WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
break;
default:
- WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
+ brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
err = -EINVAL;
goto done;
}
- bssidx = brcmf_find_bssidx(cfg, ndev);
- err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+ err = send_key_to_dongle(ndev, &key);
if (err)
goto done;
- err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+ err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- WL_ERR("get wsec error (%d)\n", err);
+ brcmf_err("get wsec error (%d)\n", err);
goto done;
}
wsec |= val;
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err) {
- WL_ERR("set wsec error (%d)\n", err);
+ brcmf_err("set wsec error (%d)\n", err);
goto done;
}
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2173,37 +1802,32 @@ static s32
brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_wsec_key key;
s32 err = 0;
- s32 bssidx;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
+ if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
+ /* we ignore this key index in this case */
+ brcmf_err("invalid key index (%d)\n", key_idx);
+ return -EINVAL;
+ }
+
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
key.flags = BRCMF_PRIMARY_KEY;
key.algo = CRYPTO_ALGO_OFF;
- WL_CONN("key index (%d)\n", key_idx);
+ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
/* Set the new key/index */
- bssidx = brcmf_find_bssidx(cfg, ndev);
- err = send_key_to_dongle(cfg, bssidx, ndev, &key);
- if (err) {
- if (err == -EINVAL) {
- if (key.index >= DOT11_MAX_DEFAULT_KEYS)
- /* we ignore this key index in this case */
- WL_ERR("invalid key index (%d)\n", key_idx);
- }
- /* Ignore this error, may happen during DISASSOC */
- err = -EAGAIN;
- }
+ err = send_key_to_dongle(ndev, &key);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2213,24 +1837,22 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
void (*callback) (void *cookie, struct key_params * params))
{
struct key_params params;
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_cfg80211_security *sec;
s32 wsec;
s32 err = 0;
- s32 bssidx;
- WL_TRACE("Enter\n");
- WL_CONN("key index (%d)\n", key_idx);
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+ if (!check_vif_up(ifp->vif))
return -EIO;
memset(&params, 0, sizeof(params));
- bssidx = brcmf_find_bssidx(cfg, ndev);
- err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+ err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
- WL_ERR("WLC_GET_WSEC error (%d)\n", err);
+ brcmf_err("WLC_GET_WSEC error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
@@ -2240,29 +1862,29 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
sec = &profile->sec;
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
params.cipher = WLAN_CIPHER_SUITE_WEP40;
- WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
params.cipher = WLAN_CIPHER_SUITE_WEP104;
- WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
}
break;
case TKIP_ENABLED:
params.cipher = WLAN_CIPHER_SUITE_TKIP;
- WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
break;
case AES_ENABLED:
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
- WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
+ brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
break;
default:
- WL_ERR("Invalid algo (0x%x)\n", wsec);
+ brcmf_err("Invalid algo (0x%x)\n", wsec);
err = -EINVAL;
goto done;
}
callback(cookie, &params);
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2270,7 +1892,7 @@ static s32
brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *ndev, u8 key_idx)
{
- WL_INFO("Not supported\n");
+ brcmf_dbg(INFO, "Not supported\n");
return -EOPNOTSUPP;
}
@@ -2279,73 +1901,73 @@ static s32
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
u8 *mac, struct station_info *sinfo)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_scb_val_le scb_val;
int rssi;
s32 rate;
s32 err = 0;
u8 *bssid = profile->bssid;
- struct brcmf_sta_info_le *sta_info_le;
+ struct brcmf_sta_info_le sta_info_le;
- WL_TRACE("Enter, MAC %pM\n", mac);
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
+ if (!check_vif_up(ifp->vif))
return -EIO;
- if (cfg->conf->mode == WL_MODE_AP) {
- err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN,
- cfg->dcmd_buf,
- WL_DCMD_LEN_MAX);
+ if (ifp->vif->mode == WL_MODE_AP) {
+ memcpy(&sta_info_le, mac, ETH_ALEN);
+ err = brcmf_fil_iovar_data_get(ifp, "sta_info",
+ &sta_info_le,
+ sizeof(sta_info_le));
if (err < 0) {
- WL_ERR("GET STA INFO failed, %d\n", err);
+ brcmf_err("GET STA INFO failed, %d\n", err);
goto done;
}
- sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf;
-
sinfo->filled = STATION_INFO_INACTIVE_TIME;
- sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000;
- if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) {
+ sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+ if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
sinfo->filled |= STATION_INFO_CONNECTED_TIME;
- sinfo->connected_time = le32_to_cpu(sta_info_le->in);
+ sinfo->connected_time = le32_to_cpu(sta_info_le.in);
}
- WL_TRACE("STA idle time : %d ms, connected time :%d sec\n",
- sinfo->inactive_time, sinfo->connected_time);
- } else if (cfg->conf->mode == WL_MODE_BSS) {
+ brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
+ sinfo->inactive_time, sinfo->connected_time);
+ } else if (ifp->vif->mode == WL_MODE_BSS) {
if (memcmp(mac, bssid, ETH_ALEN)) {
- WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
- mac, bssid);
+ brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
+ mac, bssid);
err = -ENOENT;
goto done;
}
/* Report the current tx rate */
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
if (err) {
- WL_ERR("Could not get rate (%d)\n", err);
+ brcmf_err("Could not get rate (%d)\n", err);
goto done;
} else {
sinfo->filled |= STATION_INFO_TX_BITRATE;
sinfo->txrate.legacy = rate * 5;
- WL_CONN("Rate %d Mbps\n", rate / 2);
+ brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
}
- if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) {
+ if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+ &ifp->vif->sme_state)) {
memset(&scb_val, 0, sizeof(scb_val));
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
- sizeof(scb_val));
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+ &scb_val, sizeof(scb_val));
if (err) {
- WL_ERR("Could not get rssi (%d)\n", err);
+ brcmf_err("Could not get rssi (%d)\n", err);
goto done;
} else {
rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi;
- WL_CONN("RSSI %d dBm\n", rssi);
+ brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
}
}
} else
err = -EPERM;
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2356,8 +1978,9 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
s32 pm;
s32 err = 0;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
/*
* Powersave enable/disable request is coming from the
@@ -2367,24 +1990,24 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
* FW later while initializing the dongle
*/
cfg->pwr_save = enabled;
- if (!test_bit(WL_STATUS_READY, &cfg->status)) {
+ if (!check_vif_up(ifp->vif)) {
- WL_INFO("Device is not ready, storing the value in cfg_info struct\n");
+ brcmf_dbg(INFO, "Device is not ready, storing the value in cfg_info struct\n");
goto done;
}
pm = enabled ? PM_FAST : PM_OFF;
- WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
+ brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
if (err) {
if (err == -ENODEV)
- WL_ERR("net_device is not ready yet\n");
+ brcmf_err("net_device is not ready yet\n");
else
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
}
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2393,6 +2016,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcm_rateset_le rateset_le;
s32 rate;
s32 val;
@@ -2401,16 +2025,16 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
u32 legacy;
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
/* addr param is always NULL. ignore it */
/* Get current rateset */
- err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
- sizeof(rateset_le));
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CURR_RATESET,
+ &rateset_le, sizeof(rateset_le));
if (err) {
- WL_ERR("could not get current rateset (%d)\n", err);
+ brcmf_err("could not get current rateset (%d)\n", err);
goto done;
}
@@ -2428,22 +2052,23 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
/* Specified rate in bps */
rate = val / 500000;
- WL_CONN("rate %d mbps\n", rate / 2);
+ brcmf_dbg(CONN, "rate %d mbps\n", rate / 2);
/*
*
* Set rate override,
* Since the is a/b/g-blind, both a/bg_rate are enforced.
*/
- err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
- err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
+ err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate);
+ err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate);
if (err_bg && err_a) {
- WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
+ brcmf_err("could not set fixed rate (%d) (%d)\n", err_bg,
+ err_a);
err = err_bg | err_a;
}
done:
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -2464,7 +2089,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
s32 notify_signal;
if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
- WL_ERR("Bss info is larger than buffer. Discarding\n");
+ brcmf_err("Bss info is larger than buffer. Discarding\n");
return 0;
}
@@ -2485,13 +2110,11 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
notify_ielen = le32_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
- WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
- bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
- WL_CONN("Channel: %d(%d)\n", channel, freq);
- WL_CONN("Capability: %X\n", notify_capability);
- WL_CONN("Beacon interval: %d\n", notify_interval);
- WL_CONN("Signal: %d\n", notify_signal);
+ brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);
+ brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);
+ brcmf_dbg(CONN, "Capability: %X\n", notify_capability);
+ brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
+ brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
0, notify_capability, notify_interval, notify_ie,
@@ -2522,13 +2145,14 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
int i;
bss_list = cfg->bss_list;
- if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
- WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
- bss_list->version);
+ if (bss_list->count != 0 &&
+ bss_list->version != BRCMF_BSS_INFO_VERSION) {
+ brcmf_err("Version %d != WL_BSS_INFO_VERSION\n",
+ bss_list->version);
return -EOPNOTSUPP;
}
- WL_SCAN("scanned AP count (%d)\n", bss_list->count);
- for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
+ brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);
+ for (i = 0; i < bss_list->count; i++) {
bi = next_bss_le(bss_list, bi);
err = brcmf_inform_single_bss(cfg, bi);
if (err)
@@ -2555,7 +2179,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
size_t notify_ielen;
s32 notify_signal;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
if (buf == NULL) {
@@ -2565,9 +2189,10 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+ err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
+ buf, WL_BSS_INFO_MAX);
if (err) {
- WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
+ brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err);
goto CleanUp;
}
@@ -2590,10 +2215,10 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
notify_ielen = le32_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
- WL_CONN("channel: %d(%d)\n", channel, freq);
- WL_CONN("capability: %X\n", notify_capability);
- WL_CONN("beacon interval: %d\n", notify_interval);
- WL_CONN("signal: %d\n", notify_signal);
+ brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
+ brcmf_dbg(CONN, "capability: %X\n", notify_capability);
+ brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
+ brcmf_dbg(CONN, "signal: %d\n", notify_signal);
bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
0, notify_capability, notify_interval,
@@ -2610,14 +2235,14 @@ CleanUp:
kfree(buf);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
-static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg)
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
{
- return cfg->conf->mode == WL_MODE_IBSS;
+ return vif->mode == WL_MODE_IBSS;
}
/*
@@ -2674,12 +2299,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
return false;
}
-struct brcmf_vs_tlv *
+static struct brcmf_vs_tlv *
brcmf_find_wpaie(u8 *parse, u32 len)
{
struct brcmf_tlv *ie;
- while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) {
+ while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
return (struct brcmf_vs_tlv *)ie;
@@ -2689,7 +2314,9 @@ brcmf_find_wpaie(u8 *parse, u32 len)
static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_bss_info_le *bi;
struct brcmf_ssid *ssid;
struct brcmf_tlv *tim;
@@ -2699,17 +2326,17 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
u8 *ie;
s32 err = 0;
- WL_TRACE("Enter\n");
- if (brcmf_is_ibssmode(cfg))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (brcmf_is_ibssmode(ifp->vif))
return err;
ssid = &profile->ssid;
*(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
- err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO,
- cfg->extra_buf, WL_EXTRA_BUF_MAX);
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+ cfg->extra_buf, WL_EXTRA_BUF_MAX);
if (err) {
- WL_ERR("Could not get bss info %d\n", err);
+ brcmf_err("Could not get bss info %d\n", err);
goto update_bss_info_out;
}
@@ -2732,252 +2359,30 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
* so we speficially query dtim information to dongle.
*/
u32 var;
- err = brcmf_dev_intvar_get(cfg_to_ndev(cfg),
- "dtim_assoc", &var);
+ err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
if (err) {
- WL_ERR("wl dtim_assoc failed (%d)\n", err);
+ brcmf_err("wl dtim_assoc failed (%d)\n", err);
goto update_bss_info_out;
}
dtim_period = (u8)var;
}
- profile->beacon_interval = beacon_interval;
- profile->dtim_period = dtim_period;
-
update_bss_info_out:
- WL_TRACE("Exit");
+ brcmf_dbg(TRACE, "Exit");
return err;
}
static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
struct escan_info *escan = &cfg->escan_info;
- struct brcmf_ssid ssid;
-
- set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status);
- if (cfg->iscan_on) {
- iscan->state = WL_ISCAN_STATE_IDLE;
-
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
-
- cancel_work_sync(&iscan->work);
- /* Abort iscan running in FW */
- memset(&ssid, 0, sizeof(ssid));
- brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
-
- if (cfg->scan_request) {
- /* Indidate scan abort to cfg80211 layer */
- WL_INFO("Terminating scan in progress\n");
- cfg80211_scan_done(cfg->scan_request, true);
- cfg->scan_request = NULL;
- }
- }
- if (cfg->escan_on && cfg->scan_request) {
+ set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
+ if (cfg->scan_request) {
escan->escan_state = WL_ESCAN_STATE_IDLE;
brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
}
- clear_bit(WL_STATUS_SCANNING, &cfg->status);
- clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status);
-}
-
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
- bool aborted)
-{
- struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
- struct net_device *ndev = cfg_to_ndev(cfg);
-
- if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scan complete while device not scanning\n");
- return;
- }
- if (cfg->scan_request) {
- WL_SCAN("ISCAN Completed scan: %s\n",
- aborted ? "Aborted" : "Done");
- cfg80211_scan_done(cfg->scan_request, aborted);
- brcmf_set_mpc(ndev, 1);
- cfg->scan_request = NULL;
- }
- cfg->iscan_kickstart = false;
-}
-
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
-{
- if (iscan->state != WL_ISCAN_STATE_IDLE) {
- WL_SCAN("wake up iscan\n");
- schedule_work(&iscan->work);
- return 0;
- }
-
- return -EIO;
-}
-
-static s32
-brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
- struct brcmf_scan_results **bss_list)
-{
- struct brcmf_iscan_results list;
- struct brcmf_scan_results *results;
- struct brcmf_scan_results_le *results_le;
- struct brcmf_iscan_results *list_buf;
- s32 err = 0;
-
- memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
- list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
- results = &list_buf->results;
- results_le = &list_buf->results_le;
- results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
- results->version = 0;
- results->count = 0;
-
- memset(&list, 0, sizeof(list));
- list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
- err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
- BRCMF_ISCAN_RESULTS_FIXED_SIZE,
- iscan->scan_buf, WL_ISCAN_BUF_MAX);
- if (err) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- results->buflen = le32_to_cpu(results_le->buflen);
- results->version = le32_to_cpu(results_le->version);
- results->count = le32_to_cpu(results_le->count);
- WL_SCAN("results->count = %d\n", results_le->count);
- WL_SCAN("results->buflen = %d\n", results_le->buflen);
- *status = le32_to_cpu(list_buf->status_le);
- WL_SCAN("status = %d\n", *status);
- *bss_list = results;
-
- return err;
-}
-
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
- s32 err = 0;
-
- iscan->state = WL_ISCAN_STATE_IDLE;
- brcmf_inform_bss(cfg);
- brcmf_notify_iscan_complete(iscan, false);
-
- return err;
-}
-
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
- s32 err = 0;
-
- /* Reschedule the timer */
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
-
- return err;
-}
-
-static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
- s32 err = 0;
-
- brcmf_inform_bss(cfg);
- brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
- /* Reschedule the timer */
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
-
- return err;
-}
-
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
- s32 err = 0;
-
- iscan->state = WL_ISCAN_STATE_IDLE;
- brcmf_notify_iscan_complete(iscan, true);
-
- return err;
-}
-
-static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- container_of(work, struct brcmf_cfg80211_iscan_ctrl,
- work);
- struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
- struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
- u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
-
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
-
- if (brcmf_get_iscan_results(iscan, &status, &cfg->bss_list)) {
- status = BRCMF_SCAN_RESULTS_ABORTED;
- WL_ERR("Abort iscan\n");
- }
-
- el->handler[status](cfg);
-}
-
-static void brcmf_iscan_timer(unsigned long data)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- (struct brcmf_cfg80211_iscan_ctrl *)data;
-
- if (iscan) {
- iscan->timer_on = 0;
- WL_SCAN("timer expired\n");
- brcmf_wakeup_iscan(iscan);
- }
-}
-
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
-
- if (cfg->iscan_on) {
- iscan->state = WL_ISCAN_STATE_IDLE;
- INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
- }
-
- return 0;
-}
-
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
-{
- memset(el, 0, sizeof(*el));
- el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
- el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
- el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
- el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
- el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
-}
-
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
- int err = 0;
-
- if (cfg->iscan_on) {
- iscan->ndev = cfg_to_ndev(cfg);
- brcmf_init_iscan_eloop(&iscan->el);
- iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
- init_timer(&iscan->timer);
- iscan->timer.data = (unsigned long) iscan;
- iscan->timer.function = brcmf_iscan_timer;
- err = brcmf_invoke_iscan(cfg);
- if (!err)
- iscan->data = cfg;
- }
-
- return err;
+ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+ clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
}
static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
@@ -2996,9 +2401,8 @@ static void brcmf_escan_timeout(unsigned long data)
(struct brcmf_cfg80211_info *)data;
if (cfg->scan_request) {
- WL_ERR("timer expired\n");
- if (cfg->escan_on)
- schedule_work(&cfg->escan_timeout_work);
+ brcmf_err("timer expired\n");
+ schedule_work(&cfg->escan_timeout_work);
}
}
@@ -3035,10 +2439,11 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
}
static s32
-brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
+brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct net_device *ndev = ifp->ndev;
s32 status;
s32 err = 0;
struct brcmf_escan_result_le *escan_result_le;
@@ -3049,31 +2454,29 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
u32 i;
bool aborted;
- status = be32_to_cpu(e->status);
+ status = e->status;
- if (!ndev || !cfg->escan_on ||
- !test_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
- ndev, cfg->escan_on,
- !test_bit(WL_STATUS_SCANNING, &cfg->status));
+ if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ brcmf_err("scan not ready ndev %p drv_status %x\n", ndev,
+ !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
return -EPERM;
}
if (status == BRCMF_E_STATUS_PARTIAL) {
- WL_SCAN("ESCAN Partial result\n");
+ brcmf_dbg(SCAN, "ESCAN Partial result\n");
escan_result_le = (struct brcmf_escan_result_le *) data;
if (!escan_result_le) {
- WL_ERR("Invalid escan result (NULL pointer)\n");
+ brcmf_err("Invalid escan result (NULL pointer)\n");
goto exit;
}
if (!cfg->scan_request) {
- WL_SCAN("result without cfg80211 request\n");
+ brcmf_dbg(SCAN, "result without cfg80211 request\n");
goto exit;
}
if (le16_to_cpu(escan_result_le->bss_count) != 1) {
- WL_ERR("Invalid bss_count %d: ignoring\n",
- escan_result_le->bss_count);
+ brcmf_err("Invalid bss_count %d: ignoring\n",
+ escan_result_le->bss_count);
goto exit;
}
bss_info_le = &escan_result_le->bss_info_le;
@@ -3081,8 +2484,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
bi_length = le32_to_cpu(bss_info_le->length);
if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
WL_ESCAN_RESULTS_FIXED_SIZE)) {
- WL_ERR("Invalid bss_info length %d: ignoring\n",
- bi_length);
+ brcmf_err("Invalid bss_info length %d: ignoring\n",
+ bi_length);
goto exit;
}
@@ -3090,7 +2493,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
BIT(NL80211_IFTYPE_ADHOC))) {
if (le16_to_cpu(bss_info_le->capability) &
WLAN_CAPABILITY_IBSS) {
- WL_ERR("Ignoring IBSS result\n");
+ brcmf_err("Ignoring IBSS result\n");
goto exit;
}
}
@@ -3098,7 +2501,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
list = (struct brcmf_scan_results *)
cfg->escan_info.escan_buf;
if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
- WL_ERR("Buffer is too small: ignoring\n");
+ brcmf_err("Buffer is too small: ignoring\n");
goto exit;
}
@@ -3124,7 +2527,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
brcmf_notify_escan_complete(cfg, ndev, aborted,
false);
} else
- WL_ERR("Unexpected scan result 0x%x\n", status);
+ brcmf_err("Unexpected scan result 0x%x\n", status);
}
exit:
return err;
@@ -3132,18 +2535,15 @@ exit:
static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
{
-
- if (cfg->escan_on) {
- cfg->el.handler[BRCMF_E_ESCAN_RESULT] =
- brcmf_cfg80211_escan_handler;
- cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
- /* Init scan_timeout timer */
- init_timer(&cfg->escan_timeout);
- cfg->escan_timeout.data = (unsigned long) cfg;
- cfg->escan_timeout.function = brcmf_escan_timeout;
- INIT_WORK(&cfg->escan_timeout_work,
- brcmf_cfg80211_escan_timeout_worker);
- }
+ brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,
+ brcmf_cfg80211_escan_handler);
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ /* Init scan_timeout timer */
+ init_timer(&cfg->escan_timeout);
+ cfg->escan_timeout.data = (unsigned long) cfg;
+ cfg->escan_timeout.function = brcmf_escan_timeout;
+ INIT_WORK(&cfg->escan_timeout_work,
+ brcmf_cfg80211_escan_timeout_worker);
}
static __always_inline void brcmf_delay(u32 ms)
@@ -3158,19 +2558,8 @@ static __always_inline void brcmf_delay(u32 ms)
static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-
- /*
- * Check for WL_STATUS_READY before any function call which
- * could result is bus access. Don't block the resume for
- * any driver error conditions
- */
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
- if (test_bit(WL_STATUS_READY, &cfg->status))
- brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
-
- WL_TRACE("Exit\n");
return 0;
}
@@ -3179,85 +2568,49 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_cfg80211_vif *vif;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
/*
- * Check for WL_STATUS_READY before any function call which
- * could result is bus access. Don't block the suspend for
- * any driver error conditions
+ * if the primary net_device is not READY there is nothing
+ * we can do but pray resume goes smoothly.
*/
+ vif = ((struct brcmf_if *)netdev_priv(ndev))->vif;
+ if (!check_vif_up(vif))
+ goto exit;
- /*
- * While going to suspend if associated with AP disassociate
- * from AP to save power while system is in suspended state
- */
- if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) ||
- test_bit(WL_STATUS_CONNECTING, &cfg->status)) &&
- test_bit(WL_STATUS_READY, &cfg->status)) {
- WL_INFO("Disassociating from AP"
- " while entering suspend state\n");
- brcmf_link_down(cfg);
-
+ list_for_each_entry(vif, &cfg->vif_list, list) {
+ if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))
+ continue;
/*
- * Make sure WPA_Supplicant receives all the event
+ * While going to suspend if associated with AP disassociate
+ * from AP to save power while system is in suspended state
+ */
+ brcmf_link_down(vif);
+
+ /* Make sure WPA_Supplicant receives all the event
* generated due to DISASSOC call to the fw to keep
* the state fw and WPA_Supplicant state consistent
*/
brcmf_delay(500);
}
- if (test_bit(WL_STATUS_READY, &cfg->status))
+ /* end any scanning */
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
brcmf_abort_scanning(cfg);
- else
- clear_bit(WL_STATUS_SCANNING, &cfg->status);
/* Turn off watchdog timer */
- if (test_bit(WL_STATUS_READY, &cfg->status))
- brcmf_set_mpc(ndev, 1);
-
- WL_TRACE("Exit\n");
+ brcmf_set_mpc(ndev, 1);
+exit:
+ brcmf_dbg(TRACE, "Exit\n");
+ /* clear any scanning activity */
+ cfg->scan_status = 0;
return 0;
}
static __used s32
-brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
-{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- u32 buflen;
-
- buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf,
- WL_DCMD_LEN_MAX);
- BUG_ON(!buflen);
-
- return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf,
- buflen);
-}
-
-static s32
-brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
- s32 buf_len)
-{
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
- u32 len;
- s32 err = 0;
-
- len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf,
- WL_DCMD_LEN_MAX);
- BUG_ON(!len);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf,
- WL_DCMD_LEN_MAX);
- if (err) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- memcpy(buf, cfg->dcmd_buf, buf_len);
-
- return err;
-}
-
-static __used s32
brcmf_update_pmklist(struct net_device *ndev,
struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
{
@@ -3266,17 +2619,18 @@ brcmf_update_pmklist(struct net_device *ndev,
pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
- WL_CONN("No of elements %d\n", pmkid_len);
+ brcmf_dbg(CONN, "No of elements %d\n", pmkid_len);
for (i = 0; i < pmkid_len; i++) {
- WL_CONN("PMKID[%d]: %pM =\n", i,
- &pmk_list->pmkids.pmkid[i].BSSID);
+ brcmf_dbg(CONN, "PMKID[%d]: %pM =\n", i,
+ &pmk_list->pmkids.pmkid[i].BSSID);
for (j = 0; j < WLAN_PMKID_LEN; j++)
- WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
+ brcmf_dbg(CONN, "%02x\n",
+ pmk_list->pmkids.pmkid[i].PMKID[j]);
}
if (!err)
- brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
- sizeof(*pmk_list));
+ brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
+ (char *)pmk_list, sizeof(*pmk_list));
return err;
}
@@ -3286,13 +2640,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
s32 err = 0;
int i;
int pmkid_len;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
pmkid_len = le32_to_cpu(pmkids->npmkid);
@@ -3309,14 +2664,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
} else
err = -EINVAL;
- WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
- pmkids->pmkid[pmkid_len].BSSID);
+ brcmf_dbg(CONN, "set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
+ pmkids->pmkid[pmkid_len].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
- WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
+ brcmf_dbg(CONN, "%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -3325,21 +2680,22 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list pmkid;
s32 err = 0;
int i, pmkid_len;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
- WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
- &pmkid.pmkid[0].BSSID);
+ brcmf_dbg(CONN, "del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
+ &pmkid.pmkid[0].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
- WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
+ brcmf_dbg(CONN, "%02x\n", pmkid.pmkid[0].PMKID[i]);
pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
for (i = 0; i < pmkid_len; i++)
@@ -3366,7 +2722,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -3375,16 +2731,17 @@ static s32
brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
- WL_TRACE("Enter\n");
- if (!check_sys_up(wiphy))
+ brcmf_dbg(TRACE, "Enter\n");
+ if (!check_vif_up(ifp->vif))
return -EIO;
memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -3398,10 +2755,11 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
* cfg80211_scan_request one out of the received PNO event.
*/
static s32
-brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
+brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct net_device *ndev = ifp->ndev;
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
struct cfg80211_scan_request *request = NULL;
struct cfg80211_ssid *ssid = NULL;
@@ -3414,10 +2772,10 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
u32 result_count;
u32 status;
- WL_SCAN("Enter\n");
+ brcmf_dbg(SCAN, "Enter\n");
- if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) {
- WL_SCAN("PFN NET LOST event. Do Nothing\n");
+ if (e->event_code == BRCMF_E_PFN_NET_LOST) {
+ brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");
return 0;
}
@@ -3430,7 +2788,7 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
* multiple NET_FOUND events. For now place a warning here.
*/
WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
- WL_SCAN("PFN NET FOUND event. count: %d\n", result_count);
+ brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
if (result_count > 0) {
int i;
@@ -3449,13 +2807,14 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
for (i = 0; i < result_count; i++) {
netinfo = &netinfo_start[i];
if (!netinfo) {
- WL_ERR("Invalid netinfo ptr. index: %d\n", i);
+ brcmf_err("Invalid netinfo ptr. index: %d\n",
+ i);
err = -EINVAL;
goto out_err;
}
- WL_SCAN("SSID:%s Channel:%d\n",
- netinfo->SSID, netinfo->channel);
+ brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
+ netinfo->SSID, netinfo->channel);
memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
ssid[i].ssid_len = netinfo->SSID_len;
request->n_ssids++;
@@ -3478,21 +2837,21 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
if (request->n_ssids)
request->ssids = &ssid[0];
- if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
/* Abort any on-going scan */
brcmf_abort_scanning(cfg);
}
- set_bit(WL_STATUS_SCANNING, &cfg->status);
+ set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
err = brcmf_do_escan(cfg, wiphy, ndev, request);
if (err) {
- clear_bit(WL_STATUS_SCANNING, &cfg->status);
+ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
goto out_err;
}
cfg->sched_escan = true;
cfg->scan_request = request;
} else {
- WL_ERR("FALSE PNO Event. (pfn_count == 0)\n");
+ brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
goto out_err;
}
@@ -3509,21 +2868,19 @@ out_err:
return err;
}
-#ifndef CONFIG_BRCMISCAN
static int brcmf_dev_pno_clean(struct net_device *ndev)
{
- char iovbuf[128];
int ret;
/* Disable pfn */
- ret = brcmf_dev_intvar_set(ndev, "pfn", 0);
+ ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
if (ret == 0) {
/* clear pfn */
- ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0,
- iovbuf, sizeof(iovbuf));
+ ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
+ NULL, 0);
}
if (ret < 0)
- WL_ERR("failed code %d\n", ret);
+ brcmf_err("failed code %d\n", ret);
return ret;
}
@@ -3531,7 +2888,6 @@ static int brcmf_dev_pno_clean(struct net_device *ndev)
static int brcmf_dev_pno_config(struct net_device *ndev)
{
struct brcmf_pno_param_le pfn_param;
- char iovbuf[128];
memset(&pfn_param, 0, sizeof(pfn_param));
pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
@@ -3544,9 +2900,8 @@ static int brcmf_dev_pno_config(struct net_device *ndev)
/* set up pno scan fr */
pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
- return brcmf_dev_iovar_setbuf(ndev, "pfn_set",
- &pfn_param, sizeof(pfn_param),
- iovbuf, sizeof(iovbuf));
+ return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
+ &pfn_param, sizeof(pfn_param));
}
static int
@@ -3554,30 +2909,30 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct net_device *ndev,
struct cfg80211_sched_scan_request *request)
{
- char iovbuf[128];
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
struct brcmf_pno_net_param_le pfn;
int i;
int ret = 0;
- WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n",
- request->n_match_sets, request->n_ssids);
- if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scanning already : status (%lu)\n", cfg->status);
+ brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
+ request->n_match_sets, request->n_ssids);
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
return -EAGAIN;
}
if (!request || !request->n_ssids || !request->n_match_sets) {
- WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
- request ? request->n_ssids : 0);
+ brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
+ request ? request->n_ssids : 0);
return -EINVAL;
}
if (request->n_ssids > 0) {
for (i = 0; i < request->n_ssids; i++) {
/* Active scan req for ssids */
- WL_SCAN(">>> Active scan req for ssid (%s)\n",
- request->ssids[i].ssid);
+ brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
+ request->ssids[i].ssid);
/*
* match_set ssids is a supert set of n_ssid list,
@@ -3590,14 +2945,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
/* clean up everything */
ret = brcmf_dev_pno_clean(ndev);
if (ret < 0) {
- WL_ERR("failed error=%d\n", ret);
+ brcmf_err("failed error=%d\n", ret);
return ret;
}
/* configure pno */
ret = brcmf_dev_pno_config(ndev);
if (ret < 0) {
- WL_ERR("PNO setup failed!! ret=%d\n", ret);
+ brcmf_err("PNO setup failed!! ret=%d\n", ret);
return -EINVAL;
}
@@ -3610,7 +2965,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
ssid_len = ssid->ssid_len;
if (!ssid_len) {
- WL_ERR("skip broadcast ssid\n");
+ brcmf_err("skip broadcast ssid\n");
continue;
}
pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
@@ -3620,16 +2975,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
- ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add",
- &pfn, sizeof(pfn),
- iovbuf, sizeof(iovbuf));
- WL_SCAN(">>> PNO filter %s for ssid (%s)\n",
- ret == 0 ? "set" : "failed",
- ssid->ssid);
+ ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
+ sizeof(pfn));
+ brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
+ ret == 0 ? "set" : "failed", ssid->ssid);
}
/* Enable the PNO */
- if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) {
- WL_ERR("PNO enable failed!! ret=%d\n", ret);
+ if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
+ brcmf_err("PNO enable failed!! ret=%d\n", ret);
return -EINVAL;
}
} else {
@@ -3644,24 +2997,31 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- WL_SCAN("enter\n");
+ brcmf_dbg(SCAN, "enter\n");
brcmf_dev_pno_clean(ndev);
if (cfg->sched_escan)
brcmf_notify_escan_complete(cfg, ndev, true, true);
return 0;
}
-#endif /* CONFIG_BRCMISCAN */
#ifdef CONFIG_NL80211_TESTMODE
static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = cfg->wdev->netdev;
+ struct net_device *ndev = cfg_to_ndev(cfg);
struct brcmf_dcmd *dcmd = data;
struct sk_buff *reply;
int ret;
- ret = brcmf_netlink_dcmd(ndev, dcmd);
+ brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
+ dcmd->buf, dcmd->len);
+
+ if (dcmd->set)
+ ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
+ dcmd->buf, dcmd->len);
+ else
+ ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
+ dcmd->buf, dcmd->len);
if (ret == 0) {
reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
@@ -3673,25 +3033,25 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
/* set auth */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
if (err < 0) {
- WL_ERR("auth error %d\n", err);
+ brcmf_err("auth error %d\n", err);
return err;
}
/* set wsec */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
if (err < 0) {
- WL_ERR("wsec error %d\n", err);
+ brcmf_err("wsec error %d\n", err);
return err;
}
/* set upper-layer auth */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth",
- WPA_AUTH_NONE, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
if (err < 0) {
- WL_ERR("wpa_auth error %d\n", err);
+ brcmf_err("wpa_auth error %d\n", err);
return err;
}
@@ -3708,8 +3068,9 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
static s32
brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
- bool is_rsn_ie, s32 bssidx)
+ bool is_rsn_ie)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
u32 auth = 0; /* d11 open authentication */
u16 count;
s32 err = 0;
@@ -3724,7 +3085,7 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
u16 rsn_cap;
u32 wme_bss_disable;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
if (wpa_ie == NULL)
goto exit;
@@ -3738,13 +3099,13 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
/* check for multicast cipher suite */
if (offset + WPA_IE_MIN_OUI_LEN > len) {
err = -EINVAL;
- WL_ERR("no multicast cipher suite\n");
+ brcmf_err("no multicast cipher suite\n");
goto exit;
}
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- WL_ERR("ivalid OUI\n");
+ brcmf_err("ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
@@ -3766,7 +3127,7 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
break;
default:
err = -EINVAL;
- WL_ERR("Invalid multi cast cipher info\n");
+ brcmf_err("Invalid multi cast cipher info\n");
goto exit;
}
@@ -3777,13 +3138,13 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
/* Check for unicast suite(s) */
if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
err = -EINVAL;
- WL_ERR("no unicast cipher suite\n");
+ brcmf_err("no unicast cipher suite\n");
goto exit;
}
for (i = 0; i < count; i++) {
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- WL_ERR("ivalid OUI\n");
+ brcmf_err("ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
@@ -3801,7 +3162,7 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
pval |= AES_ENABLED;
break;
default:
- WL_ERR("Ivalid unicast security info\n");
+ brcmf_err("Ivalid unicast security info\n");
}
offset++;
}
@@ -3811,33 +3172,33 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
/* Check for auth key management suite(s) */
if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
err = -EINVAL;
- WL_ERR("no auth key mgmt suite\n");
+ brcmf_err("no auth key mgmt suite\n");
goto exit;
}
for (i = 0; i < count; i++) {
if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
err = -EINVAL;
- WL_ERR("ivalid OUI\n");
+ brcmf_err("ivalid OUI\n");
goto exit;
}
offset += TLV_OUI_LEN;
switch (data[offset]) {
case RSN_AKM_NONE:
- WL_TRACE("RSN_AKM_NONE\n");
+ brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
wpa_auth |= WPA_AUTH_NONE;
break;
case RSN_AKM_UNSPECIFIED:
- WL_TRACE("RSN_AKM_UNSPECIFIED\n");
+ brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
(wpa_auth |= WPA_AUTH_UNSPECIFIED);
break;
case RSN_AKM_PSK:
- WL_TRACE("RSN_AKM_PSK\n");
+ brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
(wpa_auth |= WPA_AUTH_PSK);
break;
default:
- WL_ERR("Ivalid key mgmt info\n");
+ brcmf_err("Ivalid key mgmt info\n");
}
offset++;
}
@@ -3850,10 +3211,10 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
wme_bss_disable = 0;
}
/* set wme_bss_disable to sync RSN Capabilities */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable",
- wme_bss_disable, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
+ wme_bss_disable);
if (err < 0) {
- WL_ERR("wme_bss_disable error %d\n", err);
+ brcmf_err("wme_bss_disable error %d\n", err);
goto exit;
}
}
@@ -3861,21 +3222,21 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
wsec = (pval | gval | SES_OW_ENABLED);
/* set auth */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
if (err < 0) {
- WL_ERR("auth error %d\n", err);
+ brcmf_err("auth error %d\n", err);
goto exit;
}
/* set wsec */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err < 0) {
- WL_ERR("wsec error %d\n", err);
+ brcmf_err("wsec error %d\n", err);
goto exit;
}
/* set upper-layer auth */
- err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx);
+ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
if (err < 0) {
- WL_ERR("wpa_auth error %d\n", err);
+ brcmf_err("wpa_auth error %d\n", err);
goto exit;
}
@@ -3884,7 +3245,7 @@ exit:
}
static s32
-brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
+brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
struct parsed_vndr_ies *vndr_ies)
{
s32 err = 0;
@@ -3903,15 +3264,15 @@ brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
vndrie = (struct brcmf_vs_tlv *)ie;
/* len should be bigger than OUI length + one */
if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
- WL_ERR("invalid vndr ie. length is too small %d\n",
- vndrie->len);
+ brcmf_err("invalid vndr ie. length is too small %d\n",
+ vndrie->len);
goto next;
}
/* if wpa or wme ie, do not add ie */
if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
((vndrie->oui_type == WPA_OUI_TYPE) ||
(vndrie->oui_type == WME_OUI_TYPE))) {
- WL_TRACE("Found WPA/WME oui. Do not add it\n");
+ brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");
goto next;
}
@@ -3924,20 +3285,21 @@ brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
vndr_ies->count++;
- WL_TRACE("** OUI %02x %02x %02x, type 0x%02x\n",
- parsed_info->vndrie.oui[0],
- parsed_info->vndrie.oui[1],
- parsed_info->vndrie.oui[2],
- parsed_info->vndrie.oui_type);
+ brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n",
+ parsed_info->vndrie.oui[0],
+ parsed_info->vndrie.oui[1],
+ parsed_info->vndrie.oui[2],
+ parsed_info->vndrie.oui_type);
if (vndr_ies->count >= MAX_VNDR_IE_NUMBER)
break;
next:
- remaining_len -= ie->len;
- if (remaining_len <= 2)
+ remaining_len -= (ie->len + TLV_HDR_LEN);
+ if (remaining_len <= TLV_HDR_LEN)
ie = NULL;
else
- ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len);
+ ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
+ TLV_HDR_LEN);
}
return err;
}
@@ -3963,17 +3325,18 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
return ie_len + VNDR_IE_HDR_SIZE;
}
-s32
-brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev, s32 bssidx, s32 pktflag,
- u8 *vndr_ie_buf, u32 vndr_ie_len)
+static
+s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
+ const u8 *vndr_ie_buf, u32 vndr_ie_len)
{
+ struct brcmf_if *ifp;
+ struct vif_saved_ie *saved_ie;
s32 err = 0;
u8 *iovar_ie_buf;
u8 *curr_ie_buf;
u8 *mgmt_ie_buf = NULL;
int mgmt_ie_buf_len;
- u32 *mgmt_ie_len = 0;
+ u32 *mgmt_ie_len;
u32 del_add_ie_buf_len = 0;
u32 total_ie_buf_len = 0;
u32 parsed_ie_buf_len = 0;
@@ -3984,40 +3347,42 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
u8 *ptr;
int remained_buf_len;
- WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
+ if (!vif)
+ return -ENODEV;
+ ifp = vif->ifp;
+ saved_ie = &vif->saved_ie;
+
+ brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (!iovar_ie_buf)
return -ENOMEM;
curr_ie_buf = iovar_ie_buf;
- if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) ||
- test_bit(WL_STATUS_AP_CREATED, &cfg->status)) {
+ if (ifp->vif->mode == WL_MODE_AP) {
switch (pktflag) {
case VNDR_IE_PRBRSP_FLAG:
- mgmt_ie_buf = cfg->ap_info->probe_res_ie;
- mgmt_ie_len = &cfg->ap_info->probe_res_ie_len;
- mgmt_ie_buf_len =
- sizeof(cfg->ap_info->probe_res_ie);
+ mgmt_ie_buf = saved_ie->probe_res_ie;
+ mgmt_ie_len = &saved_ie->probe_res_ie_len;
+ mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
break;
case VNDR_IE_BEACON_FLAG:
- mgmt_ie_buf = cfg->ap_info->beacon_ie;
- mgmt_ie_len = &cfg->ap_info->beacon_ie_len;
- mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie);
+ mgmt_ie_buf = saved_ie->beacon_ie;
+ mgmt_ie_len = &saved_ie->beacon_ie_len;
+ mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
break;
default:
err = -EPERM;
- WL_ERR("not suitable type\n");
+ brcmf_err("not suitable type\n");
goto exit;
}
- bssidx = 0;
} else {
err = -EPERM;
- WL_ERR("not suitable type\n");
+ brcmf_err("not suitable type\n");
goto exit;
}
if (vndr_ie_len > mgmt_ie_buf_len) {
err = -ENOMEM;
- WL_ERR("extra IE size too big\n");
+ brcmf_err("extra IE size too big\n");
goto exit;
}
@@ -4033,11 +3398,11 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
}
}
- if (mgmt_ie_buf != NULL) {
+ if (mgmt_ie_buf && *mgmt_ie_len) {
if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
(memcmp(mgmt_ie_buf, curr_ie_buf,
parsed_ie_buf_len) == 0)) {
- WL_TRACE("Previous mgmt IE is equals to current IE");
+ brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");
goto exit;
}
@@ -4048,12 +3413,12 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
for (i = 0; i < old_vndr_ies.count; i++) {
vndrie_info = &old_vndr_ies.ie_info[i];
- WL_TRACE("DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
- vndrie_info->vndrie.id,
- vndrie_info->vndrie.len,
- vndrie_info->vndrie.oui[0],
- vndrie_info->vndrie.oui[1],
- vndrie_info->vndrie.oui[2]);
+ brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
+ vndrie_info->vndrie.id,
+ vndrie_info->vndrie.len,
+ vndrie_info->vndrie.oui[0],
+ vndrie_info->vndrie.oui[1],
+ vndrie_info->vndrie.oui[2]);
del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
vndrie_info->ie_ptr,
@@ -4075,24 +3440,27 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
for (i = 0; i < new_vndr_ies.count; i++) {
vndrie_info = &new_vndr_ies.ie_info[i];
- WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
- vndrie_info->vndrie.id,
- vndrie_info->vndrie.len,
- vndrie_info->vndrie.oui[0],
- vndrie_info->vndrie.oui[1],
- vndrie_info->vndrie.oui[2]);
+ /* verify remained buf size before copy data */
+ if (remained_buf_len < (vndrie_info->vndrie.len +
+ VNDR_IE_VSIE_OFFSET)) {
+ brcmf_err("no space in mgmt_ie_buf: len left %d",
+ remained_buf_len);
+ break;
+ }
+ remained_buf_len -= (vndrie_info->ie_len +
+ VNDR_IE_VSIE_OFFSET);
+
+ brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
+ vndrie_info->vndrie.id,
+ vndrie_info->vndrie.len,
+ vndrie_info->vndrie.oui[0],
+ vndrie_info->vndrie.oui[1],
+ vndrie_info->vndrie.oui[2]);
del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
vndrie_info->ie_ptr,
vndrie_info->ie_len,
"add");
- /* verify remained buf size before copy data */
- remained_buf_len -= vndrie_info->ie_len;
- if (remained_buf_len < 0) {
- WL_ERR("no space in mgmt_ie_buf: len left %d",
- remained_buf_len);
- break;
- }
/* save the parsed IE in wl struct */
memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
@@ -4104,13 +3472,10 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
}
}
if (total_ie_buf_len) {
- err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie",
- iovar_ie_buf,
- total_ie_buf_len,
- cfg->extra_buf,
- WL_EXTRA_BUF_MAX, bssidx);
+ err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
+ total_ie_buf_len);
if (err)
- WL_ERR("vndr ie set error : %d\n", err);
+ brcmf_err("vndr ie set error : %d\n", err);
}
exit:
@@ -4123,25 +3488,25 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ap_settings *settings)
{
s32 ie_offset;
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_tlv *ssid_ie;
struct brcmf_ssid_le ssid_le;
- s32 ioctl_value;
s32 err = -EPERM;
struct brcmf_tlv *rsn_ie;
struct brcmf_vs_tlv *wpa_ie;
struct brcmf_join_params join_params;
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
s32 bssidx = 0;
- WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
- settings->channel_type, settings->beacon_interval,
- settings->dtim_period);
- WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
- settings->ssid, settings->ssid_len, settings->auth_type,
- settings->inactivity_timeout);
+ brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
+ cfg80211_get_chandef_type(&settings->chandef),
+ settings->beacon_interval,
+ settings->dtim_period);
+ brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
+ settings->ssid, settings->ssid_len, settings->auth_type,
+ settings->inactivity_timeout);
- if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) {
- WL_ERR("Not in AP creation mode\n");
+ if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) {
+ brcmf_err("Not in AP creation mode\n");
return -EPERM;
}
@@ -4157,29 +3522,26 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
- WL_TRACE("SSID is (%s) in Head\n", ssid_le.SSID);
+ brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);
} else {
memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
}
brcmf_set_mpc(ndev, 0);
- ioctl_value = 1;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
if (err < 0) {
- WL_ERR("BRCMF_C_DOWN error %d\n", err);
+ brcmf_err("BRCMF_C_DOWN error %d\n", err);
goto exit;
}
- ioctl_value = 1;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
if (err < 0) {
- WL_ERR("SET INFRA error %d\n", err);
+ brcmf_err("SET INFRA error %d\n", err);
goto exit;
}
- ioctl_value = 1;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
if (err < 0) {
- WL_ERR("setting AP mode failed %d\n", err);
+ brcmf_err("setting AP mode failed %d\n", err);
goto exit;
}
@@ -4191,82 +3553,63 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
settings->beacon.tail_len);
- kfree(cfg->ap_info->rsn_ie);
- cfg->ap_info->rsn_ie = NULL;
- kfree(cfg->ap_info->wpa_ie);
- cfg->ap_info->wpa_ie = NULL;
-
if ((wpa_ie != NULL || rsn_ie != NULL)) {
- WL_TRACE("WPA(2) IE is found\n");
+ brcmf_dbg(TRACE, "WPA(2) IE is found\n");
if (wpa_ie != NULL) {
/* WPA IE */
- err = brcmf_configure_wpaie(ndev, wpa_ie, false,
- bssidx);
+ err = brcmf_configure_wpaie(ndev, wpa_ie, false);
if (err < 0)
goto exit;
- cfg->ap_info->wpa_ie = kmemdup(wpa_ie,
- wpa_ie->len +
- TLV_HDR_LEN,
- GFP_KERNEL);
} else {
/* RSN IE */
err = brcmf_configure_wpaie(ndev,
- (struct brcmf_vs_tlv *)rsn_ie, true, bssidx);
+ (struct brcmf_vs_tlv *)rsn_ie, true);
if (err < 0)
goto exit;
- cfg->ap_info->rsn_ie = kmemdup(rsn_ie,
- rsn_ie->len +
- TLV_HDR_LEN,
- GFP_KERNEL);
}
- cfg->ap_info->security_mode = true;
} else {
- WL_TRACE("No WPA(2) IEs found\n");
+ brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
brcmf_configure_opensecurity(ndev, bssidx);
- cfg->ap_info->security_mode = false;
}
/* Set Beacon IEs to FW */
- err = brcmf_set_management_ie(cfg, ndev, bssidx,
- VNDR_IE_BEACON_FLAG,
- (u8 *)settings->beacon.tail,
- settings->beacon.tail_len);
+ err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
+ VNDR_IE_BEACON_FLAG,
+ settings->beacon.tail,
+ settings->beacon.tail_len);
if (err)
- WL_ERR("Set Beacon IE Failed\n");
+ brcmf_err("Set Beacon IE Failed\n");
else
- WL_TRACE("Applied Vndr IEs for Beacon\n");
+ brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
/* Set Probe Response IEs to FW */
- err = brcmf_set_management_ie(cfg, ndev, bssidx,
- VNDR_IE_PRBRSP_FLAG,
- (u8 *)settings->beacon.proberesp_ies,
- settings->beacon.proberesp_ies_len);
+ err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
+ VNDR_IE_PRBRSP_FLAG,
+ settings->beacon.proberesp_ies,
+ settings->beacon.proberesp_ies_len);
if (err)
- WL_ERR("Set Probe Resp IE Failed\n");
+ brcmf_err("Set Probe Resp IE Failed\n");
else
- WL_TRACE("Applied Vndr IEs for Probe Resp\n");
+ brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
if (settings->beacon_interval) {
- ioctl_value = settings->beacon_interval;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD,
- &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
+ settings->beacon_interval);
if (err < 0) {
- WL_ERR("Beacon Interval Set Error, %d\n", err);
+ brcmf_err("Beacon Interval Set Error, %d\n", err);
goto exit;
}
}
if (settings->dtim_period) {
- ioctl_value = settings->dtim_period;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD,
- &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
+ settings->dtim_period);
if (err < 0) {
- WL_ERR("DTIM Interval Set Error, %d\n", err);
+ brcmf_err("DTIM Interval Set Error, %d\n", err);
goto exit;
}
}
- ioctl_value = 1;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0) {
- WL_ERR("BRCMF_C_UP error (%d)\n", err);
+ brcmf_err("BRCMF_C_UP error (%d)\n", err);
goto exit;
}
@@ -4274,14 +3617,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
/* join parameters starts with ssid */
memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
/* create softap */
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params,
- sizeof(join_params));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+ &join_params, sizeof(join_params));
if (err < 0) {
- WL_ERR("SET SSID error (%d)\n", err);
+ brcmf_err("SET SSID error (%d)\n", err);
goto exit;
}
- clear_bit(WL_STATUS_AP_CREATING, &cfg->status);
- set_bit(WL_STATUS_AP_CREATED, &cfg->status);
+ clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+ set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
exit:
if (err)
@@ -4291,31 +3634,28 @@ exit:
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- s32 ioctl_value;
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = -EPERM;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
- if (cfg->conf->mode == WL_MODE_AP) {
+ if (ifp->vif->mode == WL_MODE_AP) {
/* Due to most likely deauths outstanding we sleep */
/* first to make sure they get processed by fw. */
msleep(400);
- ioctl_value = 0;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0) {
- WL_ERR("setting AP mode failed %d\n", err);
+ brcmf_err("setting AP mode failed %d\n", err);
goto exit;
}
- ioctl_value = 0;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
if (err < 0) {
- WL_ERR("BRCMF_C_UP error %d\n", err);
+ brcmf_err("BRCMF_C_UP error %d\n", err);
goto exit;
}
brcmf_set_mpc(ndev, 1);
- clear_bit(WL_STATUS_AP_CREATING, &cfg->status);
- clear_bit(WL_STATUS_AP_CREATED, &cfg->status);
+ clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+ clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
}
exit:
return err;
@@ -4326,24 +3666,25 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
u8 *mac)
{
struct brcmf_scb_val_le scbval;
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
if (!mac)
return -EFAULT;
- WL_TRACE("Enter %pM\n", mac);
+ brcmf_dbg(TRACE, "Enter %pM\n", mac);
- if (!check_sys_up(wiphy))
+ if (!check_vif_up(ifp->vif))
return -EIO;
memcpy(&scbval.ea, mac, ETH_ALEN);
scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
- &scbval, sizeof(scbval));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
+ &scbval, sizeof(scbval));
if (err)
- WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
+ brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -4373,11 +3714,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.start_ap = brcmf_cfg80211_start_ap,
.stop_ap = brcmf_cfg80211_stop_ap,
.del_station = brcmf_cfg80211_del_station,
-#ifndef CONFIG_BRCMISCAN
- /* scheduled scan need e-scan, which is mutual exclusive with i-scan */
.sched_scan_start = brcmf_cfg80211_sched_scan_start,
.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
-#endif
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode
#endif
@@ -4401,106 +3739,126 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
{
-#ifndef CONFIG_BRCMISCAN
/* scheduled scan settings */
wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-#endif
}
-static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev)
+static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
{
- struct wireless_dev *wdev;
+ struct wiphy *wiphy;
s32 err = 0;
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
- if (!wdev)
+ wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
+ if (!wiphy) {
+ brcmf_err("Could not allocate wiphy device\n");
return ERR_PTR(-ENOMEM);
-
- wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
- sizeof(struct brcmf_cfg80211_info));
- if (!wdev->wiphy) {
- WL_ERR("Could not allocate wiphy device\n");
- err = -ENOMEM;
- goto wiphy_new_out;
- }
- set_wiphy_dev(wdev->wiphy, ndev);
- wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
- wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_AP);
- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
+ }
+ set_wiphy_dev(wiphy, phydev);
+ wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+ wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
* it as 11a by default.
* This will be updated with
* 11n phy tables in
* "ifconfig up"
* if phy has 11n capability
*/
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
- wdev->wiphy->cipher_suites = __wl_cipher_suites;
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
- wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wiphy->cipher_suites = __wl_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
* save mode
* by default
*/
- brcmf_wiphy_pno_params(wdev->wiphy);
- err = wiphy_register(wdev->wiphy);
+ brcmf_wiphy_pno_params(wiphy);
+ err = wiphy_register(wiphy);
if (err < 0) {
- WL_ERR("Could not register wiphy device (%d)\n", err);
- goto wiphy_register_out;
+ brcmf_err("Could not register wiphy device (%d)\n", err);
+ wiphy_free(wiphy);
+ return ERR_PTR(err);
}
- return wdev;
+ return wiphy;
+}
+
+static
+struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+ struct net_device *netdev,
+ s32 mode, bool pm_block)
+{
+ struct brcmf_cfg80211_vif *vif;
-wiphy_register_out:
- wiphy_free(wdev->wiphy);
+ if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
+ return ERR_PTR(-ENOSPC);
-wiphy_new_out:
- kfree(wdev);
+ vif = kzalloc(sizeof(*vif), GFP_KERNEL);
+ if (!vif)
+ return ERR_PTR(-ENOMEM);
+
+ vif->wdev.wiphy = cfg->wiphy;
+ vif->wdev.netdev = netdev;
+ vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
+
+ if (netdev) {
+ vif->ifp = netdev_priv(netdev);
+ netdev->ieee80211_ptr = &vif->wdev;
+ SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
+ }
- return ERR_PTR(err);
+ vif->mode = mode;
+ vif->pm_block = pm_block;
+ vif->roam_off = -1;
+
+ brcmf_init_prof(&vif->profile);
+
+ list_add_tail(&vif->list, &cfg->vif_list);
+ cfg->vif_cnt++;
+ return vif;
}
-static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg)
+static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
{
- struct wireless_dev *wdev = cfg->wdev;
+ struct brcmf_cfg80211_info *cfg;
+ struct wiphy *wiphy;
- if (!wdev) {
- WL_ERR("wdev is invalid\n");
- return;
+ wiphy = vif->wdev.wiphy;
+ cfg = wiphy_priv(wiphy);
+ list_del(&vif->list);
+ cfg->vif_cnt--;
+
+ kfree(vif);
+ if (!cfg->vif_cnt) {
+ wiphy_unregister(wiphy);
+ wiphy_free(wiphy);
}
- wiphy_unregister(wdev->wiphy);
- wiphy_free(wdev->wiphy);
- kfree(wdev);
- cfg->wdev = NULL;
}
-static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
- const struct brcmf_event_msg *e)
+static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
{
- u32 event = be32_to_cpu(e->event_type);
- u32 status = be32_to_cpu(e->status);
+ u32 event = e->event_code;
+ u32 status = e->status;
if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
- WL_CONN("Processing set ssid\n");
- cfg->link_up = true;
+ brcmf_dbg(CONN, "Processing set ssid\n");
return true;
}
return false;
}
-static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg,
- const struct brcmf_event_msg *e)
+static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
{
- u32 event = be32_to_cpu(e->event_type);
- u16 flags = be16_to_cpu(e->flags);
+ u32 event = e->event_code;
+ u16 flags = e->flags;
if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
- WL_CONN("Processing link down\n");
+ brcmf_dbg(CONN, "Processing link down\n");
return true;
}
return false;
@@ -4509,18 +3867,17 @@ static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg,
static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
const struct brcmf_event_msg *e)
{
- u32 event = be32_to_cpu(e->event_type);
- u32 status = be32_to_cpu(e->status);
+ u32 event = e->event_code;
+ u32 status = e->status;
if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
- WL_CONN("Processing Link %s & no network found\n",
- be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
- "up" : "down");
+ brcmf_dbg(CONN, "Processing Link %s & no network found\n",
+ e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
return true;
}
if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
- WL_CONN("Processing connecting & no network found\n");
+ brcmf_dbg(CONN, "Processing connecting & no network found\n");
return true;
}
@@ -4541,7 +3898,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
{
- struct net_device *ndev = cfg_to_ndev(cfg);
+ struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
u32 req_len;
@@ -4550,10 +3907,10 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
brcmf_clear_assoc_ies(cfg);
- err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf,
- WL_ASSOC_INFO_MAX);
+ err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
+ cfg->extra_buf, WL_ASSOC_INFO_MAX);
if (err) {
- WL_ERR("could not get assoc info (%d)\n", err);
+ brcmf_err("could not get assoc info (%d)\n", err);
return err;
}
assoc_info =
@@ -4561,11 +3918,11 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
req_len = le32_to_cpu(assoc_info->req_len);
resp_len = le32_to_cpu(assoc_info->resp_len);
if (req_len) {
- err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
- cfg->extra_buf,
- WL_ASSOC_INFO_MAX);
+ err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
+ cfg->extra_buf,
+ WL_ASSOC_INFO_MAX);
if (err) {
- WL_ERR("could not get assoc req (%d)\n", err);
+ brcmf_err("could not get assoc req (%d)\n", err);
return err;
}
conn_info->req_ie_len = req_len;
@@ -4577,11 +3934,11 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
conn_info->req_ie = NULL;
}
if (resp_len) {
- err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
- cfg->extra_buf,
- WL_ASSOC_INFO_MAX);
+ err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
+ cfg->extra_buf,
+ WL_ASSOC_INFO_MAX);
if (err) {
- WL_ERR("could not get assoc resp (%d)\n", err);
+ brcmf_err("could not get assoc resp (%d)\n", err);
return err;
}
conn_info->resp_ie_len = resp_len;
@@ -4592,8 +3949,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
conn_info->resp_ie_len = 0;
conn_info->resp_ie = NULL;
}
- WL_CONN("req len (%d) resp len (%d)\n",
- conn_info->req_ie_len, conn_info->resp_ie_len);
+ brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",
+ conn_info->req_ie_len, conn_info->resp_ie_len);
return err;
}
@@ -4603,7 +3960,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
const struct brcmf_event_msg *e)
{
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
struct wiphy *wiphy = cfg_to_wiphy(cfg);
struct ieee80211_channel *notify_channel = NULL;
@@ -4614,7 +3972,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
u32 target_channel;
u8 *buf;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
brcmf_get_assoc_ies(cfg);
memcpy(profile->bssid, e->addr, ETH_ALEN);
@@ -4628,7 +3986,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
/* data sent to dongle has to be little endian */
*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+ buf, WL_BSS_INFO_MAX);
if (err)
goto done;
@@ -4650,10 +4009,10 @@ done:
cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
conn_info->req_ie, conn_info->req_ie_len,
conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
- WL_CONN("Report roaming result\n");
+ brcmf_dbg(CONN, "Report roaming result\n");
- set_bit(WL_STATUS_CONNECTED, &cfg->status);
- WL_TRACE("Exit\n");
+ set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -4662,13 +4021,15 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev, const struct brcmf_event_msg *e,
bool completed)
{
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
s32 err = 0;
- WL_TRACE("Enter\n");
+ brcmf_dbg(TRACE, "Enter\n");
- if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) {
+ if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+ &ifp->vif->sme_state)) {
if (completed) {
brcmf_get_assoc_ies(cfg);
memcpy(profile->bssid, e->addr, ETH_ALEN);
@@ -4684,11 +4045,12 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
WLAN_STATUS_AUTH_TIMEOUT,
GFP_KERNEL);
if (completed)
- set_bit(WL_STATUS_CONNECTED, &cfg->status);
- WL_CONN("Report connect result - connection %s\n",
- completed ? "succeeded" : "failed");
+ set_bit(BRCMF_VIF_STATUS_CONNECTED,
+ &ifp->vif->sme_state);
+ brcmf_dbg(CONN, "Report connect result - connection %s\n",
+ completed ? "succeeded" : "failed");
}
- WL_TRACE("Exit\n");
+ brcmf_dbg(TRACE, "Exit\n");
return err;
}
@@ -4698,14 +4060,14 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
const struct brcmf_event_msg *e, void *data)
{
s32 err = 0;
- u32 event = be32_to_cpu(e->event_type);
- u32 reason = be32_to_cpu(e->reason);
- u32 len = be32_to_cpu(e->datalen);
+ u32 event = e->event_code;
+ u32 reason = e->reason;
+ u32 len = e->datalen;
static int generation;
struct station_info sinfo;
- WL_CONN("event %d, reason %d\n", event, reason);
+ brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
memset(&sinfo, 0, sizeof(sinfo));
sinfo.filled = 0;
@@ -4713,7 +4075,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
reason == BRCMF_E_STATUS_SUCCESS) {
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
if (!data) {
- WL_ERR("No IEs present in ASSOC/REASSOC_IND");
+ brcmf_err("No IEs present in ASSOC/REASSOC_IND");
return -EINVAL;
}
sinfo.assoc_req_ies = data;
@@ -4732,45 +4094,43 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
}
static s32
-brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
+brcmf_notify_connect_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_cfg80211_profile *profile = cfg->profile;
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+ struct net_device *ndev = ifp->ndev;
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
s32 err = 0;
- if (cfg->conf->mode == WL_MODE_AP) {
+ if (ifp->vif->mode == WL_MODE_AP) {
err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
- } else if (brcmf_is_linkup(cfg, e)) {
- WL_CONN("Linkup\n");
- if (brcmf_is_ibssmode(cfg)) {
+ } else if (brcmf_is_linkup(e)) {
+ brcmf_dbg(CONN, "Linkup\n");
+ if (brcmf_is_ibssmode(ifp->vif)) {
memcpy(profile->bssid, e->addr, ETH_ALEN);
wl_inform_ibss(cfg, ndev, e->addr);
cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
- clear_bit(WL_STATUS_CONNECTING, &cfg->status);
- set_bit(WL_STATUS_CONNECTED, &cfg->status);
+ clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+ &ifp->vif->sme_state);
+ set_bit(BRCMF_VIF_STATUS_CONNECTED,
+ &ifp->vif->sme_state);
} else
brcmf_bss_connect_done(cfg, ndev, e, true);
- } else if (brcmf_is_linkdown(cfg, e)) {
- WL_CONN("Linkdown\n");
- if (brcmf_is_ibssmode(cfg)) {
- clear_bit(WL_STATUS_CONNECTING, &cfg->status);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg->status))
- brcmf_link_down(cfg);
- } else {
+ } else if (brcmf_is_linkdown(e)) {
+ brcmf_dbg(CONN, "Linkdown\n");
+ if (!brcmf_is_ibssmode(ifp->vif)) {
brcmf_bss_connect_done(cfg, ndev, e, false);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg->status)) {
+ if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
+ &ifp->vif->sme_state))
cfg80211_disconnected(ndev, 0, NULL, 0,
- GFP_KERNEL);
- brcmf_link_down(cfg);
- }
+ GFP_KERNEL);
}
- brcmf_init_prof(cfg->profile);
+ brcmf_link_down(ifp->vif);
+ brcmf_init_prof(ndev_to_prof(ndev));
} else if (brcmf_is_nonetwork(cfg, e)) {
- if (brcmf_is_ibssmode(cfg))
- clear_bit(WL_STATUS_CONNECTING, &cfg->status);
+ if (brcmf_is_ibssmode(ifp->vif))
+ clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+ &ifp->vif->sme_state);
else
brcmf_bss_connect_done(cfg, ndev, e, false);
}
@@ -4779,30 +4139,29 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
}
static s32
-brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
+brcmf_notify_roaming_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 err = 0;
- u32 event = be32_to_cpu(e->event_type);
- u32 status = be32_to_cpu(e->status);
+ u32 event = e->event_code;
+ u32 status = e->status;
if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
- if (test_bit(WL_STATUS_CONNECTED, &cfg->status))
- brcmf_bss_roaming_done(cfg, ndev, e);
+ if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+ brcmf_bss_roaming_done(cfg, ifp->ndev, e);
else
- brcmf_bss_connect_done(cfg, ndev, e, true);
+ brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
}
return err;
}
static s32
-brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
+brcmf_notify_mic_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
- u16 flags = be16_to_cpu(e->flags);
+ u16 flags = e->flags;
enum nl80211_key_type key_type;
if (flags & BRCMF_EVENT_MSG_GROUP)
@@ -4810,85 +4169,14 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg,
else
key_type = NL80211_KEYTYPE_PAIRWISE;
- cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
+ cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
NULL, GFP_KERNEL);
return 0;
}
-static s32
-brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- struct brcmf_channel_info_le channel_inform_le;
- struct brcmf_scan_results_le *bss_list_le;
- u32 len = WL_SCAN_BUF_MAX;
- s32 err = 0;
- bool scan_abort = false;
- u32 scan_channel;
-
- WL_TRACE("Enter\n");
-
- if (cfg->iscan_on && cfg->iscan_kickstart) {
- WL_TRACE("Exit\n");
- return brcmf_wakeup_iscan(cfg_to_iscan(cfg));
- }
-
- if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
- WL_ERR("Scan complete while device not scanning\n");
- scan_abort = true;
- err = -EINVAL;
- goto scan_done_out;
- }
-
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
- sizeof(channel_inform_le));
- if (err) {
- WL_ERR("scan busy (%d)\n", err);
- scan_abort = true;
- goto scan_done_out;
- }
- scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
- if (scan_channel)
- WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
- cfg->bss_list = cfg->scan_results;
- bss_list_le = (struct brcmf_scan_results_le *) cfg->bss_list;
-
- memset(cfg->scan_results, 0, len);
- bss_list_le->buflen = cpu_to_le32(len);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
- cfg->scan_results, len);
- if (err) {
- WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
- err = -EINVAL;
- scan_abort = true;
- goto scan_done_out;
- }
- cfg->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
- cfg->scan_results->version = le32_to_cpu(bss_list_le->version);
- cfg->scan_results->count = le32_to_cpu(bss_list_le->count);
-
- err = brcmf_inform_bss(cfg);
- if (err)
- scan_abort = true;
-
-scan_done_out:
- if (cfg->scan_request) {
- WL_SCAN("calling cfg80211_scan_done\n");
- cfg80211_scan_done(cfg->scan_request, scan_abort);
- brcmf_set_mpc(ndev, 1);
- cfg->scan_request = NULL;
- }
-
- WL_TRACE("Exit\n");
-
- return err;
-}
-
static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
{
- conf->mode = (u32)-1;
conf->frag_threshold = (u32)-1;
conf->rts_threshold = (u32)-1;
conf->retry_short = (u32)-1;
@@ -4896,82 +4184,53 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
conf->tx_power = -1;
}
-static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
-{
- memset(el, 0, sizeof(*el));
- el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
- el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
- el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
- el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
- el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results;
+static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
+{
+ brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
+ brcmf_notify_roaming_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
+ brcmf_notify_mic_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
+ brcmf_notify_connect_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+ brcmf_notify_sched_scan_results);
}
static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
{
- kfree(cfg->scan_results);
- cfg->scan_results = NULL;
- kfree(cfg->bss_info);
- cfg->bss_info = NULL;
kfree(cfg->conf);
cfg->conf = NULL;
- kfree(cfg->profile);
- cfg->profile = NULL;
- kfree(cfg->scan_req_int);
- cfg->scan_req_int = NULL;
kfree(cfg->escan_ioctl_buf);
cfg->escan_ioctl_buf = NULL;
- kfree(cfg->dcmd_buf);
- cfg->dcmd_buf = NULL;
kfree(cfg->extra_buf);
cfg->extra_buf = NULL;
- kfree(cfg->iscan);
- cfg->iscan = NULL;
kfree(cfg->pmk_list);
cfg->pmk_list = NULL;
- if (cfg->ap_info) {
- kfree(cfg->ap_info->wpa_ie);
- kfree(cfg->ap_info->rsn_ie);
- kfree(cfg->ap_info);
- cfg->ap_info = NULL;
- }
}
static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
{
- cfg->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
- if (!cfg->scan_results)
- goto init_priv_mem_out;
cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
if (!cfg->conf)
goto init_priv_mem_out;
- cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL);
- if (!cfg->profile)
- goto init_priv_mem_out;
- cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (!cfg->bss_info)
- goto init_priv_mem_out;
- cfg->scan_req_int = kzalloc(sizeof(*cfg->scan_req_int),
- GFP_KERNEL);
- if (!cfg->scan_req_int)
- goto init_priv_mem_out;
cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
if (!cfg->escan_ioctl_buf)
goto init_priv_mem_out;
- cfg->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
- if (!cfg->dcmd_buf)
- goto init_priv_mem_out;
cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (!cfg->extra_buf)
goto init_priv_mem_out;
- cfg->iscan = kzalloc(sizeof(*cfg->iscan), GFP_KERNEL);
- if (!cfg->iscan)
- goto init_priv_mem_out;
cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
if (!cfg->pmk_list)
goto init_priv_mem_out;
@@ -4984,298 +4243,107 @@ init_priv_mem_out:
return -ENOMEM;
}
-/*
-* retrieve first queued event from head
-*/
-
-static struct brcmf_cfg80211_event_q *brcmf_deq_event(
- struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_event_q *e = NULL;
-
- spin_lock_irq(&cfg->evt_q_lock);
- if (!list_empty(&cfg->evt_q_list)) {
- e = list_first_entry(&cfg->evt_q_list,
- struct brcmf_cfg80211_event_q, evt_q_list);
- list_del(&e->evt_q_list);
- }
- spin_unlock_irq(&cfg->evt_q_lock);
-
- return e;
-}
-
-/*
-* push event to tail of the queue
-*
-* remark: this function may not sleep as it is called in atomic context.
-*/
-
-static s32
-brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event,
- const struct brcmf_event_msg *msg, void *data)
-{
- struct brcmf_cfg80211_event_q *e;
- s32 err = 0;
- ulong flags;
- u32 data_len;
- u32 total_len;
-
- total_len = sizeof(struct brcmf_cfg80211_event_q);
- if (data)
- data_len = be32_to_cpu(msg->datalen);
- else
- data_len = 0;
- total_len += data_len;
- e = kzalloc(total_len, GFP_ATOMIC);
- if (!e)
- return -ENOMEM;
-
- e->etype = event;
- memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
- if (data)
- memcpy(&e->edata, data, data_len);
-
- spin_lock_irqsave(&cfg->evt_q_lock, flags);
- list_add_tail(&e->evt_q_list, &cfg->evt_q_list);
- spin_unlock_irqrestore(&cfg->evt_q_lock, flags);
-
- return err;
-}
-
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
-{
- kfree(e);
-}
-
-static void brcmf_cfg80211_event_handler(struct work_struct *work)
-{
- struct brcmf_cfg80211_info *cfg =
- container_of(work, struct brcmf_cfg80211_info,
- event_work);
- struct brcmf_cfg80211_event_q *e;
-
- e = brcmf_deq_event(cfg);
- if (unlikely(!e)) {
- WL_ERR("event queue empty...\n");
- return;
- }
-
- do {
- WL_INFO("event type (%d)\n", e->etype);
- if (cfg->el.handler[e->etype])
- cfg->el.handler[e->etype](cfg,
- cfg_to_ndev(cfg),
- &e->emsg, e->edata);
- else
- WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
- brcmf_put_event(e);
- } while ((e = brcmf_deq_event(cfg)));
-
-}
-
-static void brcmf_init_eq(struct brcmf_cfg80211_info *cfg)
-{
- spin_lock_init(&cfg->evt_q_lock);
- INIT_LIST_HEAD(&cfg->evt_q_list);
-}
-
-static void brcmf_flush_eq(struct brcmf_cfg80211_info *cfg)
-{
- struct brcmf_cfg80211_event_q *e;
-
- spin_lock_irq(&cfg->evt_q_lock);
- while (!list_empty(&cfg->evt_q_list)) {
- e = list_first_entry(&cfg->evt_q_list,
- struct brcmf_cfg80211_event_q, evt_q_list);
- list_del(&e->evt_q_list);
- kfree(e);
- }
- spin_unlock_irq(&cfg->evt_q_lock);
-}
-
static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
{
s32 err = 0;
cfg->scan_request = NULL;
cfg->pwr_save = true;
-#ifdef CONFIG_BRCMISCAN
- cfg->iscan_on = true; /* iscan on & off switch.
- we enable iscan per default */
- cfg->escan_on = false; /* escan on & off switch.
- we disable escan per default */
-#else
- cfg->iscan_on = false; /* iscan on & off switch.
- we disable iscan per default */
- cfg->escan_on = true; /* escan on & off switch.
- we enable escan per default */
-#endif
cfg->roam_on = true; /* roam on & off switch.
we enable roam per default */
-
- cfg->iscan_kickstart = false;
cfg->active_scan = true; /* we do active scan for
specific scan per default */
cfg->dongle_up = false; /* dongle is not up yet */
- brcmf_init_eq(cfg);
err = brcmf_init_priv_mem(cfg);
if (err)
return err;
- INIT_WORK(&cfg->event_work, brcmf_cfg80211_event_handler);
- brcmf_init_eloop_handler(&cfg->el);
+ brcmf_register_event_handlers(cfg);
mutex_init(&cfg->usr_sync);
- err = brcmf_init_iscan(cfg);
- if (err)
- return err;
brcmf_init_escan(cfg);
brcmf_init_conf(cfg->conf);
- brcmf_init_prof(cfg->profile);
- brcmf_link_down(cfg);
return err;
}
static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
{
- cancel_work_sync(&cfg->event_work);
cfg->dongle_up = false; /* dongle down */
- brcmf_flush_eq(cfg);
- brcmf_link_down(cfg);
brcmf_abort_scanning(cfg);
brcmf_deinit_priv_mem(cfg);
}
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
- struct device *busdev,
- struct brcmf_pub *drvr)
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+ struct device *busdev)
{
- struct wireless_dev *wdev;
+ struct net_device *ndev = drvr->iflist[0]->ndev;
struct brcmf_cfg80211_info *cfg;
+ struct wiphy *wiphy;
+ struct brcmf_cfg80211_vif *vif;
+ struct brcmf_if *ifp;
s32 err = 0;
if (!ndev) {
- WL_ERR("ndev is invalid\n");
+ brcmf_err("ndev is invalid\n");
return NULL;
}
- wdev = brcmf_alloc_wdev(busdev);
- if (IS_ERR(wdev)) {
+ ifp = netdev_priv(ndev);
+ wiphy = brcmf_setup_wiphy(busdev);
+ if (IS_ERR(wiphy))
return NULL;
- }
- wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
- cfg = wdev_to_cfg(wdev);
- cfg->wdev = wdev;
+ cfg = wiphy_priv(wiphy);
+ cfg->wiphy = wiphy;
cfg->pub = drvr;
- ndev->ieee80211_ptr = wdev;
- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
- wdev->netdev = ndev;
+ INIT_LIST_HEAD(&cfg->vif_list);
+
+ vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
+ if (IS_ERR(vif)) {
+ wiphy_free(wiphy);
+ return NULL;
+ }
+
err = wl_init_priv(cfg);
if (err) {
- WL_ERR("Failed to init iwm_priv (%d)\n", err);
+ brcmf_err("Failed to init iwm_priv (%d)\n", err);
goto cfg80211_attach_out;
}
+ ifp->vif = vif;
return cfg;
cfg80211_attach_out:
- brcmf_free_wdev(cfg);
+ brcmf_free_vif(vif);
return NULL;
}
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
{
- wl_deinit_priv(cfg);
- brcmf_free_wdev(cfg);
-}
-
-void
-brcmf_cfg80211_event(struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- u32 event_type = be32_to_cpu(e->event_type);
- struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-
- if (!brcmf_enq_event(cfg, event_type, e, data))
- schedule_work(&cfg->event_work);
-}
-
-static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
-{
- /* Room for "event_msgs" + '\0' + bitvec */
- s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
- s8 eventmask[BRCMF_EVENTING_MASK_LEN];
- s32 err = 0;
+ struct brcmf_cfg80211_vif *vif;
+ struct brcmf_cfg80211_vif *tmp;
- WL_TRACE("Enter\n");
-
- /* Setup event_msgs */
- brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
- if (err) {
- WL_ERR("Get event_msgs error (%d)\n", err);
- goto dongle_eventmsg_out;
- }
- memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
-
- setbit(eventmask, BRCMF_E_SET_SSID);
- setbit(eventmask, BRCMF_E_ROAM);
- setbit(eventmask, BRCMF_E_PRUNE);
- setbit(eventmask, BRCMF_E_AUTH);
- setbit(eventmask, BRCMF_E_REASSOC);
- setbit(eventmask, BRCMF_E_REASSOC_IND);
- setbit(eventmask, BRCMF_E_DEAUTH_IND);
- setbit(eventmask, BRCMF_E_DISASSOC_IND);
- setbit(eventmask, BRCMF_E_DISASSOC);
- setbit(eventmask, BRCMF_E_JOIN);
- setbit(eventmask, BRCMF_E_ASSOC_IND);
- setbit(eventmask, BRCMF_E_PSK_SUP);
- setbit(eventmask, BRCMF_E_LINK);
- setbit(eventmask, BRCMF_E_NDIS_LINK);
- setbit(eventmask, BRCMF_E_MIC_ERROR);
- setbit(eventmask, BRCMF_E_PMKID_CACHE);
- setbit(eventmask, BRCMF_E_TXFAIL);
- setbit(eventmask, BRCMF_E_JOIN_START);
- setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
- setbit(eventmask, BRCMF_E_ESCAN_RESULT);
- setbit(eventmask, BRCMF_E_PFN_NET_FOUND);
-
- brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
- if (err) {
- WL_ERR("Set event_msgs error (%d)\n", err);
- goto dongle_eventmsg_out;
+ wl_deinit_priv(cfg);
+ list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
+ brcmf_free_vif(vif);
}
-
-dongle_eventmsg_out:
- WL_TRACE("Exit\n");
- return err;
}
static s32
brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
{
- s8 iovbuf[32];
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
__le32 roamtrigger[2];
__le32 roam_delta[2];
- __le32 bcn_to_le;
- __le32 roamvar_le;
/*
* Setup timeout if Beacons are lost and roam is
* off to report link down
*/
if (roamvar) {
- bcn_to_le = cpu_to_le32(bcn_timeout);
- brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
- sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
+ err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
if (err) {
- WL_ERR("bcn_timeout error (%d)\n", err);
+ brcmf_err("bcn_timeout error (%d)\n", err);
goto dongle_rom_out;
}
}
@@ -5284,31 +4352,28 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
* Enable/Disable built-in roaming to allow supplicant
* to take care of roaming
*/
- WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
- roamvar_le = cpu_to_le32(roamvar);
- brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
- sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
+ brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On");
+ err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
if (err) {
- WL_ERR("roam_off error (%d)\n", err);
+ brcmf_err("roam_off error (%d)\n", err);
goto dongle_rom_out;
}
roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
- (void *)roamtrigger, sizeof(roamtrigger));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
+ (void *)roamtrigger, sizeof(roamtrigger));
if (err) {
- WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
+ brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
goto dongle_rom_out;
}
roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
- (void *)roam_delta, sizeof(roam_delta));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
+ (void *)roam_delta, sizeof(roam_delta));
if (err) {
- WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
+ brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
goto dongle_rom_out;
}
@@ -5320,37 +4385,35 @@ static s32
brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
s32 scan_unassoc_time, s32 scan_passive_time)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
- __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
- __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
- __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ scan_assoc_time);
if (err) {
if (err == -EOPNOTSUPP)
- WL_INFO("Scan assoc time is not supported\n");
+ brcmf_dbg(INFO, "Scan assoc time is not supported\n");
else
- WL_ERR("Scan assoc time error (%d)\n", err);
+ brcmf_err("Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ scan_unassoc_time);
if (err) {
if (err == -EOPNOTSUPP)
- WL_INFO("Scan unassoc time is not supported\n");
+ brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
else
- WL_ERR("Scan unassoc time error (%d)\n", err);
+ brcmf_err("Scan unassoc time error (%d)\n", err);
goto dongle_scantime_out;
}
- err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
- &scan_passive_tm_le, sizeof(scan_passive_tm_le));
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+ scan_passive_time);
if (err) {
if (err == -EOPNOTSUPP)
- WL_INFO("Scan passive time is not supported\n");
+ brcmf_dbg(INFO, "Scan passive time is not supported\n");
else
- WL_ERR("Scan passive time error (%d)\n", err);
+ brcmf_err("Scan passive time error (%d)\n", err);
goto dongle_scantime_out;
}
@@ -5360,20 +4423,21 @@ dongle_scantime_out:
static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
{
+ struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct wiphy *wiphy;
s32 phy_list;
s8 phy;
s32 err = 0;
- err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST,
- &phy_list, sizeof(phy_list));
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
+ &phy_list, sizeof(phy_list));
if (err) {
- WL_ERR("error (%d)\n", err);
+ brcmf_err("error (%d)\n", err);
return err;
}
phy = ((char *)&phy_list)[0];
- WL_INFO("%c phy\n", phy);
+ brcmf_dbg(INFO, "%c phy\n", phy);
if (phy == 'n' || phy == 'a') {
wiphy = cfg_to_wiphy(cfg);
wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
@@ -5403,16 +4467,13 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
- err = brcmf_dongle_eventmsg(ndev);
- if (err)
- goto default_conf_out;
-
power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
- err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
+ err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM,
+ power_mode);
if (err)
goto default_conf_out;
- WL_INFO("power save set to %s\n",
- (power_mode ? "enabled" : "disabled"));
+ brcmf_dbg(INFO, "power save set to %s\n",
+ (power_mode ? "enabled" : "disabled"));
err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1),
WL_BEACON_TIMEOUT);
@@ -5436,68 +4497,25 @@ default_conf_out:
}
-static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
{
- char buf[10+IFNAMSIZ];
- struct dentry *fd;
- s32 err = 0;
-
- sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name);
- cfg->debugfsdir = debugfs_create_dir(buf,
- cfg_to_wiphy(cfg)->debugfsdir);
-
- fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir,
- (u16 *)&cfg->profile->beacon_interval);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
-
- fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir,
- (u8 *)&cfg->profile->dtim_period);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
+ set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
+ if (ifp->idx)
+ return 0;
-err_out:
- return err;
+ return brcmf_config_dongle(ifp->drvr->config);
}
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
{
- debugfs_remove_recursive(cfg->debugfsdir);
- cfg->debugfsdir = NULL;
-}
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
-static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
-{
- s32 err = 0;
-
- set_bit(WL_STATUS_READY, &cfg->status);
-
- brcmf_debugfs_add_netdev_params(cfg);
-
- err = brcmf_config_dongle(cfg);
- if (err)
- return err;
-
- brcmf_invoke_iscan(cfg);
-
- return err;
-}
-
-static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
-{
/*
* While going down, if associated with AP disassociate
* from AP to save power
*/
- if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) ||
- test_bit(WL_STATUS_CONNECTING, &cfg->status)) &&
- test_bit(WL_STATUS_READY, &cfg->status)) {
- WL_INFO("Disassociating from AP");
- brcmf_link_down(cfg);
+ if (check_vif_up(ifp->vif)) {
+ brcmf_link_down(ifp->vif);
/* Make sure WPA_Supplicant receives all the event
generated due to DISASSOC call to the fw to keep
@@ -5507,30 +4525,32 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
}
brcmf_abort_scanning(cfg);
- clear_bit(WL_STATUS_READY, &cfg->status);
-
- brcmf_debugfs_remove_netdev(cfg);
+ clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
return 0;
}
-s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_up(struct net_device *ndev)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 err = 0;
mutex_lock(&cfg->usr_sync);
- err = __brcmf_cfg80211_up(cfg);
+ err = __brcmf_cfg80211_up(ifp);
mutex_unlock(&cfg->usr_sync);
return err;
}
-s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_down(struct net_device *ndev)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 err = 0;
mutex_lock(&cfg->usr_sync);
- err = __brcmf_cfg80211_down(cfg);
+ err = __brcmf_cfg80211_down(ifp);
mutex_unlock(&cfg->usr_sync);
return err;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 71ced174748a..e4d9cc7a8e63 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -17,98 +17,12 @@
#ifndef _wl_cfg80211_h_
#define _wl_cfg80211_h_
-#define WL_DBG_NONE 0
-#define WL_DBG_CONN (1 << 5)
-#define WL_DBG_SCAN (1 << 4)
-#define WL_DBG_TRACE (1 << 3)
-#define WL_DBG_INFO (1 << 1)
-#define WL_DBG_ERR (1 << 0)
-#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \
- (WL_DBG_SCAN) | (WL_DBG_CONN))
-
-#define WL_ERR(fmt, ...) \
-do { \
- if (brcmf_dbg_level & WL_DBG_ERR) { \
- if (net_ratelimit()) { \
- pr_err("ERROR @%s : " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
-} while (0)
-
-#if (defined DEBUG)
-#define WL_INFO(fmt, ...) \
-do { \
- if (brcmf_dbg_level & WL_DBG_INFO) { \
- if (net_ratelimit()) { \
- pr_err("INFO @%s : " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
-} while (0)
-
-#define WL_TRACE(fmt, ...) \
-do { \
- if (brcmf_dbg_level & WL_DBG_TRACE) { \
- if (net_ratelimit()) { \
- pr_err("TRACE @%s : " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
-} while (0)
-
-#define WL_SCAN(fmt, ...) \
-do { \
- if (brcmf_dbg_level & WL_DBG_SCAN) { \
- if (net_ratelimit()) { \
- pr_err("SCAN @%s : " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
-} while (0)
-
-#define WL_CONN(fmt, ...) \
-do { \
- if (brcmf_dbg_level & WL_DBG_CONN) { \
- if (net_ratelimit()) { \
- pr_err("CONN @%s : " fmt, \
- __func__, ##__VA_ARGS__); \
- } \
- } \
-} while (0)
-
-#else /* (defined DEBUG) */
-#define WL_INFO(fmt, args...)
-#define WL_TRACE(fmt, args...)
-#define WL_SCAN(fmt, args...)
-#define WL_CONN(fmt, args...)
-#endif /* (defined DEBUG) */
-
-#define WL_NUM_SCAN_MAX 1
-#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used
- * for 2.6.33 kernel
- * or later
- */
-#define WL_SCAN_BUF_MAX (1024 * 8)
+#define WL_NUM_SCAN_MAX 10
+#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
-#define WL_ASSOC_INFO_MAX 512 /*
- * needs to grab assoc info from dongle to
- * report it to cfg80211 through "connect"
- * event
- */
-#define WL_DCMD_LEN_MAX 1024
-#define WL_EXTRA_BUF_MAX 2048
-#define WL_ISCAN_BUF_MAX 2048 /*
- * the buf length can be BRCMF_DCMD_MAXLEN
- * to reduce iteration
- */
-#define WL_ISCAN_TIMER_INTERVAL_MS 3000
-#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1)
-#define WL_AP_MAX 256 /* virtually unlimitted as long
- * as kernel memory allows
- */
-
+#define WL_ASSOC_INFO_MAX 512 /* assoc related fil max buf */
+#define WL_EXTRA_BUF_MAX 2048
#define WL_ROAM_TRIGGER_LEVEL -75
#define WL_ROAM_DELTA 20
#define WL_BEACON_TIMEOUT 3
@@ -127,15 +41,15 @@ do { \
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
#define IE_MAX_LEN 512
-/* dongle status */
-enum wl_status {
- WL_STATUS_READY,
- WL_STATUS_SCANNING,
- WL_STATUS_SCAN_ABORTING,
- WL_STATUS_CONNECTING,
- WL_STATUS_CONNECTED,
- WL_STATUS_AP_CREATING,
- WL_STATUS_AP_CREATED
+/**
+ * enum brcmf_scan_status - dongle scan status
+ *
+ * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
+ * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
+ */
+enum brcmf_scan_status {
+ BRCMF_SCAN_STATUS_BUSY,
+ BRCMF_SCAN_STATUS_ABORT,
};
/* wi-fi mode */
@@ -145,28 +59,8 @@ enum wl_mode {
WL_MODE_AP
};
-/* dongle profile list */
-enum wl_prof_list {
- WL_PROF_MODE,
- WL_PROF_SSID,
- WL_PROF_SEC,
- WL_PROF_IBSS,
- WL_PROF_BAND,
- WL_PROF_BSSID,
- WL_PROF_ACT,
- WL_PROF_BEACONINT,
- WL_PROF_DTIMPERIOD
-};
-
-/* dongle iscan state */
-enum wl_iscan_state {
- WL_ISCAN_STATE_IDLE,
- WL_ISCAN_STATE_SCANING
-};
-
/* dongle configuration */
struct brcmf_cfg80211_conf {
- u32 mode; /* adhoc , infrastructure or ap */
u32 frag_threshold;
u32 rts_threshold;
u32 retry_short;
@@ -175,17 +69,6 @@ struct brcmf_cfg80211_conf {
struct ieee80211_channel channel;
};
-/* forward declaration */
-struct brcmf_cfg80211_info;
-
-/* cfg80211 main event loop */
-struct brcmf_cfg80211_event_loop {
- s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-};
-
/* basic structure of scan request */
struct brcmf_cfg80211_scan_req {
struct brcmf_ssid_le ssid_le;
@@ -197,14 +80,6 @@ struct brcmf_cfg80211_ie {
u8 buf[WL_TLV_INFO_MAX];
};
-/* event queue for cfg80211 main event */
-struct brcmf_cfg80211_event_q {
- struct list_head evt_q_list;
- u32 etype;
- struct brcmf_event_msg emsg;
- s8 edata[1];
-};
-
/* security information with currently associated ap */
struct brcmf_cfg80211_security {
u32 wpa_versions;
@@ -214,45 +89,73 @@ struct brcmf_cfg80211_security {
u32 wpa_auth;
};
-/* ibss information for currently joined ibss network */
-struct brcmf_cfg80211_ibss {
- u8 beacon_interval; /* in millisecond */
- u8 atim; /* in millisecond */
- s8 join_only;
- u8 band;
- u8 channel;
-};
-
-/* dongle profile */
+/**
+ * struct brcmf_cfg80211_profile - profile information.
+ *
+ * @ssid: ssid of associated/associating ap.
+ * @bssid: bssid of joined/joining ibss.
+ * @sec: security information.
+ */
struct brcmf_cfg80211_profile {
- u32 mode;
struct brcmf_ssid ssid;
u8 bssid[ETH_ALEN];
- u16 beacon_interval;
- u8 dtim_period;
struct brcmf_cfg80211_security sec;
- struct brcmf_cfg80211_ibss ibss;
- s32 band;
};
-/* dongle iscan event loop */
-struct brcmf_cfg80211_iscan_eloop {
- s32 (*handler[WL_SCAN_ERSULTS_LAST])
- (struct brcmf_cfg80211_info *cfg);
+/**
+ * enum brcmf_vif_status - bit indices for vif status.
+ *
+ * @BRCMF_VIF_STATUS_READY: ready for operation.
+ * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
+ * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
+ * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
+ * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
+ */
+enum brcmf_vif_status {
+ BRCMF_VIF_STATUS_READY,
+ BRCMF_VIF_STATUS_CONNECTING,
+ BRCMF_VIF_STATUS_CONNECTED,
+ BRCMF_VIF_STATUS_AP_CREATING,
+ BRCMF_VIF_STATUS_AP_CREATED
+};
+
+/**
+ * struct vif_saved_ie - holds saved IEs for a virtual interface.
+ *
+ * @probe_res_ie: IE info for probe response.
+ * @beacon_ie: IE info for beacon frame.
+ * @probe_res_ie_len: IE info length for probe response.
+ * @beacon_ie_len: IE info length for beacon frame.
+ */
+struct vif_saved_ie {
+ u8 probe_res_ie[IE_MAX_LEN];
+ u8 beacon_ie[IE_MAX_LEN];
+ u32 probe_res_ie_len;
+ u32 beacon_ie_len;
};
-/* dongle iscan controller */
-struct brcmf_cfg80211_iscan_ctrl {
- struct net_device *ndev;
- struct timer_list timer;
- u32 timer_ms;
- u32 timer_on;
- s32 state;
- struct work_struct work;
- struct brcmf_cfg80211_iscan_eloop el;
- void *data;
- s8 dcmd_buf[BRCMF_DCMD_SMLEN];
- s8 scan_buf[WL_ISCAN_BUF_MAX];
+/**
+ * struct brcmf_cfg80211_vif - virtual interface specific information.
+ *
+ * @ifp: lower layer interface pointer
+ * @wdev: wireless device.
+ * @profile: profile information.
+ * @mode: operating mode.
+ * @roam_off: roaming state.
+ * @sme_state: SME state using enum brcmf_vif_status bits.
+ * @pm_block: power-management blocked.
+ * @list: linked list.
+ */
+struct brcmf_cfg80211_vif {
+ struct brcmf_if *ifp;
+ struct wireless_dev wdev;
+ struct brcmf_cfg80211_profile profile;
+ s32 mode;
+ s32 roam_off;
+ unsigned long sme_state;
+ bool pm_block;
+ struct vif_saved_ie saved_ie;
+ struct list_head list;
};
/* association inform */
@@ -288,17 +191,6 @@ struct escan_info {
struct net_device *ndev;
};
-/* Structure to hold WPS, WPA IEs for a AP */
-struct ap_info {
- u8 probe_res_ie[IE_MAX_LEN];
- u8 beacon_ie[IE_MAX_LEN];
- u32 probe_res_ie_len;
- u32 beacon_ie_len;
- u8 *wpa_ie;
- u8 *rsn_ie;
- bool security_mode;
-};
-
/**
* struct brcmf_pno_param_le - PNO scan configuration parameters
*
@@ -383,32 +275,22 @@ struct brcmf_pno_scanresults_le {
/**
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
*
- * @wdev: representing wl cfg80211 device.
+ * @wiphy: wiphy object for cfg80211 interface.
* @conf: dongle configuration.
* @scan_request: cfg80211 scan request object.
- * @el: main event loop.
- * @evt_q_list: used for event queue.
- * @evt_q_lock: for event queue synchronization.
* @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information.
- * @scan_results: results of the last scan.
* @scan_req_int: internal scan request object.
* @bss_info: bss information for cfg80211 layer.
* @ie: information element object for internal purpose.
- * @profile: holding dongle profile.
- * @iscan: iscan controller information.
* @conn_info: association info.
* @pmk_list: wpa2 pmk list.
- * @event_work: event handler work struct.
- * @status: current dongle status.
+ * @scan_status: scan activity on the dongle.
* @pub: common driver information.
* @channel: current channel.
- * @iscan_on: iscan on/off switch.
- * @iscan_kickstart: indicate iscan already started.
* @active_scan: current scan mode.
* @sched_escan: e-scan for scheduled scan support running.
* @ibss_starter: indicates this sta is ibss starter.
- * @link_up: link/connection up flag.
* @pwr_save: indicate whether dongle to support power save mode.
* @dongle_up: indicate whether dongle up or not.
* @roam_on: on/off switch for dongle self-roaming.
@@ -416,41 +298,30 @@ struct brcmf_pno_scanresults_le {
* @dcmd_buf: dcmd buffer.
* @extra_buf: mainly to grab assoc information.
* @debugfsdir: debugfs folder for this device.
- * @escan_on: escan on/off switch.
* @escan_info: escan information.
* @escan_timeout: Timer for catch scan timeout.
* @escan_timeout_work: scan timeout worker.
* @escan_ioctl_buf: dongle command buffer for escan commands.
- * @ap_info: host ap information.
- * @ci: used to link this structure to netdev private data.
+ * @vif_list: linked list of vif instances.
+ * @vif_cnt: number of vif instances.
*/
struct brcmf_cfg80211_info {
- struct wireless_dev *wdev;
+ struct wiphy *wiphy;
struct brcmf_cfg80211_conf *conf;
struct cfg80211_scan_request *scan_request;
- struct brcmf_cfg80211_event_loop el;
- struct list_head evt_q_list;
- spinlock_t evt_q_lock;
struct mutex usr_sync;
struct brcmf_scan_results *bss_list;
- struct brcmf_scan_results *scan_results;
- struct brcmf_cfg80211_scan_req *scan_req_int;
+ struct brcmf_cfg80211_scan_req scan_req_int;
struct wl_cfg80211_bss_info *bss_info;
struct brcmf_cfg80211_ie ie;
- struct brcmf_cfg80211_profile *profile;
- struct brcmf_cfg80211_iscan_ctrl *iscan;
struct brcmf_cfg80211_connect_info conn_info;
struct brcmf_cfg80211_pmk_list *pmk_list;
- struct work_struct event_work;
- unsigned long status;
+ unsigned long scan_status;
struct brcmf_pub *pub;
u32 channel;
- bool iscan_on;
- bool iscan_kickstart;
bool active_scan;
bool sched_escan;
bool ibss_starter;
- bool link_up;
bool pwr_save;
bool dongle_up;
bool roam_on;
@@ -458,17 +329,17 @@ struct brcmf_cfg80211_info {
u8 *dcmd_buf;
u8 *extra_buf;
struct dentry *debugfsdir;
- bool escan_on;
struct escan_info escan_info;
struct timer_list escan_timeout;
struct work_struct escan_timeout_work;
u8 *escan_ioctl_buf;
- struct ap_info *ap_info;
+ struct list_head vif_list;
+ u8 vif_cnt;
};
-static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w)
+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
{
- return w->wdev->wiphy;
+ return cfg->wiphy;
}
static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
@@ -481,9 +352,12 @@ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
}
-static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
+static inline
+struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
{
- return cfg->wdev->netdev;
+ struct brcmf_cfg80211_vif *vif;
+ vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
+ return vif->wdev.netdev;
}
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
@@ -491,8 +365,17 @@ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
return wdev_to_cfg(ndev->ieee80211_ptr);
}
-#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data))
-#define cfg_to_iscan(w) (w->iscan)
+static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
+{
+ struct brcmf_if *ifp = netdev_priv(nd);
+ return &ifp->vif->profile;
+}
+
+static inline struct brcmf_cfg80211_vif *ndev_to_vif(struct net_device *ndev)
+{
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ return ifp->vif;
+}
static inline struct
brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
@@ -500,15 +383,10 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
return &cfg->conn_info;
}
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
- struct device *busdev,
- struct brcmf_pub *drvr);
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+ struct device *busdev);
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
-
-/* event handler from dongle */
-void brcmf_cfg80211_event(struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data);
-s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg);
-s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg);
+s32 brcmf_cfg80211_up(struct net_device *ndev);
+s32 brcmf_cfg80211_down(struct net_device *ndev);
#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index e227c4c68ef9..d3d4151c3eda 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -40,7 +40,8 @@ BRCMSMAC_OFILES := \
phy/phytbl_n.o \
phy/phy_qmath.o \
dma.o \
- brcms_trace_events.o
+ brcms_trace_events.o \
+ debug.o
MODULEPFX := brcmsmac
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index b89f1272b93f..f0888a9ee32e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
sii = container_of(sih, struct si_info, pub);
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
- bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
+ bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
}
/* Unconfigure and/or apply various WARs when going down */
@@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
sii = container_of(sih, struct si_info, pub);
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
- bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
+ bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
}
/* Enable BT-COEX & Ex-PA for 4313 */
@@ -721,7 +721,7 @@ void ai_epa_4313war(struct si_pub *sih)
/* check if the device is removed */
bool ai_deviceremoved(struct si_pub *sih)
{
- u32 w;
+ u32 w = 0;
struct si_info *sii;
sii = container_of(sih, struct si_info, pub);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index be5bcfb9153b..1de94f30564f 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -21,6 +21,8 @@
#include "antsel.h"
#include "main.h"
#include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
/* max number of mpdus in an ampdu */
#define AMPDU_MAX_MPDU 32
@@ -40,8 +42,6 @@
#define AMPDU_DEF_RETRY_LIMIT 5
/* default tx retry limit at reg rate */
#define AMPDU_DEF_RR_RETRY_LIMIT 2
-/* default weight of ampdu in txfifo */
-#define AMPDU_DEF_TXPKT_WEIGHT 2
/* default ffpld reserved bytes */
#define AMPDU_DEF_FFPLD_RSVD 2048
/* # of inis to be freed on detach */
@@ -114,7 +114,6 @@ struct brcms_fifo_info {
* mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
* max_pdu: max pdus allowed in ampdu
* dur: max duration of an ampdu (in msec)
- * txpkt_weight: weight of ampdu in txfifo; reduces rate lag
* rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
* ffpld_rsvd: number of bytes to reserve for preload
* max_txlen: max size of ampdu per mcs, bw and sgi
@@ -136,7 +135,6 @@ struct ampdu_info {
u8 mpdu_density;
s8 max_pdu;
u8 dur;
- u8 txpkt_weight;
u8 rx_factor;
u32 ffpld_rsvd;
u32 max_txlen[MCS_TABLE_SIZE][2][2];
@@ -183,18 +181,19 @@ static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
{
struct brcms_c_info *wlc = ampdu->wlc;
+ struct bcma_device *core = wlc->hw->d11core;
wlc->pub->_ampdu = false;
if (on) {
if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
- wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
- "nmode enabled\n", wlc->pub->unit);
+ brcms_err(core, "wl%d: driver not nmode enabled\n",
+ wlc->pub->unit);
return -ENOTSUPP;
}
if (!brcms_c_ampdu_cap(ampdu)) {
- wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
- "ampdu capable\n", wlc->pub->unit);
+ brcms_err(core, "wl%d: device not ampdu capable\n",
+ wlc->pub->unit);
return -ENOTSUPP;
}
wlc->pub->_ampdu = on;
@@ -247,7 +246,6 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
ampdu->max_pdu = AUTO;
ampdu->dur = AMPDU_MAX_DUR;
- ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
/*
@@ -374,7 +372,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
offsetof(struct macstat, txfunfl[fid]));
new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
if (new_txunfl == 0) {
- BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
+ brcms_dbg_ht(wlc->hw->d11core,
+ "TX status FRAG set but no tx underflows\n");
return -1;
}
fifo->prev_txfunfl = cur_txunfl;
@@ -396,8 +395,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
if (fifo->accum_txfunfl < 10)
return 0;
- BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
- current_ampdu_cnt, fifo->accum_txfunfl);
+ brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d tx_underflows %d\n",
+ current_ampdu_cnt, fifo->accum_txfunfl);
/*
compute the current ratio of tx unfl per ampdu.
@@ -450,9 +449,10 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
/ (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
- BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
- "pre-load size %d\n",
- fifo->dmaxferrate, fifo->ampdu_pld_size);
+ brcms_dbg_ht(wlc->hw->d11core,
+ "DMA estimated transfer rate %d; "
+ "pre-load size %d\n",
+ fifo->dmaxferrate, fifo->ampdu_pld_size);
} else {
/* decrease ampdu size */
@@ -486,7 +486,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
scb_ampdu = &scb->scb_ampdu;
if (!ampdu->ini_enable[tid]) {
- wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
+ brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
__func__, tid);
return;
}
@@ -498,378 +498,324 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
}
-int
-brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
- struct sk_buff **pdu, int prec)
+void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+ struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc;
- struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
- u8 tid, ndelim;
- int err = 0;
- u8 preamble_type = BRCMS_GF_PREAMBLE;
- u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
- u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
- u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
+ session->wlc = wlc;
+ skb_queue_head_init(&session->skb_list);
+ session->max_ampdu_len = 0; /* determined from first MPDU */
+ session->max_ampdu_frames = 0; /* determined from first MPDU */
+ session->ampdu_len = 0;
+ session->dma_len = 0;
+}
- bool rr = true, fbr = false;
- uint i, count = 0, fifo, seg_cnt = 0;
- u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
- u32 ampdu_len, max_ampdu_bytes = 0;
- struct d11txh *txh = NULL;
+/*
+ * Preps the given packet for AMPDU based on the session data. If the
+ * frame cannot be accomodated in the current session, -ENOSPC is
+ * returned.
+ */
+int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+ struct sk_buff *p)
+{
+ struct brcms_c_info *wlc = session->wlc;
+ struct ampdu_info *ampdu = wlc->ampdu;
+ struct scb *scb = &wlc->pri_scb;
+ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+ struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+ struct d11txh *txh = (struct d11txh *)p->data;
+ unsigned ampdu_frames;
+ u8 ndelim, tid;
u8 *plcp;
- struct ieee80211_hdr *h;
- struct scb *scb;
- struct scb_ampdu *scb_ampdu;
- struct scb_ampdu_tid_ini *ini;
- u8 mcs = 0;
- bool use_rts = false, use_cts = false;
- u32 rspec = 0, rspec_fallback = 0;
- u32 rts_rspec = 0, rts_rspec_fallback = 0;
- u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
- struct ieee80211_rts *rts;
- u8 rr_retry_limit;
- struct brcms_fifo_info *f;
+ uint len;
+ u16 mcl;
bool fbr_iscck;
- struct ieee80211_tx_info *tx_info;
- u16 qlen;
- struct wiphy *wiphy;
-
- wlc = ampdu->wlc;
- wiphy = wlc->wiphy;
- p = *pdu;
-
- tid = (u8) (p->priority);
+ bool rr;
- f = ampdu->fifo_tb + prio2fifo[tid];
+ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+ plcp = (u8 *)(txh + 1);
+ fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+ BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+ len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
- scb = &wlc->pri_scb;
- scb_ampdu = &scb->scb_ampdu;
- ini = &scb_ampdu->ini[tid];
+ ampdu_frames = skb_queue_len(&session->skb_list);
+ if (ampdu_frames != 0) {
+ struct sk_buff *first;
- /* Let pressure continue to build ... */
- qlen = pktq_plen(&qi->q, prec);
- if (ini->tx_in_transit > 0 &&
- qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
- /* Collect multiple MPDU's to be sent in the next AMPDU */
- return -EBUSY;
+ if (ampdu_frames + 1 > session->max_ampdu_frames ||
+ session->ampdu_len + len > session->max_ampdu_len)
+ return -ENOSPC;
- /* at this point we intend to transmit an AMPDU */
- rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
- ampdu_len = 0;
- dma_len = 0;
- while (p) {
- struct ieee80211_tx_rate *txrate;
-
- tx_info = IEEE80211_SKB_CB(p);
- txrate = tx_info->status.rates;
+ /*
+ * We aren't really out of space if the new frame is of
+ * a different priority, but we want the same behaviour
+ * so return -ENOSPC anyway.
+ *
+ * XXX: The old AMPDU code did this, but is it really
+ * necessary?
+ */
+ first = skb_peek(&session->skb_list);
+ if (p->priority != first->priority)
+ return -ENOSPC;
+ }
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- err = brcms_c_prep_pdu(wlc, p, &fifo);
- } else {
- wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
- *pdu = NULL;
- err = 0;
- break;
- }
+ /*
+ * Now that we're sure this frame can be accomodated, update the
+ * session information.
+ */
+ session->ampdu_len += len;
+ session->dma_len += p->len;
- if (err) {
- if (err == -EBUSY) {
- wiphy_err(wiphy, "wl%d: sendampdu: "
- "prep_xdu retry; seq 0x%x\n",
- wlc->pub->unit, seq);
- *pdu = p;
- break;
- }
+ tid = (u8)p->priority;
- /* error in the packet; reject it */
- wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
- "rejected; seq 0x%x\n", wlc->pub->unit, seq);
- *pdu = NULL;
- break;
- }
+ /* Handle retry limits */
+ if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
+ txrate[0].count++;
+ rr = true;
+ } else {
+ txrate[1].count++;
+ rr = false;
+ }
- /* pkt is good to be aggregated */
- txh = (struct d11txh *) p->data;
- plcp = (u8 *) (txh + 1);
- h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
- seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
- index = TX_SEQ_TO_INDEX(seq);
+ if (ampdu_frames == 0) {
+ u8 plcp0, plcp3, is40, sgi, mcs;
+ uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+ struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
- /* check mcl fields and test whether it can be agg'd */
- mcl = le16_to_cpu(txh->MacTxControlLow);
- mcl &= ~TXC_AMPDU_MASK;
- fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
- txh->PreloadSize = 0; /* always default to 0 */
-
- /* Handle retry limits */
- if (txrate[0].count <= rr_retry_limit) {
- txrate[0].count++;
- rr = true;
- fbr = false;
+ if (rr) {
+ plcp0 = plcp[0];
+ plcp3 = plcp[3];
} else {
- fbr = true;
- rr = false;
- txrate[1].count++;
- }
-
- /* extract the length info */
- len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
- : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-
- /* retrieve null delimiter count */
- ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
- seg_cnt += 1;
+ plcp0 = txh->FragPLCPFallback[0];
+ plcp3 = txh->FragPLCPFallback[3];
- BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
- wlc->pub->unit, count, len);
-
- /*
- * aggregateable mpdu. For ucode/hw agg,
- * test whether need to break or change the epoch
- */
- if (count == 0) {
- mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
- /* refill the bits since might be a retx mpdu */
- mcl |= TXC_STARTMSDU;
- rts = (struct ieee80211_rts *)&txh->rts_frame;
-
- if (ieee80211_is_rts(rts->frame_control)) {
- mcl |= TXC_SENDRTS;
- use_rts = true;
- }
- if (ieee80211_is_cts(rts->frame_control)) {
- mcl |= TXC_SENDCTS;
- use_cts = true;
- }
- } else {
- mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
- mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
}
- len = roundup(len, 4);
- ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
+ /* Limit AMPDU size based on MCS */
+ is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+ sgi = plcp3_issgi(plcp3) ? 1 : 0;
+ mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+ session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
+ ampdu->max_txlen[mcs][is40][sgi]);
- dma_len += (u16) p->len;
+ session->max_ampdu_frames = scb_ampdu->max_pdu;
+ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+ session->max_ampdu_frames =
+ min_t(u16, f->mcs2ampdu_table[mcs],
+ session->max_ampdu_frames);
+ }
+ }
- BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
- " seg_cnt %d null delim %d\n",
- wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
+ /*
+ * Treat all frames as "middle" frames of AMPDU here. First and
+ * last frames must be fixed up after all MPDUs have been prepped.
+ */
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ mcl &= ~TXC_AMPDU_MASK;
+ mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
+ mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
+ txh->MacTxControlLow = cpu_to_le16(mcl);
+ txh->PreloadSize = 0; /* always default to 0 */
- txh->MacTxControlLow = cpu_to_le16(mcl);
+ skb_queue_tail(&session->skb_list, p);
- /* this packet is added */
- pkt[count++] = p;
+ return 0;
+}
- /* patch the first MPDU */
- if (count == 1) {
- u8 plcp0, plcp3, is40, sgi;
+void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
+{
+ struct brcms_c_info *wlc = session->wlc;
+ struct ampdu_info *ampdu = wlc->ampdu;
+ struct sk_buff *first, *last;
+ struct d11txh *txh;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *txrate;
+ u8 ndelim;
+ u8 *plcp;
+ uint len;
+ uint fifo;
+ struct brcms_fifo_info *f;
+ u16 mcl;
+ bool fbr;
+ bool fbr_iscck;
+ struct ieee80211_rts *rts;
+ bool use_rts = false, use_cts = false;
+ u16 dma_len = session->dma_len;
+ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+ u32 rspec = 0, rspec_fallback = 0;
+ u32 rts_rspec = 0, rts_rspec_fallback = 0;
+ u8 plcp0, plcp3, is40, sgi, mcs;
+ u16 mch;
+ u8 preamble_type = BRCMS_GF_PREAMBLE;
+ u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
+ u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
+ u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
- if (rr) {
- plcp0 = plcp[0];
- plcp3 = plcp[3];
- } else {
- plcp0 = txh->FragPLCPFallback[0];
- plcp3 = txh->FragPLCPFallback[3];
+ if (skb_queue_empty(&session->skb_list))
+ return;
- }
- is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
- sgi = plcp3_issgi(plcp3) ? 1 : 0;
- mcs = plcp0 & ~MIMO_PLCP_40MHZ;
- max_ampdu_bytes =
- min(scb_ampdu->max_rx_ampdu_bytes,
- ampdu->max_txlen[mcs][is40][sgi]);
-
- if (is40)
- mimo_ctlchbw =
- CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
- wlc->band->pi))
- ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
- /* rebuild the rspec and rspec_fallback */
- rspec = RSPEC_MIMORATE;
- rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
- if (plcp[0] & MIMO_PLCP_40MHZ)
- rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-
- if (fbr_iscck) /* CCK */
- rspec_fallback = cck_rspec(cck_phy2mac_rate
- (txh->FragPLCPFallback[0]));
- else { /* MIMO */
- rspec_fallback = RSPEC_MIMORATE;
- rspec_fallback |=
- txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
- if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
- rspec_fallback |=
- (PHY_TXC1_BW_40MHZ <<
- RSPEC_BW_SHIFT);
- }
+ first = skb_peek(&session->skb_list);
+ last = skb_peek_tail(&session->skb_list);
+
+ /* Need to fix up last MPDU first to adjust AMPDU length */
+ txh = (struct d11txh *)last->data;
+ fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+ f = &ampdu->fifo_tb[fifo];
+
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ mcl &= ~TXC_AMPDU_MASK;
+ mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
+ txh->MacTxControlLow = cpu_to_le16(mcl);
+
+ /* remove the null delimiter after last mpdu */
+ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
+ session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
+
+ /* remove the pad len from last mpdu */
+ fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
+ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+ BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+ session->ampdu_len -= roundup(len, 4) - len;
+
+ /* Now fix up the first MPDU */
+ tx_info = IEEE80211_SKB_CB(first);
+ txrate = tx_info->status.rates;
+ txh = (struct d11txh *)first->data;
+ plcp = (u8 *)(txh + 1);
+ rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ /* If only one MPDU leave it marked as last */
+ if (first != last) {
+ mcl &= ~TXC_AMPDU_MASK;
+ mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
+ }
+ mcl |= TXC_STARTMSDU;
+ if (ieee80211_is_rts(rts->frame_control)) {
+ mcl |= TXC_SENDRTS;
+ use_rts = true;
+ }
+ if (ieee80211_is_cts(rts->frame_control)) {
+ mcl |= TXC_SENDCTS;
+ use_cts = true;
+ }
+ txh->MacTxControlLow = cpu_to_le16(mcl);
- if (use_rts || use_cts) {
- rts_rspec =
- brcms_c_rspec_to_rts_rspec(wlc,
- rspec, false, mimo_ctlchbw);
- rts_rspec_fallback =
- brcms_c_rspec_to_rts_rspec(wlc,
- rspec_fallback, false, mimo_ctlchbw);
- }
- }
+ fbr = txrate[1].count > 0;
+ if (!fbr) {
+ plcp0 = plcp[0];
+ plcp3 = plcp[3];
+ } else {
+ plcp0 = txh->FragPLCPFallback[0];
+ plcp3 = txh->FragPLCPFallback[3];
+ }
+ is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+ sgi = plcp3_issgi(plcp3) ? 1 : 0;
+ mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+
+ if (is40) {
+ if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
+ mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
+ else
+ mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+ }
- /* if (first mpdu for host agg) */
- /* test whether to add more */
- if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) &&
- (count == f->mcs2ampdu_table[mcs])) {
- BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
- " ampdu at %d for mcs %d\n",
- wlc->pub->unit, count, mcs);
- break;
- }
+ /* rebuild the rspec and rspec_fallback */
+ rspec = RSPEC_MIMORATE;
+ rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
+ if (plcp[0] & MIMO_PLCP_40MHZ)
+ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
- if (count == scb_ampdu->max_pdu)
- break;
+ fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+ if (fbr_iscck) {
+ rspec_fallback =
+ cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
+ } else {
+ rspec_fallback = RSPEC_MIMORATE;
+ rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
+ if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
+ rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
+ }
- /*
- * check to see if the next pkt is
- * a candidate for aggregation
- */
- p = pktq_ppeek(&qi->q, prec);
- if (p) {
- tx_info = IEEE80211_SKB_CB(p);
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
- ((u8) (p->priority) == tid)) {
- plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
- plen = max(scb_ampdu->min_len, plen);
+ if (use_rts || use_cts) {
+ rts_rspec =
+ brcms_c_rspec_to_rts_rspec(wlc, rspec,
+ false, mimo_ctlchbw);
+ rts_rspec_fallback =
+ brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
+ false, mimo_ctlchbw);
+ }
- if ((plen + ampdu_len) > max_ampdu_bytes) {
- p = NULL;
- continue;
- }
+ BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
+ /* mark plcp to indicate ampdu */
+ BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
- /*
- * check if there are enough
- * descriptors available
- */
- if (*wlc->core->txavail[fifo] <= seg_cnt + 1) {
- wiphy_err(wiphy, "%s: No fifo space "
- "!!\n", __func__);
- p = NULL;
- continue;
- }
- /* next packet fit for aggregation so dequeue */
- p = brcmu_pktq_pdeq(&qi->q, prec);
- } else {
- p = NULL;
- }
- }
- } /* end while(p) */
+ /* reset the mixed mode header durations */
+ if (txh->MModeLen) {
+ u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
+ session->ampdu_len);
+ txh->MModeLen = cpu_to_le16(mmodelen);
+ preamble_type = BRCMS_MM_PREAMBLE;
+ }
+ if (txh->MModeFbrLen) {
+ u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
+ session->ampdu_len);
+ txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
+ fbr_preamble_type = BRCMS_MM_PREAMBLE;
+ }
- ini->tx_in_transit += count;
+ /* set the preload length */
+ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+ dma_len = min(dma_len, f->ampdu_pld_size);
+ txh->PreloadSize = cpu_to_le16(dma_len);
+ } else {
+ txh->PreloadSize = 0;
+ }
- if (count) {
- /* patch up the last txh */
- txh = (struct d11txh *) pkt[count - 1]->data;
- mcl = le16_to_cpu(txh->MacTxControlLow);
- mcl &= ~TXC_AMPDU_MASK;
- mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
- txh->MacTxControlLow = cpu_to_le16(mcl);
-
- /* remove the null delimiter after last mpdu */
- ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
- txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
- ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
-
- /* remove the pad len from last mpdu */
- fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
- len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
- : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
- ampdu_len -= roundup(len, 4) - len;
-
- /* patch up the first txh & plcp */
- txh = (struct d11txh *) pkt[0]->data;
- plcp = (u8 *) (txh + 1);
+ mch = le16_to_cpu(txh->MacTxControlHigh);
- BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
- /* mark plcp to indicate ampdu */
- BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+ /* update RTS dur fields */
+ if (use_rts || use_cts) {
+ u16 durid;
+ if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
+ TXC_PREAMBLE_RTS_MAIN_SHORT)
+ rts_preamble_type = BRCMS_SHORT_PREAMBLE;
- /* reset the mixed mode header durations */
- if (txh->MModeLen) {
- u16 mmodelen =
- brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
- txh->MModeLen = cpu_to_le16(mmodelen);
- preamble_type = BRCMS_MM_PREAMBLE;
- }
- if (txh->MModeFbrLen) {
- u16 mmfbrlen =
- brcms_c_calc_lsig_len(wlc, rspec_fallback,
- ampdu_len);
- txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
- fbr_preamble_type = BRCMS_MM_PREAMBLE;
- }
+ if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
+ TXC_PREAMBLE_RTS_FB_SHORT)
+ rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
- /* set the preload length */
- if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
- dma_len = min(dma_len, f->ampdu_pld_size);
- txh->PreloadSize = cpu_to_le16(dma_len);
- } else
- txh->PreloadSize = 0;
-
- mch = le16_to_cpu(txh->MacTxControlHigh);
-
- /* update RTS dur fields */
- if (use_rts || use_cts) {
- u16 durid;
- rts = (struct ieee80211_rts *)&txh->rts_frame;
- if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
- TXC_PREAMBLE_RTS_MAIN_SHORT)
- rts_preamble_type = BRCMS_SHORT_PREAMBLE;
-
- if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
- TXC_PREAMBLE_RTS_FB_SHORT)
- rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
-
- durid =
- brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
rspec, rts_preamble_type,
- preamble_type, ampdu_len,
- true);
- rts->duration = cpu_to_le16(durid);
- durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
- rts_rspec_fallback,
- rspec_fallback,
- rts_fbr_preamble_type,
- fbr_preamble_type,
- ampdu_len, true);
- txh->RTSDurFallback = cpu_to_le16(durid);
- /* set TxFesTimeNormal */
- txh->TxFesTimeNormal = rts->duration;
- /* set fallback rate version of TxFesTimeNormal */
- txh->TxFesTimeFallback = txh->RTSDurFallback;
- }
-
- /* set flag and plcp for fallback rate */
- if (fbr) {
- mch |= TXC_AMPDU_FBR;
- txh->MacTxControlHigh = cpu_to_le16(mch);
- BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
- BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
- }
-
- BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
- wlc->pub->unit, count, ampdu_len);
-
- /* inform rate_sel if it this is a rate probe pkt */
- frameid = le16_to_cpu(txh->TxFrameID);
- if (frameid & TXFID_RATE_PROBE_MASK)
- wiphy_err(wiphy, "%s: XXX what to do with "
- "TXFID_RATE_PROBE_MASK!?\n", __func__);
-
- for (i = 0; i < count; i++)
- brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
- ampdu->txpkt_weight);
+ preamble_type,
+ session->ampdu_len, true);
+ rts->duration = cpu_to_le16(durid);
+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+ rts_rspec_fallback,
+ rspec_fallback,
+ rts_fbr_preamble_type,
+ fbr_preamble_type,
+ session->ampdu_len, true);
+ txh->RTSDurFallback = cpu_to_le16(durid);
+ /* set TxFesTimeNormal */
+ txh->TxFesTimeNormal = rts->duration;
+ /* set fallback rate version of TxFesTimeNormal */
+ txh->TxFesTimeFallback = txh->RTSDurFallback;
+ }
+ /* set flag and plcp for fallback rate */
+ if (fbr) {
+ mch |= TXC_AMPDU_FBR;
+ txh->MacTxControlHigh = cpu_to_le16(mch);
+ BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+ BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
}
- /* endif (count) */
- return err;
+
+ brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
+ wlc->pub->unit, skb_queue_len(&session->skb_list),
+ session->ampdu_len);
}
static void
@@ -909,7 +855,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
u8 antselid = 0;
u8 retry_limit, rr_retry_limit;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
- struct wiphy *wiphy = wlc->wiphy;
#ifdef DEBUG
u8 hole[AMPDU_MAX_MPDU];
@@ -955,13 +900,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
if (supr_status) {
update_rate = false;
if (supr_status == TX_STATUS_SUPR_BADCH) {
- wiphy_err(wiphy,
+ brcms_err(wlc->hw->d11core,
"%s: Pkt tx suppressed, illegal channel possibly %d\n",
__func__, CHSPEC_CHANNEL(
wlc->default_bss->chanspec));
} else {
if (supr_status != TX_STATUS_SUPR_FRAG)
- wiphy_err(wiphy, "%s: supr_status 0x%x\n",
+ brcms_err(wlc->hw->d11core,
+ "%s: supr_status 0x%x\n",
__func__, supr_status);
}
/* no need to retry for badch; will fail again */
@@ -977,20 +923,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
* if there were underflows, but pre-loading
* is not active, notify rate adaptation.
*/
- if (brcms_c_ffpld_check_txfunfl(wlc,
- prio2fifo[tid]) > 0)
+ if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0)
tx_error = true;
}
} else if (txs->phyerr) {
update_rate = false;
- wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
+ brcms_err(wlc->hw->d11core,
+ "%s: ampdu tx phy error (0x%x)\n",
__func__, txs->phyerr);
-
- if (brcm_msg_level & LOG_ERROR_VAL) {
- brcmu_prpkt("txpkt (AMPDU)", p);
- brcms_c_print_txdesc((struct d11txh *) p->data);
- }
- brcms_c_print_txstatus(txs);
}
}
@@ -1003,6 +943,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+ trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
if (tot_mpdu == 0) {
mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
@@ -1012,10 +954,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
ack_recd = false;
if (ba_recd) {
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
- BCMMSG(wiphy,
- "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
- tid, seq, start_seq, bindex,
- isset(bitmap, bindex), index);
+ brcms_dbg_ht(wlc->hw->d11core,
+ "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
+ tid, seq, start_seq, bindex,
+ isset(bitmap, bindex), index);
/* if acked then clear bit and free packet */
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
&& isset(bitmap, bindex)) {
@@ -1046,14 +988,16 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
/* either retransmit or send bar if ack not recd */
if (!ack_recd) {
if (retry && (ini->txretry[index] < (int)retry_limit)) {
+ int ret;
ini->txretry[index]++;
ini->tx_in_transit--;
+ ret = brcms_c_txfifo(wlc, queue, p);
/*
- * Use high prededence for retransmit to
- * give some punch
+ * We shouldn't be out of space in the DMA
+ * ring here since we're reinserting a frame
+ * that was just pulled out.
*/
- brcms_c_txq_enq(wlc, scb, p,
- BRCMS_PRIO_TO_HI_PREC(tid));
+ WARN_ONCE(ret, "queue %d out of txds\n", queue);
} else {
/* Retry timeout */
ini->tx_in_transit--;
@@ -1064,9 +1008,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
IEEE80211_TX_STAT_AMPDU_NO_BACK;
skb_pull(p, D11_PHY_HDR_LEN);
skb_pull(p, D11_TXH_LEN);
- BCMMSG(wiphy,
- "BA Timeout, seq %d, in_transit %d\n",
- seq, ini->tx_in_transit);
+ brcms_dbg_ht(wlc->hw->d11core,
+ "BA Timeout, seq %d, in_transit %d\n",
+ seq, ini->tx_in_transit);
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
p);
}
@@ -1080,12 +1024,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
}
- brcms_c_send_q(wlc);
/* update rate state */
antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
-
- brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
void
@@ -1133,6 +1074,8 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
while (p) {
tx_info = IEEE80211_SKB_CB(p);
txh = (struct d11txh *) p->data;
+ trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+ sizeof(*txh));
mcl = le16_to_cpu(txh->MacTxControlLow);
brcmu_pkt_buf_free_skb(p);
/* break out if last packet of ampdu */
@@ -1142,7 +1085,6 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
p = dma_getnexttxp(wlc->hw->di[queue],
DMA_RANGE_TRANSMITTED);
}
- brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
}
@@ -1182,23 +1124,6 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
}
/*
- * callback function that helps flushing ampdu packets from a priority queue
- */
-static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
- struct cb_del_ampdu_pars *ampdu_pars =
- (struct cb_del_ampdu_pars *)arg_a;
- bool rc;
-
- rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
- rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL ||
- tx_info->rate_driver_data[0] == ampdu_pars->sta);
- rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
- return rc;
-}
-
-/*
* callback function that helps invalidating ampdu packets in a DMA queue
*/
static void dma_cb_fn_ampdu(void *txi, void *arg_a)
@@ -1218,15 +1143,5 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a)
void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
struct ieee80211_sta *sta, u16 tid)
{
- struct brcms_txq_info *qi = wlc->pkt_queue;
- struct pktq *pq = &qi->q;
- int prec;
- struct cb_del_ampdu_pars ampdu_pars;
-
- ampdu_pars.sta = sta;
- ampdu_pars.tid = tid;
- for (prec = 0; prec < pq->num_prec; prec++)
- brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
- (void *)&ampdu_pars);
brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
index 421f4ba7c63c..73d01e586109 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
@@ -17,11 +17,34 @@
#ifndef _BRCM_AMPDU_H_
#define _BRCM_AMPDU_H_
+/*
+ * Data structure representing an in-progress session for accumulating
+ * frames for AMPDU.
+ *
+ * wlc: pointer to common driver data
+ * skb_list: queue of skb's for AMPDU
+ * max_ampdu_len: maximum length for this AMPDU
+ * max_ampdu_frames: maximum number of frames for this AMPDU
+ * ampdu_len: total number of bytes accumulated for this AMPDU
+ * dma_len: DMA length of this AMPDU
+ */
+struct brcms_ampdu_session {
+ struct brcms_c_info *wlc;
+ struct sk_buff_head skb_list;
+ unsigned max_ampdu_len;
+ u16 max_ampdu_frames;
+ u16 ampdu_len;
+ u16 dma_len;
+};
+
+extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+ struct brcms_c_info *wlc);
+extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+ struct sk_buff *p);
+extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
+
extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
-extern int brcms_c_sendampdu(struct ampdu_info *ampdu,
- struct brcms_txq_info *qi,
- struct sk_buff **aggp, int prec);
extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
struct sk_buff *p, struct tx_status *txs);
extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
index 55e12c327911..54c616919590 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
@@ -21,6 +21,7 @@
#include "main.h"
#include "phy_shim.h"
#include "antsel.h"
+#include "debug.h"
#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */
#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */
@@ -137,7 +138,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
asi->antsel_avail = false;
} else {
asi->antsel_avail = false;
- wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
+ brcms_err(wlc->hw->d11core,
+ "antsel_attach: 2o3 "
"board cfg invalid\n");
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
index 27dd73eef56d..871781e6a713 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
@@ -14,22 +14,29 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM brcmsmac
-
#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
#define __TRACE_BRCMSMAC_H
+#include <linux/types.h>
+#include <linux/device.h>
#include <linux/tracepoint.h>
#include "mac80211_if.h"
-#ifndef CONFIG_BRCMDBG
+#ifndef CONFIG_BRCM_TRACING
#undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \
static inline void trace_ ## name(proto) {}
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
#endif
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
/*
* We define a tracepoint, its arguments, its printk format and its
* 'fast binary record' layout.
@@ -78,9 +85,165 @@ TRACE_EVENT(brcms_dpc,
)
);
+TRACE_EVENT(brcms_macintstatus,
+ TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
+ u32 mask),
+ TP_ARGS(dev, in_isr, macintstatus, mask),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+ __field(int, in_isr)
+ __field(u32, macintstatus)
+ __field(u32, mask)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+ __entry->in_isr = in_isr;
+ __entry->macintstatus = macintstatus;
+ __entry->mask = mask;
+ ),
+ TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
+ __entry->in_isr, __entry->macintstatus, __entry->mask)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_tx
+
+TRACE_EVENT(brcms_txdesc,
+ TP_PROTO(const struct device *dev,
+ void *txh, size_t txh_len),
+ TP_ARGS(dev, txh, txh_len),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+ __dynamic_array(u8, txh, txh_len)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+ memcpy(__get_dynamic_array(txh), txh, txh_len);
+ ),
+ TP_printk("[%s] txdesc", __get_str(dev))
+);
+
+TRACE_EVENT(brcms_txstatus,
+ TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
+ u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
+ u16 ackphyrxsh),
+ TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
+ ackphyrxsh),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+ __field(u16, framelen)
+ __field(u16, frameid)
+ __field(u16, status)
+ __field(u16, lasttxtime)
+ __field(u16, sequence)
+ __field(u16, phyerr)
+ __field(u16, ackphyrxsh)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+ __entry->framelen = framelen;
+ __entry->frameid = frameid;
+ __entry->status = status;
+ __entry->lasttxtime = lasttxtime;
+ __entry->sequence = sequence;
+ __entry->phyerr = phyerr;
+ __entry->ackphyrxsh = ackphyrxsh;
+ ),
+ TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
+ "Seq %#04x PHYTxStatus %#04x RxAck %#04x",
+ __get_str(dev), __entry->frameid, __entry->status,
+ __entry->lasttxtime, __entry->sequence, __entry->phyerr,
+ __entry->ackphyrxsh)
+);
+
+TRACE_EVENT(brcms_ampdu_session,
+ TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
+ u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
+ u16 dma_len),
+ TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
+ dma_len),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+ __field(unsigned, max_ampdu_len)
+ __field(u16, max_ampdu_frames)
+ __field(u16, ampdu_len)
+ __field(u16, ampdu_frames)
+ __field(u16, dma_len)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+ __entry->max_ampdu_len = max_ampdu_len;
+ __entry->max_ampdu_frames = max_ampdu_frames;
+ __entry->ampdu_len = ampdu_len;
+ __entry->ampdu_frames = ampdu_frames;
+ __entry->dma_len = dma_len;
+ ),
+ TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
+ __get_str(dev), __entry->max_ampdu_len,
+ __entry->max_ampdu_frames, __entry->ampdu_len,
+ __entry->ampdu_frames, __entry->dma_len)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_msg
+
+#define MAX_MSG_LEN 100
+
+DECLARE_EVENT_CLASS(brcms_msg_event,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf),
+ TP_STRUCT__entry(
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+ TP_fast_assign(
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >= MAX_MSG_LEN);
+ ),
+ TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_info,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_warn,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_err,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_crit,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+
+TRACE_EVENT(brcms_dbg,
+ TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+ TP_ARGS(level, func, vaf),
+ TP_STRUCT__entry(
+ __field(u32, level)
+ __string(func, func)
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+ TP_fast_assign(
+ __entry->level = level;
+ __assign_str(func, func);
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >= MAX_MSG_LEN);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
#endif /* __TRACE_BRCMSMAC_H */
-#ifdef CONFIG_BRCMDBG
+#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
@@ -89,4 +252,4 @@ TRACE_EVENT(brcms_dpc,
#include <trace/define_trace.h>
-#endif /* CONFIG_BRCMDBG */
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 64a48f06d68b..a90b72202ec5 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -26,6 +26,7 @@
#include "stf.h"
#include "channel.h"
#include "mac80211_if.h"
+#include "debug.h"
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
@@ -336,8 +337,6 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
const char *ccode = sprom->alpha2;
int ccode_len = sizeof(sprom->alpha2);
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
if (wlc_cm == NULL)
return NULL;
@@ -615,8 +614,8 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
/* check the chanspec */
if (brcms_c_chspec_malformed(chspec)) {
- wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
- wlc->pub->unit, chspec);
+ brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
+ wlc->pub->unit, chspec);
return false;
}
@@ -738,7 +737,8 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
} else {
mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: no valid channel for \"%s\"\n",
wlc->pub->unit, __func__, request->alpha2);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
new file mode 100644
index 000000000000..9761deb46204
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ * Copyright (c) 2012 Canonical Ltd.
+ *
+ * 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/debugfs.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+#include <linux/module.h>
+#include <net/mac80211.h>
+
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "types.h"
+#include "main.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+
+static struct dentry *root_folder;
+
+void brcms_debugfs_init(void)
+{
+ root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (IS_ERR(root_folder))
+ root_folder = NULL;
+}
+
+void brcms_debugfs_exit(void)
+{
+ if (!root_folder)
+ return;
+
+ debugfs_remove_recursive(root_folder);
+ root_folder = NULL;
+}
+
+int brcms_debugfs_attach(struct brcms_pub *drvr)
+{
+ if (!root_folder)
+ return -ENODEV;
+
+ drvr->dbgfs_dir = debugfs_create_dir(
+ dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
+ return PTR_RET(drvr->dbgfs_dir);
+}
+
+void brcms_debugfs_detach(struct brcms_pub *drvr)
+{
+ if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
+ debugfs_remove_recursive(drvr->dbgfs_dir);
+}
+
+struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr)
+{
+ return drvr->dbgfs_dir;
+}
+
+static
+ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ char buf[128];
+ int res;
+ struct brcms_pub *drvr = f->private_data;
+
+ /* only allow read from start */
+ if (*ppos > 0)
+ return 0;
+
+ res = scnprintf(buf, sizeof(buf),
+ "board vendor: %x\n"
+ "board type: %x\n"
+ "board revision: %x\n"
+ "board flags: %x\n"
+ "board flags2: %x\n"
+ "firmware revision: %x\n",
+ drvr->wlc->hw->d11core->bus->boardinfo.vendor,
+ drvr->wlc->hw->d11core->bus->boardinfo.type,
+ drvr->wlc->hw->boardrev,
+ drvr->wlc->hw->boardflags,
+ drvr->wlc->hw->boardflags2,
+ drvr->wlc->ucode_rev
+ );
+
+ return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations brcms_debugfs_hardware_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = brcms_debugfs_hardware_read
+};
+
+void brcms_debugfs_create_files(struct brcms_pub *drvr)
+{
+ struct dentry *dentry = drvr->dbgfs_dir;
+
+ if (!IS_ERR_OR_NULL(dentry))
+ debugfs_create_file("hardware", S_IRUGO, dentry,
+ drvr, &brcms_debugfs_hardware_ops);
+}
+
+#define __brcms_fn(fn) \
+void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \
+{ \
+ struct va_format vaf = { \
+ .fmt = fmt, \
+ }; \
+ va_list args; \
+ \
+ va_start(args, fmt); \
+ vaf.va = &args; \
+ dev_ ##fn(dev, "%pV", &vaf); \
+ trace_brcms_ ##fn(&vaf); \
+ va_end(args); \
+}
+
+__brcms_fn(info)
+__brcms_fn(warn)
+__brcms_fn(err)
+__brcms_fn(crit)
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+ const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+#ifdef CONFIG_BRCMDBG
+ if ((brcm_msg_level & level) && net_ratelimit())
+ dev_err(dev, "%s %pV", func, &vaf);
+#endif
+ trace_brcms_dbg(level, func, &vaf);
+ va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/brcm80211/brcmsmac/debug.h
new file mode 100644
index 000000000000..796836b0f469
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012 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 _BRCMS_DEBUG_H_
+#define _BRCMS_DEBUG_H_
+
+#include <linux/device.h>
+#include <linux/bcma/bcma.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include "main.h"
+#include "mac80211_if.h"
+
+__printf(2, 3)
+void __brcms_info(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_warn(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_err(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_crit(struct device *dev, const char *fmt, ...);
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+__printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+ const char *fmt, ...);
+#else
+static inline __printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+ const char *fmt, ...)
+{
+}
+#endif
+
+/*
+ * Debug macros cannot be used when wlc is uninitialized. Generally
+ * this means any code that could run before brcms_c_attach() has
+ * returned successfully probably shouldn't use the following macros.
+ */
+
+#define brcms_dbg(core, l, f, a...) __brcms_dbg(&(core)->dev, l, __func__, f, ##a)
+#define brcms_info(core, f, a...) __brcms_info(&(core)->dev, f, ##a)
+#define brcms_warn(core, f, a...) __brcms_warn(&(core)->dev, f, ##a)
+#define brcms_err(core, f, a...) __brcms_err(&(core)->dev, f, ##a)
+#define brcms_crit(core, f, a...) __brcms_crit(&(core)->dev, f, ##a)
+
+#define brcms_dbg_info(core, f, a...) brcms_dbg(core, BRCM_DL_INFO, f, ##a)
+#define brcms_dbg_mac80211(core, f, a...) brcms_dbg(core, BRCM_DL_MAC80211, f, ##a)
+#define brcms_dbg_rx(core, f, a...) brcms_dbg(core, BRCM_DL_RX, f, ##a)
+#define brcms_dbg_tx(core, f, a...) brcms_dbg(core, BRCM_DL_TX, f, ##a)
+#define brcms_dbg_int(core, f, a...) brcms_dbg(core, BRCM_DL_INT, f, ##a)
+#define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a)
+#define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a)
+
+struct brcms_pub;
+void brcms_debugfs_init(void);
+void brcms_debugfs_exit(void);
+int brcms_debugfs_attach(struct brcms_pub *drvr);
+void brcms_debugfs_detach(struct brcms_pub *drvr);
+struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr);
+void brcms_debugfs_create_files(struct brcms_pub *drvr);
+
+#endif /* _BRCMS_DEBUG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 5e53305bd9a9..1860c572b3c4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -14,17 +14,22 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
#include <brcmu_utils.h>
#include <aiutils.h>
#include "types.h"
+#include "main.h"
#include "dma.h"
#include "soc.h"
+#include "scb.h"
+#include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
/*
* dma register field offset calculation
@@ -176,28 +181,6 @@
#define BCMEXTRAHDROOM 172
-/* debug/trace */
-#ifdef DEBUG
-#define DMA_ERROR(fmt, ...) \
-do { \
- if (*di->msg_level & 1) \
- pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
-} while (0)
-#define DMA_TRACE(fmt, ...) \
-do { \
- if (*di->msg_level & 2) \
- pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
-} while (0)
-#else
-#define DMA_ERROR(fmt, ...) \
- no_printk(fmt, ##__VA_ARGS__)
-#define DMA_TRACE(fmt, ...) \
- no_printk(fmt, ##__VA_ARGS__)
-#endif /* DEBUG */
-
-#define DMA_NONE(fmt, ...) \
- no_printk(fmt, ##__VA_ARGS__)
-
#define MAXNAMEL 8 /* 8 char names */
/* macros to convert between byte offsets and indexes */
@@ -224,12 +207,14 @@ struct dma64desc {
/* dma engine software state */
struct dma_info {
struct dma_pub dma; /* exported structure */
- uint *msg_level; /* message level pointer */
char name[MAXNAMEL]; /* callers name for diag msgs */
struct bcma_device *core;
struct device *dmadev;
+ /* session information for AMPDU */
+ struct brcms_ampdu_session ampdu_session;
+
bool dma64; /* this dma engine is operating in 64-bit mode */
bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
@@ -298,12 +283,6 @@ struct dma_info {
bool aligndesc_4k;
};
-/*
- * default dma message level (if input msg_level
- * pointer is null in dma_attach())
- */
-static uint dma_msg_level;
-
/* Check for odd number of 1's */
static u32 parity32(__le32 data)
{
@@ -353,7 +332,7 @@ static uint prevtxd(struct dma_info *di, uint i)
static uint nextrxd(struct dma_info *di, uint i)
{
- return txd(di, i + 1);
+ return rxd(di, i + 1);
}
static uint ntxdactive(struct dma_info *di, uint h, uint t)
@@ -370,10 +349,8 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
{
uint dmactrlflags;
- if (di == NULL) {
- DMA_ERROR("NULL dma handle\n");
+ if (di == NULL)
return 0;
- }
dmactrlflags = di->dma.dmactrlflags;
dmactrlflags &= ~mask;
@@ -423,13 +400,15 @@ static bool _dma_isaddrext(struct dma_info *di)
/* not all tx or rx channel are available */
if (di->d64txregbase != 0) {
if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
- DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
- di->name);
+ brcms_dbg_dma(di->core,
+ "%s: DMA64 tx doesn't have AE set\n",
+ di->name);
return true;
} else if (di->d64rxregbase != 0) {
if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
- DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
- di->name);
+ brcms_dbg_dma(di->core,
+ "%s: DMA64 rx doesn't have AE set\n",
+ di->name);
return true;
}
@@ -530,8 +509,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
&alloced, &di->txdpaorig);
if (va == NULL) {
- DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
- di->name);
+ brcms_dbg_dma(di->core,
+ "%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
+ di->name);
return false;
}
align = (1 << align_bits);
@@ -544,8 +524,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
&alloced, &di->rxdpaorig);
if (va == NULL) {
- DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
- di->name);
+ brcms_dbg_dma(di->core,
+ "%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
+ di->name);
return false;
}
align = (1 << align_bits);
@@ -564,12 +545,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction)
return dma64_alloc(di, direction);
}
-struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- struct bcma_device *core,
+struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
- uint nrxpost, uint rxoffset, uint *msg_level)
+ uint nrxpost, uint rxoffset)
{
+ struct si_pub *sih = wlc->hw->sih;
+ struct bcma_device *core = wlc->hw->d11core;
struct dma_info *di;
u8 rev = core->id.rev;
uint size;
@@ -580,9 +562,6 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
if (di == NULL)
return NULL;
- di->msg_level = msg_level ? msg_level : &dma_msg_level;
-
-
di->dma64 =
((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
@@ -598,11 +577,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
*/
_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
- DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d "
- "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
- "txregbase %u rxregbase %u\n", name, "DMA64",
- di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
- rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
+ brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d "
+ "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+ "txregbase %u rxregbase %u\n", name, "DMA64",
+ di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+ rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
/* make a private copy of our callers name */
strncpy(di->name, name, MAXNAMEL);
@@ -664,8 +643,8 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
di->dmadesc_align = 4; /* 16 byte alignment */
}
- DMA_NONE("DMA descriptor align_needed %d, align %d\n",
- di->aligndesc_4k, di->dmadesc_align);
+ brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n",
+ di->aligndesc_4k, di->dmadesc_align);
/* allocate tx packet pointer vector */
if (ntxd) {
@@ -703,21 +682,27 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
if ((di->ddoffsetlow != 0) && !di->addrext) {
if (di->txdpa > SI_PCI_DMA_SZ) {
- DMA_ERROR("%s: txdpa 0x%x: addrext not supported\n",
- di->name, (u32)di->txdpa);
+ brcms_dbg_dma(di->core,
+ "%s: txdpa 0x%x: addrext not supported\n",
+ di->name, (u32)di->txdpa);
goto fail;
}
if (di->rxdpa > SI_PCI_DMA_SZ) {
- DMA_ERROR("%s: rxdpa 0x%x: addrext not supported\n",
- di->name, (u32)di->rxdpa);
+ brcms_dbg_dma(di->core,
+ "%s: rxdpa 0x%x: addrext not supported\n",
+ di->name, (u32)di->rxdpa);
goto fail;
}
}
- DMA_TRACE("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
- di->ddoffsetlow, di->ddoffsethigh,
- di->dataoffsetlow, di->dataoffsethigh,
- di->addrext);
+ /* Initialize AMPDU session */
+ brcms_c_ampdu_reset_session(&di->ampdu_session, wlc);
+
+ brcms_dbg_dma(di->core,
+ "ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
+ di->ddoffsetlow, di->ddoffsethigh,
+ di->dataoffsetlow, di->dataoffsethigh,
+ di->addrext);
return (struct dma_pub *) di;
@@ -763,7 +748,7 @@ void dma_detach(struct dma_pub *pub)
{
struct dma_info *di = (struct dma_info *)pub;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
/* free dma descriptor rings */
if (di->txd64)
@@ -839,7 +824,7 @@ static void _dma_rxenable(struct dma_info *di)
uint dmactrlflags = di->dma.dmactrlflags;
u32 control;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
control = D64_RC_RE | (bcma_read32(di->core,
DMA64RXREGOFFS(di, control)) &
@@ -859,7 +844,7 @@ void dma_rxinit(struct dma_pub *pub)
{
struct dma_info *di = (struct dma_info *)pub;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
if (di->nrxd == 0)
return;
@@ -954,7 +939,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
return 0;
len = le16_to_cpu(*(__le16 *) (p->data));
- DMA_TRACE("%s: dma_rx len %d\n", di->name, len);
+ brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len);
dma_spin_for_len(len, p);
/* set actual length */
@@ -981,14 +966,15 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
DMA64RXREGOFFS(di, status0)) &
D64_RS0_CD_MASK) - di->rcvptrbase) &
D64_RS0_CD_MASK, struct dma64desc);
- DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
- di->rxin, di->rxout, cur);
+ brcms_dbg_dma(di->core,
+ "rxin %d rxout %d, hw_curr %d\n",
+ di->rxin, di->rxout, cur);
}
#endif /* DEBUG */
if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
- DMA_ERROR("%s: bad frame length (%d)\n",
- di->name, len);
+ brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n",
+ di->name, len);
skb_queue_walk_safe(&dma_frames, p, next) {
skb_unlink(p, &dma_frames);
brcmu_pkt_buf_free_skb(p);
@@ -1005,7 +991,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
static bool dma64_rxidle(struct dma_info *di)
{
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
if (di->nrxd == 0)
return true;
@@ -1016,6 +1002,17 @@ static bool dma64_rxidle(struct dma_info *di)
D64_RS0_CD_MASK));
}
+static bool dma64_txidle(struct dma_info *di)
+{
+ if (di->ntxd == 0)
+ return true;
+
+ return ((bcma_read32(di->core,
+ DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) ==
+ (bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) &
+ D64_XS0_CD_MASK));
+}
+
/*
* post receive buffers
* return false is refill failed completely and ring is empty this will stall
@@ -1047,7 +1044,7 @@ bool dma_rxfill(struct dma_pub *pub)
n = di->nrxpost - nrxdactive(di, rxin, rxout);
- DMA_TRACE("%s: post %d\n", di->name, n);
+ brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n);
if (di->rxbufsize > BCMEXTRAHDROOM)
extra_offset = di->rxextrahdrroom;
@@ -1060,9 +1057,11 @@ bool dma_rxfill(struct dma_pub *pub)
p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
if (p == NULL) {
- DMA_ERROR("%s: out of rxbufs\n", di->name);
+ brcms_dbg_dma(di->core, "%s: out of rxbufs\n",
+ di->name);
if (i == 0 && dma64_rxidle(di)) {
- DMA_ERROR("%s: ring is empty !\n", di->name);
+ brcms_dbg_dma(di->core, "%s: ring is empty !\n",
+ di->name);
ring_empty = true;
}
di->dma.rxnobuf++;
@@ -1107,7 +1106,7 @@ void dma_rxreclaim(struct dma_pub *pub)
struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
while ((p = _dma_getnextrxp(di, true)))
brcmu_pkt_buf_free_skb(p);
@@ -1138,7 +1137,7 @@ void dma_txinit(struct dma_pub *pub)
struct dma_info *di = (struct dma_info *)pub;
u32 control = D64_XC_XE;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
if (di->ntxd == 0)
return;
@@ -1170,7 +1169,7 @@ void dma_txsuspend(struct dma_pub *pub)
{
struct dma_info *di = (struct dma_info *)pub;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
if (di->ntxd == 0)
return;
@@ -1182,7 +1181,7 @@ void dma_txresume(struct dma_pub *pub)
{
struct dma_info *di = (struct dma_info *)pub;
- DMA_TRACE("%s:\n", di->name);
+ brcms_dbg_dma(di->core, "%s:\n", di->name);
if (di->ntxd == 0)
return;
@@ -1205,11 +1204,11 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p;
- DMA_TRACE("%s: %s\n",
- di->name,
- range == DMA_RANGE_ALL ? "all" :
- range == DMA_RANGE_TRANSMITTED ? "transmitted" :
- "transferred");
+ brcms_dbg_dma(di->core, "%s: %s\n",
+ di->name,
+ range == DMA_RANGE_ALL ? "all" :
+ range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+ "transferred");
if (di->txin == di->txout)
return;
@@ -1264,39 +1263,25 @@ bool dma_rxreset(struct dma_pub *pub)
return status == D64_RS0_RS_DISABLED;
}
-/*
- * !! tx entry routine
- * WARNING: call must check the return value for error.
- * the error(toss frames) could be fatal and cause many subsequent hard
- * to debug problems
- */
-int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
+static void dma_txenq(struct dma_info *di, struct sk_buff *p)
{
- struct dma_info *di = (struct dma_info *)pub;
unsigned char *data;
uint len;
u16 txout;
u32 flags = 0;
dma_addr_t pa;
- DMA_TRACE("%s:\n", di->name);
-
txout = di->txout;
+ if (WARN_ON(nexttxd(di, txout) == di->txin))
+ return;
+
/*
* obtain and initialize transmit descriptor entry.
*/
data = p->data;
len = p->len;
- /* no use to transmit a zero length packet */
- if (len == 0)
- return 0;
-
- /* return nonzero if out of tx descriptors */
- if (nexttxd(di, txout) == di->txin)
- goto outoftxd;
-
/* get physical address of buffer start */
pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
@@ -1318,23 +1303,147 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
/* bump the tx descriptor index */
di->txout = txout;
+}
- /* kick the chip */
- if (commit)
- bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
- di->xmtptrbase + I2B(txout, struct dma64desc));
+static void ampdu_finalize(struct dma_info *di)
+{
+ struct brcms_ampdu_session *session = &di->ampdu_session;
+ struct sk_buff *p;
+
+ trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev,
+ session->max_ampdu_len,
+ session->max_ampdu_frames,
+ session->ampdu_len,
+ skb_queue_len(&session->skb_list),
+ session->dma_len);
+
+ if (WARN_ON(skb_queue_empty(&session->skb_list)))
+ return;
+
+ brcms_c_ampdu_finalize(session);
+
+ while (!skb_queue_empty(&session->skb_list)) {
+ p = skb_dequeue(&session->skb_list);
+ dma_txenq(di, p);
+ }
+
+ bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+ di->xmtptrbase + I2B(di->txout, struct dma64desc));
+ brcms_c_ampdu_reset_session(session, session->wlc);
+}
+
+static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)
+{
+ struct brcms_ampdu_session *session = &di->ampdu_session;
+ int ret;
+
+ ret = brcms_c_ampdu_add_frame(session, p);
+ if (ret == -ENOSPC) {
+ /*
+ * AMPDU cannot accomodate this frame. Close out the in-
+ * progress AMPDU session and start a new one.
+ */
+ ampdu_finalize(di);
+ ret = brcms_c_ampdu_add_frame(session, p);
+ }
+
+ WARN_ON(ret);
+}
+
+/* Update count of available tx descriptors based on current DMA state */
+static void dma_update_txavail(struct dma_info *di)
+{
+ /*
+ * Available space is number of descriptors less the number of
+ * active descriptors and the number of queued AMPDU frames.
+ */
+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) -
+ skb_queue_len(&di->ampdu_session.skb_list) - 1;
+}
+
+/*
+ * !! tx entry routine
+ * WARNING: call must check the return value for error.
+ * the error(toss frames) could be fatal and cause many subsequent hard
+ * to debug problems
+ */
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+ struct sk_buff *p)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct brcms_ampdu_session *session = &di->ampdu_session;
+ struct ieee80211_tx_info *tx_info;
+ bool is_ampdu;
+
+ /* no use to transmit a zero length packet */
+ if (p->len == 0)
+ return 0;
+
+ /* return nonzero if out of tx descriptors */
+ if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin)
+ goto outoftxd;
+
+ tx_info = IEEE80211_SKB_CB(p);
+ is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU;
+ if (is_ampdu)
+ prep_ampdu_frame(di, p);
+ else
+ dma_txenq(di, p);
/* tx flow control */
- di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+ dma_update_txavail(di);
+
+ /* kick the chip */
+ if (is_ampdu) {
+ /*
+ * Start sending data if we've got a full AMPDU, there's
+ * no more space in the DMA ring, or the ring isn't
+ * currently transmitting.
+ */
+ if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames ||
+ di->dma.txavail == 0 || dma64_txidle(di))
+ ampdu_finalize(di);
+ } else {
+ bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+ di->xmtptrbase + I2B(di->txout, struct dma64desc));
+ }
return 0;
outoftxd:
- DMA_ERROR("%s: out of txds !!!\n", di->name);
+ brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name);
brcmu_pkt_buf_free_skb(p);
di->dma.txavail = 0;
di->dma.txnobuf++;
- return -1;
+ return -ENOSPC;
+}
+
+void dma_txflush(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct brcms_ampdu_session *session = &di->ampdu_session;
+
+ if (!skb_queue_empty(&session->skb_list))
+ ampdu_finalize(di);
+}
+
+int dma_txpending(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ return ntxdactive(di, di->txin, di->txout);
+}
+
+/*
+ * If we have an active AMPDU session and are not transmitting,
+ * this function will force tx to start.
+ */
+void dma_kick_tx(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct brcms_ampdu_session *session = &di->ampdu_session;
+
+ if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di))
+ ampdu_finalize(di);
}
/*
@@ -1354,11 +1463,11 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
u16 active_desc;
struct sk_buff *txp;
- DMA_TRACE("%s: %s\n",
- di->name,
- range == DMA_RANGE_ALL ? "all" :
- range == DMA_RANGE_TRANSMITTED ? "transmitted" :
- "transferred");
+ brcms_dbg_dma(di->core, "%s: %s\n",
+ di->name,
+ range == DMA_RANGE_ALL ? "all" :
+ range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+ "transferred");
if (di->ntxd == 0)
return NULL;
@@ -1412,13 +1521,13 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
di->txin = i;
/* tx flow control */
- di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+ dma_update_txavail(di);
return txp;
bogus:
- DMA_NONE("bogus curr: start %d end %d txout %d\n",
- start, end, di->txout);
+ brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n",
+ start, end, di->txout);
return NULL;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
index cc269ee5c499..ff5b80b09046 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
@@ -74,12 +74,11 @@ struct dma_pub {
uint txnobuf; /* tx out of dma descriptors */
};
-extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- struct bcma_device *d11core,
+extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
uint txregbase, uint rxregbase,
uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
- uint nrxpost, uint rxoffset, uint *msg_level);
+ uint nrxpost, uint rxoffset);
void dma_rxinit(struct dma_pub *pub);
int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
@@ -87,7 +86,11 @@ bool dma_rxfill(struct dma_pub *pub);
bool dma_rxreset(struct dma_pub *pub);
bool dma_txreset(struct dma_pub *pub);
void dma_txinit(struct dma_pub *pub);
-int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit);
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+ struct sk_buff *p0);
+void dma_txflush(struct dma_pub *pub);
+int dma_txpending(struct dma_pub *pub);
+void dma_kick_tx(struct dma_pub *pub);
void dma_txsuspend(struct dma_pub *pub);
bool dma_txsuspended(struct dma_pub *pub);
void dma_txresume(struct dma_pub *pub);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index a744ea5a9559..1fbd8ecbe2ea 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -33,6 +33,7 @@
#include "ucode_loader.h"
#include "mac80211_if.h"
#include "main.h"
+#include "debug.h"
#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
@@ -92,16 +93,21 @@ MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw");
/* recognized BCMA Core IDs */
static struct bcma_device_id brcms_coreid_table[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
BCMA_CORETABLE_END
};
MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
-#ifdef DEBUG
-static int msglevel = 0xdeadbeef;
-module_param(msglevel, int, 0);
-#endif /* DEBUG */
+#if defined(CONFIG_BRCMDBG)
+/*
+ * Module parameter for setting the debug message level. Available
+ * flags are specified by the BRCM_DL_* macros in
+ * drivers/net/wireless/brcm80211/include/defs.h.
+ */
+module_param_named(debug, brcm_msg_level, uint, S_IRUGO | S_IWUSR);
+#endif
static struct ieee80211_channel brcms_2ghz_chantable[] = {
CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
@@ -276,12 +282,12 @@ static void brcms_ops_tx(struct ieee80211_hw *hw,
spin_lock_bh(&wl->lock);
if (!wl->pub->up) {
- wiphy_err(wl->wiphy, "ops->tx called while down\n");
+ brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n");
kfree_skb(skb);
goto done;
}
- brcms_c_sendpkt_mac80211(wl->wlc, skb, hw);
- tx_info->rate_driver_data[0] = control->sta;
+ if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw))
+ tx_info->rate_driver_data[0] = control->sta;
done:
spin_unlock_bh(&wl->lock);
}
@@ -313,8 +319,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
spin_unlock_bh(&wl->lock);
if (err != 0)
- wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
- err);
+ brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
+ __func__, err);
return err;
}
@@ -332,7 +338,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
status = brcms_c_chipmatch(wl->wlc->hw->d11core);
spin_unlock_bh(&wl->lock);
if (!status) {
- wiphy_err(wl->wiphy,
+ brcms_err(wl->wlc->hw->d11core,
"wl: brcms_ops_stop: chipmatch failed\n");
return;
}
@@ -350,8 +356,9 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
/* Just STA for now */
if (vif->type != NL80211_IFTYPE_STATION) {
- wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
- " STA for now\n", __func__, vif->type);
+ brcms_err(wl->wlc->hw->d11core,
+ "%s: Attempt to add type %d, only STA for now\n",
+ __func__, vif->type);
return -EOPNOTSUPP;
}
@@ -370,9 +377,9 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
{
struct ieee80211_conf *conf = &hw->conf;
struct brcms_info *wl = hw->priv;
+ struct bcma_device *core = wl->wlc->hw->d11core;
int err = 0;
int new_int;
- struct wiphy *wiphy = hw->wiphy;
spin_lock_bh(&wl->lock);
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
@@ -380,25 +387,26 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
conf->listen_interval);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
- wiphy_dbg(wiphy, "%s: change monitor mode: %s\n",
- __func__, conf->flags & IEEE80211_CONF_MONITOR ?
- "true" : "false");
+ brcms_dbg_info(core, "%s: change monitor mode: %s\n",
+ __func__, conf->flags & IEEE80211_CONF_MONITOR ?
+ "true" : "false");
if (changed & IEEE80211_CONF_CHANGE_PS)
- wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
+ brcms_err(core, "%s: change power-save mode: %s (implement)\n",
__func__, conf->flags & IEEE80211_CONF_PS ?
"true" : "false");
if (changed & IEEE80211_CONF_CHANGE_POWER) {
err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
if (err < 0) {
- wiphy_err(wiphy, "%s: Error setting power_level\n",
+ brcms_err(core, "%s: Error setting power_level\n",
__func__);
goto config_out;
}
new_int = brcms_c_get_tx_power(wl->wlc);
if (new_int != conf->power_level)
- wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
- "\n", __func__, conf->power_level,
+ brcms_err(core,
+ "%s: Power level req != actual, %d %d\n",
+ __func__, conf->power_level,
new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -425,13 +433,13 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info, u32 changed)
{
struct brcms_info *wl = hw->priv;
- struct wiphy *wiphy = hw->wiphy;
+ struct bcma_device *core = wl->wlc->hw->d11core;
if (changed & BSS_CHANGED_ASSOC) {
/* association status changed (associated/disassociated)
* also implies a change in the AID.
*/
- wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
+ brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME,
__func__, info->assoc ? "" : "dis");
spin_lock_bh(&wl->lock);
brcms_c_associate_upd(wl->wlc, info->assoc);
@@ -491,7 +499,7 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
error = brcms_c_set_rateset(wl->wlc, &rs);
spin_unlock_bh(&wl->lock);
if (error)
- wiphy_err(wiphy, "changing basic rates failed: %d\n",
+ brcms_err(core, "changing basic rates failed: %d\n",
error);
}
if (changed & BSS_CHANGED_BEACON_INT) {
@@ -508,30 +516,30 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_BEACON)
/* Beacon data changed, retrieve new beacon (beaconing modes) */
- wiphy_err(wiphy, "%s: beacon changed\n", __func__);
+ brcms_err(core, "%s: beacon changed\n", __func__);
if (changed & BSS_CHANGED_BEACON_ENABLED) {
/* Beaconing should be enabled/disabled (beaconing modes) */
- wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
+ brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
info->enable_beacon ? "true" : "false");
}
if (changed & BSS_CHANGED_CQM) {
/* Connection quality monitor config changed */
- wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
+ brcms_err(core, "%s: cqm change: threshold %d, hys %d "
" (implement)\n", __func__, info->cqm_rssi_thold,
info->cqm_rssi_hyst);
}
if (changed & BSS_CHANGED_IBSS) {
/* IBSS join status changed */
- wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
- info->ibss_joined ? "true" : "false");
+ brcms_err(core, "%s: IBSS joined: %s (implement)\n",
+ __func__, info->ibss_joined ? "true" : "false");
}
if (changed & BSS_CHANGED_ARP_FILTER) {
/* Hardware ARP filter address list or state changed */
- wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
+ brcms_err(core, "%s: arp filtering: enabled %s, count %d"
" (implement)\n", __func__, info->arp_filter_enabled ?
"true" : "false", info->arp_addr_cnt);
}
@@ -541,8 +549,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
* QoS for this association was enabled/disabled.
* Note that it is only ever disabled for station mode.
*/
- wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
- info->qos ? "true" : "false");
+ brcms_err(core, "%s: qos enabled: %s (implement)\n",
+ __func__, info->qos ? "true" : "false");
}
return;
}
@@ -553,25 +561,25 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
unsigned int *total_flags, u64 multicast)
{
struct brcms_info *wl = hw->priv;
- struct wiphy *wiphy = hw->wiphy;
+ struct bcma_device *core = wl->wlc->hw->d11core;
changed_flags &= MAC_FILTERS;
*total_flags &= MAC_FILTERS;
if (changed_flags & FIF_PROMISC_IN_BSS)
- wiphy_dbg(wiphy, "FIF_PROMISC_IN_BSS\n");
+ brcms_dbg_info(core, "FIF_PROMISC_IN_BSS\n");
if (changed_flags & FIF_ALLMULTI)
- wiphy_dbg(wiphy, "FIF_ALLMULTI\n");
+ brcms_dbg_info(core, "FIF_ALLMULTI\n");
if (changed_flags & FIF_FCSFAIL)
- wiphy_dbg(wiphy, "FIF_FCSFAIL\n");
+ brcms_dbg_info(core, "FIF_FCSFAIL\n");
if (changed_flags & FIF_CONTROL)
- wiphy_dbg(wiphy, "FIF_CONTROL\n");
+ brcms_dbg_info(core, "FIF_CONTROL\n");
if (changed_flags & FIF_OTHER_BSS)
- wiphy_dbg(wiphy, "FIF_OTHER_BSS\n");
+ brcms_dbg_info(core, "FIF_OTHER_BSS\n");
if (changed_flags & FIF_PSPOLL)
- wiphy_dbg(wiphy, "FIF_PSPOLL\n");
+ brcms_dbg_info(core, "FIF_PSPOLL\n");
if (changed_flags & FIF_BCN_PRBRESP_PROMISC)
- wiphy_dbg(wiphy, "FIF_BCN_PRBRESP_PROMISC\n");
+ brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n");
spin_lock_bh(&wl->lock);
brcms_c_mac_promisc(wl->wlc, *total_flags);
@@ -653,8 +661,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
status = brcms_c_aggregatable(wl->wlc, tid);
spin_unlock_bh(&wl->lock);
if (!status) {
- wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
- tid);
+ brcms_err(wl->wlc->hw->d11core,
+ "START: tid %d is not agg\'able\n", tid);
return -EINVAL;
}
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -681,8 +689,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
/* Power save wakeup */
break;
default:
- wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
- __func__);
+ brcms_err(wl->wlc->hw->d11core,
+ "%s: Invalid command, ignoring\n", __func__);
}
return 0;
@@ -839,8 +847,10 @@ static void brcms_free(struct brcms_info *wl)
/* kill dpc */
tasklet_kill(&wl->tasklet);
- if (wl->pub)
+ if (wl->pub) {
+ brcms_debugfs_detach(wl->pub);
brcms_c_module_unregister(wl->pub, "linux", wl);
+ }
/* free common resources */
if (wl->wlc) {
@@ -889,27 +899,22 @@ static void brcms_remove(struct bcma_device *pdev)
static irqreturn_t brcms_isr(int irq, void *dev_id)
{
struct brcms_info *wl;
- bool ours, wantdpc;
+ irqreturn_t ret = IRQ_NONE;
wl = (struct brcms_info *) dev_id;
spin_lock(&wl->isr_lock);
/* call common first level interrupt handler */
- ours = brcms_c_isr(wl->wlc, &wantdpc);
- if (ours) {
- /* if more to do... */
- if (wantdpc) {
-
- /* ...and call the second level interrupt handler */
- /* schedule dpc */
- tasklet_schedule(&wl->tasklet);
- }
+ if (brcms_c_isr(wl->wlc)) {
+ /* schedule second level handler */
+ tasklet_schedule(&wl->tasklet);
+ ret = IRQ_HANDLED;
}
spin_unlock(&wl->isr_lock);
- return IRQ_RETVAL(ours);
+ return ret;
}
/*
@@ -1075,6 +1080,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
regulatory_hint(wl->wiphy, wl->pub->srom_ccode))
wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);
+ brcms_debugfs_attach(wl->pub);
+ brcms_debugfs_create_files(wl->pub);
n_adapters_found++;
return wl;
@@ -1093,7 +1100,7 @@ fail:
*
* Perimeter lock is initialized in the course of this function.
*/
-static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
+static int brcms_bcma_probe(struct bcma_device *pdev)
{
struct brcms_info *wl;
struct ieee80211_hw *hw;
@@ -1144,14 +1151,13 @@ static int brcms_suspend(struct bcma_device *pdev)
wl->pub->hw_up = false;
spin_unlock_bh(&wl->lock);
- pr_debug("brcms_suspend ok\n");
+ brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n");
return 0;
}
static int brcms_resume(struct bcma_device *pdev)
{
- pr_debug("brcms_resume ok\n");
return 0;
}
@@ -1160,7 +1166,7 @@ static struct bcma_driver brcms_bcma_driver = {
.probe = brcms_bcma_probe,
.suspend = brcms_suspend,
.resume = brcms_resume,
- .remove = __devexit_p(brcms_remove),
+ .remove = brcms_remove,
.id_table = brcms_coreid_table,
};
@@ -1184,10 +1190,7 @@ static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
static int __init brcms_module_init(void)
{
-#ifdef DEBUG
- if (msglevel != 0xdeadbeef)
- brcm_msg_level = msglevel;
-#endif
+ brcms_debugfs_init();
if (!schedule_work(&brcms_driver_work))
return -EBUSY;
@@ -1205,6 +1208,7 @@ static void __exit brcms_module_exit(void)
{
cancel_work_sync(&brcms_driver_work);
bcma_driver_unregister(&brcms_bcma_driver);
+ brcms_debugfs_exit();
}
module_init(brcms_module_init);
@@ -1216,7 +1220,7 @@ module_exit(brcms_module_exit);
void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
bool state, int prio)
{
- wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
+ brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__);
}
/*
@@ -1224,7 +1228,8 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
*/
void brcms_init(struct brcms_info *wl)
{
- BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
+ brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n",
+ wl->pub->unit);
brcms_reset(wl);
brcms_c_init(wl->wlc, wl->mute_tx);
}
@@ -1234,7 +1239,7 @@ void brcms_init(struct brcms_info *wl)
*/
uint brcms_reset(struct brcms_info *wl)
{
- BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
+ brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit);
brcms_c_reset(wl->wlc);
/* dpc will not be rescheduled */
@@ -1248,7 +1253,7 @@ uint brcms_reset(struct brcms_info *wl)
void brcms_fatal_error(struct brcms_info *wl)
{
- wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+ brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n",
wl->wlc->pub->unit);
brcms_reset(wl);
ieee80211_restart_hw(wl->pub->ieee_hw);
@@ -1396,8 +1401,9 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
#ifdef DEBUG
if (t->set)
- wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
- __func__, t->name, periodic);
+ brcms_dbg_info(t->wl->wlc->hw->d11core,
+ "%s: Already set. Name: %s, per %d\n",
+ __func__, t->name, periodic);
#endif
t->ms = ms;
t->periodic = (bool) periodic;
@@ -1486,8 +1492,8 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
}
}
}
- wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
- idx);
+ brcms_err(wl->wlc->hw->d11core,
+ "ERROR: ucode buf tag:%d can not be found!\n", idx);
*pbuf = NULL;
fail:
return -ENODATA;
@@ -1510,7 +1516,7 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
pdata = wl->fw.fw_bin[i]->data +
le32_to_cpu(hdr->offset);
if (le32_to_cpu(hdr->len) != 4) {
- wiphy_err(wl->wiphy,
+ brcms_err(wl->wlc->hw->d11core,
"ERROR: fw hdr len\n");
return -ENOMSG;
}
@@ -1519,7 +1525,8 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
}
}
}
- wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
+ brcms_err(wl->wlc->hw->d11core,
+ "ERROR: ucode tag:%d can not be found!\n", idx);
return -ENOMSG;
}
@@ -1560,8 +1567,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
sizeof(struct firmware_hdr));
rc = -EBADF;
} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
- wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
- "%zu\n", __func__, fw->size);
+ wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n",
+ __func__, fw->size);
rc = -EBADF;
} else {
/* check if ucode section overruns firmware image */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 75086b37c817..17594de4199e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -34,12 +34,9 @@
#include "ucode_loader.h"
#include "main.h"
#include "soc.h"
-
-/*
- * Indication for txflowcontrol that all priority bits in
- * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
- */
-#define ALLPRIO -1
+#include "dma.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
/* watchdog timer, in unit of ms */
#define TIMER_INTERVAL_WATCHDOG 1000
@@ -126,21 +123,6 @@
#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */
-/* precedences numbers for wlc queues. These are twice as may levels as
- * 802.1D priorities.
- * Odd numbers are used for HI priority traffic at same precedence levels
- * These constants are used ONLY by wlc_prio2prec_map. Do not use them
- * elsewhere.
- */
-#define _BRCMS_PREC_NONE 0 /* None = - */
-#define _BRCMS_PREC_BK 2 /* BK - Background */
-#define _BRCMS_PREC_BE 4 /* BE - Best-effort */
-#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */
-#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */
-#define _BRCMS_PREC_VI 10 /* Vi - Video */
-#define _BRCMS_PREC_VO 12 /* Vo - Voice */
-#define _BRCMS_PREC_NC 14 /* NC - Network Control */
-
/* synthpu_dly times in us */
#define SYNTHPU_DLY_APHY_US 3700
#define SYNTHPU_DLY_BPHY_US 1050
@@ -237,17 +219,17 @@
#define MAX_DMA_SEGS 4
-/* Max # of entries in Tx FIFO based on 4kb page size */
-#define NTXD 256
+/* # of entries in Tx FIFO */
+#define NTXD 64
/* Max # of entries in Rx FIFO based on 4kb page size */
#define NRXD 256
+/* Amount of headroom to leave in Tx FIFO */
+#define TX_HEADROOM 4
+
/* try to keep this # rbufs posted to the chip */
#define NRXBUFPOST 32
-/* data msg txq hiwat mark */
-#define BRCMS_DATAHIWAT 50
-
/* max # frames to process in brcms_c_recv() */
#define RXBND 8
/* max # tx status to process in wlc_txstatus() */
@@ -283,24 +265,8 @@ struct edcf_acparam {
u16 TXOP;
} __packed;
-const u8 prio2fifo[NUMPRIO] = {
- TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */
- TX_AC_BK_FIFO, /* 1 BK AC_BK Background */
- TX_AC_BK_FIFO, /* 2 -- AC_BK Background */
- TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */
- TX_AC_VI_FIFO, /* 4 CL AC_VI Video */
- TX_AC_VI_FIFO, /* 5 VI AC_VI Video */
- TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */
- TX_AC_VO_FIFO /* 7 NC AC_VO Voice */
-};
-
/* debug/trace */
-uint brcm_msg_level =
-#if defined(DEBUG)
- LOG_ERROR_VAL;
-#else
- 0;
-#endif /* DEBUG */
+uint brcm_msg_level;
/* TX FIFO number to WME/802.1E Access Category */
static const u8 wme_fifo2ac[] = {
@@ -320,18 +286,6 @@ static const u8 wme_ac2fifo[] = {
TX_AC_BK_FIFO
};
-/* 802.1D Priority to precedence queue mapping */
-const u8 wlc_prio2prec_map[] = {
- _BRCMS_PREC_BE, /* 0 BE - Best-effort */
- _BRCMS_PREC_BK, /* 1 BK - Background */
- _BRCMS_PREC_NONE, /* 2 None = - */
- _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */
- _BRCMS_PREC_CL, /* 4 CL - Controlled Load */
- _BRCMS_PREC_VI, /* 5 Vi - Video */
- _BRCMS_PREC_VO, /* 6 Vo - Voice */
- _BRCMS_PREC_NC, /* 7 NC - Network Control */
-};
-
static const u16 xmtfifo_sz[][NFIFO] = {
/* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */
{20, 192, 192, 21, 17, 5},
@@ -371,6 +325,36 @@ static const char fifo_names[6][0];
static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
#endif
+/* Mapping of ieee80211 AC numbers to tx fifos */
+static const u8 ac_to_fifo_mapping[IEEE80211_NUM_ACS] = {
+ [IEEE80211_AC_VO] = TX_AC_VO_FIFO,
+ [IEEE80211_AC_VI] = TX_AC_VI_FIFO,
+ [IEEE80211_AC_BE] = TX_AC_BE_FIFO,
+ [IEEE80211_AC_BK] = TX_AC_BK_FIFO,
+};
+
+/* Mapping of tx fifos to ieee80211 AC numbers */
+static const u8 fifo_to_ac_mapping[IEEE80211_NUM_ACS] = {
+ [TX_AC_BK_FIFO] = IEEE80211_AC_BK,
+ [TX_AC_BE_FIFO] = IEEE80211_AC_BE,
+ [TX_AC_VI_FIFO] = IEEE80211_AC_VI,
+ [TX_AC_VO_FIFO] = IEEE80211_AC_VO,
+};
+
+static u8 brcms_ac_to_fifo(u8 ac)
+{
+ if (ac >= ARRAY_SIZE(ac_to_fifo_mapping))
+ return TX_AC_BE_FIFO;
+ return ac_to_fifo_mapping[ac];
+}
+
+static u8 brcms_fifo_to_ac(u8 fifo)
+{
+ if (fifo >= ARRAY_SIZE(fifo_to_ac_mapping))
+ return IEEE80211_AC_BE;
+ return fifo_to_ac_mapping[fifo];
+}
+
/* Find basic rate for a given rate */
static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
{
@@ -415,10 +399,15 @@ static bool brcms_deviceremoved(struct brcms_c_info *wlc)
}
/* sum the individual fifo tx pending packet counts */
-static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
+static int brcms_txpktpendtot(struct brcms_c_info *wlc)
{
- return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
- wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
+ int i;
+ int pending = 0;
+
+ for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+ if (wlc->hw->di[i])
+ pending += dma_txpending(wlc->hw->di[i]);
+ return pending;
}
static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
@@ -626,14 +615,11 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
uint rate = rspec2rate(ratespec);
if (rate == 0) {
- wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
+ brcms_err(wlc->hw->d11core, "wl%d: WAR: using rate of 1 mbps\n",
wlc->pub->unit);
rate = BRCM_RATE_1M;
}
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
- wlc->pub->unit, ratespec, preamble_type, mac_len);
-
if (is_mcs_rate(ratespec)) {
uint mcs = ratespec & RSPEC_RATE_MASK;
int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
@@ -696,7 +682,7 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
u16 size;
u32 value;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
size = le16_to_cpu(inits[i].size);
@@ -725,19 +711,19 @@ static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
{
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
/* init microcode host flags */
brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
/* do band-specific ucode IHR, SHM, and SCR inits */
- if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
if (BRCMS_ISNPHY(wlc_hw->band))
brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
- " %d\n", __func__, wlc_hw->unit,
+ brcms_err(wlc_hw->d11core,
+ "%s: wl%d: unsupported phy in corerev %d\n",
+ __func__, wlc_hw->unit,
wlc_hw->corerev);
} else {
if (D11REV_IS(wlc_hw->corerev, 24)) {
@@ -745,12 +731,14 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
brcms_c_write_inits(wlc_hw,
ucode->d11lcn0bsinitvals24);
else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
- " core rev %d\n", __func__,
- wlc_hw->unit, wlc_hw->corerev);
+ brcms_err(wlc_hw->d11core,
+ "%s: wl%d: unsupported phy in core rev %d\n",
+ __func__, wlc_hw->unit,
+ wlc_hw->corerev);
} else {
- wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
+ brcms_err(wlc_hw->d11core,
+ "%s: wl%d: unsupported corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
}
}
}
@@ -765,7 +753,7 @@ static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v)
static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d: clk %d\n", wlc_hw->unit, clk);
wlc_hw->phyclk = clk;
@@ -790,8 +778,8 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
/* low-level band switch utility routine */
static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- bandunit);
+ brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+ bandunit);
wlc_hw->band = wlc_hw->bandstate[bandunit];
@@ -819,7 +807,7 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
u32 macintmask;
u32 macctrl;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_mac80211(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
macctrl = bcma_read32(wlc_hw->d11core,
D11REGOFFS(maccontrol));
WARN_ON((macctrl & MCTL_EN_MAC) != 0);
@@ -841,9 +829,10 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
static bool
brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
{
- struct sk_buff *p;
- uint queue;
- struct d11txh *txh;
+ struct sk_buff *p = NULL;
+ uint queue = NFIFO;
+ struct dma_pub *dma = NULL;
+ struct d11txh *txh = NULL;
struct scb *scb = NULL;
bool free_pdu;
int tx_rts, tx_frame_count, tx_rts_count;
@@ -854,6 +843,11 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *txrate;
int i;
+ bool fatal = true;
+
+ trace_brcms_txstatus(&wlc->hw->d11core->dev, txs->framelen,
+ txs->frameid, txs->status, txs->lasttxtime,
+ txs->sequence, txs->phyerr, txs->ackphyrxsh);
/* discard intermediate indications for ucode with one legitimate case:
* e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
@@ -862,34 +856,36 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
*/
if (!(txs->status & TX_STATUS_AMPDU)
&& (txs->status & TX_STATUS_INTERMEDIATE)) {
- BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
- return false;
+ brcms_dbg_tx(wlc->hw->d11core, "INTERMEDIATE but not AMPDU\n");
+ fatal = false;
+ goto out;
}
queue = txs->frameid & TXFID_QUEUE_MASK;
if (queue >= NFIFO) {
- p = NULL;
- goto fatal;
+ brcms_err(wlc->hw->d11core, "queue %u >= NFIFO\n", queue);
+ goto out;
}
+ dma = wlc->hw->di[queue];
+
p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
- if (p == NULL)
- goto fatal;
+ if (p == NULL) {
+ brcms_err(wlc->hw->d11core, "dma_getnexttxp returned null!\n");
+ goto out;
+ }
txh = (struct d11txh *) (p->data);
mcl = le16_to_cpu(txh->MacTxControlLow);
- if (txs->phyerr) {
- if (brcm_msg_level & LOG_ERROR_VAL) {
- wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
- txs->phyerr, txh->MainRates);
- brcms_c_print_txdesc(txh);
- }
- brcms_c_print_txstatus(txs);
- }
+ if (txs->phyerr)
+ brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+ txs->phyerr, txh->MainRates);
- if (txs->frameid != le16_to_cpu(txh->TxFrameID))
- goto fatal;
+ if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
+ brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
+ goto out;
+ }
tx_info = IEEE80211_SKB_CB(p);
h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
@@ -898,14 +894,24 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
- return false;
+ fatal = false;
+ goto out;
}
+ /*
+ * brcms_c_ampdu_dotxstatus() will trace tx descriptors for AMPDU
+ * frames; this traces them for the rest.
+ */
+ trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
supr_status = txs->status & TX_STATUS_SUPR_MASK;
- if (supr_status == TX_STATUS_SUPR_BADCH)
- BCMMSG(wlc->wiphy,
- "%s: Pkt tx suppressed, possibly channel %d\n",
- __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+ if (supr_status == TX_STATUS_SUPR_BADCH) {
+ unsigned xfts = le16_to_cpu(txh->XtraFrameTypes);
+ brcms_dbg_tx(wlc->hw->d11core,
+ "Pkt tx suppressed, dest chan %u, current %d\n",
+ (xfts >> XFTS_CHANNEL_SHIFT) & 0xff,
+ CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+ }
tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS;
tx_frame_count =
@@ -916,7 +922,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
lastframe = !ieee80211_has_morefrags(h->frame_control);
if (!lastframe) {
- wiphy_err(wlc->wiphy, "Not last frame!\n");
+ brcms_err(wlc->hw->d11core, "Not last frame!\n");
} else {
/*
* Set information to be consumed by Minstrel ht.
@@ -982,26 +988,37 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
totlen = p->len;
free_pdu = true;
- brcms_c_txfifo_complete(wlc, queue, 1);
-
if (lastframe) {
/* remove PLCP & Broadcom tx descriptor header */
skb_pull(p, D11_PHY_HDR_LEN);
skb_pull(p, D11_TXH_LEN);
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
} else {
- wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
- "tx_status\n", __func__);
+ brcms_err(wlc->hw->d11core,
+ "%s: Not last frame => not calling tx_status\n",
+ __func__);
}
- return false;
+ fatal = false;
- fatal:
- if (p)
- brcmu_pkt_buf_free_skb(p);
+ out:
+ if (fatal) {
+ if (txh)
+ trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+ sizeof(*txh));
+ if (p)
+ brcmu_pkt_buf_free_skb(p);
+ }
- return true;
+ if (dma && queue < NFIFO) {
+ u16 ac_queue = brcms_fifo_to_ac(queue);
+ if (dma->txavail > TX_HEADROOM && queue < TX_BCMC_FIFO &&
+ ieee80211_queue_stopped(wlc->pub->ieee_hw, ac_queue))
+ ieee80211_wake_queue(wlc->pub->ieee_hw, ac_queue);
+ dma_kick_tx(dma);
+ }
+ return fatal;
}
/* process tx completion events in BMAC
@@ -1011,7 +1028,6 @@ static bool
brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
{
bool morepending = false;
- struct brcms_c_info *wlc = wlc_hw->wlc;
struct bcma_device *core;
struct tx_status txstatus, *txs;
u32 s1, s2;
@@ -1022,19 +1038,23 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
*/
uint max_tx_num = bound ? TXSBND : -1;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
txs = &txstatus;
core = wlc_hw->d11core;
*fatal = false;
s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
while (!(*fatal)
&& (s1 & TXS_V)) {
+ /* !give others some time to run! */
+ if (n >= max_tx_num) {
+ morepending = true;
+ break;
+ }
if (s1 == 0xffffffff) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
- wlc_hw->unit, __func__);
- return morepending;
+ brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ *fatal = true;
+ return false;
}
s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
@@ -1046,20 +1066,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
*fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
- /* !give others some time to run! */
- if (++n >= max_tx_num)
- break;
s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
+ n++;
}
if (*fatal)
- return 0;
-
- if (n >= max_tx_num)
- morepending = true;
-
- if (!pktq_empty(&wlc->pkt_queue->q))
- brcms_c_send_q(wlc);
+ return false;
return morepending;
}
@@ -1112,7 +1124,6 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
u16 pio_mhf2 = 0;
struct brcms_hardware *wlc_hw = wlc->hw;
uint unit = wlc_hw->unit;
- struct wiphy *wiphy = wlc->wiphy;
/* name and offsets for dma_attach */
snprintf(name, sizeof(name), "wl%d", unit);
@@ -1125,12 +1136,12 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
* TX: TX_AC_BK_FIFO (TX AC Background data packets)
* RX: RX_FIFO (RX data packets)
*/
- wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+ wlc_hw->di[0] = dma_attach(name, wlc,
(wme ? dmareg(DMA_TX, 0) : 0),
dmareg(DMA_RX, 0),
(wme ? NTXD : 0), NRXD,
RXBUFSZ, -1, NRXBUFPOST,
- BRCMS_HWRXOFF, &brcm_msg_level);
+ BRCMS_HWRXOFF);
dma_attach_err |= (NULL == wlc_hw->di[0]);
/*
@@ -1139,10 +1150,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
* (legacy) TX_DATA_FIFO (TX data packets)
* RX: UNUSED
*/
- wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+ wlc_hw->di[1] = dma_attach(name, wlc,
dmareg(DMA_TX, 1), 0,
- NTXD, 0, 0, -1, 0, 0,
- &brcm_msg_level);
+ NTXD, 0, 0, -1, 0, 0);
dma_attach_err |= (NULL == wlc_hw->di[1]);
/*
@@ -1150,26 +1160,26 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
* TX: TX_AC_VI_FIFO (TX AC Video data packets)
* RX: UNUSED
*/
- wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+ wlc_hw->di[2] = dma_attach(name, wlc,
dmareg(DMA_TX, 2), 0,
- NTXD, 0, 0, -1, 0, 0,
- &brcm_msg_level);
+ NTXD, 0, 0, -1, 0, 0);
dma_attach_err |= (NULL == wlc_hw->di[2]);
/*
* FIFO 3
* TX: TX_AC_VO_FIFO (TX AC Voice data packets)
* (legacy) TX_CTL_FIFO (TX control & mgmt packets)
*/
- wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+ wlc_hw->di[3] = dma_attach(name, wlc,
dmareg(DMA_TX, 3),
0, NTXD, 0, 0, -1,
- 0, 0, &brcm_msg_level);
+ 0, 0);
dma_attach_err |= (NULL == wlc_hw->di[3]);
/* Cleaner to leave this as if with AP defined */
if (dma_attach_err) {
- wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
- "\n", unit);
+ brcms_err(wlc_hw->d11core,
+ "wl%d: wlc_attach: dma_attach failed\n",
+ unit);
return false;
}
@@ -1503,8 +1513,7 @@ brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
u16 mac_m;
u16 mac_h;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
- wlc_hw->unit);
+ brcms_dbg_rx(core, "wl%d: brcms_b_set_addrmatch\n", wlc_hw->unit);
mac_l = addr[0] | (addr[1] << 8);
mac_m = addr[2] | (addr[3] << 8);
@@ -1527,7 +1536,7 @@ brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
__le32 word_le;
__be32 word_be;
bool be_bit;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
bcma_write32(core, D11REGOFFS(tplatewrptr), offset);
@@ -1700,8 +1709,8 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
{
struct brcms_hardware *wlc_hw = wlc->hw;
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
+ brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc_hw->band->bandunit);
brcms_c_ucode_bsinit(wlc_hw);
@@ -1736,8 +1745,6 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
/* Perform a soft reset of the PHY PLL */
void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
udelay(1);
@@ -1782,7 +1789,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
u32 phy_bw_clkbits;
bool phy_in_reset = false;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d: reset phy\n", wlc_hw->unit);
if (pih == NULL)
return;
@@ -1916,7 +1923,7 @@ static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_
/* power both the pll and external oscillator on/off */
static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d: want %d\n", wlc_hw->unit, want);
/*
* dont power down if plldown is false or
@@ -2005,7 +2012,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
if (flags == BRCMS_USE_COREFLAGS)
flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d: core reset\n", wlc_hw->unit);
/* request FAST clock if not on */
fastclk = wlc_hw->forcefastclk;
@@ -2016,13 +2023,13 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
if (bcma_core_is_enabled(wlc_hw->d11core)) {
for (i = 0; i < NFIFO; i++)
if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
+ brcms_err(wlc_hw->d11core, "wl%d: %s: "
"dma_txreset[%d]: cannot stop dma\n",
wlc_hw->unit, __func__, i);
if ((wlc_hw->di[RX_FIFO])
&& (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
+ brcms_err(wlc_hw->d11core, "wl%d: %s: dma_rxreset"
"[%d]: cannot stop dma\n",
wlc_hw->unit, __func__, RX_FIFO);
}
@@ -2235,7 +2242,7 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
uint i;
uint count;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
count = (nbytes / sizeof(u32));
@@ -2257,14 +2264,14 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
if (wlc_hw->ucode_loaded)
return;
- if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
if (BRCMS_ISNPHY(wlc_hw->band)) {
brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo,
ucode->bcm43xx_16_mimosz);
wlc_hw->ucode_loaded = true;
} else
- wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
- "corerev %d\n",
+ brcms_err(wlc_hw->d11core,
+ "%s: wl%d: unsupported phy in corerev %d\n",
__func__, wlc_hw->unit, wlc_hw->corerev);
} else if (D11REV_IS(wlc_hw->corerev, 24)) {
if (BRCMS_ISLCNPHY(wlc_hw->band)) {
@@ -2272,8 +2279,8 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
ucode->bcm43xx_24_lcnsz);
wlc_hw->ucode_loaded = true;
} else {
- wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
- "corerev %d\n",
+ brcms_err(wlc_hw->d11core,
+ "%s: wl%d: unsupported phy in corerev %d\n",
__func__, wlc_hw->unit, wlc_hw->corerev);
}
}
@@ -2310,7 +2317,6 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
uint unit;
uint intstatus, idx;
struct bcma_device *core = wlc_hw->d11core;
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
unit = wlc_hw->unit;
@@ -2323,39 +2329,39 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
if (!intstatus)
continue;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
- unit, idx, intstatus);
+ brcms_dbg_int(core, "wl%d: intstatus%d 0x%x\n",
+ unit, idx, intstatus);
if (intstatus & I_RO) {
- wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
+ brcms_err(core, "wl%d: fifo %d: receive fifo "
"overflow\n", unit, idx);
fatal = true;
}
if (intstatus & I_PC) {
- wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
- unit, idx);
+ brcms_err(core, "wl%d: fifo %d: descriptor error\n",
+ unit, idx);
fatal = true;
}
if (intstatus & I_PD) {
- wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
+ brcms_err(core, "wl%d: fifo %d: data error\n", unit,
idx);
fatal = true;
}
if (intstatus & I_DE) {
- wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
+ brcms_err(core, "wl%d: fifo %d: descriptor protocol "
"error\n", unit, idx);
fatal = true;
}
if (intstatus & I_RU)
- wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
+ brcms_err(core, "wl%d: fifo %d: receive descriptor "
"underflow\n", idx, unit);
if (intstatus & I_XU) {
- wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
+ brcms_err(core, "wl%d: fifo %d: transmit fifo "
"underflow\n", idx, unit);
fatal = true;
}
@@ -2516,13 +2522,13 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
{
struct brcms_hardware *wlc_hw = wlc->hw;
struct bcma_device *core = wlc_hw->d11core;
- u32 macintstatus;
+ u32 macintstatus, mask;
/* macintstatus includes a DMA interrupt summary bit */
macintstatus = bcma_read32(core, D11REGOFFS(macintstatus));
+ mask = in_isr ? wlc->macintmask : wlc->defmacintmask;
- BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
- macintstatus);
+ trace_brcms_macintstatus(&core->dev, in_isr, macintstatus, mask);
/* detect cardbus removed, in power down(suspend) and in reset */
if (brcms_deviceremoved(wlc))
@@ -2535,16 +2541,12 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
return 0;
/* defer unsolicited interrupts */
- macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+ macintstatus &= mask;
/* if not for us */
if (macintstatus == 0)
return 0;
- /* interrupts are already turned off for CFE build
- * Caution: For CFE Turning off the interrupts again has some undesired
- * consequences
- */
/* turn off the interrupts */
bcma_write32(core, D11REGOFFS(macintmask), 0);
(void)bcma_read32(core, D11REGOFFS(macintmask));
@@ -2587,33 +2589,31 @@ bool brcms_c_intrsupd(struct brcms_c_info *wlc)
/*
* First-level interrupt processing.
- * Return true if this was our interrupt, false otherwise.
- * *wantdpc will be set to true if further brcms_c_dpc() processing is required,
+ * Return true if this was our interrupt
+ * and if further brcms_c_dpc() processing is required,
* false otherwise.
*/
-bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
+bool brcms_c_isr(struct brcms_c_info *wlc)
{
struct brcms_hardware *wlc_hw = wlc->hw;
u32 macintstatus;
- *wantdpc = false;
-
if (!wlc_hw->up || !wlc->macintmask)
return false;
/* read and clear macintstatus and intstatus registers */
macintstatus = wlc_intstatus(wlc, true);
- if (macintstatus == 0xffffffff)
- wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
- " path\n");
+ if (macintstatus == 0xffffffff) {
+ brcms_err(wlc_hw->d11core,
+ "DEVICEREMOVED detected in the ISR code path\n");
+ return false;
+ }
/* it is not for us */
if (macintstatus == 0)
return false;
- *wantdpc = true;
-
/* save interrupt status bits */
wlc->macintstatus = macintstatus;
@@ -2626,10 +2626,9 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
struct brcms_hardware *wlc_hw = wlc->hw;
struct bcma_device *core = wlc_hw->d11core;
u32 mc, mi;
- struct wiphy *wiphy = wlc->wiphy;
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
+ brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc_hw->band->bandunit);
/*
* Track overlapping suspend requests
@@ -2644,7 +2643,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
mc = bcma_read32(core, D11REGOFFS(maccontrol));
if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
__func__);
brcms_down(wlc->wl);
return;
@@ -2655,7 +2654,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
mi = bcma_read32(core, D11REGOFFS(macintstatus));
if (mi == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
__func__);
brcms_down(wlc->wl);
return;
@@ -2668,10 +2667,10 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
BRCMS_MAX_MAC_SUSPEND);
if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) {
- wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
+ brcms_err(core, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
" and MI_MACSSPNDD is still not on.\n",
wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
- wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
+ brcms_err(core, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
"psm_brc 0x%04x\n", wlc_hw->unit,
bcma_read32(core, D11REGOFFS(psmdebug)),
bcma_read32(core, D11REGOFFS(phydebug)),
@@ -2680,7 +2679,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
mc = bcma_read32(core, D11REGOFFS(maccontrol));
if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
__func__);
brcms_down(wlc->wl);
return;
@@ -2696,8 +2695,8 @@ void brcms_c_enable_mac(struct brcms_c_info *wlc)
struct bcma_device *core = wlc_hw->d11core;
u32 mc, mi;
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc->band->bandunit);
+ brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc->band->bandunit);
/*
* Track overlapping suspend requests
@@ -2740,8 +2739,6 @@ static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
u32 w, val;
struct wiphy *wiphy = wlc_hw->wlc->wiphy;
- BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
-
/* Validate dchip register access */
bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
@@ -2802,7 +2799,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
struct bcma_device *core = wlc_hw->d11core;
u32 tmp;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
tmp = 0;
@@ -2818,8 +2815,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT)
- wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
- " PLL failed\n", __func__);
+ brcms_err(core, "%s: turn on PHY PLL failed\n",
+ __func__);
} else {
bcma_set32(core, D11REGOFFS(clk_ctl_st),
tmp | CCS_ERSRC_REQ_D11PLL |
@@ -2835,8 +2832,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
(CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
!=
(CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
- wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
- "PHY PLL failed\n", __func__);
+ brcms_err(core, "%s: turn on PHY PLL failed\n",
+ __func__);
}
} else {
/*
@@ -2854,7 +2851,7 @@ static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
{
bool dev_gone;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d: disable core\n", wlc_hw->unit);
dev_gone = brcms_deviceremoved(wlc_hw->wlc);
@@ -2884,12 +2881,14 @@ static void brcms_c_flushqueues(struct brcms_c_info *wlc)
uint i;
/* free any posted tx packets */
- for (i = 0; i < NFIFO; i++)
+ for (i = 0; i < NFIFO; i++) {
if (wlc_hw->di[i]) {
dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
- wlc->core->txpktpend[i] = 0;
- BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
+ if (i < TX_BCMC_FIFO)
+ ieee80211_wake_queue(wlc->pub->ieee_hw,
+ brcms_fifo_to_ac(i));
}
+ }
/* free any posted rx packets */
dma_rxreclaim(wlc_hw->di[RX_FIFO]);
@@ -2921,7 +2920,7 @@ brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
if (offset & 2)
objoff += 2;
- bcma_write16(core, objoff, v);
+ bcma_wflush16(core, objoff, v);
}
/*
@@ -3109,7 +3108,7 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
/* check for rx fifo 0 overflow */
delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
if (delta)
- wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
+ brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n",
wlc->pub->unit, delta);
/* check for tx fifo underflows */
@@ -3118,8 +3117,9 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
(u16) (wlc->core->macstat_snapshot->txfunfl[i] -
txfunfl[i]);
if (delta)
- wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
- "\n", wlc->pub->unit, delta, i);
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %u tx fifo %d underflows!\n",
+ wlc->pub->unit, delta, i);
}
#endif /* DEBUG */
@@ -3132,8 +3132,6 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
static void brcms_b_reset(struct brcms_hardware *wlc_hw)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
/* reset the core */
if (!brcms_deviceremoved(wlc_hw->wlc))
brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
@@ -3144,7 +3142,7 @@ static void brcms_b_reset(struct brcms_hardware *wlc_hw)
void brcms_c_reset(struct brcms_c_info *wlc)
{
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
/* slurp up hw mac counters before core reset */
brcms_c_statsupd(wlc);
@@ -3189,10 +3187,9 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
bool fifosz_fixup = false;
int err = 0;
u16 buf[NFIFO];
- struct wiphy *wiphy = wlc->wiphy;
struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(core, "wl%d: core init\n", wlc_hw->unit);
/* reset PSM */
brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
@@ -3212,29 +3209,29 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) &
MI_MACSSPNDD) == 0), 1000 * 1000);
if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0)
- wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
+ brcms_err(core, "wl%d: wlc_coreinit: ucode did not self-"
"suspend!\n", wlc_hw->unit);
brcms_c_gpio_init(wlc);
sflags = bcma_aread32(core, BCMA_IOST);
- if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
if (BRCMS_ISNPHY(wlc_hw->band))
brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+ brcms_err(core, "%s: wl%d: unsupported phy in corerev"
" %d\n", __func__, wlc_hw->unit,
wlc_hw->corerev);
} else if (D11REV_IS(wlc_hw->corerev, 24)) {
if (BRCMS_ISLCNPHY(wlc_hw->band))
brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24);
else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+ brcms_err(core, "%s: wl%d: unsupported phy in corerev"
" %d\n", __func__, wlc_hw->unit,
wlc_hw->corerev);
} else {
- wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+ brcms_err(core, "%s: wl%d: unsupported corerev %d\n",
__func__, wlc_hw->unit, wlc_hw->corerev);
}
@@ -3276,7 +3273,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
err = -1;
}
if (err != 0)
- wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
+ brcms_err(core, "wlc_coreinit: txfifo mismatch: ucode size %d"
" driver size %d index %d\n", buf[i],
wlc_hw->xmtfifo_sz[i], i);
@@ -3359,8 +3356,6 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) {
bool fastclk;
struct brcms_c_info *wlc = wlc_hw->wlc;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
/* request FAST clock if not on */
fastclk = wlc_hw->forcefastclk;
if (!fastclk)
@@ -3453,7 +3448,7 @@ static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
rate = (rateset->rates[i] & BRCMS_RATE_MASK);
if (rate > BRCM_MAXRATE) {
- wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+ brcms_err(wlc->hw->d11core, "brcms_c_rate_lookup_init: "
"invalid rate 0x%X in rate set\n",
rateset->rates[i]);
continue;
@@ -3529,7 +3524,6 @@ static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
uint parkband;
uint i, band_order[2];
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/*
* We might have been bandlocked during down and the chip
* power-cycled (hibernate). Figure out the right band to park on
@@ -3710,8 +3704,8 @@ static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
/* band-specific init */
static void brcms_c_bsinit(struct brcms_c_info *wlc)
{
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
- wlc->pub->unit, wlc->band->bandunit);
+ brcms_dbg_info(wlc->hw->d11core, "wl%d: bandunit %d\n",
+ wlc->pub->unit, wlc->band->bandunit);
/* write ucode ACK/CTS rate table */
brcms_c_set_ratetable(wlc);
@@ -3734,7 +3728,8 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
M_TX_IDLE_BUSY_RATIO_X_16_CCK;
if (duty_cycle > 100 || duty_cycle < 0) {
- wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n",
+ brcms_err(wlc->hw->d11core,
+ "wl%d: duty cycle value off limit\n",
wlc->pub->unit);
return -EINVAL;
}
@@ -3752,40 +3747,6 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
return 0;
}
-/*
- * Initialize the base precedence map for dequeueing
- * from txq based on WME settings
- */
-static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
-{
- wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
- memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
-
- wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
- wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
- wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
- wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
-}
-
-static void
-brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi, bool on, int prio)
-{
- /* transmit flowcontrol is not yet implemented */
-}
-
-static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
-{
- struct brcms_txq_info *qi;
-
- for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
- if (qi->stopped) {
- brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
- qi->stopped = 0;
- }
- }
-}
-
/* push sw hps and wake state through hardware */
static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
{
@@ -3795,7 +3756,8 @@ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
hps = brcms_c_ps_allowed(wlc);
- BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
+ brcms_dbg_mac80211(wlc->hw->d11core, "wl%d: hps %d\n", wlc->pub->unit,
+ hps);
v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
v2 = MCTL_WAKE;
@@ -3881,7 +3843,8 @@ brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
{
uint bandunit;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
+ brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: 0x%x\n", wlc_hw->unit,
+ chanspec);
wlc_hw->chanspec = chanspec;
@@ -3942,7 +3905,7 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
u16 old_chanspec = wlc->chanspec;
if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
+ brcms_err(wlc->hw->d11core, "wl%d: %s: Bad channel %d\n",
wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
return;
}
@@ -3953,8 +3916,8 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
switchband = true;
if (wlc->bandlocked) {
- wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d "
- "band is locked!\n",
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: chspec %d band is locked!\n",
wlc->pub->unit, __func__,
CHSPEC_CHANNEL(chanspec));
return;
@@ -4018,6 +3981,10 @@ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
*/
void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
{
+ /*
+ * Cannot use brcms_dbg_* here because this function is called
+ * before wlc is sufficiently initialized.
+ */
BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
switch (idx) {
@@ -4090,8 +4057,8 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
/* Only apply params if the core is out of reset and has clocks */
if (!wlc->clk) {
- wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
- __func__);
+ brcms_err(wlc->hw->d11core, "wl%d: %s : no-clock\n",
+ wlc->pub->unit, __func__);
return;
}
@@ -4109,7 +4076,7 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
if (acp_shm.aifs < EDCF_AIFSN_MIN
|| acp_shm.aifs > EDCF_AIFSN_MAX) {
- wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
+ brcms_err(wlc->hw->d11core, "wl%d: edcf_setparams: bad "
"aifs %d\n", wlc->pub->unit, acp_shm.aifs);
} else {
acp_shm.cwmin = params->cw_min;
@@ -4224,8 +4191,8 @@ static void brcms_c_radio_timer(void *arg)
struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
if (brcms_deviceremoved(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
+ brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+ wlc->pub->unit, __func__);
brcms_down(wlc->wl);
return;
}
@@ -4238,8 +4205,6 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc)
{
struct brcms_hardware *wlc_hw = wlc->hw;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
if (!wlc_hw->up)
return;
@@ -4258,14 +4223,14 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc)
/* common watchdog code */
static void brcms_c_watchdog(struct brcms_c_info *wlc)
{
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
if (!wlc->pub->up)
return;
if (brcms_deviceremoved(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
+ brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+ wlc->pub->unit, __func__);
brcms_down(wlc->wl);
return;
}
@@ -4437,13 +4402,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
struct ssb_sprom *sprom = &core->bus->sprom;
if (core->bus->hosttype == BCMA_HOSTTYPE_PCI)
- BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
- pcidev->vendor,
- pcidev->device);
+ brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+ pcidev->vendor,
+ pcidev->device);
else
- BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
- core->bus->boardinfo.vendor,
- core->bus->boardinfo.type);
+ brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+ core->bus->boardinfo.vendor,
+ core->bus->boardinfo.type);
wme = true;
@@ -4535,7 +4500,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
/* check device id(srom, nvram etc.) to set bands */
if (wlc_hw->deviceid == BCM43224_D11N_ID ||
- wlc_hw->deviceid == BCM43224_D11N_ID_VEN1)
+ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1 ||
+ wlc_hw->deviceid == BCM43224_CHIP_ID)
/* Dualband boards */
wlc_hw->_nbands = 2;
else
@@ -4715,8 +4681,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
goto fail;
}
- BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n",
- wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih));
+ brcms_dbg_info(wlc_hw->d11core, "deviceid 0x%x nbands %d board 0x%x\n",
+ wlc_hw->deviceid, wlc_hw->_nbands,
+ ai_get_boardtype(wlc_hw->sih));
return err;
@@ -4836,56 +4803,6 @@ static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
bi->flags |= BRCMS_BSS_HT;
}
-static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
-{
- struct brcms_txq_info *qi, *p;
-
- qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
- if (qi != NULL) {
- /*
- * Have enough room for control packets along with HI watermark
- * Also, add room to txq for total psq packets if all the SCBs
- * leave PS mode. The watermark for flowcontrol to OS packets
- * will remain the same
- */
- brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
- 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT);
-
- /* add this queue to the the global list */
- p = wlc->tx_queues;
- if (p == NULL) {
- wlc->tx_queues = qi;
- } else {
- while (p->next != NULL)
- p = p->next;
- p->next = qi;
- }
- }
- return qi;
-}
-
-static void brcms_c_txq_free(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi)
-{
- struct brcms_txq_info *p;
-
- if (qi == NULL)
- return;
-
- /* remove the queue from the linked list */
- p = wlc->tx_queues;
- if (p == qi)
- wlc->tx_queues = p->next;
- else {
- while (p != NULL && p->next != qi)
- p = p->next;
- if (p != NULL)
- p->next = p->next->next;
- }
-
- kfree(qi);
-}
-
static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
{
uint i;
@@ -4991,8 +4908,6 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
if (wlc == NULL)
return 0;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
callbacks += brcms_b_detach(wlc);
/* delete software timers */
@@ -5005,10 +4920,6 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
brcms_c_detach_module(wlc);
-
- while (wlc->tx_queues != NULL)
- brcms_c_txq_free(wlc, wlc->tx_queues);
-
brcms_c_detach_mfree(wlc);
return callbacks;
}
@@ -5026,7 +4937,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
if (wlc_hw->wlc->pub->hw_up)
return;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
/*
* Enable pll and xtal, initialize the power control registers,
@@ -5063,7 +4974,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
/*
* Enable pll and xtal, initialize the power control registers,
@@ -5077,7 +4988,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
* Configure pci/pcmcia here instead of in brcms_c_attach()
* to allow mfg hotswap: down, hotswap (chip power cycle), up.
*/
- bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
+ bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
true);
/*
@@ -5102,8 +5013,6 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
wlc_hw->up = true;
wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
@@ -5135,7 +5044,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
{
struct ieee80211_channel *ch;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
/* HW is turned off so don't try to access it */
if (wlc->pub->hw_off || brcms_deviceremoved(wlc))
@@ -5176,8 +5085,8 @@ int brcms_c_up(struct brcms_c_info *wlc)
WL_RADIO_HW_DISABLE);
if (bsscfg->enable && bsscfg->BSS)
- wiphy_err(wlc->wiphy, "wl%d: up"
- ": rfdisable -> "
+ brcms_err(wlc->hw->d11core,
+ "wl%d: up: rfdisable -> "
"bsscfg_disable()\n",
wlc->pub->unit);
}
@@ -5237,8 +5146,6 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
bool dev_gone;
uint callbacks = 0;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
if (!wlc_hw->up)
return callbacks;
@@ -5265,8 +5172,6 @@ static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
uint callbacks = 0;
bool dev_gone;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
if (!wlc_hw->up)
return callbacks;
@@ -5314,14 +5219,14 @@ uint brcms_c_down(struct brcms_c_info *wlc)
uint callbacks = 0;
int i;
bool dev_gone = false;
- struct brcms_txq_info *qi;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
/* check if we are already in the going down path */
if (wlc->going_down) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return"
- "\n", wlc->pub->unit, __func__);
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: Driver going down so return\n",
+ wlc->pub->unit, __func__);
return 0;
}
if (!wlc->pub->up)
@@ -5353,13 +5258,6 @@ uint brcms_c_down(struct brcms_c_info *wlc)
wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
- /* clear txq flow control */
- brcms_c_txflowcontrol_reset(wlc);
-
- /* flush tx queues */
- for (qi = wlc->tx_queues; qi != NULL; qi = qi->next)
- brcmu_pktq_flush(&qi->q, true, NULL, NULL);
-
callbacks += brcms_b_down_finish(wlc->hw);
/* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */
@@ -5441,7 +5339,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
default:
/* Error */
- wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
+ brcms_err(wlc->hw->d11core, "wl%d: %s: invalid gmode %d\n",
wlc->pub->unit, __func__, gmode);
return -ENOTSUPP;
}
@@ -5745,45 +5643,6 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
return -ENODATA;
}
-void brcms_c_print_txstatus(struct tx_status *txs)
-{
- pr_debug("\ntxpkt (MPDU) Complete\n");
-
- pr_debug("FrameID: %04x TxStatus: %04x\n", txs->frameid, txs->status);
-
- pr_debug("[15:12] %d frame attempts\n",
- (txs->status & TX_STATUS_FRM_RTX_MASK) >>
- TX_STATUS_FRM_RTX_SHIFT);
- pr_debug(" [11:8] %d rts attempts\n",
- (txs->status & TX_STATUS_RTS_RTX_MASK) >>
- TX_STATUS_RTS_RTX_SHIFT);
- pr_debug(" [7] %d PM mode indicated\n",
- txs->status & TX_STATUS_PMINDCTD ? 1 : 0);
- pr_debug(" [6] %d intermediate status\n",
- txs->status & TX_STATUS_INTERMEDIATE ? 1 : 0);
- pr_debug(" [5] %d AMPDU\n",
- txs->status & TX_STATUS_AMPDU ? 1 : 0);
- pr_debug(" [4:2] %d Frame Suppressed Reason (%s)\n",
- (txs->status & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT,
- (const char *[]) {
- "None",
- "PMQ Entry",
- "Flush request",
- "Previous frag failure",
- "Channel mismatch",
- "Lifetime Expiry",
- "Underflow"
- } [(txs->status & TX_STATUS_SUPR_MASK) >>
- TX_STATUS_SUPR_SHIFT]);
- pr_debug(" [1] %d acked\n",
- txs->status & TX_STATUS_ACK_RCV ? 1 : 0);
-
- pr_debug("LastTxTime: %04x Seq: %04x PHYTxStatus: %04x RxAckRSSI: %04x RxAckSQ: %04x\n",
- txs->lasttxtime, txs->sequence, txs->phyerr,
- (txs->ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT,
- (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
-}
-
static bool brcms_c_chipmatch_pci(struct bcma_device *core)
{
struct pci_dev *pcidev = core->bus->host_pci;
@@ -5795,7 +5654,7 @@ static bool brcms_c_chipmatch_pci(struct bcma_device *core)
return false;
}
- if (device == BCM43224_D11N_ID_VEN1)
+ if (device == BCM43224_D11N_ID_VEN1 || device == BCM43224_CHIP_ID)
return true;
if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
return true;
@@ -5832,184 +5691,6 @@ bool brcms_c_chipmatch(struct bcma_device *core)
}
}
-#if defined(DEBUG)
-void brcms_c_print_txdesc(struct d11txh *txh)
-{
- u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
- u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
- u16 mfc = le16_to_cpu(txh->MacFrameControl);
- u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
- u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
- u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
- u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
- u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
- u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
- u16 mainrates = le16_to_cpu(txh->MainRates);
- u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
- u8 *iv = txh->IV;
- u8 *ra = txh->TxFrameRA;
- u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
- u8 *rtspfb = txh->RTSPLCPFallback;
- u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
- u8 *fragpfb = txh->FragPLCPFallback;
- u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
- u16 mmodelen = le16_to_cpu(txh->MModeLen);
- u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
- u16 tfid = le16_to_cpu(txh->TxFrameID);
- u16 txs = le16_to_cpu(txh->TxStatus);
- u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
- u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
- u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
- u16 mmbyte = le16_to_cpu(txh->MinMBytes);
-
- u8 *rtsph = txh->RTSPhyHeader;
- struct ieee80211_rts rts = txh->rts_frame;
-
- /* add plcp header along with txh descriptor */
- brcmu_dbg_hex_dump(txh, sizeof(struct d11txh) + 48,
- "Raw TxDesc + plcp header:\n");
-
- pr_debug("TxCtlLow: %04x ", mtcl);
- pr_debug("TxCtlHigh: %04x ", mtch);
- pr_debug("FC: %04x ", mfc);
- pr_debug("FES Time: %04x\n", tfest);
- pr_debug("PhyCtl: %04x%s ", ptcw,
- (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
- pr_debug("PhyCtl_1: %04x ", ptcw_1);
- pr_debug("PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
- pr_debug("PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
- pr_debug("PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
- pr_debug("MainRates: %04x ", mainrates);
- pr_debug("XtraFrameTypes: %04x ", xtraft);
- pr_debug("\n");
-
- print_hex_dump_bytes("SecIV:", DUMP_PREFIX_OFFSET, iv, sizeof(txh->IV));
- print_hex_dump_bytes("RA:", DUMP_PREFIX_OFFSET,
- ra, sizeof(txh->TxFrameRA));
-
- pr_debug("Fb FES Time: %04x ", tfestfb);
- print_hex_dump_bytes("Fb RTS PLCP:", DUMP_PREFIX_OFFSET,
- rtspfb, sizeof(txh->RTSPLCPFallback));
- pr_debug("RTS DUR: %04x ", rtsdfb);
- print_hex_dump_bytes("PLCP:", DUMP_PREFIX_OFFSET,
- fragpfb, sizeof(txh->FragPLCPFallback));
- pr_debug("DUR: %04x", fragdfb);
- pr_debug("\n");
-
- pr_debug("MModeLen: %04x ", mmodelen);
- pr_debug("MModeFbrLen: %04x\n", mmodefbrlen);
-
- pr_debug("FrameID: %04x\n", tfid);
- pr_debug("TxStatus: %04x\n", txs);
-
- pr_debug("MaxNumMpdu: %04x\n", mnmpdu);
- pr_debug("MaxAggbyte: %04x\n", mabyte);
- pr_debug("MaxAggbyte_fb: %04x\n", mabyte_f);
- pr_debug("MinByte: %04x\n", mmbyte);
-
- print_hex_dump_bytes("RTS PLCP:", DUMP_PREFIX_OFFSET,
- rtsph, sizeof(txh->RTSPhyHeader));
- print_hex_dump_bytes("RTS Frame:", DUMP_PREFIX_OFFSET,
- (u8 *)&rts, sizeof(txh->rts_frame));
- pr_debug("\n");
-}
-#endif /* defined(DEBUG) */
-
-#if defined(DEBUG)
-static int
-brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf,
- int len)
-{
- int i;
- char *p = buf;
- char hexstr[16];
- int slen = 0, nlen = 0;
- u32 bit;
- const char *name;
-
- if (len < 2 || !buf)
- return 0;
-
- buf[0] = '\0';
-
- for (i = 0; flags != 0; i++) {
- bit = bd[i].bit;
- name = bd[i].name;
- if (bit == 0 && flags != 0) {
- /* print any unnamed bits */
- snprintf(hexstr, 16, "0x%X", flags);
- name = hexstr;
- flags = 0; /* exit loop */
- } else if ((flags & bit) == 0)
- continue;
- flags &= ~bit;
- nlen = strlen(name);
- slen += nlen;
- /* count btwn flag space */
- if (flags != 0)
- slen += 1;
- /* need NULL char as well */
- if (len <= slen)
- break;
- /* copy NULL char but don't count it */
- strncpy(p, name, nlen + 1);
- p += nlen;
- /* copy btwn flag space and NULL char */
- if (flags != 0)
- p += snprintf(p, 2, " ");
- len -= slen;
- }
-
- /* indicate the str was too short */
- if (flags != 0) {
- if (len < 2)
- p -= 2 - len; /* overwrite last char */
- p += snprintf(p, 2, ">");
- }
-
- return (int)(p - buf);
-}
-#endif /* defined(DEBUG) */
-
-#if defined(DEBUG)
-void brcms_c_print_rxh(struct d11rxhdr *rxh)
-{
- u16 len = rxh->RxFrameSize;
- u16 phystatus_0 = rxh->PhyRxStatus_0;
- u16 phystatus_1 = rxh->PhyRxStatus_1;
- u16 phystatus_2 = rxh->PhyRxStatus_2;
- u16 phystatus_3 = rxh->PhyRxStatus_3;
- u16 macstatus1 = rxh->RxStatus1;
- u16 macstatus2 = rxh->RxStatus2;
- char flagstr[64];
- char lenbuf[20];
- static const struct brcms_c_bit_desc macstat_flags[] = {
- {RXS_FCSERR, "FCSErr"},
- {RXS_RESPFRAMETX, "Reply"},
- {RXS_PBPRES, "PADDING"},
- {RXS_DECATMPT, "DeCr"},
- {RXS_DECERR, "DeCrErr"},
- {RXS_BCNSENT, "Bcn"},
- {0, NULL}
- };
-
- brcmu_dbg_hex_dump(rxh, sizeof(struct d11rxhdr), "Raw RxDesc:\n");
-
- brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64);
-
- snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
-
- pr_debug("RxFrameSize: %6s (%d)%s\n", lenbuf, len,
- (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
- pr_debug("RxPHYStatus: %04x %04x %04x %04x\n",
- phystatus_0, phystatus_1, phystatus_2, phystatus_3);
- pr_debug("RxMACStatus: %x %s\n", macstatus1, flagstr);
- pr_debug("RXMACaggtype: %x\n",
- (macstatus2 & RXS_AGGTYPE_MASK));
- pr_debug("RxTSFTime: %04x\n", rxh->RxTSFTime);
-}
-#endif /* defined(DEBUG) */
-
u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
{
u16 table_ptr;
@@ -6033,86 +5714,6 @@ u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
}
-static bool
-brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
- struct sk_buff *pkt, int prec, bool head)
-{
- struct sk_buff *p;
- int eprec = -1; /* precedence to evict from */
-
- /* Determine precedence from which to evict packet, if any */
- if (pktq_pfull(q, prec))
- eprec = prec;
- else if (pktq_full(q)) {
- p = brcmu_pktq_peek_tail(q, &eprec);
- if (eprec > prec) {
- wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d"
- "\n", __func__, eprec, prec);
- return false;
- }
- }
-
- /* Evict if needed */
- if (eprec >= 0) {
- bool discard_oldest;
-
- discard_oldest = ac_bitmap_tst(0, eprec);
-
- /* Refuse newer packet unless configured to discard oldest */
- if (eprec == prec && !discard_oldest) {
- wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d"
- "\n", __func__, prec);
- return false;
- }
-
- /* Evict packet according to discard policy */
- p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
- brcmu_pktq_pdeq_tail(q, eprec);
- brcmu_pkt_buf_free_skb(p);
- }
-
- /* Enqueue */
- if (head)
- p = brcmu_pktq_penq_head(q, prec, pkt);
- else
- p = brcmu_pktq_penq(q, prec, pkt);
-
- return true;
-}
-
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
- struct sk_buff *pkt, int prec)
-{
- return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
- struct sk_buff *sdu, uint prec)
-{
- struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */
- struct pktq *q = &qi->q;
- int prio;
-
- prio = sdu->priority;
-
- if (!brcms_c_prec_enq(wlc, q, sdu, prec)) {
- /*
- * we might hit this condtion in case
- * packet flooding from mac80211 stack
- */
- brcmu_pkt_buf_free_skb(sdu);
- }
-}
-
/*
* bcmc_fid_generate:
* Generate frame ID for a BCMC packet. The frag field is not used
@@ -6140,8 +5741,6 @@ brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
{
uint dur = 0;
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
- wlc->pub->unit, rspec, preamble_type);
/*
* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
* is less than or equal to the rate of the immediately previous
@@ -6159,8 +5758,6 @@ static uint
brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec,
u8 preamble_type)
{
- BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
- wlc->pub->unit, rspec, preamble_type);
return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
}
@@ -6168,8 +5765,6 @@ static uint
brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec,
u8 preamble_type)
{
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
- "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
/*
* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
* is less than or equal to the rate of the immediately previous
@@ -6223,9 +5818,6 @@ brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
uint nsyms, mac_len, Ndps, kNdps;
uint rate = rspec2rate(ratespec);
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
- wlc->pub->unit, ratespec, preamble_type, dur);
-
if (is_mcs_rate(ratespec)) {
uint mcs = ratespec & RSPEC_RATE_MASK;
int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
@@ -6292,7 +5884,7 @@ static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
return true;
error:
if (verbose)
- wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+ brcms_err(wlc->hw->d11core, "wl%d: valid_rate: rate spec 0x%x "
"not in hw_rateset\n", wlc->pub->unit, rspec);
return false;
@@ -6302,6 +5894,7 @@ static u32
mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
u32 int_val)
{
+ struct bcma_device *core = wlc->hw->d11core;
u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
u8 rate = int_val & NRATE_RATE_MASK;
u32 rspec;
@@ -6318,7 +5911,7 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) {
/* mcs only allowed when nmode */
if (stf > PHY_TXC1_MODE_SDM) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
+ brcms_err(core, "wl%d: %s: Invalid stf\n",
wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
@@ -6329,8 +5922,8 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
if (!CHSPEC_IS40(wlc->home_chanspec) ||
((stf != PHY_TXC1_MODE_SISO)
&& (stf != PHY_TXC1_MODE_CDD))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
- "32\n", wlc->pub->unit, __func__);
+ brcms_err(core, "wl%d: %s: Invalid mcs 32\n",
+ wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
}
@@ -6338,9 +5931,9 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
/* mcs > 7 must use stf SDM */
if (stf != PHY_TXC1_MODE_SDM) {
- BCMMSG(wlc->wiphy, "wl%d: enabling "
- "SDM mode for mcs %d\n",
- wlc->pub->unit, rate);
+ brcms_dbg_mac80211(core, "wl%d: enabling "
+ "SDM mode for mcs %d\n",
+ wlc->pub->unit, rate);
stf = PHY_TXC1_MODE_SDM;
}
} else {
@@ -6351,15 +5944,15 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
if ((stf > PHY_TXC1_MODE_STBC) ||
(!BRCMS_STBC_CAP_PHY(wlc)
&& (stf == PHY_TXC1_MODE_STBC))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
- "\n", wlc->pub->unit, __func__);
+ brcms_err(core, "wl%d: %s: Invalid STBC\n",
+ wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
}
}
} else if (is_ofdm_rate(rate)) {
if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
+ brcms_err(core, "wl%d: %s: Invalid OFDM\n",
wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
@@ -6367,20 +5960,20 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
} else if (is_cck_rate(rate)) {
if ((cur_band->bandtype != BRCM_BAND_2G)
|| (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
+ brcms_err(core, "wl%d: %s: Invalid CCK\n",
wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
}
} else {
- wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
+ brcms_err(core, "wl%d: %s: Unknown rate type\n",
wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
}
/* make sure multiple antennae are available for non-siso rates */
if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
+ brcms_err(core, "wl%d: %s: SISO antenna but !SISO "
"request\n", wlc->pub->unit, __func__);
bcmerror = -EINVAL;
goto done;
@@ -6449,7 +6042,7 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
break;
default:
- wiphy_err(wlc->wiphy,
+ brcms_err(wlc->hw->d11core,
"brcms_c_cck_plcp_set: unsupported rate %d\n",
rate_500);
rate_500 = BRCM_RATE_1M;
@@ -6582,7 +6175,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
bw = rspec_get_bw(rspec);
/* 10Mhz is not supported yet */
if (bw < PHY_TXC1_BW_20MHZ) {
- wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
+ brcms_err(wlc->hw->d11core, "phytxctl1_calc: bw %d is "
"not supported yet, set to 20L\n", bw);
bw = PHY_TXC1_BW_20MHZ;
}
@@ -6609,7 +6202,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
/* get the phyctl byte from rate phycfg table */
phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
if (phycfg == -1) {
- wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
+ brcms_err(wlc->hw->d11core, "phytxctl1_calc: wrong "
"legacy OFDM/CCK rate\n");
phycfg = 0;
}
@@ -6689,8 +6282,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
/* non-AP STA should never use BCMC queue */
if (queue == TX_BCMC_FIFO) {
- wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
- "TX_BCMC!\n", wlc->pub->unit, __func__);
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: ASSERT queue == TX_BCMC!\n",
+ wlc->pub->unit, __func__);
frameid = bcmc_fid_generate(wlc, NULL, txh);
} else {
/* Increment the counter for first fragment */
@@ -6860,7 +6454,8 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
&& (!is_mcs_rate(rspec[k]))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: IEEE80211_TX_"
"RC_MCS != is_mcs_rate(rspec)\n",
wlc->pub->unit, __func__);
}
@@ -7254,14 +6849,16 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
wlc->fragthresh[queue] =
(u16) newfragthresh;
} else {
- wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s txop invalid "
"for rate %d\n",
wlc->pub->unit, fifo_names[queue],
rspec2rate(rspec[0]));
}
if (dur > wlc->edcf_txop[ac])
- wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
+ brcms_err(wlc->hw->d11core,
+ "wl%d: %s: %s txop "
"exceeded phylen %d/%d dur %d/%d\n",
wlc->pub->unit, __func__,
fifo_names[queue],
@@ -7273,79 +6870,33 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
return 0;
}
-void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
- struct ieee80211_hw *hw)
+static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb)
{
- u8 prio;
- uint fifo;
- struct scb *scb = &wlc->pri_scb;
- struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
-
- /*
- * 802.11 standard requires management traffic
- * to go at highest priority
- */
- prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
- MAXPRIO;
- fifo = prio2fifo[prio];
- if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0))
- return;
- brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio));
- brcms_c_send_q(wlc);
-}
-
-void brcms_c_send_q(struct brcms_c_info *wlc)
-{
- struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
- int prec;
- u16 prec_map;
- int err = 0, i, count;
- uint fifo;
- struct brcms_txq_info *qi = wlc->pkt_queue;
- struct pktq *q = &qi->q;
- struct ieee80211_tx_info *tx_info;
+ struct dma_pub *dma;
+ int fifo, ret = -ENOSPC;
+ struct d11txh *txh;
+ u16 frameid = INVALIDFID;
- prec_map = wlc->tx_prec_map;
+ fifo = brcms_ac_to_fifo(skb_get_queue_mapping(skb));
+ dma = wlc->hw->di[fifo];
+ txh = (struct d11txh *)(skb->data);
- /* Send all the enq'd pkts that we can.
- * Dequeue packets with precedence with empty HW fifo only
- */
- while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
- tx_info = IEEE80211_SKB_CB(pkt[0]);
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
- } else {
- count = 1;
- err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
- if (!err) {
- for (i = 0; i < count; i++)
- brcms_c_txfifo(wlc, fifo, pkt[i], true,
- 1);
- }
- }
-
- if (err == -EBUSY) {
- brcmu_pktq_penq_head(q, prec, pkt[0]);
- /*
- * If send failed due to any other reason than a
- * change in HW FIFO condition, quit. Otherwise,
- * read the new prec_map!
- */
- if (prec_map == wlc->tx_prec_map)
- break;
- prec_map = wlc->tx_prec_map;
- }
+ if (dma->txavail == 0) {
+ /*
+ * We sometimes get a frame from mac80211 after stopping
+ * the queues. This only ever seems to be a single frame
+ * and is seems likely to be a race. TX_HEADROOM should
+ * ensure that we have enough space to handle these stray
+ * packets, so warn if there isn't. If we're out of space
+ * in the tx ring and the tx queue isn't stopped then
+ * we've really got a bug; warn loudly if that happens.
+ */
+ brcms_warn(wlc->hw->d11core,
+ "Received frame for tx with no space in DMA ring\n");
+ WARN_ON(!ieee80211_queue_stopped(wlc->pub->ieee_hw,
+ skb_get_queue_mapping(skb)));
+ return -ENOSPC;
}
-}
-
-void
-brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
- bool commit, s8 txpktpend)
-{
- u16 frameid = INVALIDFID;
- struct d11txh *txh;
-
- txh = (struct d11txh *) (p->data);
/* When a BC/MC frame is being committed to the BCMC fifo
* via DMA (NOT PIO), update ucode or BSS info as appropriate.
@@ -7353,16 +6904,6 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
if (fifo == TX_BCMC_FIFO)
frameid = le16_to_cpu(txh->TxFrameID);
- /*
- * Bump up pending count for if not using rpc. If rpc is
- * used, this will be handled in brcms_b_txfifo()
- */
- if (commit) {
- wlc->core->txpktpend[fifo] += txpktpend;
- BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
- txpktpend, wlc->core->txpktpend[fifo]);
- }
-
/* Commit BCMC sequence number in the SHM frame ID location */
if (frameid != INVALIDFID) {
/*
@@ -7372,8 +6913,55 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid);
}
- if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0)
+ ret = brcms_c_txfifo(wlc, fifo, skb);
+ /*
+ * The only reason for brcms_c_txfifo to fail is because
+ * there weren't any DMA descriptors, but we've already
+ * checked for that. So if it does fail yell loudly.
+ */
+ WARN_ON_ONCE(ret);
+
+ return ret;
+}
+
+bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+ struct ieee80211_hw *hw)
+{
+ uint fifo;
+ struct scb *scb = &wlc->pri_scb;
+
+ fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu));
+ brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0);
+ if (!brcms_c_tx(wlc, sdu))
+ return true;
+
+ /* packet discarded */
+ dev_kfree_skb_any(sdu);
+ return false;
+}
+
+int
+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p)
+{
+ struct dma_pub *dma = wlc->hw->di[fifo];
+ int ret;
+ u16 queue;
+
+ ret = dma_txfast(wlc, dma, p);
+ if (ret < 0)
wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+
+ /*
+ * Stop queue if DMA ring is full. Reserve some free descriptors,
+ * as we sometimes receive a frame from mac80211 after the queues
+ * are stopped.
+ */
+ queue = skb_get_queue_mapping(p);
+ if (dma->txavail <= TX_HEADROOM && fifo < TX_BCMC_FIFO &&
+ !ieee80211_queue_stopped(wlc->pub->ieee_hw, queue))
+ ieee80211_stop_queue(wlc->pub->ieee_hw, queue);
+
+ return ret;
}
u32
@@ -7423,19 +7011,6 @@ brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
return rts_rspec;
}
-void
-brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
-{
- wlc->core->txpktpend[fifo] -= txpktpend;
- BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
- wlc->core->txpktpend[fifo]);
-
- /* There is more room; mark precedences related to this FIFO sendable */
- wlc->tx_prec_map |= wlc->fifo2prec_map[fifo];
-
- /* figure out which bsscfg is being worked on... */
-}
-
/* Update beacon listen interval in shared memory */
static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
{
@@ -7508,7 +7083,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
/* fill in TSF and flag its presence */
rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh);
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
@@ -7571,7 +7146,8 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
rx_status->rate_idx = 11;
break;
default:
- wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
+ brcms_err(wlc->hw->d11core,
+ "%s: Unknown rate\n", __func__);
}
/*
@@ -7590,7 +7166,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
} else if (is_ofdm_rate(rspec)) {
rx_status->flag |= RX_FLAG_SHORTPRE;
} else {
- wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
+ brcms_err(wlc->hw->d11core, "%s: Unknown modulation\n",
__func__);
}
}
@@ -7600,12 +7176,12 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
if (rxh->RxStatus1 & RXS_DECERR) {
rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
- wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n",
+ brcms_err(wlc->hw->d11core, "%s: RX_FLAG_FAILED_PLCP_CRC\n",
__func__);
}
if (rxh->RxStatus1 & RXS_FCSERR) {
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n",
+ brcms_err(wlc->hw->d11core, "%s: RX_FLAG_FAILED_FCS_CRC\n",
__func__);
}
}
@@ -7649,9 +7225,6 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
{
uint nsyms, len = 0, kNdps;
- BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
- wlc->pub->unit, rspec2rate(ratespec), mac_len);
-
if (is_mcs_rate(ratespec)) {
uint mcs = ratespec & RSPEC_RATE_MASK;
int tot_streams = (mcs_2_txstreams(mcs) + 1) +
@@ -7883,35 +7456,6 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
}
-/* prepares pdu for transmission. returns BCM error codes */
-int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
-{
- uint fifo;
- struct d11txh *txh;
- struct ieee80211_hdr *h;
- struct scb *scb;
-
- txh = (struct d11txh *) (pdu->data);
- h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
- /* get the pkt queue info. This was put at brcms_c_sendctl or
- * brcms_c_send for PDU */
- fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
-
- scb = NULL;
-
- *fifop = fifo;
-
- /* return if insufficient dma resources */
- if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) {
- /* Mark precedences related to this FIFO, unsendable */
- /* A fifo is full. Clear precedences related to that FIFO */
- wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]);
- return -EBUSY;
- }
- return 0;
-}
-
int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
uint *blocks)
{
@@ -7977,13 +7521,15 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
{
int timeout = 20;
+ int i;
- /* flush packet queue when requested */
- if (drop)
- brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+ /* Kick DMA to send any pending AMPDU */
+ for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+ if (wlc->hw->di[i])
+ dma_txflush(wlc->hw->di[i]);
/* wait for queue and DMA fifos to run dry */
- while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
+ while (brcms_txpktpendtot(wlc) > 0) {
brcms_msleep(wlc->wl, 1);
if (--timeout == 0)
@@ -8032,8 +7578,6 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
uint len;
bool is_amsdu;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
/* frame starts with rxhdr */
rxh = (struct d11rxhdr *) (p->data);
@@ -8043,8 +7587,9 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
if (rxh->RxStatus1 & RXS_PBPRES) {
if (p->len < 2) {
- wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
- "len %d\n", wlc->pub->unit, p->len);
+ brcms_err(wlc->hw->d11core,
+ "wl%d: recv: rcvd runt of len %d\n",
+ wlc->pub->unit, p->len);
goto toss;
}
skb_pull(p, 2);
@@ -8088,17 +7633,19 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
uint n = 0;
uint bound_limit = bound ? RXBND : -1;
+ bool morepending;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
skb_queue_head_init(&recv_frames);
/* gather received frames */
- while (dma_rx(wlc_hw->di[fifo], &recv_frames)) {
-
+ do {
/* !give others some time to run! */
- if (++n >= bound_limit)
+ if (n >= bound_limit)
break;
- }
+
+ morepending = dma_rx(wlc_hw->di[fifo], &recv_frames);
+ n++;
+ } while (morepending);
/* post more rbufs */
dma_rxfill(wlc_hw->di[fifo]);
@@ -8128,7 +7675,7 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
brcms_c_recv(wlc_hw->wlc, p);
}
- return n >= bound_limit;
+ return morepending;
}
/* second-level interrupt processing
@@ -8140,10 +7687,9 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
u32 macintstatus;
struct brcms_hardware *wlc_hw = wlc->hw;
struct bcma_device *core = wlc_hw->d11core;
- struct wiphy *wiphy = wlc->wiphy;
if (brcms_deviceremoved(wlc)) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
__func__);
brcms_down(wlc->wl);
return false;
@@ -8153,8 +7699,8 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
macintstatus = wlc->macintstatus;
wlc->macintstatus = 0;
- BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
- wlc_hw->unit, macintstatus);
+ brcms_dbg_int(core, "wl%d: macintstatus 0x%x\n",
+ wlc_hw->unit, macintstatus);
WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
@@ -8164,7 +7710,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
wlc->macintstatus |= MI_TFS;
if (fatal) {
- wiphy_err(wiphy, "MI_TFS: fatal\n");
+ brcms_err(core, "MI_TFS: fatal\n");
goto fatal;
}
}
@@ -8174,7 +7720,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
/* ATIM window end */
if (macintstatus & MI_ATIMWINEND) {
- BCMMSG(wlc->wiphy, "end of ATIM window\n");
+ brcms_dbg_info(core, "end of ATIM window\n");
bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid);
wlc->qvalid = 0;
}
@@ -8192,7 +7738,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
wlc_phy_noise_sample_intr(wlc_hw->band->pi);
if (macintstatus & MI_GP0) {
- wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
+ brcms_err(core, "wl%d: PSM microcode watchdog fired at %d "
"(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
@@ -8206,15 +7752,11 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
bcma_write32(core, D11REGOFFS(gptimer), 0);
if (macintstatus & MI_RFDISABLE) {
- BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
- " RF Disable Input\n", wlc_hw->unit);
+ brcms_dbg_info(core, "wl%d: BMAC Detected a change on the"
+ " RF Disable Input\n", wlc_hw->unit);
brcms_rfkill_set_hw_state(wlc->wl);
}
- /* send any enq'd tx packets. Just makes sure to jump start tx */
- if (!pktq_empty(&wlc->pkt_queue->q))
- brcms_c_send_q(wlc);
-
/* it isn't done and needs to be resched if macintstatus is non-zero */
return wlc->macintstatus != 0;
@@ -8229,7 +7771,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
u16 chanspec;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
chanspec = ch20mhz_chspec(ch->hw_value);
@@ -8286,9 +7828,6 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF);
brcms_c_edcf_setparams(wlc, false);
- /* Init precedence maps for empty FIFOs */
- brcms_c_tx_prec_map_init(wlc);
-
/* read the ucode version if we have not yet done so */
if (wlc->ucode_rev == 0) {
wlc->ucode_rev =
@@ -8303,9 +7842,6 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
if (mute_tx)
brcms_b_mute(wlc->hw, true);
- /* clear tx flow control */
- brcms_c_txflowcontrol_reset(wlc);
-
/* enable the RF Disable Delay timer */
bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT);
@@ -8464,15 +8000,6 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
* Complete the wlc default state initializations..
*/
- /* allocate our initial queue */
- wlc->pkt_queue = brcms_c_txq_alloc(wlc);
- if (wlc->pkt_queue == NULL) {
- wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
- unit, __func__);
- err = 100;
- goto fail;
- }
-
wlc->bsscfg->wlc = wlc;
wlc->mimoft = FT_HT;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 8debc74c54e1..fb447747c2c6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -101,9 +101,6 @@
#define DATA_BLOCK_TX_SUPR (1 << 4)
-/* 802.1D Priority to TX FIFO number for wme */
-extern const u8 prio2fifo[];
-
/* Ucode MCTL_WAKE override bits */
#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01
#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02
@@ -242,7 +239,6 @@ struct brcms_core {
/* fifo */
uint *txavail[NFIFO]; /* # tx descriptors available */
- s16 txpktpend[NFIFO]; /* tx admission control */
struct macstat *macstat_snapshot; /* mac hw prev read values */
};
@@ -382,19 +378,6 @@ struct brcms_hardware {
*/
};
-/* TX Queue information
- *
- * Each flow of traffic out of the device has a TX Queue with independent
- * flow control. Several interfaces may be associated with a single TX Queue
- * if they belong to the same flow of traffic from the device. For multi-channel
- * operation there are independent TX Queues for each channel.
- */
-struct brcms_txq_info {
- struct brcms_txq_info *next;
- struct pktq q;
- uint stopped; /* tx flow control bits */
-};
-
/*
* Principal common driver data structure.
*
@@ -435,11 +418,8 @@ struct brcms_txq_info {
* WDlast: last time wlc_watchdog() was called.
* edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
* wme_retries: per-AC retry limits.
- * tx_prec_map: Precedence map based on HW FIFO space.
- * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
* bsscfg: set of BSS configurations, idx 0 is default and always valid.
* cfg: the primary bsscfg (can be AP or STA).
- * tx_queues: common TX Queue list.
* modulecb:
* mimoft: SIGN or 11N.
* cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode.
@@ -469,7 +449,6 @@ struct brcms_txq_info {
* tempsense_lasttime;
* tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM.
* tx_duty_cycle_cck: maximum allowed duty cycle for CCK.
- * pkt_queue: txq for transmit packets.
* wiphy:
* pri_scb: primary Station Control Block
*/
@@ -533,14 +512,9 @@ struct brcms_c_info {
u16 edcf_txop[IEEE80211_NUM_ACS];
u16 wme_retries[IEEE80211_NUM_ACS];
- u16 tx_prec_map;
- u16 fifo2prec_map[NFIFO];
struct brcms_bss_cfg *bsscfg;
- /* tx queue */
- struct brcms_txq_info *tx_queues;
-
struct modulecb *modulecb;
u8 mimoft;
@@ -585,7 +559,6 @@ struct brcms_c_info {
u16 tx_duty_cycle_ofdm;
u16 tx_duty_cycle_cck;
- struct brcms_txq_info *pkt_queue;
struct wiphy *wiphy;
struct scb pri_scb;
};
@@ -637,30 +610,13 @@ struct brcms_bss_cfg {
struct brcms_bss_info *current_bss;
};
-extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
- struct sk_buff *p,
- bool commit, s8 txpktpend);
-extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
- s8 txpktpend);
-extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
- struct sk_buff *sdu, uint prec);
-extern void brcms_c_print_txstatus(struct tx_status *txs);
+extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
+ struct sk_buff *p);
extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
uint *blocks);
-#if defined(DEBUG)
-extern void brcms_c_print_txdesc(struct d11txh *txh);
-#else
-static inline void brcms_c_print_txdesc(struct d11txh *txh)
-{
-}
-#endif
-
extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
-extern void brcms_c_send_q(struct brcms_c_info *wlc);
-extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
- uint *fifo);
extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
uint mac_len);
extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
index abfd78822fb8..606b534347bc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1137,8 +1137,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
gain0_15 = ((biq1 & 0xf) << 12) |
((tia & 0xf) << 8) |
((lna2 & 0x3) << 6) |
- ((lna2 &
- 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+ ((lna2 & 0x3) << 4) |
+ ((lna1 & 0x3) << 2) |
+ ((lna1 & 0x3) << 0);
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1156,6 +1157,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
}
mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+ mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
}
@@ -1328,6 +1331,43 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
}
+static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
+ u16 tia_gain, u16 lna2_gain)
+{
+ u32 i_thresh_l, q_thresh_l;
+ u32 i_thresh_h, q_thresh_h;
+ struct lcnphy_iq_est iq_est_h, iq_est_l;
+
+ wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
+ lna2_gain, 0);
+
+ wlc_lcnphy_rx_gain_override_enable(pi, true);
+ wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
+ usleep_range(500, 500);
+ write_radio_reg(pi, RADIO_2064_REG112, 0);
+ if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
+ return false;
+
+ wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
+ usleep_range(500, 500);
+ write_radio_reg(pi, RADIO_2064_REG112, 0);
+ if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
+ return false;
+
+ i_thresh_l = (iq_est_l.i_pwr << 1);
+ i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
+
+ q_thresh_l = (iq_est_l.q_pwr << 1);
+ q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
+ if ((iq_est_h.i_pwr > i_thresh_l) &&
+ (iq_est_h.i_pwr < i_thresh_h) &&
+ (iq_est_h.q_pwr > q_thresh_l) &&
+ (iq_est_h.q_pwr < q_thresh_h))
+ return true;
+
+ return false;
+}
+
static bool
wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1342,8 +1382,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
rfoverride3_old, rfoverride3val_old, rfoverride4_old,
rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
- int tia_gain;
- u32 received_power, rx_pwr_threshold;
+ int tia_gain, lna2_gain, biq1_gain;
+ bool set_gain;
u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
u16 values_to_save[11];
s16 *ptr;
@@ -1368,126 +1408,134 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
goto cal_done;
}
- if (module == 1) {
+ WARN_ON(module != 1);
+ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
- tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+ for (i = 0; i < 11; i++)
+ values_to_save[i] =
+ read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+ Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+ or_phy_reg(pi, 0x631, 0x0015);
+
+ RFOverride0_old = read_phy_reg(pi, 0x44c);
+ RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+ rfoverride2_old = read_phy_reg(pi, 0x4b0);
+ rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+ rfoverride3_old = read_phy_reg(pi, 0x4f9);
+ rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+ rfoverride4_old = read_phy_reg(pi, 0x938);
+ rfoverride4val_old = read_phy_reg(pi, 0x939);
+ afectrlovr_old = read_phy_reg(pi, 0x43b);
+ afectrlovrval_old = read_phy_reg(pi, 0x43c);
+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
- for (i = 0; i < 11; i++)
- values_to_save[i] =
- read_radio_reg(pi, rxiq_cal_rf_reg[i]);
- Core1TxControl_old = read_phy_reg(pi, 0x631);
-
- or_phy_reg(pi, 0x631, 0x0015);
-
- RFOverride0_old = read_phy_reg(pi, 0x44c);
- RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
- rfoverride2_old = read_phy_reg(pi, 0x4b0);
- rfoverride2val_old = read_phy_reg(pi, 0x4b1);
- rfoverride3_old = read_phy_reg(pi, 0x4f9);
- rfoverride3val_old = read_phy_reg(pi, 0x4fa);
- rfoverride4_old = read_phy_reg(pi, 0x938);
- rfoverride4val_old = read_phy_reg(pi, 0x939);
- afectrlovr_old = read_phy_reg(pi, 0x43b);
- afectrlovrval_old = read_phy_reg(pi, 0x43c);
- old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
- old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
- tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
- if (tx_gain_override_old) {
- wlc_lcnphy_get_tx_gain(pi, &old_gains);
- tx_gain_index_old = pi_lcn->lcnphy_current_index;
- }
+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+ if (tx_gain_override_old) {
+ wlc_lcnphy_get_tx_gain(pi, &old_gains);
+ tx_gain_index_old = pi_lcn->lcnphy_current_index;
+ }
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
- mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
- mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
- write_radio_reg(pi, RADIO_2064_REG116, 0x06);
- write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
- write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
- write_radio_reg(pi, RADIO_2064_REG098, 0x03);
- write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
- mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
- write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
- write_radio_reg(pi, RADIO_2064_REG114, 0x01);
- write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
- write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
- mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
- mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
- mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
- wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
- write_phy_reg(pi, 0x6da, 0xffff);
- or_phy_reg(pi, 0x6db, 0x3);
- wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
- wlc_lcnphy_rx_gain_override_enable(pi, true);
-
- tia_gain = 8;
- rx_pwr_threshold = 950;
- while (tia_gain > 0) {
- tia_gain -= 1;
- wlc_lcnphy_set_rx_gain_by_distribution(pi,
- 0, 0, 2, 2,
- (u16)
- tia_gain, 1, 0);
- udelay(500);
+ write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+ write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+ write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+ write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+ write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+ write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
- received_power =
- wlc_lcnphy_measure_digital_power(pi, 2000);
- if (received_power < rx_pwr_threshold)
- break;
+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+ write_phy_reg(pi, 0x6da, 0xffff);
+ or_phy_reg(pi, 0x6db, 0x3);
+
+ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+ set_gain = false;
+
+ lna2_gain = 3;
+ while ((lna2_gain >= 0) && !set_gain) {
+ tia_gain = 4;
+
+ while ((tia_gain >= 0) && !set_gain) {
+ biq1_gain = 6;
+
+ while ((biq1_gain >= 0) && !set_gain) {
+ set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
+ (u16)
+ biq1_gain,
+ (u16)
+ tia_gain,
+ (u16)
+ lna2_gain);
+ biq1_gain -= 1;
+ }
+ tia_gain -= 1;
}
- result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+ lna2_gain -= 1;
+ }
- wlc_lcnphy_stop_tx_tone(pi);
+ if (set_gain)
+ result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
+ else
+ result = false;
- write_phy_reg(pi, 0x631, Core1TxControl_old);
+ wlc_lcnphy_stop_tx_tone(pi);
- write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
- write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
- write_phy_reg(pi, 0x4b0, rfoverride2_old);
- write_phy_reg(pi, 0x4b1, rfoverride2val_old);
- write_phy_reg(pi, 0x4f9, rfoverride3_old);
- write_phy_reg(pi, 0x4fa, rfoverride3val_old);
- write_phy_reg(pi, 0x938, rfoverride4_old);
- write_phy_reg(pi, 0x939, rfoverride4val_old);
- write_phy_reg(pi, 0x43b, afectrlovr_old);
- write_phy_reg(pi, 0x43c, afectrlovrval_old);
- write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
- write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+ write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+ write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x4b0, rfoverride2_old);
+ write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+ write_phy_reg(pi, 0x4f9, rfoverride3_old);
+ write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+ write_phy_reg(pi, 0x938, rfoverride4_old);
+ write_phy_reg(pi, 0x939, rfoverride4val_old);
+ write_phy_reg(pi, 0x43b, afectrlovr_old);
+ write_phy_reg(pi, 0x43c, afectrlovrval_old);
+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
- wlc_lcnphy_clear_trsw_override(pi);
+ wlc_lcnphy_clear_trsw_override(pi);
- mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
- for (i = 0; i < 11; i++)
- write_radio_reg(pi, rxiq_cal_rf_reg[i],
- values_to_save[i]);
+ for (i = 0; i < 11; i++)
+ write_radio_reg(pi, rxiq_cal_rf_reg[i],
+ values_to_save[i]);
- if (tx_gain_override_old)
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
- else
- wlc_lcnphy_disable_tx_gain_override(pi);
+ if (tx_gain_override_old)
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+ else
+ wlc_lcnphy_disable_tx_gain_override(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
- wlc_lcnphy_rx_gain_override_enable(pi, false);
- }
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+ wlc_lcnphy_rx_gain_override_enable(pi, false);
cal_done:
kfree(ptr);
@@ -1781,6 +1829,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
write_radio_reg(pi, RADIO_2064_REG038, 3);
write_radio_reg(pi, RADIO_2064_REG091, 7);
}
+
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
+ 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
+
+ write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
+ write_radio_reg(pi, RADIO_2064_REG091, 0x3);
+ write_radio_reg(pi, RADIO_2064_REG038, 0x3);
+
+ write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
+ }
}
static int
@@ -1860,41 +1919,6 @@ wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
return (filt_index != -1) ? 0 : -1;
}
-void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
-{
- u8 channel = CHSPEC_CHANNEL(chanspec);
-
- wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
-
- wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
-
- or_phy_reg(pi, 0x44a, 0x44);
- write_phy_reg(pi, 0x44a, 0x80);
-
- wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
- udelay(1000);
-
- wlc_lcnphy_toggle_afe_pwdn(pi);
-
- write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
- write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
-
- if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
- wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
- } else {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
- wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
- }
-
- wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
-
- mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-
-}
-
static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
{
u16 pa_gain;
@@ -1936,6 +1960,21 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
wlc_lcnphy_enable_tx_gain_override(pi);
}
+static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
+{
+ u16 m0m1;
+ struct phytbl_info tab;
+
+ tab.tbl_ptr = &m0m1;
+ tab.tbl_len = 1;
+ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+ tab.tbl_offset = 87;
+ tab.tbl_width = 16;
+ wlc_lcnphy_read_table(pi, &tab);
+
+ return (u8) ((m0m1 & 0xff00) >> 8);
+}
+
static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0)
{
u16 m0m1 = (u16) m0 << 8;
@@ -1995,6 +2034,16 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
} else {
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
+ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
+ mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
+ mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
}
} else {
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2081,12 +2130,14 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+ mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
}
static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
{
struct phytbl_info tab;
u32 rfseq, ind;
+ u8 tssi_sel;
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
tab.tbl_width = 32;
@@ -2108,7 +2159,13 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
- wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+ if (pi->sh->boardflags & BFL_FEM) {
+ tssi_sel = 0x1;
+ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+ } else {
+ tssi_sel = 0xe;
+ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
+ }
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2144,9 +2201,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
} else {
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
}
@@ -2193,6 +2251,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+ mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+
wlc_lcnphy_pwrctrl_rssiparams(pi);
}
@@ -2811,6 +2873,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
read_radio_reg(pi, RADIO_2064_REG007) & 1;
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+ u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
+
idleTssi = read_phy_reg(pi, 0x4ab);
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
@@ -2828,6 +2892,12 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
wlc_lcnphy_tssi_setup(pi);
+
+ mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
+ mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
+
+ wlc_lcnphy_set_bbmult(pi, 0x0);
+
wlc_phy_do_dummy_tx(pi, true, OFF);
idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
>> 0);
@@ -2849,6 +2919,7 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+ wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
wlc_lcnphy_set_tx_gain(pi, &old_gains);
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3062,6 +3133,11 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
wlc_lcnphy_write_table(pi, &tab);
tab.tbl_offset++;
}
+ mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
+ mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
+ mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
+ mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
+ mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
@@ -3075,21 +3151,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
wlapi_enable_mac(pi->sh->physhim);
}
-static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
-{
- u16 m0m1;
- struct phytbl_info tab;
-
- tab.tbl_ptr = &m0m1;
- tab.tbl_len = 1;
- tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
- tab.tbl_offset = 87;
- tab.tbl_width = 16;
- wlc_lcnphy_read_table(pi, &tab);
-
- return (u8) ((m0m1 & 0xff00) >> 8);
-}
-
static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain)
{
mod_phy_reg(pi, 0x4fb,
@@ -3878,7 +3939,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
target_gains.pad_gain = 21;
target_gains.dac_gain = 0;
wlc_lcnphy_set_tx_gain(pi, &target_gains);
- wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
@@ -3889,6 +3949,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
lcnphy_recal ? LCNPHY_CAL_RECAL :
LCNPHY_CAL_FULL), false);
} else {
+ wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
@@ -4313,17 +4374,22 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
if (CHSPEC_IS5G(pi->radio_chanspec))
pa_gain = 0x70;
else
- pa_gain = 0x70;
+ pa_gain = 0x60;
if (pi->sh->boardflags & BFL_FEM)
pa_gain = 0x10;
+
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
tab.tbl_width = 32;
tab.tbl_len = 1;
tab.tbl_ptr = &val;
for (j = 0; j < 128; j++) {
- gm_gain = gain_table[j].gm;
+ if (pi->sh->boardflags & BFL_FEM)
+ gm_gain = gain_table[j].gm;
+ else
+ gm_gain = 15;
+
val = (((u32) pa_gain << 24) |
(gain_table[j].pad << 16) |
(gain_table[j].pga << 8) | gm_gain);
@@ -4534,7 +4600,10 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
write_phy_reg(pi, 0x4ea, 0x4688);
- mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+ if (pi->sh->boardflags & BFL_FEM)
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+ else
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
@@ -4545,6 +4614,13 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
wlc_lcnphy_rcal(pi);
wlc_lcnphy_rc_cal(pi);
+
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
+ write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+ write_radio_reg(pi, RADIO_2064_REG039, 0xe);
+ }
+
}
static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4574,22 +4650,20 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
wlc_lcnphy_write_table(pi, &tab);
}
- tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
- tab.tbl_width = 16;
- tab.tbl_ptr = &val;
- tab.tbl_len = 1;
-
- val = 114;
- tab.tbl_offset = 0;
- wlc_lcnphy_write_table(pi, &tab);
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+ tab.tbl_width = 16;
+ tab.tbl_ptr = &val;
+ tab.tbl_len = 1;
- val = 130;
- tab.tbl_offset = 1;
- wlc_lcnphy_write_table(pi, &tab);
+ val = 150;
+ tab.tbl_offset = 0;
+ wlc_lcnphy_write_table(pi, &tab);
- val = 6;
- tab.tbl_offset = 8;
- wlc_lcnphy_write_table(pi, &tab);
+ val = 220;
+ tab.tbl_offset = 1;
+ wlc_lcnphy_write_table(pi, &tab);
+ }
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (pi->sh->boardflags & BFL_FEM)
@@ -4946,6 +5020,44 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
}
}
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
+{
+ u8 channel = CHSPEC_CHANNEL(chanspec);
+
+ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec);
+
+ wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
+
+ or_phy_reg(pi, 0x44a, 0x44);
+ write_phy_reg(pi, 0x44a, 0x80);
+
+ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+ udelay(1000);
+
+ wlc_lcnphy_toggle_afe_pwdn(pi);
+
+ write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
+ write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
+
+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+ wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
+ } else {
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+ wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
+ }
+
+ if (pi->sh->boardflags & BFL_FEM)
+ wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
+ else
+ wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
+
+ mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+ wlc_lcnphy_tssi_setup(pi);
+}
+
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
{
kfree(pi->u.pi_lcnphy);
@@ -4982,8 +5094,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
return false;
- if ((pi->sh->boardflags & BFL_FEM) &&
- (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
if (pi_lcn->lcnphy_tempsense_option == 3) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
index 622c01ca72c5..b7e95acc2084 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
};
static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
- 0x000a,
0x0009,
- 0x0006,
- 0x0005,
0x000a,
- 0x0009,
- 0x0006,
0x0005,
- 0x000a,
- 0x0009,
0x0006,
- 0x0005,
- 0x000a,
0x0009,
- 0x0006,
- 0x0005,
0x000a,
- 0x0009,
- 0x0006,
0x0005,
- 0x000a,
- 0x0009,
0x0006,
- 0x0005,
- 0x000a,
0x0009,
- 0x0006,
- 0x0005,
0x000a,
- 0x0009,
- 0x0006,
0x0005,
- 0x000a,
- 0x0009,
0x0006,
- 0x0005,
- 0x000a,
0x0009,
- 0x0006,
- 0x0005,
0x000a,
- 0x0009,
- 0x0006,
0x0005,
- 0x000a,
- 0x0009,
0x0006,
- 0x0005,
+ 0x0009,
0x000a,
+ 0x0005,
+ 0x0006,
0x0009,
+ 0x000a,
+ 0x0005,
0x0006,
+ 0x0009,
+ 0x000a,
0x0005,
+ 0x0006,
+ 0x0009,
0x000a,
+ 0x0005,
+ 0x0006,
0x0009,
+ 0x000a,
+ 0x0005,
0x0006,
+ 0x0009,
+ 0x000a,
0x0005,
+ 0x0006,
+ 0x0009,
0x000a,
+ 0x0005,
+ 0x0006,
0x0009,
+ 0x000a,
+ 0x0005,
0x0006,
+ 0x0009,
+ 0x000a,
0x0005,
+ 0x0006,
+ 0x0009,
0x000a,
+ 0x0005,
+ 0x0006,
0x0009,
+ 0x000a,
+ 0x0005,
0x0006,
+ 0x0009,
+ 0x000a,
0x0005,
+ 0x0006,
};
static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 5855f4fd16dc..4fb2834f4e64 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -176,6 +176,7 @@ struct brcms_pub {
bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */
struct wl_cnt *_cnt; /* low-level counters in driver */
+ struct dentry *dbgfs_dir;
};
enum wlc_par_id {
@@ -200,43 +201,6 @@ enum wlc_par_id {
/* WL11N Support */
#define AMPDU_AGG_HOST 1
-/* pri is priority encoded in the packet. This maps the Packet priority to
- * enqueue precedence as defined in wlc_prec_map
- */
-extern const u8 wlc_prio2prec_map[];
-#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7]
-
-#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */
-
-/* Mask to describe all precedence levels */
-#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT)
-
-/*
- * This maps priority to one precedence higher - Used by PS-Poll response
- * packets to simulate enqueue-at-head operation, but still maintain the
- * order on the queue
- */
-#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\
- BRCMS_PREC_COUNT - 1)
-
-/* Define a bitmap of precedences comprised by each AC */
-#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \
- NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
-#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \
- NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
-#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \
- NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
-#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \
- NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \
- NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
-
/* network protection config */
#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */
#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */
@@ -319,9 +283,9 @@ extern void brcms_c_intrson(struct brcms_c_info *wlc);
extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
-extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc);
+extern bool brcms_c_isr(struct brcms_c_info *wlc);
extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
-extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
+extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
struct sk_buff *sdu,
struct ieee80211_hw *hw);
extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
index ed1d1aa71d2d..dd9162722495 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
@@ -23,6 +23,7 @@
#include "channel.h"
#include "main.h"
#include "stf.h"
+#include "debug.h"
#define MIN_SPATIAL_EXPANSION 0
#define MAX_SPATIAL_EXPANSION 1
@@ -160,8 +161,8 @@ bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
u8 core_mask)
{
- BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
- wlc->pub->unit, Nsts, core_mask);
+ brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n",
+ wlc->pub->unit, Nsts, core_mask);
if (hweight8(core_mask) > wlc->stf->txstreams)
core_mask = 0;
@@ -194,7 +195,8 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
int i;
u8 core_mask = 0;
- BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
+ brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit,
+ val);
wlc->stf->spatial_policy = (s8) val;
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/types.h b/drivers/net/wireless/brcm80211/brcmsmac/types.h
index e11ae83111e4..ae1f3ad40d45 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/types.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/types.h
@@ -246,7 +246,7 @@
#define BCMMSG(dev, fmt, args...) \
do { \
- if (brcm_msg_level & LOG_TRACE_VAL) \
+ if (brcm_msg_level & BRCM_DL_INFO) \
wiphy_err(dev, "%s: " fmt, __func__, ##args); \
} while (0)
@@ -281,7 +281,6 @@ struct ieee80211_tx_queue_params;
struct brcms_info;
struct brcms_c_info;
struct brcms_hardware;
-struct brcms_txq_info;
struct brcms_band;
struct dma_pub;
struct si_pub;
diff --git a/drivers/net/wireless/brcm80211/include/defs.h b/drivers/net/wireless/brcm80211/include/defs.h
index f0d8c04a9c8c..fb7cbcf81179 100644
--- a/drivers/net/wireless/brcm80211/include/defs.h
+++ b/drivers/net/wireless/brcm80211/include/defs.h
@@ -78,9 +78,14 @@
#define PM_OFF 0
#define PM_MAX 1
-/* Message levels */
-#define LOG_ERROR_VAL 0x00000001
-#define LOG_TRACE_VAL 0x00000002
+/* Debug levels */
+#define BRCM_DL_INFO 0x00000001
+#define BRCM_DL_MAC80211 0x00000002
+#define BRCM_DL_RX 0x00000004
+#define BRCM_DL_TX 0x00000008
+#define BRCM_DL_INT 0x00000010
+#define BRCM_DL_DMA 0x00000020
+#define BRCM_DL_HT 0x00000040
#define PM_OFF 0
#define PM_MAX 1
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index df7050abe717..d39e3e24077b 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -415,7 +415,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
ssid = pos + 2;
ssid_len = pos[1];
break;
- case WLAN_EID_GENERIC:
+ case WLAN_EID_VENDOR_SPECIFIC:
if (pos[1] >= 4 &&
pos[2] == 0x00 && pos[3] == 0x50 &&
pos[4] == 0xf2 && pos[5] == 1) {
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 29b8fa1adefd..d92b21a8e597 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1788,10 +1788,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
}
/* Initialize the geo */
- if (libipw_set_geo(priv->ieee, &ipw_geos[0])) {
- printk(KERN_WARNING DRV_NAME "Could not set geo\n");
- return 0;
- }
+ libipw_set_geo(priv->ieee, &ipw_geos[0]);
priv->ieee->freq_band = LIBIPW_24GHZ_BAND;
lock = LOCK_NONE;
@@ -6413,7 +6410,7 @@ out:
goto out;
}
-static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
+static void ipw2100_pci_remove_one(struct pci_dev *pci_dev)
{
struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
struct net_device *dev = priv->net_dev;
@@ -6609,7 +6606,7 @@ static struct pci_driver ipw2100_pci_driver = {
.name = DRV_NAME,
.id_table = ipw2100_pci_id_table,
.probe = ipw2100_pci_init_one,
- .remove = __devexit_p(ipw2100_pci_remove_one),
+ .remove = ipw2100_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ipw2100_suspend,
.resume = ipw2100_resume,
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h
index 973125242490..5fe17cbab1f3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.h
+++ b/drivers/net/wireless/ipw2x00/ipw2100.h
@@ -1045,7 +1045,7 @@ typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW
IPW_ORD_POWER_MGMT_MODE, // Power mode - 0=CAM, 1=PSP
IPW_ORD_POWER_MGMT_INDEX, //NS //
IPW_ORD_COUNTRY_CODE, // IEEE country code as recv'd from beacon
- IPW_ORD_COUNTRY_CHANNELS, // channels suported by country
+ IPW_ORD_COUNTRY_CHANNELS, // channels supported by country
// IPW_ORD_COUNTRY_CHANNELS:
// For 11b the lower 2-byte are used for channels from 1-14
// and the higher 2-byte are not used.
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 768bf612533e..844f201b7b70 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -6812,7 +6812,6 @@ static int ipw_wx_get_auth(struct net_device *dev,
struct libipw_device *ieee = priv->ieee;
struct lib80211_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
- int ret = 0;
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
@@ -6822,8 +6821,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
/*
* wpa_supplicant will control these internally
*/
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
case IW_AUTH_TKIP_COUNTERMEASURES:
crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
@@ -10774,7 +10772,7 @@ static void ipw_bg_link_down(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
-static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv)
+static int ipw_setup_deferred_work(struct ipw_priv *priv)
{
int ret = 0;
@@ -11269,10 +11267,31 @@ static const struct libipw_geo ipw_geos[] = {
}
};
+static void ipw_set_geo(struct ipw_priv *priv)
+{
+ int j;
+
+ for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
+ if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
+ ipw_geos[j].name, 3))
+ break;
+ }
+
+ if (j == ARRAY_SIZE(ipw_geos)) {
+ IPW_WARNING("SKU [%c%c%c] not recognized.\n",
+ priv->eeprom[EEPROM_COUNTRY_CODE + 0],
+ priv->eeprom[EEPROM_COUNTRY_CODE + 1],
+ priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
+ j = 0;
+ }
+
+ libipw_set_geo(priv->ieee, &ipw_geos[j]);
+}
+
#define MAX_HW_RESTARTS 5
static int ipw_up(struct ipw_priv *priv)
{
- int rc, i, j;
+ int rc, i;
/* Age scan list entries found before suspend */
if (priv->suspend_time) {
@@ -11310,22 +11329,7 @@ static int ipw_up(struct ipw_priv *priv)
memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN);
- for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
- if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
- ipw_geos[j].name, 3))
- break;
- }
- if (j == ARRAY_SIZE(ipw_geos)) {
- IPW_WARNING("SKU [%c%c%c] not recognized.\n",
- priv->eeprom[EEPROM_COUNTRY_CODE + 0],
- priv->eeprom[EEPROM_COUNTRY_CODE + 1],
- priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
- j = 0;
- }
- if (libipw_set_geo(priv->ieee, &ipw_geos[j])) {
- IPW_WARNING("Could not set geography.");
- return 0;
- }
+ ipw_set_geo(priv);
if (priv->status & STATUS_RF_KILL_SW) {
IPW_WARNING("Radio disabled by module parameter.\n");
@@ -11722,7 +11726,7 @@ static const struct net_device_ops ipw_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit ipw_pci_probe(struct pci_dev *pdev,
+static int ipw_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int err = 0;
@@ -11895,7 +11899,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
return err;
}
-static void __devexit ipw_pci_remove(struct pci_dev *pdev)
+static void ipw_pci_remove(struct pci_dev *pdev)
{
struct ipw_priv *priv = pci_get_drvdata(pdev);
struct list_head *p, *q;
@@ -12057,7 +12061,7 @@ static struct pci_driver ipw_driver = {
.name = DRV_NAME,
.id_table = card_ids,
.probe = ipw_pci_probe,
- .remove = __devexit_p(ipw_pci_remove),
+ .remove = ipw_pci_remove,
#ifdef CONFIG_PM
.suspend = ipw_pci_suspend,
.resume = ipw_pci_resume,
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index 0b22fb421735..6eede52ad8c0 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -978,7 +978,7 @@ extern void libipw_network_reset(struct libipw_network *network);
/* libipw_geo.c */
extern const struct libipw_geo *libipw_get_geo(struct libipw_device
*ieee);
-extern int libipw_set_geo(struct libipw_device *ieee,
+extern void libipw_set_geo(struct libipw_device *ieee,
const struct libipw_geo *geo);
extern int libipw_is_valid_channel(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c
index c9fe3c99cb00..218f2a32de21 100644
--- a/drivers/net/wireless/ipw2x00/libipw_geo.c
+++ b/drivers/net/wireless/ipw2x00/libipw_geo.c
@@ -132,7 +132,7 @@ u8 libipw_freq_to_channel(struct libipw_device * ieee, u32 freq)
return 0;
}
-int libipw_set_geo(struct libipw_device *ieee,
+void libipw_set_geo(struct libipw_device *ieee,
const struct libipw_geo *geo)
{
memcpy(ieee->geo.name, geo->name, 3);
@@ -143,7 +143,6 @@ int libipw_set_geo(struct libipw_device *ieee,
sizeof(struct libipw_channel));
memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
sizeof(struct libipw_channel));
- return 0;
}
const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee)
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index 02e057923236..95a1ca1e895c 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1108,7 +1108,7 @@ static const char *get_info_element_string(u16 id)
MFIE_STRING(ERP_INFO);
MFIE_STRING(RSN);
MFIE_STRING(EXT_SUPP_RATES);
- MFIE_STRING(GENERIC);
+ MFIE_STRING(VENDOR_SPECIFIC);
MFIE_STRING(QOS_PARAMETER);
default:
return "UNKNOWN";
@@ -1248,8 +1248,8 @@ static int libipw_parse_info_param(struct libipw_info_element
LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n");
break;
- case WLAN_EID_GENERIC:
- LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n",
+ case WLAN_EID_VENDOR_SPECIFIC:
+ LIBIPW_DEBUG_MGMT("WLAN_EID_VENDOR_SPECIFIC: %d bytes\n",
info_element->len);
if (!libipw_parse_qos_info_param_IE(info_element,
network))
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index e252acb9c862..d604b4036a76 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -3794,7 +3794,7 @@ out:
return err;
}
-static void __devexit
+static void
il3945_pci_remove(struct pci_dev *pdev)
{
struct il_priv *il = pci_get_drvdata(pdev);
@@ -3884,7 +3884,7 @@ static struct pci_driver il3945_driver = {
.name = DRV_NAME,
.id_table = il3945_hw_card_ids,
.probe = il3945_pci_probe,
- .remove = __devexit_p(il3945_pci_remove),
+ .remove = il3945_pci_remove,
.driver.pm = IL_LEGACY_PM_OPS,
};
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index 87e539894330..e0b9d7fa5de0 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -516,7 +516,7 @@ static void
il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
{
struct ieee80211_hdr *header;
- struct ieee80211_rx_status rx_status;
+ struct ieee80211_rx_status rx_status = {};
struct il_rx_pkt *pkt = rxb_addr(rxb);
struct il3945_rx_frame_stats *rx_stats = IL_RX_STATS(pkt);
struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index eac4dc8bc879..c3fbf6717564 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -613,7 +613,7 @@ void
il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
{
struct ieee80211_hdr *header;
- struct ieee80211_rx_status rx_status;
+ struct ieee80211_rx_status rx_status = {};
struct il_rx_pkt *pkt = rxb_addr(rxb);
struct il_rx_phy_res *phy_res;
__le32 rx_pkt_status;
@@ -686,7 +686,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
/* TSF isn't reliable. In order to allow smooth user experience,
* this W/A doesn't propagate it to the mac80211 */
- /*rx_status.flag |= RX_FLAG_MACTIME_MPDU; */
+ /*rx_status.flag |= RX_FLAG_MACTIME_START; */
il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
@@ -6664,7 +6664,7 @@ out:
return err;
}
-static void __devexit
+static void
il4965_pci_remove(struct pci_dev *pdev)
{
struct il_priv *il = pci_get_drvdata(pdev);
@@ -6772,7 +6772,7 @@ static struct pci_driver il4965_driver = {
.name = DRV_NAME,
.id_table = il4965_hw_card_ids,
.probe = il4965_pci_probe,
- .remove = __devexit_p(il4965_pci_remove),
+ .remove = il4965_pci_remove,
.driver.pm = IL_LEGACY_PM_OPS,
};
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 2d092f328547..1b15b0b2292b 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -917,10 +917,6 @@ struct il4965_scd_bc_tbl {
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
-
#define IL4965_DEFAULT_TX_RETRY 15
/* EEPROM */
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 318ed3c9fe74..7e16d10a7f14 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -1183,9 +1183,10 @@ EXPORT_SYMBOL(il_power_update_mode);
void
il_power_initialize(struct il_priv *il)
{
- u16 lctl = il_pcie_link_ctl(il);
+ u16 lctl;
- il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+ pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+ il->power_data.pci_pm = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
il->power_data.debug_sleep_level_override = -1;
@@ -4233,9 +4234,8 @@ il_apm_init(struct il_priv *il)
* power savings, even without L1.
*/
if (il->cfg->set_l0s) {
- lctl = il_pcie_link_ctl(il);
- if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
- PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+ pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+ if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
/* L1-ASPM enabled; disable(!) L0S */
il_set_bit(il, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED);
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index b4bb813362bd..a9a569f432fb 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1829,14 +1829,6 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
* PCI *
*****************************************************/
-static inline u16
-il_pcie_link_ctl(struct il_priv *il)
-{
- u16 pci_lnk_ctl;
- pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl);
- return pci_lnk_ctl;
-}
-
void il_bg_watchdog(unsigned long data);
u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval);
__le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
@@ -2434,10 +2426,6 @@ struct il_tfd {
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
-
struct il_rate_info {
u8 plcp; /* uCode API: RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: RATE_SISO_6M_PLCP, etc. */
@@ -2919,9 +2907,8 @@ do { \
#define IL_DBG(level, fmt, args...) \
do { \
if (il_get_debug_level(il) & level) \
- dev_printk(KERN_ERR, &il->hw->wiphy->dev, \
- "%c %s " fmt, in_interrupt() ? 'I' : 'U', \
- __func__ , ## args); \
+ dev_err(&il->hw->wiphy->dev, "%c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __func__ , ##args); \
} while (0)
#define il_print_hex_dump(il, level, p, len) \
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 727fbb5db9da..5cf43236421e 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -133,12 +133,3 @@ config IWLWIFI_P2P
support when it is loaded.
Say Y only if you want to experiment with P2P.
-
-config IWLWIFI_EXPERIMENTAL_MFP
- bool "support MFP (802.11w) even if uCode doesn't advertise"
- depends on IWLWIFI
- help
- This option enables experimental MFP (802.11W) support
- even if the microcode doesn't advertise it.
-
- Say Y only if you want to experiment with MFP.
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 75e12f29d9eb..33b3ad2e546b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -176,8 +176,8 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
-int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
-void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
+int iwlagn_txfifo_flush(struct iwl_priv *priv);
+void iwlagn_dev_txfifo_flush(struct iwl_priv *priv);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear);
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c
index f2dd671d7dc8..de54713b680c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/calib.c
@@ -833,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* To be safe, simply mask out any chains that we know
* are not on the device.
*/
- active_chains &= priv->eeprom_data->valid_rx_ant;
+ active_chains &= priv->nvm_data->valid_rx_ant;
num_tx_chains = 0;
for (i = 0; i < NUM_RX_CHAINS; i++) {
/* loops on all the bits of
* priv->hw_setting.valid_tx_ant */
u8 ant_msk = (1 << i);
- if (!(priv->eeprom_data->valid_tx_ant & ant_msk))
+ if (!(priv->nvm_data->valid_tx_ant & ant_msk))
continue;
num_tx_chains++;
@@ -854,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* connect the first valid tx chain
*/
first_chain =
- find_first_chain(priv->eeprom_data->valid_tx_ant);
+ find_first_chain(priv->nvm_data->valid_tx_ant);
data->disconn_array[first_chain] = 0;
active_chains |= BIT(first_chain);
IWL_DEBUG_CALIB(priv,
@@ -864,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
}
}
- if (active_chains != priv->eeprom_data->valid_rx_ant &&
+ if (active_chains != priv->nvm_data->valid_rx_ant &&
active_chains != priv->chain_noise_data.active_chains)
IWL_DEBUG_CALIB(priv,
"Detected that not all antennas are connected! "
"Connected: %#x, valid: %#x.\n",
active_chains,
- priv->eeprom_data->valid_rx_ant);
+ priv->nvm_data->valid_rx_ant);
/* Save for use within RXON, TX, SCAN commands, etc. */
data->active_chains = active_chains;
@@ -1055,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
priv->cfg->bt_params->advanced_bt_coexist) {
/* Disable disconnected antenna algorithm for advanced
bt coex, assuming valid antennas are connected */
- data->active_chains = priv->eeprom_data->valid_rx_ant;
+ data->active_chains = priv->nvm_data->valid_rx_ant;
for (i = 0; i < NUM_RX_CHAINS; i++)
if (!(data->active_chains & (1<<i)))
data->disconn_array[i] = 1;
@@ -1086,7 +1086,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
iwlagn_gain_computation(
priv, average_noise,
- find_first_chain(priv->eeprom_data->valid_rx_ant));
+ find_first_chain(priv->nvm_data->valid_rx_ant));
/* Some power changes may have been made during the calibration.
* Update and commit the RXON
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 01128c96b5d8..71ab76b2b39d 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -986,8 +986,7 @@ struct iwl_rem_sta_cmd {
#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)
-#define IWL_DROP_SINGLE 0
-#define IWL_DROP_ALL (BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
+#define IWL_DROP_ALL BIT(1)
/*
* REPLY_TXFIFO_FLUSH = 0x1e(command and response)
@@ -1004,14 +1003,14 @@ struct iwl_rem_sta_cmd {
* the flush operation ends when both the scheduler DMA done and TXFIFO empty
* are set.
*
- * @fifo_control: bit mask for which queues to flush
+ * @queue_control: bit mask for which queues to flush
* @flush_control: flush controls
* 0: Dump single MSDU
* 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
* 2: Dump all FIFO
*/
struct iwl_txfifo_flush_cmd {
- __le32 fifo_control;
+ __le32 queue_control;
__le16 flush_control;
__le16 reserved;
} __packed;
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index 1a98fa3ab06d..5b9533eef54d 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -305,7 +305,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
int pos = 0, ofs = 0, buf_size = 0;
const u8 *ptr;
char *buf;
- u16 eeprom_ver;
+ u16 nvm_ver;
size_t eeprom_len = priv->eeprom_blob_size;
buf_size = 4 * eeprom_len + 256;
@@ -321,9 +321,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
if (!buf)
return -ENOMEM;
- eeprom_ver = priv->eeprom_data->eeprom_version;
+ nvm_ver = priv->nvm_data->nvm_version;
pos += scnprintf(buf + pos, buf_size - pos,
- "NVM version: 0x%x\n", eeprom_ver);
+ "NVM version: 0x%x\n", nvm_ver);
for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
@@ -1333,17 +1333,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
pos += scnprintf(buf + pos, bufsz - pos,
"tx power: (1/2 dB step)\n");
- if ((priv->eeprom_data->valid_tx_ant & ANT_A) &&
+ if ((priv->nvm_data->valid_tx_ant & ANT_A) &&
tx->tx_power.ant_a)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna A:",
tx->tx_power.ant_a);
- if ((priv->eeprom_data->valid_tx_ant & ANT_B) &&
+ if ((priv->nvm_data->valid_tx_ant & ANT_B) &&
tx->tx_power.ant_b)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna B:",
tx->tx_power.ant_b);
- if ((priv->eeprom_data->valid_tx_ant & ANT_C) &&
+ if ((priv->nvm_data->valid_tx_ant & ANT_C) &&
tx->tx_power.ant_c)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna C:",
@@ -2101,7 +2101,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (iwl_is_rfkill(priv))
return -EFAULT;
- iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
+ iwlagn_dev_txfifo_flush(priv);
return count;
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 8141f91c3725..2653a891cc7e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -789,7 +789,6 @@ struct iwl_priv {
/* remain-on-channel offload support */
struct ieee80211_channel *hw_roc_channel;
struct delayed_work hw_roc_disable_work;
- enum nl80211_channel_type hw_roc_chantype;
int hw_roc_duration;
bool hw_roc_setup, hw_roc_start_notified;
@@ -844,7 +843,7 @@ struct iwl_priv {
void *wowlan_sram;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
- struct iwl_eeprom_data *eeprom_data;
+ struct iwl_nvm_data *nvm_data;
/* eeprom blob for debugfs/testmode */
u8 *eeprom_blob;
size_t eeprom_blob_size;
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index da5862064195..8c72be3f37c1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -305,8 +305,8 @@ static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
{
u16 temperature, voltage;
- temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature);
- voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage);
+ temperature = le16_to_cpu(priv->nvm_data->kelvin_temperature);
+ voltage = le16_to_cpu(priv->nvm_data->kelvin_voltage);
/* offset = temp - volt / coeff */
return (s32)(temperature -
@@ -460,13 +460,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
break;
case IWL_DEVICE_FAMILY_6050:
/* Indicate calibration version to uCode. */
- if (priv->eeprom_data->calib_version >= 6)
+ if (priv->nvm_data->calib_version >= 6)
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
break;
case IWL_DEVICE_FAMILY_6150:
/* Indicate calibration version to uCode. */
- if (priv->eeprom_data->calib_version >= 6)
+ if (priv->nvm_data->calib_version >= 6)
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index bef88c1a2c9b..6ff46605ad4f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -59,7 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
/* half dBm need to multiply */
tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
- if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) {
+ if (tx_power_cmd.global_lmt > priv->nvm_data->max_tx_pwr_half_dbm) {
/*
* For the newer devices which using enhanced/extend tx power
* table in EEPROM, the format is in half dBm. driver need to
@@ -72,7 +72,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
* half-dBm format), lower the tx power based on EEPROM
*/
tx_power_cmd.global_lmt =
- priv->eeprom_data->max_tx_pwr_half_dbm;
+ priv->nvm_data->max_tx_pwr_half_dbm;
}
tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
-int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
+int iwlagn_txfifo_flush(struct iwl_priv *priv)
{
struct iwl_txfifo_flush_cmd flush_cmd;
struct iwl_host_cmd cmd = {
@@ -146,35 +146,34 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
.data = { &flush_cmd, },
};
- might_sleep();
-
memset(&flush_cmd, 0, sizeof(flush_cmd));
- if (flush_control & BIT(IWL_RXON_CTX_BSS))
- flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
- IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
- IWL_SCD_MGMT_MSK;
- if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
- (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
- flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
- IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
- IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
- IWL_PAN_SCD_MULTICAST_MSK;
-
- if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
- flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
-
- IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
- flush_cmd.fifo_control);
- flush_cmd.flush_control = cpu_to_le16(flush_control);
+
+ flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+ IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+ IWL_SCD_MGMT_MSK;
+ if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+ flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK |
+ IWL_PAN_SCD_VI_MSK |
+ IWL_PAN_SCD_BE_MSK |
+ IWL_PAN_SCD_BK_MSK |
+ IWL_PAN_SCD_MGMT_MSK |
+ IWL_PAN_SCD_MULTICAST_MSK;
+
+ if (priv->nvm_data->sku_cap_11n_enable)
+ flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
+
+ IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
+ flush_cmd.queue_control);
+ flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
return iwl_dvm_send_cmd(priv, &cmd);
}
-void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
+void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
- if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -826,7 +825,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (priv->chain_noise_data.active_chains)
active_chains = priv->chain_noise_data.active_chains;
else
- active_chains = priv->eeprom_data->valid_rx_ant;
+ active_chains = priv->nvm_data->valid_rx_ant;
if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist &&
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 2d9eee93c743..3163e0f38c25 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -164,14 +164,17 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
*/
- if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (priv->nvm_data->sku_cap_11n_enable)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
-#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP
- /* enable 11w if the uCode advertise */
- if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
-#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
+ /*
+ * Enable 11w if advertised by firmware and software crypto
+ * is not enabled (as the firmware will interpret some mgmt
+ * packets, so enabling it with software crypto isn't safe)
+ */
+ if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP &&
+ !iwlwifi_mod_params.sw_crypto)
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
hw->sta_data_size = sizeof(struct iwl_station_priv);
@@ -239,12 +242,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
- if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels)
+ if (priv->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels)
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
- &priv->eeprom_data->bands[IEEE80211_BAND_2GHZ];
- if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels)
+ &priv->nvm_data->bands[IEEE80211_BAND_2GHZ];
+ if (priv->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels)
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &priv->eeprom_data->bands[IEEE80211_BAND_5GHZ];
+ &priv->nvm_data->bands[IEEE80211_BAND_5GHZ];
hw->wiphy->hw_version = priv->trans->hw_id;
@@ -651,7 +654,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE))
+ if (!(priv->nvm_data->sku_cap_11n_enable))
return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1019,7 +1022,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
- if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
+ if (iwlagn_txfifo_flush(priv)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -1032,8 +1035,8 @@ done:
}
static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
- enum nl80211_channel_type channel_type,
int duration)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1065,7 +1068,6 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
}
priv->hw_roc_channel = channel;
- priv->hw_roc_chantype = channel_type;
/* convert from ms to TU */
priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
priv->hw_roc_start_notified = false;
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 408132cf83c1..faa05932efae 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -185,7 +185,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
rate = info->control.rates[0].idx;
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
- priv->eeprom_data->valid_tx_ant);
+ priv->nvm_data->valid_tx_ant);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
/* In mac80211, rates for 5 GHz start at 0 */
@@ -511,7 +511,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
return;
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
- iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
+ iwlagn_dev_txfifo_flush(priv);
}
/*
@@ -776,7 +776,7 @@ int iwl_alive_start(struct iwl_priv *priv)
ieee80211_wake_queues(priv->hw);
/* Configure Tx antenna selection based on H/W config */
- iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant);
+ iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant);
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
struct iwl_rxon_cmd *active_rxon =
@@ -1191,36 +1191,38 @@ static void iwl_option_config(struct iwl_priv *priv)
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
- u16 radio_cfg;
+ struct iwl_nvm_data *data = priv->nvm_data;
+ char *debug_msg;
- priv->eeprom_data->sku = priv->eeprom_data->sku;
-
- if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+ if (data->sku_cap_11n_enable &&
!priv->cfg->ht_params) {
IWL_ERR(priv, "Invalid 11n configuration\n");
return -EINVAL;
}
- if (!priv->eeprom_data->sku) {
+ if (!data->sku_cap_11n_enable && !data->sku_cap_band_24GHz_enable &&
+ !data->sku_cap_band_52GHz_enable) {
IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL;
}
- IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
-
- radio_cfg = priv->eeprom_data->radio_cfg;
+ debug_msg = "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n";
+ IWL_DEBUG_INFO(priv, debug_msg,
+ data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled",
+ data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled",
+ data->sku_cap_11n_enable ? "" : "NOT", "enabled");
priv->hw_params.tx_chains_num =
- num_of_ant(priv->eeprom_data->valid_tx_ant);
+ num_of_ant(data->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1;
else
priv->hw_params.rx_chains_num =
- num_of_ant(priv->eeprom_data->valid_rx_ant);
+ num_of_ant(data->valid_rx_ant);
- IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
- priv->eeprom_data->valid_tx_ant,
- priv->eeprom_data->valid_rx_ant);
+ IWL_DEBUG_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
+ data->valid_tx_ant,
+ data->valid_rx_ant);
return 0;
}
@@ -1235,7 +1237,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
struct iwl_op_mode *op_mode;
u16 num_mac;
u32 ucode_flags;
- struct iwl_trans_config trans_cfg;
+ struct iwl_trans_config trans_cfg = {};
static const u8 no_reclaim_cmds[] = {
REPLY_RX_PHY_CMD,
REPLY_RX_MPDU_CMD,
@@ -1334,6 +1336,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/* Configure transport layer */
iwl_trans_configure(priv->trans, &trans_cfg);
+ trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+ trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
+
/* At this point both hw and priv are allocated. */
SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
@@ -1377,24 +1382,24 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(priv->trans, false);
- priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
+ priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
priv->eeprom_blob,
priv->eeprom_blob_size);
- if (!priv->eeprom_data)
+ if (!priv->nvm_data)
goto out_free_eeprom_blob;
- if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans))
+ if (iwl_nvm_check_version(priv->nvm_data, priv->trans))
goto out_free_eeprom;
if (iwl_eeprom_init_hw_params(priv))
goto out_free_eeprom;
/* extract MAC Address */
- memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN);
+ memcpy(priv->addresses[0].addr, priv->nvm_data->hw_addr, ETH_ALEN);
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
priv->hw->wiphy->addresses = priv->addresses;
priv->hw->wiphy->n_addresses = 1;
- num_mac = priv->eeprom_data->n_hw_addrs;
+ num_mac = priv->nvm_data->n_hw_addrs;
if (num_mac > 1) {
memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
ETH_ALEN);
@@ -1407,7 +1412,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
************************/
iwl_set_hw_params(priv);
- if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
+ if (!(priv->nvm_data->sku_cap_ipan_enable)) {
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
/*
@@ -1489,7 +1494,7 @@ out_destroy_workqueue:
out_free_eeprom_blob:
kfree(priv->eeprom_blob);
out_free_eeprom:
- iwl_free_eeprom_data(priv->eeprom_data);
+ iwl_free_nvm_data(priv->nvm_data);
out_free_hw:
ieee80211_free_hw(priv->hw);
out:
@@ -1508,12 +1513,8 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
iwl_tt_exit(priv);
- /*This will stop the queues, move the device to low power state */
- priv->ucode_loaded = false;
- iwl_trans_stop_device(priv->trans);
-
kfree(priv->eeprom_blob);
- iwl_free_eeprom_data(priv->eeprom_data);
+ iwl_free_nvm_data(priv->nvm_data);
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
@@ -1927,8 +1928,6 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
* commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->status);
- wake_up(&priv->trans->wait_command_queue);
-
if (!ondemand) {
/*
* If firmware keep reloading, then it indicate something
@@ -1989,7 +1988,6 @@ static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
static void iwl_nic_config(struct iwl_op_mode *op_mode)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
- u16 radio_cfg = priv->eeprom_data->radio_cfg;
/* SKU Control */
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
@@ -2001,13 +1999,13 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
/* write radio config values to register */
- if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
+ if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
u32 reg_val =
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <<
+ priv->nvm_data->radio_cfg_type <<
CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE |
- EEPROM_RF_CFG_STEP_MSK(radio_cfg) <<
+ priv->nvm_data->radio_cfg_step <<
CSR_HW_IF_CONFIG_REG_POS_PHY_STEP |
- EEPROM_RF_CFG_DASH_MSK(radio_cfg) <<
+ priv->nvm_data->radio_cfg_dash <<
CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
@@ -2016,9 +2014,9 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val);
IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
- EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
- EEPROM_RF_CFG_STEP_MSK(radio_cfg),
- EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+ priv->nvm_data->radio_cfg_type,
+ priv->nvm_data->radio_cfg_step,
+ priv->nvm_data->radio_cfg_dash);
} else {
WARN_ON(1);
}
@@ -2152,8 +2150,6 @@ static int __init iwl_init(void)
{
int ret;
- pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
- pr_info(DRV_COPYRIGHT "\n");
ret = iwlagn_rate_control_register();
if (ret) {
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index a82f46c10f5e..f3dd0da60d8a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -820,7 +820,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if (num_of_ant(tbl->ant_type) > 1)
tbl->ant_type =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
tbl->is_ht40 = 0;
tbl->is_SGI = 0;
@@ -1448,7 +1448,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ u8 valid_tx_ant = priv->nvm_data->valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret = 0;
u8 update_search_tbl_counter = 0;
@@ -1466,7 +1466,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */
valid_tx_ant =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
tbl->action != IWL_LEGACY_SWITCH_SISO)
tbl->action = IWL_LEGACY_SWITCH_SISO;
@@ -1490,7 +1490,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_SISO;
valid_tx_ant =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
}
start_action = tbl->action;
@@ -1624,7 +1624,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ u8 valid_tx_ant = priv->nvm_data->valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
@@ -1642,7 +1642,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */
valid_tx_ant =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break;
@@ -1660,7 +1660,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
/* configure as 1x1 if bt full concurrency */
if (priv->bt_full_concurrent) {
valid_tx_ant =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
}
@@ -1796,7 +1796,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ u8 valid_tx_ant = priv->nvm_data->valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
@@ -1966,7 +1966,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ u8 valid_tx_ant = priv->nvm_data->valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret;
u8 update_search_tbl_counter = 0;
@@ -2700,7 +2700,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
i = lq_sta->last_txrate_idx;
- valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ valid_tx_ant = priv->nvm_data->valid_tx_ant;
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
@@ -2894,15 +2894,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
/* These values will be overridden later */
lq_sta->lq.general_params.single_stream_ant_msk =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
lq_sta->lq.general_params.dual_stream_ant_msk =
- priv->eeprom_data->valid_tx_ant &
- ~first_antenna(priv->eeprom_data->valid_tx_ant);
+ priv->nvm_data->valid_tx_ant &
+ ~first_antenna(priv->nvm_data->valid_tx_ant);
if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) {
+ } else if (num_of_ant(priv->nvm_data->valid_tx_ant) == 2) {
lq_sta->lq.general_params.dual_stream_ant_msk =
- priv->eeprom_data->valid_tx_ant;
+ priv->nvm_data->valid_tx_ant;
}
/* as default allow aggregation for all tids */
@@ -2948,7 +2948,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv && priv->bt_full_concurrent) {
/* 1x1 only */
tbl_type.ant_type =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
}
/* How many times should we repeat the initial rate? */
@@ -2980,7 +2980,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv->bt_full_concurrent)
valid_tx_ant = ANT_A;
else
- valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ valid_tx_ant = priv->nvm_data->valid_tx_ant;
}
/* Fill rest of rate table */
@@ -3014,7 +3014,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv && priv->bt_full_concurrent) {
/* 1x1 only */
tbl_type.ant_type =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
}
/* Indicate to uCode which entries might be MIMO.
@@ -3101,7 +3101,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u8 ant_sel_tx;
priv = lq_sta->drv;
- valid_tx_ant = priv->eeprom_data->valid_tx_ant;
+ valid_tx_ant = priv->nvm_data->valid_tx_ant;
if (lq_sta->dbg_fixed_rate) {
ant_sel_tx =
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
@@ -3172,9 +3172,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
- (priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "",
- (priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "",
- (priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : "");
+ (priv->nvm_data->valid_tx_ant & ANT_A) ? "ANT_A," : "",
+ (priv->nvm_data->valid_tx_ant & ANT_B) ? "ANT_B," : "",
+ (priv->nvm_data->valid_tx_ant & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(tbl->lq_type)) ? "legacy" : "HT");
if (is_Ht(tbl->lq_type)) {
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index 5a9c325804f6..cac4f37cc427 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -631,8 +631,6 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
test_bit(STATUS_RF_KILL_HW, &priv->status)))
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
test_bit(STATUS_RF_KILL_HW, &priv->status));
- else
- wake_up(&priv->trans->wait_command_queue);
return 0;
}
@@ -901,7 +899,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
struct iwl_device_cmd *cmd)
{
struct ieee80211_hdr *header;
- struct ieee80211_rx_status rx_status;
+ struct ieee80211_rx_status rx_status = {};
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rx_phy_res *phy_res;
__le32 rx_pkt_status;
@@ -951,7 +949,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
/* TSF isn't reliable. In order to allow smooth user experience,
* this W/A doesn't propagate it to the mac80211 */
- /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+ /*rx_status.flag |= RX_FLAG_MACTIME_START;*/
priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 2830ea290502..9a891e6e60e8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -420,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) {
+ if (tx_power > DIV_ROUND_UP(priv->nvm_data->max_tx_pwr_half_dbm, 2)) {
IWL_WARN(priv,
"Requested user TXPOWER %d above upper limit %d.\n",
- tx_power, priv->eeprom_data->max_tx_pwr_half_dbm);
+ tx_power, priv->nvm_data->max_tx_pwr_half_dbm);
return -EINVAL;
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index bb9f6252d28f..610ed2204e1f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -660,12 +660,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
u16 rx_chain = 0;
enum ieee80211_band band;
u8 n_probes = 0;
- u8 rx_ant = priv->eeprom_data->valid_rx_ant;
+ u8 rx_ant = priv->nvm_data->valid_rx_ant;
u8 rate;
bool is_active = false;
int chan_mod;
u8 active_chains;
- u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant;
+ u8 scan_tx_antennas = priv->nvm_data->valid_tx_ant;
int ret;
int scan_cmd_size = sizeof(struct iwl_scan_cmd) +
MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) +
@@ -673,8 +673,9 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
const u8 *ssid = NULL;
u8 ssid_len = 0;
- if (WARN_ON_ONCE(priv->scan_request &&
- priv->scan_request->n_channels > MAX_SCAN_CHANNEL))
+ if (WARN_ON(priv->scan_type == IWL_SCAN_NORMAL &&
+ (!priv->scan_request ||
+ priv->scan_request->n_channels > MAX_SCAN_CHANNEL)))
return -EINVAL;
lockdep_assert_held(&priv->mutex);
@@ -881,7 +882,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
/* MIMO is not used here, but value is required */
rx_chain |=
- priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+ priv->nvm_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
@@ -998,7 +999,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
void iwl_init_scan_params(struct iwl_priv *priv)
{
- u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1;
+ u8 ant_idx = fls(priv->nvm_data->valid_tx_ant) - 1;
if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c
index cd9b6de4273e..bdba9543c351 100644
--- a/drivers/net/wireless/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c
@@ -634,23 +634,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
- rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) <<
+ rate_flags |= first_antenna(priv->nvm_data->valid_tx_ant) <<
RATE_MCS_ANT_POS;
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
link_cmd->general_params.single_stream_ant_msk =
- first_antenna(priv->eeprom_data->valid_tx_ant);
+ first_antenna(priv->nvm_data->valid_tx_ant);
link_cmd->general_params.dual_stream_ant_msk =
- priv->eeprom_data->valid_tx_ant &
- ~first_antenna(priv->eeprom_data->valid_tx_ant);
+ priv->nvm_data->valid_tx_ant &
+ ~first_antenna(priv->nvm_data->valid_tx_ant);
if (!link_cmd->general_params.dual_stream_ant_msk) {
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) {
+ } else if (num_of_ant(priv->nvm_data->valid_tx_ant) == 2) {
link_cmd->general_params.dual_stream_ant_msk =
- priv->eeprom_data->valid_tx_ant;
+ priv->nvm_data->valid_tx_ant;
}
link_cmd->agg_params.agg_dis_start_th =
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index f5ca73a89870..da21328ca8ed 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -188,7 +188,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
rate_idx = rate_lowest_index(
- &priv->eeprom_data->bands[info->band], sta);
+ &priv->nvm_data->bands[info->band], sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
if (info->band == IEEE80211_BAND_5GHZ)
rate_idx += IWL_FIRST_OFDM_RATE;
@@ -207,11 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
priv->bt_full_concurrent) {
/* operated as 1x1 in full concurrency mode */
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
- first_antenna(priv->eeprom_data->valid_tx_ant));
+ first_antenna(priv->nvm_data->valid_tx_ant));
} else
priv->mgmt_tx_ant = iwl_toggle_tx_ant(
priv, priv->mgmt_tx_ant,
- priv->eeprom_data->valid_tx_ant);
+ priv->nvm_data->valid_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
/* Set the rate in the TX cmd */
@@ -305,7 +305,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
u8 hdr_len;
u16 len, seq_number = 0;
u8 sta_id, tid = IWL_MAX_TID_COUNT;
- bool is_agg = false;
+ bool is_agg = false, is_data_qos = false;
int txq_id;
if (info->control.vif)
@@ -378,9 +378,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
}
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
- is_agg = true;
-
dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans);
if (unlikely(!dev_cmd))
@@ -442,6 +439,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10;
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ is_agg = true;
+ is_data_qos = true;
}
/* Copy MAC header from skb into command buffer */
@@ -474,8 +475,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id))
goto drop_unlock_sta;
- if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) &&
- !ieee80211_has_morefrags(fc))
+ if (is_data_qos && !ieee80211_has_morefrags(fc))
priv->tid_data[sta_id][tid].seq_number = seq_number;
spin_unlock(&priv->sta_lock);
@@ -1075,14 +1075,11 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
static void iwlagn_set_tx_status(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
- struct iwlagn_tx_resp *tx_resp,
- bool is_agg)
+ struct iwlagn_tx_resp *tx_resp)
{
- u16 status = le16_to_cpu(tx_resp->status.status);
+ u16 status = le16_to_cpu(tx_resp->status.status);
info->status.rates[0].count = tx_resp->failure_frame + 1;
- if (is_agg)
- info->flags &= ~IEEE80211_TX_CTL_AMPDU;
info->flags |= iwl_tx_status_to_mac80211(status);
iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
info);
@@ -1100,29 +1097,6 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
}
}
-static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid,
- int txq_id, int ssn, struct sk_buff_head *skbs)
-{
- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
- tid != IWL_TID_NON_QOS &&
- txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) {
- /*
- * FIXME: this is a uCode bug which need to be addressed,
- * log the information and return for now.
- * Since it is can possibly happen very often and in order
- * not to fill the syslog, don't use IWL_ERR or IWL_WARN
- */
- IWL_DEBUG_TX_QUEUES(priv,
- "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n",
- txq_id, sta_id, tid,
- priv->tid_data[sta_id][tid].agg.txq_id);
- return 1;
- }
-
- iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs);
- return 0;
-}
-
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
@@ -1184,9 +1158,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
next_reclaimed);
}
- /*we can free until ssn % q.n_bd not inclusive */
- WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid,
- txq_id, ssn, &skbs));
+ iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
+
iwlagn_check_ratid_empty(priv, sta_id, tid);
freed = 0;
@@ -1231,7 +1204,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
if (is_agg && !iwl_is_tx_success(status))
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb),
- tx_resp, is_agg);
+ tx_resp);
if (!is_agg)
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
@@ -1311,16 +1284,27 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
return 0;
}
+ if (unlikely(scd_flow != agg->txq_id)) {
+ /*
+ * FIXME: this is a uCode bug which need to be addressed,
+ * log the information and return for now.
+ * Since it is can possibly happen very often and in order
+ * not to fill the syslog, don't use IWL_ERR or IWL_WARN
+ */
+ IWL_DEBUG_TX_QUEUES(priv,
+ "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n",
+ scd_flow, sta_id, tid, agg->txq_id);
+ spin_unlock(&priv->sta_lock);
+ return 0;
+ }
+
__skb_queue_head_init(&reclaimed_skbs);
/* Release all TFDs before the SSN, i.e. all TFDs in front of
* block-ack window (we assume that they've been successfully
* transmitted ... if not, it's too late anyway). */
- if (iwl_reclaim(priv, sta_id, tid, scd_flow,
- ba_resp_scd_ssn, &reclaimed_skbs)) {
- spin_unlock(&priv->sta_lock);
- return 0;
- }
+ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn,
+ &reclaimed_skbs);
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
"sta_id = %d\n",
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c
index 2cb1efbc5ed1..c6467e5554f5 100644
--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c
@@ -61,7 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type)
static int iwl_set_Xtal_calib(struct iwl_priv *priv)
{
struct iwl_calib_xtal_freq_cmd cmd;
- __le16 *xtal_calib = priv->eeprom_data->xtal_calib;
+ __le16 *xtal_calib = priv->nvm_data->xtal_calib;
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
@@ -75,7 +75,7 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
- cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature;
+ cmd.radio_sensor_offset = priv->nvm_data->raw_temperature;
if (!(cmd.radio_sensor_offset))
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
@@ -90,14 +90,14 @@ static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
- cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature;
- cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature;
+ cmd.radio_sensor_offset_high = priv->nvm_data->kelvin_temperature;
+ cmd.radio_sensor_offset_low = priv->nvm_data->raw_temperature;
if (!cmd.radio_sensor_offset_low) {
IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
}
- cmd.burntVoltageRef = priv->eeprom_data->calib_voltage;
+ cmd.burntVoltageRef = priv->nvm_data->calib_voltage;
IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
le16_to_cpu(cmd.radio_sensor_offset_high));
@@ -254,10 +254,10 @@ static int iwl_alive_notify(struct iwl_priv *priv)
int ret;
int i;
- iwl_trans_fw_alive(priv->trans);
+ iwl_trans_fw_alive(priv->trans, 0);
if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
- priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) {
+ priv->nvm_data->sku_cap_ipan_enable) {
n_queues = ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo);
queue_to_txf = iwlagn_ipan_queue_to_tx_fifo;
} else {
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 87f465a49df1..864219d2136a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -150,7 +150,7 @@ enum iwl_led_mode {
struct iwl_base_params {
int eeprom_size;
int num_of_queues; /* def: HW dependent */
- /* for iwl_apm_init() */
+ /* for iwl_pcie_apm_init() */
u32 pll_cfg_val;
const u16 max_ll_items;
@@ -226,8 +226,8 @@ struct iwl_eeprom_params {
* @max_data_size: The maximal length of the fw data section
* @valid_tx_ant: valid transmit antenna
* @valid_rx_ant: valid receive antenna
- * @eeprom_ver: EEPROM version
- * @eeprom_calib_ver: EEPROM calibration version
+ * @nvm_ver: NVM version
+ * @nvm_calib_ver: NVM calibration version
* @lib: pointer to the lib ops
* @base_params: pointer to basic parameters
* @ht_params: point to ht patameters
@@ -257,8 +257,8 @@ struct iwl_cfg {
const u32 max_inst_size;
u8 valid_tx_ant;
u8 valid_rx_ant;
- u16 eeprom_ver;
- u16 eeprom_calib_ver;
+ u16 nvm_ver;
+ u16 nvm_calib_ver;
/* params not likely to change within a device family */
const struct iwl_base_params *base_params;
/* params likely to change within a device family */
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 59a5f78402fc..dc7e26b2f383 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -25,6 +25,39 @@
*****************************************************************************/
#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include "iwl-trans.h"
+#if !defined(__IWLWIFI_DEVICE_TRACE)
+static inline bool iwl_trace_data(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+
+ if (ieee80211_is_data(hdr->frame_control))
+ return skb->protocol != cpu_to_be16(ETH_P_PAE);
+ return false;
+}
+
+static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
+ void *rxbuf, size_t len)
+{
+ struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32));
+ struct ieee80211_hdr *hdr;
+
+ if (cmd->cmd != trans->rx_mpdu_cmd)
+ return len;
+
+ hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) +
+ trans->rx_mpdu_cmd_hdr_size);
+ if (!ieee80211_is_data(hdr->frame_control))
+ return len;
+ /* maybe try to identify EAPOL frames? */
+ return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
+ ieee80211_hdrlen(hdr->frame_control);
+}
+#endif
+
#define __IWLWIFI_DEVICE_TRACE
#include <linux/tracepoint.h>
@@ -100,6 +133,40 @@ TRACE_EVENT(iwlwifi_dev_iowrite32,
__get_str(dev), __entry->offs, __entry->val)
);
+TRACE_EVENT(iwlwifi_dev_iowrite_prph32,
+ TP_PROTO(const struct device *dev, u32 offs, u32 val),
+ TP_ARGS(dev, offs, val),
+ TP_STRUCT__entry(
+ DEV_ENTRY
+ __field(u32, offs)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ DEV_ASSIGN;
+ __entry->offs = offs;
+ __entry->val = val;
+ ),
+ TP_printk("[%s] write PRPH[%#x] = %#x)",
+ __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_ioread_prph32,
+ TP_PROTO(const struct device *dev, u32 offs, u32 val),
+ TP_ARGS(dev, offs, val),
+ TP_STRUCT__entry(
+ DEV_ENTRY
+ __field(u32, offs)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ DEV_ASSIGN;
+ __entry->offs = offs;
+ __entry->val = val;
+ ),
+ TP_printk("[%s] read PRPH[%#x] = %#x",
+ __get_str(dev), __entry->offs, __entry->val)
+);
+
TRACE_EVENT(iwlwifi_dev_irq,
TP_PROTO(const struct device *dev),
TP_ARGS(dev),
@@ -235,6 +302,48 @@ TRACE_EVENT(iwlwifi_dbg,
);
#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_data
+
+TRACE_EVENT(iwlwifi_dev_tx_data,
+ TP_PROTO(const struct device *dev,
+ struct sk_buff *skb,
+ void *data, size_t data_len),
+ TP_ARGS(dev, skb, data, data_len),
+ TP_STRUCT__entry(
+ DEV_ENTRY
+
+ __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
+ ),
+ TP_fast_assign(
+ DEV_ASSIGN;
+ if (iwl_trace_data(skb))
+ memcpy(__get_dynamic_array(data), data, data_len);
+ ),
+ TP_printk("[%s] TX frame data", __get_str(dev))
+);
+
+TRACE_EVENT(iwlwifi_dev_rx_data,
+ TP_PROTO(const struct device *dev,
+ const struct iwl_trans *trans,
+ void *rxbuf, size_t len),
+ TP_ARGS(dev, trans, rxbuf, len),
+ TP_STRUCT__entry(
+ DEV_ENTRY
+
+ __dynamic_array(u8, data,
+ len - iwl_rx_trace_len(trans, rxbuf, len))
+ ),
+ TP_fast_assign(
+ size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
+ DEV_ASSIGN;
+ if (offs < len)
+ memcpy(__get_dynamic_array(data),
+ ((u8 *)rxbuf) + offs, len - offs);
+ ),
+ TP_printk("[%s] RX frame data", __get_str(dev))
+);
+
+#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
TRACE_EVENT(iwlwifi_dev_hcmd,
@@ -270,25 +379,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
);
TRACE_EVENT(iwlwifi_dev_rx,
- TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
- TP_ARGS(dev, rxbuf, len),
+ TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
+ void *rxbuf, size_t len),
+ TP_ARGS(dev, trans, rxbuf, len),
TP_STRUCT__entry(
DEV_ENTRY
- __dynamic_array(u8, rxbuf, len)
+ __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
),
TP_fast_assign(
DEV_ASSIGN;
- memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
+ memcpy(__get_dynamic_array(rxbuf), rxbuf,
+ iwl_rx_trace_len(trans, rxbuf, len));
),
TP_printk("[%s] RX cmd %#.2x",
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
);
TRACE_EVENT(iwlwifi_dev_tx,
- TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
+ TP_PROTO(const struct device *dev, struct sk_buff *skb,
+ void *tfd, size_t tfdlen,
void *buf0, size_t buf0_len,
void *buf1, size_t buf1_len),
- TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+ TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
TP_STRUCT__entry(
DEV_ENTRY
@@ -301,14 +413,15 @@ TRACE_EVENT(iwlwifi_dev_tx,
* for the possible padding).
*/
__dynamic_array(u8, buf0, buf0_len)
- __dynamic_array(u8, buf1, buf1_len)
+ __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->framelen = buf0_len + buf1_len;
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
- memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+ if (!iwl_trace_data(skb))
+ memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
),
TP_printk("[%s] TX %.2x (%zu bytes)",
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 198634b75ed0..d3549f493a17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1032,6 +1032,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
if (!drv->dbgfs_drv) {
IWL_ERR(drv, "failed to create debugfs directory\n");
+ ret = -ENOMEM;
goto err_free_drv;
}
@@ -1040,12 +1041,12 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
if (!drv->trans->dbgfs_dir) {
IWL_ERR(drv, "failed to create transport debugfs directory\n");
+ ret = -ENOMEM;
goto err_free_dbgfs;
}
#endif
ret = iwl_request_firmware(drv, true);
-
if (ret) {
IWL_ERR(trans, "Couldn't request the fw\n");
goto err_fw;
@@ -1060,9 +1061,8 @@ err_free_dbgfs:
err_free_drv:
#endif
kfree(drv);
- drv = NULL;
- return drv;
+ return ERR_PTR(ret);
}
void iwl_drv_stop(struct iwl_drv *drv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index f10170fe8799..471986690cf0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -116,6 +116,24 @@ struct iwl_eeprom_calib_hdr {
#define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
#define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL)
+/* SKU Capabilities (actual values from EEPROM definition) */
+enum eeprom_sku_bits {
+ EEPROM_SKU_CAP_BAND_24GHZ = BIT(4),
+ EEPROM_SKU_CAP_BAND_52GHZ = BIT(5),
+ EEPROM_SKU_CAP_11N_ENABLE = BIT(6),
+ EEPROM_SKU_CAP_AMT_ENABLE = BIT(7),
+ EEPROM_SKU_CAP_IPAN_ENABLE = BIT(8)
+};
+
+/* radio config bits (actual values from EEPROM definition) */
+#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
+#define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
+#define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
+#define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
+#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
+#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
+
+
/*
* EEPROM bands
* These are the channel numbers from each band in the order
@@ -251,7 +269,7 @@ static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
}
static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size,
- struct iwl_eeprom_data *data)
+ struct iwl_nvm_data *data)
{
struct iwl_eeprom_calib_hdr *hdr;
@@ -330,7 +348,7 @@ struct iwl_eeprom_enhanced_txpwr {
s8 mimo3_max;
} __packed;
-static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data,
+static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp)
{
s8 result = 0; /* (.5 dBm) */
@@ -364,7 +382,7 @@ static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data,
((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "")
static void
-iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data,
+iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp,
int n_channels, s8 max_txpower_avg)
{
@@ -392,7 +410,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data,
}
static void iwl_eeprom_enhanced_txpower(struct device *dev,
- struct iwl_eeprom_data *data,
+ struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size,
int n_channels)
{
@@ -504,7 +522,7 @@ static void iwl_init_band_reference(const struct iwl_cfg *cfg,
((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "")
static void iwl_mod_ht40_chan_info(struct device *dev,
- struct iwl_eeprom_data *data, int n_channels,
+ struct iwl_nvm_data *data, int n_channels,
enum ieee80211_band band, u16 channel,
const struct iwl_eeprom_channel *eeprom_ch,
u8 clear_ht40_extension_channel)
@@ -547,7 +565,7 @@ static void iwl_mod_ht40_chan_info(struct device *dev,
((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "")
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
- struct iwl_eeprom_data *data,
+ struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
int band, ch_idx;
@@ -685,7 +703,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
return n_channels;
}
-static int iwl_init_sband_channels(struct iwl_eeprom_data *data,
+static int iwl_init_sband_channels(struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband,
int n_channels, enum ieee80211_band band)
{
@@ -711,7 +729,7 @@ static int iwl_init_sband_channels(struct iwl_eeprom_data *data,
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
- struct iwl_eeprom_data *data,
+ struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band)
{
@@ -725,7 +743,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
else
rx_chains = hweight8(data->valid_rx_ant);
- if (!(data->sku & EEPROM_SKU_CAP_11N_ENABLE) || !cfg->ht_params) {
+ if (!(data->sku_cap_11n_enable) || !cfg->ht_params) {
ht_info->ht_supported = false;
return;
}
@@ -773,7 +791,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
}
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
- struct iwl_eeprom_data *data,
+ struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
int n_channels = iwl_init_channel_map(dev, cfg, data,
@@ -804,12 +822,13 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
/* EEPROM data functions */
-struct iwl_eeprom_data *
+struct iwl_nvm_data *
iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size)
{
- struct iwl_eeprom_data *data;
+ struct iwl_nvm_data *data;
const void *tmp;
+ u16 radio_cfg, sku;
if (WARN_ON(!cfg || !cfg->eeprom_params))
return NULL;
@@ -849,18 +868,27 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
data->kelvin_temperature = *(__le16 *)tmp;
data->kelvin_voltage = *((__le16 *)tmp + 1);
- data->radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size,
+ radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size,
EEPROM_RADIO_CONFIG);
- data->sku = iwl_eeprom_query16(eeprom, eeprom_size,
- EEPROM_SKU_CAP);
+ data->radio_cfg_dash = EEPROM_RF_CFG_DASH_MSK(radio_cfg);
+ data->radio_cfg_pnum = EEPROM_RF_CFG_PNUM_MSK(radio_cfg);
+ data->radio_cfg_step = EEPROM_RF_CFG_STEP_MSK(radio_cfg);
+ data->radio_cfg_type = EEPROM_RF_CFG_TYPE_MSK(radio_cfg);
+ data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+ data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+
+ sku = iwl_eeprom_query16(eeprom, eeprom_size,
+ EEPROM_SKU_CAP);
+ data->sku_cap_11n_enable = sku & EEPROM_SKU_CAP_11N_ENABLE;
+ data->sku_cap_amt_enable = sku & EEPROM_SKU_CAP_AMT_ENABLE;
+ data->sku_cap_band_24GHz_enable = sku & EEPROM_SKU_CAP_BAND_24GHZ;
+ data->sku_cap_band_52GHz_enable = sku & EEPROM_SKU_CAP_BAND_52GHZ;
+ data->sku_cap_ipan_enable = sku & EEPROM_SKU_CAP_IPAN_ENABLE;
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
- data->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
-
- data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size,
- EEPROM_VERSION);
+ data->sku_cap_11n_enable = false;
- data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(data->radio_cfg);
- data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(data->radio_cfg);
+ data->nvm_version = iwl_eeprom_query16(eeprom, eeprom_size,
+ EEPROM_VERSION);
/* check overrides (some devices have wrong EEPROM) */
if (cfg->valid_tx_ant)
@@ -884,20 +912,20 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data);
/* helper functions */
-int iwl_eeprom_check_version(struct iwl_eeprom_data *data,
+int iwl_nvm_check_version(struct iwl_nvm_data *data,
struct iwl_trans *trans)
{
- if (data->eeprom_version >= trans->cfg->eeprom_ver ||
- data->calib_version >= trans->cfg->eeprom_calib_ver) {
- IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n",
- data->eeprom_version, data->calib_version);
+ if (data->nvm_version >= trans->cfg->nvm_ver ||
+ data->calib_version >= trans->cfg->nvm_calib_ver) {
+ IWL_DEBUG_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+ data->nvm_version, data->calib_version);
return 0;
}
IWL_ERR(trans,
"Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
- data->eeprom_version, trans->cfg->eeprom_ver,
- data->calib_version, trans->cfg->eeprom_calib_ver);
+ data->nvm_version, trans->cfg->nvm_ver,
+ data->calib_version, trans->cfg->nvm_calib_ver);
return -EINVAL;
}
-EXPORT_SYMBOL_GPL(iwl_eeprom_check_version);
+EXPORT_SYMBOL_GPL(iwl_nvm_check_version);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
index a5e425718f56..555f0eb61d48 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
@@ -66,22 +66,7 @@
#include <linux/if_ether.h>
#include "iwl-trans.h"
-/* SKU Capabilities (actual values from EEPROM definition) */
-#define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
-#define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
-#define EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
-#define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7)
-#define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8)
-
-/* radio config bits (actual values from EEPROM definition) */
-#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
-#define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
-#define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
-#define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
-#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
-#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
-
-struct iwl_eeprom_data {
+struct iwl_nvm_data {
int n_hw_addrs;
u8 hw_addr[ETH_ALEN];
@@ -93,13 +78,21 @@ struct iwl_eeprom_data {
__le16 kelvin_voltage;
__le16 xtal_calib[2];
- u16 sku;
- u16 radio_cfg;
- u16 eeprom_version;
- s8 max_tx_pwr_half_dbm;
+ bool sku_cap_band_24GHz_enable;
+ bool sku_cap_band_52GHz_enable;
+ bool sku_cap_11n_enable;
+ bool sku_cap_amt_enable;
+ bool sku_cap_ipan_enable;
+ u8 radio_cfg_type;
+ u8 radio_cfg_step;
+ u8 radio_cfg_dash;
+ u8 radio_cfg_pnum;
u8 valid_tx_ant, valid_rx_ant;
+ u16 nvm_version;
+ s8 max_tx_pwr_half_dbm;
+
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels[];
};
@@ -115,22 +108,22 @@ struct iwl_eeprom_data {
* This function parses all EEPROM values we need and then
* returns a (newly allocated) struct containing all the
* relevant values for driver use. The struct must be freed
- * later with iwl_free_eeprom_data().
+ * later with iwl_free_nvm_data().
*/
-struct iwl_eeprom_data *
+struct iwl_nvm_data *
iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size);
/**
- * iwl_free_eeprom_data - free EEPROM data
+ * iwl_free_nvm_data - free NVM data
* @data: the data to free
*/
-static inline void iwl_free_eeprom_data(struct iwl_eeprom_data *data)
+static inline void iwl_free_nvm_data(struct iwl_nvm_data *data)
{
kfree(data);
}
-int iwl_eeprom_check_version(struct iwl_eeprom_data *data,
- struct iwl_trans *trans);
+int iwl_nvm_check_version(struct iwl_nvm_data *data,
+ struct iwl_trans *trans);
#endif /* __iwl_eeprom_parse_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 806046641747..ec48563d3c6a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -267,7 +267,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20)
#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4)
-#define RX_RB_TIMEOUT (0x10)
+#define RX_RB_TIMEOUT (0x11)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 3dfebfb8434f..cdaff9572059 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -214,84 +214,84 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
}
EXPORT_SYMBOL_GPL(iwl_poll_direct_bit);
-static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
+static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
{
- iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
- return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
+ u32 val = iwl_trans_read_prph(trans, ofs);
+ trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
+ return val;
}
-static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
+static inline void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
- iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
- ((addr & 0x0000FFFF) | (3 << 24)));
- iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
+ trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
+ iwl_trans_write_prph(trans, ofs, val);
}
-u32 iwl_read_prph(struct iwl_trans *trans, u32 reg)
+u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans);
- val = __iwl_read_prph(trans, reg);
+ val = __iwl_read_prph(trans, ofs);
iwl_release_nic_access(trans);
spin_unlock_irqrestore(&trans->reg_lock, flags);
return val;
}
EXPORT_SYMBOL_GPL(iwl_read_prph);
-void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
+void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
- __iwl_write_prph(trans, addr, val);
+ __iwl_write_prph(trans, ofs, val);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_write_prph);
-void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
+void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
- __iwl_write_prph(trans, reg,
- __iwl_read_prph(trans, reg) | mask);
+ __iwl_write_prph(trans, ofs,
+ __iwl_read_prph(trans, ofs) | mask);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
-void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
+void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
- __iwl_write_prph(trans, reg,
- (__iwl_read_prph(trans, reg) & mask) | bits);
+ __iwl_write_prph(trans, ofs,
+ (__iwl_read_prph(trans, ofs) & mask) | bits);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
-void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
+void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
- val = __iwl_read_prph(trans, reg);
- __iwl_write_prph(trans, reg, (val & ~mask));
+ val = __iwl_read_prph(trans, ofs);
+ __iwl_write_prph(trans, ofs, (val & ~mask));
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
@@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
- void *buf, int dwords)
+ const void *buf, int dwords)
{
unsigned long flags;
int offs, result = 0;
- u32 *vals = buf;
+ const u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 50d3819739d1..48dc753e3742 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -69,12 +69,12 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
-u32 iwl_read_prph(struct iwl_trans *trans, u32 reg);
-void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
-void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask);
-void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
+u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
+void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
+void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
+void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask);
-void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask);
+void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
@@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
} while (0)
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
- void *buf, int dwords);
+ const void *buf, int dwords);
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 9253ef1dba72..c3a4bb41e533 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -213,6 +213,9 @@
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
+#define SCD_TX_STTS_QUEUE_OFFSET(x)\
+ (SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
+
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index ff1154232885..b76532e238c1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -221,14 +221,21 @@ struct iwl_device_cmd {
/**
* struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
*
- * IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
+ * @IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
* ring. The transport layer doesn't map the command's buffer to DMA, but
* rather copies it to an previously allocated DMA buffer. This flag tells
* the transport layer not to copy the command, but to map the existing
- * buffer. This can save memcpy and is worth with very big comamnds.
+ * buffer (that is passed in) instead. This saves the memcpy and allows
+ * commands that are bigger than the fixed buffer to be submitted.
+ * Note that a TFD entry after a NOCOPY one cannot be a normal copied one.
+ * @IWL_HCMD_DFL_DUP: Only valid without NOCOPY, duplicate the memory for this
+ * chunk internally and free it again after the command completes. This
+ * can (currently) be used only once per command.
+ * Note that a TFD entry after a DUP one cannot be a normal copied one.
*/
enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_NOCOPY = BIT(0),
+ IWL_HCMD_DFL_DUP = BIT(1),
};
/**
@@ -348,14 +355,17 @@ struct iwl_trans;
* @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image.
* May sleep
- * @fw_alive: called when the fw sends alive notification
+ * @fw_alive: called when the fw sends alive notification. If the fw provides
+ * the SCD base address in SRAM, then provide it here, or 0 otherwise.
* May sleep
* @stop_device:stops the whole device (embedded CPU put to reset)
* May sleep
* @wowlan_suspend: put the device into the correct mode for WoWLAN during
* suspend. This is optional, if not implemented WoWLAN will not be
* supported. This callback may sleep.
- * @send_cmd:send a host command
+ * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted.
+ * If RFkill is asserted in the middle of a SYNC host command, it must
+ * return -ERFKILL straight away.
* May sleep only if CMD_SYNC is set
* @tx: send an skb
* Must be atomic
@@ -375,6 +385,8 @@ struct iwl_trans;
* @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR
+ * @read_prph: read a DWORD from a periphery register
+ * @write_prph: write a DWORD to a periphery register
* @configure: configure parameters required by the transport layer from
* the op_mode. May be called several times before start_fw, can't be
* called after that.
@@ -385,7 +397,7 @@ struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans);
void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
- void (*fw_alive)(struct iwl_trans *trans);
+ void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
void (*stop_device)(struct iwl_trans *trans);
void (*wowlan_suspend)(struct iwl_trans *trans);
@@ -410,6 +422,8 @@ struct iwl_trans_ops {
void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
+ u32 (*read_prph)(struct iwl_trans *trans, u32 ofs);
+ void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val);
void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state);
@@ -438,12 +452,15 @@ enum iwl_trans_state {
* Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported
- * @wait_command_queue: the wait_queue for SYNC host commands
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_headroom: room needed for the transport's private use before the
* device_cmd for Tx - for internal use only
* The user should use iwl_trans_{alloc,free}_tx_cmd.
+ * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
+ * starting the firmware, used for tracing
+ * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
+ * start of the 802.11 header in the @rx_mpdu_cmd
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@@ -457,9 +474,9 @@ struct iwl_trans {
u32 hw_id;
char hw_id_str[52];
- bool pm_support;
+ u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
- wait_queue_head_t wait_command_queue;
+ bool pm_support;
/* The following fields are internal only */
struct kmem_cache *dev_cmd_pool;
@@ -476,10 +493,6 @@ struct iwl_trans {
static inline void iwl_trans_configure(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg)
{
- /*
- * only set the op_mode for the moment. Later on, this function will do
- * more
- */
trans->op_mode = trans_cfg->op_mode;
trans->ops->configure(trans, trans_cfg);
@@ -499,16 +512,19 @@ static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
trans->ops->stop_hw(trans, op_mode_leaving);
+ if (op_mode_leaving)
+ trans->op_mode = NULL;
+
trans->state = IWL_TRANS_NO_FW;
}
-static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
+static inline void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
{
might_sleep();
trans->state = IWL_TRANS_FW_ALIVE;
- trans->ops->fw_alive(trans);
+ trans->ops->fw_alive(trans, scd_addr);
}
static inline int iwl_trans_start_fw(struct iwl_trans *trans,
@@ -516,6 +532,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
{
might_sleep();
+ WARN_ON_ONCE(!trans->rx_mpdu_cmd);
+
return trans->ops->start_fw(trans, fw);
}
@@ -650,6 +668,17 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
return trans->ops->read32(trans, ofs);
}
+static inline u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs)
+{
+ return trans->ops->read_prph(trans, ofs);
+}
+
+static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs,
+ u32 val)
+{
+ return trans->ops->write_prph(trans, ofs, val);
+}
+
static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
{
trans->ops->set_pmi(trans, state);
diff --git a/drivers/net/wireless/iwlwifi/pcie/1000.c b/drivers/net/wireless/iwlwifi/pcie/1000.c
index 81b83f484f08..f8620ecae6b4 100644
--- a/drivers/net/wireless/iwlwifi/pcie/1000.c
+++ b/drivers/net/wireless/iwlwifi/pcie/1000.c
@@ -94,8 +94,8 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
.device_family = IWL_DEVICE_FAMILY_1000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_1000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_BLINK
@@ -119,8 +119,8 @@ const struct iwl_cfg iwl1000_bg_cfg = {
.device_family = IWL_DEVICE_FAMILY_100, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_1000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
diff --git a/drivers/net/wireless/iwlwifi/pcie/2000.c b/drivers/net/wireless/iwlwifi/pcie/2000.c
index 9fbde32f7559..244019cec3e1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/2000.c
+++ b/drivers/net/wireless/iwlwifi/pcie/2000.c
@@ -138,8 +138,8 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.device_family = IWL_DEVICE_FAMILY_2000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.need_temp_offset_calib = true, \
@@ -166,8 +166,8 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = {
.device_family = IWL_DEVICE_FAMILY_2030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2030_base_params, \
.bt_params = &iwl2030_bt_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
@@ -190,8 +190,8 @@ const struct iwl_cfg iwl2030_2bgn_cfg = {
.device_family = IWL_DEVICE_FAMILY_105, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.need_temp_offset_calib = true, \
@@ -220,8 +220,8 @@ const struct iwl_cfg iwl105_bgn_d_cfg = {
.device_family = IWL_DEVICE_FAMILY_135, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2030_base_params, \
.bt_params = &iwl2030_bt_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
diff --git a/drivers/net/wireless/iwlwifi/pcie/5000.c b/drivers/net/wireless/iwlwifi/pcie/5000.c
index d1665fa6d15a..83ca40321ff1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/5000.c
+++ b/drivers/net/wireless/iwlwifi/pcie/5000.c
@@ -92,8 +92,8 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
.device_family = IWL_DEVICE_FAMILY_5000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_5000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK
@@ -139,8 +139,8 @@ const struct iwl_cfg iwl5350_agn_cfg = {
.device_family = IWL_DEVICE_FAMILY_5000,
.max_inst_size = IWLAGN_RTC_INST_SIZE,
.max_data_size = IWLAGN_RTC_DATA_SIZE,
- .eeprom_ver = EEPROM_5050_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+ .nvm_ver = EEPROM_5050_EEPROM_VERSION,
+ .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.base_params = &iwl5000_base_params,
.eeprom_params = &iwl5000_eeprom_params,
.ht_params = &iwl5000_ht_params,
@@ -156,8 +156,8 @@ const struct iwl_cfg iwl5350_agn_cfg = {
.device_family = IWL_DEVICE_FAMILY_5150, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_5050_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.no_xtal_calib = true, \
diff --git a/drivers/net/wireless/iwlwifi/pcie/6000.c b/drivers/net/wireless/iwlwifi/pcie/6000.c
index 4a57624afc40..d4df976d4709 100644
--- a/drivers/net/wireless/iwlwifi/pcie/6000.c
+++ b/drivers/net/wireless/iwlwifi/pcie/6000.c
@@ -160,8 +160,8 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.device_family = IWL_DEVICE_FAMILY_6005, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6005_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.need_temp_offset_calib = true, \
@@ -215,8 +215,8 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6030_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \
.bt_params = &iwl6000_bt_params, \
.eeprom_params = &iwl6000_eeprom_params, \
@@ -254,8 +254,8 @@ const struct iwl_cfg iwl6030_2bg_cfg = {
.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6030_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \
.bt_params = &iwl6000_bt_params, \
.eeprom_params = &iwl6000_eeprom_params, \
@@ -306,8 +306,8 @@ const struct iwl_cfg iwl130_bg_cfg = {
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
- .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6000_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.base_params = &iwl6000_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK
@@ -337,8 +337,8 @@ const struct iwl_cfg iwl6000i_2bg_cfg = {
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
- .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6050_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
@@ -362,8 +362,8 @@ const struct iwl_cfg iwl6050_2abg_cfg = {
.device_family = IWL_DEVICE_FAMILY_6150, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
- .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \
- .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
+ .nvm_ver = EEPROM_6150_EEPROM_VERSION, \
+ .nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
@@ -389,8 +389,8 @@ const struct iwl_cfg iwl6000_3agn_cfg = {
.device_family = IWL_DEVICE_FAMILY_6000,
.max_inst_size = IWL60_RTC_INST_SIZE,
.max_data_size = IWL60_RTC_DATA_SIZE,
- .eeprom_ver = EEPROM_6000_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+ .nvm_ver = EEPROM_6000_EEPROM_VERSION,
+ .nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.base_params = &iwl6000_base_params,
.eeprom_params = &iwl6000_eeprom_params,
.ht_params = &iwl6000_ht_params,
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 2a4675396707..c2e141af353c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -69,7 +69,6 @@
#include "iwl-trans.h"
#include "iwl-drv.h"
-#include "iwl-trans.h"
#include "cfg.h"
#include "internal.h"
@@ -268,6 +267,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
struct iwl_trans *iwl_trans;
struct iwl_trans_pcie *trans_pcie;
+ int ret;
iwl_trans = iwl_trans_pcie_alloc(pdev, ent, cfg);
if (iwl_trans == NULL)
@@ -277,11 +277,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
trans_pcie->drv = iwl_drv_start(iwl_trans, cfg);
- if (!trans_pcie->drv)
+
+ if (IS_ERR_OR_NULL(trans_pcie->drv)) {
+ ret = PTR_ERR(trans_pcie->drv);
goto out_free_trans;
+ }
/* register transport layer debugfs here */
- if (iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir))
+ ret = iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir);
+ if (ret)
goto out_free_drv;
return 0;
@@ -291,10 +295,10 @@ out_free_drv:
out_free_trans:
iwl_trans_pcie_free(iwl_trans);
pci_set_drvdata(pdev, NULL);
- return -EFAULT;
+ return ret;
}
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+static void iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_trans *trans = pci_get_drvdata(pdev);
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -353,7 +357,7 @@ static struct pci_driver iwl_pci_driver = {
.name = DRV_NAME,
.id_table = iwl_hw_card_ids,
.probe = iwl_pci_probe,
- .remove = __devexit_p(iwl_pci_remove),
+ .remove = iwl_pci_remove,
.driver.pm = IWL_PM_OPS,
};
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 401178f44a3b..d91d2e8c62f5 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -73,7 +73,7 @@ struct isr_statistics {
};
/**
- * struct iwl_rx_queue - Rx queue
+ * struct iwl_rxq - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
* @pool:
@@ -91,7 +91,7 @@ struct isr_statistics {
*
* NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/
-struct iwl_rx_queue {
+struct iwl_rxq {
__le32 *bd;
dma_addr_t bd_dma;
struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
@@ -157,8 +157,8 @@ struct iwl_cmd_meta {
* 32 since we don't need so many commands pending. Since the HW
* still uses 256 BDs for DMA though, n_bd stays 256. As a result,
* the software buffers (in the variables @meta, @txb in struct
- * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
- * in the same struct) have 256.
+ * iwl_txq) only have 32 entries, while the HW buffers (@tfds in
+ * the same struct) have 256.
* This means that we end up with the following:
* HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
* SW entries: | 0 | ... | 31 |
@@ -182,15 +182,17 @@ struct iwl_queue {
#define TFD_TX_CMD_SLOTS 256
#define TFD_CMD_SLOTS 32
-struct iwl_pcie_tx_queue_entry {
+struct iwl_pcie_txq_entry {
struct iwl_device_cmd *cmd;
struct iwl_device_cmd *copy_cmd;
struct sk_buff *skb;
+ /* buffer to free after command completes */
+ const void *free_buf;
struct iwl_cmd_meta meta;
};
/**
- * struct iwl_tx_queue - Tx Queue for DMA
+ * struct iwl_txq - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @tfds: transmit frame descriptors (DMA memory)
* @entries: transmit entries (driver state)
@@ -203,10 +205,10 @@ struct iwl_pcie_tx_queue_entry {
* A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
* descriptors) and required locking structures.
*/
-struct iwl_tx_queue {
+struct iwl_txq {
struct iwl_queue q;
struct iwl_tfd *tfds;
- struct iwl_pcie_tx_queue_entry *entries;
+ struct iwl_pcie_txq_entry *entries;
spinlock_t lock;
struct timer_list stuck_timer;
struct iwl_trans_pcie *trans_pcie;
@@ -236,7 +238,7 @@ struct iwl_tx_queue {
* @wd_timeout: queue watchdog timeout (jiffies)
*/
struct iwl_trans_pcie {
- struct iwl_rx_queue rxq;
+ struct iwl_rxq rxq;
struct work_struct rx_replenish;
struct iwl_trans *trans;
struct iwl_drv *drv;
@@ -258,7 +260,7 @@ struct iwl_trans_pcie {
struct iwl_dma_ptr scd_bc_tbls;
struct iwl_dma_ptr kw;
- struct iwl_tx_queue *txq;
+ struct iwl_txq *txq;
unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
@@ -268,6 +270,8 @@ struct iwl_trans_pcie {
bool ucode_write_complete;
wait_queue_head_t ucode_write_waitq;
+ wait_queue_head_t wait_command_queue;
+
unsigned long status;
u8 cmd_queue;
u8 cmd_fifo;
@@ -283,13 +287,23 @@ struct iwl_trans_pcie {
unsigned long wd_timeout;
};
-/*****************************************************
-* DRIVER STATUS FUNCTIONS
-******************************************************/
-#define STATUS_HCMD_ACTIVE 0
-#define STATUS_DEVICE_ENABLED 1
-#define STATUS_TPOWER_PMI 2
-#define STATUS_INT_ENABLED 3
+/**
+ * enum iwl_pcie_status: status of the PCIe transport
+ * @STATUS_HCMD_ACTIVE: a SYNC command is being processed
+ * @STATUS_DEVICE_ENABLED: APM is enabled
+ * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
+ * @STATUS_INT_ENABLED: interrupts are enabled
+ * @STATUS_RFKILL: the HW RFkill switch is in KILL position
+ * @STATUS_FW_ERROR: the fw is in error state
+ */
+enum iwl_pcie_status {
+ STATUS_HCMD_ACTIVE,
+ STATUS_DEVICE_ENABLED,
+ STATUS_TPOWER_PMI,
+ STATUS_INT_ENABLED,
+ STATUS_RFKILL,
+ STATUS_FW_ERROR,
+};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
@@ -301,6 +315,10 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
trans_specific);
}
+/*
+ * Convention: trans API functions: iwl_trans_pcie_XXX
+ * Other functions: iwl_pcie_XXX
+ */
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent,
const struct iwl_cfg *cfg);
@@ -309,50 +327,43 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
/*****************************************************
* RX
******************************************************/
-void iwl_bg_rx_replenish(struct work_struct *data);
-void iwl_irq_tasklet(struct iwl_trans *trans);
-void iwl_rx_replenish(struct iwl_trans *trans);
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
- struct iwl_rx_queue *q);
+int iwl_pcie_rx_init(struct iwl_trans *trans);
+void iwl_pcie_tasklet(struct iwl_trans *trans);
+int iwl_pcie_rx_stop(struct iwl_trans *trans);
+void iwl_pcie_rx_free(struct iwl_trans *trans);
/*****************************************************
-* ICT
+* ICT - interrupt handling
******************************************************/
-void iwl_reset_ict(struct iwl_trans *trans);
-void iwl_disable_ict(struct iwl_trans *trans);
-int iwl_alloc_isr_ict(struct iwl_trans *trans);
-void iwl_free_isr_ict(struct iwl_trans *trans);
-irqreturn_t iwl_isr_ict(int irq, void *data);
+irqreturn_t iwl_pcie_isr_ict(int irq, void *data);
+int iwl_pcie_alloc_ict(struct iwl_trans *trans);
+void iwl_pcie_free_ict(struct iwl_trans *trans);
+void iwl_pcie_reset_ict(struct iwl_trans *trans);
+void iwl_pcie_disable_ict(struct iwl_trans *trans);
/*****************************************************
* TX / HCMD
******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_trans *trans,
- struct iwl_tx_queue *txq);
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
- struct iwl_tx_queue *txq,
- dma_addr_t addr, u16 len, u8 reset);
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
-void iwl_tx_cmd_complete(struct iwl_trans *trans,
- struct iwl_rx_cmd_buffer *rxb, int handler_status);
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
- struct iwl_tx_queue *txq,
- u16 byte_cnt);
+int iwl_pcie_tx_init(struct iwl_trans *trans);
+void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
+int iwl_pcie_tx_stop(struct iwl_trans *trans);
+void iwl_pcie_tx_free(struct iwl_trans *trans);
void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
int sta_id, int tid, int frame_limit, u16 ssn);
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue);
-void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
- enum dma_data_direction dma_dir);
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
- struct sk_buff_head *skbs);
-int iwl_queue_space(const struct iwl_queue *q);
-
+int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_cmd *dev_cmd, int txq_id);
+void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq);
+int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
+void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
+ struct iwl_rx_cmd_buffer *rxb, int handler_status);
+void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+ struct sk_buff_head *skbs);
/*****************************************************
* Error handling
******************************************************/
-int iwl_dump_fh(struct iwl_trans *trans, char **buf);
-void iwl_dump_csr(struct iwl_trans *trans);
+int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf);
+void iwl_pcie_dump_csr(struct iwl_trans *trans);
/*****************************************************
* Helpers
@@ -388,7 +399,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
}
static inline void iwl_wake_queue(struct iwl_trans *trans,
- struct iwl_tx_queue *txq)
+ struct iwl_txq *txq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -399,7 +410,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
}
static inline void iwl_stop_queue(struct iwl_trans *trans,
- struct iwl_tx_queue *txq)
+ struct iwl_txq *txq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -411,7 +422,7 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
txq->q.id);
}
-static inline int iwl_queue_used(const struct iwl_queue *q, int i)
+static inline bool iwl_queue_used(const struct iwl_queue *q, int i)
{
return q->write_ptr >= q->read_ptr ?
(i >= q->read_ptr && i < q->write_ptr) :
@@ -423,8 +434,8 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
return index & (q->n_window - 1);
}
-static inline const char *
-trans_pcie_get_cmd_string(struct iwl_trans_pcie *trans_pcie, u8 cmd)
+static inline const char *get_cmd_string(struct iwl_trans_pcie *trans_pcie,
+ u8 cmd)
{
if (!trans_pcie->command_names || !trans_pcie->command_names[cmd])
return "UNKNOWN";
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index bb69f8f90b3b..dad4c4aad91f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -76,7 +76,7 @@
* + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
* iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
* to replenish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the
* iwl->rxq is replenished and the READ INDEX is updated (updating the
* 'processed' and 'read' driver indexes as well)
* + A received packet is processed and handed to the kernel network stack,
@@ -89,28 +89,28 @@
*
* Driver sequence:
*
- * iwl_rx_queue_alloc() Allocates rx_free
- * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls
- * iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * iwl_rxq_alloc() Allocates rx_free
+ * iwl_pcie_rx_replenish() Replenishes rx_free list from rx_used, and calls
+ * iwl_pcie_rxq_restock
+ * iwl_pcie_rxq_restock() Moves available buffers from rx_free into Rx
* queue, updates firmware pointers, and updates
* the WRITE index. If insufficient rx_free buffers
- * are available, schedules iwl_rx_replenish
+ * are available, schedules iwl_pcie_rx_replenish
*
* -- enable interrupts --
- * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
+ * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
* READ INDEX, detaching the SKB from the pool.
* Moves the packet buffer from queue to rx_used.
- * Calls iwl_rx_queue_restock to refill any empty
+ * Calls iwl_pcie_rxq_restock to refill any empty
* slots.
* ...
*
*/
-/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
+/*
+ * iwl_rxq_space - Return number of free slots available in queue.
*/
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+static int iwl_rxq_space(const struct iwl_rxq *q)
{
int s = q->read - q->write;
if (s <= 0)
@@ -122,11 +122,28 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
return s;
}
-/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+/*
+ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr)
+{
+ return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/*
+ * iwl_pcie_rx_stop - stops the Rx DMA
+ */
+int iwl_pcie_rx_stop(struct iwl_trans *trans)
+{
+ iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG,
+ FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
+/*
+ * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue
*/
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
- struct iwl_rx_queue *q)
+static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q)
{
unsigned long flags;
u32 reg;
@@ -176,16 +193,8 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
spin_unlock_irqrestore(&q->lock, flags);
}
-/**
- * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr)
-{
- return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
+/*
+ * iwl_pcie_rxq_restock - refill RX queue from pre-allocated pool
*
* If there are slots in the RX queue that need to be restocked,
* and we have free pre-allocated buffers, fill the ranks as much
@@ -195,11 +204,10 @@ static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr)
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-static void iwl_rx_queue_restock(struct iwl_trans *trans)
+static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- struct list_head *element;
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
@@ -215,18 +223,18 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans)
return;
spin_lock_irqsave(&rxq->lock, flags);
- while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) {
/* The overwritten rxb must be a used one */
rxb = rxq->queue[rxq->write];
BUG_ON(rxb && rxb->page);
/* Get next free Rx buffer, remove from free list */
- element = rxq->rx_free.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
- list_del(element);
+ rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer,
+ list);
+ list_del(&rxb->list);
/* Point to Rx buffer via next RBD in circular buffer */
- rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma);
+ rxq->bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
@@ -243,24 +251,23 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans)
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- iwl_rx_queue_update_write_ptr(trans, rxq);
+ iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
}
}
/*
- * iwl_rx_allocate - allocate a page for each used RBD
+ * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD
*
* A used RBD is an Rx buffer that has been given to the stack. To use it again
* a page must be allocated and the RBD must point to the page. This function
* doesn't change the HW pointer but handles the list of pages that is used by
- * iwl_rx_queue_restock. The latter function will update the HW to use the newly
+ * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly
* allocated buffers.
*/
-static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
+static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- struct list_head *element;
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
struct iwl_rx_mem_buffer *rxb;
struct page *page;
unsigned long flags;
@@ -308,10 +315,9 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
__free_pages(page, trans_pcie->rx_page_order);
return;
}
- element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
- list_del(element);
-
+ rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer,
+ list);
+ list_del(&rxb->list);
spin_unlock_irqrestore(&rxq->lock, flags);
BUG_ON(rxb->page);
@@ -343,47 +349,227 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
}
}
+static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
+ int i;
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+ /* In the reset function, these buffers may have been allocated
+ * to an SKB, so we need to unmap and free potential storage */
+ if (rxq->pool[i].page != NULL) {
+ dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
+ PAGE_SIZE << trans_pcie->rx_page_order,
+ DMA_FROM_DEVICE);
+ __free_pages(rxq->pool[i].page,
+ trans_pcie->rx_page_order);
+ rxq->pool[i].page = NULL;
+ }
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+ }
+}
+
/*
- * iwl_rx_replenish - Move all used buffers from rx_used to rx_free
+ * iwl_pcie_rx_replenish - Move all used buffers from rx_used to rx_free
*
* When moving to rx_free an page is allocated for the slot.
*
- * Also restock the Rx queue via iwl_rx_queue_restock.
+ * Also restock the Rx queue via iwl_pcie_rxq_restock.
* This is called as a scheduled work item (except for during initialization)
*/
-void iwl_rx_replenish(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
- iwl_rx_allocate(trans, GFP_KERNEL);
+ iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
- iwl_rx_queue_restock(trans);
+ iwl_pcie_rxq_restock(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
}
-static void iwl_rx_replenish_now(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
{
- iwl_rx_allocate(trans, GFP_ATOMIC);
+ iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC);
- iwl_rx_queue_restock(trans);
+ iwl_pcie_rxq_restock(trans);
}
-void iwl_bg_rx_replenish(struct work_struct *data)
+static void iwl_pcie_rx_replenish_work(struct work_struct *data)
{
struct iwl_trans_pcie *trans_pcie =
container_of(data, struct iwl_trans_pcie, rx_replenish);
- iwl_rx_replenish(trans_pcie->trans);
+ iwl_pcie_rx_replenish(trans_pcie->trans);
+}
+
+static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
+ struct device *dev = trans->dev;
+
+ memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
+
+ spin_lock_init(&rxq->lock);
+
+ if (WARN_ON(rxq->bd || rxq->rb_stts))
+ return -EINVAL;
+
+ /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
+ rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+ &rxq->bd_dma, GFP_KERNEL);
+ if (!rxq->bd)
+ goto err_bd;
+
+ /*Allocate the driver's pointer to receive buffer status */
+ rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts),
+ &rxq->rb_stts_dma, GFP_KERNEL);
+ if (!rxq->rb_stts)
+ goto err_rb_stts;
+
+ return 0;
+
+err_rb_stts:
+ dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+ rxq->bd, rxq->bd_dma);
+ memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+ rxq->bd = NULL;
+err_bd:
+ return -ENOMEM;
+}
+
+static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 rb_size;
+ const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+
+ if (trans_pcie->rx_buf_size_8k)
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+ else
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+ /* Stop Rx DMA */
+ iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+ /* Reset driver's Rx queue write index */
+ iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+ /* Tell device where to find RBD circular buffer in DRAM */
+ iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+ (u32)(rxq->bd_dma >> 8));
+
+ /* Tell device where in DRAM to update its Rx status */
+ iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+ rxq->rb_stts_dma >> 4);
+
+ /* Enable Rx DMA
+ * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
+ * the credit mechanism in 5000 HW RX FIFO
+ * Direct rx interrupts to hosts
+ * Rx buffer size 4 or 8k
+ * RB timeout 0x10
+ * 256 RBDs
+ */
+ iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+ FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+ FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
+ FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+ rb_size|
+ (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+ (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+ /* Set interrupt coalescing timer to default (2048 usecs) */
+ iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+}
+
+int iwl_pcie_rx_init(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
+
+ int i, err;
+ unsigned long flags;
+
+ if (!rxq->bd) {
+ err = iwl_pcie_rx_alloc(trans);
+ if (err)
+ return err;
+ }
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ INIT_WORK(&trans_pcie->rx_replenish,
+ iwl_pcie_rx_replenish_work);
+
+ iwl_pcie_rxq_free_rbs(trans);
+
+ for (i = 0; i < RX_QUEUE_SIZE; i++)
+ rxq->queue[i] = NULL;
+
+ /* Set us so that we have processed and used all buffers, but have
+ * not restocked the Rx queue with fresh buffers */
+ rxq->read = rxq->write = 0;
+ rxq->write_actual = 0;
+ rxq->free_count = 0;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ iwl_pcie_rx_replenish(trans);
+
+ iwl_pcie_rx_hw_init(trans, rxq);
+
+ spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+ rxq->need_update = 1;
+ iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
+ spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
+ return 0;
}
-static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
+void iwl_pcie_rx_free(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
+ unsigned long flags;
+
+ /*if rxq->bd is NULL, it means that nothing has been allocated,
+ * exit now */
+ if (!rxq->bd) {
+ IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
+ return;
+ }
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ iwl_pcie_rxq_free_rbs(trans);
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
+ rxq->bd, rxq->bd_dma);
+ memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+ rxq->bd = NULL;
+
+ if (rxq->rb_stts)
+ dma_free_coherent(trans->dev,
+ sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
+ else
+ IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
+ memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
+ rxq->rb_stts = NULL;
+}
+
+static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
+ struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
unsigned long flags;
bool page_stolen = false;
int max_len = PAGE_SIZE << trans_pcie->rx_page_order;
@@ -413,13 +599,13 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
break;
IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n",
- rxcb._offset,
- trans_pcie_get_cmd_string(trans_pcie, pkt->hdr.cmd),
+ rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd),
pkt->hdr.cmd);
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
len += sizeof(u32); /* account for status word */
- trace_iwlwifi_dev_rx(trans->dev, pkt, len);
+ trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len);
+ trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len);
/* Reclaim a command buffer only if this packet is a response
* to a (driver-originated) command.
@@ -445,7 +631,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
cmd_index = get_cmd_index(&txq->q, index);
if (reclaim) {
- struct iwl_pcie_tx_queue_entry *ent;
+ struct iwl_pcie_txq_entry *ent;
ent = &txq->entries[cmd_index];
cmd = ent->copy_cmd;
WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
@@ -459,6 +645,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
/* The original command isn't needed any more */
kfree(txq->entries[cmd_index].copy_cmd);
txq->entries[cmd_index].copy_cmd = NULL;
+ /* nor is the duplicated part of the command */
+ kfree(txq->entries[cmd_index].free_buf);
+ txq->entries[cmd_index].free_buf = NULL;
}
/*
@@ -472,7 +661,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
* iwl_trans_send_cmd()
* as we reclaim the driver command queue */
if (!rxcb._page_stolen)
- iwl_tx_cmd_complete(trans, &rxcb, err);
+ iwl_pcie_hcmd_complete(trans, &rxcb, err);
else
IWL_WARN(trans, "Claim null rxb?\n");
}
@@ -514,17 +703,13 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
spin_unlock_irqrestore(&rxq->lock, flags);
}
-/**
- * iwl_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
+/*
+ * iwl_pcie_rx_handle - Main entry function for receiving responses from fw
*/
-static void iwl_rx_handle(struct iwl_trans *trans)
+static void iwl_pcie_rx_handle(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
u32 r, i;
u8 fill_rx = 0;
u32 count = 8;
@@ -532,7 +717,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
/* uCode's read index (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
- r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
+ r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF;
i = rxq->read;
/* Rx interrupt, but nothing sent from uCode */
@@ -555,7 +740,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d (%p)\n",
r, i, rxb);
- iwl_rx_handle_rxbuf(trans, rxb);
+ iwl_pcie_rx_handle_rb(trans, rxb);
i = (i + 1) & RX_QUEUE_MASK;
/* If there are a lot of unused frames,
@@ -564,7 +749,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
count++;
if (count >= 8) {
rxq->read = i;
- iwl_rx_replenish_now(trans);
+ iwl_pcie_rx_replenish_now(trans);
count = 0;
}
}
@@ -573,39 +758,41 @@ static void iwl_rx_handle(struct iwl_trans *trans)
/* Backtrack one entry */
rxq->read = i;
if (fill_rx)
- iwl_rx_replenish_now(trans);
+ iwl_pcie_rx_replenish_now(trans);
else
- iwl_rx_queue_restock(trans);
+ iwl_pcie_rxq_restock(trans);
}
-/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
+/*
+ * iwl_pcie_irq_handle_error - called for HW or SW error interrupt from card
*/
-static void iwl_irq_handle_error(struct iwl_trans *trans)
+static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if (trans->cfg->internal_wimax_coex &&
(!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(trans, APMG_PS_CTRL_REG) &
APMG_PS_CTRL_VAL_RESET_REQ))) {
- struct iwl_trans_pcie *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
-
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
iwl_op_mode_wimax_active(trans->op_mode);
- wake_up(&trans->wait_command_queue);
+ wake_up(&trans_pcie->wait_command_queue);
return;
}
- iwl_dump_csr(trans);
- iwl_dump_fh(trans, NULL);
+ iwl_pcie_dump_csr(trans);
+ iwl_pcie_dump_fh(trans, NULL);
+
+ set_bit(STATUS_FW_ERROR, &trans_pcie->status);
+ clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+ wake_up(&trans_pcie->wait_command_queue);
iwl_op_mode_nic_error(trans->op_mode);
}
-/* tasklet for iwlagn interrupt */
-void iwl_irq_tasklet(struct iwl_trans *trans)
+void iwl_pcie_tasklet(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
@@ -657,7 +844,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
iwl_disable_interrupts(trans);
isr_stats->hw++;
- iwl_irq_handle_error(trans);
+ iwl_pcie_irq_handle_error(trans);
handled |= CSR_INT_BIT_HW_ERR;
@@ -694,6 +881,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
isr_stats->rfkill++;
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+ if (hw_rfkill) {
+ set_bit(STATUS_RFKILL, &trans_pcie->status);
+ if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
+ &trans_pcie->status))
+ IWL_DEBUG_RF_KILL(trans,
+ "Rfkill while SYNC HCMD in flight\n");
+ wake_up(&trans_pcie->wait_command_queue);
+ } else {
+ clear_bit(STATUS_RFKILL, &trans_pcie->status);
+ }
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -710,17 +907,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
IWL_ERR(trans, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta);
isr_stats->sw++;
- iwl_irq_handle_error(trans);
+ iwl_pcie_irq_handle_error(trans);
handled |= CSR_INT_BIT_SW_ERR;
}
/* uCode wakes up after power-down sleep */
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
- iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
+ iwl_pcie_rxq_inc_wr_ptr(trans, &trans_pcie->rxq);
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++)
- iwl_txq_update_write_ptr(trans,
- &trans_pcie->txq[i]);
+ iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]);
isr_stats->wakeup++;
@@ -758,7 +954,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
iwl_write8(trans, CSR_INT_PERIODIC_REG,
CSR_INT_PERIODIC_DIS);
- iwl_rx_handle(trans);
+ iwl_pcie_rx_handle(trans);
/*
* Enable periodic interrupt in 8 msec only if we received
@@ -816,7 +1012,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
#define ICT_COUNT (ICT_SIZE / sizeof(u32))
/* Free dram table */
-void iwl_free_isr_ict(struct iwl_trans *trans)
+void iwl_pcie_free_ict(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -829,13 +1025,12 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
}
}
-
/*
* allocate dram shared table, it is an aligned memory
* block of ICT_SIZE.
* also reset all data related to ICT table interrupt.
*/
-int iwl_alloc_isr_ict(struct iwl_trans *trans)
+int iwl_pcie_alloc_ict(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -848,7 +1043,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
/* just an API sanity check ... it is guaranteed to be aligned */
if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) {
- iwl_free_isr_ict(trans);
+ iwl_pcie_free_ict(trans);
return -EINVAL;
}
@@ -869,7 +1064,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
/* Device is going up inform it about using ICT interrupt table,
* also we need to tell the driver to start using ICT interrupt.
*/
-void iwl_reset_ict(struct iwl_trans *trans)
+void iwl_pcie_reset_ict(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 val;
@@ -899,7 +1094,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
}
/* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_trans *trans)
+void iwl_pcie_disable_ict(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
@@ -910,7 +1105,7 @@ void iwl_disable_ict(struct iwl_trans *trans)
}
/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_isr(int irq, void *data)
+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);
@@ -927,12 +1122,20 @@ static irqreturn_t iwl_isr(int irq, void *data)
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */
+ inta_mask = iwl_read32(trans, CSR_INT_MASK);
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
inta = iwl_read32(trans, CSR_INT);
+ if (inta & (~inta_mask)) {
+ IWL_DEBUG_ISR(trans,
+ "We got a masked interrupt (0x%08x)...Ack and ignore\n",
+ inta & (~inta_mask));
+ iwl_write32(trans, CSR_INT, inta & (~inta_mask));
+ inta &= inta_mask;
+ }
+
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
@@ -957,7 +1160,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
#endif
trans_pcie->inta |= inta;
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ /* iwl_pcie_tasklet() will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
@@ -982,7 +1185,7 @@ none:
* the interrupt we need to service, driver will set the entries back to 0 and
* set index.
*/
-irqreturn_t iwl_isr_ict(int irq, void *data)
+irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
{
struct iwl_trans *trans = data;
struct iwl_trans_pcie *trans_pcie;
@@ -1002,23 +1205,21 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
* use legacy interrupt.
*/
if (unlikely(!trans_pcie->use_ict)) {
- irqreturn_t ret = iwl_isr(irq, data);
+ irqreturn_t ret = iwl_pcie_isr(irq, data);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
return ret;
}
trace_iwlwifi_dev_irq(trans->dev);
-
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here.
*/
- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */
+ inta_mask = iwl_read32(trans, CSR_INT_MASK);
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
-
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
@@ -1067,7 +1268,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
inta &= trans_pcie->inta_mask;
trans_pcie->inta |= inta;
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ /* iwl_pcie_tasklet() will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index fe0fffd04304..35708b959ad6 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -74,584 +74,8 @@
#include "iwl-prph.h"
#include "iwl-agn-hw.h"
#include "internal.h"
-/* FIXME: need to abstract out TX command (once we know what it looks like) */
-#include "dvm/commands.h"
-#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \
- (((1<<trans->cfg->base_params->num_of_queues) - 1) &\
- (~(1<<(trans_pcie)->cmd_queue)))
-
-static int iwl_trans_rx_alloc(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- struct device *dev = trans->dev;
-
- memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
-
- spin_lock_init(&rxq->lock);
-
- if (WARN_ON(rxq->bd || rxq->rb_stts))
- return -EINVAL;
-
- /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
- &rxq->bd_dma, GFP_KERNEL);
- if (!rxq->bd)
- goto err_bd;
-
- /*Allocate the driver's pointer to receive buffer status */
- rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts),
- &rxq->rb_stts_dma, GFP_KERNEL);
- if (!rxq->rb_stts)
- goto err_rb_stts;
-
- return 0;
-
-err_rb_stts:
- dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
- rxq->bd, rxq->bd_dma);
- memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
- rxq->bd = NULL;
-err_bd:
- return -ENOMEM;
-}
-
-static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- int i;
-
- /* Fill the rx_used queue with _all_ of the Rx buffers */
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
- /* In the reset function, these buffers may have been allocated
- * to an SKB, so we need to unmap and free potential storage */
- if (rxq->pool[i].page != NULL) {
- dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
- PAGE_SIZE << trans_pcie->rx_page_order,
- DMA_FROM_DEVICE);
- __free_pages(rxq->pool[i].page,
- trans_pcie->rx_page_order);
- rxq->pool[i].page = NULL;
- }
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- }
-}
-
-static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
- struct iwl_rx_queue *rxq)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u32 rb_size;
- const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
- u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */
-
- if (trans_pcie->rx_buf_size_8k)
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
- else
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
- /* Stop Rx DMA */
- iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
- /* Reset driver's Rx queue write index */
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
- /* Tell device where to find RBD circular buffer in DRAM */
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- (u32)(rxq->bd_dma >> 8));
-
- /* Tell device where in DRAM to update its Rx status */
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG,
- rxq->rb_stts_dma >> 4);
-
- /* Enable Rx DMA
- * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
- * the credit mechanism in 5000 HW RX FIFO
- * Direct rx interrupts to hosts
- * Rx buffer size 4 or 8k
- * RB timeout 0x10
- * 256 RBDs
- */
- iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
- FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
- FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- rb_size|
- (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
- (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-
- /* Set interrupt coalescing timer to default (2048 usecs) */
- iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-}
-
-static int iwl_rx_init(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-
- int i, err;
- unsigned long flags;
-
- if (!rxq->bd) {
- err = iwl_trans_rx_alloc(trans);
- if (err)
- return err;
- }
-
- spin_lock_irqsave(&rxq->lock, flags);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
-
- iwl_trans_rxq_free_rx_bufs(trans);
-
- for (i = 0; i < RX_QUEUE_SIZE; i++)
- rxq->queue[i] = NULL;
-
- /* Set us so that we have processed and used all buffers, but have
- * not restocked the Rx queue with fresh buffers */
- rxq->read = rxq->write = 0;
- rxq->write_actual = 0;
- rxq->free_count = 0;
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- iwl_rx_replenish(trans);
-
- iwl_trans_rx_hw_init(trans, rxq);
-
- spin_lock_irqsave(&trans_pcie->irq_lock, flags);
- rxq->need_update = 1;
- iwl_rx_queue_update_write_ptr(trans, rxq);
- spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
- return 0;
-}
-
-static void iwl_trans_pcie_rx_free(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
- unsigned long flags;
-
- /*if rxq->bd is NULL, it means that nothing has been allocated,
- * exit now */
- if (!rxq->bd) {
- IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
- return;
- }
-
- spin_lock_irqsave(&rxq->lock, flags);
- iwl_trans_rxq_free_rx_bufs(trans);
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
- rxq->bd, rxq->bd_dma);
- memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
- rxq->bd = NULL;
-
- if (rxq->rb_stts)
- dma_free_coherent(trans->dev,
- sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
- else
- IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
- memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
- rxq->rb_stts = NULL;
-}
-
-static int iwl_trans_rx_stop(struct iwl_trans *trans)
-{
-
- /* stop Rx DMA */
- iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG,
- FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-}
-
-static int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
- struct iwl_dma_ptr *ptr, size_t size)
-{
- if (WARN_ON(ptr->addr))
- return -EINVAL;
-
- ptr->addr = dma_alloc_coherent(trans->dev, size,
- &ptr->dma, GFP_KERNEL);
- if (!ptr->addr)
- return -ENOMEM;
- ptr->size = size;
- return 0;
-}
-
-static void iwlagn_free_dma_ptr(struct iwl_trans *trans,
- struct iwl_dma_ptr *ptr)
-{
- if (unlikely(!ptr->addr))
- return;
-
- dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma);
- memset(ptr, 0, sizeof(*ptr));
-}
-
-static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
-{
- struct iwl_tx_queue *txq = (void *)data;
- struct iwl_queue *q = &txq->q;
- struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
- struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
- u32 scd_sram_addr = trans_pcie->scd_base_addr +
- SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id);
- u8 buf[16];
- int i;
-
- spin_lock(&txq->lock);
- /* check if triggered erroneously */
- if (txq->q.read_ptr == txq->q.write_ptr) {
- spin_unlock(&txq->lock);
- return;
- }
- spin_unlock(&txq->lock);
-
- IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id,
- jiffies_to_msecs(trans_pcie->wd_timeout));
- IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
- txq->q.read_ptr, txq->q.write_ptr);
-
- iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
-
- iwl_print_hex_error(trans, buf, sizeof(buf));
-
- for (i = 0; i < FH_TCSR_CHNL_NUM; i++)
- IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i,
- iwl_read_direct32(trans, FH_TX_TRB_REG(i)));
-
- for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
- u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i));
- u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
- bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
- u32 tbl_dw =
- iwl_read_targ_mem(trans,
- trans_pcie->scd_base_addr +
- SCD_TRANS_TBL_OFFSET_QUEUE(i));
-
- if (i & 0x1)
- tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
- else
- tbl_dw = tbl_dw & 0x0000FFFF;
-
- IWL_ERR(trans,
- "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
- i, active ? "" : "in", fifo, tbl_dw,
- iwl_read_prph(trans,
- SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
- iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
- }
-
- for (i = q->read_ptr; i != q->write_ptr;
- i = iwl_queue_inc_wrap(i, q->n_bd)) {
- struct iwl_tx_cmd *tx_cmd =
- (struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
- IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
- get_unaligned_le32(&tx_cmd->scratch));
- }
-
- iwl_op_mode_nic_error(trans->op_mode);
-}
-
-static int iwl_trans_txq_alloc(struct iwl_trans *trans,
- struct iwl_tx_queue *txq, int slots_num,
- u32 txq_id)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
- int i;
-
- if (WARN_ON(txq->entries || txq->tfds))
- return -EINVAL;
-
- setup_timer(&txq->stuck_timer, iwl_trans_pcie_queue_stuck_timer,
- (unsigned long)txq);
- txq->trans_pcie = trans_pcie;
-
- txq->q.n_window = slots_num;
-
- txq->entries = kcalloc(slots_num,
- sizeof(struct iwl_pcie_tx_queue_entry),
- GFP_KERNEL);
-
- if (!txq->entries)
- goto error;
-
- if (txq_id == trans_pcie->cmd_queue)
- for (i = 0; i < slots_num; i++) {
- txq->entries[i].cmd =
- kmalloc(sizeof(struct iwl_device_cmd),
- GFP_KERNEL);
- if (!txq->entries[i].cmd)
- goto error;
- }
-
- /* Circular buffer of transmit frame descriptors (TFDs),
- * shared with device */
- txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz,
- &txq->q.dma_addr, GFP_KERNEL);
- if (!txq->tfds) {
- IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
- goto error;
- }
- txq->q.id = txq_id;
-
- return 0;
-error:
- if (txq->entries && txq_id == trans_pcie->cmd_queue)
- for (i = 0; i < slots_num; i++)
- kfree(txq->entries[i].cmd);
- kfree(txq->entries);
- txq->entries = NULL;
-
- return -ENOMEM;
-
-}
-
-static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id)
-{
- int ret;
-
- txq->need_update = 0;
-
- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
- /* Initialize queue's high/low-water marks, and head/tail indexes */
- ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
- txq_id);
- if (ret)
- return ret;
-
- spin_lock_init(&txq->lock);
-
- /*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- * Circular buffer (TFD queue in DRAM) physical base address */
- iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id),
- txq->q.dma_addr >> 8);
-
- return 0;
-}
-
-/**
- * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
- */
-static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- enum dma_data_direction dma_dir;
-
- if (!q->n_bd)
- return;
-
- /* In the command queue, all the TBs are mapped as BIDI
- * so unmap them as such.
- */
- if (txq_id == trans_pcie->cmd_queue)
- dma_dir = DMA_BIDIRECTIONAL;
- else
- dma_dir = DMA_TO_DEVICE;
-
- spin_lock_bh(&txq->lock);
- while (q->write_ptr != q->read_ptr) {
- iwl_txq_free_tfd(trans, txq, dma_dir);
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
- }
- spin_unlock_bh(&txq->lock);
-}
-
-/**
- * iwl_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
- struct device *dev = trans->dev;
- int i;
-
- if (WARN_ON(!txq))
- return;
-
- iwl_tx_queue_unmap(trans, txq_id);
-
- /* De-alloc array of command/tx buffers */
- if (txq_id == trans_pcie->cmd_queue)
- for (i = 0; i < txq->q.n_window; i++) {
- kfree(txq->entries[i].cmd);
- kfree(txq->entries[i].copy_cmd);
- }
-
- /* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd) {
- dma_free_coherent(dev, sizeof(struct iwl_tfd) *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
- memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
- }
-
- kfree(txq->entries);
- txq->entries = NULL;
-
- del_timer_sync(&txq->stuck_timer);
-
- /* 0-fill queue descriptor structure */
- memset(txq, 0, sizeof(*txq));
-}
-
-/**
- * iwl_trans_tx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
-{
- int txq_id;
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- /* Tx queues */
- if (trans_pcie->txq) {
- for (txq_id = 0;
- txq_id < trans->cfg->base_params->num_of_queues; txq_id++)
- iwl_tx_queue_free(trans, txq_id);
- }
-
- kfree(trans_pcie->txq);
- trans_pcie->txq = NULL;
-
- iwlagn_free_dma_ptr(trans, &trans_pcie->kw);
-
- iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
-}
-
-/**
- * iwl_trans_tx_alloc - allocate TX context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-static int iwl_trans_tx_alloc(struct iwl_trans *trans)
-{
- int ret;
- int txq_id, slots_num;
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
-
- /*It is not allowed to alloc twice, so warn when this happens.
- * We cannot rely on the previous allocation, so free and fail */
- if (WARN_ON(trans_pcie->txq)) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
- scd_bc_tbls_size);
- if (ret) {
- IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
- goto error;
- }
-
- /* Alloc keep-warm buffer */
- ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
- if (ret) {
- IWL_ERR(trans, "Keep Warm allocation failed\n");
- goto error;
- }
-
- trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues,
- sizeof(struct iwl_tx_queue), GFP_KERNEL);
- if (!trans_pcie->txq) {
- IWL_ERR(trans, "Not enough memory for txq\n");
- ret = ENOMEM;
- goto error;
- }
-
- /* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
- txq_id++) {
- slots_num = (txq_id == trans_pcie->cmd_queue) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
- slots_num, txq_id);
- if (ret) {
- IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
- goto error;
- }
- }
-
- return 0;
-
-error:
- iwl_trans_pcie_tx_free(trans);
-
- return ret;
-}
-static int iwl_tx_init(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- int ret;
- int txq_id, slots_num;
- unsigned long flags;
- bool alloc = false;
-
- if (!trans_pcie->txq) {
- ret = iwl_trans_tx_alloc(trans);
- if (ret)
- goto error;
- alloc = true;
- }
-
- spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
- /* Turn off all Tx DMA fifos */
- iwl_write_prph(trans, SCD_TXFACT, 0);
-
- /* Tell NIC where to find the "keep warm" buffer */
- iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
- trans_pcie->kw.dma >> 4);
-
- spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
- /* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
- txq_id++) {
- slots_num = (txq_id == trans_pcie->cmd_queue) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
- slots_num, txq_id);
- if (ret) {
- IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
- goto error;
- }
- }
-
- return 0;
-error:
- /*Upon error, free only if we allocated something */
- if (alloc)
- iwl_trans_pcie_tx_free(trans);
- return ret;
-}
-
-static void iwl_set_pwr_vmain(struct iwl_trans *trans)
+static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
{
/*
* (for documentation purposes)
@@ -670,21 +94,12 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
-static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans)
+static void iwl_pcie_apm_config(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u16 pci_lnk_ctl;
-
- pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL,
- &pci_lnk_ctl);
- return pci_lnk_ctl;
-}
+ u16 lctl;
-static void iwl_apm_config(struct iwl_trans *trans)
-{
/*
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
* Check if BIOS (or OS) enabled L1-ASPM on this device.
@@ -693,29 +108,25 @@ static void iwl_apm_config(struct iwl_trans *trans)
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
- u16 lctl = iwl_pciexp_link_ctrl(trans);
-
- if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
- PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+ pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
+ if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
/* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
- dev_printk(KERN_INFO, trans->dev,
- "L1 Enabled; Disabling L0S\n");
+ dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
} else {
/* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
- dev_printk(KERN_INFO, trans->dev,
- "L1 Disabled; Enabling L0S\n");
+ dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
}
- trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+ trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
}
/*
* Start up NIC's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_apm_stop())
+ * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
* NOTE: This does not load uCode nor start the embedded processor
*/
-static int iwl_apm_init(struct iwl_trans *trans)
+static int iwl_pcie_apm_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret = 0;
@@ -747,7 +158,7 @@ static int iwl_apm_init(struct iwl_trans *trans)
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
- iwl_apm_config(trans);
+ iwl_pcie_apm_config(trans);
/* Configure analog phase-lock-loop before activating to D0A */
if (trans->cfg->base_params->pll_cfg_val)
@@ -793,7 +204,7 @@ out:
return ret;
}
-static int iwl_apm_stop_master(struct iwl_trans *trans)
+static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
{
int ret = 0;
@@ -811,7 +222,7 @@ static int iwl_apm_stop_master(struct iwl_trans *trans)
return ret;
}
-static void iwl_apm_stop(struct iwl_trans *trans)
+static void iwl_pcie_apm_stop(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
@@ -819,7 +230,7 @@ static void iwl_apm_stop(struct iwl_trans *trans)
clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
/* Stop device's DMA activity */
- iwl_apm_stop_master(trans);
+ iwl_pcie_apm_stop_master(trans);
/* Reset the entire device */
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
@@ -834,29 +245,29 @@ static void iwl_apm_stop(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
}
-static int iwl_nic_init(struct iwl_trans *trans)
+static int iwl_pcie_nic_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
/* nic_init */
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
- iwl_apm_init(trans);
+ 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_set_pwr_vmain(trans);
+ iwl_pcie_set_pwr_vmain(trans);
iwl_op_mode_nic_config(trans->op_mode);
/* Allocate the RX queue, or reset if it is already allocated */
- iwl_rx_init(trans);
+ iwl_pcie_rx_init(trans);
/* Allocate or reset and init all Tx and Command queues */
- if (iwl_tx_init(trans))
+ if (iwl_pcie_tx_init(trans))
return -ENOMEM;
if (trans->cfg->base_params->shadow_reg_enable) {
@@ -871,7 +282,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
#define HW_READY_TIMEOUT (50)
/* Note: returns poll_bit return value, which is >= 0 if success */
-static int iwl_set_hw_ready(struct iwl_trans *trans)
+static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
{
int ret;
@@ -889,14 +300,14 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
}
/* Note: returns standard 0/-ERROR code */
-static int iwl_prepare_card_hw(struct iwl_trans *trans)
+static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
{
int ret;
int t = 0;
IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
- ret = iwl_set_hw_ready(trans);
+ ret = iwl_pcie_set_hw_ready(trans);
/* If the card is ready, exit 0 */
if (ret >= 0)
return 0;
@@ -906,7 +317,7 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
CSR_HW_IF_CONFIG_REG_PREPARE);
do {
- ret = iwl_set_hw_ready(trans);
+ ret = iwl_pcie_set_hw_ready(trans);
if (ret >= 0)
return 0;
@@ -920,7 +331,7 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
/*
* ucode
*/
-static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
+static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
dma_addr_t phy_addr, u32 byte_cnt)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -967,7 +378,7 @@ static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
return 0;
}
-static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
+static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
const struct fw_desc *section)
{
u8 *v_addr;
@@ -988,8 +399,9 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
copy_size = min_t(u32, PAGE_SIZE, section->len - offset);
memcpy(v_addr, (u8 *)section->data + offset, copy_size);
- ret = iwl_load_firmware_chunk(trans, section->offset + offset,
- p_addr, copy_size);
+ ret = iwl_pcie_load_firmware_chunk(trans,
+ section->offset + offset,
+ p_addr, copy_size);
if (ret) {
IWL_ERR(trans,
"Could not load the [%d] uCode section\n",
@@ -1002,7 +414,7 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
return ret;
}
-static int iwl_load_given_ucode(struct iwl_trans *trans,
+static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
const struct fw_img *image)
{
int i, ret = 0;
@@ -1011,7 +423,7 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
if (!image->sec[i].data)
break;
- ret = iwl_load_section(trans, i, &image->sec[i]);
+ ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
if (ret)
return ret;
}
@@ -1025,15 +437,18 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
const struct fw_img *fw)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
bool hw_rfkill;
/* This may fail if AMT took ownership of the device */
- if (iwl_prepare_card_hw(trans)) {
+ if (iwl_pcie_prepare_card_hw(trans)) {
IWL_WARN(trans, "Exit HW not ready\n");
return -EIO;
}
+ clear_bit(STATUS_FW_ERROR, &trans_pcie->status);
+
iwl_enable_rfkill_int(trans);
/* If platform's RF_KILL switch is NOT set to KILL */
@@ -1044,7 +459,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
- ret = iwl_nic_init(trans);
+ ret = iwl_pcie_nic_init(trans);
if (ret) {
IWL_ERR(trans, "Unable to init nic\n");
return ret;
@@ -1064,125 +479,13 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- return iwl_load_given_ucode(trans, fw);
+ return iwl_pcie_load_given_ucode(trans, fw);
}
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- */
-static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
+static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
{
- struct iwl_trans_pcie __maybe_unused *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
-
- iwl_write_prph(trans, SCD_TXFACT, mask);
-}
-
-static void iwl_tx_start(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u32 a;
- int chan;
- u32 reg_val;
-
- /* make sure all queue are not stopped/used */
- memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
-
- trans_pcie->scd_base_addr =
- iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
- a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
- /* reset conext data memory */
- for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
- a += 4)
- iwl_write_targ_mem(trans, a, 0);
- /* reset tx status memory */
- for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
- a += 4)
- iwl_write_targ_mem(trans, a, 0);
- for (; a < trans_pcie->scd_base_addr +
- SCD_TRANS_TBL_OFFSET_QUEUE(
- trans->cfg->base_params->num_of_queues);
- a += 4)
- iwl_write_targ_mem(trans, a, 0);
-
- iwl_write_prph(trans, SCD_DRAM_BASE_ADDR,
- trans_pcie->scd_bc_tbls.dma >> 10);
-
- /* The chain extension of the SCD doesn't work well. This feature is
- * enabled by default by the HW, so we need to disable it manually.
- */
- iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
-
- iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
- trans_pcie->cmd_fifo);
-
- /* Activate all Tx DMA/FIFO channels */
- iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
-
- /* Enable DMA channel */
- for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
- iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
- /* Update FH chicken bits */
- reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG);
- iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG,
- reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
- /* Enable L1-Active */
- iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-}
-
-static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
-{
- iwl_reset_ict(trans);
- iwl_tx_start(trans);
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-static int iwl_trans_tx_stop(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- int ch, txq_id, ret;
- unsigned long flags;
-
- /* Turn off all Tx DMA fifos */
- spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
- iwl_trans_txq_set_sched(trans, 0);
-
- /* Stop each Tx DMA channel, and wait for it to be idle */
- for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
- iwl_write_direct32(trans,
- FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
- ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
- if (ret < 0)
- IWL_ERR(trans,
- "Failing on timeout while stopping DMA channel %d [0x%08x]\n",
- ch,
- iwl_read_direct32(trans,
- FH_TSSR_TX_STATUS_REG));
- }
- spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
- if (!trans_pcie->txq) {
- IWL_WARN(trans,
- "Stopping tx queues that aren't allocated...\n");
- return 0;
- }
-
- /* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
- txq_id++)
- iwl_tx_queue_unmap(trans, txq_id);
-
- return 0;
+ iwl_pcie_reset_ict(trans);
+ iwl_pcie_tx_start(trans, scd_addr);
}
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
@@ -1196,7 +499,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
/* device going down, Stop using ICT table */
- iwl_disable_ict(trans);
+ iwl_pcie_disable_ict(trans);
/*
* If a HW restart happens during firmware loading,
@@ -1206,8 +509,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* already dead.
*/
if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
- iwl_trans_tx_stop(trans);
- iwl_trans_rx_stop(trans);
+ iwl_pcie_tx_stop(trans);
+ iwl_pcie_rx_stop(trans);
/* Power-down device's busmaster DMA clocks */
iwl_write_prph(trans, APMG_CLK_DIS_REG,
@@ -1220,7 +523,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* Stop the device, and put it in low power state */
- iwl_apm_stop(trans);
+ iwl_pcie_apm_stop(trans);
/* Upon stop, the APM issues an interrupt if HW RF kill is set.
* Clean again the interrupt here
@@ -1245,6 +548,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
+ clear_bit(STATUS_RFKILL, &trans_pcie->status);
}
static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
@@ -1258,169 +562,6 @@ static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
-static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
- struct iwl_device_cmd *dev_cmd, int txq_id)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
- struct iwl_cmd_meta *out_meta;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
- dma_addr_t phys_addr = 0;
- dma_addr_t txcmd_phys;
- dma_addr_t scratch_phys;
- u16 len, firstlen, secondlen;
- u8 wait_write_ptr = 0;
- __le16 fc = hdr->frame_control;
- u8 hdr_len = ieee80211_hdrlen(fc);
- u16 __maybe_unused wifi_seq;
-
- txq = &trans_pcie->txq[txq_id];
- q = &txq->q;
-
- if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
- WARN_ON_ONCE(1);
- return -EINVAL;
- }
-
- spin_lock(&txq->lock);
-
- /* In AGG mode, the index in the ring must correspond to the WiFi
- * sequence number. This is a HW requirements to help the SCD to parse
- * the BA.
- * Check here that the packets are in the right place on the ring.
- */
-#ifdef CONFIG_IWLWIFI_DEBUG
- wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
- WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&
- ((wifi_seq & 0xff) != q->write_ptr),
- "Q: %d WiFi Seq %d tfdNum %d",
- txq_id, wifi_seq, q->write_ptr);
-#endif
-
- /* Set up driver data for this TFD */
- 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)));
-
- /* Set up first empty entry in queue's array of Tx/cmd buffers */
- out_meta = &txq->entries[q->write_ptr].meta;
-
- /*
- * Use the first empty entry in this queue's command buffer array
- * to contain the Tx command and MAC header concatenated together
- * (payload data will be in another buffer).
- * Size of this varies, due to varying MAC header length.
- * If end is not dword aligned, we'll have 2 extra bytes at the end
- * of the MAC header (device reads on dword boundaries).
- * We'll tell device about this padding later.
- */
- len = sizeof(struct iwl_tx_cmd) +
- sizeof(struct iwl_cmd_header) + hdr_len;
- firstlen = (len + 3) & ~3;
-
- /* Tell NIC about any 2-byte padding after MAC header */
- if (firstlen != len)
- tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
- /* Physical address of this Tx command's header (not MAC header!),
- * within command buffer array. */
- txcmd_phys = dma_map_single(trans->dev,
- &dev_cmd->hdr, firstlen,
- DMA_BIDIRECTIONAL);
- if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
- goto out_err;
- dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
- dma_unmap_len_set(out_meta, len, firstlen);
-
- if (!ieee80211_has_morefrags(fc)) {
- txq->need_update = 1;
- } else {
- wait_write_ptr = 1;
- txq->need_update = 0;
- }
-
- /* Set up TFD's 2nd entry to point directly to remainder of skb,
- * if any (802.11 null frames have no payload). */
- secondlen = skb->len - hdr_len;
- if (secondlen > 0) {
- phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
- secondlen, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
- dma_unmap_single(trans->dev,
- dma_unmap_addr(out_meta, mapping),
- dma_unmap_len(out_meta, len),
- DMA_BIDIRECTIONAL);
- goto out_err;
- }
- }
-
- /* Attach buffers to TFD */
- iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1);
- if (secondlen > 0)
- iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
- secondlen, 0);
-
- scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl_tx_cmd, scratch);
-
- /* take back ownership of DMA buffer to enable update */
- dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
- DMA_BIDIRECTIONAL);
- tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
- tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
- IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
- le16_to_cpu(dev_cmd->hdr.sequence));
- IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-
- /* Set up entry for this TFD in Tx byte-count array */
- iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
-
- dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
- DMA_BIDIRECTIONAL);
-
- trace_iwlwifi_dev_tx(trans->dev,
- &txq->tfds[txq->q.write_ptr],
- sizeof(struct iwl_tfd),
- &dev_cmd->hdr, firstlen,
- skb->data + hdr_len, secondlen);
-
- /* start timer if queue currently empty */
- if (txq->need_update && q->read_ptr == q->write_ptr &&
- trans_pcie->wd_timeout)
- mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
-
- /* Tell device the write index *just past* this latest filled TFD */
- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl_txq_update_write_ptr(trans, txq);
-
- /*
- * At this point the frame is "transmitted" successfully
- * and we will get a TX status notification eventually,
- * regardless of the value of ret. "ret" only indicates
- * whether or not we should update the write pointer.
- */
- if (iwl_queue_space(q) < q->high_mark) {
- if (wait_write_ptr) {
- txq->need_update = 1;
- iwl_txq_update_write_ptr(trans, txq);
- } else {
- iwl_stop_queue(trans, txq);
- }
- }
- spin_unlock(&txq->lock);
- return 0;
- out_err:
- spin_unlock(&txq->lock);
- return -1;
-}
-
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1431,29 +572,28 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
if (!trans_pcie->irq_requested) {
tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
- iwl_irq_tasklet, (unsigned long)trans);
+ iwl_pcie_tasklet, (unsigned long)trans);
- iwl_alloc_isr_ict(trans);
+ iwl_pcie_alloc_ict(trans);
- err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED,
- DRV_NAME, trans);
+ err = request_irq(trans_pcie->irq, iwl_pcie_isr_ict,
+ IRQF_SHARED, DRV_NAME, trans);
if (err) {
IWL_ERR(trans, "Error allocating IRQ %d\n",
trans_pcie->irq);
goto error;
}
- INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish);
trans_pcie->irq_requested = true;
}
- err = iwl_prepare_card_hw(trans);
+ err = iwl_pcie_prepare_card_hw(trans);
if (err) {
IWL_ERR(trans, "Error while preparing HW: %d\n", err);
goto err_free_irq;
}
- iwl_apm_init(trans);
+ iwl_pcie_apm_init(trans);
/* From now on, the op_mode will be kept updated about RF kill state */
iwl_enable_rfkill_int(trans);
@@ -1467,7 +607,7 @@ err_free_irq:
trans_pcie->irq_requested = false;
free_irq(trans_pcie->irq, trans);
error:
- iwl_free_isr_ict(trans);
+ iwl_pcie_free_ict(trans);
tasklet_kill(&trans_pcie->irq_tasklet);
return err;
}
@@ -1483,12 +623,14 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
- iwl_apm_stop(trans);
+ iwl_pcie_apm_stop(trans);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+ iwl_pcie_disable_ict(trans);
+
if (!op_mode_leaving) {
/*
* Even if we stop the HW, we still want the RF kill
@@ -1507,28 +649,6 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
}
}
-static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
- struct sk_buff_head *skbs)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
- /* n_bd is usually 256 => n_bd - 1 = 0xff */
- int tfd_num = ssn & (txq->q.n_bd - 1);
- int freed = 0;
-
- spin_lock(&txq->lock);
-
- if (txq->q.read_ptr != tfd_num) {
- IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
- txq_id, txq->q.read_ptr, tfd_num, ssn);
- freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
- if (iwl_queue_space(&txq->q) > txq->q.low_mark)
- iwl_wake_queue(trans, txq);
- }
-
- spin_unlock(&txq->lock);
-}
-
static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
@@ -1544,6 +664,20 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
}
+static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg)
+{
+ iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT);
+}
+
+static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr,
+ u32 val)
+{
+ iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR,
+ ((addr & 0x0000FFFF) | (3 << 24)));
+ iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
+}
+
static void iwl_trans_pcie_configure(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg)
{
@@ -1575,12 +709,12 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- iwl_trans_pcie_tx_free(trans);
- iwl_trans_pcie_rx_free(trans);
+ iwl_pcie_tx_free(trans);
+ iwl_pcie_rx_free(trans);
if (trans_pcie->irq_requested == true) {
free_irq(trans_pcie->irq, trans);
- iwl_free_isr_ict(trans);
+ iwl_pcie_free_ict(trans);
}
pci_disable_msi(trans_pcie->pci_dev);
@@ -1626,10 +760,10 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
#define IWL_FLUSH_WAIT_MS 2000
-static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
+static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq;
+ struct iwl_txq *txq;
struct iwl_queue *q;
int cnt;
unsigned long now = jiffies;
@@ -1673,7 +807,7 @@ static const char *get_fh_string(int cmd)
#undef IWL_CMD
}
-int iwl_dump_fh(struct iwl_trans *trans, char **buf)
+int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf)
{
int i;
static const u32 fh_tbl[] = {
@@ -1752,7 +886,7 @@ static const char *get_csr_string(int cmd)
#undef IWL_CMD
}
-void iwl_dump_csr(struct iwl_trans *trans)
+void iwl_pcie_dump_csr(struct iwl_trans *trans)
{
int i;
static const u32 csr_tbl[] = {
@@ -1809,7 +943,6 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
const char __user *user_buf, \
size_t count, loff_t *ppos);
-
#define DEBUGFS_READ_FILE_OPS(name) \
DEBUGFS_READ_FUNC(name); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
@@ -1842,7 +975,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
{
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq;
+ struct iwl_txq *txq;
struct iwl_queue *q;
char *buf;
int pos = 0;
@@ -1879,7 +1012,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
{
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+ struct iwl_rxq *rxq = &trans_pcie->rxq;
char buf[256];
int pos = 0;
const size_t bufsz = sizeof(buf);
@@ -1998,7 +1131,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
if (sscanf(buf, "%d", &csr) != 1)
return -EFAULT;
- iwl_dump_csr(trans);
+ iwl_pcie_dump_csr(trans);
return count;
}
@@ -2012,7 +1145,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
int pos = 0;
ssize_t ret = -EFAULT;
- ret = pos = iwl_dump_fh(trans, &buf);
+ ret = pos = iwl_pcie_dump_fh(trans, &buf);
if (buf) {
ret = simple_read_from_buffer(user_buf,
count, ppos, buf, pos);
@@ -2081,7 +1214,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
- .send_cmd = iwl_trans_pcie_send_cmd,
+ .send_cmd = iwl_trans_pcie_send_hcmd,
.tx = iwl_trans_pcie_tx,
.reclaim = iwl_trans_pcie_reclaim,
@@ -2091,7 +1224,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.dbgfs_register = iwl_trans_pcie_dbgfs_register,
- .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty,
+ .wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty,
#ifdef CONFIG_PM_SLEEP
.suspend = iwl_trans_pcie_suspend,
@@ -2100,6 +1233,8 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.write8 = iwl_trans_pcie_write8,
.write32 = iwl_trans_pcie_write32,
.read32 = iwl_trans_pcie_read32,
+ .read_prph = iwl_trans_pcie_read_prph,
+ .write_prph = iwl_trans_pcie_write_prph,
.configure = iwl_trans_pcie_configure,
.set_pmi = iwl_trans_pcie_set_pmi,
};
@@ -2116,7 +1251,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans = kzalloc(sizeof(struct iwl_trans) +
sizeof(struct iwl_trans_pcie), GFP_KERNEL);
- if (WARN_ON(!trans))
+ if (!trans)
return NULL;
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2149,43 +1284,38 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
DMA_BIT_MASK(32));
/* both attempts failed: */
if (err) {
- dev_printk(KERN_ERR, &pdev->dev,
- "No suitable DMA available.\n");
+ dev_err(&pdev->dev, "No suitable DMA available\n");
goto out_pci_disable_device;
}
}
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
- dev_printk(KERN_ERR, &pdev->dev,
- "pci_request_regions failed\n");
+ dev_err(&pdev->dev, "pci_request_regions failed\n");
goto out_pci_disable_device;
}
trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
if (!trans_pcie->hw_base) {
- dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed\n");
+ dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
err = -ENODEV;
goto out_pci_release_regions;
}
- dev_printk(KERN_INFO, &pdev->dev,
- "pci_resource_len = 0x%08llx\n",
- (unsigned long long) pci_resource_len(pdev, 0));
- dev_printk(KERN_INFO, &pdev->dev,
- "pci_resource_base = %p\n", trans_pcie->hw_base);
-
- dev_printk(KERN_INFO, &pdev->dev,
- "HW Revision ID = 0x%X\n", pdev->revision);
-
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
err = pci_enable_msi(pdev);
- if (err)
- dev_printk(KERN_ERR, &pdev->dev,
- "pci_enable_msi failed(0X%x)\n", err);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
+ /* enable rfkill interrupt: hw bug w/a */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+ if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+ pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+ }
+ }
trans->dev = &pdev->dev;
trans_pcie->irq = pdev->irq;
@@ -2195,16 +1325,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
"PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
- /* TODO: Move this away, not needed if not MSI */
- /* enable rfkill interrupt: hw bug w/a */
- pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
- if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
- pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
- }
-
/* Initialize the wait queue for commands */
- init_waitqueue_head(&trans->wait_command_queue);
+ init_waitqueue_head(&trans_pcie->wait_command_queue);
spin_lock_init(&trans->reg_lock);
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 79a4ddc002d3..6c5b867c353a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -42,12 +42,170 @@
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
-/**
- * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill. Driver and device exchange status of each
+ * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ ***************************************************/
+static int iwl_queue_space(const struct iwl_queue *q)
+{
+ int s = q->read_ptr - q->write_ptr;
+
+ if (q->read_ptr > q->write_ptr)
+ s -= q->n_bd;
+
+ if (s <= 0)
+ s += q->n_window;
+ /* keep some reserve to not confuse empty and full situations */
+ s -= 2;
+ if (s < 0)
+ s = 0;
+ return s;
+}
+
+/*
+ * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
+{
+ q->n_bd = count;
+ q->n_window = slots_num;
+ q->id = id;
+
+ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+ * and iwl_queue_dec_wrap are broken. */
+ if (WARN_ON(!is_power_of_2(count)))
+ return -EINVAL;
+
+ /* slots_num must be power-of-two size, otherwise
+ * get_cmd_index is broken. */
+ if (WARN_ON(!is_power_of_2(slots_num)))
+ return -EINVAL;
+
+ q->low_mark = q->n_window / 4;
+ if (q->low_mark < 4)
+ q->low_mark = 4;
+
+ q->high_mark = q->n_window / 8;
+ if (q->high_mark < 2)
+ q->high_mark = 2;
+
+ q->write_ptr = 0;
+ q->read_ptr = 0;
+
+ return 0;
+}
+
+static int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
+ struct iwl_dma_ptr *ptr, size_t size)
+{
+ if (WARN_ON(ptr->addr))
+ return -EINVAL;
+
+ ptr->addr = dma_alloc_coherent(trans->dev, size,
+ &ptr->dma, GFP_KERNEL);
+ if (!ptr->addr)
+ return -ENOMEM;
+ ptr->size = size;
+ return 0;
+}
+
+static void iwl_pcie_free_dma_ptr(struct iwl_trans *trans,
+ struct iwl_dma_ptr *ptr)
+{
+ if (unlikely(!ptr->addr))
+ return;
+
+ dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma);
+ memset(ptr, 0, sizeof(*ptr));
+}
+
+static void iwl_pcie_txq_stuck_timer(unsigned long data)
+{
+ struct iwl_txq *txq = (void *)data;
+ struct iwl_queue *q = &txq->q;
+ struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
+ struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
+ u32 scd_sram_addr = trans_pcie->scd_base_addr +
+ SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
+ u8 buf[16];
+ int i;
+
+ spin_lock(&txq->lock);
+ /* check if triggered erroneously */
+ if (txq->q.read_ptr == txq->q.write_ptr) {
+ spin_unlock(&txq->lock);
+ return;
+ }
+ spin_unlock(&txq->lock);
+
+ IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id,
+ jiffies_to_msecs(trans_pcie->wd_timeout));
+ IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
+ txq->q.read_ptr, txq->q.write_ptr);
+
+ iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
+
+ iwl_print_hex_error(trans, buf, sizeof(buf));
+
+ for (i = 0; i < FH_TCSR_CHNL_NUM; i++)
+ IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i,
+ iwl_read_direct32(trans, FH_TX_TRB_REG(i)));
+
+ for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
+ u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i));
+ u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
+ bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
+ u32 tbl_dw =
+ iwl_read_targ_mem(trans,
+ trans_pcie->scd_base_addr +
+ SCD_TRANS_TBL_OFFSET_QUEUE(i));
+
+ if (i & 0x1)
+ tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
+ else
+ tbl_dw = tbl_dw & 0x0000FFFF;
+
+ IWL_ERR(trans,
+ "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
+ i, active ? "" : "in", fifo, tbl_dw,
+ iwl_read_prph(trans,
+ SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
+ iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
+ }
+
+ for (i = q->read_ptr; i != q->write_ptr;
+ i = iwl_queue_inc_wrap(i, q->n_bd)) {
+ struct iwl_tx_cmd *tx_cmd =
+ (struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
+ IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
+ get_unaligned_le32(&tx_cmd->scratch));
+ }
+
+ iwl_op_mode_nic_error(trans->op_mode);
+}
+
+/*
+ * iwl_pcie_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
- struct iwl_tx_queue *txq,
- u16 byte_cnt)
+static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
+ struct iwl_txq *txq, u16 byte_cnt)
{
struct iwlagn_scd_bc_tbl *scd_bc_tbl;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -88,10 +246,36 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
-/**
- * iwl_txq_update_write_ptr - Send new write index to hardware
+static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
+ struct iwl_txq *txq)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
+ int txq_id = txq->q.id;
+ int read_ptr = txq->q.read_ptr;
+ u8 sta_id = 0;
+ __le16 bc_ent;
+ struct iwl_tx_cmd *tx_cmd =
+ (void *)txq->entries[txq->q.read_ptr].cmd->payload;
+
+ WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+
+ if (txq_id != trans_pcie->cmd_queue)
+ sta_id = tx_cmd->sta_id;
+
+ bc_ent = cpu_to_le16(1 | (sta_id << 12));
+ scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+
+ if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+}
+
+/*
+ * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware
*/
-void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
+void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
{
u32 reg = 0;
int txq_id = txq->q.id;
@@ -137,7 +321,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
txq->need_update = 0;
}
-static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
@@ -149,15 +333,15 @@ static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
return addr;
}
-static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
return le16_to_cpu(tb->hi_n_len) >> 4;
}
-static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
- dma_addr_t addr, u16 len)
+static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+ dma_addr_t addr, u16 len)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
u16 hi_n_len = len << 4;
@@ -171,19 +355,20 @@ static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
tfd->num_tbs = idx + 1;
}
-static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd)
{
return tfd->num_tbs & 0x1f;
}
-static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
- struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
+static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
+ struct iwl_cmd_meta *meta, struct iwl_tfd *tfd,
+ enum dma_data_direction dma_dir)
{
int i;
int num_tbs;
/* Sanity check on number of chunks */
- num_tbs = iwl_tfd_get_num_tbs(tfd);
+ num_tbs = iwl_pcie_tfd_get_num_tbs(tfd);
if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
@@ -200,14 +385,14 @@ static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++)
- dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i),
- iwl_tfd_tb_get_len(tfd, i), dma_dir);
+ dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i),
+ iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir);
tfd->num_tbs = 0;
}
-/**
- * iwl_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+/*
+ * iwl_pcie_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
* @trans - transport private data
* @txq - tx queue
* @dma_dir - the direction of the DMA mapping
@@ -215,8 +400,8 @@ static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
-void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
- enum dma_data_direction dma_dir)
+static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
+ enum dma_data_direction dma_dir)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
@@ -227,8 +412,8 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
lockdep_assert_held(&txq->lock);
/* We have only q->n_window txq->entries, but we use q->n_bd tfds */
- iwl_unmap_tfd(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
- dma_dir);
+ iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
+ dma_dir);
/* free SKB */
if (txq->entries) {
@@ -247,10 +432,8 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
}
}
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
- struct iwl_tx_queue *txq,
- dma_addr_t addr, u16 len,
- u8 reset)
+static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
+ dma_addr_t addr, u16 len, u8 reset)
{
struct iwl_queue *q;
struct iwl_tfd *tfd, *tfd_tmp;
@@ -263,7 +446,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
if (reset)
memset(tfd, 0, sizeof(*tfd));
- num_tbs = iwl_tfd_get_num_tbs(tfd);
+ num_tbs = iwl_pcie_tfd_get_num_tbs(tfd);
/* Each TFD can point to a maximum 20 Tx buffers */
if (num_tbs >= IWL_NUM_OF_TBS) {
@@ -279,108 +462,534 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
IWL_ERR(trans, "Unaligned address = %llx\n",
(unsigned long long)addr);
- iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+ iwl_pcie_tfd_set_tb(tfd, num_tbs, addr, len);
return 0;
}
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill. Driver and device exchange status of each
- * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
+static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
+ struct iwl_txq *txq, int slots_num,
+ u32 txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+ int i;
+
+ if (WARN_ON(txq->entries || txq->tfds))
+ return -EINVAL;
+
+ setup_timer(&txq->stuck_timer, iwl_pcie_txq_stuck_timer,
+ (unsigned long)txq);
+ txq->trans_pcie = trans_pcie;
+
+ txq->q.n_window = slots_num;
+
+ txq->entries = kcalloc(slots_num,
+ sizeof(struct iwl_pcie_txq_entry),
+ GFP_KERNEL);
+
+ if (!txq->entries)
+ goto error;
+
+ if (txq_id == trans_pcie->cmd_queue)
+ for (i = 0; i < slots_num; i++) {
+ txq->entries[i].cmd =
+ kmalloc(sizeof(struct iwl_device_cmd),
+ GFP_KERNEL);
+ if (!txq->entries[i].cmd)
+ goto error;
+ }
+
+ /* Circular buffer of transmit frame descriptors (TFDs),
+ * shared with device */
+ txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz,
+ &txq->q.dma_addr, GFP_KERNEL);
+ if (!txq->tfds) {
+ IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
+ goto error;
+ }
+ txq->q.id = txq_id;
+
+ return 0;
+error:
+ if (txq->entries && txq_id == trans_pcie->cmd_queue)
+ for (i = 0; i < slots_num; i++)
+ kfree(txq->entries[i].cmd);
+ kfree(txq->entries);
+ txq->entries = NULL;
+
+ return -ENOMEM;
+
+}
+
+static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
+ int slots_num, u32 txq_id)
+{
+ int ret;
+
+ txq->need_update = 0;
+
+ /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+ /* Initialize queue's high/low-water marks, and head/tail indexes */
+ ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
+ txq_id);
+ if (ret)
+ return ret;
+
+ spin_lock_init(&txq->lock);
+
+ /*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ * Circular buffer (TFD queue in DRAM) physical base address */
+ iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id),
+ txq->q.dma_addr >> 8);
+
+ return 0;
+}
+
+/*
+ * iwl_pcie_txq_unmap - Unmap any remaining DMA mappings and free skb's
+ */
+static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+ struct iwl_queue *q = &txq->q;
+ enum dma_data_direction dma_dir;
+
+ if (!q->n_bd)
+ return;
+
+ /* In the command queue, all the TBs are mapped as BIDI
+ * so unmap them as such.
+ */
+ if (txq_id == trans_pcie->cmd_queue)
+ dma_dir = DMA_BIDIRECTIONAL;
+ else
+ dma_dir = DMA_TO_DEVICE;
+
+ spin_lock_bh(&txq->lock);
+ while (q->write_ptr != q->read_ptr) {
+ iwl_pcie_txq_free_tfd(trans, txq, dma_dir);
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+ }
+ spin_unlock_bh(&txq->lock);
+}
+
+/*
+ * iwl_pcie_txq_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
*
- ***************************************************/
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+ struct device *dev = trans->dev;
+ int i;
+
+ if (WARN_ON(!txq))
+ return;
+
+ iwl_pcie_txq_unmap(trans, txq_id);
-int iwl_queue_space(const struct iwl_queue *q)
+ /* De-alloc array of command/tx buffers */
+ if (txq_id == trans_pcie->cmd_queue)
+ for (i = 0; i < txq->q.n_window; i++) {
+ kfree(txq->entries[i].cmd);
+ kfree(txq->entries[i].copy_cmd);
+ kfree(txq->entries[i].free_buf);
+ }
+
+ /* De-alloc circular buffer of TFDs */
+ if (txq->q.n_bd) {
+ dma_free_coherent(dev, sizeof(struct iwl_tfd) *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
+ }
+
+ kfree(txq->entries);
+ txq->entries = NULL;
+
+ del_timer_sync(&txq->stuck_timer);
+
+ /* 0-fill queue descriptor structure */
+ memset(txq, 0, sizeof(*txq));
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ */
+static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask)
{
- int s = q->read_ptr - q->write_ptr;
+ struct iwl_trans_pcie __maybe_unused *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
- if (q->read_ptr > q->write_ptr)
- s -= q->n_bd;
+ iwl_write_prph(trans, SCD_TXFACT, mask);
+}
- if (s <= 0)
- s += q->n_window;
- /* keep some reserve to not confuse empty and full situations */
- s -= 2;
- if (s < 0)
- s = 0;
- return s;
+void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 a;
+ int chan;
+ u32 reg_val;
+
+ /* make sure all queue are not stopped/used */
+ memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
+ memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+
+ trans_pcie->scd_base_addr =
+ iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
+
+ WARN_ON(scd_base_addr != 0 &&
+ scd_base_addr != trans_pcie->scd_base_addr);
+
+ a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
+ /* reset conext data memory */
+ for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
+ a += 4)
+ iwl_write_targ_mem(trans, a, 0);
+ /* reset tx status memory */
+ for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
+ a += 4)
+ iwl_write_targ_mem(trans, a, 0);
+ for (; a < trans_pcie->scd_base_addr +
+ SCD_TRANS_TBL_OFFSET_QUEUE(
+ trans->cfg->base_params->num_of_queues);
+ a += 4)
+ iwl_write_targ_mem(trans, a, 0);
+
+ iwl_write_prph(trans, SCD_DRAM_BASE_ADDR,
+ trans_pcie->scd_bc_tbls.dma >> 10);
+
+ /* The chain extension of the SCD doesn't work well. This feature is
+ * enabled by default by the HW, so we need to disable it manually.
+ */
+ iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
+
+ iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
+ trans_pcie->cmd_fifo);
+
+ /* Activate all Tx DMA/FIFO channels */
+ iwl_pcie_txq_set_sched(trans, IWL_MASK(0, 7));
+
+ /* Enable DMA channel */
+ for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++)
+ iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+ /* Update FH chicken bits */
+ reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG);
+ iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG,
+ reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+ /* Enable L1-Active */
+ iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
+ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
}
-/**
- * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
+/*
+ * iwl_pcie_tx_stop - Stop all Tx DMA channels
*/
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
+int iwl_pcie_tx_stop(struct iwl_trans *trans)
{
- q->n_bd = count;
- q->n_window = slots_num;
- q->id = id;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int ch, txq_id, ret;
+ unsigned long flags;
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
- * and iwl_queue_dec_wrap are broken. */
- if (WARN_ON(!is_power_of_2(count)))
- return -EINVAL;
+ /* Turn off all Tx DMA fifos */
+ spin_lock_irqsave(&trans_pcie->irq_lock, flags);
- /* slots_num must be power-of-two size, otherwise
- * get_cmd_index is broken. */
- if (WARN_ON(!is_power_of_2(slots_num)))
- return -EINVAL;
+ iwl_pcie_txq_set_sched(trans, 0);
- q->low_mark = q->n_window / 4;
- if (q->low_mark < 4)
- q->low_mark = 4;
+ /* Stop each Tx DMA channel, and wait for it to be idle */
+ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
+ iwl_write_direct32(trans,
+ FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+ ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
+ if (ret < 0)
+ IWL_ERR(trans,
+ "Failing on timeout while stopping DMA channel %d [0x%08x]\n",
+ ch,
+ iwl_read_direct32(trans,
+ FH_TSSR_TX_STATUS_REG));
+ }
+ spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
- q->high_mark = q->n_window / 8;
- if (q->high_mark < 2)
- q->high_mark = 2;
+ if (!trans_pcie->txq) {
+ IWL_WARN(trans,
+ "Stopping tx queues that aren't allocated...\n");
+ return 0;
+ }
- q->write_ptr = q->read_ptr = 0;
+ /* Unmap DMA from host system and free skb's */
+ for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+ txq_id++)
+ iwl_pcie_txq_unmap(trans, txq_id);
return 0;
}
-static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
- struct iwl_tx_queue *txq)
+/*
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl_pcie_tx_free(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
- int txq_id = txq->q.id;
- int read_ptr = txq->q.read_ptr;
- u8 sta_id = 0;
- __le16 bc_ent;
- struct iwl_tx_cmd *tx_cmd =
- (void *)txq->entries[txq->q.read_ptr].cmd->payload;
+ int txq_id;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+ /* Tx queues */
+ if (trans_pcie->txq) {
+ for (txq_id = 0;
+ txq_id < trans->cfg->base_params->num_of_queues; txq_id++)
+ iwl_pcie_txq_free(trans, txq_id);
+ }
- if (txq_id != trans_pcie->cmd_queue)
- sta_id = tx_cmd->sta_id;
+ kfree(trans_pcie->txq);
+ trans_pcie->txq = NULL;
- bc_ent = cpu_to_le16(1 | (sta_id << 12));
- scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+ iwl_pcie_free_dma_ptr(trans, &trans_pcie->kw);
- if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
- scd_bc_tbl[txq_id].
- tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+ iwl_pcie_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
+}
+
+/*
+ * iwl_pcie_tx_alloc - allocate TX context
+ * Allocate all Tx DMA structures and initialize them
+ */
+static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
+{
+ int ret;
+ int txq_id, slots_num;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues *
+ sizeof(struct iwlagn_scd_bc_tbl);
+
+ /*It is not allowed to alloc twice, so warn when this happens.
+ * We cannot rely on the previous allocation, so free and fail */
+ if (WARN_ON(trans_pcie->txq)) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
+ scd_bc_tbls_size);
+ if (ret) {
+ IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
+ goto error;
+ }
+
+ /* Alloc keep-warm buffer */
+ ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
+ if (ret) {
+ IWL_ERR(trans, "Keep Warm allocation failed\n");
+ goto error;
+ }
+
+ trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues,
+ sizeof(struct iwl_txq), GFP_KERNEL);
+ if (!trans_pcie->txq) {
+ IWL_ERR(trans, "Not enough memory for txq\n");
+ ret = ENOMEM;
+ goto error;
+ }
+
+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+ for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+ txq_id++) {
+ slots_num = (txq_id == trans_pcie->cmd_queue) ?
+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ ret = iwl_pcie_txq_alloc(trans, &trans_pcie->txq[txq_id],
+ slots_num, txq_id);
+ if (ret) {
+ IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ iwl_pcie_tx_free(trans);
+
+ return ret;
+}
+int iwl_pcie_tx_init(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int ret;
+ int txq_id, slots_num;
+ unsigned long flags;
+ bool alloc = false;
+
+ if (!trans_pcie->txq) {
+ ret = iwl_pcie_tx_alloc(trans);
+ if (ret)
+ goto error;
+ alloc = true;
+ }
+
+ spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
+ /* Turn off all Tx DMA fifos */
+ iwl_write_prph(trans, SCD_TXFACT, 0);
+
+ /* Tell NIC where to find the "keep warm" buffer */
+ iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
+ trans_pcie->kw.dma >> 4);
+
+ spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+ for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+ txq_id++) {
+ slots_num = (txq_id == trans_pcie->cmd_queue) ?
+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ ret = iwl_pcie_txq_init(trans, &trans_pcie->txq[txq_id],
+ slots_num, txq_id);
+ if (ret) {
+ IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
+ goto error;
+ }
+ }
+
+ return 0;
+error:
+ /*Upon error, free only if we allocated something */
+ if (alloc)
+ iwl_pcie_tx_free(trans);
+ return ret;
+}
+
+static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie,
+ struct iwl_txq *txq)
+{
+ if (!trans_pcie->wd_timeout)
+ return;
+
+ /*
+ * if empty delete timer, otherwise move timer forward
+ * since we're making progress on this queue
+ */
+ if (txq->q.read_ptr == txq->q.write_ptr)
+ del_timer(&txq->stuck_timer);
+ else
+ mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
+}
+
+/* Frees buffers until index _not_ inclusive */
+void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+ struct sk_buff_head *skbs)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+ /* n_bd is usually 256 => n_bd - 1 = 0xff */
+ int tfd_num = ssn & (txq->q.n_bd - 1);
+ struct iwl_queue *q = &txq->q;
+ int last_to_free;
+
+ /* This function is not meant to release cmd queue*/
+ if (WARN_ON(txq_id == trans_pcie->cmd_queue))
+ return;
+
+ spin_lock(&txq->lock);
+
+ if (txq->q.read_ptr == tfd_num)
+ goto out;
+
+ IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
+ txq_id, txq->q.read_ptr, tfd_num, ssn);
+
+ /*Since we free until index _not_ inclusive, the one before index is
+ * the last we will free. This one must be used */
+ last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd);
+
+ if (!iwl_queue_used(q, last_to_free)) {
+ IWL_ERR(trans,
+ "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
+ __func__, txq_id, last_to_free, q->n_bd,
+ q->write_ptr, q->read_ptr);
+ goto out;
+ }
+
+ if (WARN_ON(!skb_queue_empty(skbs)))
+ goto out;
+
+ for (;
+ q->read_ptr != tfd_num;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+ if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
+ continue;
+
+ __skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb);
+
+ txq->entries[txq->q.read_ptr].skb = NULL;
+
+ iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
+
+ iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
+ }
+
+ iwl_pcie_txq_progress(trans_pcie, txq);
+
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark)
+ iwl_wake_queue(trans, txq);
+out:
+ spin_unlock(&txq->lock);
}
-static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
+/*
+ * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+ struct iwl_queue *q = &txq->q;
+ int nfreed = 0;
+
+ lockdep_assert_held(&txq->lock);
+
+ if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) {
+ IWL_ERR(trans,
+ "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
+ __func__, txq_id, idx, q->n_bd,
+ q->write_ptr, q->read_ptr);
+ return;
+ }
+
+ for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+ 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_pcie_txq_progress(trans_pcie, txq);
+}
+
+static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
u16 txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -405,7 +1014,8 @@ static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
return 0;
}
-static inline void iwl_txq_set_inactive(struct iwl_trans *trans, u16 txq_id)
+static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans,
+ u16 txq_id)
{
/* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
@@ -424,7 +1034,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
WARN_ONCE(1, "queue %d already used - expect issues", txq_id);
/* Stop this Tx queue before configuring it */
- iwl_txq_set_inactive(trans, txq_id);
+ iwl_pcie_txq_set_inactive(trans, txq_id);
/* Set this queue as a chain-building queue unless it is CMD queue */
if (txq_id != trans_pcie->cmd_queue)
@@ -435,7 +1045,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
u16 ra_tid = BUILD_RAxTID(sta_id, tid);
/* Map receiver-address / traffic-ID to this queue */
- iwl_txq_set_ratid_map(trans, ra_tid, txq_id);
+ iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id);
/* enable aggregations for the queue */
iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
@@ -480,20 +1090,29 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 stts_addr = trans_pcie->scd_base_addr +
+ SCD_TX_STTS_QUEUE_OFFSET(txq_id);
+ static const u32 zero_val[4] = {};
if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
WARN_ONCE(1, "queue %d not used", txq_id);
return;
}
- iwl_txq_set_inactive(trans, txq_id);
+ iwl_pcie_txq_set_inactive(trans, txq_id);
+
+ _iwl_write_targ_mem_dwords(trans, stts_addr,
+ zero_val, ARRAY_SIZE(zero_val));
+
+ iwl_pcie_txq_unmap(trans, txq_id);
+
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
}
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
-/**
- * iwl_enqueue_hcmd - enqueue a uCode command
+/*
+ * iwl_pcie_enqueue_hcmd - enqueue a uCode command
* @priv: device private data point
* @cmd: a point to the ucode command structure
*
@@ -501,15 +1120,17 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
* failed. On success, it turns the index (> 0) of command in the
* command queue.
*/
-static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
+ void *dup_buf = NULL;
dma_addr_t phys_addr;
- u32 idx;
+ int idx;
u16 copy_size, cmd_size;
bool had_nocopy = false;
int i;
@@ -526,10 +1147,33 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
continue;
if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
had_nocopy = true;
+ if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
+ idx = -EINVAL;
+ goto free_dup_buf;
+ }
+ } else if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) {
+ /*
+ * This is also a chunk that isn't copied
+ * to the static buffer so set had_nocopy.
+ */
+ had_nocopy = true;
+
+ /* only allowed once */
+ if (WARN_ON(dup_buf)) {
+ idx = -EINVAL;
+ goto free_dup_buf;
+ }
+
+ dup_buf = kmemdup(cmd->data[i], cmd->len[i],
+ GFP_ATOMIC);
+ if (!dup_buf)
+ return -ENOMEM;
} else {
/* NOCOPY must not be followed by normal! */
- if (WARN_ON(had_nocopy))
- return -EINVAL;
+ if (WARN_ON(had_nocopy)) {
+ idx = -EINVAL;
+ goto free_dup_buf;
+ }
copy_size += cmd->len[i];
}
cmd_size += cmd->len[i];
@@ -541,8 +1185,12 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
* allocated into separate TFDs, then we will need to
* increase the size of the buffers.
*/
- if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
- return -EINVAL;
+ if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE,
+ "Command %s (%#x) is too large (%d bytes)\n",
+ get_cmd_string(trans_pcie, cmd->id), cmd->id, copy_size)) {
+ idx = -EINVAL;
+ goto free_dup_buf;
+ }
spin_lock_bh(&txq->lock);
@@ -551,7 +1199,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
IWL_ERR(trans, "No space in command queue\n");
iwl_op_mode_cmd_queue_full(trans->op_mode);
- return -ENOSPC;
+ idx = -ENOSPC;
+ goto free_dup_buf;
}
idx = get_cmd_index(q, q->write_ptr);
@@ -575,7 +1224,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
continue;
- if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
+ if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+ IWL_HCMD_DFL_DUP))
break;
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
cmd_pos += cmd->len[i];
@@ -600,7 +1250,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
IWL_DEBUG_HC(trans,
"Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n",
- trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd),
+ get_cmd_string(trans_pcie, out_cmd->hdr.cmd),
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
@@ -614,28 +1264,35 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
dma_unmap_addr_set(out_meta, mapping, phys_addr);
dma_unmap_len_set(out_meta, len, copy_size);
- iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1);
+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+ const void *data = cmd->data[i];
+
if (!cmd->len[i])
continue;
- if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
+ if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+ IWL_HCMD_DFL_DUP)))
continue;
- phys_addr = dma_map_single(trans->dev, (void *)cmd->data[i],
+ if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
+ data = dup_buf;
+ phys_addr = dma_map_single(trans->dev, (void *)data,
cmd->len[i], DMA_BIDIRECTIONAL);
if (dma_mapping_error(trans->dev, phys_addr)) {
- iwl_unmap_tfd(trans, out_meta,
- &txq->tfds[q->write_ptr],
- DMA_BIDIRECTIONAL);
+ iwl_pcie_tfd_unmap(trans, out_meta,
+ &txq->tfds[q->write_ptr],
+ DMA_BIDIRECTIONAL);
idx = -ENOMEM;
goto out;
}
- iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
- cmd->len[i], 0);
+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
}
out_meta->flags = cmd->flags;
+ if (WARN_ON_ONCE(txq->entries[idx].free_buf))
+ kfree(txq->entries[idx].free_buf);
+ txq->entries[idx].free_buf = dup_buf;
txq->need_update = 1;
@@ -648,70 +1305,18 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
/* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- iwl_txq_update_write_ptr(trans, txq);
+ iwl_pcie_txq_inc_wr_ptr(trans, txq);
out:
spin_unlock_bh(&txq->lock);
+ free_dup_buf:
+ if (idx < 0)
+ kfree(dup_buf);
return idx;
}
-static inline void iwl_queue_progress(struct iwl_trans_pcie *trans_pcie,
- struct iwl_tx_queue *txq)
-{
- if (!trans_pcie->wd_timeout)
- return;
-
- /*
- * if empty delete timer, otherwise move timer forward
- * since we're making progress on this queue
- */
- if (txq->q.read_ptr == txq->q.write_ptr)
- del_timer(&txq->stuck_timer);
- else
- mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
-}
-
-/**
- * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms. If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
- int idx)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- int nfreed = 0;
-
- lockdep_assert_held(&txq->lock);
-
- if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
- IWL_ERR(trans,
- "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
- __func__, txq_id, idx, q->n_bd,
- q->write_ptr, q->read_ptr);
- return;
- }
-
- for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
- 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_queue_progress(trans_pcie, txq);
-}
-
-/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+/*
+ * iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them
* @rxb: Rx buffer to reclaim
* @handler_status: return value of the handler of the command
* (put in setup_rx_handlers)
@@ -720,8 +1325,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/
-void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
- int handler_status)
+void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
+ struct iwl_rx_cmd_buffer *rxb, int handler_status)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -731,7 +1336,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -751,7 +1356,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
cmd = txq->entries[cmd_index].cmd;
meta = &txq->entries[cmd_index].meta;
- iwl_unmap_tfd(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+ iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
@@ -763,20 +1368,18 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
meta->source->handler_status = handler_status;
}
- iwl_hcmd_queue_reclaim(trans, txq_id, index);
+ iwl_pcie_cmdq_reclaim(trans, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) {
if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
IWL_WARN(trans,
"HCMD_ACTIVE already clear for command %s\n",
- trans_pcie_get_cmd_string(trans_pcie,
- cmd->hdr.cmd));
+ get_cmd_string(trans_pcie, cmd->hdr.cmd));
}
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
- trans_pcie_get_cmd_string(trans_pcie,
- cmd->hdr.cmd));
- wake_up(&trans->wait_command_queue);
+ get_cmd_string(trans_pcie, cmd->hdr.cmd));
+ wake_up(&trans_pcie->wait_command_queue);
}
meta->flags = 0;
@@ -786,7 +1389,8 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
-static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
@@ -795,59 +1399,59 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (WARN_ON(cmd->flags & CMD_WANT_SKB))
return -EINVAL;
-
- ret = iwl_enqueue_hcmd(trans, cmd);
+ ret = iwl_pcie_enqueue_hcmd(trans, cmd);
if (ret < 0) {
IWL_ERR(trans,
"Error sending %s: enqueue_hcmd failed: %d\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret);
+ get_cmd_string(trans_pcie, cmd->id), ret);
return ret;
}
return 0;
}
-static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int cmd_idx;
int ret;
IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+ get_cmd_string(trans_pcie, cmd->id));
if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE,
&trans_pcie->status))) {
IWL_ERR(trans, "Command %s: a command is already active!\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+ get_cmd_string(trans_pcie, cmd->id));
return -EIO;
}
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+ get_cmd_string(trans_pcie, cmd->id));
- cmd_idx = iwl_enqueue_hcmd(trans, cmd);
+ cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
IWL_ERR(trans,
"Error sending %s: enqueue_hcmd failed: %d\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret);
+ get_cmd_string(trans_pcie, cmd->id), ret);
return ret;
}
- ret = wait_event_timeout(trans->wait_command_queue,
+ ret = wait_event_timeout(trans_pcie->wait_command_queue,
!test_bit(STATUS_HCMD_ACTIVE,
&trans_pcie->status),
HOST_COMPLETE_TIMEOUT);
if (!ret) {
if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
- struct iwl_tx_queue *txq =
+ 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",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id),
+ get_cmd_string(trans_pcie, cmd->id),
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
IWL_ERR(trans,
@@ -857,16 +1461,28 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
IWL_DEBUG_INFO(trans,
"Clearing HCMD_ACTIVE for command %s\n",
- trans_pcie_get_cmd_string(trans_pcie,
- cmd->id));
+ get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT;
goto cancel;
}
}
+ if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
+ IWL_ERR(trans, "FW error in SYNC CMD %s\n",
+ get_cmd_string(trans_pcie, cmd->id));
+ ret = -EIO;
+ goto cancel;
+ }
+
+ if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
+ IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n");
+ ret = -ERFKILL;
+ goto cancel;
+ }
+
if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) {
IWL_ERR(trans, "Error: Response NULL in '%s'\n",
- trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+ get_cmd_string(trans_pcie, cmd->id));
ret = -EIO;
goto cancel;
}
@@ -893,64 +1509,183 @@ cancel:
return ret;
}
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
+ return -EIO;
+
+ if (test_bit(STATUS_RFKILL, &trans_pcie->status))
+ return -ERFKILL;
+
if (cmd->flags & CMD_ASYNC)
- return iwl_send_cmd_async(trans, cmd);
+ return iwl_pcie_send_hcmd_async(trans, cmd);
- return iwl_send_cmd_sync(trans, cmd);
+ /* We still can fail on RFKILL that can be asserted while we wait */
+ return iwl_pcie_send_hcmd_sync(trans, cmd);
}
-/* Frees buffers until index _not_ inclusive */
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
- struct sk_buff_head *skbs)
+int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_cmd *dev_cmd, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- int last_to_free;
- int freed = 0;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
+ struct iwl_cmd_meta *out_meta;
+ struct iwl_txq *txq;
+ struct iwl_queue *q;
+ dma_addr_t phys_addr = 0;
+ dma_addr_t txcmd_phys;
+ dma_addr_t scratch_phys;
+ u16 len, firstlen, secondlen;
+ u8 wait_write_ptr = 0;
+ __le16 fc = hdr->frame_control;
+ u8 hdr_len = ieee80211_hdrlen(fc);
+ u16 __maybe_unused wifi_seq;
+
+ txq = &trans_pcie->txq[txq_id];
+ q = &txq->q;
- /* This function is not meant to release cmd queue*/
- if (WARN_ON(txq_id == trans_pcie->cmd_queue))
- return 0;
+ if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
- lockdep_assert_held(&txq->lock);
+ spin_lock(&txq->lock);
- /*Since we free until index _not_ inclusive, the one before index is
- * the last we will free. This one must be used */
- last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
+ /* In AGG mode, the index in the ring must correspond to the WiFi
+ * sequence number. This is a HW requirements to help the SCD to parse
+ * the BA.
+ * Check here that the packets are in the right place on the ring.
+ */
+#ifdef CONFIG_IWLWIFI_DEBUG
+ wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+ WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&
+ ((wifi_seq & 0xff) != q->write_ptr),
+ "Q: %d WiFi Seq %d tfdNum %d",
+ txq_id, wifi_seq, q->write_ptr);
+#endif
+
+ /* Set up driver data for this TFD */
+ 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)));
+
+ /* Set up first empty entry in queue's array of Tx/cmd buffers */
+ out_meta = &txq->entries[q->write_ptr].meta;
- if ((index >= q->n_bd) ||
- (iwl_queue_used(q, last_to_free) == 0)) {
- IWL_ERR(trans,
- "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
- __func__, txq_id, last_to_free, q->n_bd,
- q->write_ptr, q->read_ptr);
- return 0;
+ /*
+ * Use the first empty entry in this queue's command buffer array
+ * to contain the Tx command and MAC header concatenated together
+ * (payload data will be in another buffer).
+ * Size of this varies, due to varying MAC header length.
+ * If end is not dword aligned, we'll have 2 extra bytes at the end
+ * of the MAC header (device reads on dword boundaries).
+ * We'll tell device about this padding later.
+ */
+ len = sizeof(struct iwl_tx_cmd) +
+ sizeof(struct iwl_cmd_header) + hdr_len;
+ firstlen = (len + 3) & ~3;
+
+ /* Tell NIC about any 2-byte padding after MAC header */
+ if (firstlen != len)
+ tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+ /* Physical address of this Tx command's header (not MAC header!),
+ * within command buffer array. */
+ txcmd_phys = dma_map_single(trans->dev,
+ &dev_cmd->hdr, firstlen,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
+ goto out_err;
+ dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ dma_unmap_len_set(out_meta, len, firstlen);
+
+ if (!ieee80211_has_morefrags(fc)) {
+ txq->need_update = 1;
+ } else {
+ wait_write_ptr = 1;
+ txq->need_update = 0;
}
- if (WARN_ON(!skb_queue_empty(skbs)))
- return 0;
+ /* Set up TFD's 2nd entry to point directly to remainder of skb,
+ * if any (802.11 null frames have no payload). */
+ secondlen = skb->len - hdr_len;
+ if (secondlen > 0) {
+ phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
+ secondlen, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
+ dma_unmap_single(trans->dev,
+ dma_unmap_addr(out_meta, mapping),
+ dma_unmap_len(out_meta, len),
+ DMA_BIDIRECTIONAL);
+ goto out_err;
+ }
+ }
- for (;
- q->read_ptr != index;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ /* Attach buffers to TFD */
+ iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1);
+ if (secondlen > 0)
+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0);
- if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
- continue;
+ scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+ offsetof(struct iwl_tx_cmd, scratch);
- __skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb);
+ /* take back ownership of DMA buffer to enable update */
+ dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
+ DMA_BIDIRECTIONAL);
+ tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
- txq->entries[txq->q.read_ptr].skb = NULL;
+ IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
+ le16_to_cpu(dev_cmd->hdr.sequence));
+ IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
- iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
+ /* Set up entry for this TFD in Tx byte-count array */
+ iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
- iwl_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
- freed++;
- }
+ dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
+ DMA_BIDIRECTIONAL);
+
+ trace_iwlwifi_dev_tx(trans->dev, skb,
+ &txq->tfds[txq->q.write_ptr],
+ sizeof(struct iwl_tfd),
+ &dev_cmd->hdr, firstlen,
+ skb->data + hdr_len, secondlen);
+ trace_iwlwifi_dev_tx_data(trans->dev, skb,
+ skb->data + hdr_len, secondlen);
- iwl_queue_progress(trans_pcie, txq);
+ /* start timer if queue currently empty */
+ if (txq->need_update && q->read_ptr == q->write_ptr &&
+ trans_pcie->wd_timeout)
+ mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
+
+ /* Tell device the write index *just past* this latest filled TFD */
+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ iwl_pcie_txq_inc_wr_ptr(trans, txq);
- return freed;
+ /*
+ * At this point the frame is "transmitted" successfully
+ * and we will get a TX status notification eventually,
+ * regardless of the value of ret. "ret" only indicates
+ * whether or not we should update the write pointer.
+ */
+ if (iwl_queue_space(q) < q->high_mark) {
+ if (wait_write_ptr) {
+ txq->need_update = 1;
+ iwl_pcie_txq_inc_wr_ptr(trans, txq);
+ } else {
+ iwl_stop_queue(trans, txq);
+ }
+ }
+ spin_unlock(&txq->lock);
+ return 0;
+out_err:
+ spin_unlock(&txq->lock);
+ return -1;
}
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 1c10b542ab23..ec6d5d6b452e 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -298,6 +298,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
const u8 *rates_eid, *ext_rates_eid;
int n = 0;
+ rcu_read_lock();
rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
@@ -325,6 +326,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
*tlv++ = 0x96;
n = 4;
}
+ rcu_read_unlock();
rate_tlv->header.len = cpu_to_le16(n);
return sizeof(rate_tlv->header) + n;
@@ -436,19 +438,19 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
*/
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
- enum nl80211_channel_type channel_type)
+ struct cfg80211_chan_def *chandef)
{
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;
lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
- channel->center_freq, channel_type);
+ chandef->chan->center_freq,
+ cfg80211_get_chandef_type(chandef));
- if (channel_type != NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
goto out;
- ret = lbs_set_channel(priv, channel->hw_value);
+ ret = lbs_set_channel(priv, chandef->chan->hw_value);
out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -1140,11 +1142,13 @@ static int lbs_associate(struct lbs_private *priv,
cmd->capability = cpu_to_le16(bss->capability);
/* add SSID TLV */
+ rcu_read_lock();
ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
if (ssid_eid)
pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
else
lbs_deb_assoc("no SSID\n");
+ rcu_read_unlock();
/* add DS param TLV */
if (bss->channel)
@@ -1734,7 +1738,7 @@ static void lbs_join_post(struct lbs_private *priv,
/* Fake DS channel IE */
*fake++ = WLAN_EID_DS_PARAMS;
*fake++ = 1;
- *fake++ = params->channel->hw_value;
+ *fake++ = params->chandef.chan->hw_value;
/* Fake IBSS params IE */
*fake++ = WLAN_EID_IBSS_PARAMS;
*fake++ = 2;
@@ -1755,7 +1759,7 @@ static void lbs_join_post(struct lbs_private *priv,
lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
bss = cfg80211_inform_bss(priv->wdev->wiphy,
- params->channel,
+ params->chandef.chan,
bssid,
0,
capability,
@@ -1782,7 +1786,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
struct cfg80211_ibss_params *params,
struct cfg80211_bss *bss)
{
- const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
+ const u8 *rates_eid;
struct cmd_ds_802_11_ad_hoc_join cmd;
u8 preamble = RADIO_PREAMBLE_SHORT;
int ret = 0;
@@ -1833,7 +1837,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
cmd.bss.ds.header.len = 1;
- cmd.bss.ds.channel = params->channel->hw_value;
+ cmd.bss.ds.channel = params->chandef.chan->hw_value;
cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
cmd.bss.ibss.header.len = 2;
cmd.bss.ibss.atimwindow = 0;
@@ -1841,6 +1845,8 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
/* set rates to the intersection of our rates and the rates in the
bss */
+ rcu_read_lock();
+ rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
if (!rates_eid) {
lbs_add_rates(cmd.bss.rates);
} else {
@@ -1860,6 +1866,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
}
}
}
+ rcu_read_unlock();
/* Only v8 and below support setting this */
if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
@@ -1942,7 +1949,7 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
cmd.ibss.atimwindow = 0;
cmd.ds.header.id = WLAN_EID_DS_PARAMS;
cmd.ds.header.len = 1;
- cmd.ds.channel = params->channel->hw_value;
+ cmd.ds.channel = params->chandef.chan->hw_value;
/* Only v8 and below support setting probe delay */
if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
@@ -1987,18 +1994,18 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
lbs_deb_enter(LBS_DEB_CFG80211);
- if (!params->channel) {
+ if (!params->chandef.chan) {
ret = -ENOTSUPP;
goto out;
}
- ret = lbs_set_channel(priv, params->channel->hw_value);
+ ret = lbs_set_channel(priv, params->chandef.chan->hw_value);
if (ret)
goto out;
/* Search if someone is beaconing. This assumes that the
* bss list is populated already */
- bss = cfg80211_get_bss(wiphy, params->channel, params->bssid,
+ bss = cfg80211_get_bss(wiphy, params->chandef.chan, params->bssid,
params->ssid, params->ssid_len,
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 4cb234349fbf..739309e70d8b 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -588,17 +588,38 @@ static int if_sdio_prog_real(struct if_sdio_card *card,
size = fw->size;
while (size) {
- ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
- if (ret)
- goto release;
+ timeout = jiffies + HZ;
+ while (1) {
+ ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
+ if (ret)
+ goto release;
- req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
- if (ret)
- goto release;
+ req_size = sdio_readb(card->func, IF_SDIO_RD_BASE,
+ &ret);
+ if (ret)
+ goto release;
+
+ req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1,
+ &ret) << 8;
+ if (ret)
+ goto release;
+
+ /*
+ * For SD8688 wait until the length is not 0, 1 or 2
+ * before downloading the first FW block,
+ * since BOOT code writes the register to indicate the
+ * helper/FW download winner,
+ * the value could be 1 or 2 (Func1 or Func2).
+ */
+ if ((size != fw->size) || (req_size > 2))
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ goto release;
+ }
+ mdelay(1);
+ }
- req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
- if (ret)
- goto release;
/*
lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size);
*/
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 9604a1c4a74d..4bb6574f4073 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1124,7 +1124,7 @@ static void if_spi_resume_worker(struct work_struct *work)
}
}
-static int __devinit if_spi_probe(struct spi_device *spi)
+static int if_spi_probe(struct spi_device *spi)
{
struct if_spi_card *card;
struct lbs_private *priv = NULL;
@@ -1226,7 +1226,7 @@ out:
return err;
}
-static int __devexit libertas_spi_remove(struct spi_device *spi)
+static int libertas_spi_remove(struct spi_device *spi)
{
struct if_spi_card *card = spi_get_drvdata(spi);
struct lbs_private *priv = card->priv;
@@ -1285,7 +1285,7 @@ static const struct dev_pm_ops if_spi_pm_ops = {
static struct spi_driver libertas_spi_driver = {
.probe = if_spi_probe,
- .remove = __devexit_p(libertas_spi_remove),
+ .remove = libertas_spi_remove,
.driver = {
.name = "libertas_spi",
.owner = THIS_MODULE,
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 97807751ebcf..3e81264db81e 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -101,7 +101,7 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
switch (action) {
case CMD_ACT_MESH_CONFIG_START:
- ie->id = WLAN_EID_GENERIC;
+ ie->id = WLAN_EID_VENDOR_SPECIFIC;
ie->val.oui[0] = 0x00;
ie->val.oui[1] = 0x50;
ie->val.oui[2] = 0x43;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 429ca3215fdb..ff9085502bea 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -44,9 +44,9 @@ static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
-static bool fake_hw_scan;
-module_param(fake_hw_scan, bool, 0444);
-MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler");
+static int channels = 1;
+module_param(channels, int, 0444);
+MODULE_PARM_DESC(channels, "Number of concurrent channels");
/**
* enum hwsim_regtest - the type of regulatory tests we offer
@@ -166,7 +166,9 @@ struct hwsim_vif_priv {
static inline void hwsim_check_magic(struct ieee80211_vif *vif)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
- WARN_ON(vp->magic != HWSIM_VIF_MAGIC);
+ WARN(vp->magic != HWSIM_VIF_MAGIC,
+ "Invalid VIF (%p) magic %#x, %pM, %d/%d\n",
+ vif, vp->magic, vif->addr, vif->type, vif->p2p);
}
static inline void hwsim_set_magic(struct ieee80211_vif *vif)
@@ -185,7 +187,7 @@ struct hwsim_sta_priv {
u32 magic;
};
-#define HWSIM_STA_MAGIC 0x6d537748
+#define HWSIM_STA_MAGIC 0x6d537749
static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
{
@@ -205,6 +207,30 @@ static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
sp->magic = 0;
}
+struct hwsim_chanctx_priv {
+ u32 magic;
+};
+
+#define HWSIM_CHANCTX_MAGIC 0x6d53774a
+
+static inline void hwsim_check_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+ struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+ WARN_ON(cp->magic != HWSIM_CHANCTX_MAGIC);
+}
+
+static inline void hwsim_set_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+ struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+ cp->magic = HWSIM_CHANCTX_MAGIC;
+}
+
+static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+ struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+ cp->magic = 0;
+}
+
static struct class *hwsim_class;
static struct net_device *hwsim_mon; /* global monitor netdev */
@@ -299,6 +325,13 @@ struct mac80211_hwsim_data {
struct mac_address addresses[2];
+ struct ieee80211_channel *tmp_chan;
+ struct delayed_work roc_done;
+ struct delayed_work hw_scan;
+ struct cfg80211_scan_request *hw_scan_request;
+ struct ieee80211_vif *hw_scan_vif;
+ int scan_chan_idx;
+
struct ieee80211_channel *channel;
unsigned long beacon_int; /* in jiffies unit */
unsigned int rx_filter;
@@ -396,7 +429,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
- struct sk_buff *tx_skb)
+ struct sk_buff *tx_skb,
+ struct ieee80211_channel *chan)
{
struct mac80211_hwsim_data *data = hw->priv;
struct sk_buff *skb;
@@ -423,7 +457,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
hdr->rt_tsft = __mac80211_hwsim_get_tsf(data);
hdr->rt_flags = 0;
hdr->rt_rate = txrate->bitrate / 5;
- hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
+ hdr->rt_channel = cpu_to_le16(chan->center_freq);
flags = IEEE80211_CHAN_2GHZ;
if (txrate->flags & IEEE80211_RATE_ERP_G)
flags |= IEEE80211_CHAN_OFDM;
@@ -441,9 +475,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
}
-static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr)
+static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
+ const u8 *addr)
{
- struct mac80211_hwsim_data *data = hw->priv;
struct sk_buff *skb;
struct hwsim_radiotap_hdr *hdr;
u16 flags;
@@ -464,7 +498,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr)
(1 << IEEE80211_RADIOTAP_CHANNEL));
hdr->rt_flags = 0;
hdr->rt_rate = 0;
- hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
+ hdr->rt_channel = cpu_to_le16(chan->center_freq);
flags = IEEE80211_CHAN_2GHZ;
hdr->rt_chbitmask = cpu_to_le16(flags);
@@ -537,6 +571,7 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
md.ret = false;
md.addr = addr;
ieee80211_iterate_active_interfaces_atomic(data->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_addr_iter,
&md);
@@ -556,12 +591,6 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
int i;
struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
- if (data->idle) {
- wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
- dev_kfree_skb(my_skb);
- return;
- }
-
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
/* If the queue contains MAX_QUEUE skb's drop some */
@@ -629,8 +658,38 @@ nla_put_failure:
printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
}
+static bool hwsim_chans_compat(struct ieee80211_channel *c1,
+ struct ieee80211_channel *c2)
+{
+ if (!c1 || !c2)
+ return false;
+
+ return c1->center_freq == c2->center_freq;
+}
+
+struct tx_iter_data {
+ struct ieee80211_channel *channel;
+ bool receive;
+};
+
+static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
+ struct ieee80211_vif *vif)
+{
+ struct tx_iter_data *data = _data;
+
+ if (!vif->chanctx_conf)
+ return;
+
+ if (!hwsim_chans_compat(data->channel,
+ rcu_dereference(vif->chanctx_conf)->def.chan))
+ return;
+
+ data->receive = true;
+}
+
static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ struct ieee80211_channel *chan)
{
struct mac80211_hwsim_data *data = hw->priv, *data2;
bool ack = false;
@@ -639,15 +698,10 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
struct ieee80211_rx_status rx_status;
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info);
- if (data->idle) {
- wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
- return false;
- }
-
memset(&rx_status, 0, sizeof(rx_status));
- rx_status.flag |= RX_FLAG_MACTIME_MPDU;
- rx_status.freq = data->channel->center_freq;
- rx_status.band = data->channel->band;
+ rx_status.flag |= RX_FLAG_MACTIME_START;
+ rx_status.freq = chan->center_freq;
+ rx_status.band = chan->band;
rx_status.rate_idx = info->control.rates[0].idx;
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
rx_status.flag |= RX_FLAG_HT;
@@ -673,17 +727,35 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
list_for_each_entry(data2, &hwsim_radios, list) {
struct sk_buff *nskb;
struct ieee80211_mgmt *mgmt;
+ struct tx_iter_data tx_iter_data = {
+ .receive = false,
+ .channel = chan,
+ };
if (data == data2)
continue;
- if (data2->idle || !data2->started ||
- !hwsim_ps_rx_ok(data2, skb) || !data2->channel ||
- data->channel->center_freq != data2->channel->center_freq ||
- !(data->group & data2->group))
+ if (!data2->started || (data2->idle && !data2->tmp_chan) ||
+ !hwsim_ps_rx_ok(data2, skb))
continue;
- nskb = skb_copy(skb, GFP_ATOMIC);
+ if (!(data->group & data2->group))
+ continue;
+
+ if (!hwsim_chans_compat(chan, data2->tmp_chan) &&
+ !hwsim_chans_compat(chan, data2->channel)) {
+ ieee80211_iterate_active_interfaces_atomic(
+ data2->hw, IEEE80211_IFACE_ITER_NORMAL,
+ mac80211_hwsim_tx_iter, &tx_iter_data);
+ if (!tx_iter_data.receive)
+ continue;
+ }
+
+ /*
+ * reserve some space for our vendor and the normal
+ * radiotap header, since we're copying anyway
+ */
+ nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC);
if (nskb == NULL)
continue;
@@ -701,6 +773,33 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
(data->tsf_offset - data2->tsf_offset) +
24 * 8 * 10 / txrate->bitrate);
+#if 0
+ /*
+ * Don't enable this code by default as the OUI 00:00:00
+ * is registered to Xerox so we shouldn't use it here, it
+ * might find its way into pcap files.
+ * Note that this code requires the headroom in the SKB
+ * that was allocated earlier.
+ */
+ rx_status.vendor_radiotap_oui[0] = 0x00;
+ rx_status.vendor_radiotap_oui[1] = 0x00;
+ rx_status.vendor_radiotap_oui[2] = 0x00;
+ rx_status.vendor_radiotap_subns = 127;
+ /*
+ * Radiotap vendor namespaces can (and should) also be
+ * split into fields by using the standard radiotap
+ * presence bitmap mechanism. Use just BIT(0) here for
+ * the presence bitmap.
+ */
+ rx_status.vendor_radiotap_bitmap = BIT(0);
+ /* We have 8 bytes of (dummy) data */
+ rx_status.vendor_radiotap_len = 8;
+ /* For testing, also require it to be aligned */
+ rx_status.vendor_radiotap_align = 8;
+ /* push the data */
+ memcpy(skb_push(nskb, 8), "ABCDEFGH", 8);
+#endif
+
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(data2->hw, nskb);
}
@@ -713,18 +812,51 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
+ struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *channel;
bool ack;
- struct ieee80211_tx_info *txi;
u32 _portid;
- mac80211_hwsim_monitor_rx(hw, skb);
-
- if (skb->len < 10) {
+ if (WARN_ON(skb->len < 10)) {
/* Should not happen; just a sanity check for addr1 use */
dev_kfree_skb(skb);
return;
}
+ if (channels == 1) {
+ channel = data->channel;
+ } else if (txi->hw_queue == 4) {
+ channel = data->tmp_chan;
+ } else {
+ chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
+ if (chanctx_conf)
+ channel = chanctx_conf->def.chan;
+ else
+ channel = NULL;
+ }
+
+ if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (data->idle && !data->tmp_chan) {
+ wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (txi->control.vif)
+ hwsim_check_magic(txi->control.vif);
+ if (control->sta)
+ hwsim_check_sta_magic(control->sta);
+
+ txi->rate_driver_data[0] = channel;
+
+ mac80211_hwsim_monitor_rx(hw, skb, channel);
+
/* wmediumd mode check */
_portid = ACCESS_ONCE(wmediumd_portid);
@@ -732,15 +864,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
/* NO wmediumd detected, perfect medium simulation */
- ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
+ ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
if (ack && skb->len >= 16) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- mac80211_hwsim_monitor_ack(hw, hdr->addr2);
+ mac80211_hwsim_monitor_ack(channel, hdr->addr2);
}
- txi = IEEE80211_SKB_CB(skb);
-
ieee80211_tx_info_clear_status(txi);
/* frame was transmitted at most favorable rate at first attempt */
@@ -778,6 +908,13 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
__func__, ieee80211_vif_type_p2p(vif),
vif->addr);
hwsim_set_magic(vif);
+
+ vif->cab_queue = 0;
+ vif->hw_queue[IEEE80211_AC_VO] = 0;
+ vif->hw_queue[IEEE80211_AC_VI] = 1;
+ vif->hw_queue[IEEE80211_AC_BE] = 2;
+ vif->hw_queue[IEEE80211_AC_BK] = 3;
+
return 0;
}
@@ -807,14 +944,26 @@ static void mac80211_hwsim_remove_interface(
hwsim_clear_magic(vif);
}
+static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_channel *chan)
+{
+ u32 _pid = ACCESS_ONCE(wmediumd_portid);
+
+ mac80211_hwsim_monitor_rx(hw, skb, chan);
+
+ if (_pid)
+ return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+ mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
+ dev_kfree_skb(skb);
+}
static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct ieee80211_vif *vif)
{
struct ieee80211_hw *hw = arg;
struct sk_buff *skb;
- struct ieee80211_tx_info *info;
- u32 _portid;
hwsim_check_magic(vif);
@@ -826,18 +975,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
skb = ieee80211_beacon_get(hw, vif);
if (skb == NULL)
return;
- info = IEEE80211_SKB_CB(skb);
-
- mac80211_hwsim_monitor_rx(hw, skb);
-
- /* wmediumd mode check */
- _portid = ACCESS_ONCE(wmediumd_portid);
- if (_portid)
- return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
-
- mac80211_hwsim_tx_frame_no_nl(hw, skb);
- dev_kfree_skb(skb);
+ mac80211_hwsim_tx_frame(hw, skb,
+ rcu_dereference(vif->chanctx_conf)->def.chan);
}
@@ -850,7 +990,8 @@ static void mac80211_hwsim_beacon(unsigned long arg)
return;
ieee80211_iterate_active_interfaces_atomic(
- hw, mac80211_hwsim_beacon_tx, hw);
+ hw, IEEE80211_IFACE_ITER_NORMAL,
+ mac80211_hwsim_beacon_tx, hw);
data->beacon_timer.expires = jiffies + data->beacon_int;
add_timer(&data->beacon_timer);
@@ -877,7 +1018,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
wiphy_debug(hw->wiphy,
"%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
__func__,
- conf->channel->center_freq,
+ conf->channel ? conf->channel->center_freq : 0,
hwsim_chantypes[conf->channel_type],
!!(conf->flags & IEEE80211_CONF_IDLE),
!!(conf->flags & IEEE80211_CONF_PS),
@@ -886,6 +1027,9 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
data->channel = conf->channel;
+
+ WARN_ON(data->channel && channels > 1);
+
data->power_level = conf->power_level;
if (!data->started || !data->beacon_int)
del_timer(&data->beacon_timer);
@@ -963,15 +1107,17 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_HT) {
- wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n",
- info->ht_operation_mode,
- hwsim_chantypes[info->channel_type]);
+ wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n",
+ info->ht_operation_mode);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n",
(unsigned long long) info->basic_rates);
}
+
+ if (changed & BSS_CHANGED_TXPOWER)
+ wiphy_debug(hw->wiphy, " TX Power: %d dBm\n", info->txpower);
}
static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
@@ -1166,45 +1312,101 @@ static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
/* Not implemented, queues only on kernel side */
}
-struct hw_scan_done {
- struct delayed_work w;
- struct ieee80211_hw *hw;
-};
-
-static void hw_scan_done(struct work_struct *work)
+static void hw_scan_work(struct work_struct *work)
{
- struct hw_scan_done *hsd =
- container_of(work, struct hw_scan_done, w.work);
+ struct mac80211_hwsim_data *hwsim =
+ container_of(work, struct mac80211_hwsim_data, hw_scan.work);
+ struct cfg80211_scan_request *req = hwsim->hw_scan_request;
+ int dwell, i;
+
+ mutex_lock(&hwsim->mutex);
+ if (hwsim->scan_chan_idx >= req->n_channels) {
+ wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
+ ieee80211_scan_completed(hwsim->hw, false);
+ hwsim->hw_scan_request = NULL;
+ hwsim->hw_scan_vif = NULL;
+ hwsim->tmp_chan = NULL;
+ mutex_unlock(&hwsim->mutex);
+ return;
+ }
+
+ wiphy_debug(hwsim->hw->wiphy, "hw scan %d MHz\n",
+ 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 ||
+ !req->n_ssids) {
+ dwell = 120;
+ } else {
+ dwell = 30;
+ /* send probes */
+ for (i = 0; i < req->n_ssids; i++) {
+ struct sk_buff *probe;
+
+ probe = ieee80211_probereq_get(hwsim->hw,
+ hwsim->hw_scan_vif,
+ req->ssids[i].ssid,
+ req->ssids[i].ssid_len,
+ req->ie_len);
+ if (!probe)
+ continue;
+
+ if (req->ie_len)
+ memcpy(skb_put(probe, req->ie_len), req->ie,
+ req->ie_len);
- ieee80211_scan_completed(hsd->hw, false);
- kfree(hsd);
+ local_bh_disable();
+ mac80211_hwsim_tx_frame(hwsim->hw, probe,
+ hwsim->tmp_chan);
+ local_bh_enable();
+ }
+ }
+ ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan,
+ msecs_to_jiffies(dwell));
+ hwsim->scan_chan_idx++;
+ mutex_unlock(&hwsim->mutex);
}
static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req)
{
- struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
- int i;
-
- if (!hsd)
- return -ENOMEM;
+ struct mac80211_hwsim_data *hwsim = hw->priv;
- hsd->hw = hw;
- INIT_DELAYED_WORK(&hsd->w, hw_scan_done);
+ mutex_lock(&hwsim->mutex);
+ if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
+ mutex_unlock(&hwsim->mutex);
+ return -EBUSY;
+ }
+ hwsim->hw_scan_request = req;
+ hwsim->hw_scan_vif = vif;
+ hwsim->scan_chan_idx = 0;
+ mutex_unlock(&hwsim->mutex);
- printk(KERN_DEBUG "hwsim hw_scan request\n");
- for (i = 0; i < req->n_channels; i++)
- printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
- req->channels[i]->center_freq);
- print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
- 16, 1, req->ie, req->ie_len, 1);
+ wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
- ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
+ ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
return 0;
}
+static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *hwsim = hw->priv;
+
+ wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
+
+ cancel_delayed_work_sync(&hwsim->hw_scan);
+
+ mutex_lock(&hwsim->mutex);
+ ieee80211_scan_completed(hwsim->hw, true);
+ hwsim->tmp_chan = NULL;
+ hwsim->hw_scan_request = NULL;
+ hwsim->hw_scan_vif = NULL;
+ mutex_unlock(&hwsim->mutex);
+}
+
static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
{
struct mac80211_hwsim_data *hwsim = hw->priv;
@@ -1235,6 +1437,111 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
mutex_unlock(&hwsim->mutex);
}
+static void hw_roc_done(struct work_struct *work)
+{
+ struct mac80211_hwsim_data *hwsim =
+ container_of(work, struct mac80211_hwsim_data, roc_done.work);
+
+ mutex_lock(&hwsim->mutex);
+ ieee80211_remain_on_channel_expired(hwsim->hw);
+ hwsim->tmp_chan = NULL;
+ mutex_unlock(&hwsim->mutex);
+
+ wiphy_debug(hwsim->hw->wiphy, "hwsim ROC expired\n");
+}
+
+static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration)
+{
+ struct mac80211_hwsim_data *hwsim = hw->priv;
+
+ mutex_lock(&hwsim->mutex);
+ if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
+ mutex_unlock(&hwsim->mutex);
+ return -EBUSY;
+ }
+
+ hwsim->tmp_chan = chan;
+ mutex_unlock(&hwsim->mutex);
+
+ wiphy_debug(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n",
+ chan->center_freq, duration);
+
+ ieee80211_ready_on_channel(hw);
+
+ ieee80211_queue_delayed_work(hw, &hwsim->roc_done,
+ msecs_to_jiffies(duration));
+ return 0;
+}
+
+static int mac80211_hwsim_croc(struct ieee80211_hw *hw)
+{
+ struct mac80211_hwsim_data *hwsim = hw->priv;
+
+ cancel_delayed_work_sync(&hwsim->roc_done);
+
+ mutex_lock(&hwsim->mutex);
+ hwsim->tmp_chan = NULL;
+ mutex_unlock(&hwsim->mutex);
+
+ wiphy_debug(hw->wiphy, "hwsim ROC canceled\n");
+
+ return 0;
+}
+
+static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ hwsim_set_chanctx_magic(ctx);
+ wiphy_debug(hw->wiphy,
+ "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+ ctx->def.chan->center_freq, ctx->def.width,
+ ctx->def.center_freq1, ctx->def.center_freq2);
+ return 0;
+}
+
+static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ wiphy_debug(hw->wiphy,
+ "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+ ctx->def.chan->center_freq, ctx->def.width,
+ ctx->def.center_freq1, ctx->def.center_freq2);
+ hwsim_check_chanctx_magic(ctx);
+ hwsim_clear_chanctx_magic(ctx);
+}
+
+static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx,
+ u32 changed)
+{
+ hwsim_check_chanctx_magic(ctx);
+ wiphy_debug(hw->wiphy,
+ "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+ ctx->def.chan->center_freq, ctx->def.width,
+ ctx->def.center_freq1, ctx->def.center_freq2);
+}
+
+static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ hwsim_check_magic(vif);
+ hwsim_check_chanctx_magic(ctx);
+
+ return 0;
+}
+
+static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ hwsim_check_magic(vif);
+ hwsim_check_chanctx_magic(ctx);
+}
+
static struct ieee80211_ops mac80211_hwsim_ops =
{
.tx = mac80211_hwsim_tx,
@@ -1315,7 +1622,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_pspoll *pspoll;
- u32 _portid;
if (!vp->assoc)
return;
@@ -1335,25 +1641,18 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
memcpy(pspoll->ta, mac, ETH_ALEN);
- /* wmediumd mode check */
- _portid = ACCESS_ONCE(wmediumd_portid);
-
- if (_portid)
- return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid);
-
- if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
- printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);
- dev_kfree_skb(skb);
+ rcu_read_lock();
+ mac80211_hwsim_tx_frame(data->hw, skb,
+ rcu_dereference(vif->chanctx_conf)->def.chan);
+ rcu_read_unlock();
}
-
static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
struct ieee80211_vif *vif, int ps)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
- u32 _portid;
if (!vp->assoc)
return;
@@ -1374,15 +1673,10 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
memcpy(hdr->addr2, mac, ETH_ALEN);
memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
- /* wmediumd mode check */
- _portid = ACCESS_ONCE(wmediumd_portid);
-
- if (_portid)
- return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid);
-
- if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
- printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
- dev_kfree_skb(skb);
+ rcu_read_lock();
+ mac80211_hwsim_tx_frame(data->hw, skb,
+ rcu_dereference(vif->chanctx_conf)->def.chan);
+ rcu_read_unlock();
}
@@ -1423,14 +1717,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
if (val == PS_MANUAL_POLL) {
ieee80211_iterate_active_interfaces(data->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
hwsim_send_ps_poll, data);
data->ps_poll_pending = true;
} else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
ieee80211_iterate_active_interfaces(data->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
hwsim_send_nullfunc_ps,
data);
} else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
ieee80211_iterate_active_interfaces(data->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
hwsim_send_nullfunc_no_ps,
data);
}
@@ -1551,7 +1848,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
(hwsim_flags & HWSIM_TX_STAT_ACK)) {
if (skb->len >= 16) {
hdr = (struct ieee80211_hdr *) skb->data;
- mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
+ mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+ hdr->addr2);
}
txi->flags |= IEEE80211_TX_STAT_ACK;
}
@@ -1566,7 +1864,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
struct genl_info *info)
{
- struct mac80211_hwsim_data *data2;
+ struct mac80211_hwsim_data *data2;
struct ieee80211_rx_status rx_status;
struct mac_address *dst;
int frame_data_len;
@@ -1574,9 +1872,9 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
struct sk_buff *skb = NULL;
if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
- !info->attrs[HWSIM_ATTR_FRAME] ||
- !info->attrs[HWSIM_ATTR_RX_RATE] ||
- !info->attrs[HWSIM_ATTR_SIGNAL])
+ !info->attrs[HWSIM_ATTR_FRAME] ||
+ !info->attrs[HWSIM_ATTR_RX_RATE] ||
+ !info->attrs[HWSIM_ATTR_SIGNAL])
goto out;
dst = (struct mac_address *)nla_data(
@@ -1604,7 +1902,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
/* check if radio is configured properly */
- if (data2->idle || !data2->started || !data2->channel)
+ if (data2->idle || !data2->started)
goto out;
/*A frame is received from user space*/
@@ -1688,6 +1986,11 @@ static struct notifier_block hwsim_netlink_notifier = {
static int hwsim_init_netlink(void)
{
int rc;
+
+ /* userspace test API hasn't been adjusted for multi-channel */
+ if (channels > 1)
+ return 0;
+
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
rc = genl_register_family_with_ops(&hwsim_genl_family,
@@ -1710,6 +2013,10 @@ static void hwsim_exit_netlink(void)
{
int ret;
+ /* userspace test API hasn't been adjusted for multi-channel */
+ if (channels > 1)
+ return;
+
printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
/* unregister the notifier */
netlink_unregister_notifier(&hwsim_netlink_notifier);
@@ -1732,7 +2039,7 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
};
-static const struct ieee80211_iface_combination hwsim_if_comb = {
+static struct ieee80211_iface_combination hwsim_if_comb = {
.limits = hwsim_if_limits,
.n_limits = ARRAY_SIZE(hwsim_if_limits),
.max_interfaces = 2048,
@@ -1750,10 +2057,30 @@ static int __init init_mac80211_hwsim(void)
if (radios < 1 || radios > 100)
return -EINVAL;
- if (fake_hw_scan) {
+ if (channels < 1)
+ return -EINVAL;
+
+ if (channels > 1) {
+ hwsim_if_comb.num_different_channels = channels;
mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
+ mac80211_hwsim_ops.cancel_hw_scan =
+ mac80211_hwsim_cancel_hw_scan;
mac80211_hwsim_ops.sw_scan_start = NULL;
mac80211_hwsim_ops.sw_scan_complete = NULL;
+ mac80211_hwsim_ops.remain_on_channel =
+ mac80211_hwsim_roc;
+ mac80211_hwsim_ops.cancel_remain_on_channel =
+ mac80211_hwsim_croc;
+ mac80211_hwsim_ops.add_chanctx =
+ mac80211_hwsim_add_chanctx;
+ mac80211_hwsim_ops.remove_chanctx =
+ mac80211_hwsim_remove_chanctx;
+ mac80211_hwsim_ops.change_chanctx =
+ mac80211_hwsim_change_chanctx;
+ mac80211_hwsim_ops.assign_vif_chanctx =
+ mac80211_hwsim_assign_vif_chanctx;
+ mac80211_hwsim_ops.unassign_vif_chanctx =
+ mac80211_hwsim_unassign_vif_chanctx;
}
spin_lock_init(&hwsim_radio_lock);
@@ -1803,13 +2130,18 @@ static int __init init_mac80211_hwsim(void)
hw->wiphy->iface_combinations = &hwsim_if_comb;
hw->wiphy->n_iface_combinations = 1;
- if (fake_hw_scan) {
+ 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;
}
+ INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
+ INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
+
hw->channel_change_time = 1;
- hw->queues = 4;
+ hw->queues = 5;
+ hw->offchannel_tx_hw_queue = 4;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1824,7 +2156,8 @@ static int __init init_mac80211_hwsim(void)
IEEE80211_HW_SUPPORTS_STATIC_SMPS |
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_AMPDU_AGGREGATION |
- IEEE80211_HW_WANT_MONITOR_VIF;
+ IEEE80211_HW_WANT_MONITOR_VIF |
+ IEEE80211_HW_QUEUE_CONTROL;
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -1874,6 +2207,34 @@ static int __init init_mac80211_hwsim(void)
sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
hw->wiphy->bands[band] = sband;
+
+ if (channels == 1)
+ continue;
+
+ sband->vht_cap.vht_supported = true;
+ sband->vht_cap.cap =
+ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+ IEEE80211_VHT_CAP_RXLDPC |
+ IEEE80211_VHT_CAP_SHORT_GI_80 |
+ IEEE80211_VHT_CAP_SHORT_GI_160 |
+ IEEE80211_VHT_CAP_TXSTBC |
+ IEEE80211_VHT_CAP_RXSTBC_1 |
+ IEEE80211_VHT_CAP_RXSTBC_2 |
+ IEEE80211_VHT_CAP_RXSTBC_3 |
+ IEEE80211_VHT_CAP_RXSTBC_4 |
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+ sband->vht_cap.vht_mcs.rx_mcs_map =
+ cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 |
+ IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 |
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 |
+ IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 |
+ IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 |
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 |
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 |
+ IEEE80211_VHT_MCS_SUPPORT_0_8 << 14);
+ sband->vht_cap.vht_mcs.tx_mcs_map =
+ sband->vht_cap.vht_mcs.rx_mcs_map;
}
/* By default all radios are belonging to the first group */
data->group = 1;
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 395f1bfd4102..68d52cfc1ebd 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -197,7 +197,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
ra_list_flags);
mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
- mwifiex_write_data_complete(adapter, skb_src, 0);
+ mwifiex_write_data_complete(adapter, skb_src, 0, 0);
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
@@ -256,7 +256,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
- mwifiex_write_data_complete(adapter, skb_aggr, -1);
+ mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
return -1;
}
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
@@ -282,13 +282,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
dev_err(adapter->dev, "%s: host_to_card failed: %#x\n",
__func__, ret);
adapter->dbg.num_tx_host_to_card_failure++;
- mwifiex_write_data_complete(adapter, skb_aggr, ret);
+ mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
return 0;
case -EINPROGRESS:
adapter->data_sent = false;
break;
case 0:
- mwifiex_write_data_complete(adapter, skb_aggr, ret);
+ mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
break;
default:
break;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 9402b93b9a36..4a97acd170f7 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
else
- mwifiex_process_rx_packet(priv->adapter,
- rx_tmp_ptr);
+ mwifiex_process_rx_packet(priv, rx_tmp_ptr);
}
}
@@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
else
- mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
+ mwifiex_process_rx_packet(priv, rx_tmp_ptr);
}
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, payload);
else
- mwifiex_process_rx_packet(priv->adapter,
- payload);
+ mwifiex_process_rx_packet(priv, payload);
}
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 8e384fae3e68..b2e27723f801 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -1,7 +1,6 @@
config MWIFIEX
tristate "Marvell WiFi-Ex Driver"
depends on CFG80211
- select LIB80211
---help---
This adds support for wireless adapters based on Marvell
802.11n chipsets.
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 780d3e168297..a875499f8945 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -180,10 +180,8 @@ 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,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie)
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie)
{
struct sk_buff *skb;
u16 pkt_len;
@@ -253,7 +251,6 @@ static int
mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
@@ -271,15 +268,14 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
}
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
- &channel_type, duration);
+ duration);
if (!ret) {
*cookie = random32() | 1;
priv->roc_cfg.cookie = *cookie;
priv->roc_cfg.chan = *chan;
- priv->roc_cfg.chan_type = channel_type;
- cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type,
+ cfg80211_ready_on_channel(wdev, *cookie, chan,
duration, GFP_ATOMIC);
wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
@@ -302,13 +298,11 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
return -ENOENT;
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
- &priv->roc_cfg.chan,
- &priv->roc_cfg.chan_type, 0);
+ &priv->roc_cfg.chan, 0);
if (!ret) {
cfg80211_remain_on_channel_expired(wdev, cookie,
&priv->roc_cfg.chan,
- priv->roc_cfg.chan_type,
GFP_ATOMIC);
memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
@@ -324,6 +318,7 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
*/
static int
mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
enum nl80211_tx_power_setting type,
int mbm)
{
@@ -471,13 +466,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
flag = 1;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
- max_pwr = ch->max_reg_power;
+ max_pwr = ch->max_power;
no_of_parsed_chan = 1;
continue;
}
if (ch->hw_value == next_chan + 1 &&
- ch->max_reg_power == max_pwr) {
+ ch->max_power == max_pwr) {
next_chan++;
no_of_parsed_chan++;
} else {
@@ -488,7 +483,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
no_of_triplet++;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
- max_pwr = ch->max_reg_power;
+ max_pwr = ch->max_power;
no_of_parsed_chan = 1;
}
}
@@ -1296,21 +1291,23 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
return -EINVAL;
}
- bss_cfg->channel =
- (u8)ieee80211_frequency_to_channel(params->channel->center_freq);
+ bss_cfg->channel = ieee80211_frequency_to_channel(
+ params->chandef.chan->center_freq);
/* Set appropriate bands */
- if (params->channel->band == IEEE80211_BAND_2GHZ) {
+ if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
bss_cfg->band_cfg = BAND_CONFIG_BG;
- if (params->channel_type == NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(&params->chandef) ==
+ NL80211_CHAN_NO_HT)
config_bands = BAND_B | BAND_G;
else
config_bands = BAND_B | BAND_G | BAND_GN;
} else {
bss_cfg->band_cfg = BAND_CONFIG_A;
- if (params->channel_type == NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(&params->chandef) ==
+ NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
config_bands = BAND_AN | BAND_A;
@@ -1683,7 +1680,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
int index = 0, i;
u8 config_bands = 0;
- if (params->channel->band == IEEE80211_BAND_2GHZ) {
+ if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
if (!params->basic_rates) {
config_bands = BAND_B | BAND_G;
} else {
@@ -1708,10 +1705,12 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
}
}
- if (params->channel_type != NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(&params->chandef) !=
+ NL80211_CHAN_NO_HT)
config_bands |= BAND_GN;
} else {
- if (params->channel_type == NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(&params->chandef) !=
+ NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
config_bands = BAND_AN | BAND_A;
@@ -1728,9 +1727,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
}
adapter->sec_chan_offset =
- mwifiex_chan_type_to_sec_chan_offset(params->channel_type);
- priv->adhoc_channel =
- ieee80211_frequency_to_channel(params->channel->center_freq);
+ mwifiex_chan_type_to_sec_chan_offset(
+ cfg80211_get_chandef_type(&params->chandef));
+ priv->adhoc_channel = ieee80211_frequency_to_channel(
+ params->chandef.chan->center_freq);
wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
@@ -1764,7 +1764,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
params->bssid, priv->bss_mode,
- params->channel, NULL, params->privacy);
+ params->chandef.chan, NULL,
+ params->privacy);
done:
if (!ret) {
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
@@ -1819,12 +1820,18 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
- if (atomic_read(&priv->wmm.tx_pkts_queued) >=
+ if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+ atomic_read(&priv->wmm.tx_pkts_queued) >=
MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
return -EBUSY;
}
+ if (priv->user_scan_cfg) {
+ dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
+ return -EBUSY;
+ }
+
priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
GFP_KERNEL);
if (!priv->user_scan_cfg) {
@@ -1941,6 +1948,21 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
else
ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
+ if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
+ ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+ else
+ ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
+
+ if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
+ ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+ else
+ ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+
+ if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
+ ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+ else
+ ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
+
ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
@@ -2074,8 +2096,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
- dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
- ether_setup, 1);
+ dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
+ ether_setup, IEEE80211_NUM_ACS, 1);
if (!dev) {
wiphy_err(wiphy, "no memory available for netdevice\n");
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2116,7 +2138,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
}
sema_init(&priv->async_sem, 1);
- priv->scan_pending_on_block = false;
dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
@@ -2138,8 +2159,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
mwifiex_dev_debugfs_remove(priv);
#endif
- if (!netif_queue_stopped(priv->netdev))
- netif_stop_queue(priv->netdev);
+ mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
@@ -2253,8 +2273,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
- wiphy->features = NL80211_FEATURE_HT_IBSS |
- NL80211_FEATURE_INACTIVITY_TIMER;
+ wiphy->features |= NL80211_FEATURE_HT_IBSS |
+ NL80211_FEATURE_INACTIVITY_TIMER |
+ NL80211_FEATURE_LOW_PRIORITY_SCAN;
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index ae9010ed58de..5f438e6c2155 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -914,21 +914,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
dev_err(adapter->dev, "last_cmd_index = %d\n",
adapter->dbg.last_cmd_index);
- print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
- adapter->dbg.last_cmd_id, DBG_CMD_NUM);
- print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
- adapter->dbg.last_cmd_act, DBG_CMD_NUM);
+ dev_err(adapter->dev, "last_cmd_id: %*ph\n",
+ (int)sizeof(adapter->dbg.last_cmd_id),
+ adapter->dbg.last_cmd_id);
+ dev_err(adapter->dev, "last_cmd_act: %*ph\n",
+ (int)sizeof(adapter->dbg.last_cmd_act),
+ adapter->dbg.last_cmd_act);
dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
adapter->dbg.last_cmd_resp_index);
- print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
- adapter->dbg.last_cmd_resp_id,
- DBG_CMD_NUM);
+ dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
+ (int)sizeof(adapter->dbg.last_cmd_resp_id),
+ adapter->dbg.last_cmd_resp_id);
dev_err(adapter->dev, "last_event_index = %d\n",
adapter->dbg.last_event_index);
- print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
- adapter->dbg.last_event, DBG_CMD_NUM);
+ dev_err(adapter->dev, "last_event: %*ph\n",
+ (int)sizeof(adapter->dbg.last_event),
+ adapter->dbg.last_event);
dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
adapter->data_sent, adapter->cmd_sent);
@@ -946,6 +949,9 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
}
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
mwifiex_init_fw_complete(adapter);
+
+ if (adapter->if_ops.card_reset)
+ adapter->if_ops.card_reset(adapter);
}
/*
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index a870b5885c09..46e34aa65d1c 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -178,6 +178,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
(struct mwifiex_private *) file->private_data;
struct net_device *netdev = priv->netdev;
struct netdev_hw_addr *ha;
+ struct netdev_queue *txq;
unsigned long page = get_zeroed_page(GFP_KERNEL);
char *p = (char *) page, fmt[64];
struct mwifiex_bss_info info;
@@ -229,8 +230,13 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
? "on" : "off"));
- p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev))
- ? "stopped" : "started"));
+ p += sprintf(p, "tx queue");
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ txq = netdev_get_tx_queue(netdev, i);
+ p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
+ "stopped" : "started");
+ }
+ p += sprintf(p, "\n");
ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
(unsigned long) p - page);
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index dda588b35570..4dc8e2e9a889 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -194,6 +194,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25))
#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
+#define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8))
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22))
/* httxcfg bitmap
* 0 reserved
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index b5d37a8caa09..39f03ce5a5b1 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -84,18 +84,19 @@ static void scan_delay_timer_fn(unsigned long data)
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
if (priv->user_scan_cfg) {
- dev_dbg(priv->adapter->dev,
- "info: %s: scan aborted\n", __func__);
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
+ if (priv->scan_request) {
+ dev_dbg(priv->adapter->dev,
+ "info: aborting scan\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ } else {
+ dev_dbg(priv->adapter->dev,
+ "info: scan already aborted\n");
+ }
+
kfree(priv->user_scan_cfg);
priv->user_scan_cfg = NULL;
}
-
- if (priv->scan_pending_on_block) {
- priv->scan_pending_on_block = false;
- up(&priv->async_sem);
- }
goto done;
}
@@ -387,9 +388,17 @@ void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter)
{
unsigned long dev_queue_flags;
+ unsigned int i;
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
- netif_tx_wake_all_queues(netdev);
+
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+ if (netif_tx_queue_stopped(txq))
+ netif_tx_wake_queue(txq);
+ }
+
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
}
@@ -400,9 +409,17 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter)
{
unsigned long dev_queue_flags;
+ unsigned int i;
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
- netif_tx_stop_all_queues(netdev);
+
+ for (i = 0; i < netdev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+ if (!netif_tx_queue_stopped(txq))
+ netif_tx_stop_queue(txq);
+ }
+
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
}
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 7b0858af8f5d..88664ae667ba 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -721,8 +721,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
if (!netif_carrier_ok(priv->netdev))
netif_carrier_on(priv->netdev);
- if (netif_queue_stopped(priv->netdev))
- netif_wake_queue(priv->netdev);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
priv->scan_block = true;
@@ -1238,8 +1237,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
if (!netif_carrier_ok(priv->netdev))
netif_carrier_on(priv->netdev);
- if (netif_queue_stopped(priv->netdev))
- netif_wake_queue(priv->netdev);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
mwifiex_save_curr_bcn(priv);
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index eb22dd248d54..9c802ede9c3b 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -282,6 +282,7 @@ exit_main_proc:
mwifiex_shutdown_drv(adapter);
return ret;
}
+EXPORT_SYMBOL_GPL(mwifiex_main_process);
/*
* This function frees the adapter structure.
@@ -412,49 +413,6 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
}
/*
- * This function fills a driver buffer.
- *
- * The function associates a given SKB with the provided driver buffer
- * and also updates some of the SKB parameters, including IP header,
- * priority and timestamp.
- */
-static void
-mwifiex_fill_buffer(struct sk_buff *skb)
-{
- struct ethhdr *eth;
- struct iphdr *iph;
- struct timeval tv;
- u8 tid = 0;
-
- eth = (struct ethhdr *) skb->data;
- switch (eth->h_proto) {
- case __constant_htons(ETH_P_IP):
- iph = ip_hdr(skb);
- tid = IPTOS_PREC(iph->tos);
- pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
- eth->h_proto, tid, skb->priority);
- break;
- case __constant_htons(ETH_P_ARP):
- pr_debug("data: ARP packet: %04x\n", eth->h_proto);
- default:
- break;
- }
-/* Offset for TOS field in the IP header */
-#define IPTOS_OFFSET 5
- tid = (tid >> IPTOS_OFFSET);
- skb->priority = tid;
- /* Record the current time the packet was queued; used to
- determine the amount of time the packet was queued in
- the driver before it was sent to the firmware.
- The delay is then sent along with the packet to the
- firmware for aggregate delay calculation for stats and
- MSDU lifetime expiry.
- */
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
-}
-
-/*
* CFG802.11 network device handler for open.
*
* Starts the data queue.
@@ -472,6 +430,14 @@ mwifiex_open(struct net_device *dev)
static int
mwifiex_close(struct net_device *dev)
{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+ if (priv->scan_request) {
+ dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ }
+
return 0;
}
@@ -480,17 +446,23 @@ mwifiex_close(struct net_device *dev)
*/
int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
{
- mwifiex_wmm_add_buf_txqueue(priv, skb);
+ struct netdev_queue *txq;
+ int index = mwifiex_1d_to_wmm_queue[skb->priority];
+
+ if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
+ txq = netdev_get_tx_queue(priv->netdev, index);
+ if (!netif_tx_queue_stopped(txq)) {
+ netif_tx_stop_queue(txq);
+ dev_dbg(priv->adapter->dev, "stop queue: %d\n", index);
+ }
+ }
+
atomic_inc(&priv->adapter->tx_pending);
+ mwifiex_wmm_add_buf_txqueue(priv, skb);
if (priv->adapter->scan_delay_cnt)
atomic_set(&priv->adapter->is_tx_received, true);
- if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
- mwifiex_set_trans_start(priv->netdev);
- mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
- }
-
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
return 0;
@@ -505,6 +477,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct sk_buff *new_skb;
struct mwifiex_txinfo *tx_info;
+ struct timeval tv;
dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
jiffies, priv->bss_type, priv->bss_num);
@@ -542,7 +515,16 @@ 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;
- mwifiex_fill_buffer(skb);
+
+ /* Record the current time the packet was queued; used to
+ * determine the amount of time the packet was queued in
+ * the driver before it was sent to the firmware.
+ * The delay is then sent along with the packet to the
+ * firmware for aggregate delay calculation for stats and
+ * MSDU lifetime expiry.
+ */
+ do_gettimeofday(&tv);
+ skb->tstamp = timeval_to_ktime(tv);
mwifiex_queue_tx_pkt(priv, skb);
@@ -622,6 +604,13 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
return &priv->stats;
}
+static u16
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ skb->priority = cfg80211_classify8021d(skb);
+ return mwifiex_1d_to_wmm_queue[skb->priority];
+}
+
/* Network device handlers */
static const struct net_device_ops mwifiex_netdev_ops = {
.ndo_open = mwifiex_open,
@@ -631,6 +620,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
.ndo_tx_timeout = mwifiex_tx_timeout,
.ndo_get_stats = mwifiex_get_stats,
.ndo_set_rx_mode = mwifiex_set_multicast_list,
+ .ndo_select_queue = mwifiex_netdev_select_wmm_queue,
};
/*
@@ -830,9 +820,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
if (priv && priv->netdev) {
- if (!netif_queue_stopped(priv->netdev))
- mwifiex_stop_net_dev_queue(priv->netdev,
- adapter);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c2d0ab146af5..1b3cfc821940 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -115,8 +115,6 @@ enum {
#define MWIFIEX_TYPE_DATA 0
#define MWIFIEX_TYPE_EVENT 3
-#define DBG_CMD_NUM 5
-
#define MAX_BITMAP_RATES_SIZE 10
#define MAX_CHANNEL_BAND_BG 14
@@ -373,7 +371,6 @@ struct wps {
struct mwifiex_roc_cfg {
u64 cookie;
struct ieee80211_channel chan;
- enum nl80211_channel_type chan_type;
};
struct mwifiex_adapter;
@@ -442,6 +439,7 @@ struct mwifiex_private {
u8 wmm_enabled;
u8 wmm_qosinfo;
struct mwifiex_wmm_desc wmm;
+ atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
struct list_head sta_list;
/* spin lock for associated station list */
spinlock_t sta_list_spinlock;
@@ -484,7 +482,6 @@ struct mwifiex_private {
u8 nick_name[16];
u16 current_key_index;
struct semaphore async_sem;
- u8 scan_pending_on_block;
u8 report_scan_result;
struct cfg80211_scan_request *scan_request;
struct mwifiex_user_scan_cfg *user_scan_cfg;
@@ -603,6 +600,7 @@ struct mwifiex_if_ops {
int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *);
int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
+ void (*card_reset) (struct mwifiex_adapter *);
};
struct mwifiex_adapter {
@@ -750,9 +748,9 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
-int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
-int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
struct sk_buff *skb);
int mwifiex_process_event(struct mwifiex_adapter *adapter);
@@ -791,7 +789,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
struct mwifiex_tx_param *tx_param);
int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
- struct sk_buff *skb, int status);
+ struct sk_buff *skb, int aggr, int status);
void mwifiex_clean_txrx(struct mwifiex_private *priv);
u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
@@ -809,7 +807,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv,
u8 activated);
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
-int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
struct sk_buff *skb);
int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid,
@@ -819,9 +817,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
void *data_buf, void *cmd_buf);
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
struct host_cmd_ds_command *resp);
-int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *,
struct sk_buff *skb);
-int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
struct sk_buff *skb);
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
struct sk_buff *skb);
@@ -1019,7 +1017,6 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv);
int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
struct ieee80211_channel *chan,
- enum nl80211_channel_type *channel_type,
unsigned int duration);
int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 9171aaedbccd..9189a32b7844 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -153,7 +153,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
if (((bss_desc->bcn_wpa_ie) &&
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
- WLAN_EID_WPA))) {
+ WLAN_EID_VENDOR_SPECIFIC))) {
iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
oui = &mwifiex_wpa_oui[cipher][0];
ret = mwifiex_search_oui_in_ie(iebody, oui);
@@ -202,7 +202,7 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
!priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
- WLAN_EID_WPA)) &&
+ WLAN_EID_VENDOR_SPECIFIC)) &&
((!bss_desc->bcn_rsn_ie) ||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
WLAN_EID_RSN)) &&
@@ -237,7 +237,8 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
{
if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
!priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
- ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == WLAN_EID_WPA))
+ ((*(bss_desc->bcn_wpa_ie)).
+ vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
/*
* Privacy bit may NOT be set in some APs like
* LinkSys WRT54G && bss_desc->privacy
@@ -309,7 +310,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
!priv->sec_info.wpa2_enabled &&
((!bss_desc->bcn_wpa_ie) ||
- ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+ ((*(bss_desc->bcn_wpa_ie)).
+ vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
((!bss_desc->bcn_rsn_ie) ||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
!priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -329,7 +331,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
!priv->sec_info.wpa2_enabled &&
((!bss_desc->bcn_wpa_ie) ||
- ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+ ((*(bss_desc->bcn_wpa_ie)).
+ vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
((!bss_desc->bcn_rsn_ie) ||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -938,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv,
chan_idx)->chan_scan_mode_bitmap
&= ~MWIFIEX_PASSIVE_SCAN;
+ if (*filtered_scan)
+ (scan_chan_list +
+ chan_idx)->chan_scan_mode_bitmap
+ |= MWIFIEX_DISABLE_CHAN_FILT;
+
if (user_scan_in->chan_list[chan_idx].scan_time) {
scan_dur = (u16) user_scan_in->
chan_list[chan_idx].scan_time;
@@ -1759,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
}
if (priv->report_scan_result)
priv->report_scan_result = false;
- if (priv->scan_pending_on_block) {
- priv->scan_pending_on_block = false;
- up(&priv->async_sem);
- }
if (priv->user_scan_cfg) {
- dev_dbg(priv->adapter->dev,
- "info: %s: sending scan results\n", __func__);
- cfg80211_scan_done(priv->scan_request, 0);
- priv->scan_request = NULL;
+ if (priv->scan_request) {
+ dev_dbg(priv->adapter->dev,
+ "info: notifying scan done\n");
+ cfg80211_scan_done(priv->scan_request, 0);
+ priv->scan_request = NULL;
+ } else {
+ dev_dbg(priv->adapter->dev,
+ "info: scan already aborted\n");
+ }
+
kfree(priv->user_scan_cfg);
priv->user_scan_cfg = NULL;
}
} else {
- if (!mwifiex_wmm_lists_empty(adapter)) {
+ if (priv->user_scan_cfg && !priv->scan_request) {
+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+ flags);
+ adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
+ mod_timer(&priv->scan_delay_timer, jiffies);
+ dev_dbg(priv->adapter->dev,
+ "info: %s: triggerring scan abort\n", __func__);
+ } else if (!mwifiex_wmm_lists_empty(adapter) &&
+ (priv->scan_request && (priv->scan_request->flags &
+ NL80211_SCAN_FLAG_LOW_PRIORITY))) {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
adapter->scan_delay_cnt = 1;
mod_timer(&priv->scan_delay_timer, jiffies +
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
+ dev_dbg(priv->adapter->dev,
+ "info: %s: deferring scan\n", __func__);
} else {
/* Get scan command from scan_pending_q and put to
cmd_pending_q */
@@ -1891,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
__func__);
return -1;
}
- priv->scan_pending_on_block = true;
priv->adapter->scan_wait_q_woken = false;
@@ -1905,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
if (!ret)
ret = mwifiex_wait_queue_complete(priv->adapter);
- if (ret == -1) {
- priv->scan_pending_on_block = false;
- up(&priv->async_sem);
- }
+ up(&priv->async_sem);
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 82cf0fa2d9f6..5a1c1d0e5599 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -906,8 +906,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
/*
* SDIO interrupt handler.
*
- * This function reads the interrupt status from firmware and assigns
- * the main process in workqueue which will handle the interrupt.
+ * This function reads the interrupt status from firmware and handles
+ * the interrupt in current thread (ksdioirqd) right away.
*/
static void
mwifiex_sdio_interrupt(struct sdio_func *func)
@@ -930,7 +930,7 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
adapter->ps_state = PS_STATE_AWAKE;
mwifiex_interrupt_status(adapter);
- queue_work(adapter->workqueue, &adapter->main_work);
+ mwifiex_main_process(adapter);
}
/*
@@ -1749,6 +1749,37 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
port, card->mp_data_port_mask);
}
+static struct mmc_host *reset_host;
+static void sdio_card_reset_worker(struct work_struct *work)
+{
+ /* The actual reset operation must be run outside of driver thread.
+ * This is because mmc_remove_host() will cause the device to be
+ * instantly destroyed, and the driver then needs to end its thread,
+ * leading to a deadlock.
+ *
+ * We run it in a totally independent workqueue.
+ */
+
+ pr_err("Resetting card...\n");
+ mmc_remove_host(reset_host);
+ /* 20ms delay is based on experiment with sdhci controller */
+ mdelay(20);
+ mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, sdio_card_reset_worker);
+
+/* This function resets the card */
+static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
+{
+ struct sdio_mmc_card *card = adapter->card;
+
+ if (work_pending(&card_reset_work))
+ return;
+
+ reset_host = card->func->card->host;
+ schedule_work(&card_reset_work);
+}
+
static struct mwifiex_if_ops sdio_ops = {
.init_if = mwifiex_init_sdio,
.cleanup_if = mwifiex_cleanup_sdio,
@@ -1767,6 +1798,7 @@ static struct mwifiex_if_ops sdio_ops = {
.cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
.cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
.event_complete = mwifiex_sdio_event_complete,
+ .card_reset = mwifiex_sdio_card_reset,
};
/*
@@ -1804,6 +1836,7 @@ mwifiex_sdio_cleanup_module(void)
/* Set the flag as user is removing this module. */
user_rmmod = 1;
+ cancel_work_sync(&card_reset_work);
sdio_unregister_driver(&mwifiex_sdio);
}
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 21033738ef0c..8cc5468654b4 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -25,6 +25,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include "main.h"
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 09e6a267f566..65c12eb3e5e7 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
if (priv->report_scan_result)
priv->report_scan_result = false;
- if (priv->scan_pending_on_block) {
- priv->scan_pending_on_block = false;
- up(&priv->async_sem);
- }
break;
case HostCmd_CMD_MAC_CONTROL:
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8132119e1a21..41aafc7454ed 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -124,8 +124,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
}
memset(priv->cfg_bssid, 0, ETH_ALEN);
- if (!netif_queue_stopped(priv->netdev))
- mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
}
@@ -197,8 +196,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
dev_dbg(adapter->dev, "event: LINK_SENSED\n");
if (!netif_carrier_ok(priv->netdev))
netif_carrier_on(priv->netdev);
- if (netif_queue_stopped(priv->netdev))
- mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
break;
case EVENT_DEAUTHENTICATED:
@@ -306,8 +304,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
priv->adhoc_is_link_sensed = false;
mwifiex_clean_txrx(priv);
- if (!netif_queue_stopped(priv->netdev))
- mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
break;
@@ -424,7 +421,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
cfg80211_remain_on_channel_expired(priv->wdev,
priv->roc_cfg.cookie,
&priv->roc_cfg.chan,
- priv->roc_cfg.chan_type,
GFP_ATOMIC);
memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 0c9f70b2cbe6..cb682561c438 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -160,10 +160,21 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
{
int ret;
u8 *beacon_ie;
+ size_t beacon_ie_len;
struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
+ const struct cfg80211_bss_ies *ies;
+
+ rcu_read_lock();
+ ies = rcu_dereference(bss->ies);
+ if (WARN_ON(!ies)) {
+ /* should never happen */
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
+ beacon_ie_len = ies->len;
+ rcu_read_unlock();
- beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies,
- GFP_KERNEL);
if (!beacon_ie) {
dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
return -ENOMEM;
@@ -172,7 +183,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);
bss_desc->rssi = bss->signal;
bss_desc->beacon_buf = beacon_ie;
- bss_desc->beacon_buf_size = bss->len_beacon_ies;
+ bss_desc->beacon_buf_size = beacon_ie_len;
bss_desc->beacon_period = bss->beacon_interval;
bss_desc->cap_info_bitmap = bss->capability;
bss_desc->bss_band = bss_priv->band;
@@ -198,18 +209,23 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
struct cfg80211_bss *bss)
{
- u8 *country_ie, country_ie_len;
+ const u8 *country_ie;
+ u8 country_ie_len;
struct mwifiex_802_11d_domain_reg *domain_info =
&priv->adapter->domain_reg;
- country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
-
- if (!country_ie)
+ rcu_read_lock();
+ country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+ if (!country_ie) {
+ rcu_read_unlock();
return 0;
+ }
country_ie_len = country_ie[1];
- if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
+ if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
+ rcu_read_unlock();
return 0;
+ }
domain_info->country_code[0] = country_ie[2];
domain_info->country_code[1] = country_ie[3];
@@ -223,6 +239,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
memcpy((u8 *)domain_info->triplet,
&country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);
+ rcu_read_unlock();
+
if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
HostCmd_ACT_GEN_SET, 0, NULL)) {
wiphy_err(priv->adapter->wiphy,
@@ -276,8 +294,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
dev_dbg(adapter->dev, "info: SSID found in scan list ... "
"associating...\n");
- if (!netif_queue_stopped(priv->netdev))
- mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
@@ -318,8 +335,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
ret = mwifiex_check_network_compatibility(priv, bss_desc);
- if (!netif_queue_stopped(priv->netdev))
- mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
@@ -463,7 +479,7 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
}
if (adapter->hs_activated) {
- dev_dbg(adapter->dev, "cmd: HS Already actived\n");
+ dev_dbg(adapter->dev, "cmd: HS Already activated\n");
return true;
}
@@ -713,7 +729,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
priv->wpa_ie_len, priv->wpa_ie[0]);
- if (priv->wpa_ie[0] == WLAN_EID_WPA) {
+ if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
priv->sec_info.wpa_enabled = true;
} else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
priv->sec_info.wpa2_enabled = true;
@@ -1046,7 +1062,6 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv)
int
mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
struct ieee80211_channel *chan,
- enum nl80211_channel_type *ct,
unsigned int duration)
{
struct host_cmd_ds_remain_on_chan roc_cfg;
@@ -1056,7 +1071,7 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
roc_cfg.action = cpu_to_le16(action);
if (action == HostCmd_ACT_GEN_SET) {
roc_cfg.band_cfg = chan->band;
- sc = mwifiex_chan_type_to_sec_chan_offset(*ct);
+ sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);
roc_cfg.band_cfg |= (sc << 2);
roc_cfg.channel =
@@ -1253,7 +1268,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
}
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
/* Test to see if it is a WPA IE, if not, then it is a gen IE */
- if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
+ if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
(!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
(pvendor_ie->element_id == WLAN_EID_RSN)) {
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 07d32b73783e..b5c109504393 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -38,14 +38,10 @@
*
* The completion callback is called after processing in complete.
*/
-int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
struct sk_buff *skb)
{
int ret;
- struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
- struct mwifiex_private *priv =
- mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
- rx_info->bss_type);
struct rx_packet_hdr *rx_pkt_hdr;
struct rxpd *local_rx_pd;
int hdr_chop;
@@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
priv->rxpd_htinfo = local_rx_pd->ht_info;
- ret = mwifiex_recv_packet(adapter, skb);
+ ret = mwifiex_recv_packet(priv, skb);
if (ret == -1)
- dev_err(adapter->dev, "recv packet failed\n");
+ dev_err(priv->adapter->dev, "recv packet failed\n");
return ret;
}
@@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
*
* The completion callback is called after processing in complete.
*/
-int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
struct sk_buff *skb)
{
+ struct mwifiex_adapter *adapter = priv->adapter;
int ret = 0;
struct rxpd *local_rx_pd;
- struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
struct rx_packet_hdr *rx_pkt_hdr;
u8 ta[ETH_ALEN];
u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
- struct mwifiex_private *priv =
- mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
- rx_info->bss_type);
-
- if (!priv)
- return -1;
local_rx_pd = (struct rxpd *) (skb->data);
rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
@@ -169,13 +159,13 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
while (!skb_queue_empty(&list)) {
rx_skb = __skb_dequeue(&list);
- ret = mwifiex_recv_packet(adapter, rx_skb);
+ ret = mwifiex_recv_packet(priv, rx_skb);
if (ret == -1)
dev_err(adapter->dev, "Rx of A-MSDU failed");
}
return 0;
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
- ret = mwifiex_process_mgmt_packet(adapter, skb);
+ ret = mwifiex_process_mgmt_packet(priv, skb);
if (ret)
dev_err(adapter->dev, "Rx of mgmt packet failed");
dev_kfree_skb_any(skb);
@@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
*/
if (!IS_11N_ENABLED(priv) ||
memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) {
- mwifiex_process_rx_packet(adapter, skb);
+ mwifiex_process_rx_packet(priv, skb);
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 2af263992e83..8c80024c30ff 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
if (!priv)
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+ if (!priv) {
+ dev_err(adapter->dev, "data: priv not found. Drop RX packet\n");
+ dev_kfree_skb_any(skb);
+ return -1;
+ }
+
rx_info->bss_num = priv->bss_num;
rx_info->bss_type = priv->bss_type;
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
- return mwifiex_process_uap_rx_packet(adapter, skb);
+ return mwifiex_process_uap_rx_packet(priv, skb);
- return mwifiex_process_sta_rx_packet(adapter, skb);
+ return mwifiex_process_sta_rx_packet(priv, skb);
}
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
@@ -115,13 +121,13 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
ret);
adapter->dbg.num_tx_host_to_card_failure++;
- mwifiex_write_data_complete(adapter, skb, ret);
+ mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
case -EINPROGRESS:
adapter->data_sent = false;
break;
case 0:
- mwifiex_write_data_complete(adapter, skb, ret);
+ mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
default:
break;
@@ -138,11 +144,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
* wakes up stalled traffic queue if required, and then frees the buffer.
*/
int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
- struct sk_buff *skb, int status)
+ struct sk_buff *skb, int aggr, int status)
{
- struct mwifiex_private *priv, *tpriv;
+ struct mwifiex_private *priv;
struct mwifiex_txinfo *tx_info;
- int i;
+ struct netdev_queue *txq;
+ int index;
if (!skb)
return 0;
@@ -166,15 +173,20 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
atomic_dec_return(&adapter->pending_bridged_pkts);
- if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
+
+ if (aggr)
+ /* For skb_aggr, do not wake up tx queue */
goto done;
- for (i = 0; i < adapter->priv_num; i++) {
- tpriv = adapter->priv[i];
+ atomic_dec(&adapter->tx_pending);
- if (tpriv->media_connected &&
- netif_queue_stopped(tpriv->netdev))
- mwifiex_wake_up_net_dev_queue(tpriv->netdev, adapter);
+ index = mwifiex_1d_to_wmm_queue[skb->priority];
+ if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
+ txq = netdev_get_tx_queue(priv->netdev, index);
+ if (netif_tx_queue_stopped(txq)) {
+ netif_tx_wake_queue(txq);
+ dev_dbg(adapter->dev, "wake queue: %d\n", index);
+ }
}
done:
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index d95a2d558fcf..8dd72240f162 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -188,10 +188,19 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
const u8 *var_pos = params->beacon.head + var_offset;
int len = params->beacon.head_len - var_offset;
+ u8 rate_len = 0;
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
- if (rate_ie)
+ if (rate_ie) {
memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+ rate_len = rate_ie->len;
+ }
+
+ rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
+ params->beacon.tail,
+ params->beacon.tail_len);
+ if (rate_ie)
+ memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
return;
}
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index a33fa394e349..21c640d3b579 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -235,11 +235,18 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
break;
case EVENT_UAP_BSS_IDLE:
priv->media_connected = false;
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+ mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+
mwifiex_clean_txrx(priv);
mwifiex_del_all_sta_list(priv);
break;
case EVENT_UAP_BSS_ACTIVE:
priv->media_connected = true;
+ if (!netif_carrier_ok(priv->netdev))
+ netif_carrier_on(priv->netdev);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
break;
case EVENT_UAP_BSS_START:
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index 0966ac24b3b4..a018e42d117e 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
}
/* Forward unicat/Inter-BSS packets to kernel. */
- return mwifiex_process_rx_packet(adapter, skb);
+ return mwifiex_process_rx_packet(priv, skb);
}
/*
@@ -159,24 +159,17 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
*
* The completion callback is called after processing is complete.
*/
-int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
struct sk_buff *skb)
{
+ struct mwifiex_adapter *adapter = priv->adapter;
int ret;
struct uap_rxpd *uap_rx_pd;
- struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
struct rx_packet_hdr *rx_pkt_hdr;
u16 rx_pkt_type;
u8 ta[ETH_ALEN], pkt_type;
struct mwifiex_sta_node *node;
- struct mwifiex_private *priv =
- mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
- rx_info->bss_type);
-
- if (!priv)
- return -1;
-
uap_rx_pd = (struct uap_rxpd *)(skb->data);
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
@@ -210,7 +203,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
while (!skb_queue_empty(&list)) {
rx_skb = __skb_dequeue(&list);
- ret = mwifiex_recv_packet(adapter, rx_skb);
+ ret = mwifiex_recv_packet(priv, rx_skb);
if (ret)
dev_err(adapter->dev,
"AP:Rx A-MSDU failed");
@@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
return 0;
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
- ret = mwifiex_process_mgmt_packet(adapter, skb);
+ ret = mwifiex_process_mgmt_packet(priv, skb);
if (ret)
dev_err(adapter->dev, "Rx of mgmt packet failed");
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 22a5916564b8..63ac9f2d11ae 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -238,7 +238,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
} else {
dev_dbg(adapter->dev, "%s: DATA\n", __func__);
atomic_dec(&card->tx_data_urb_pending);
- mwifiex_write_data_complete(adapter, context->skb,
+ mwifiex_write_data_complete(adapter, context->skb, 0,
urb->status ? -1 : 0);
}
@@ -351,7 +351,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
card->udev = udev;
card->intf = intf;
- pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocl=%#x\n",
+ pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n",
udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass,
udev->descriptor.bDeviceSubClass,
udev->descriptor.bDeviceProtocol);
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index ae88f80cf86b..0982375ba3b1 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
* to the kernel.
*/
int
-mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
+mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
struct sk_buff *skb)
{
struct rxpd *rx_pd;
- struct mwifiex_private *priv;
u16 pkt_len;
if (!skb)
return -1;
rx_pd = (struct rxpd *)skb->data;
- priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type);
- if (!priv)
- return -1;
skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
skb_pull(skb, sizeof(pkt_len));
@@ -190,20 +186,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
* the function creates a blank SKB, fills it with the data from the
* received buffer and then sends this new SKB to the kernel.
*/
-int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
{
- struct mwifiex_rxinfo *rx_info;
- struct mwifiex_private *priv;
-
if (!skb)
return -1;
- rx_info = MWIFIEX_SKB_RXCB(skb);
- priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
- rx_info->bss_type);
- if (!priv)
- return -1;
-
skb->dev = priv->netdev;
skb->protocol = eth_type_trans(skb, priv->netdev);
skb->ip_summed = CHECKSUM_NONE;
@@ -225,7 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
* fragments. Currently we fail the Filesndl-ht.scr script
* for UDP, hence this fix
*/
- if ((adapter->iface_type == MWIFIEX_USB) &&
+ if ((priv->adapter->iface_type == MWIFIEX_USB) &&
(skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 600d8194610e..818f871ae987 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -483,7 +483,7 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
struct sk_buff *skb, *tmp;
skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
- mwifiex_write_data_complete(adapter, skb, -1);
+ mwifiex_write_data_complete(adapter, skb, 0, -1);
}
/*
@@ -650,7 +650,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
dev_dbg(adapter->dev, "data: drop packet in disconnect\n");
- mwifiex_write_data_complete(adapter, skb, -1);
+ mwifiex_write_data_complete(adapter, skb, 0, -1);
return;
}
@@ -680,7 +680,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
if (!ra_list) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
- mwifiex_write_data_complete(adapter, skb, -1);
+ mwifiex_write_data_complete(adapter, skb, 0, -1);
return;
}
@@ -1090,7 +1090,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
- mwifiex_write_data_complete(adapter, skb, -1);
+ mwifiex_write_data_complete(adapter, skb, 0, -1);
return;
}
@@ -1195,7 +1195,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
- mwifiex_write_data_complete(adapter, skb, -1);
+ mwifiex_write_data_complete(adapter, skb, 0, -1);
return;
}
@@ -1209,7 +1209,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
adapter->data_sent = false;
dev_err(adapter->dev, "host_to_card failed: %#x\n", ret);
adapter->dbg.num_tx_host_to_card_failure++;
- mwifiex_write_data_complete(adapter, skb, ret);
+ mwifiex_write_data_complete(adapter, skb, 0, ret);
break;
case -EINPROGRESS:
adapter->data_sent = false;
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index ec839952d2e7..b92f39d8963b 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -31,6 +31,8 @@ enum ieee_types_wmm_ecw_bitmasks {
MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)),
};
+static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+
/*
* This function retrieves the TID of the given RA list.
*/
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 5099e5375cb3..f221b95b90b3 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1851,6 +1851,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
bool start_ba_session = false;
bool mgmtframe = false;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ bool eapol_frame = false;
wh = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_data_qos(wh->frame_control))
@@ -1858,6 +1859,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
else
qos = 0;
+ if (skb->protocol == cpu_to_be16(ETH_P_PAE))
+ eapol_frame = true;
+
if (ieee80211_is_mgmt(wh->frame_control))
mgmtframe = true;
@@ -1916,9 +1920,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
txpriority = index;
- if (priv->ap_fw && sta && sta->ht_cap.ht_supported
- && skb->protocol != cpu_to_be16(ETH_P_PAE)
- && ieee80211_is_data_qos(wh->frame_control)) {
+ if (priv->ap_fw && sta && sta->ht_cap.ht_supported && !eapol_frame &&
+ ieee80211_is_data_qos(wh->frame_control)) {
tid = qos & 0xf;
mwl8k_tx_count_packet(sta, tid);
spin_lock(&priv->stream_lock);
@@ -2005,6 +2008,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
spin_unlock(&priv->stream_lock);
}
spin_unlock_bh(&priv->tx_lock);
+ pci_unmap_single(priv->pdev, dma, skb->len,
+ PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
return;
}
@@ -2025,9 +2030,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
else
tx->peer_id = 0;
- if (priv->ap_fw)
+ if (priv->ap_fw && ieee80211_is_data(wh->frame_control) && !eapol_frame)
tx->timestamp = cpu_to_le32(ioread32(priv->regs +
MWL8K_HW_TIMER_REGISTER));
+ else
+ tx->timestamp = 0;
wmb();
tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
@@ -3679,7 +3686,8 @@ struct mwl8k_cmd_bastream {
} __packed;
static int
-mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
+mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
+ struct ieee80211_vif *vif)
{
struct mwl8k_cmd_bastream *cmd;
int rc;
@@ -3702,7 +3710,7 @@ mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
- rc = mwl8k_post_cmd(hw, &cmd->header);
+ rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
kfree(cmd);
@@ -3711,7 +3719,7 @@ mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
static int
mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
- u8 buf_size)
+ u8 buf_size, struct ieee80211_vif *vif)
{
struct mwl8k_cmd_bastream *cmd;
int rc;
@@ -3745,7 +3753,7 @@ mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
BASTREAM_FLAG_DIRECTION_UPSTREAM);
- rc = mwl8k_post_cmd(hw, &cmd->header);
+ rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
stream->sta->addr, stream->tid);
@@ -5085,6 +5093,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_ampdu_stream *stream;
u8 *addr = sta->addr;
+ struct mwl8k_sta *sta_info = MWL8K_STA(sta);
if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
return -ENOTSUPP;
@@ -5127,7 +5136,16 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
/* Release the lock before we do the time consuming stuff */
spin_unlock(&priv->stream_lock);
for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) {
- rc = mwl8k_check_ba(hw, stream);
+
+ /* Check if link is still valid */
+ if (!sta_info->is_ampdu_allowed) {
+ spin_lock(&priv->stream_lock);
+ mwl8k_remove_stream(hw, stream);
+ spin_unlock(&priv->stream_lock);
+ return -EBUSY;
+ }
+
+ rc = mwl8k_check_ba(hw, stream, vif);
/* If HW restart is in progress mwl8k_post_cmd will
* return -EBUSY. Avoid retrying mwl8k_check_ba in
@@ -5167,7 +5185,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
BUG_ON(stream == NULL);
BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS);
spin_unlock(&priv->stream_lock);
- rc = mwl8k_create_ba(hw, stream, buf_size);
+ rc = mwl8k_create_ba(hw, stream, buf_size, vif);
spin_lock(&priv->stream_lock);
if (!rc)
stream->state = AMPDU_STREAM_ACTIVE;
@@ -5240,7 +5258,7 @@ enum {
#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
-static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
+static struct mwl8k_device_info mwl8k_info_tbl[] = {
[MWL8363] = {
.part_name = "88w8363",
.helper_image = "mwl8k/helper_8363.fw",
@@ -5617,6 +5635,18 @@ fail:
return rc;
}
+static const struct ieee80211_iface_limit ap_if_limits[] = {
+ { .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
+};
+
+static const struct ieee80211_iface_combination ap_if_comb = {
+ .limits = ap_if_limits,
+ .n_limits = ARRAY_SIZE(ap_if_limits),
+ .max_interfaces = 8,
+ .num_different_channels = 1,
+};
+
+
static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
{
struct ieee80211_hw *hw = priv->hw;
@@ -5696,8 +5726,13 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
goto err_free_cookie;
hw->wiphy->interface_modes = 0;
- if (priv->ap_macids_supported || priv->device_info->fw_image_ap)
+
+ if (priv->ap_macids_supported || priv->device_info->fw_image_ap) {
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
+ hw->wiphy->iface_combinations = &ap_if_comb;
+ hw->wiphy->n_iface_combinations = 1;
+ }
+
if (priv->sta_macids_supported || priv->device_info->fw_image_sta)
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
@@ -5721,7 +5756,7 @@ err_free_cookie:
return rc;
}
-static int __devinit mwl8k_probe(struct pci_dev *pdev,
+static int mwl8k_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
static int printed_version;
@@ -5838,12 +5873,7 @@ err_disable_device:
return rc;
}
-static void __devexit mwl8k_shutdown(struct pci_dev *pdev)
-{
- printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__);
-}
-
-static void __devexit mwl8k_remove(struct pci_dev *pdev)
+static void mwl8k_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct mwl8k_priv *priv;
@@ -5895,8 +5925,7 @@ static struct pci_driver mwl8k_driver = {
.name = MWL8K_NAME,
.id_table = mwl8k_pci_id_table,
.probe = mwl8k_probe,
- .remove = __devexit_p(mwl8k_remove),
- .shutdown = __devexit_p(mwl8k_shutdown),
+ .remove = mwl8k_remove,
};
module_pci_driver(mwl8k_driver);
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 7b751fba7e1f..d01edd2c50c5 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -161,24 +161,23 @@ static int orinoco_scan(struct wiphy *wiphy,
}
static int orinoco_set_monitor_channel(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
+ struct cfg80211_chan_def *chandef)
{
struct orinoco_private *priv = wiphy_priv(wiphy);
int err = 0;
unsigned long flags;
int channel;
- if (!chan)
+ if (!chandef->chan)
return -EINVAL;
- if (channel_type != NL80211_CHAN_NO_HT)
+ if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
return -EINVAL;
- if (chan->band != IEEE80211_BAND_2GHZ)
+ if (chandef->chan->band != IEEE80211_BAND_2GHZ)
return -EINVAL;
- channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
+ channel = ieee80211_freq_to_dsss_chan(chandef->chan->center_freq);
if ((channel < 1) || (channel > NUM_CHANNELS) ||
!(priv->channel_mask & (1 << (channel - 1))))
diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h
index 4dadf9880a97..5a8fec26136e 100644
--- a/drivers/net/wireless/orinoco/main.h
+++ b/drivers/net/wireless/orinoco/main.h
@@ -39,7 +39,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
{
u8 *p = data;
while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
- if ((p[0] == WLAN_EID_GENERIC) &&
+ if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
(memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
return p;
p += p[1] + 2;
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index 326396b313a6..d73fdf6185a2 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -255,7 +255,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
return err;
}
-static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
+static void orinoco_nortel_remove_one(struct pci_dev *pdev)
{
struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
@@ -288,7 +288,7 @@ static struct pci_driver orinoco_nortel_driver = {
.name = DRIVER_NAME,
.id_table = orinoco_nortel_id_table,
.probe = orinoco_nortel_init_one,
- .remove = __devexit_p(orinoco_nortel_remove_one),
+ .remove = orinoco_nortel_remove_one,
.suspend = orinoco_pci_suspend,
.resume = orinoco_pci_resume,
};
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 6058c66b844e..677bf14eca84 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -199,7 +199,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
return err;
}
-static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
+static void orinoco_pci_remove_one(struct pci_dev *pdev)
{
struct orinoco_private *priv = pci_get_drvdata(pdev);
@@ -228,7 +228,7 @@ static struct pci_driver orinoco_pci_driver = {
.name = DRIVER_NAME,
.id_table = orinoco_pci_id_table,
.probe = orinoco_pci_init_one,
- .remove = __devexit_p(orinoco_pci_remove_one),
+ .remove = orinoco_pci_remove_one,
.suspend = orinoco_pci_suspend,
.resume = orinoco_pci_resume,
};
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index 2bac8248a991..2559dbd6184b 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -294,7 +294,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
return err;
}
-static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
+static void orinoco_plx_remove_one(struct pci_dev *pdev)
{
struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
@@ -334,7 +334,7 @@ static struct pci_driver orinoco_plx_driver = {
.name = DRIVER_NAME,
.id_table = orinoco_plx_id_table,
.probe = orinoco_plx_init_one,
- .remove = __devexit_p(orinoco_plx_remove_one),
+ .remove = orinoco_plx_remove_one,
.suspend = orinoco_pci_suspend,
.resume = orinoco_pci_resume,
};
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 93159d68ec93..42afeeea2c40 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -188,7 +188,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
return err;
}
-static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
+static void orinoco_tmd_remove_one(struct pci_dev *pdev)
{
struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
@@ -214,7 +214,7 @@ static struct pci_driver orinoco_tmd_driver = {
.name = DRIVER_NAME,
.id_table = orinoco_tmd_id_table,
.probe = orinoco_tmd_init_one,
- .remove = __devexit_p(orinoco_tmd_remove_one),
+ .remove = orinoco_tmd_remove_one,
.suspend = orinoco_pci_suspend,
.resume = orinoco_pci_resume,
};
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 7f53cea2f205..01624dcaf73e 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
static int ezusb_access_ltv(struct ezusb_priv *upriv,
struct request_context *ctx,
u16 length, const void *data, u16 frame_type,
- void *ans_buff, int ans_size, u16 *ans_length)
+ void *ans_buff, unsigned ans_size, u16 *ans_length)
{
int req_size;
int retval = 0;
@@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
}
if (ctx->in_rid) {
struct ezusb_packet *ans = ctx->buf;
- int exp_len;
+ unsigned exp_len;
if (ans->hermes_len != 0)
exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
@@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
}
if (ans_buff)
- memcpy(ans_buff, ans->data,
- min_t(int, exp_len, ans_size));
+ memcpy(ans_buff, ans->data, min(exp_len, ans_size));
if (ans_length)
*ans_length = le16_to_cpu(ans->hermes_len);
}
@@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
struct ezusb_priv *upriv = hw->priv;
struct request_context *ctx;
- if ((bufsize < 0) || (bufsize % 2))
+ if (bufsize % 2)
return -EINVAL;
ctx = ezusb_alloc_ctx(upriv, rid, rid);
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 1ef1bfe6a9d7..d43e3740e45d 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -541,8 +541,9 @@ static int p54_parse_rssical(struct ieee80211_hw *dev,
entries = (len - offset) /
sizeof(struct pda_rssi_cal_ext_entry);
- if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
- entries <= 0) {
+ if (len < offset ||
+ (len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
+ entries == 0) {
wiphy_err(dev->wiphy, "invalid rssi database.\n");
goto err_data;
}
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index b4390797d78c..933e5d941937 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -540,7 +540,7 @@ out:
pci_dev_put(pdev);
}
-static int __devinit p54p_probe(struct pci_dev *pdev,
+static int p54p_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct p54p_priv *priv;
@@ -639,7 +639,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
return err;
}
-static void __devexit p54p_remove(struct pci_dev *pdev)
+static void p54p_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct p54p_priv *priv;
@@ -659,7 +659,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
p54_free_common(dev);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int p54p_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
@@ -681,25 +681,18 @@ static int p54p_resume(struct device *device)
return pci_set_power_state(pdev, PCI_D0);
}
-static const struct dev_pm_ops p54pci_pm_ops = {
- .suspend = p54p_suspend,
- .resume = p54p_resume,
- .freeze = p54p_suspend,
- .thaw = p54p_resume,
- .poweroff = p54p_suspend,
- .restore = p54p_resume,
-};
+static SIMPLE_DEV_PM_OPS(p54pci_pm_ops, p54p_suspend, p54p_resume);
#define P54P_PM_OPS (&p54pci_pm_ops)
#else
#define P54P_PM_OPS (NULL)
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
static struct pci_driver p54p_driver = {
.name = "p54pci",
.id_table = p54p_table,
.probe = p54p_probe,
- .remove = __devexit_p(p54p_remove),
+ .remove = p54p_remove,
.driver.pm = P54P_PM_OPS,
};
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index f7929906d437..4fd49a007b51 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -595,7 +595,7 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
cancel_work_sync(&priv->work);
}
-static int __devinit p54spi_probe(struct spi_device *spi)
+static int p54spi_probe(struct spi_device *spi)
{
struct p54s_priv *priv = NULL;
struct ieee80211_hw *hw;
@@ -683,7 +683,7 @@ err_free:
return ret;
}
-static int __devexit p54spi_remove(struct spi_device *spi)
+static int p54spi_remove(struct spi_device *spi)
{
struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
@@ -710,7 +710,7 @@ static struct spi_driver p54spi_driver = {
},
.probe = p54spi_probe,
- .remove = __devexit_p(p54spi_remove),
+ .remove = p54spi_remove,
};
static int __init p54spi_init(void)
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index effb044a8a9d..e71c702e2eb1 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -986,7 +986,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
return err;
}
-static int __devinit p54u_probe(struct usb_interface *intf,
+static int p54u_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
@@ -1057,7 +1057,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
return err;
}
-static void __devexit p54u_disconnect(struct usb_interface *intf)
+static void p54u_disconnect(struct usb_interface *intf)
{
struct ieee80211_hw *dev = usb_get_intfdata(intf);
struct p54u_priv *priv;
@@ -1131,7 +1131,7 @@ static struct usb_driver p54u_driver = {
.name = "p54usb",
.id_table = p54u_table,
.probe = p54u_probe,
- .disconnect = __devexit_p(p54u_disconnect),
+ .disconnect = p54u_disconnect,
.pre_reset = p54u_pre_reset,
.post_reset = p54u_post_reset,
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 5861e13a6fd8..12f0a34477f2 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -369,7 +369,11 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
priv->tsf_low32 = tsf32;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ /* LMAC API Page 10/29 - s_lm_data_in - clock
+ * "usec accurate timestamp of hardware clock
+ * at end of frame (before OFDM SIFS EOF padding"
+ */
+ rx_status->flag |= RX_FLAG_MACTIME_END;
if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
header_len += hdr->align[0];
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index bd1f0cb56085..abe1d039be81 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -490,9 +490,12 @@ static int rndis_scan(struct wiphy *wiphy,
static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
static int rndis_set_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
enum nl80211_tx_power_setting type,
int mbm);
-static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
+static int rndis_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ int *dbm);
static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme);
@@ -1903,6 +1906,7 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
}
static int rndis_set_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
enum nl80211_tx_power_setting type,
int mbm)
{
@@ -1930,7 +1934,9 @@ static int rndis_set_tx_power(struct wiphy *wiphy,
return -ENOTSUPP;
}
-static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
+static int rndis_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ int *dbm)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
@@ -2287,7 +2293,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
- struct ieee80211_channel *channel = params->channel;
+ struct ieee80211_channel *channel = params->chandef.chan;
struct ndis_80211_ssid ssid;
enum nl80211_auth_type auth_type;
int ret, alg, length, chan = -1;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index e3a2d9070cf6..a2d2bc2c7b3d 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1831,7 +1831,7 @@ static struct pci_driver rt2400pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2400pci_device_table,
.probe = rt2400pci_probe,
- .remove = __devexit_p(rt2x00pci_remove),
+ .remove = rt2x00pci_remove,
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
};
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 479d756e275b..9bea10f53f0a 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2122,7 +2122,7 @@ static struct pci_driver rt2500pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2500pci_device_table,
.probe = rt2500pci_probe,
- .remove = __devexit_p(rt2x00pci_remove),
+ .remove = rt2x00pci_remove,
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
};
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 6d67c3ede651..4db1088a847f 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1993,8 +1993,10 @@ struct mac_iveiv_entry {
*/
#define RFCSR3_K FIELD8(0x0f)
/* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */
-#define RFCSR3_PA1_BIAS_CCK FIELD8(0x70);
-#define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80);
+#define RFCSR3_PA1_BIAS_CCK FIELD8(0x70)
+#define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80)
+/* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */
+#define RFCSR3_VCOCAL_EN FIELD8(0x80)
/*
* FRCSR 5:
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 59474ae0aec0..197b4466a5d2 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2173,7 +2173,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 59,
r59_nonbt_rev[idx]);
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392)) {
static const char r59_non_bt[] = {0x8f, 0x8f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
@@ -2243,7 +2243,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}
@@ -2264,7 +2264,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
if (rf->channel <= 14) {
if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
+ !rt2x00_rt(rt2x00dev, RT5392)) {
if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,
&rt2x00dev->cap_flags)) {
rt2800_bbp_write(rt2x00dev, 82, 0x62);
@@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
return comp_value;
}
+static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
+ int power_level, int max_power)
+{
+ int delta;
+
+ if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags))
+ return 0;
+
+ /*
+ * XXX: We don't know the maximum transmit power of our hardware since
+ * the EEPROM doesn't expose it. We only know that we are calibrated
+ * to 100% tx power.
+ *
+ * Hence, we assume the regulatory limit that cfg80211 calulated for
+ * the current channel is our maximum and if we are requested to lower
+ * the value we just reduce our tx power accordingly.
+ */
+ delta = power_level - max_power;
+ return min(delta, 0);
+}
+
static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
enum ieee80211_band band, int power_level,
u8 txpower, int delta)
{
- u32 reg;
u16 eeprom;
u8 criterion;
u8 eirp_txpower;
u8 eirp_txpower_criterion;
u8 reg_limit;
- if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
- return txpower;
-
if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
/*
* Check if eirp txpower exceed txpower_limit.
@@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
* .11b data rate need add additional 4dbm
* when calculating eirp txpower.
*/
- rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
- criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
+ &eeprom);
+ criterion = rt2x00_get_field16(eeprom,
+ EEPROM_TXPOWER_BYRATE_RATE0);
- rt2x00_eeprom_read(rt2x00dev,
- EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
+ &eeprom);
if (band == IEEE80211_BAND_2GHZ)
eirp_txpower_criterion = rt2x00_get_field16(eeprom,
@@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
} else
reg_limit = 0;
- return txpower + delta - reg_limit;
+ txpower = max(0, txpower + delta - reg_limit);
+ return min_t(u8, txpower, 0xc);
}
+/*
+ * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
+ * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
+ * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
+ * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
+ * Reference per rate transmit power values are located in the EEPROM at
+ * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
+ * current conditions (i.e. band, bandwidth, temperature, user settings).
+ */
static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
- enum ieee80211_band band,
+ struct ieee80211_channel *chan,
int power_level)
{
- u8 txpower;
+ u8 txpower, r1;
u16 eeprom;
- int i, is_rate_b;
- u32 reg;
- u8 r1;
- u32 offset;
- int delta;
+ u32 reg, offset;
+ int i, is_rate_b, delta, power_ctrl;
+ enum ieee80211_band band = chan->band;
/*
- * Calculate HT40 compensation delta
+ * Calculate HT40 compensation. For 40MHz we need to add or subtract
+ * value read from EEPROM (different for 2GHz and for 5GHz).
*/
delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
/*
- * calculate temperature compensation delta
+ * Calculate temperature compensation. Depends on measurement of current
+ * TSSI (Transmitter Signal Strength Indication) we know TX power (due
+ * to temperature or maybe other factors) is smaller or bigger than
+ * expected. We adjust it, based on TSSI reference and boundaries values
+ * provided in EEPROM.
*/
delta += rt2800_get_gain_calibration_delta(rt2x00dev);
/*
- * set to normal bbp tx power control mode: +/- 0dBm
+ * Decrease power according to user settings, on devices with unknown
+ * maximum tx power. For other devices we take user power_level into
+ * consideration on rt2800_compensate_txpower().
+ */
+ delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
+ chan->max_power);
+
+ /*
+ * BBP_R1 controls TX power for all rates, it allow to set the following
+ * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
+ *
+ * TODO: we do not use +6 dBm option to do not increase power beyond
+ * regulatory limit, however this could be utilized for devices with
+ * CAPABILITY_POWER_LIMIT.
*/
rt2800_bbp_read(rt2x00dev, 1, &r1);
- rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
+ if (delta <= -12) {
+ power_ctrl = 2;
+ delta += 12;
+ } else if (delta <= -6) {
+ power_ctrl = 1;
+ delta += 6;
+ } else {
+ power_ctrl = 0;
+ }
+ rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
rt2800_bbp_write(rt2x00dev, 1, r1);
offset = TX_PWR_CFG_0;
@@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
{
- rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
+ rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
rt2x00dev->tx_power);
}
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
@@ -2750,7 +2804,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
case RF5390:
case RF5392:
rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
break;
default:
@@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
rt2800_config_channel(rt2x00dev, libconf->conf,
&libconf->rf, &libconf->channel);
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
libconf->conf->power_level);
}
if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
libconf->conf->power_level);
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
rt2800_config_retry_limit(rt2x00dev, libconf);
@@ -3538,8 +3592,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
rt2800_bbp_write(rt2x00dev, 84, 0x19);
else if (rt2x00_rt(rt2x00dev, RT3290) ||
- rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 84, 0x9a);
else
rt2800_bbp_write(rt2x00dev, 84, 0x99);
@@ -3598,7 +3652,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
else if (rt2x00_rt(rt2x00dev, RT3352))
rt2800_bbp_write(rt2x00dev, 105, 0x34);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c);
else
rt2800_bbp_write(rt2x00dev, 105, 0x05);
@@ -3692,7 +3746,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
}
if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392)) {
int ant, div_mode;
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
@@ -4166,66 +4220,66 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
- } else if (rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
- rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
- rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
- rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
- rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
- rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
- rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
- rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
- rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
- rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
- rt2800_rfcsr_write(rt2x00dev, 19, 0x4d);
- rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 21, 0x8d);
- rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
- rt2800_rfcsr_write(rt2x00dev, 23, 0x0b);
- rt2800_rfcsr_write(rt2x00dev, 24, 0x44);
- rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
- rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
- rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
- rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
- rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
- rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
- rt2800_rfcsr_write(rt2x00dev, 32, 0x20);
- rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
- rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
- rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
- rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
- rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
- rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
- rt2800_rfcsr_write(rt2x00dev, 40, 0x0f);
- rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
- rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
- rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
- rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
- rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
- rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
- rt2800_rfcsr_write(rt2x00dev, 47, 0x0c);
- rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
- rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
- rt2800_rfcsr_write(rt2x00dev, 50, 0x94);
- rt2800_rfcsr_write(rt2x00dev, 51, 0x3a);
- rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
- rt2800_rfcsr_write(rt2x00dev, 53, 0x44);
- rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
- rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
- rt2800_rfcsr_write(rt2x00dev, 56, 0xa1);
- rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
- rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
- rt2800_rfcsr_write(rt2x00dev, 59, 0x07);
- rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
- rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
- rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
- rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+ } else if (rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x4d);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0x8d);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0x0b);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x44);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
+ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+ rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x0c);
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
+ rt2800_rfcsr_write(rt2x00dev, 50, 0x94);
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x3a);
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
+ rt2800_rfcsr_write(rt2x00dev, 53, 0x44);
+ rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 56, 0xa1);
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x07);
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+ rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
+ rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
+ rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
}
if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -4302,7 +4356,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
+ !rt2x00_rt(rt2x00dev, RT5392)) {
/*
* Set back to initial state
*/
@@ -4331,7 +4385,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
+ !rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
if (rt2x00_rt(rt2x00dev, RT3070) ||
@@ -4403,7 +4457,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
}
if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
@@ -5036,7 +5090,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_AMPDU_AGGREGATION |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL;
/*
* Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 27829e1e2e38..9224d874bf24 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1176,7 +1176,7 @@ static struct platform_driver rt2800soc_driver = {
.mod_name = KBUILD_MODNAME,
},
.probe = rt2800soc_probe,
- .remove = __devexit_p(rt2x00soc_remove),
+ .remove = rt2x00soc_remove,
.suspend = rt2x00soc_suspend,
.resume = rt2x00soc_resume,
};
@@ -1193,7 +1193,7 @@ static struct pci_driver rt2800pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2800pci_device_table,
.probe = rt2800pci_probe,
- .remove = __devexit_p(rt2x00pci_remove),
+ .remove = rt2x00pci_remove,
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
};
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 3b8fb5a603f2..5c149b58ab46 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1096,6 +1096,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x177f, 0x0153) },
{ USB_DEVICE(0x177f, 0x0302) },
{ USB_DEVICE(0x177f, 0x0313) },
+ { USB_DEVICE(0x177f, 0x0323) },
/* U-Media */
{ USB_DEVICE(0x157e, 0x300e) },
{ USB_DEVICE(0x157e, 0x3013) },
@@ -1169,6 +1170,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x2001, 0x3c19) },
{ USB_DEVICE(0x2001, 0x3c1c) },
{ USB_DEVICE(0x2001, 0x3c1d) },
+ { USB_DEVICE(0x2001, 0x3c1e) },
/* LG innotek */
{ USB_DEVICE(0x043e, 0x7a22) },
/* Panasonic */
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 69097d1faeb6..4ffb6a584cd0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -157,6 +157,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
* requested configurations.
*/
ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
rt2x00lib_intf_scheduled_iter,
rt2x00dev);
}
@@ -225,9 +226,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
return;
/* send buffered bc/mc frames out for every bssid */
- ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
- rt2x00lib_bc_buffer_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(
+ rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ rt2x00lib_bc_buffer_iter, rt2x00dev);
/*
* Devices with pre tbtt interrupt don't need to update the beacon
* here as they will fetch the next beacon directly prior to
@@ -237,9 +238,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
return;
/* fetch next beacon */
- ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
- rt2x00lib_beaconupdate_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(
+ rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ rt2x00lib_beaconupdate_iter, rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
@@ -249,9 +250,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
return;
/* fetch next beacon */
- ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
- rt2x00lib_beaconupdate_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(
+ rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ rt2x00lib_beaconupdate_iter, rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
@@ -391,10 +392,9 @@ void rt2x00lib_txdone(struct queue_entry *entry,
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
- /*
- * TODO: Need to tear down BA session here
- * if not successful.
- */
+
+ if (!success)
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
}
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
@@ -1123,6 +1123,9 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
struct ieee80211_iface_limit *if_limit;
struct ieee80211_iface_combination *if_combination;
+ if (rt2x00dev->ops->max_ap_intf < 2)
+ return;
+
/*
* Build up AP interface limits structure.
*/
@@ -1182,6 +1185,13 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
/*
+ * rt2x00 devices can only use the last n bits of the MAC address
+ * for virtual interfaces.
+ */
+ rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] =
+ (rt2x00dev->ops->max_ap_intf - 1);
+
+ /*
* Determine which operating modes are supported, all modes
* which require beaconing, depend on the availability of
* beacon entries.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 98a9e48f8e4a..ed7a1bb3f245 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -424,9 +424,9 @@ int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return 0;
- ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
- rt2x00mac_set_tim_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(
+ rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ rt2x00mac_set_tim_iter, rt2x00dev);
/* queue work to upodate the beacon template */
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index d6582a2fa353..f95792cfcf89 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3094,7 +3094,7 @@ static struct pci_driver rt61pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt61pci_device_table,
.probe = rt61pci_probe,
- .remove = __devexit_p(rt2x00pci_remove),
+ .remove = rt2x00pci_remove,
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
};
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 021d83e1b1d3..1b3c2843221d 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -150,7 +150,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
rx_status.mactime = le64_to_cpu(entry->tsft);
- rx_status.flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -901,7 +901,7 @@ static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom)
udelay(10);
}
-static int __devinit rtl8180_probe(struct pci_dev *pdev,
+static int rtl8180_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ieee80211_hw *dev;
@@ -1131,7 +1131,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
return err;
}
-static void __devexit rtl8180_remove(struct pci_dev *pdev)
+static void rtl8180_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct rtl8180_priv *priv;
@@ -1170,7 +1170,7 @@ static struct pci_driver rtl8180_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl8180_table,
.probe = rtl8180_probe,
- .remove = __devexit_p(rtl8180_remove),
+ .remove = rtl8180_remove,
#ifdef CONFIG_PM
.suspend = rtl8180_suspend,
.resume = rtl8180_resume,
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 7811b6315973..4574bd213705 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -381,7 +381,7 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.rate_idx = rate;
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
- rx_status.flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -1411,7 +1411,7 @@ static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
udelay(10);
}
-static int __devinit rtl8187_probe(struct usb_interface *intf,
+static int rtl8187_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
@@ -1639,7 +1639,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
return err;
}
-static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+static void rtl8187_disconnect(struct usb_interface *intf)
{
struct ieee80211_hw *dev = usb_get_intfdata(intf);
struct rtl8187_priv *priv;
@@ -1664,7 +1664,7 @@ static struct usb_driver rtl8187_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl8187_table,
.probe = rtl8187_probe,
- .disconnect = __devexit_p(rtl8187_disconnect),
+ .disconnect = rtl8187_disconnect,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 6b28e92d1d21..21b1bbb93a7e 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -32,6 +32,17 @@ config RTL8192DE
If you choose to build it as a module, it will be called rtl8192de
+config RTL8723AE
+ tristate "Realtek RTL8723AE PCIe Wireless Network Adapter"
+ depends on MAC80211 && PCI && EXPERIMENTAL
+ select FW_LOADER
+ select RTLWIFI
+ ---help---
+ This is the driver for Realtek RTL8723AE 802.11n PCIe
+ wireless network adapters.
+
+ If you choose to build it as a module, it will be called rtl8723ae
+
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on MAC80211 && USB
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 97935c565bab..3b1cbac741e3 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -7,7 +7,8 @@ rtlwifi-objs := \
efuse.o \
ps.o \
rc.o \
- regd.o
+ regd.o \
+ stats.o
rtl8192c_common-objs += \
@@ -24,5 +25,6 @@ obj-$(CONFIG_RTL8192CE) += rtl8192ce/
obj-$(CONFIG_RTL8192CU) += rtl8192cu/
obj-$(CONFIG_RTL8192SE) += rtl8192se/
obj-$(CONFIG_RTL8192DE) += rtl8192de/
+obj-$(CONFIG_RTL8723AE) += rtl8723ae/
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 59381fe8ed06..4494d130b37c 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -826,6 +826,30 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(rtlwifi_rate_mapping);
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ __le16 fc = rtl_get_fc(skb);
+
+ if (rtlpriv->dm.supp_phymode_switch &&
+ mac->link_state < MAC80211_LINKED &&
+ (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) {
+ if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+ rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+ }
+ if (ieee80211_is_auth(fc)) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
+ rtl_ips_nic_on(hw);
+
+ mac->link_state = MAC80211_LINKING;
+ /* Dual mac */
+ rtlpriv->phy.need_iqk = true;
+ }
+
+ return true;
+}
+
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index f35af0fdaaf0..5a8c80e259f7 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -142,4 +142,6 @@ u8 rtl_tid_to_ac(u8 tid);
extern struct attribute_group rtl_attribute_group;
int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
bool isht, u8 desc_rate, bool first_ampdu);
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
+
#endif
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 5b4b4d4eaf9e..0e510f73041a 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
u32 target_content = 0;
u8 entry_i;
- RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
- "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
- key_cont_128[0], key_cont_128[1],
- key_cont_128[2], key_cont_128[3],
- key_cont_128[4], key_cont_128[5]);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
+ key_cont_128);
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
@@ -340,7 +337,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
if (((bitmap & BIT(0)) == BIT(0)) &&
(memcmp(addr, sta_addr, ETH_ALEN) == 0)) {
/* Remove from HW Security CAM */
- memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
+ eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
"del CAM entry %d\n", i);
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index a7c0e52869ba..be33aa14c8af 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -962,7 +962,6 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
int err = 0;
u8 mac_addr[ETH_ALEN];
u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- u8 zero_addr[ETH_ALEN] = { 0 };
if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -1057,7 +1056,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
memcpy(rtlpriv->sec.key_buf[key_idx],
key->key, key->keylen);
rtlpriv->sec.key_len[key_idx] = key->keylen;
- memcpy(mac_addr, zero_addr, ETH_ALEN);
+ eth_zero_addr(mac_addr);
} else if (group_key) { /* group key */
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
"set group key\n");
@@ -1108,7 +1107,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
rtlpriv->sec.key_len[key_idx] = 0;
- memcpy(mac_addr, zero_addr, ETH_ALEN);
+ eth_zero_addr(mac_addr);
/*
*mac80211 will delete entrys one by one,
*so don't use rtl_cam_reset_all_entry
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index 07493d2957f2..fd3269f47685 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -106,6 +106,8 @@
#define COMP_REGD BIT(27)
#define COMP_CHAN BIT(28)
#define COMP_USB BIT(29)
+#define COMP_EASY_CONCURRENT COMP_USB /* reuse of this bit is OK */
+#define COMP_BT_COEXIST BIT(30)
/*--------------------------------------------------------------
Define the rt_print components
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index abc306b502ac..3deacafdcd5e 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1309,6 +1309,7 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_sta_info *sta_entry = NULL;
u8 tid = rtl_get_tid(skb);
+ __le16 fc = rtl_get_fc(skb);
if (!sta)
return false;
@@ -1316,6 +1317,12 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
if (!rtlpriv->rtlhal.earlymode_enable)
return false;
+ if (ieee80211_is_nullfunc(fc))
+ return false;
+ if (ieee80211_is_qos_nullfunc(fc))
+ return false;
+ if (ieee80211_is_pspoll(fc))
+ return false;
if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL)
return false;
if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE)
@@ -1357,10 +1364,8 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
u8 own;
u8 temp_one = 1;
- if (ieee80211_is_auth(fc)) {
- RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
- rtl_ips_nic_on(hw);
- }
+ if (ieee80211_is_mgmt(fc))
+ rtl_tx_mgmt_proc(hw, skb);
if (rtlpriv->psc.sw_ps_enabled) {
if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) &&
@@ -1628,7 +1633,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
"8192 PCI-E is found - vid/did=%x/%x\n",
venderid, deviceid);
rtlhal->hw_type = HARDWARE_TYPE_RTL8192E;
- break;
+ return false;
case RTL_PCI_REVISION_ID_8192SE:
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"8192SE is found - vid/did=%x/%x\n",
@@ -1643,6 +1648,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
break;
}
+ } else if (deviceid == RTL_PCI_8723AE_DID) {
+ rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "8723AE PCI-E is found - "
+ "vid/did=%x/%x\n", venderid, deviceid);
} else if (deviceid == RTL_PCI_8192CET_DID ||
deviceid == RTL_PCI_8192CE_DID ||
deviceid == RTL_PCI_8191CE_DID ||
@@ -1746,7 +1756,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
return true;
}
-int __devinit rtl_pci_probe(struct pci_dev *pdev,
+int rtl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ieee80211_hw *hw = NULL;
@@ -1972,6 +1982,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
}
EXPORT_SYMBOL(rtl_pci_disconnect);
+#ifdef CONFIG_PM_SLEEP
/***************************************
kernel pci power state define:
PCI_D0 ((pci_power_t __force) 0)
@@ -2011,6 +2022,7 @@ int rtl_pci_resume(struct device *dev)
return 0;
}
EXPORT_SYMBOL(rtl_pci_resume);
+#endif /* CONFIG_PM_SLEEP */
struct rtl_intf_ops rtl_pci_ops = {
.read_efuse_byte = read_efuse_byte,
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 241448fc9ed5..65b08f50022e 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -79,6 +79,7 @@
#define RTL_PCI_8173_DID 0x8173 /*8191 SE Crab */
#define RTL_PCI_8172_DID 0x8172 /*8191 SE RE */
#define RTL_PCI_8171_DID 0x8171 /*8191 SE Unicron */
+#define RTL_PCI_8723AE_DID 0x8723 /*8723AE */
#define RTL_PCI_0045_DID 0x0045 /*8190 PCI for Ceraga */
#define RTL_PCI_0046_DID 0x0046 /*8190 Cardbus for Ceraga */
#define RTL_PCI_0044_DID 0x0044 /*8192e PCIE for Ceraga */
@@ -152,6 +153,7 @@ struct rtl8192_rx_ring {
struct rtl_pci {
struct pci_dev *pdev;
+ bool irq_enabled;
bool driver_is_goingto_unload;
bool up_first_time;
@@ -234,11 +236,13 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw);
extern struct rtl_intf_ops rtl_pci_ops;
-int __devinit rtl_pci_probe(struct pci_dev *pdev,
+int rtl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
void rtl_pci_disconnect(struct pci_dev *pdev);
+#ifdef CONFIG_PM_SLEEP
int rtl_pci_suspend(struct device *dev);
int rtl_pci_resume(struct device *dev);
+#endif /* CONFIG_PM_SLEEP */
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index d5cbf01da8ac..c1e065f136ba 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -55,7 +55,8 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv,
* 1M we will not use FW rate but user rate.
*/
if (rtlmac->opmode == NL80211_IFTYPE_AP ||
- rtlmac->opmode == NL80211_IFTYPE_ADHOC) {
+ rtlmac->opmode == NL80211_IFTYPE_ADHOC ||
+ rtlmac->opmode == NL80211_IFTYPE_MESH_POINT) {
if (sta) {
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
wireless_mode = sta_entry->wireless_mode;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 1ca4e25c143b..1cdf5a271c9f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -43,8 +43,8 @@
#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \
((RTLPRIV(_priv))->mac80211.opmode == \
NL80211_IFTYPE_ADHOC) ? \
- ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \
- ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb)
+ ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
+ ((RTLPRIV(_priv))->dm.undec_sm_pwdb)
static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
0x7f8001fe,
@@ -167,18 +167,18 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
dm_digtable->cur_igvalue = 0x20;
dm_digtable->pre_igvalue = 0x0;
- dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
- dm_digtable->presta_connectstate = DIG_STA_DISCONNECT;
- dm_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+ dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+ dm_digtable->presta_cstate = DIG_STA_DISCONNECT;
+ dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
dm_digtable->rx_gain_range_max = DM_DIG_MAX;
dm_digtable->rx_gain_range_min = DM_DIG_MIN;
- dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
- dm_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX;
- dm_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+ dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+ 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;
}
@@ -189,22 +189,21 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
long rssi_val_min = 0;
- if ((dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
- (dm_digtable->cursta_connectstate == DIG_STA_CONNECT)) {
- if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
+ if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
+ (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
+ if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
rssi_val_min =
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
- rtlpriv->dm.undecorated_smoothed_pwdb) ?
- rtlpriv->dm.undecorated_smoothed_pwdb :
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ (rtlpriv->dm.entry_min_undec_sm_pwdb >
+ rtlpriv->dm.undec_sm_pwdb) ?
+ rtlpriv->dm.undec_sm_pwdb :
+ rtlpriv->dm.entry_min_undec_sm_pwdb;
else
- rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
- } else if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT ||
- dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT) {
- rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
- } else if (dm_digtable->curmultista_connectstate ==
- DIG_MULTISTA_CONNECT) {
- rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+ } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
+ dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
+ rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+ } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+ rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
}
return (u8) rssi_val_min;
@@ -286,37 +285,33 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+ struct dig_t *digtable = &rtlpriv->dm_digtable;
- if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) {
- if ((dm_digtable->backoff_val - 2) <
- dm_digtable->backoff_val_range_min)
- dm_digtable->backoff_val =
- dm_digtable->backoff_val_range_min;
+ 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
- dm_digtable->backoff_val -= 2;
- } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) {
- if ((dm_digtable->backoff_val + 2) >
- dm_digtable->backoff_val_range_max)
- dm_digtable->backoff_val =
- dm_digtable->backoff_val_range_max;
+ 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
- dm_digtable->backoff_val += 2;
+ digtable->back_val += 2;
}
- if ((dm_digtable->rssi_val_min + 10 - dm_digtable->backoff_val) >
- dm_digtable->rx_gain_range_max)
- dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_max;
- else if ((dm_digtable->rssi_val_min + 10 -
- dm_digtable->backoff_val) < dm_digtable->rx_gain_range_min)
- dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_min;
+ if ((digtable->rssi_val_min + 10 - digtable->back_val) >
+ digtable->rx_gain_range_max)
+ digtable->cur_igvalue = digtable->rx_gain_range_max;
+ else if ((digtable->rssi_val_min + 10 -
+ digtable->back_val) < digtable->rx_gain_range_min)
+ digtable->cur_igvalue = digtable->rx_gain_range_min;
else
- dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 -
- dm_digtable->backoff_val;
+ digtable->cur_igvalue = digtable->rssi_val_min + 10 -
+ digtable->back_val;
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
- "rssi_val_min = %x backoff_val %x\n",
- dm_digtable->rssi_val_min, dm_digtable->backoff_val);
+ "rssi_val_min = %x back_val %x\n",
+ digtable->rssi_val_min, digtable->back_val);
rtl92c_dm_write_dig(hw);
}
@@ -327,14 +322,14 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
bool multi_sta = false;
if (mac->opmode == NL80211_IFTYPE_ADHOC)
multi_sta = true;
if (!multi_sta ||
- dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
+ dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
initialized = false;
dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
return;
@@ -345,7 +340,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
rtl92c_dm_write_dig(hw);
}
- if (dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) {
+ if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
(dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
@@ -367,8 +362,8 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
}
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
- "curmultista_connectstate = %x dig_ext_port_stage %x\n",
- dm_digtable->curmultista_connectstate,
+ "curmultista_cstate = %x dig_ext_port_stage %x\n",
+ dm_digtable->curmultista_cstate,
dm_digtable->dig_ext_port_stage);
}
@@ -378,15 +373,14 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
- "presta_connectstate = %x, cursta_connectstate = %x\n",
- dm_digtable->presta_connectstate,
- dm_digtable->cursta_connectstate);
+ "presta_cstate = %x, cursta_cstate = %x\n",
+ dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
- if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectstate
- || dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT
- || dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+ if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
+ dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
+ dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
- if (dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
+ if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
dm_digtable->rssi_val_min =
rtl92c_dm_initial_gain_min_pwdb(hw);
rtl92c_dm_ctrl_initgain_by_rssi(hw);
@@ -394,7 +388,7 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
} else {
dm_digtable->rssi_val_min = 0;
dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
- dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
+ dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
dm_digtable->cur_igvalue = 0x20;
dm_digtable->pre_igvalue = 0;
rtl92c_dm_write_dig(hw);
@@ -407,7 +401,7 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
- if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+ if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
@@ -484,15 +478,15 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
return;
if (mac->link_state >= MAC80211_LINKED)
- dm_digtable->cursta_connectstate = DIG_STA_CONNECT;
+ dm_digtable->cursta_cstate = DIG_STA_CONNECT;
else
- dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
+ dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
rtl92c_dm_initial_gain_sta(hw);
rtl92c_dm_initial_gain_multi_sta(hw);
rtl92c_dm_cck_packet_detection_thresh(hw);
- dm_digtable->presta_connectstate = dm_digtable->cursta_connectstate;
+ dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
}
@@ -526,9 +520,9 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
- "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n",
+ "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
- dm_digtable->backoff_val);
+ dm_digtable->back_val);
dm_digtable->cur_igvalue += 2;
if (dm_digtable->cur_igvalue > 0x3f)
@@ -555,20 +549,18 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
return;
if (tmpentry_max_pwdb != 0) {
- rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
- tmpentry_max_pwdb;
+ rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
} else {
- rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
+ rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
}
if (tmpentry_min_pwdb != 0xff) {
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
- tmpentry_min_pwdb;
+ rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
} else {
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
+ rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
}
- h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
+ h2c_parameter[2] = (u8) (rtlpriv->dm.undec_sm_pwdb & 0xFF);
h2c_parameter[0] = 0;
rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
@@ -1160,7 +1152,7 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rate_adaptive *p_ra = &(rtlpriv->ra);
- u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
+ u32 low_rssi_thresh, high_rssi_thresh;
struct ieee80211_sta *sta = NULL;
if (is_hal_stop(rtlhal)) {
@@ -1179,35 +1171,33 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
mac->opmode == NL80211_IFTYPE_STATION) {
switch (p_ra->pre_ratr_state) {
case DM_RATR_STA_HIGH:
- high_rssithresh_for_ra = 50;
- low_rssithresh_for_ra = 20;
+ high_rssi_thresh = 50;
+ low_rssi_thresh = 20;
break;
case DM_RATR_STA_MIDDLE:
- high_rssithresh_for_ra = 55;
- low_rssithresh_for_ra = 20;
+ high_rssi_thresh = 55;
+ low_rssi_thresh = 20;
break;
case DM_RATR_STA_LOW:
- high_rssithresh_for_ra = 50;
- low_rssithresh_for_ra = 25;
+ high_rssi_thresh = 50;
+ low_rssi_thresh = 25;
break;
default:
- high_rssithresh_for_ra = 50;
- low_rssithresh_for_ra = 20;
+ high_rssi_thresh = 50;
+ low_rssi_thresh = 20;
break;
}
- if (rtlpriv->dm.undecorated_smoothed_pwdb >
- (long)high_rssithresh_for_ra)
+ if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh)
p_ra->ratr_state = DM_RATR_STA_HIGH;
- else if (rtlpriv->dm.undecorated_smoothed_pwdb >
- (long)low_rssithresh_for_ra)
+ else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh)
p_ra->ratr_state = DM_RATR_STA_MIDDLE;
else
p_ra->ratr_state = DM_RATR_STA_LOW;
if (p_ra->pre_ratr_state != p_ra->ratr_state) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n",
- rtlpriv->dm.undecorated_smoothed_pwdb);
+ rtlpriv->dm.undec_sm_pwdb);
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"RSSI_LEVEL = %d\n", p_ra->ratr_state);
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
@@ -1315,7 +1305,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
if (((mac->link_state == MAC80211_NOLINK)) &&
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
dm_pstable->rssi_val_min = 0;
RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
}
@@ -1323,20 +1313,19 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
if (mac->link_state == MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
dm_pstable->rssi_val_min =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
dm_pstable->rssi_val_min);
} else {
- dm_pstable->rssi_val_min =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
dm_pstable->rssi_val_min);
}
} else {
dm_pstable->rssi_val_min =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
@@ -1368,7 +1357,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if (!rtlpriv->dm.dynamic_txpower_enable)
return;
@@ -1379,7 +1368,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
}
if ((mac->link_state < MAC80211_LINKED) &&
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected to any\n");
@@ -1391,41 +1380,35 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
- if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
- } else if ((undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
- (undecorated_smoothed_pwdb >=
- TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+ } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+ (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
- } else if (undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_NORMAL\n");
@@ -1473,48 +1456,46 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
u8 curr_bt_rssi_state = 0x00;
if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
- undecorated_smoothed_pwdb =
- GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
+ undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
} else {
- if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)
- undecorated_smoothed_pwdb = 100;
+ if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
+ undec_sm_pwdb = 100;
else
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
}
/* Check RSSI to determine HighPower/NormalPower state for
* BT coexistence. */
- if (undecorated_smoothed_pwdb >= 67)
+ if (undec_sm_pwdb >= 67)
curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
- else if (undecorated_smoothed_pwdb < 62)
+ else if (undec_sm_pwdb < 62)
curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
/* Check RSSI to determine AMPDU setting for BT coexistence. */
- if (undecorated_smoothed_pwdb >= 40)
+ if (undec_sm_pwdb >= 40)
curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
- else if (undecorated_smoothed_pwdb <= 32)
+ else if (undec_sm_pwdb <= 32)
curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
/* Marked RSSI state. It will be used to determine BT coexistence
* setting later. */
- if (undecorated_smoothed_pwdb < 35)
+ if (undec_sm_pwdb < 35)
curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW;
else
curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
/* Set Tx Power according to BT status. */
- if (undecorated_smoothed_pwdb >= 30)
+ if (undec_sm_pwdb >= 30)
curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW;
- else if (undecorated_smoothed_pwdb < 25)
+ 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 (undecorated_smoothed_pwdb < 15)
+ if (undec_sm_pwdb < 15)
curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW;
else
curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index cdcad7d9f15e..1d5d3604e3e0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -34,9 +34,6 @@
#include "dm_common.h"
#include "phy_common.h"
-/* Define macro to shorten lines */
-#define MCS_TXPWR mcs_txpwrlevel_origoffset
-
u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -138,13 +135,13 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
BIT(8));
if (rfpi_enable)
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
BLSSIREADBACKDATA);
else
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
BLSSIREADBACKDATA);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
- rfpath, pphyreg->rflssi_readback, retvalue);
+ rfpath, pphyreg->rf_rb, retvalue);
return retvalue;
}
EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read);
@@ -290,11 +287,11 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
else
return;
- rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index] = data;
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n",
rtlphy->pwrgroup_cnt, index,
- rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index]);
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]);
if (index == 13)
rtlphy->pwrgroup_cnt++;
@@ -374,14 +371,10 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
- rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
@@ -393,47 +386,33 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
- rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
- ROFDM0_XARXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
- ROFDM0_XBRXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
- ROFDM0_XCRXIQIMBANLANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
- ROFDM0_XDRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
- rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
- ROFDM0_XATXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
- ROFDM0_XBTXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
- ROFDM0_XCTXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
- ROFDM0_XDTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
- RFPGA0_XA_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
- RFPGA0_XB_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
- RFPGA0_XC_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
- RFPGA0_XD_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
- TRANSCEIVEA_HSPI_READBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
- TRANSCEIVEB_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
}
EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition);
@@ -724,6 +703,26 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(rtl92c_phy_sw_chnl);
+static void _rtl92c_phy_sw_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ if (channel == 6 && rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20)
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+ 0x00255);
+ else{
+ u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A,
+ RF_RX_G1, RFREG_OFFSET_MASK);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+ backupRF0x1A);
+ }
+ }
+}
+
static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
u32 cmdtableidx, u32 cmdtablesz,
enum swchnlcmd_id cmdid,
@@ -837,6 +836,7 @@ bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
currentcmd->para1,
RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[rfpath]);
+ _rtl92c_phy_sw_rf_setting(hw, channel);
}
break;
default:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 2925094b2d91..3cfa1bb0f476 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -116,6 +116,9 @@
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
#define CHIP_VER_B BIT(4)
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
+#define CHIP_BONDING_92C_1T2R 0x1
+#define RF_TYPE_1T2R BIT(1)
#define CHIP_92C_BITMASK BIT(0)
#define CHIP_UNKNOWN BIT(7)
#define CHIP_92C_1T2R 0x03
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
index 27b3af880d96..74f9c083b80d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
@@ -41,7 +41,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if (!rtlpriv->dm.dynamic_txpower_enable)
return;
@@ -52,7 +52,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
}
if ((mac->link_state < MAC80211_LINKED) &&
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected to any\n");
@@ -64,41 +64,35 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
- if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
- } else if ((undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
- (undecorated_smoothed_pwdb >=
- TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+ } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+ (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
- } else if (undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_NORMAL\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 86d73b32d995..d1f34f6ffbdf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- static bool iqk_initialized; /* initialized to false */
bool rtstatus = true;
bool is92c;
int err;
@@ -921,9 +920,28 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
rtlhal->last_hmeboxnum = 0;
rtl92c_phy_mac_config(hw);
+ /* because last function modify RCR, so we update
+ * rcr var here, or TP will unstable for receive_config
+ * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+ * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+ rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+ rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
rtl92c_phy_bb_config(hw);
rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
rtl92c_phy_rf_config(hw);
+ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+ !IS_92C_SERIAL(rtlhal->version)) {
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+ } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+ }
rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
RF_CHNLBW, RFREG_OFFSET_MASK);
rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
@@ -945,11 +963,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
if (ppsc->rfpwr_state == ERFON) {
rtl92c_phy_set_rfpath_switch(hw, 1);
- if (iqk_initialized) {
+ if (rtlphy->iqk_initialized) {
rtl92c_phy_iq_calibrate(hw, true);
} else {
rtl92c_phy_iq_calibrate(hw, false);
- iqk_initialized = true;
+ rtlphy->iqk_initialized = true;
}
rtl92c_dm_check_txpower_tracking(hw);
@@ -1004,6 +1022,13 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
CHIP_VENDOR_UMC));
}
+ if (IS_92C_SERIAL(version)) {
+ value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+ version = (enum version_8192c)(version |
+ ((CHIP_BONDING_IDENTIFIER(value32)
+ == CHIP_BONDING_92C_1T2R) ?
+ RF_TYPE_1T2R : 0));
+ }
}
switch (version) {
@@ -1019,12 +1044,30 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
case VERSION_A_CHIP_88C:
versionid = "A_CHIP_88C";
break;
+ case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+ versionid = "A_CUT_92C_1T2R";
+ break;
+ case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+ versionid = "A_CUT_92C";
+ break;
+ case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+ versionid = "A_CUT_88C";
+ break;
+ case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+ versionid = "B_CUT_92C_1T2R";
+ break;
+ case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+ versionid = "B_CUT_92C";
+ break;
+ case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+ versionid = "B_CUT_88C";
+ break;
default:
versionid = "Unknown. Bug?";
break;
}
- RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
"Chip Version ID: %s\n", versionid);
switch (version & 0x3) {
@@ -1197,6 +1240,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 u1b_tmp;
u32 u4b_tmp;
@@ -1225,7 +1269,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
- rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+ if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
if (rtlpcipriv->bt_coexist.bt_coexistence) {
u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
u4b_tmp |= 0x03824800;
@@ -1254,6 +1299,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
_rtl92ce_poweroff_adapter(hw);
+
+ /* after power off we should do iqk again */
+ rtlpriv->phy.iqk_initialized = false;
}
void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -1355,9 +1403,9 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
else
tempval = EEPROM_DEFAULT_HT40_2SDIFF;
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
(tempval & 0xf);
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
((tempval & 0xf0) >> 4);
}
@@ -1381,7 +1429,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
rf_path, i,
rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]);
+ eprom_chnl_txpwr_ht40_2sdf[rf_path][i]);
for (rf_path = 0; rf_path < 2; rf_path++) {
for (i = 0; i < 14; i++) {
@@ -1396,14 +1444,14 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
if ((rtlefuse->
eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+ eprom_chnl_txpwr_ht40_2sdf[rf_path][index])
> 0) {
rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
rtlefuse->
eeprom_chnlarea_txpwr_ht40_1s[rf_path]
[index] -
rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+ eprom_chnl_txpwr_ht40_2sdf[rf_path]
[index];
} else {
rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
@@ -1912,16 +1960,16 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
ratr_bitmap &= 0x0f0ff0ff;
break;
}
+ sta_entry->ratr_index = ratr_index;
+
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
"ratr_bitmap :%x\n", ratr_bitmap);
*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
(ratr_index << 28);
rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
- "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
- ratr_index, ratr_bitmap,
- rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
- rate_mask[4]);
+ "Rate_index:%x, ratr_val:%x, %5phC\n",
+ ratr_index, ratr_bitmap, rate_mask);
rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
if (macid != 0)
@@ -2176,7 +2224,7 @@ static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw)
if (rtlpcipriv->bt_coexist.reg_bt_iso == 2)
rtlpcipriv->bt_coexist.bt_ant_isolation =
- rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation;
+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isol;
else
rtlpcipriv->bt_coexist.bt_ant_isolation =
rtlpcipriv->bt_coexist.reg_bt_iso;
@@ -2207,23 +2255,22 @@ void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
bool auto_load_fail, u8 *hwinfo)
{
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
- u8 value;
+ u8 val;
if (!auto_load_fail) {
rtlpcipriv->bt_coexist.eeprom_bt_coexist =
((hwinfo[RF_OPTION1] & 0xe0) >> 5);
- value = hwinfo[RF_OPTION4];
- rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1);
- rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1);
- rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation =
- ((value & 0x10) >> 4);
+ val = hwinfo[RF_OPTION4];
+ rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1);
+ rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1);
+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4);
rtlpcipriv->bt_coexist.eeprom_bt_radio_shared =
- ((value & 0x20) >> 5);
+ ((val & 0x20) >> 5);
} else {
rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0;
rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE;
rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2;
- rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0;
+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0;
rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index 88deae67cc14..73262ca3864b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -82,6 +82,8 @@ bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
if (is92c)
rtl_write_byte(rtlpriv, 0x14, 0x71);
+ else
+ rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
return rtstatus;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 54c7614958a8..a9c406f33d0a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -97,15 +97,12 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
}
if (rtlefuse->eeprom_regulatory == 0) {
- tmpval =
- (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
- (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
- 8);
+ tmpval = (rtlphy->mcs_offset[0][6]) +
+ (rtlphy->mcs_offset[0][7] << 8);
tx_agc[RF90_PATH_A] += tmpval;
- tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
- (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
- 24);
+ tmpval = (rtlphy->mcs_offset[0][14]) +
+ (rtlphy->mcs_offset[0][15] << 24);
tx_agc[RF90_PATH_B] += tmpval;
}
}
@@ -209,8 +206,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
case 0:
chnlgroup = 0;
- writeVal =
- rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
+ writeVal = rtlphy->mcs_offset[chnlgroup][index +
(rf ? 8 : 0)]
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
@@ -240,8 +236,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
chnlgroup++;
}
- writeVal =
- rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+ writeVal = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)] + ((index < 2) ?
powerBase0[rf] :
powerBase1[rf]);
@@ -276,8 +271,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
1]);
}
for (i = 0; i < 4; i++) {
- pwr_diff_limit[i] =
- (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+ pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset
[chnlgroup][index +
(rf ? 8 : 0)] & (0x7f << (i * 8))) >>
(i * 8));
@@ -317,8 +311,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
break;
default:
chnlgroup = 0;
- writeVal =
- rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+ writeVal = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)]
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index ea2e1bd847c8..49f663bd93ff 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
/* request fw */
if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
- !IS_92C_SERIAL(rtlhal->version)) {
+ !IS_92C_SERIAL(rtlhal->version))
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
- } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
- pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
- }
rtlpriv->max_fw_size = 0x4000;
pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
@@ -374,14 +372,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
-static const struct dev_pm_ops rtlwifi_pm_ops = {
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
- .freeze = rtl_pci_suspend,
- .thaw = rtl_pci_resume,
- .poweroff = rtl_pci_suspend,
- .restore = rtl_pci_resume,
-};
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
static struct pci_driver rtl92ce_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 390d6d4fcaa0..173424756149 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -127,11 +127,11 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_sts_cck_8192s_t *cck_buf;
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
s8 rx_pwr_all = 0, rx_pwr[4];
u8 evm, pwdb_all, rf_rx_num = 0;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
- bool in_powersavemode = false;
bool is_cck_rate;
is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
@@ -140,14 +140,14 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
pstats->is_cck = is_cck_rate;
pstats->packet_beacon = packet_beacon;
pstats->is_cck = is_cck_rate;
- pstats->rx_mimo_signalquality[0] = -1;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = -1;
+ pstats->rx_mimo_sig_qual[1] = -1;
if (is_cck_rate) {
u8 report, cck_highpwr;
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
- if (!in_powersavemode)
+ if (ppsc->rfpwr_state == ERFON)
cck_highpwr = (u8) rtl_get_bbreg(hw,
RFPGA0_XA_HSSIPARAMETER2,
BIT(9));
@@ -211,8 +211,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
}
pstats->signalquality = sq;
- pstats->rx_mimo_signalquality[0] = sq;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = sq;
+ pstats->rx_mimo_sig_qual[1] = -1;
}
} else {
rtlpriv->dm.rfpath_rxenable[0] =
@@ -251,8 +251,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
if (i == 0)
pstats->signalquality =
(u8) (evm & 0xff);
- pstats->rx_mimo_signalquality[i] =
- (u8) (evm & 0xff);
+ pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff);
}
}
}
@@ -362,36 +361,31 @@ static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
return;
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
}
if (pstats->packet_toself || pstats->packet_beacon) {
- if (undecorated_smoothed_pwdb < 0)
- undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+ if (undec_sm_pwdb < 0)
+ undec_sm_pwdb = pstats->rx_pwdb_all;
- if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
- undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
- + 1;
+ undec_sm_pwdb += 1;
} else {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
}
- rtlpriv->dm.undecorated_smoothed_pwdb =
- undecorated_smoothed_pwdb;
+ rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
_rtl92ce_update_rxsignalstatistics(hw, pstats);
}
}
@@ -438,15 +432,14 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
for (n_spatialstream = 0; n_spatialstream < 2;
n_spatialstream++) {
if (pstats->
- rx_mimo_signalquality[n_spatialstream] !=
- -1) {
+ rx_mimo_sig_qual[n_spatialstream] != -1) {
if (rtlpriv->stats.
rx_evm_percentage[n_spatialstream]
== 0) {
rtlpriv->stats.
rx_evm_percentage
[n_spatialstream] =
- pstats->rx_mimo_signalquality
+ pstats->rx_mimo_sig_qual
[n_spatialstream];
}
@@ -456,8 +449,7 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
stats.rx_evm_percentage
[n_spatialstream] *
(RX_SMOOTH_FACTOR - 1)) +
- (pstats->
- rx_mimo_signalquality
+ (pstats->rx_mimo_sig_qual
[n_spatialstream] * 1)) /
(RX_SMOOTH_FACTOR);
}
@@ -567,7 +559,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
if (GET_RX_DESC_RXHT(pdesc))
rx_status->flag |= RX_FLAG_HT;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
index 6fd39eaf361e..16a0b9e59acf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
@@ -39,7 +39,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if (!rtlpriv->dm.dynamic_txpower_enable)
return;
@@ -50,7 +50,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
}
if ((mac->link_state < MAC80211_LINKED) &&
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected to any\n");
@@ -62,41 +62,35 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
- if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
- } else if ((undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
- (undecorated_smoothed_pwdb >=
- TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+ } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+ (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
- } else if (undecorated_smoothed_pwdb <
- (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_NORMAL\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 4bbb711a36c5..b1ccff474c79 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -152,9 +152,9 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
else
tempval = EEPROM_DEFAULT_HT40_2SDIFF;
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
(tempval & 0xf);
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
((tempval & 0xf0) >> 4);
}
for (rf_path = 0; rf_path < 2; rf_path++)
@@ -177,7 +177,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
rf_path, i,
rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]);
+ eprom_chnl_txpwr_ht40_2sdf[rf_path][i]);
for (rf_path = 0; rf_path < 2; rf_path++) {
for (i = 0; i < 14; i++) {
index = _rtl92c_get_chnl_group((u8) i);
@@ -189,13 +189,13 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
if ((rtlefuse->
eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+ eprom_chnl_txpwr_ht40_2sdf[rf_path][index])
> 0) {
rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
rtlefuse->
eeprom_chnlarea_txpwr_ht40_1s[rf_path]
[index] - rtlefuse->
- eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+ eprom_chnl_txpwr_ht40_2sdf[rf_path]
[index];
} else {
rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
ratr_index << 28);
rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
- "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
- ratr_index, ratr_bitmap,
- rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
- rate_mask[4]);
+ "Rate_index:%x, ratr_val:%x, %5phC\n",
+ ratr_index, ratr_bitmap, rate_mask);
rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index 7e91c76582ec..32ff959a0251 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -46,7 +46,7 @@
#define LINK_Q ui_link_quality
#define RX_EVM rx_evm_percentage
-#define RX_SIGQ rx_mimo_signalquality
+#define RX_SIGQ rx_mimo_sig_qual
void rtl92c_read_chip_version(struct ieee80211_hw *hw)
@@ -982,32 +982,27 @@ static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb = 0;
+ long undec_sm_pwdb = 0;
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
return;
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
}
if (pstats->packet_toself || pstats->packet_beacon) {
- if (undecorated_smoothed_pwdb < 0)
- undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
- if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ if (undec_sm_pwdb < 0)
+ undec_sm_pwdb = pstats->rx_pwdb_all;
+ if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
- undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
- + 1;
+ undec_sm_pwdb += 1;
} else {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
}
- rtlpriv->dm.undecorated_smoothed_pwdb =
- undecorated_smoothed_pwdb;
+ rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
_rtl92c_update_rxsignalstatistics(hw, pstats);
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index 506b9a078ed1..953f1a0f8532 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -115,15 +115,11 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
(ppowerlevel[idx1] << 24);
}
if (rtlefuse->eeprom_regulatory == 0) {
- tmpval = (rtlphy->mcs_txpwrlevel_origoffset
- [0][6]) +
- (rtlphy->mcs_txpwrlevel_origoffset
- [0][7] << 8);
+ tmpval = (rtlphy->mcs_offset[0][6]) +
+ (rtlphy->mcs_offset[0][7] << 8);
tx_agc[RF90_PATH_A] += tmpval;
- tmpval = (rtlphy->mcs_txpwrlevel_origoffset
- [0][14]) +
- (rtlphy->mcs_txpwrlevel_origoffset
- [0][15] << 24);
+ tmpval = (rtlphy->mcs_offset[0][14]) +
+ (rtlphy->mcs_offset[0][15] << 24);
tx_agc[RF90_PATH_B] += tmpval;
}
}
@@ -215,7 +211,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
switch (rtlefuse->eeprom_regulatory) {
case 0:
chnlgroup = 0;
- writeVal = rtlphy->mcs_txpwrlevel_origoffset
+ writeVal = rtlphy->mcs_offset
[chnlgroup][index + (rf ? 8 : 0)]
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
@@ -238,8 +234,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
else
chnlgroup += 4;
}
- writeVal = rtlphy->mcs_txpwrlevel_origoffset
- [chnlgroup][index +
+ writeVal = rtlphy->mcs_offset[chnlgroup][index +
(rf ? 8 : 0)] +
((index < 2) ? powerBase0[rf] :
powerBase1[rf]);
@@ -271,8 +266,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
[channel - 1]);
}
for (i = 0; i < 4; i++) {
- pwr_diff_limit[i] =
- (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+ pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset
[chnlgroup][index + (rf ? 8 : 0)]
& (0x7f << (i * 8))) >> (i * 8));
if (rtlphy->current_chan_bw ==
@@ -306,7 +300,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
break;
default:
chnlgroup = 0;
- writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+ writeVal = rtlphy->mcs_offset[chnlgroup]
[index + (rf ? 8 : 0)] + ((index < 2) ?
powerBase0[rf] : powerBase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 6e66f04c363f..b6222eedb835 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -334,7 +334,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
rx_status->flag |= RX_FLAG_40MHZ;
if (GET_RX_DESC_RX_HT(pdesc))
rx_status->flag |= RX_FLAG_HT;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
rx_status->rate_idx = rtlwifi_rate_mapping(hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
index ed868c396c25..fd8df233ff22 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -35,7 +35,7 @@
#include "dm.h"
#include "fw.h"
-#define UNDEC_SM_PWDB entry_min_undecoratedsmoothed_pwdb
+#define UNDEC_SM_PWDB entry_min_undec_sm_pwdb
static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
0x7f8001fe, /* 0, +6.0dB */
@@ -164,18 +164,18 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
de_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
de_digtable->cur_igvalue = 0x20;
de_digtable->pre_igvalue = 0x0;
- de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
- de_digtable->presta_connectstate = DIG_STA_DISCONNECT;
- de_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+ de_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+ de_digtable->presta_cstate = DIG_STA_DISCONNECT;
+ de_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
de_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
de_digtable->rx_gain_range_max = DM_DIG_FA_UPPER;
de_digtable->rx_gain_range_min = DM_DIG_FA_LOWER;
- de_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
- de_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX;
- de_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+ de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+ de_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
+ de_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
de_digtable->pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
de_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
de_digtable->large_fa_hit = 0;
@@ -273,35 +273,34 @@ static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
/* Determine the minimum RSSI */
if ((mac->link_state < MAC80211_LINKED) &&
(rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
- de_digtable->min_undecorated_pwdb_for_dm = 0;
+ de_digtable->min_undec_pwdb_for_dm = 0;
RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
"Not connected to any\n");
}
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
- de_digtable->min_undecorated_pwdb_for_dm =
+ de_digtable->min_undec_pwdb_for_dm =
rtlpriv->dm.UNDEC_SM_PWDB;
RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
rtlpriv->dm.UNDEC_SM_PWDB);
} else {
- de_digtable->min_undecorated_pwdb_for_dm =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ de_digtable->min_undec_pwdb_for_dm =
+ rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
"STA Default Port PWDB = 0x%x\n",
- de_digtable->min_undecorated_pwdb_for_dm);
+ de_digtable->min_undec_pwdb_for_dm);
}
} else {
- de_digtable->min_undecorated_pwdb_for_dm =
- rtlpriv->dm.UNDEC_SM_PWDB;
+ de_digtable->min_undec_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB;
RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
"AP Ext Port or disconnect PWDB = 0x%x\n",
- de_digtable->min_undecorated_pwdb_for_dm);
+ de_digtable->min_undec_pwdb_for_dm);
}
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
- de_digtable->min_undecorated_pwdb_for_dm);
+ de_digtable->min_undec_pwdb_for_dm);
}
static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
@@ -310,16 +309,16 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
struct dig_t *de_digtable = &rtlpriv->dm_digtable;
unsigned long flag = 0;
- if (de_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+ if (de_digtable->cursta_cstate == DIG_STA_CONNECT) {
if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
- if (de_digtable->min_undecorated_pwdb_for_dm <= 25)
+ if (de_digtable->min_undec_pwdb_for_dm <= 25)
de_digtable->cur_cck_pd_state =
CCK_PD_STAGE_LOWRSSI;
else
de_digtable->cur_cck_pd_state =
CCK_PD_STAGE_HIGHRSSI;
} else {
- if (de_digtable->min_undecorated_pwdb_for_dm <= 20)
+ if (de_digtable->min_undec_pwdb_for_dm <= 20)
de_digtable->cur_cck_pd_state =
CCK_PD_STAGE_LOWRSSI;
else
@@ -342,7 +341,7 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state;
}
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n",
- de_digtable->cursta_connectstate == DIG_STA_CONNECT ?
+ de_digtable->cursta_cstate == DIG_STA_CONNECT ?
"DIG_STA_CONNECT " : "DIG_STA_DISCONNECT");
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n",
de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
@@ -358,9 +357,9 @@ void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
struct dig_t *de_digtable = &rtlpriv->dm_digtable;
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
- "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n",
+ "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
de_digtable->cur_igvalue, de_digtable->pre_igvalue,
- de_digtable->backoff_val);
+ de_digtable->back_val);
if (de_digtable->dig_enable_flag == false) {
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n");
de_digtable->pre_igvalue = 0x17;
@@ -382,13 +381,13 @@ static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) &&
(rtlpriv->mac80211.vendor == PEER_CISCO)) {
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n");
- if (de_digtable->last_min_undecorated_pwdb_for_dm >= 50
- && de_digtable->min_undecorated_pwdb_for_dm < 50) {
+ if (de_digtable->last_min_undec_pwdb_for_dm >= 50
+ && de_digtable->min_undec_pwdb_for_dm < 50) {
rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
"Early Mode Off\n");
- } else if (de_digtable->last_min_undecorated_pwdb_for_dm <= 55 &&
- de_digtable->min_undecorated_pwdb_for_dm > 55) {
+ } else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 &&
+ de_digtable->min_undec_pwdb_for_dm > 55) {
rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
"Early Mode On\n");
@@ -409,8 +408,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n");
if (rtlpriv->rtlhal.earlymode_enable) {
rtl92d_early_mode_enabled(rtlpriv);
- de_digtable->last_min_undecorated_pwdb_for_dm =
- de_digtable->min_undecorated_pwdb_for_dm;
+ de_digtable->last_min_undec_pwdb_for_dm =
+ de_digtable->min_undec_pwdb_for_dm;
}
if (!rtlpriv->dm.dm_initialgain_enable)
return;
@@ -428,9 +427,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n");
/* Decide the current status and if modify initial gain or not */
if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
- de_digtable->cursta_connectstate = DIG_STA_CONNECT;
+ de_digtable->cursta_cstate = DIG_STA_CONNECT;
else
- de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
+ de_digtable->cursta_cstate = DIG_STA_DISCONNECT;
/* adjust initial gain according to false alarm counter */
if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
@@ -522,7 +521,7 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if ((!rtlpriv->dm.dynamic_txpower_enable)
|| rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
@@ -539,62 +538,62 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
}
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- undecorated_smoothed_pwdb =
+ undec_sm_pwdb =
rtlpriv->dm.UNDEC_SM_PWDB;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"IBSS Client PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb =
+ rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
} else {
- undecorated_smoothed_pwdb =
+ undec_sm_pwdb =
rtlpriv->dm.UNDEC_SM_PWDB;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
if (rtlhal->current_bandtype == BAND_ON_5G) {
- if (undecorated_smoothed_pwdb >= 0x33) {
+ if (undec_sm_pwdb >= 0x33) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_LEVEL2;
RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
"5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n");
- } else if ((undecorated_smoothed_pwdb < 0x33)
- && (undecorated_smoothed_pwdb >= 0x2b)) {
+ } else if ((undec_sm_pwdb < 0x33)
+ && (undec_sm_pwdb >= 0x2b)) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
"5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n");
- } else if (undecorated_smoothed_pwdb < 0x2b) {
+ } else if (undec_sm_pwdb < 0x2b) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_NORMAL;
RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
"5G:TxHighPwrLevel_Normal\n");
}
} else {
- if (undecorated_smoothed_pwdb >=
+ if (undec_sm_pwdb >=
TX_POWER_NEAR_FIELD_THRESH_LVL2) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_LEVEL2;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
} else
- if ((undecorated_smoothed_pwdb <
+ if ((undec_sm_pwdb <
(TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
- && (undecorated_smoothed_pwdb >=
+ && (undec_sm_pwdb >=
TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
- } else if (undecorated_smoothed_pwdb <
+ } else if (undec_sm_pwdb <
(TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
rtlpriv->dm.dynamic_txhighpower_lvl =
TXHIGHPWRLEVEL_NORMAL;
@@ -620,7 +619,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
return;
/* Indicate Rx signal strength to FW. */
if (rtlpriv->dm.useramask) {
- u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb;
+ u32 temp = rtlpriv->dm.undec_sm_pwdb;
temp <<= 16;
temp |= 0x100;
@@ -629,7 +628,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
} else {
rtl_write_byte(rtlpriv, 0x4fe,
- (u8) rtlpriv->dm.undecorated_smoothed_pwdb);
+ (u8) rtlpriv->dm.undec_sm_pwdb);
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
index db0086062d05..33041bd4da81 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -298,13 +298,13 @@ static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw,
rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
BIT(8));
if (rfpi_enable)
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
BLSSIREADBACKDATA);
else
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
BLSSIREADBACKDATA);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x] = 0x%x\n",
- rfpath, pphyreg->rflssi_readback, retvalue);
+ rfpath, pphyreg->rf_rb, retvalue);
return retvalue;
}
@@ -478,14 +478,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
/* RF switch Control */
/* TR/Ant switch control */
- rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
/* AGC control 1 */
rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
@@ -500,14 +496,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
/* RX AFE control 1 */
- rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
- ROFDM0_XARXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
- ROFDM0_XBRXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
- ROFDM0_XCRXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
- ROFDM0_XDRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
/*RX AFE control 1 */
rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
@@ -516,14 +508,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
/* Tx AFE control 1 */
- rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
- ROFDM0_XATxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
- ROFDM0_XBTxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
- ROFDM0_XCTxIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
- ROFDM0_XDTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE;
/* Tx AFE control 2 */
rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
@@ -532,20 +520,14 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
/* Tranceiver LSSI Readback SI mode */
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
- RFPGA0_XA_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
- RFPGA0_XB_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
- RFPGA0_XC_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
- RFPGA0_XD_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
/* Tranceiver LSSI Readback PI mode */
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
- TRANSCEIVERA_HSPI_READBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
- TRANSCEIVERB_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK;
}
static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
@@ -702,12 +684,11 @@ static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
else
return;
- rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data;
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%ulx\n",
rtlphy->pwrgroup_cnt, index,
- rtlphy->mcs_txpwrlevel_origoffset
- [rtlphy->pwrgroup_cnt][index]);
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]);
if (index == 13)
rtlphy->pwrgroup_cnt++;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
index 3066a7fb0b57..20144e0b4142 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
@@ -106,11 +106,11 @@ void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
(ppowerlevel[idx1] << 24);
}
if (rtlefuse->eeprom_regulatory == 0) {
- tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
- (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
+ tmpval = (rtlphy->mcs_offset[0][6]) +
+ (rtlphy->mcs_offset[0][7] << 8);
tx_agc[RF90_PATH_A] += tmpval;
- tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
- (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
+ tmpval = (rtlphy->mcs_offset[0][14]) +
+ (rtlphy->mcs_offset[0][15] << 24);
tx_agc[RF90_PATH_B] += tmpval;
}
}
@@ -227,7 +227,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
switch (rtlefuse->eeprom_regulatory) {
case 0:
chnlgroup = 0;
- writeval = rtlphy->mcs_txpwrlevel_origoffset
+ writeval = rtlphy->mcs_offset
[chnlgroup][index +
(rf ? 8 : 0)] + ((index < 2) ?
powerbase0[rf] :
@@ -247,7 +247,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
chnlgroup++;
else
chnlgroup += 4;
- writeval = rtlphy->mcs_txpwrlevel_origoffset
+ writeval = rtlphy->mcs_offset
[chnlgroup][index +
(rf ? 8 : 0)] + ((index < 2) ?
powerbase0[rf] :
@@ -280,8 +280,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
[channel - 1]);
}
for (i = 0; i < 4; i++) {
- pwr_diff_limit[i] =
- (u8)((rtlphy->mcs_txpwrlevel_origoffset
+ pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset
[chnlgroup][index + (rf ? 8 : 0)] &
(0x7f << (i * 8))) >> (i * 8));
if (rtlphy->current_chan_bw ==
@@ -316,8 +315,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
break;
default:
chnlgroup = 0;
- writeval = rtlphy->mcs_txpwrlevel_origoffset
- [chnlgroup][index +
+ writeval = rtlphy->mcs_offset[chnlgroup][index +
(rf ? 8 : 0)] + ((index < 2) ?
powerbase0[rf] : powerbase1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index 480862c07f92..03c6d18b2e07 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -352,7 +352,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {
.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
-static struct pci_device_id rtl92de_pci_ids[] __devinitdata = {
+static struct pci_device_id rtl92de_pci_ids[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)},
{},
@@ -378,14 +378,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
-static const struct dev_pm_ops rtlwifi_pm_ops = {
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
- .freeze = rtl_pci_suspend,
- .thaw = rtl_pci_resume,
- .poweroff = rtl_pci_suspend,
- .restore = rtl_pci_resume,
-};
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
static struct pci_driver rtl92de_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
index 4686f340b9d6..f9f3861046c1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -132,8 +132,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
pstats->packet_toself = packet_toself;
pstats->packet_beacon = packet_beacon;
pstats->is_cck = is_cck_rate;
- pstats->rx_mimo_signalquality[0] = -1;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = -1;
+ pstats->rx_mimo_sig_qual[1] = -1;
if (is_cck_rate) {
u8 report, cck_highpwr;
@@ -212,8 +212,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
sq = ((64 - sq) * 100) / 44;
}
pstats->signalquality = sq;
- pstats->rx_mimo_signalquality[0] = sq;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = sq;
+ pstats->rx_mimo_sig_qual[1] = -1;
}
} else {
rtlpriv->dm.rfpath_rxenable[0] = true;
@@ -246,7 +246,7 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
if (i == 0)
pstats->signalquality =
(u8)(evm & 0xff);
- pstats->rx_mimo_signalquality[i] =
+ pstats->rx_mimo_sig_qual[i] =
(u8)(evm & 0xff);
}
}
@@ -345,33 +345,28 @@ static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
if (mac->opmode == NL80211_IFTYPE_ADHOC ||
mac->opmode == NL80211_IFTYPE_AP)
return;
else
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
if (pstats->packet_toself || pstats->packet_beacon) {
- if (undecorated_smoothed_pwdb < 0)
- undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
- if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ if (undec_sm_pwdb < 0)
+ undec_sm_pwdb = pstats->rx_pwdb_all;
+ if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
- undecorated_smoothed_pwdb =
- undecorated_smoothed_pwdb + 1;
+ undec_sm_pwdb = undec_sm_pwdb + 1;
} else {
- undecorated_smoothed_pwdb =
- (((undecorated_smoothed_pwdb) *
+ undec_sm_pwdb = (((undec_sm_pwdb) *
(RX_SMOOTH_FACTOR - 1)) +
(pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
}
- rtlpriv->dm.undecorated_smoothed_pwdb =
- undecorated_smoothed_pwdb;
+ rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
_rtl92de_update_rxsignalstatistics(hw, pstats);
}
}
@@ -383,15 +378,15 @@ static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
int stream;
for (stream = 0; stream < 2; stream++) {
- if (pstats->rx_mimo_signalquality[stream] != -1) {
+ if (pstats->rx_mimo_sig_qual[stream] != -1) {
if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
rtlpriv->stats.rx_evm_percentage[stream] =
- pstats->rx_mimo_signalquality[stream];
+ pstats->rx_mimo_sig_qual[stream];
}
rtlpriv->stats.rx_evm_percentage[stream] =
((rtlpriv->stats.rx_evm_percentage[stream]
* (RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_mimo_signalquality[stream] * 1)) /
+ (pstats->rx_mimo_sig_qual[stream] * 1)) /
(RX_SMOOTH_FACTOR);
}
}
@@ -514,7 +509,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
rx_status->flag |= RX_FLAG_40MHZ;
if (GET_RX_DESC_RXHT(pdesc))
rx_status->flag |= RX_FLAG_HT;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
rx_status->rate_idx = rtlwifi_rate_mapping(hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 20afec62ce05..2d255e02d795 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -522,8 +522,7 @@ enum fwcmd_iotype {
FW_CMD_IQK_ENABLE = 30,
};
-/*
- * Driver info contain PHY status
+/* Driver info contain PHY status
* and other variabel size info
* PHY Status content as below
*/
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index 465f58157101..e551fe5f9ccd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -267,13 +267,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
break;
}
- if (rtlpriv->dm.undecorated_smoothed_pwdb >
- (long)high_rssi_thresh) {
+ if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_HIGH;
- } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+ } else if (rtlpriv->dm.undec_sm_pwdb >
(long)middle_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
- } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+ } else if (rtlpriv->dm.undec_sm_pwdb >
(long)low_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
} else {
@@ -283,8 +282,7 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
if (ra->pre_ratr_state != ra->ratr_state) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
- rtlpriv->dm.undecorated_smoothed_pwdb,
- ra->ratr_state,
+ rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
ra->pre_ratr_state, ra->ratr_state);
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
@@ -316,7 +314,7 @@ static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
if (mac->link_state >= MAC80211_LINKED) {
- if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) {
+ if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) {
rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
}
@@ -424,18 +422,18 @@ static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
- if ((digtable->backoff_val - 6) <
+ if ((digtable->back_val - 6) <
digtable->backoffval_range_min)
- digtable->backoff_val = digtable->backoffval_range_min;
+ digtable->back_val = digtable->backoffval_range_min;
else
- digtable->backoff_val -= 6;
+ digtable->back_val -= 6;
} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
- if ((digtable->backoff_val + 6) >
+ if ((digtable->back_val + 6) >
digtable->backoffval_range_max)
- digtable->backoff_val =
+ digtable->back_val =
digtable->backoffval_range_max;
else
- digtable->backoff_val += 6;
+ digtable->back_val += 6;
}
}
@@ -447,28 +445,28 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
static u8 initialized, force_write;
u8 initial_gain = 0;
- if ((digtable->pre_sta_connectstate == digtable->cur_sta_connectstate) ||
- (digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) {
- if (digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) {
+ if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) ||
+ (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) {
+ if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) {
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
if (digtable->backoff_enable_flag)
rtl92s_backoff_enable_flag(hw);
else
- digtable->backoff_val = DM_DIG_BACKOFF;
+ digtable->back_val = DM_DIG_BACKOFF;
- if ((digtable->rssi_val + 10 - digtable->backoff_val) >
+ if ((digtable->rssi_val + 10 - digtable->back_val) >
digtable->rx_gain_range_max)
digtable->cur_igvalue =
digtable->rx_gain_range_max;
- else if ((digtable->rssi_val + 10 - digtable->backoff_val)
+ else if ((digtable->rssi_val + 10 - digtable->back_val)
< digtable->rx_gain_range_min)
digtable->cur_igvalue =
digtable->rx_gain_range_min;
else
- digtable->cur_igvalue = digtable->rssi_val + 10 -
- digtable->backoff_val;
+ digtable->cur_igvalue = digtable->rssi_val + 10
+ - digtable->back_val;
if (falsealm_cnt->cnt_all > 10000)
digtable->cur_igvalue =
@@ -490,7 +488,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
- digtable->backoff_val = DM_DIG_BACKOFF;
+ digtable->back_val = DM_DIG_BACKOFF;
digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0];
digtable->pre_igvalue = 0;
return;
@@ -520,7 +518,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct dig_t *digtable = &rtlpriv->dm_digtable;
+ struct dig_t *dig = &rtlpriv->dm_digtable;
if (rtlpriv->mac80211.act_scanning)
return;
@@ -528,17 +526,17 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
/* Decide the current status and if modify initial gain or not */
if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
- digtable->cur_sta_connectstate = DIG_STA_CONNECT;
+ dig->cur_sta_cstate = DIG_STA_CONNECT;
else
- digtable->cur_sta_connectstate = DIG_STA_DISCONNECT;
+ dig->cur_sta_cstate = DIG_STA_DISCONNECT;
- digtable->rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb;
+ dig->rssi_val = rtlpriv->dm.undec_sm_pwdb;
/* Change dig mode to rssi */
- if (digtable->cur_sta_connectstate != DIG_STA_DISCONNECT) {
- if (digtable->dig_twoport_algorithm ==
+ if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) {
+ if (dig->dig_twoport_algorithm ==
DIG_TWO_PORT_ALGO_FALSE_ALARM) {
- digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
+ dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
}
}
@@ -546,7 +544,7 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
_rtl92s_dm_false_alarm_counter_statistics(hw);
_rtl92s_dm_initial_gain_sta_beforeconnect(hw);
- digtable->pre_sta_connectstate = digtable->cur_sta_connectstate;
+ dig->pre_sta_cstate = dig->cur_sta_cstate;
}
static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
@@ -573,7 +571,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
long txpwr_threshold_lv1, txpwr_threshold_lv2;
/* 2T2R TP issue */
@@ -587,7 +585,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
}
if ((mac->link_state < MAC80211_LINKED) &&
- (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected to any\n");
@@ -599,25 +597,22 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
} else {
- undecorated_smoothed_pwdb =
- rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
- undecorated_smoothed_pwdb);
+ undec_sm_pwdb);
}
txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
@@ -625,12 +620,12 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
- else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2)
+ else if (undec_sm_pwdb >= txpwr_threshold_lv2)
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
- else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) &&
- (undecorated_smoothed_pwdb >= txpwr_threshold_lv1))
+ else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) &&
+ (undec_sm_pwdb >= txpwr_threshold_lv1))
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
- else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3))
+ else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3))
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
@@ -665,10 +660,10 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
digtable->dig_state = DM_STA_DIG_MAX;
digtable->dig_highpwrstate = DM_STA_DIG_MAX;
- digtable->cur_sta_connectstate = DIG_STA_DISCONNECT;
- digtable->pre_sta_connectstate = DIG_STA_DISCONNECT;
- digtable->cur_ap_connectstate = DIG_AP_DISCONNECT;
- digtable->pre_ap_connectstate = DIG_AP_DISCONNECT;
+ digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
+ digtable->pre_sta_cstate = DIG_STA_DISCONNECT;
+ digtable->cur_ap_cstate = DIG_AP_DISCONNECT;
+ digtable->pre_ap_cstate = DIG_AP_DISCONNECT;
digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
@@ -681,7 +676,7 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
/* for dig debug rssi value */
digtable->rssi_val = 50;
- digtable->backoff_val = DM_DIG_BACKOFF;
+ digtable->back_val = DM_DIG_BACKOFF;
digtable->rx_gain_range_max = DM_DIG_MAX;
digtable->rx_gain_range_min = DM_DIG_MIN;
@@ -709,7 +704,7 @@ void rtl92s_dm_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
- rtlpriv->dm.undecorated_smoothed_pwdb = -1;
+ rtlpriv->dm.undec_sm_pwdb = -1;
_rtl92s_dm_init_dynamic_txpower(hw);
rtl92s_dm_init_edca_turbo(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 4542e6952b97..28526a7361f5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1089,8 +1089,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
return err;
}
-void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr)
+void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr)
{
+ /* This is a stub. */
}
void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
@@ -1697,7 +1698,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i];
/* Read OFDM RF A & B Tx power for 2T */
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path][i]
= hwinfo[EEPROM_TXPOWERBASE + 12 +
rf_path * 3 + i];
}
@@ -1722,7 +1723,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
rf_path, i,
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf
[rf_path][i]);
for (rf_path = 0; rf_path < 2; rf_path++) {
@@ -1748,7 +1749,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
[rf_path][index];
rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
- rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf
[rf_path][index];
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
index 1886c2644a26..a8e068c76e47 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
@@ -54,7 +54,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw);
int rtl92se_set_network_type(struct ieee80211_hw *hw,
enum nl80211_iftype type);
void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
-void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr);
+void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr);
void rtl92se_set_qos(struct ieee80211_hw *hw, int aci);
void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw);
void rtl92se_set_beacon_interval(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index b917a2a3caf7..67404975e00b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -139,17 +139,17 @@ static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw,
BIT(8));
if (rfpi_enable)
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
BLSSI_READBACK_DATA);
else
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
BLSSI_READBACK_DATA);
- retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
BLSSI_READBACK_DATA);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
- rfpath, pphyreg->rflssi_readback, retvalue);
+ rfpath, pphyreg->rf_rb, retvalue);
return retvalue;
@@ -696,7 +696,7 @@ static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
else
return;
- rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data;
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
if (index == 5)
rtlphy->pwrgroup_cnt++;
}
@@ -765,14 +765,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2;
/* RF switch Control */
- rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
- RFPGA0_XAB_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
- rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
- RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
/* AGC control 1 */
rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
@@ -787,14 +783,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
/* RX AFE control 1 */
- rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
- ROFDM0_XARXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
- ROFDM0_XBRXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
- ROFDM0_XCRXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
- ROFDM0_XDRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
/* RX AFE control 1 */
rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
@@ -803,14 +795,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
/* Tx AFE control 1 */
- rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
- ROFDM0_XATXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
- ROFDM0_XBTXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
- ROFDM0_XCTXIQIMBALANCE;
- rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
- ROFDM0_XDTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
/* Tx AFE control 2 */
rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
@@ -819,20 +807,14 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
/* Tranceiver LSSI Readback */
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
- RFPGA0_XA_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
- RFPGA0_XB_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
- RFPGA0_XC_LSSIREADBACK;
- rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
- RFPGA0_XD_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
/* Tranceiver LSSI Readback PI mode */
- rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
- TRANSCEIVERA_HSPI_READBACK;
- rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
- TRANSCEIVERB_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 08c2f5625129..5061f1db3f02 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -192,8 +192,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
* defined by Realtek for large power */
chnlgroup = 0;
- writeval = rtlphy->mcs_txpwrlevel_origoffset
- [chnlgroup][index] +
+ writeval = rtlphy->mcs_offset[chnlgroup][index] +
((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
@@ -223,8 +222,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
chnlgroup++;
}
- writeval = rtlphy->mcs_txpwrlevel_origoffset
- [chnlgroup][index]
+ writeval = rtlphy->mcs_offset[chnlgroup][index]
+ ((index < 2) ?
pwrbase0 : pwrbase1);
@@ -257,8 +255,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
}
for (i = 0; i < 4; i++) {
- pwrdiff_limit[i] =
- (u8)((rtlphy->mcs_txpwrlevel_origoffset
+ pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset
[chnlgroup][index] & (0x7f << (i * 8)))
>> (i * 8));
@@ -296,7 +293,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
break;
default:
chnlgroup = 0;
- writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] +
+ writeval = rtlphy->mcs_offset[chnlgroup][index] +
((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"RTK better performance, writeval = 0x%x\n", writeval);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index ad4b4803482d..cecc377e9e61 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -50,8 +50,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
/*close ASPM for AMD defaultly */
rtlpci->const_amdpci_aspm = 0;
- /*
- * ASPM PS mode.
+ /* ASPM PS mode.
* 0 - Disable ASPM,
* 1 - Enable ASPM without Clock Req,
* 2 - Enable ASPM with Clock Req,
@@ -67,8 +66,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
/*Setting for PCI-E bridge */
rtlpci->const_hostpci_aspm_setting = 0x02;
- /*
- * In Hw/Sw Radio Off situation.
+ /* In Hw/Sw Radio Off situation.
* 0 - Default,
* 1 - From ASPM setting without low Mac Pwr,
* 2 - From ASPM setting with low Mac Pwr,
@@ -77,8 +75,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
*/
rtlpci->const_hwsw_rfoff_d3 = 2;
- /*
- * This setting works for those device with
+ /* This setting works for those device with
* backdoor ASPM setting such as EPHY setting.
* 0 - Not support ASPM,
* 1 - Support ASPM,
@@ -403,7 +400,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
-static struct pci_device_id rtl92se_pci_ids[] __devinitdata = {
+static struct pci_device_id rtl92se_pci_ids[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)},
@@ -432,14 +429,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
-static const struct dev_pm_ops rtlwifi_pm_ops = {
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
- .freeze = rtl_pci_suspend,
- .thaw = rtl_pci_resume,
- .poweroff = rtl_pci_suspend,
- .restore = rtl_pci_resume,
-};
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
static struct pci_driver rtl92se_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index e3cf4c02122a..0e9f6ebf078a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -129,8 +129,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
pstats->packet_matchbssid = packet_match_bssid;
pstats->packet_toself = packet_toself;
pstats->packet_beacon = packet_beacon;
- pstats->rx_mimo_signalquality[0] = -1;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = -1;
+ pstats->rx_mimo_sig_qual[1] = -1;
if (is_cck) {
u8 report, cck_highpwr;
@@ -216,8 +216,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
}
pstats->signalquality = sq;
- pstats->rx_mimo_signalquality[0] = sq;
- pstats->rx_mimo_signalquality[1] = -1;
+ pstats->rx_mimo_sig_qual[0] = sq;
+ pstats->rx_mimo_sig_qual[1] = -1;
}
} else {
rtlpriv->dm.rfpath_rxenable[0] =
@@ -256,8 +256,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
if (i == 0)
pstats->signalquality = (u8)(evm &
0xff);
- pstats->rx_mimo_signalquality[i] =
- (u8) (evm & 0xff);
+ pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff);
}
}
}
@@ -366,7 +365,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
return;
} else {
undec_sm_pwdb =
- rtlpriv->dm.undecorated_smoothed_pwdb;
+ rtlpriv->dm.undec_sm_pwdb;
}
if (pstats->packet_toself || pstats->packet_beacon) {
@@ -386,7 +385,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
(RX_SMOOTH_FACTOR);
}
- rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb;
+ rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
_rtl92se_update_rxsignalstatistics(hw, pstats);
}
}
@@ -398,16 +397,16 @@ static void rtl_92s_process_streams(struct ieee80211_hw *hw,
u32 stream;
for (stream = 0; stream < 2; stream++) {
- if (pstats->rx_mimo_signalquality[stream] != -1) {
+ if (pstats->rx_mimo_sig_qual[stream] != -1) {
if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
rtlpriv->stats.rx_evm_percentage[stream] =
- pstats->rx_mimo_signalquality[stream];
+ pstats->rx_mimo_sig_qual[stream];
}
rtlpriv->stats.rx_evm_percentage[stream] =
((rtlpriv->stats.rx_evm_percentage[stream] *
(RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_mimo_signalquality[stream] *
+ (pstats->rx_mimo_sig_qual[stream] *
1)) / (RX_SMOOTH_FACTOR);
}
}
@@ -554,7 +553,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
if (stats->is_ht)
rx_status->flag |= RX_FLAG_HT;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
/* hw will set stats->decrypted true, if it finds the
* frame is open data frame or mgmt frame,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
new file mode 100644
index 000000000000..4ed731f09b1f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
@@ -0,0 +1,22 @@
+obj-m := rtl8723ae.o
+
+
+rtl8723ae-objs := \
+ dm.o \
+ fw.o \
+ hal_btc.o \
+ hal_bt_coexist.o\
+ hw.o \
+ led.o \
+ phy.o \
+ pwrseq.o \
+ pwrseqcmd.o \
+ rf.o \
+ sw.o \
+ table.o \
+ trx.o \
+
+
+obj-$(CONFIG_RTL8723AE) += rtl8723ae.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
new file mode 100644
index 000000000000..417afeed36af
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ **
+ ** Copyright(c) 2009-2012 Realtek Corporation.
+ **
+ ** 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 LICENSE.
+ **
+ ** Contact Information:
+ ** wlanfae <wlanfae@realtek.com>
+ ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ ** Hsinchu 300, Taiwan.
+ ** Larry Finger <Larry.Finger@lwfinger.net>
+ **
+ *****************************************************************************
+ */
+
+#ifndef __RTL8723E_BTC_H__
+#define __RTL8723E_BTC_H__
+
+#include "../wifi.h"
+#include "hal_bt_coexist.h"
+
+struct bt_coexist_c2h_info {
+ u8 no_parse_c2h;
+ u8 has_c2h;
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/rtlwifi/rtl8723ae/def.h
new file mode 100644
index 000000000000..8c110356dff9
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/def.h
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL8723E_DEF_H__
+#define __RTL8723E_DEF_H__
+
+#define HAL_PRIME_CHNL_OFFSET_LOWER 1
+
+#define RX_MPDU_QUEUE 0
+
+#define CHIP_8723 BIT(0)
+#define NORMAL_CHIP BIT(3)
+#define RF_TYPE_1T2R BIT(4)
+#define RF_TYPE_2T2R BIT(5)
+#define CHIP_VENDOR_UMC BIT(7)
+#define B_CUT_VERSION BIT(12)
+#define C_CUT_VERSION BIT(13)
+#define D_CUT_VERSION ((BIT(12)|BIT(13)))
+#define E_CUT_VERSION BIT(14)
+#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28))
+
+enum version_8723e {
+ VERSION_TEST_UMC_CHIP_8723 = 0x0081,
+ VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089,
+ VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089,
+};
+
+/* MASK */
+#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2))
+#define CHIP_TYPE_MASK BIT(3)
+#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6))
+#define MANUFACTUER_MASK BIT(7)
+#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8))
+#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12))
+
+/* Get element */
+#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK)
+#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK)
+#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK)
+
+#define IS_81XXC(version) ((GET_CVID_IC_TYPE(version) == 0) ?\
+ true : false)
+#define IS_8723_SERIES(version) \
+ ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version) \
+ ((GET_CVID_MANUFACTUER(version)) ? true : false)
+
+#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
+#define IS_VENDOR_8723_A_CUT(version) ((IS_8723_SERIES(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) \
+ ? ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? \
+ true : false) : false)
+
+enum rf_optype {
+ RF_OP_BY_SW_3WIRE = 0,
+ RF_OP_BY_FW,
+ RF_OP_MAX
+};
+
+enum rf_power_state {
+ RF_ON,
+ RF_OFF,
+ RF_SLEEP,
+ RF_SHUT_DOWN,
+};
+
+enum power_save_mode {
+ POWER_SAVE_MODE_ACTIVE,
+ POWER_SAVE_MODE_SAVE,
+};
+
+enum power_polocy_config {
+ POWERCFG_MAX_POWER_SAVINGS,
+ POWERCFG_GLOBAL_POWER_SAVINGS,
+ POWERCFG_LOCAL_POWER_SAVINGS,
+ POWERCFG_LENOVO,
+};
+
+enum interface_select_pci {
+ INTF_SEL1_MINICARD = 0,
+ INTF_SEL0_PCIE = 1,
+ INTF_SEL2_RSV = 2,
+ INTF_SEL3_RSV = 3,
+};
+
+enum hal_fw_c2h_cmd_id {
+ HAL_FW_C2H_CMD_Read_MACREG = 0,
+ HAL_FW_C2H_CMD_Read_BBREG = 1,
+ HAL_FW_C2H_CMD_Read_RFREG = 2,
+ HAL_FW_C2H_CMD_Read_EEPROM = 3,
+ HAL_FW_C2H_CMD_Read_EFUSE = 4,
+ HAL_FW_C2H_CMD_Read_CAM = 5,
+ HAL_FW_C2H_CMD_Get_BasicRate = 6,
+ HAL_FW_C2H_CMD_Get_DataRate = 7,
+ HAL_FW_C2H_CMD_Survey = 8,
+ HAL_FW_C2H_CMD_SurveyDone = 9,
+ HAL_FW_C2H_CMD_JoinBss = 10,
+ HAL_FW_C2H_CMD_AddSTA = 11,
+ HAL_FW_C2H_CMD_DelSTA = 12,
+ HAL_FW_C2H_CMD_AtimDone = 13,
+ HAL_FW_C2H_CMD_TX_Report = 14,
+ HAL_FW_C2H_CMD_CCX_Report = 15,
+ HAL_FW_C2H_CMD_DTM_Report = 16,
+ HAL_FW_C2H_CMD_TX_Rate_Statistics = 17,
+ HAL_FW_C2H_CMD_C2HLBK = 18,
+ HAL_FW_C2H_CMD_C2HDBG = 19,
+ HAL_FW_C2H_CMD_C2HFEEDBACK = 20,
+ HAL_FW_C2H_CMD_MAX
+};
+
+enum rtl_desc_qsel {
+ QSLT_BK = 0x2,
+ QSLT_BE = 0x0,
+ QSLT_VI = 0x5,
+ QSLT_VO = 0x7,
+ QSLT_BEACON = 0x10,
+ QSLT_HIGH = 0x11,
+ QSLT_MGNT = 0x12,
+ QSLT_CMD = 0x13,
+};
+
+struct phy_sts_cck_8723e_t {
+ u8 adc_pwdb_X[4];
+ u8 sq_rpt;
+ u8 cck_agc_rpt;
+};
+
+struct h2c_cmd_8723e {
+ u8 element_id;
+ u32 cmd_len;
+ u8 *p_cmdbuffer;
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
new file mode 100644
index 000000000000..12e2a3cb0701
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
@@ -0,0 +1,920 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#include "../wifi.h"
+#include "../base.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "hal_btc.h"
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
+ 0x7f8001fe,
+ 0x788001e2,
+ 0x71c001c7,
+ 0x6b8001ae,
+ 0x65400195,
+ 0x5fc0017f,
+ 0x5a400169,
+ 0x55400155,
+ 0x50800142,
+ 0x4c000130,
+ 0x47c0011f,
+ 0x43c0010f,
+ 0x40000100,
+ 0x3c8000f2,
+ 0x390000e4,
+ 0x35c000d7,
+ 0x32c000cb,
+ 0x300000c0,
+ 0x2d4000b5,
+ 0x2ac000ab,
+ 0x288000a2,
+ 0x26000098,
+ 0x24000090,
+ 0x22000088,
+ 0x20000080,
+ 0x1e400079,
+ 0x1c800072,
+ 0x1b00006c,
+ 0x19800066,
+ 0x18000060,
+ 0x16c0005b,
+ 0x15800056,
+ 0x14400051,
+ 0x1300004c,
+ 0x12000048,
+ 0x11000044,
+ 0x10000040,
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
+};
+
+static void rtl8723ae_dm_diginit(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ dm_digtable->dig_enable_flag = true;
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+ dm_digtable->cur_igvalue = 0x20;
+ dm_digtable->pre_igvalue = 0x0;
+ dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+ dm_digtable->presta_cstate = DIG_STA_DISCONNECT;
+ dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
+ dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
+ dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
+ dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+ dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+ dm_digtable->rx_gain_range_max = DM_DIG_MAX;
+ dm_digtable->rx_gain_range_min = DM_DIG_MIN;
+ dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+ 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;
+}
+
+static u8 rtl_init_gain_min_pwdb(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+ long rssi_val_min = 0;
+
+ if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
+ (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
+ if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
+ rssi_val_min =
+ (rtlpriv->dm.entry_min_undec_sm_pwdb >
+ rtlpriv->dm.undec_sm_pwdb) ?
+ rtlpriv->dm.undec_sm_pwdb :
+ rtlpriv->dm.entry_min_undec_sm_pwdb;
+ else
+ rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+ } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
+ dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
+ rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+ } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+ rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
+ }
+
+ return (u8) rssi_val_min;
+}
+
+static void rtl8723ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+ u32 ret_value;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
+ falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
+ falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+ falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+
+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
+ falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+ 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;
+
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
+ falsealm_cnt->cnt_cck_fail = ret_value;
+
+ ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
+ falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+ falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
+ falsealm_cnt->cnt_rate_illegal +
+ falsealm_cnt->cnt_crc8_fail +
+ falsealm_cnt->cnt_mcs_fail +
+ falsealm_cnt->cnt_cck_fail);
+
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+ rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+ "cnt_parity_fail = %d, cnt_rate_illegal = %d, "
+ "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
+ falsealm_cnt->cnt_parity_fail,
+ falsealm_cnt->cnt_rate_illegal,
+ falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+ "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
+ falsealm_cnt->cnt_ofdm_fail,
+ falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+ u8 value_igi = dm_digtable->cur_igvalue;
+
+ if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
+ value_igi--;
+ else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
+ value_igi += 0;
+ else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
+ value_igi++;
+ else
+ value_igi += 2;
+
+ value_igi = clamp(value_igi, (u8)DM_DIG_FA_LOWER, (u8)DM_DIG_FA_UPPER);
+ if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+ value_igi = 0x32;
+
+ dm_digtable->cur_igvalue = value_igi;
+ rtl8723ae_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dgtbl = &rtlpriv->dm_digtable;
+
+ if (rtlpriv->falsealm_cnt.cnt_all > dgtbl->fa_highthresh) {
+ if ((dgtbl->back_val - 2) < dgtbl->back_range_min)
+ dgtbl->back_val = dgtbl->back_range_min;
+ else
+ dgtbl->back_val -= 2;
+ } else if (rtlpriv->falsealm_cnt.cnt_all < dgtbl->fa_lowthresh) {
+ if ((dgtbl->back_val + 2) > dgtbl->back_range_max)
+ dgtbl->back_val = dgtbl->back_range_max;
+ else
+ dgtbl->back_val += 2;
+ }
+
+ if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) >
+ dgtbl->rx_gain_range_max)
+ dgtbl->cur_igvalue = dgtbl->rx_gain_range_max;
+ else if ((dgtbl->rssi_val_min + 10 -
+ dgtbl->back_val) < dgtbl->rx_gain_range_min)
+ dgtbl->cur_igvalue = dgtbl->rx_gain_range_min;
+ else
+ dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val;
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+ "rssi_val_min = %x back_val %x\n",
+ dgtbl->rssi_val_min, dgtbl->back_val);
+
+ rtl8723ae_dm_write_dig(hw);
+}
+
+static void rtl8723ae_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+ long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
+ bool multi_sta = false;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC)
+ multi_sta = true;
+
+ if ((!multi_sta) ||
+ (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) {
+ rtlpriv->initialized = false;
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+ return;
+ } else if (!rtlpriv->initialized) {
+ rtlpriv->initialized = true;
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+ dm_digtable->cur_igvalue = 0x20;
+ rtl8723ae_dm_write_dig(hw);
+ }
+
+ if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+ if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
+ (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
+
+ if (dm_digtable->dig_ext_port_stage ==
+ DIG_EXT_PORT_STAGE_2) {
+ dm_digtable->cur_igvalue = 0x20;
+ rtl8723ae_dm_write_dig(hw);
+ }
+
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
+ } else if (rssi_strength > dm_digtable->rssi_highthresh) {
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
+ rtl92c_dm_ctrl_initgain_by_fa(hw);
+ }
+ } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+ dm_digtable->cur_igvalue = 0x20;
+ rtl8723ae_dm_write_dig(hw);
+ }
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+ "curmultista_cstate = %x dig_ext_port_stage %x\n",
+ dm_digtable->curmultista_cstate,
+ dm_digtable->dig_ext_port_stage);
+}
+
+static void rtl8723ae_dm_initial_gain_sta(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ 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) {
+
+ if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
+ dm_digtable->rssi_val_min = rtl_init_gain_min_pwdb(hw);
+ rtl92c_dm_ctrl_initgain_by_rssi(hw);
+ }
+ } else {
+ dm_digtable->rssi_val_min = 0;
+ dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+ dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+ dm_digtable->cur_igvalue = 0x20;
+ dm_digtable->pre_igvalue = 0;
+ rtl8723ae_dm_write_dig(hw);
+ }
+}
+static void rtl8723ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
+ dm_digtable->rssi_val_min = rtl_init_gain_min_pwdb(hw);
+
+ if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+ if (dm_digtable->rssi_val_min <= 25)
+ dm_digtable->cur_cck_pd_state =
+ CCK_PD_STAGE_LowRssi;
+ else
+ dm_digtable->cur_cck_pd_state =
+ CCK_PD_STAGE_HighRssi;
+ } else {
+ if (dm_digtable->rssi_val_min <= 20)
+ dm_digtable->cur_cck_pd_state =
+ CCK_PD_STAGE_LowRssi;
+ else
+ dm_digtable->cur_cck_pd_state =
+ CCK_PD_STAGE_HighRssi;
+ }
+ } else {
+ dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
+ }
+
+ 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);
+
+ } else {
+ rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
+ rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
+
+ }
+ 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);
+
+}
+
+static void rtl8723ae_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
+{
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ if (mac->act_scanning == true)
+ return;
+
+ if (mac->link_state >= MAC80211_LINKED)
+ dm_digtable->cursta_cstate = DIG_STA_CONNECT;
+ else
+ dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+
+ rtl8723ae_dm_initial_gain_sta(hw);
+ rtl8723ae_dm_initial_gain_multi_sta(hw);
+ rtl8723ae_dm_cck_packet_detection_thresh(hw);
+
+ dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
+
+}
+
+static void rtl8723ae_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)
+ return;
+
+ rtl8723ae_dm_ctrl_initgain_by_twoport(hw);
+}
+
+static void rtl8723ae_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dynamic_txpower_enable = false;
+
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl8723ae_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ long undec_sm_pwdb;
+
+ if (!rtlpriv->dm.dynamic_txpower_enable)
+ return;
+
+ if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+
+ if ((mac->link_state < MAC80211_LINKED) &&
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+ "Not connected\n");
+
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+
+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+ return;
+ }
+
+ if (mac->link_state >= MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "AP Client PWDB = 0x%lx\n",
+ undec_sm_pwdb);
+ } else {
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "STA Default Port PWDB = 0x%lx\n",
+ undec_sm_pwdb);
+ }
+ } else {
+ undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "AP Ext Port PWDB = 0x%lx\n",
+ undec_sm_pwdb);
+ }
+
+ if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
+ } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+ (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
+ } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "TXHIGHPWRLEVEL_NORMAL\n");
+ }
+
+ if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "PHY_SetTxPowerLevel8192S() Channel = %d\n",
+ rtlphy->current_channel);
+ rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+ }
+
+ rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+void rtl8723ae_dm_write_dig(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+ "cur_igvalue = 0x%x, "
+ "pre_igvalue = 0x%x, back_val = %d\n",
+ dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
+ dm_digtable->back_val);
+
+ if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+ dm_digtable->cur_igvalue);
+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+ dm_digtable->cur_igvalue);
+
+ dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
+ }
+}
+
+static void rtl8723ae_dm_pwdmonitor(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.current_turbo_edca = false;
+ rtlpriv->dm.is_any_nonbepkts = false;
+ rtlpriv->dm.is_cur_rdlstate = false;
+}
+
+static void rtl8723ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+ u64 cur_txok_cnt = 0;
+ u64 cur_rxok_cnt = 0;
+ u32 edca_be_ul = 0x5ea42b;
+ u32 edca_be_dl = 0x5ea42b;
+ bool bt_change_edca = false;
+
+ if ((mac->last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
+ (mac->last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
+ rtlpriv->dm.current_turbo_edca = false;
+ mac->last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+ mac->last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
+ }
+
+ if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
+ edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+ bt_change_edca = true;
+ }
+
+ if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
+ edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
+ bt_change_edca = true;
+ }
+
+ if (mac->link_state != MAC80211_LINKED) {
+ rtlpriv->dm.current_turbo_edca = false;
+ return;
+ }
+
+ if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
+ if (!(edca_be_ul & 0xffff0000))
+ edca_be_ul |= 0x005e0000;
+
+ if (!(edca_be_dl & 0xffff0000))
+ edca_be_dl |= 0x005e0000;
+ }
+
+ if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
+ (!rtlpriv->dm.disable_framebursting))) {
+
+ cur_txok_cnt = rtlpriv->stats.txbytesunicast -
+ mac->last_txok_cnt;
+ cur_rxok_cnt = rtlpriv->stats.rxbytesunicast -
+ mac->last_rxok_cnt;
+
+ if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+ if (!rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv,
+ REG_EDCA_BE_PARAM,
+ edca_be_dl);
+ rtlpriv->dm.is_cur_rdlstate = true;
+ }
+ } else {
+ if (rtlpriv->dm.is_cur_rdlstate ||
+ !rtlpriv->dm.current_turbo_edca) {
+ rtl_write_dword(rtlpriv,
+ REG_EDCA_BE_PARAM,
+ edca_be_ul);
+ rtlpriv->dm.is_cur_rdlstate = false;
+ }
+ }
+ rtlpriv->dm.current_turbo_edca = true;
+ } else {
+ if (rtlpriv->dm.current_turbo_edca) {
+ u8 tmp = AC0_BE;
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AC_PARAM,
+ (u8 *) (&tmp));
+ rtlpriv->dm.current_turbo_edca = false;
+ }
+ }
+
+ rtlpriv->dm.is_any_nonbepkts = false;
+ mac->last_txok_cnt = rtlpriv->stats.txbytesunicast;
+ mac->last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl8723ae_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.txpower_tracking = true;
+ rtlpriv->dm.txpower_trackinginit = false;
+
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ "pMgntInfo->txpower_tracking = %d\n",
+ rtlpriv->dm.txpower_tracking);
+}
+
+void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rate_adaptive *p_ra = &(rtlpriv->ra);
+
+ p_ra->ratr_state = DM_RATR_STA_INIT;
+ p_ra->pre_ratr_state = DM_RATR_STA_INIT;
+
+ if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+ rtlpriv->dm.useramask = true;
+ else
+ rtlpriv->dm.useramask = false;
+}
+
+static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm_pstable.pre_ccastate = CCA_MAX;
+ rtlpriv->dm_pstable.cur_ccasate = CCA_MAX;
+ rtlpriv->dm_pstable.pre_rfstate = RF_MAX;
+ rtlpriv->dm_pstable.cur_rfstate = RF_MAX;
+ rtlpriv->dm_pstable.rssi_val_min = 0;
+}
+
+void rtl8723ae_dm_rf_saving(struct ieee80211_hw *hw, u8 force_in_normal)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
+
+ if (!rtlpriv->reg_init) {
+ rtlpriv->reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ MASKDWORD) & 0x1CC000) >> 14;
+
+ rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
+ MASKDWORD) & BIT(3)) >> 3;
+
+ rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+ MASKDWORD) & 0xFF000000) >> 24;
+
+ rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
+ 0xF000) >> 12;
+
+ rtlpriv->reg_init = true;
+ }
+
+ if (!force_in_normal) {
+ if (dm_pstable->rssi_val_min != 0) {
+ if (dm_pstable->pre_rfstate == RF_NORMAL) {
+ if (dm_pstable->rssi_val_min >= 30)
+ dm_pstable->cur_rfstate = RF_SAVE;
+ else
+ dm_pstable->cur_rfstate = RF_NORMAL;
+ } else {
+ if (dm_pstable->rssi_val_min <= 25)
+ dm_pstable->cur_rfstate = RF_NORMAL;
+ else
+ dm_pstable->cur_rfstate = RF_SAVE;
+ }
+ } else {
+ dm_pstable->cur_rfstate = RF_MAX;
+ }
+ } else {
+ dm_pstable->cur_rfstate = RF_NORMAL;
+ }
+
+ if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
+ if (dm_pstable->cur_rfstate == RF_SAVE) {
+
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ BIT(5), 0x1);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ 0x1C0000, 0x2);
+ rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
+ rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+ 0xFF000000, 0x63);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ 0xC000, 0x2);
+ rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
+ rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+ rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
+ } else {
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ 0x1CC000, rtlpriv->reg_874);
+ rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
+ rtlpriv->reg_c70);
+ rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
+ rtlpriv->reg_85c);
+ rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
+ rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+ rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+ BIT(5), 0x0);
+ }
+
+ dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
+ }
+}
+
+static void rtl8723ae_dm_dynamic_bpowersaving(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
+
+ if (((mac->link_state == MAC80211_NOLINK)) &&
+ (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
+ dm_pstable->rssi_val_min = 0;
+ RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+ "Not connected to any\n");
+ }
+
+ if (mac->link_state == MAC80211_LINKED) {
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ dm_pstable->rssi_val_min =
+ rtlpriv->dm.entry_min_undec_sm_pwdb;
+ RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+ "AP Client PWDB = 0x%lx\n",
+ dm_pstable->rssi_val_min);
+ } else {
+ dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+ RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+ "STA Default Port PWDB = 0x%lx\n",
+ dm_pstable->rssi_val_min);
+ }
+ } else {
+ dm_pstable->rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+ RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+ "AP Ext Port PWDB = 0x%lx\n",
+ dm_pstable->rssi_val_min);
+ }
+
+ rtl8723ae_dm_rf_saving(hw, false);
+}
+
+void rtl8723ae_dm_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+ rtl8723ae_dm_diginit(hw);
+ rtl8723ae_dm_init_dynamic_txpower(hw);
+ rtl8723ae_dm_init_edca_turbo(hw);
+ rtl8723ae_dm_init_rate_adaptive_mask(hw);
+ rtl8723ae_dm_initialize_txpower_tracking(hw);
+ rtl8723ae_dm_init_dynamic_bpowersaving(hw);
+}
+
+void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ bool fw_current_inpsmode = false;
+ bool fw_ps_awake = true;
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+ (u8 *) (&fw_current_inpsmode));
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+ (u8 *) (&fw_ps_awake));
+
+ if ((ppsc->rfpwr_state == ERFON) &&
+ ((!fw_current_inpsmode) && fw_ps_awake) &&
+ (!ppsc->rfchange_inprogress)) {
+ rtl8723ae_dm_pwdmonitor(hw);
+ rtl8723ae_dm_dig(hw);
+ rtl8723ae_dm_false_alarm_counter_statistics(hw);
+ rtl8723ae_dm_dynamic_bpowersaving(hw);
+ rtl8723ae_dm_dynamic_txpower(hw);
+ /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
+ rtl8723ae_dm_bt_coexist(hw);
+ rtl8723ae_dm_check_edca_turbo(hw);
+ }
+ if (rtlpcipriv->bt_coexist.init_set)
+ rtl_write_byte(rtlpriv, 0x76e, 0xc);
+}
+
+static void rtl8723ae_dm_init_bt_coexist(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ rtlpcipriv->bt_coexist.bt_rfreg_origin_1e
+ = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff);
+ rtlpcipriv->bt_coexist.bt_rfreg_origin_1f
+ = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0);
+
+ rtlpcipriv->bt_coexist.cstate = 0;
+ rtlpcipriv->bt_coexist.previous_state = 0;
+ rtlpcipriv->bt_coexist.cstate_h = 0;
+ rtlpcipriv->bt_coexist.previous_state_h = 0;
+ rtlpcipriv->bt_coexist.lps_counter = 0;
+
+ /* Enable counter statistics */
+ rtl_write_byte(rtlpriv, 0x76e, 0x4);
+ rtl_write_byte(rtlpriv, 0x778, 0x3);
+ rtl_write_byte(rtlpriv, 0x40, 0x20);
+
+ rtlpcipriv->bt_coexist.init_set = true;
+}
+
+void rtl8723ae_dm_bt_coexist(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 tmp_byte = 0;
+ if (!rtlpcipriv->bt_coexist.bt_coexistence) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[DM]{BT], BT not exist!!\n");
+ return;
+ }
+
+ if (!rtlpcipriv->bt_coexist.init_set) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[DM][BT], rtl8723ae_dm_bt_coexist()\n");
+
+ rtl8723ae_dm_init_bt_coexist(hw);
+ }
+
+ tmp_byte = rtl_read_byte(rtlpriv, 0x40);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[DM][BT], 0x40 is 0x%x", tmp_byte);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[DM][BT], bt_dm_coexist start");
+ rtl8723ae_dm_bt_coexist_8723(hw);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
new file mode 100644
index 000000000000..39d246196247
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
@@ -0,0 +1,149 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL8723E_DM_H__
+#define __RTL8723E_DM_H__
+
+#define HAL_DM_HIPWR_DISABLE BIT(1)
+
+#define OFDM_TABLE_SIZE 37
+#define CCK_TABLE_SIZE 33
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DM_FALSEALARM_THRESH_LOW 400
+#define DM_FALSEALARM_THRESH_HIGH 1000
+
+#define DM_DIG_MAX 0x3e
+#define DM_DIG_MIN 0x1e
+
+#define DM_DIG_FA_UPPER 0x32
+#define DM_DIG_FA_LOWER 0x20
+#define DM_DIG_FA_TH0 0x20
+#define DM_DIG_FA_TH1 0x100
+#define DM_DIG_FA_TH2 0x200
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+#define DM_DIG_BACKOFF_DEFAULT 10
+
+#define DM_RATR_STA_INIT 0
+
+#define TXHIGHPWRLEVEL_NORMAL 0
+#define TXHIGHPWRLEVEL_LEVEL1 1
+#define TXHIGHPWRLEVEL_LEVEL2 2
+#define TXHIGHPWRLEVEL_BT1 3
+#define TXHIGHPWRLEVEL_BT2 4
+
+#define DM_TYPE_BYDRIVER 1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+
+struct swat_t {
+ u8 failure_cnt;
+ u8 try_flag;
+ u8 stop_trying;
+ long pre_rssi;
+ long trying_threshold;
+ u8 cur_antenna;
+ u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+ DIG_TYPE_THRESH_HIGH = 0,
+ DIG_TYPE_THRESH_LOW = 1,
+ DIG_TYPE_BACKOFF = 2,
+ DIG_TYPE_RX_GAIN_MIN = 3,
+ DIG_TYPE_RX_GAIN_MAX = 4,
+ DIG_TYPE_ENABLE = 5,
+ DIG_TYPE_DISABLE = 6,
+ DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+ CCK_PD_STAGE_LowRssi = 0,
+ CCK_PD_STAGE_HighRssi = 1,
+ CCK_FA_STAGE_Low = 2,
+ CCK_FA_STAGE_High = 3,
+ CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca_e {
+ CCA_1R = 0,
+ CCA_2R = 1,
+ CCA_MAX = 2,
+};
+
+enum dm_rf_e {
+ RF_SAVE = 0,
+ RF_NORMAL = 1,
+ RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch_e {
+ ANS_ANTENNA_B = 1,
+ ANS_ANTENNA_A = 2,
+ ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg_e {
+ DIG_EXT_PORT_STAGE_0 = 0,
+ DIG_EXT_PORT_STAGE_1 = 1,
+ DIG_EXT_PORT_STAGE_2 = 2,
+ DIG_EXT_PORT_STAGE_3 = 3,
+ DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect_e {
+ DIG_STA_DISCONNECT = 0,
+ DIG_STA_CONNECT = 1,
+ DIG_STA_BEFORE_CONNECT = 2,
+ DIG_MULTISTA_DISCONNECT = 3,
+ DIG_MULTISTA_CONNECT = 4,
+ DIG_CONNECT_MAX
+};
+
+#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \
+ ((((struct rtl_priv *)(_priv))->mac80211.opmode == \
+ NL80211_IFTYPE_ADHOC) ? \
+ (((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) \
+ : (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb))
+
+void rtl8723ae_dm_init(struct ieee80211_hw *hw);
+void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw);
+void rtl8723ae_dm_write_dig(struct ieee80211_hw *hw);
+void rtl8723ae_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+void rtl8723ae_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl8723ae_dm_bt_coexist(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
new file mode 100644
index 000000000000..f55b1767ef57
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
@@ -0,0 +1,745 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+
+static void _rtl8723ae_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp;
+ if (enable) {
+ tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
+
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+ } else {
+ tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+
+ rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
+ }
+}
+
+static void _rtl8723ae_fw_block_write(struct ieee80211_hw *hw,
+ const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 blockSize = sizeof(u32);
+ u8 *bufferPtr = (u8 *) buffer;
+ u32 *pu4BytePtr = (u32 *) buffer;
+ u32 i, offset, blockCount, remainSize;
+
+ blockCount = size / blockSize;
+ remainSize = size % blockSize;
+
+ for (i = 0; i < blockCount; i++) {
+ offset = i * blockSize;
+ rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
+ *(pu4BytePtr + i));
+ }
+
+ if (remainSize) {
+ offset = blockCount * blockSize;
+ bufferPtr += offset;
+ for (i = 0; i < remainSize; i++) {
+ rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
+ offset + i), *(bufferPtr + i));
+ }
+ }
+}
+
+static void _rtl8723ae_fw_page_write(struct ieee80211_hw *hw,
+ u32 page, const u8 *buffer, u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value8;
+ u8 u8page = (u8) (page & 0x07);
+
+ value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+
+ rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+ _rtl8723ae_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl8723ae_write_fw(struct ieee80211_hw *hw,
+ enum version_8723e version, u8 *buffer,
+ u32 size)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 *bufferPtr = (u8 *) buffer;
+ u32 page_nums, remain_size;
+ u32 page, offset;
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
+
+ page_nums = size / FW_8192C_PAGE_SIZE;
+ remain_size = size % FW_8192C_PAGE_SIZE;
+
+ if (page_nums > 6) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Page numbers should not be greater then 6\n");
+ }
+
+ for (page = 0; page < page_nums; page++) {
+ offset = page * FW_8192C_PAGE_SIZE;
+ _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
+ FW_8192C_PAGE_SIZE);
+ }
+
+ if (remain_size) {
+ offset = page_nums * FW_8192C_PAGE_SIZE;
+ page = page_nums;
+ _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
+ remain_size);
+ }
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
+}
+
+static int _rtl8723ae_fw_free_to_go(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int err = -EIO;
+ u32 counter = 0;
+ u32 value32;
+
+ do {
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
+ (!(value32 & FWDL_ChkSum_rpt)));
+
+ if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+ value32);
+ goto exit;
+ }
+
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
+
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ value32 &= ~WINTINI_RDY;
+ rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+
+ counter = 0;
+
+ do {
+ value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+ if (value32 & WINTINI_RDY) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
+ value32);
+ err = 0;
+ goto exit;
+ }
+
+ mdelay(FW_8192C_POLLING_DELAY);
+
+ } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
+
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
+
+exit:
+ return err;
+}
+
+int rtl8723ae_download_fw(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl8723ae_firmware_header *pfwheader;
+ u8 *pfwdata;
+ u32 fwsize;
+ int err;
+ enum version_8723e version = rtlhal->version;
+
+ if (!rtlhal->pfirmware)
+ return 1;
+
+ pfwheader = (struct rtl8723ae_firmware_header *)rtlhal->pfirmware;
+ pfwdata = (u8 *) rtlhal->pfirmware;
+ fwsize = rtlhal->fwsize;
+
+ if (IS_FW_HEADER_EXIST(pfwheader)) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ "Firmware Version(%d), Signature(%#x),Size(%d)\n",
+ pfwheader->version, pfwheader->signature,
+ (int)sizeof(struct rtl8723ae_firmware_header));
+
+ pfwdata = pfwdata + sizeof(struct rtl8723ae_firmware_header);
+ fwsize = fwsize - sizeof(struct rtl8723ae_firmware_header);
+ }
+
+ if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
+ rtl8723ae_firmware_selfreset(hw);
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+ }
+ _rtl8723ae_enable_fw_download(hw, true);
+ _rtl8723ae_write_fw(hw, version, pfwdata, fwsize);
+ _rtl8723ae_enable_fw_download(hw, false);
+
+ err = _rtl8723ae_fw_free_to_go(hw);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Firmware is not ready to run!\n");
+ } else {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "Firmware is ready to run!\n");
+ }
+ return 0;
+}
+
+static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 val_hmetfr, val_mcutst_1;
+ bool result = false;
+
+ val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+ val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
+
+ if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
+ result = true;
+ return result;
+}
+
+static void _rtl8723ae_fill_h2c_command(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len,
+ u8 *p_cmdbuffer)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 boxnum;
+ u16 box_reg = 0, box_extreg = 0;
+ u8 u1tmp;
+ bool isfw_rd = false;
+ bool bwrite_sucess = false;
+ u8 wait_h2c_limmit = 100;
+ u8 wait_writeh2c_limmit = 100;
+ u8 boxcontent[4], boxextcontent[2];
+ u32 h2c_waitcounter = 0;
+ unsigned long flag;
+ u8 idx;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
+
+ while (true) {
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ if (rtlhal->h2c_setinprogress) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "H2C set in progress! Wait to set..element_id(%d).\n",
+ element_id);
+
+ while (rtlhal->h2c_setinprogress) {
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+ flag);
+ h2c_waitcounter++;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "Wait 100 us (%d times)...\n",
+ h2c_waitcounter);
+ udelay(100);
+
+ if (h2c_waitcounter > 1000)
+ return;
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+ flag);
+ }
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ } else {
+ rtlhal->h2c_setinprogress = true;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+ break;
+ }
+ }
+
+ while (!bwrite_sucess) {
+ wait_writeh2c_limmit--;
+ if (wait_writeh2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Write H2C fail because no trigger "
+ "for FW INT!\n");
+ break;
+ }
+
+ boxnum = rtlhal->last_hmeboxnum;
+ switch (boxnum) {
+ case 0:
+ box_reg = REG_HMEBOX_0;
+ box_extreg = REG_HMEBOX_EXT_0;
+ break;
+ case 1:
+ box_reg = REG_HMEBOX_1;
+ box_extreg = REG_HMEBOX_EXT_1;
+ break;
+ case 2:
+ box_reg = REG_HMEBOX_2;
+ box_extreg = REG_HMEBOX_EXT_2;
+ break;
+ case 3:
+ box_reg = REG_HMEBOX_3;
+ box_extreg = REG_HMEBOX_EXT_3;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ break;
+ }
+
+ isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
+ while (!isfw_rd) {
+
+ wait_h2c_limmit--;
+ if (wait_h2c_limmit == 0) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "Wating too long for FW read clear HMEBox(%d)!\n",
+ boxnum);
+ break;
+ }
+
+ udelay(10);
+
+ isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
+ u1tmp = rtl_read_byte(rtlpriv, 0x1BF);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "Wating for FW read clear HMEBox(%d)!!! "
+ "0x1BF = %2x\n", boxnum, u1tmp);
+ }
+
+ if (!isfw_rd) {
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "Write H2C register BOX[%d] fail!!!!! "
+ "Fw do not read.\n", boxnum);
+ break;
+ }
+
+ memset(boxcontent, 0, sizeof(boxcontent));
+ memset(boxextcontent, 0, sizeof(boxextcontent));
+ boxcontent[0] = element_id;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "Write element_id box_reg(%4x) = %2x\n",
+ box_reg, element_id);
+
+ switch (cmd_len) {
+ case 1:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy((u8 *) (boxcontent) + 1,
+ p_cmdbuffer, 1);
+
+ for (idx = 0; idx < 4; idx++) {
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ }
+ break;
+ case 2:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy((u8 *) (boxcontent) + 1,
+ p_cmdbuffer, 2);
+
+ for (idx = 0; idx < 4; idx++) {
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ }
+ break;
+ case 3:
+ boxcontent[0] &= ~(BIT(7));
+ memcpy((u8 *) (boxcontent) + 1,
+ p_cmdbuffer, 3);
+
+ for (idx = 0; idx < 4; idx++) {
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ }
+ break;
+ case 4:
+ boxcontent[0] |= (BIT(7));
+ memcpy((u8 *) (boxextcontent),
+ p_cmdbuffer, 2);
+ memcpy((u8 *) (boxcontent) + 1,
+ p_cmdbuffer + 2, 2);
+
+ for (idx = 0; idx < 2; idx++) {
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ }
+
+ for (idx = 0; idx < 4; idx++) {
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ }
+ break;
+ case 5:
+ boxcontent[0] |= (BIT(7));
+ memcpy((u8 *) (boxextcontent),
+ p_cmdbuffer, 2);
+ memcpy((u8 *) (boxcontent) + 1,
+ p_cmdbuffer + 2, 3);
+
+ for (idx = 0; idx < 2; idx++) {
+ rtl_write_byte(rtlpriv, box_extreg + idx,
+ boxextcontent[idx]);
+ }
+
+ for (idx = 0; idx < 4; idx++) {
+ rtl_write_byte(rtlpriv, box_reg + idx,
+ boxcontent[idx]);
+ }
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+
+ bwrite_sucess = true;
+
+ rtlhal->last_hmeboxnum = boxnum + 1;
+ if (rtlhal->last_hmeboxnum == 4)
+ rtlhal->last_hmeboxnum = 0;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+ "pHalData->last_hmeboxnum = %d\n",
+ rtlhal->last_hmeboxnum);
+ }
+
+ spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+ rtlhal->h2c_setinprogress = false;
+ spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
+}
+
+void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
+ u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+ if (rtlhal->fw_ready == false) {
+ RT_ASSERT(false,
+ "return H2C cmd because of Fw download fail!!!\n");
+ return;
+ }
+
+ _rtl8723ae_fill_h2c_command(hw, element_id, cmd_len, p_cmdbuffer);
+ return;
+}
+
+void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
+{
+ u8 u1tmp;
+ u8 delay = 100;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+ u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+
+ while (u1tmp & BIT(2)) {
+ delay--;
+ if (delay == 0)
+ break;
+ udelay(50);
+ u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ }
+ if (delay == 0) {
+ u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1tmp&(~BIT(2)));
+ }
+}
+
+void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 u1_h2c_set_pwrmode[3] = { 0 };
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+
+ SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+ SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+ SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+ ppsc->reg_max_lps_awakeintvl);
+
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+ u1_h2c_set_pwrmode, 3);
+ rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+
+}
+
+static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl8192_tx_ring *ring;
+ struct rtl_tx_desc *pdesc;
+ u8 own;
+ unsigned long flags;
+ struct sk_buff *pskb = NULL;
+
+ ring = &rtlpci->tx_ring[BEACON_QUEUE];
+
+ pskb = __skb_dequeue(&ring->queue);
+ if (pskb)
+ kfree_skb(pskb);
+
+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+
+ pdesc = &ring->desc[0];
+ own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+
+ rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+
+ __skb_queue_tail(&ring->queue, skb);
+
+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+
+ rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+
+ return true;
+}
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+ /* page 0 beacon */
+ 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 1 beacon */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 2 ps-poll */
+ 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 3 null */
+ 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 4 probe_resp */
+ 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+ 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+ 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+ 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+ 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+ 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+ 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+ 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+ 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+ 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+ 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* page 5 probe_resp */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct sk_buff *skb = NULL;
+
+ u32 totalpacketlen;
+ bool rtstatus;
+ u8 u1RsvdPageLoc[3] = { 0 };
+ bool dlok = false;
+
+ u8 *beacon;
+ u8 *p_pspoll;
+ u8 *nullfunc;
+ u8 *p_probersp;
+ /*---------------------------------------------------------
+ (1) beacon
+ ---------------------------------------------------------
+ */
+ beacon = &reserved_page_packet[BEACON_PG * 128];
+ SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+
+ /*-------------------------------------------------------
+ (2) ps-poll
+ --------------------------------------------------------
+ */
+ p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+ SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+ SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+ SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+
+ SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+
+ /*--------------------------------------------------------
+ (3) null data
+ ---------------------------------------------------------i
+ */
+ nullfunc = &reserved_page_packet[NULL_PG * 128];
+ SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+ SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+
+ SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+
+ /*---------------------------------------------------------
+ (4) probe response
+ ----------------------------------------------------------
+ */
+ p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+ SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+ SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+ SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+
+ SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+
+ totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ &reserved_page_packet[0], totalpacketlen);
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+ u1RsvdPageLoc, 3);
+
+ skb = dev_alloc_skb(totalpacketlen);
+ memcpy((u8 *) skb_put(skb, totalpacketlen),
+ &reserved_page_packet, totalpacketlen);
+
+ rtstatus = _rtl8723ae_cmd_send_packet(hw, skb);
+
+ if (rtstatus)
+ dlok = true;
+
+ if (dlok) {
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "Set RSVD page location to Fw.\n");
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+ "H2C_RSVDPAGE:\n",
+ u1RsvdPageLoc, 3);
+ rtl8723ae_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+ sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+ } else
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "Set RSVD page location to Fw FAIL!!!!!!.\n");
+}
+
+void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+ u8 u1_joinbssrpt_parm[1] = { 0 };
+
+ SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+
+ rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
new file mode 100644
index 000000000000..89994e16dc83
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL92C__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_START_ADDRESS 0x1000
+#define FW_8192C_END_ADDRESS 0x3FFF
+#define FW_8192C_PAGE_SIZE 4096
+#define FW_8192C_POLLING_DELAY 5
+#define FW_8192C_POLLING_TIMEOUT_COUNT 1000
+
+#define BEACON_PG 0
+#define PSPOLL_PG 2
+#define NULL_PG 3
+#define PROBERSP_PG 4 /* ->5 */
+
+#define TOTAL_RESERVED_PKT_LEN 768
+
+#define IS_FW_HEADER_EXIST(_pfwhdr) \
+ ((_pfwhdr->signature&0xFF00) == 0x2300)
+
+struct rtl8723ae_firmware_header {
+ u16 signature;
+ u8 category;
+ u8 function;
+ u16 version;
+ u8 subversion;
+ u8 rsvd1;
+ u8 month;
+ u8 date;
+ u8 hour;
+ u8 minute;
+ u16 ramcodeSize;
+ u16 rsvd2;
+ u32 svnindex;
+ u32 rsvd3;
+ u32 rsvd4;
+ u32 rsvd5;
+};
+
+enum rtl8192c_h2c_cmd {
+ H2C_AP_OFFLOAD = 0,
+ H2C_SETPWRMODE = 1,
+ H2C_JOINBSSRPT = 2,
+ H2C_RSVDPAGE = 3,
+ H2C_RSSI_REPORT = 5,
+ H2C_RA_MASK = 6,
+ MAX_H2CCMD
+};
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+
+int rtl8723ae_download_fw(struct ieee80211_hw *hw);
+void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+ u32 cmd_len, u8 *p_cmdbuffer);
+void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
new file mode 100644
index 000000000000..3d092e4b0b7f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
@@ -0,0 +1,542 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "hal_bt_coexist.h"
+#include "../pci.h"
+#include "dm.h"
+#include "fw.h"
+#include "phy.h"
+#include "reg.h"
+#include "hal_btc.h"
+
+void rtl8723ae_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
+ bool reject)
+{
+}
+
+void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ if (rtlpriv->link_info.busytraffic) {
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_IDLE;
+
+ if (rtlpriv->link_info.tx_busy_traffic)
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_UPLINK;
+ else
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_UPLINK;
+
+ if (rtlpriv->link_info.rx_busy_traffic)
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_DOWNLINK;
+ else
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_DOWNLINK;
+ } else {
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_WIFI_IDLE;
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_UPLINK;
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_DOWNLINK;
+ }
+
+ if (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
+ rtlpriv->mac80211.mode == WIRELESS_MODE_B) {
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_WIFI_LEGACY;
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_HT20;
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_HT40;
+ } else {
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_LEGACY;
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_HT40;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_HT20;
+ } else {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_HT20;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_HT40;
+ }
+ }
+
+ if (rtlpriv->bt_operation_on)
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BT30;
+ else
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_BT30;
+}
+
+u8 rtl8723ae_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
+ u8 level_num, u8 rssi_thresh,
+ u8 rssi_thresh1)
+
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ long smooth;
+ u8 bt_rssi_state = 0;
+
+ smooth = rtl8723ae_dm_bt_get_rx_ss(hw);
+
+ if (level_num == 2) {
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+
+ if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_LOW) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_LOW)) {
+ if (smooth >= (rssi_thresh +
+ BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_HIGH;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to High\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state stay at Low\n");
+ }
+ } else {
+ if (smooth < rssi_thresh) {
+ bt_rssi_state = BT_RSSI_STATE_LOW;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to Low\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state stay at High\n");
+ }
+ }
+ } else if (level_num == 3) {
+ if (rssi_thresh > rssi_thresh1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 thresh error!!\n");
+ return rtlpcipriv->bt_coexist.bt_pre_rssi_state;
+ }
+
+ if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_LOW) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_LOW)) {
+ if (smooth >=
+ (rssi_thresh+BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to Medium\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state stay at Low\n");
+ }
+ } else if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_MEDIUM) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_MEDIUM)) {
+ if (smooth >= (rssi_thresh1 +
+ BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_HIGH;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to High\n");
+ } else if (smooth < rssi_thresh) {
+ bt_rssi_state = BT_RSSI_STATE_LOW;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to Low\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state stay at Medium\n");
+ }
+ } else {
+ if (smooth < rssi_thresh1) {
+ bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state switch to Medium\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI_1 state stay at High\n");
+ }
+ }
+ }
+
+ rtlpcipriv->bt_coexist.bt_pre_rssi_state1 = bt_rssi_state;
+
+ return bt_rssi_state;
+}
+
+u8 rtl8723ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
+ u8 level_num, u8 rssi_thresh,
+ u8 rssi_thresh1)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ long smooth;
+ u8 bt_rssi_state = 0;
+
+ smooth = rtl8723ae_dm_bt_get_rx_ss(hw);
+
+ if (level_num == 2) {
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+
+ if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_LOW) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_LOW)){
+ if (smooth >=
+ (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_HIGH;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_HIGH;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to High\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state stay at Low\n");
+ }
+ } else {
+ if (smooth < rssi_thresh) {
+ bt_rssi_state = BT_RSSI_STATE_LOW;
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_WIFI_RSSI_LOW;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to Low\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state stay at High\n");
+ }
+ }
+ } else if (level_num == 3) {
+ if (rssi_thresh > rssi_thresh1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI thresh error!!\n");
+ return rtlpcipriv->bt_coexist.bt_pre_rssi_state;
+ }
+ if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_LOW) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_LOW)) {
+ if (smooth >=
+ (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate
+ |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to Medium\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state stay at Low\n");
+ }
+ } else if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_MEDIUM) ||
+ (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+ BT_RSSI_STATE_STAY_MEDIUM)) {
+ if (smooth >=
+ (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
+ bt_rssi_state = BT_RSSI_STATE_HIGH;
+ rtlpcipriv->bt_coexist.cstate
+ |= BT_COEX_STATE_WIFI_RSSI_HIGH;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to High\n");
+ } else if (smooth < rssi_thresh) {
+ bt_rssi_state = BT_RSSI_STATE_LOW;
+ rtlpcipriv->bt_coexist.cstate
+ |= BT_COEX_STATE_WIFI_RSSI_LOW;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to Low\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state stay at Medium\n");
+ }
+ } else {
+ if (smooth < rssi_thresh1) {
+ bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate
+ |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+ rtlpcipriv->bt_coexist.cstate
+ &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state switch to Medium\n");
+ } else {
+ bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], RSSI state stay at High\n");
+ }
+ }
+ }
+
+ rtlpcipriv->bt_coexist.bt_pre_rssi_state = bt_rssi_state;
+ return bt_rssi_state;
+}
+
+long rtl8723ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ long smooth = 0;
+
+ if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ smooth = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
+ else
+ smooth = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_get_rx_ss() = %ld\n", smooth);
+
+ return smooth;
+}
+
+void rtl8723ae_dm_bt_balance(struct ieee80211_hw *hw,
+ bool balance_on, u8 ms0, u8 ms1)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[3] = {0};
+
+ if (balance_on) {
+ h2c_parameter[2] = 1;
+ h2c_parameter[1] = ms1;
+ h2c_parameter[0] = ms0;
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ } else {
+ h2c_parameter[2] = 0;
+ h2c_parameter[1] = 0;
+ h2c_parameter[0] = 0;
+ }
+ rtlpcipriv->bt_coexist.balance_on = balance_on;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n",
+ balance_on ? "ON" : "OFF", ms0, ms1,
+ h2c_parameter[0]<<16 | h2c_parameter[1]<<8 | h2c_parameter[2]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter);
+}
+
+
+void rtl8723ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ if (type == BT_AGCTABLE_OFF) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BT]AGCTable Off!\n");
+ rtl_write_dword(rtlpriv, 0xc78, 0x641c0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x631d0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x621e0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x611f0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x60200001);
+
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0x32000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0x71000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0xb0000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0xfc000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_G1, 0xfffff, 0x30355);
+ } else if (type == BT_AGCTABLE_ON) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BT]AGCTable On!\n");
+ rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001);
+ rtl_write_dword(rtlpriv, 0xc78, 0x4a200001);
+
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0xdc000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0x90000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0x51000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_AGC_HP, 0xfffff, 0x12000);
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+ RF_RX_G1, 0xfffff, 0x00355);
+
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+ }
+}
+
+void rtl8723ae_dm_bt_bback_off_level(struct ieee80211_hw *hw, u8 type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ if (type == BT_BB_BACKOFF_OFF) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BT]BBBackOffLevel Off!\n");
+ rtl_write_dword(rtlpriv, 0xc04, 0x3a05611);
+ } else if (type == BT_BB_BACKOFF_ON) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BT]BBBackOffLevel On!\n");
+ rtl_write_dword(rtlpriv, 0xc04, 0x3a07611);
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+ }
+}
+
+void rtl8723ae_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_fw_coex_all_off()\n");
+
+ if (rtlpcipriv->bt_coexist.fw_coexist_all_off)
+ return;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_fw_coex_all_off(), real Do\n");
+ rtl8723ae_dm_bt_fw_coex_all_off_8723a(hw);
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = true;
+}
+
+void rtl8723ae_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_sw_coex_all_off()\n");
+
+ if (rtlpcipriv->bt_coexist.sw_coexist_all_off)
+ return;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_sw_coex_all_off(), real Do\n");
+ rtl8723ae_dm_bt_sw_coex_all_off_8723a(hw);
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = true;
+}
+
+void rtl8723ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_hw_coex_all_off()\n");
+
+ if (rtlpcipriv->bt_coexist.hw_coexist_all_off)
+ return;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "rtl8723ae_dm_bt_hw_coex_all_off(), real Do\n");
+
+ rtl8723ae_dm_bt_hw_coex_all_off_8723a(hw);
+
+ rtlpcipriv->bt_coexist.hw_coexist_all_off = true;
+}
+
+void rtl8723ae_btdm_coex_all_off(struct ieee80211_hw *hw)
+{
+ rtl8723ae_dm_bt_fw_coex_all_off(hw);
+ rtl8723ae_dm_bt_sw_coex_all_off(hw);
+ rtl8723ae_dm_bt_hw_coex_all_off(hw);
+}
+
+bool rtl8723ae_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ if ((rtlpcipriv->bt_coexist.previous_state ==
+ rtlpcipriv->bt_coexist.cstate) &&
+ (rtlpcipriv->bt_coexist.previous_state_h ==
+ rtlpcipriv->bt_coexist.cstate_h))
+ return false;
+ else
+ return true;
+}
+
+bool rtl8723ae_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->link_info.tx_busy_traffic)
+ return true;
+ else
+ return false;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
new file mode 100644
index 000000000000..76f4d122dbc1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
@@ -0,0 +1,160 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_HAL_BT_COEXIST_H__
+#define __RTL8723E_HAL_BT_COEXIST_H__
+
+#include "../wifi.h"
+
+/* The reg define is for 8723 */
+#define REG_HIGH_PRIORITY_TXRX 0x770
+#define REG_LOW_PRIORITY_TXRX 0x774
+
+#define BT_FW_COEX_THRESH_TOL 6
+#define BT_FW_COEX_THRESH_20 20
+#define BT_FW_COEX_THRESH_23 23
+#define BT_FW_COEX_THRESH_25 25
+#define BT_FW_COEX_THRESH_30 30
+#define BT_FW_COEX_THRESH_35 35
+#define BT_FW_COEX_THRESH_40 40
+#define BT_FW_COEX_THRESH_45 45
+#define BT_FW_COEX_THRESH_47 47
+#define BT_FW_COEX_THRESH_50 50
+#define BT_FW_COEX_THRESH_55 55
+
+#define BT_COEX_STATE_BT30 BIT(0)
+#define BT_COEX_STATE_WIFI_HT20 BIT(1)
+#define BT_COEX_STATE_WIFI_HT40 BIT(2)
+#define BT_COEX_STATE_WIFI_LEGACY BIT(3)
+
+#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4)
+#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5)
+#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6)
+#define BT_COEX_STATE_DEC_BT_POWER BIT(7)
+
+#define BT_COEX_STATE_WIFI_IDLE BIT(8)
+#define BT_COEX_STATE_WIFI_UPLINK BIT(9)
+#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10)
+
+#define BT_COEX_STATE_BT_INQ_PAGE BIT(11)
+#define BT_COEX_STATE_BT_IDLE BIT(12)
+#define BT_COEX_STATE_BT_UPLINK BIT(13)
+#define BT_COEX_STATE_BT_DOWNLINK BIT(14)
+
+#define BT_COEX_STATE_HOLD_FOR_BT_OPERATION BIT(15)
+#define BT_COEX_STATE_BT_RSSI_LOW BIT(19)
+
+#define BT_COEX_STATE_PROFILE_HID BIT(20)
+#define BT_COEX_STATE_PROFILE_A2DP BIT(21)
+#define BT_COEX_STATE_PROFILE_PAN BIT(22)
+#define BT_COEX_STATE_PROFILE_SCO BIT(23)
+
+#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24)
+#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25)
+#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26)
+
+#define BT_COEX_STATE_BTINFO_COMMON BIT(30)
+#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT(31)
+#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT(29)
+
+#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT(0)
+#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT(1)
+#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT(2)
+#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT(3)
+
+#define BT_RSSI_STATE_HIGH 0
+#define BT_RSSI_STATE_MEDIUM 1
+#define BT_RSSI_STATE_LOW 2
+#define BT_RSSI_STATE_STAY_HIGH 3
+#define BT_RSSI_STATE_STAY_MEDIUM 4
+#define BT_RSSI_STATE_STAY_LOW 5
+
+#define BT_AGCTABLE_OFF 0
+#define BT_AGCTABLE_ON 1
+#define BT_BB_BACKOFF_OFF 0
+#define BT_BB_BACKOFF_ON 1
+#define BT_FW_NAV_OFF 0
+#define BT_FW_NAV_ON 1
+
+#define BT_COEX_MECH_NONE 0
+#define BT_COEX_MECH_SCO 1
+#define BT_COEX_MECH_HID 2
+#define BT_COEX_MECH_A2DP 3
+#define BT_COEX_MECH_PAN 4
+#define BT_COEX_MECH_HID_A2DP 5
+#define BT_COEX_MECH_HID_PAN 6
+#define BT_COEX_MECH_PAN_A2DP 7
+#define BT_COEX_MECH_HID_SCO_ESCO 8
+#define BT_COEX_MECH_FTP_A2DP 9
+#define BT_COEX_MECH_COMMON 10
+#define BT_COEX_MECH_MAX 11
+
+#define BT_DBG_PROFILE_NONE 0
+#define BT_DBG_PROFILE_SCO 1
+#define BT_DBG_PROFILE_HID 2
+#define BT_DBG_PROFILE_A2DP 3
+#define BT_DBG_PROFILE_PAN 4
+#define BT_DBG_PROFILE_HID_A2DP 5
+#define BT_DBG_PROFILE_HID_PAN 6
+#define BT_DBG_PROFILE_PAN_A2DP 7
+#define BT_DBG_PROFILE_MAX 9
+
+#define BTINFO_B_FTP BIT(7)
+#define BTINFO_B_A2DP BIT(6)
+#define BTINFO_B_HID BIT(5)
+#define BTINFO_B_SCO_BUSY BIT(4)
+#define BTINFO_B_ACL_BUSY BIT(3)
+#define BTINFO_B_INQ_PAGE BIT(2)
+#define BTINFO_B_SCO_ESCO BIT(1)
+#define BTINFO_B_CONNECTION BIT(0)
+
+
+void rtl8723ae_btdm_coex_all_off(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw);
+
+void rtl8723ae_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw);
+long rtl8723ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_balance(struct ieee80211_hw *hw,
+ bool balance_on, u8 ms0, u8 ms1);
+void rtl8723ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type);
+void rtl8723ae_dm_bt_bback_off_level(struct ieee80211_hw *hw, u8 type);
+u8 rtl8723ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
+ u8 level_num, u8 rssi_thresh,
+ u8 rssi_thresh1);
+u8 rtl8723ae_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
+ u8 level_num, u8 rssi_thresh,
+ u8 rssi_thresh1);
+void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
+ bool reject);
+
+bool rtl8723ae_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw);
+bool rtl8723ae_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
new file mode 100644
index 000000000000..887d521fe690
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
@@ -0,0 +1,1786 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+#include "hal_btc.h"
+#include "../pci.h"
+#include "phy.h"
+#include "fw.h"
+#include "reg.h"
+#include "def.h"
+
+void rtl8723ae_bt_coex_off_before_lps(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ if (!rtlpcipriv->bt_coexist.bt_coexistence)
+ return;
+
+ if (ppsc->inactiveps) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BT][DM], Before enter IPS, turn off all Coexist DM\n");
+ rtlpcipriv->bt_coexist.cstate = 0;
+ rtlpcipriv->bt_coexist.previous_state = 0;
+ rtlpcipriv->bt_coexist.cstate_h = 0;
+ rtlpcipriv->bt_coexist.previous_state_h = 0;
+ rtl8723ae_btdm_coex_all_off(hw);
+ }
+}
+
+static enum _RT_MEDIA_STATUS mgnt_link_status_query(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ enum _RT_MEDIA_STATUS m_status = RT_MEDIA_DISCONNECT;
+
+ u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
+
+ if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ m_status = RT_MEDIA_CONNECT;
+
+ return m_status;
+}
+
+void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw,
+ bool mstatus)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 h2c_parameter[3] = {0};
+ u8 chnl;
+
+ if (!rtlpcipriv->bt_coexist.bt_coexistence)
+ return;
+
+ if (RT_MEDIA_CONNECT == mstatus)
+ h2c_parameter[0] = 0x1; /* 0: disconnected, 1:connected */
+ else
+ h2c_parameter[0] = 0x0;
+
+ if (mgnt_link_status_query(hw)) {
+ chnl = rtlphy->current_channel;
+ h2c_parameter[1] = chnl;
+ }
+
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
+ h2c_parameter[2] = 0x30;
+ else
+ h2c_parameter[2] = 0x20;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], FW write 0x19 = 0x%x\n",
+ h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x19, 3, h2c_parameter);
+
+}
+
+static bool rtl8723ae_dm_bt_is_wifi_busy(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ if (rtlpriv->link_info.busytraffic ||
+ rtlpriv->link_info.rx_busy_traffic ||
+ rtlpriv->link_info.tx_busy_traffic)
+ return true;
+ else
+ return false;
+}
+
+static void rtl8723ae_dm_bt_set_fw_3a(struct ieee80211_hw *hw,
+ u8 byte1, u8 byte2, u8 byte3,
+ u8 byte4, u8 byte5)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[5] = {0};
+
+ h2c_parameter[0] = byte1;
+ h2c_parameter[1] = byte2;
+ h2c_parameter[2] = byte3;
+ h2c_parameter[3] = byte4;
+ h2c_parameter[4] = byte5;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], FW write 0x3a(4bytes) = 0x%x%8x\n",
+ h2c_parameter[0], h2c_parameter[1]<<24 | h2c_parameter[2]<<16 |
+ h2c_parameter[3]<<8 | h2c_parameter[4]);
+ rtl8723ae_fill_h2c_cmd(hw, 0x3a, 5, h2c_parameter);
+}
+
+static bool rtl8723ae_dm_bt_need_to_dec_bt_pwr(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Need to decrease bt power\n");
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_DEC_BT_POWER;
+ return true;
+ }
+
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_DEC_BT_POWER;
+ return false;
+}
+
+static bool rtl8723ae_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ if ((rtlpcipriv->bt_coexist.previous_state ==
+ rtlpcipriv->bt_coexist.cstate) &&
+ (rtlpcipriv->bt_coexist.previous_state_h ==
+ rtlpcipriv->bt_coexist.cstate_h)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[DM][BT], Coexist state do not chang!!\n");
+ return true;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[DM][BT], Coexist state changed!!\n");
+ return false;
+ }
+}
+
+static void rtl8723ae_dm_bt_set_coex_table(struct ieee80211_hw *hw,
+ u32 val_0x6c0, u32 val_0x6c8,
+ u32 val_0x6cc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "set coex table, set 0x6c0 = 0x%x\n", val_0x6c0);
+ rtl_write_dword(rtlpriv, 0x6c0, val_0x6c0);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "set coex table, set 0x6c8 = 0x%x\n", val_0x6c8);
+ rtl_write_dword(rtlpriv, 0x6c8, val_0x6c8);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "set coex table, set 0x6cc = 0x%x\n", val_0x6cc);
+ rtl_write_byte(rtlpriv, 0x6cc, val_0x6cc);
+}
+
+static void rtl8723ae_dm_bt_set_hw_pta_mode(struct ieee80211_hw *hw, bool mode)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (BT_PTA_MODE_ON == mode) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode on, ");
+ /* Enable GPIO 0/1/2/3/8 pins for bt */
+ rtl_write_byte(rtlpriv, 0x40, 0x20);
+ rtlpcipriv->bt_coexist.hw_coexist_all_off = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode off\n");
+ rtl_write_byte(rtlpriv, 0x40, 0x0);
+ }
+}
+
+static void rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(struct ieee80211_hw *hw,
+ u8 type)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (BT_RF_RX_LPF_CORNER_SHRINK == type) {
+ /* Shrink RF Rx LPF corner, 0x1e[7:4]=1111 ==> [11:4] by Jenyu*/
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "Shrink RF Rx LPF corner!!\n");
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff,
+ 0xf0ff7);
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+ } else if (BT_RF_RX_LPF_CORNER_RESUME == type) {
+ /*Resume RF Rx LPF corner*/
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "Resume RF Rx LPF corner!!\n");
+ rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff,
+ rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
+ }
+}
+
+static void rtl8723ae_bt_set_penalty_tx_rate_adap(struct ieee80211_hw *hw,
+ u8 ra_type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 tmu1;
+
+ tmu1 = rtl_read_byte(rtlpriv, 0x4fd);
+ tmu1 |= BIT(0);
+ if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == ra_type) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "Tx rate adaptive, set low penalty!!\n");
+ tmu1 &= ~BIT(2);
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+ } else if (BT_TX_RATE_ADAPTIVE_NORMAL == ra_type) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "Tx rate adaptive, set normal!!\n");
+ tmu1 |= BIT(2);
+ }
+ rtl_write_byte(rtlpriv, 0x4fd, tmu1);
+}
+
+static void rtl8723ae_dm_bt_btdm_structure_reload(struct ieee80211_hw *hw,
+ struct btdm_8723 *btdm)
+{
+ btdm->all_off = false;
+ btdm->agc_table_en = false;
+ btdm->adc_back_off_on = false;
+ btdm->b2_ant_hid_en = false;
+ btdm->low_penalty_rate_adaptive = false;
+ btdm->rf_rx_lpf_shrink = false;
+ btdm->reject_aggre_pkt = false;
+
+ btdm->tdma_on = false;
+ btdm->tdma_ant = TDMA_2ANT;
+ btdm->tdma_nav = TDMA_NAV_OFF;
+ btdm->tdma_dac_swing = TDMA_DAC_SWING_OFF;
+ btdm->fw_dac_swing_lvl = 0x20;
+
+ btdm->tra_tdma_on = false;
+ btdm->tra_tdma_ant = TDMA_2ANT;
+ btdm->tra_tdma_nav = TDMA_NAV_OFF;
+ btdm->ignore_wlan_act = false;
+
+ btdm->ps_tdma_on = false;
+ btdm->ps_tdma_byte[0] = 0x0;
+ btdm->ps_tdma_byte[1] = 0x0;
+ btdm->ps_tdma_byte[2] = 0x0;
+ btdm->ps_tdma_byte[3] = 0x8;
+ btdm->ps_tdma_byte[4] = 0x0;
+
+ btdm->pta_on = true;
+ btdm->val_0x6c0 = 0x5a5aaaaa;
+ btdm->val_0x6c8 = 0xcc;
+ btdm->val_0x6cc = 0x3;
+
+ btdm->sw_dac_swing_on = false;
+ btdm->sw_dac_swing_lvl = 0xc0;
+ btdm->wlan_act_hi = 0x20;
+ btdm->wlan_act_lo = 0x10;
+ btdm->bt_retry_index = 2;
+
+ btdm->dec_bt_pwr = false;
+}
+
+static void dm_bt_btdm_structure_reload_all_off(struct ieee80211_hw *hw,
+ struct btdm_8723 *btdm)
+{
+ rtl8723ae_dm_bt_btdm_structure_reload(hw, btdm);
+ btdm->all_off = true;
+ btdm->pta_on = false;
+ btdm->wlan_act_hi = 0x10;
+}
+
+static bool rtl8723ae_dm_bt_is_2_ant_common_action(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct btdm_8723 btdm8723;
+ bool common = false;
+
+ rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+
+ if (!rtl8723ae_dm_bt_is_wifi_busy(hw)
+ && !rtlpcipriv->bt_coexist.bt_busy) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi idle + Bt idle, bt coex mechanism always off!!\n");
+ dm_bt_btdm_structure_reload_all_off(hw, &btdm8723);
+ common = true;
+ } else if (rtl8723ae_dm_bt_is_wifi_busy(hw)
+ && !rtlpcipriv->bt_coexist.bt_busy) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi non-idle + Bt disabled/idle!!\n");
+ btdm8723.low_penalty_rate_adaptive = true;
+ btdm8723.rf_rx_lpf_shrink = false;
+ btdm8723.reject_aggre_pkt = false;
+
+ /* sw mechanism */
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = false;
+ btdm8723.sw_dac_swing_on = false;
+
+ btdm8723.pta_on = true;
+ btdm8723.val_0x6c0 = 0x5a5aaaaa;
+ btdm8723.val_0x6c8 = 0xcccc;
+ btdm8723.val_0x6cc = 0x3;
+
+ btdm8723.tdma_on = false;
+ btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF;
+ btdm8723.b2_ant_hid_en = false;
+
+ common = true;
+ } else if (rtlpcipriv->bt_coexist.bt_busy) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Bt non-idle!\n");
+ if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi connection exist\n");
+ common = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "No Wifi connection!\n");
+ btdm8723.rf_rx_lpf_shrink = true;
+ btdm8723.low_penalty_rate_adaptive = false;
+ btdm8723.reject_aggre_pkt = false;
+
+ /* sw mechanism */
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = false;
+ btdm8723.sw_dac_swing_on = false;
+
+ btdm8723.pta_on = true;
+ btdm8723.val_0x6c0 = 0x55555555;
+ btdm8723.val_0x6c8 = 0x0000ffff;
+ btdm8723.val_0x6cc = 0x3;
+
+ btdm8723.tdma_on = false;
+ btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF;
+ btdm8723.b2_ant_hid_en = false;
+
+ common = true;
+ }
+ }
+
+ if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+ btdm8723.dec_bt_pwr = true;
+
+ if (common)
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BTINFO_COMMON;
+
+ if (common && rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+ rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+
+ return common;
+}
+
+static void rtl8723ae_dm_bt_set_sw_full_time_dac_swing(struct ieee80211_hw *hw,
+ bool sw_dac_swing_on,
+ u32 sw_dac_swing_lvl)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (sw_dac_swing_on) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], SwDacSwing = 0x%x\n", sw_dac_swing_lvl);
+ rtl8723ae_phy_set_bb_reg(hw, 0x880, 0xff000000,
+ sw_dac_swing_lvl);
+ rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], SwDacSwing Off!\n");
+ rtl8723ae_phy_set_bb_reg(hw, 0x880, 0xff000000, 0xc0);
+ }
+}
+
+static void rtl8723ae_dm_bt_set_fw_dec_bt_pwr(struct ieee80211_hw *hw,
+ bool dec_bt_pwr)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = 0;
+
+ if (dec_bt_pwr) {
+ h2c_parameter[0] |= BIT(1);
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ }
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], decrease Bt Power : %s, write 0x21 = 0x%x\n",
+ (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x21, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_2_ant_hid(struct ieee80211_hw *hw,
+ bool enable, bool dac_swing_on)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ if (enable) {
+ h2c_parameter[0] |= BIT(0);
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ }
+ if (dac_swing_on)
+ h2c_parameter[0] |= BIT(1); /* Dac Swing default enable */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], turn 2-Ant+HID mode %s, DACSwing:%s, write 0x15 = 0x%x\n",
+ (enable ? "ON!!" : "OFF!!"), (dac_swing_on ? "ON" : "OFF"),
+ h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x15, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_tdma_ctrl(struct ieee80211_hw *hw,
+ bool enable, u8 ant_num, u8 nav_en,
+ u8 dac_swing_en)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 h2c_parameter[1] = {0};
+ u8 h2c_parameter1[1] = {0};
+
+ h2c_parameter[0] = 0;
+ h2c_parameter1[0] = 0;
+
+ if (enable) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], set BT PTA update manager to trigger update!!\n");
+ h2c_parameter1[0] |= BIT(0);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], turn TDMA mode ON!!\n");
+ h2c_parameter[0] |= BIT(0); /* function enable */
+ if (TDMA_1ANT == ant_num) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_1ANT\n");
+ h2c_parameter[0] |= BIT(1);
+ } else if (TDMA_2ANT == ant_num) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_2ANT\n");
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Unknown Ant\n");
+ }
+
+ if (TDMA_NAV_OFF == nav_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_NAV_OFF\n");
+ } else if (TDMA_NAV_ON == nav_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_NAV_ON\n");
+ h2c_parameter[0] |= BIT(2);
+ }
+
+ if (TDMA_DAC_SWING_OFF == dac_swing_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_DAC_SWING_OFF\n");
+ } else if (TDMA_DAC_SWING_ON == dac_swing_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TDMA_DAC_SWING_ON\n");
+ h2c_parameter[0] |= BIT(4);
+ }
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], set BT PTA update manager to no update!!\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], turn TDMA mode OFF!!\n");
+ }
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], FW2AntTDMA, write 0x26 = 0x%x\n",
+ h2c_parameter1[0]);
+ rtl8723ae_fill_h2c_cmd(hw, 0x26, 1, h2c_parameter1);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], FW2AntTDMA, write 0x14 = 0x%x\n", h2c_parameter[0]);
+ rtl8723ae_fill_h2c_cmd(hw, 0x14, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_ignore_wlan_act(struct ieee80211_hw *hw,
+ bool enable)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ if (enable) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], BT Ignore Wlan_Act !!\n");
+ h2c_parameter[0] |= BIT(0); /* function enable */
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], BT don't ignore Wlan_Act !!\n");
+ }
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25 = 0x%x\n",
+ h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x25, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(struct ieee80211_hw *hw,
+ bool enable, u8 ant_num,
+ u8 nav_en)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 h2c_parameter[2] = {0};
+
+ /* Only 8723 B cut should do this */
+ if (IS_VENDOR_8723_A_CUT(rtlhal->version)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], not 8723B cut, don't set Traditional TDMA!!\n");
+ return;
+ }
+
+ if (enable) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], turn TTDMA mode ON!!\n");
+ h2c_parameter[0] |= BIT(0); /* function enable */
+ if (TDMA_1ANT == ant_num) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TTDMA_1ANT\n");
+ h2c_parameter[0] |= BIT(1);
+ } else if (TDMA_2ANT == ant_num) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TTDMA_2ANT\n");
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Unknown Ant\n");
+ }
+
+ if (TDMA_NAV_OFF == nav_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TTDMA_NAV_OFF\n");
+ } else if (TDMA_NAV_ON == nav_en) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], TTDMA_NAV_ON\n");
+ h2c_parameter[1] |= BIT(0);
+ }
+
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], turn TTDMA mode OFF!!\n");
+ }
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], FW Traditional TDMA, write 0x33 = 0x%x\n",
+ h2c_parameter[0] << 8 | h2c_parameter[1]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x33, 2, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_dac_swing_level(struct ieee80211_hw *hw,
+ u8 dac_swing_lvl)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = dac_swing_lvl;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], write 0x29 = 0x%x\n", h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x29, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_bt_hid_info(struct ieee80211_hw *hw,
+ bool enable)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = 0;
+
+ if (enable) {
+ h2c_parameter[0] |= BIT(0);
+ rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+ }
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Set BT HID information = 0x%x\n", enable);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], write 0x24 = 0x%x\n", h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x24, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_bt_retry_index(struct ieee80211_hw *hw,
+ u8 retry_index)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = retry_index;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Set BT Retry Index=%d\n", retry_index);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], write 0x23 = 0x%x\n", h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x23, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_wlan_act(struct ieee80211_hw *hw,
+ u8 wlan_act_hi, u8 wlan_act_lo)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 h2c_parameter_hi[1] = {0};
+ u8 h2c_parameter_lo[1] = {0};
+
+ h2c_parameter_hi[0] = wlan_act_hi;
+ h2c_parameter_lo[0] = wlan_act_lo;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], Set WLAN_ACT Hi:Lo = 0x%x/0x%x\n", wlan_act_hi,
+ wlan_act_lo);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], write 0x22 = 0x%x\n", h2c_parameter_hi[0]);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], write 0x11 = 0x%x\n", h2c_parameter_lo[0]);
+
+ /* WLAN_ACT = High duration, unit:ms */
+ rtl8723ae_fill_h2c_cmd(hw, 0x22, 1, h2c_parameter_hi);
+ /* WLAN_ACT = Low duration, unit:3*625us */
+ rtl8723ae_fill_h2c_cmd(hw, 0x11, 1, h2c_parameter_lo);
+}
+
+void rtl8723ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw, struct btdm_8723 *btdm)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct btdm_8723 *btdm_8723 = &rtlhal->hal_coex_8723.btdm;
+ u8 i;
+ bool fw_current_inpsmode = false;
+ bool fw_ps_awake = true;
+
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+ (u8 *)(&fw_current_inpsmode));
+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+ (u8 *)(&fw_ps_awake));
+
+ /* check new setting is different than the old one,
+ * if all the same, don't do the setting again.
+ */
+ if (memcmp(btdm_8723, btdm, sizeof(struct btdm_8723)) == 0) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], the same coexist setting, return!!\n");
+ return;
+ } else { /* save the new coexist setting */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], UPDATE TO NEW COEX SETTING!!\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bAllOff = 0x%x/ 0x%x\n",
+ btdm_8723->all_off, btdm->all_off);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new agc_table_en = 0x%x/ 0x%x\n",
+ btdm_8723->agc_table_en, btdm->agc_table_en);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new adc_back_off_on = 0x%x/ 0x%x\n",
+ btdm_8723->adc_back_off_on, btdm->adc_back_off_on);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new b2_ant_hid_en = 0x%x/ 0x%x\n",
+ btdm_8723->b2_ant_hid_en, btdm->b2_ant_hid_en);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bLowPenaltyRateAdaptive = 0x%x/ 0x%x\n",
+ btdm_8723->low_penalty_rate_adaptive,
+ btdm->low_penalty_rate_adaptive);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bRfRxLpfShrink = 0x%x/ 0x%x\n",
+ btdm_8723->rf_rx_lpf_shrink, btdm->rf_rx_lpf_shrink);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bRejectAggrePkt = 0x%x/ 0x%x\n",
+ btdm_8723->reject_aggre_pkt, btdm->reject_aggre_pkt);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new tdma_on = 0x%x/ 0x%x\n",
+ btdm_8723->tdma_on, btdm->tdma_on);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new tdmaAnt = 0x%x/ 0x%x\n",
+ btdm_8723->tdma_ant, btdm->tdma_ant);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new tdmaNav = 0x%x/ 0x%x\n",
+ btdm_8723->tdma_nav, btdm->tdma_nav);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new tdma_dac_swing = 0x%x/ 0x%x\n",
+ btdm_8723->tdma_dac_swing, btdm->tdma_dac_swing);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new fwDacSwingLvl = 0x%x/ 0x%x\n",
+ btdm_8723->fw_dac_swing_lvl, btdm->fw_dac_swing_lvl);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bTraTdmaOn = 0x%x/ 0x%x\n",
+ btdm_8723->tra_tdma_on, btdm->tra_tdma_on);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new traTdmaAnt = 0x%x/ 0x%x\n",
+ btdm_8723->tra_tdma_ant, btdm->tra_tdma_ant);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new traTdmaNav = 0x%x/ 0x%x\n",
+ btdm_8723->tra_tdma_nav, btdm->tra_tdma_nav);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bPsTdmaOn = 0x%x/ 0x%x\n",
+ btdm_8723->ps_tdma_on, btdm->ps_tdma_on);
+ for (i = 0; i < 5; i++) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new psTdmaByte[i] = 0x%x/ 0x%x\n",
+ btdm_8723->ps_tdma_byte[i],
+ btdm->ps_tdma_byte[i]);
+ }
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bIgnoreWlanAct = 0x%x/ 0x%x\n",
+ btdm_8723->ignore_wlan_act, btdm->ignore_wlan_act);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new bPtaOn = 0x%x/ 0x%x\n",
+ btdm_8723->pta_on, btdm->pta_on);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new val_0x6c0 = 0x%x/ 0x%x\n",
+ btdm_8723->val_0x6c0, btdm->val_0x6c0);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new val_0x6c8 = 0x%x/ 0x%x\n",
+ btdm_8723->val_0x6c8, btdm->val_0x6c8);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new val_0x6cc = 0x%x/ 0x%x\n",
+ btdm_8723->val_0x6cc, btdm->val_0x6cc);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new sw_dac_swing_on = 0x%x/ 0x%x\n",
+ btdm_8723->sw_dac_swing_on, btdm->sw_dac_swing_on);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new sw_dac_swing_lvl = 0x%x/ 0x%x\n",
+ btdm_8723->sw_dac_swing_lvl,
+ btdm->sw_dac_swing_lvl);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new wlanActHi = 0x%x/ 0x%x\n",
+ btdm_8723->wlan_act_hi, btdm->wlan_act_hi);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new wlanActLo = 0x%x/ 0x%x\n",
+ btdm_8723->wlan_act_lo, btdm->wlan_act_lo);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], original/new btRetryIndex = 0x%x/ 0x%x\n",
+ btdm_8723->bt_retry_index, btdm->bt_retry_index);
+
+ memcpy(btdm_8723, btdm, sizeof(struct btdm_8723));
+ }
+ /*
+ * Here we only consider when Bt Operation
+ * inquiry/paging/pairing is ON
+ * we only need to turn off TDMA
+ */
+
+ if (rtlpcipriv->bt_coexist.hold_for_bt_operation) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], set to ignore wlanAct for BT OP!!\n");
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw, true);
+ return;
+ }
+
+ if (btdm->all_off) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], disable all coexist mechanism !!\n");
+ rtl8723ae_btdm_coex_all_off(hw);
+ return;
+ }
+
+ rtl8723ae_dm_bt_reject_ap_aggregated_packet(hw, btdm->reject_aggre_pkt);
+
+ if (btdm->low_penalty_rate_adaptive)
+ rtl8723ae_bt_set_penalty_tx_rate_adap(hw,
+ BT_TX_RATE_ADAPTIVE_LOW_PENALTY);
+ else
+ rtl8723ae_bt_set_penalty_tx_rate_adap(hw,
+ BT_TX_RATE_ADAPTIVE_NORMAL);
+
+ if (btdm->rf_rx_lpf_shrink)
+ rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw,
+ BT_RF_RX_LPF_CORNER_SHRINK);
+ else
+ rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw,
+ BT_RF_RX_LPF_CORNER_RESUME);
+
+ if (btdm->agc_table_en)
+ rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_ON);
+ else
+ rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_OFF);
+
+ if (btdm->adc_back_off_on)
+ rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_ON);
+ else
+ rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_OFF);
+
+ rtl8723ae_dm_bt_set_fw_bt_retry_index(hw, btdm->bt_retry_index);
+
+ rtl8723ae_dm_bt_set_fw_dac_swing_level(hw, btdm->fw_dac_swing_lvl);
+ rtl8723ae_dm_bt_set_fw_wlan_act(hw, btdm->wlan_act_hi,
+ btdm->wlan_act_lo);
+
+ rtl8723ae_dm_bt_set_coex_table(hw, btdm->val_0x6c0,
+ btdm->val_0x6c8, btdm->val_0x6cc);
+ rtl8723ae_dm_bt_set_hw_pta_mode(hw, btdm->pta_on);
+
+ /* Note: There is a constraint between TDMA and 2AntHID
+ * Only one of 2AntHid and tdma can be turned on
+ * We should turn off those mechanisms first
+ * and then turn on them on.
+ */
+ if (btdm->b2_ant_hid_en) {
+ /* turn off tdma */
+ rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+ btdm->tra_tdma_ant,
+ btdm->tra_tdma_nav);
+ rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+ btdm->tdma_nav,
+ btdm->tdma_dac_swing);
+
+ /* turn off Pstdma */
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+ btdm->ignore_wlan_act);
+ /* Antenna control by PTA, 0x870 = 0x300. */
+ rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+
+ /* turn on 2AntHid */
+ rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, true);
+ rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, true, true);
+ } else if (btdm->tdma_on) {
+ /* turn off 2AntHid */
+ rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+ rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+ /* turn off pstdma */
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+ btdm->ignore_wlan_act);
+ /* Antenna control by PTA, 0x870 = 0x300. */
+ rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+
+ /* turn on tdma */
+ rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+ btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+ rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, true, btdm->tdma_ant,
+ btdm->tdma_nav, btdm->tdma_dac_swing);
+ } else if (btdm->ps_tdma_on) {
+ /* turn off 2AntHid */
+ rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+ rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+ /* turn off tdma */
+ rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+ btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+ rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+ btdm->tdma_nav, btdm->tdma_dac_swing);
+
+ /* turn on pstdma */
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+ btdm->ignore_wlan_act);
+ rtl8723ae_dm_bt_set_fw_3a(hw,
+ btdm->ps_tdma_byte[0],
+ btdm->ps_tdma_byte[1],
+ btdm->ps_tdma_byte[2],
+ btdm->ps_tdma_byte[3],
+ btdm->ps_tdma_byte[4]);
+ } else {
+ /* turn off 2AntHid */
+ rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+ rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+ /* turn off tdma */
+ rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+ btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+ rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+ btdm->tdma_nav, btdm->tdma_dac_swing);
+
+ /* turn off pstdma */
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+ btdm->ignore_wlan_act);
+ /* Antenna control by PTA, 0x870 = 0x300. */
+ rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+ }
+
+ /* Note:
+ * We should add delay for making sure sw DacSwing can be set
+ * sucessfully. Because of that rtl8723ae_dm_bt_set_fw_2_ant_hid()
+ * and rtl8723ae_dm_bt_set_fw_tdma_ctrl()
+ * will overwrite the reg 0x880.
+ */
+ mdelay(30);
+ rtl8723ae_dm_bt_set_sw_full_time_dac_swing(hw,
+ btdm->sw_dac_swing_on, btdm->sw_dac_swing_lvl);
+ rtl8723ae_dm_bt_set_fw_dec_bt_pwr(hw, btdm->dec_bt_pwr);
+}
+
+/*============================================================
+ * extern function start with BTDM_
+ *============================================================
+ */
+static u32 rtl8723ae_dm_bt_tx_rx_couter_h(struct ieee80211_hw *hw)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 counters = 0;
+
+ counters = rtlhal->hal_coex_8723.high_priority_tx +
+ rtlhal->hal_coex_8723.high_priority_rx;
+ return counters;
+}
+
+static u32 rtl8723ae_dm_bt_tx_rx_couter_l(struct ieee80211_hw *hw)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ return rtlhal->hal_coex_8723.low_priority_tx +
+ rtlhal->hal_coex_8723.low_priority_rx;
+}
+
+static u8 rtl8723ae_dm_bt_bt_tx_rx_counter_level(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u32 bt_tx_rx_cnt = 0;
+ u8 bt_tx_rx_cnt_lvl = 0;
+
+ bt_tx_rx_cnt = rtl8723ae_dm_bt_tx_rx_couter_h(hw) +
+ rtl8723ae_dm_bt_tx_rx_couter_l(hw);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt);
+
+ rtlpcipriv->bt_coexist.cstate_h &=
+ ~(BT_COEX_STATE_BT_CNT_LEVEL_0 | BT_COEX_STATE_BT_CNT_LEVEL_1 |
+ BT_COEX_STATE_BT_CNT_LEVEL_2);
+
+ if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_3) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters at level 3\n");
+ bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_3;
+ rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_3;
+ } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters at level 2\n");
+ bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_2;
+ rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_2;
+ } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters at level 1\n");
+ bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_1;
+ rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_1;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters at level 0\n");
+ bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_0;
+ rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_0;
+ }
+ return bt_tx_rx_cnt_lvl;
+}
+
+static void rtl8723ae_dm_bt_2_ant_hid_sco_esco(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct btdm_8723 btdm8723;
+ u8 bt_rssi_state, bt_rssi_state1;
+ u8 bt_tx_rx_cnt_lvl;
+
+ rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+
+ btdm8723.rf_rx_lpf_shrink = true;
+ btdm8723.low_penalty_rate_adaptive = true;
+ btdm8723.reject_aggre_pkt = false;
+
+ bt_tx_rx_cnt_lvl = rtl8723ae_dm_bt_bt_tx_rx_counter_level(hw);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl);
+
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n");
+ /* coex table */
+ btdm8723.val_0x6c0 = 0x55555555;
+ btdm8723.val_0x6c8 = 0xffff;
+ btdm8723.val_0x6cc = 0x3;
+
+ /* sw mechanism */
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = false;
+ btdm8723.sw_dac_swing_on = false;
+
+ /* fw mechanism */
+ btdm8723.ps_tdma_on = true;
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "HT20 or Legacy\n");
+ bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+ 47, 0);
+ bt_rssi_state1 = rtl8723ae_dm_bt_check_coex_rssi_state1(hw, 2,
+ 27, 0);
+
+ /* coex table */
+ btdm8723.val_0x6c0 = 0x55555555;
+ btdm8723.val_0x6c8 = 0xffff;
+ btdm8723.val_0x6cc = 0x3;
+
+ /* sw mechanism */
+ if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+ (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi high\n");
+ btdm8723.agc_table_en = true;
+ btdm8723.adc_back_off_on = true;
+ btdm8723.sw_dac_swing_on = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi low\n");
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = false;
+ btdm8723.sw_dac_swing_on = false;
+ }
+
+ /* fw mechanism */
+ btdm8723.ps_tdma_on = true;
+ if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) ||
+ (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi-1 high\n");
+ /* only rssi high we need to do this,
+ * when rssi low, the value will modified by fw
+ */
+ rtl_write_byte(rtlpriv, 0x883, 0x40);
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x83;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x83;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x83;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi-1 low\n");
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ }
+ }
+
+ if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+ btdm8723.dec_bt_pwr = true;
+
+ /* Always ignore WlanAct if bHid|bSCOBusy|bSCOeSCO */
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n",
+ rtlhal->hal_coex_8723.bt_inq_page_start_time,
+ bt_tx_rx_cnt_lvl);
+ if ((rtlhal->hal_coex_8723.bt_inq_page_start_time) ||
+ (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], Set BT inquiry / page scan 0x3a setting\n");
+ btdm8723.ps_tdma_on = true;
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x2;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+
+ if (rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+ rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+}
+
+static void rtl8723ae_dm_bt_2_ant_fta2dp(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct btdm_8723 btdm8723;
+ u8 bt_rssi_state, bt_rssi_state1;
+ u32 bt_tx_rx_cnt_lvl;
+
+ rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+ btdm8723.rf_rx_lpf_shrink = true;
+ btdm8723.low_penalty_rate_adaptive = true;
+ btdm8723.reject_aggre_pkt = false;
+
+ bt_tx_rx_cnt_lvl = rtl8723ae_dm_bt_bt_tx_rx_counter_level(hw);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl);
+
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n");
+ bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+ 37, 0);
+
+ /* coex table */
+ btdm8723.val_0x6c0 = 0x55555555;
+ btdm8723.val_0x6c8 = 0xffff;
+ btdm8723.val_0x6cc = 0x3;
+
+ /* sw mechanism */
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = true;
+ btdm8723.sw_dac_swing_on = false;
+
+ /* fw mechanism */
+ btdm8723.ps_tdma_on = true;
+ if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+ (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi high\n");
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi low\n");
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "HT20 or Legacy\n");
+ bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+ 47, 0);
+ bt_rssi_state1 = rtl8723ae_dm_bt_check_coex_rssi_state1(hw, 2,
+ 27, 0);
+
+ /* coex table */
+ btdm8723.val_0x6c0 = 0x55555555;
+ btdm8723.val_0x6c8 = 0xffff;
+ btdm8723.val_0x6cc = 0x3;
+
+ /* sw mechanism */
+ if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+ (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi high\n");
+ btdm8723.agc_table_en = true;
+ btdm8723.adc_back_off_on = true;
+ btdm8723.sw_dac_swing_on = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi low\n");
+ btdm8723.agc_table_en = false;
+ btdm8723.adc_back_off_on = false;
+ btdm8723.sw_dac_swing_on = false;
+ }
+
+ /* fw mechanism */
+ btdm8723.ps_tdma_on = true;
+ if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) ||
+ (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi-1 high\n");
+ /* only rssi high we need to do this,
+ * when rssi low, the value will modified by fw
+ */
+ rtl_write_byte(rtlpriv, 0x883, 0x40);
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x81;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Wifi rssi-1 low\n");
+ if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xa;
+ btdm8723.ps_tdma_byte[2] = 0xa;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT TxRx Counters < 1200\n");
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0xf;
+ btdm8723.ps_tdma_byte[2] = 0xf;
+ btdm8723.ps_tdma_byte[3] = 0x0;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+ }
+ }
+
+ if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+ btdm8723.dec_bt_pwr = true;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n",
+ rtlhal->hal_coex_8723.bt_inq_page_start_time,
+ bt_tx_rx_cnt_lvl);
+
+ if ((rtlhal->hal_coex_8723.bt_inq_page_start_time) ||
+ (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], Set BT inquiry / page scan 0x3a setting\n");
+ btdm8723.ps_tdma_on = true;
+ btdm8723.ps_tdma_byte[0] = 0xa3;
+ btdm8723.ps_tdma_byte[1] = 0x5;
+ btdm8723.ps_tdma_byte[2] = 0x5;
+ btdm8723.ps_tdma_byte[3] = 0x83;
+ btdm8723.ps_tdma_byte[4] = 0x80;
+ }
+
+ if (rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+ rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+}
+
+static void rtl8723ae_dm_bt_inq_page_monitor(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u32 cur_time = jiffies;
+
+ if (rtlhal->hal_coex_8723.c2h_bt_inquiry_page) {
+ /* bt inquiry or page is started. */
+ if (rtlhal->hal_coex_8723.bt_inq_page_start_time == 0) {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_BT_INQ_PAGE;
+ rtlhal->hal_coex_8723.bt_inq_page_start_time = cur_time;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT Inquiry/page is started at time : 0x%x\n",
+ rtlhal->hal_coex_8723.bt_inq_page_start_time);
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT Inquiry/page started time : 0x%x, cur_time : 0x%x\n",
+ rtlhal->hal_coex_8723.bt_inq_page_start_time, cur_time);
+
+ if (rtlhal->hal_coex_8723.bt_inq_page_start_time) {
+ if ((((long)cur_time -
+ (long)rtlhal->hal_coex_8723.bt_inq_page_start_time) / HZ) >=
+ 10) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BT Inquiry/page >= 10sec!!!");
+ rtlhal->hal_coex_8723.bt_inq_page_start_time = 0;
+ rtlpcipriv->bt_coexist.cstate &=
+ ~BT_COEX_STATE_BT_INQ_PAGE;
+ }
+ }
+}
+
+static void rtl8723ae_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ rtlpcipriv->bt_coexist.cstate &=
+ ~(BT_COEX_STATE_PROFILE_HID | BT_COEX_STATE_PROFILE_A2DP |
+ BT_COEX_STATE_PROFILE_PAN | BT_COEX_STATE_PROFILE_SCO);
+
+ rtlpcipriv->bt_coexist.cstate &=
+ ~(BT_COEX_STATE_BTINFO_COMMON |
+ BT_COEX_STATE_BTINFO_B_HID_SCOESCO |
+ BT_COEX_STATE_BTINFO_B_FTP_A2DP);
+}
+
+static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 bt_retry_cnt;
+ u8 bt_info_original;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex] Get bt info by fw!!\n");
+
+ _rtl8723_dm_bt_check_wifi_state(hw);
+
+ if (rtlhal->hal_coex_8723.c2h_bt_info_req_sent) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex] c2h for btInfo not rcvd yet!!\n");
+ }
+
+ bt_retry_cnt = rtlhal->hal_coex_8723.bt_retry_cnt;
+ bt_info_original = rtlhal->hal_coex_8723.c2h_bt_info_original;
+
+ /* when bt inquiry or page scan, we have to set h2c 0x25
+ * ignore wlanact for continuous 4x2secs
+ */
+ rtl8723ae_dm_bt_inq_page_monitor(hw);
+ rtl8723ae_dm_bt_reset_action_profile_state(hw);
+
+ if (rtl8723ae_dm_bt_is_2_ant_common_action(hw)) {
+ rtlpcipriv->bt_coexist.bt_profile_case = BT_COEX_MECH_COMMON;
+ rtlpcipriv->bt_coexist.bt_profile_action = BT_COEX_MECH_COMMON;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Action 2-Ant common.\n");
+ } else {
+ if ((bt_info_original & BTINFO_B_HID) ||
+ (bt_info_original & BTINFO_B_SCO_BUSY) ||
+ (bt_info_original & BTINFO_B_SCO_ESCO)) {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_BTINFO_B_HID_SCOESCO;
+ rtlpcipriv->bt_coexist.bt_profile_case =
+ BT_COEX_MECH_HID_SCO_ESCO;
+ rtlpcipriv->bt_coexist.bt_profile_action =
+ BT_COEX_MECH_HID_SCO_ESCO;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BTInfo: bHid|bSCOBusy|bSCOeSCO\n");
+ rtl8723ae_dm_bt_2_ant_hid_sco_esco(hw);
+ } else if ((bt_info_original & BTINFO_B_FTP) ||
+ (bt_info_original & BTINFO_B_A2DP)) {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_BTINFO_B_FTP_A2DP;
+ rtlpcipriv->bt_coexist.bt_profile_case =
+ BT_COEX_MECH_FTP_A2DP;
+ rtlpcipriv->bt_coexist.bt_profile_action =
+ BT_COEX_MECH_FTP_A2DP;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "BTInfo: bFTP|bA2DP\n");
+ rtl8723ae_dm_bt_2_ant_fta2dp(hw);
+ } else {
+ rtlpcipriv->bt_coexist.cstate |=
+ BT_COEX_STATE_BTINFO_B_HID_SCOESCO;
+ rtlpcipriv->bt_coexist.bt_profile_case =
+ BT_COEX_MECH_NONE;
+ rtlpcipriv->bt_coexist.bt_profile_action =
+ BT_COEX_MECH_NONE;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], BTInfo: undefined case!!!!\n");
+ rtl8723ae_dm_bt_2_ant_hid_sco_esco(hw);
+ }
+ }
+}
+
+static void _rtl8723ae_dm_bt_coexist_1_ant(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+ rtl8723ae_dm_bt_set_coex_table(hw, 0x5a5aaaaa, 0xcc, 0x3);
+ rtl8723ae_dm_bt_set_hw_pta_mode(hw, true);
+}
+
+void rtl8723ae_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+ rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw, false);
+ rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+ rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+ rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, false,
+ TDMA_2ANT, TDMA_NAV_OFF);
+ rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, TDMA_2ANT,
+ TDMA_NAV_OFF, TDMA_DAC_SWING_OFF);
+ rtl8723ae_dm_bt_set_fw_dac_swing_level(hw, 0);
+ rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+ rtl8723ae_dm_bt_set_fw_bt_retry_index(hw, 2);
+ rtl8723ae_dm_bt_set_fw_wlan_act(hw, 0x10, 0x10);
+ rtl8723ae_dm_bt_set_fw_dec_bt_pwr(hw, false);
+}
+
+void rtl8723ae_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+ rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_OFF);
+ rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_OFF);
+ rtl8723ae_dm_bt_reject_ap_aggregated_packet(hw, false);
+
+ rtl8723ae_bt_set_penalty_tx_rate_adap(hw, BT_TX_RATE_ADAPTIVE_NORMAL);
+ rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw, BT_RF_RX_LPF_CORNER_RESUME);
+ rtl8723ae_dm_bt_set_sw_full_time_dac_swing(hw, false, 0xc0);
+}
+
+static void rtl8723ae_dm_bt_query_bt_information(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ u8 h2c_parameter[1] = {0};
+
+ rtlhal->hal_coex_8723.c2h_bt_info_req_sent = true;
+
+ h2c_parameter[0] |= BIT(0);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "Query Bt information, write 0x38 = 0x%x\n",
+ h2c_parameter[0]);
+
+ rtl8723ae_fill_h2c_cmd(hw, 0x38, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_bt_hw_counters_monitor(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u32 reg_htx_rx, reg_ltx_rx, u32_tmp;
+ u32 reg_htx, reg_hrx, reg_ltx, reg_lrx;
+
+ reg_htx_rx = REG_HIGH_PRIORITY_TXRX;
+ reg_ltx_rx = REG_LOW_PRIORITY_TXRX;
+
+ u32_tmp = rtl_read_dword(rtlpriv, reg_htx_rx);
+ reg_htx = u32_tmp & MASKLWORD;
+ reg_hrx = (u32_tmp & MASKHWORD)>>16;
+
+ u32_tmp = rtl_read_dword(rtlpriv, reg_ltx_rx);
+ reg_ltx = u32_tmp & MASKLWORD;
+ reg_lrx = (u32_tmp & MASKHWORD)>>16;
+
+ if (rtlpcipriv->bt_coexist.lps_counter > 1) {
+ reg_htx %= rtlpcipriv->bt_coexist.lps_counter;
+ reg_hrx %= rtlpcipriv->bt_coexist.lps_counter;
+ reg_ltx %= rtlpcipriv->bt_coexist.lps_counter;
+ reg_lrx %= rtlpcipriv->bt_coexist.lps_counter;
+ }
+
+ rtlhal->hal_coex_8723.high_priority_tx = reg_htx;
+ rtlhal->hal_coex_8723.high_priority_rx = reg_hrx;
+ rtlhal->hal_coex_8723.low_priority_tx = reg_ltx;
+ rtlhal->hal_coex_8723.low_priority_rx = reg_lrx;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "High Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n",
+ reg_htx_rx, reg_htx, reg_htx, reg_hrx, reg_hrx);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Low Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n",
+ reg_ltx_rx, reg_ltx, reg_ltx, reg_lrx, reg_lrx);
+ rtlpcipriv->bt_coexist.lps_counter = 0;
+}
+
+static void rtl8723ae_dm_bt_bt_enable_disable_check(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ bool bt_alife = true;
+
+ if (rtlhal->hal_coex_8723.high_priority_tx == 0 &&
+ rtlhal->hal_coex_8723.high_priority_rx == 0 &&
+ rtlhal->hal_coex_8723.low_priority_tx == 0 &&
+ rtlhal->hal_coex_8723.low_priority_rx == 0)
+ bt_alife = false;
+ if (rtlhal->hal_coex_8723.high_priority_tx == 0xeaea &&
+ rtlhal->hal_coex_8723.high_priority_rx == 0xeaea &&
+ rtlhal->hal_coex_8723.low_priority_tx == 0xeaea &&
+ rtlhal->hal_coex_8723.low_priority_rx == 0xeaea)
+ bt_alife = false;
+ if (rtlhal->hal_coex_8723.high_priority_tx == 0xffff &&
+ rtlhal->hal_coex_8723.high_priority_rx == 0xffff &&
+ rtlhal->hal_coex_8723.low_priority_tx == 0xffff &&
+ rtlhal->hal_coex_8723.low_priority_rx == 0xffff)
+ bt_alife = false;
+ if (bt_alife) {
+ rtlpcipriv->bt_coexist.bt_active_zero_cnt = 0;
+ rtlpcipriv->bt_coexist.cur_bt_disabled = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "8723A BT is enabled !!\n");
+ } else {
+ rtlpcipriv->bt_coexist.bt_active_zero_cnt++;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "8723A bt all counters = 0, %d times!!\n",
+ rtlpcipriv->bt_coexist.bt_active_zero_cnt);
+ if (rtlpcipriv->bt_coexist.bt_active_zero_cnt >= 2) {
+ rtlpcipriv->bt_coexist.cur_bt_disabled = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "8723A BT is disabled !!\n");
+ }
+ }
+ if (rtlpcipriv->bt_coexist.pre_bt_disabled !=
+ rtlpcipriv->bt_coexist.cur_bt_disabled) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "8723A BT is from %s to %s!!\n",
+ (rtlpcipriv->bt_coexist.pre_bt_disabled ?
+ "disabled" : "enabled"),
+ (rtlpcipriv->bt_coexist.cur_bt_disabled ?
+ "disabled" : "enabled"));
+ rtlpcipriv->bt_coexist.pre_bt_disabled
+ = rtlpcipriv->bt_coexist.cur_bt_disabled;
+ }
+}
+
+
+void rtl8723ae_dm_bt_coexist_8723(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+ rtl8723ae_dm_bt_query_bt_information(hw);
+ rtl8723ae_dm_bt_bt_hw_counters_monitor(hw);
+ rtl8723ae_dm_bt_bt_enable_disable_check(hw);
+
+ if (rtlpcipriv->bt_coexist.bt_ant_num == ANT_X2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], 2 Ant mechanism\n");
+ _rtl8723ae_dm_bt_coexist_2_ant(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "[BTCoex], 1 Ant mechanism\n");
+ _rtl8723ae_dm_bt_coexist_1_ant(hw);
+ }
+
+ if (!rtl8723ae_dm_bt_is_same_coexist_state(hw)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTCoex], Coexist State[bitMap] change from 0x%x%8x to 0x%x%8x\n",
+ rtlpcipriv->bt_coexist.previous_state_h,
+ rtlpcipriv->bt_coexist.previous_state,
+ rtlpcipriv->bt_coexist.cstate_h,
+ rtlpcipriv->bt_coexist.cstate);
+ rtlpcipriv->bt_coexist.previous_state
+ = rtlpcipriv->bt_coexist.cstate;
+ rtlpcipriv->bt_coexist.previous_state_h
+ = rtlpcipriv->bt_coexist.cstate_h;
+ }
+}
+
+static void rtl8723ae_dm_bt_parse_bt_info(struct ieee80211_hw *hw,
+ u8 *tmbuf, u8 len)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+ u8 bt_info;
+ u8 i;
+
+ rtlhal->hal_coex_8723.c2h_bt_info_req_sent = false;
+ rtlhal->hal_coex_8723.bt_retry_cnt = 0;
+ for (i = 0; i < len; i++) {
+ if (i == 0)
+ rtlhal->hal_coex_8723.c2h_bt_info_original = tmbuf[i];
+ else if (i == 1)
+ rtlhal->hal_coex_8723.bt_retry_cnt = tmbuf[i];
+ if (i == len-1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "0x%2x]", tmbuf[i]);
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "0x%2x, ", tmbuf[i]);
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "BT info bt_info (Data)= 0x%x\n",
+ rtlhal->hal_coex_8723.c2h_bt_info_original);
+ bt_info = rtlhal->hal_coex_8723.c2h_bt_info_original;
+
+ if (bt_info & BIT(2))
+ rtlhal->hal_coex_8723.c2h_bt_inquiry_page = true;
+ else
+ rtlhal->hal_coex_8723.c2h_bt_inquiry_page = false;
+
+ if (bt_info & BTINFO_B_CONNECTION) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTC2H], BTInfo: bConnect=true\n");
+ rtlpcipriv->bt_coexist.bt_busy = true;
+ rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_BT_IDLE;
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "[BTC2H], BTInfo: bConnect=false\n");
+ rtlpcipriv->bt_coexist.bt_busy = false;
+ rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BT_IDLE;
+ }
+}
+void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct c2h_evt_hdr c2h_event;
+ u8 *ptmbuf;
+ u8 index;
+ u8 u1tmp;
+
+ memset(&c2h_event, 0, sizeof(c2h_event));
+ u1tmp = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL);
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ "&&&&&&: REG_C2HEVT_MSG_NORMAL is 0x%x\n", u1tmp);
+ c2h_event.cmd_id = u1tmp & 0xF;
+ c2h_event.cmd_len = (u1tmp & 0xF0) >> 4;
+ c2h_event.cmd_seq = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL + 1);
+ RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+ "cmd_id: %d, cmd_len: %d, cmd_seq: %d\n",
+ c2h_event.cmd_id , c2h_event.cmd_len, c2h_event.cmd_seq);
+ u1tmp = rtl_read_byte(rtlpriv, 0x01AF);
+ if (u1tmp == C2H_EVT_HOST_CLOSE) {
+ return;
+ } else if (u1tmp != C2H_EVT_FW_CLOSE) {
+ rtl_write_byte(rtlpriv, 0x1AF, 0x00);
+ return;
+ }
+ ptmbuf = kmalloc(c2h_event.cmd_len, GFP_KERNEL);
+ if (ptmbuf == NULL) {
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "malloc cmd buf failed\n");
+ return;
+ }
+
+ /* Read the content */
+ for (index = 0; index < c2h_event.cmd_len; index++)
+ ptmbuf[index] = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL +
+ 2 + index);
+
+ switch (c2h_event.cmd_id) {
+ case C2H_BT_RSSI:
+ break;
+
+ case C2H_BT_OP_MODE:
+ break;
+
+ case BT_INFO:
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "BT info Byte[0] (ID) is 0x%x\n", c2h_event.cmd_id);
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "BT info Byte[1] (Seq) is 0x%x\n", c2h_event.cmd_seq);
+ RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+ "BT info Byte[2] (Data)= 0x%x\n", ptmbuf[0]);
+
+ rtl8723ae_dm_bt_parse_bt_info(hw, ptmbuf, c2h_event.cmd_len);
+ break;
+ default:
+ break;
+ }
+ kfree(ptmbuf);
+
+ rtl_write_byte(rtlpriv, 0x01AF, C2H_EVT_HOST_CLOSE);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
new file mode 100644
index 000000000000..4325ecd58f0c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL8723E_HAL_BTC_H__
+#define __RTL8723E_HAL_BTC_H__
+
+#include "../wifi.h"
+#include "btc.h"
+#include "hal_bt_coexist.h"
+
+#define BT_TXRX_CNT_THRES_1 1200
+#define BT_TXRX_CNT_THRES_2 1400
+#define BT_TXRX_CNT_THRES_3 3000
+#define BT_TXRX_CNT_LEVEL_0 0 /* < 1200 */
+#define BT_TXRX_CNT_LEVEL_1 1 /* >= 1200 && < 1400 */
+#define BT_TXRX_CNT_LEVEL_2 2 /* >= 1400 */
+#define BT_TXRX_CNT_LEVEL_3 3
+
+/* TDMA mode definition */
+#define TDMA_2ANT 0
+#define TDMA_1ANT 1
+#define TDMA_NAV_OFF 0
+#define TDMA_NAV_ON 1
+#define TDMA_DAC_SWING_OFF 0
+#define TDMA_DAC_SWING_ON 1
+
+/* PTA mode related definition */
+#define BT_PTA_MODE_OFF 0
+#define BT_PTA_MODE_ON 1
+
+/* Penalty Tx Rate Adaptive */
+#define BT_TX_RATE_ADAPTIVE_NORMAL 0
+#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1
+
+/* RF Corner */
+#define BT_RF_RX_LPF_CORNER_RESUME 0
+#define BT_RF_RX_LPF_CORNER_SHRINK 1
+
+#define C2H_EVT_HOST_CLOSE 0x00
+#define C2H_EVT_FW_CLOSE 0xFF
+
+enum bt_traffic_mode {
+ BT_MOTOR_EXT_BE = 0x00,
+ BT_MOTOR_EXT_GUL = 0x01,
+ BT_MOTOR_EXT_GUB = 0x02,
+ BT_MOTOR_EXT_GULB = 0x03
+};
+
+enum bt_traffic_mode_profile {
+ BT_PROFILE_NONE,
+ BT_PROFILE_A2DP,
+ BT_PROFILE_PAN,
+ BT_PROFILE_HID,
+ BT_PROFILE_SCO
+};
+
+enum hci_ext_bt_operation {
+ HCI_BT_OP_NONE = 0x0,
+ HCI_BT_OP_INQUIRE_START = 0x1,
+ HCI_BT_OP_INQUIRE_FINISH = 0x2,
+ HCI_BT_OP_PAGING_START = 0x3,
+ HCI_BT_OP_PAGING_SUCCESS = 0x4,
+ HCI_BT_OP_PAGING_UNSUCCESS = 0x5,
+ HCI_BT_OP_PAIRING_START = 0x6,
+ HCI_BT_OP_PAIRING_FINISH = 0x7,
+ HCI_BT_OP_BT_DEV_ENABLE = 0x8,
+ HCI_BT_OP_BT_DEV_DISABLE = 0x9,
+ HCI_BT_OP_MAX,
+};
+
+enum bt_spec {
+ BT_SPEC_1_0_b = 0x00,
+ BT_SPEC_1_1 = 0x01,
+ BT_SPEC_1_2 = 0x02,
+ BT_SPEC_2_0_EDR = 0x03,
+ BT_SPEC_2_1_EDR = 0x04,
+ BT_SPEC_3_0_HS = 0x05,
+ BT_SPEC_4_0 = 0x06
+};
+
+struct c2h_evt_hdr {
+ u8 cmd_id;
+ u8 cmd_len;
+ u8 cmd_seq;
+};
+
+enum bt_state {
+ BT_INFO_STATE_DISABLED = 0,
+ BT_INFO_STATE_NO_CONNECTION = 1,
+ BT_INFO_STATE_CONNECT_IDLE = 2,
+ BT_INFO_STATE_INQ_OR_PAG = 3,
+ BT_INFO_STATE_ACL_ONLY_BUSY = 4,
+ BT_INFO_STATE_SCO_ONLY_BUSY = 5,
+ BT_INFO_STATE_ACL_SCO_BUSY = 6,
+ BT_INFO_STATE_HID_BUSY = 7,
+ BT_INFO_STATE_HID_SCO_BUSY = 8,
+ BT_INFO_STATE_MAX = 7
+};
+
+enum rtl8723ae_c2h_evt {
+ C2H_DBG = 0,
+ C2H_TSF = 1,
+ C2H_AP_RPT_RSP = 2,
+ C2H_CCX_TX_RPT = 3, /* The FW notify the report of the specific */
+ /* tx packet. */
+ C2H_BT_RSSI = 4,
+ C2H_BT_OP_MODE = 5,
+ C2H_HW_INFO_EXCH = 10,
+ C2H_C2H_H2C_TEST = 11,
+ BT_INFO = 12,
+ MAX_C2HEVENT
+};
+
+void rtl8723ae_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_coexist_8723(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw,
+ struct btdm_8723 *p_btdm);
+void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw);
+void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw,
+ bool mstatus);
+void rtl8723ae_bt_coex_off_before_lps(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
new file mode 100644
index 000000000000..0a8c03863fb2
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
@@ -0,0 +1,2380 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "led.h"
+#include "hw.h"
+#include "pwrseqcmd.h"
+#include "pwrseq.h"
+#include "btc.h"
+
+static void _rtl8723ae_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+ u8 set_bits, u8 clear_bits)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpci->reg_bcn_ctrl_val |= set_bits;
+ rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl8723ae_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte &= ~(BIT(0));
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl8723ae_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmp1byte;
+
+ tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+ tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+ tmp1byte |= BIT(1);
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl8723ae_enable_bcn_sufunc(struct ieee80211_hw *hw)
+{
+ _rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl8723ae_disable_bcn_sufunc(struct ieee80211_hw *hw)
+{
+ _rtl8723ae_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+void rtl8723ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ switch (variable) {
+ case HW_VAR_RCR:
+ *((u32 *) (val)) = rtlpci->receive_config;
+ break;
+ case HW_VAR_RF_STATE:
+ *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+ break;
+ case HW_VAR_FWLPS_RF_ON:{
+ enum rf_pwrstate rfState;
+ u32 val_rcr;
+
+ rtlpriv->cfg->ops->get_hw_reg(hw,
+ HW_VAR_RF_STATE,
+ (u8 *) (&rfState));
+ if (rfState == ERFOFF) {
+ *((bool *) (val)) = true;
+ } else {
+ val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+ val_rcr &= 0x00070000;
+ if (val_rcr)
+ *((bool *) (val)) = false;
+ else
+ *((bool *) (val)) = true;
+ }
+ break; }
+ case HW_VAR_FW_PSMODE_STATUS:
+ *((bool *) (val)) = ppsc->fw_current_inpsmode;
+ break;
+ case HW_VAR_CORRECT_TSF:{
+ u64 tsf;
+ u32 *ptsf_low = (u32 *)&tsf;
+ u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+ *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+ *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+
+ *((u64 *) (val)) = tsf;
+
+ break; }
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+}
+
+void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ u8 idx;
+
+ switch (variable) {
+ case HW_VAR_ETHER_ADDR:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_MACID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_BASIC_RATE:{
+ u16 rate_cfg = ((u16 *) val)[0];
+ u8 rate_index = 0;
+ rate_cfg = rate_cfg & 0x15f;
+ rate_cfg |= 0x01;
+ rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+ rtl_write_byte(rtlpriv, REG_RRSR + 1,
+ (rate_cfg >> 8) & 0xff);
+ while (rate_cfg > 0x1) {
+ rate_cfg = (rate_cfg >> 1);
+ rate_index++;
+ }
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+ rate_index);
+ break; }
+ case HW_VAR_BSSID:
+ for (idx = 0; idx < ETH_ALEN; idx++) {
+ rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+ val[idx]);
+ }
+ break;
+ case HW_VAR_SIFS:
+ rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
+
+ rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+ rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+
+ if (!mac->ht_enable)
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ 0x0e0e);
+ else
+ rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+ *((u16 *) val));
+ break;
+ case HW_VAR_SLOT_TIME:{
+ u8 e_aci;
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ "HW_VAR_SLOT_TIME %x\n", val[0]);
+
+ rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+
+ for (e_aci = 0; e_aci < AC_MAX; e_aci++) {
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_AC_PARAM,
+ (u8 *) (&e_aci));
+ }
+ break; }
+ case HW_VAR_ACK_PREAMBLE:{
+ u8 reg_tmp;
+ u8 short_preamble = (bool) (*(u8 *) val);
+ reg_tmp = (mac->cur_40_prime_sc) << 5;
+ if (short_preamble)
+ reg_tmp |= 0x80;
+
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+ break; }
+ case HW_VAR_AMPDU_MIN_SPACE:{
+ u8 min_spacing_to_set;
+ u8 sec_min_space;
+
+ min_spacing_to_set = *((u8 *) val);
+ if (min_spacing_to_set <= 7) {
+ sec_min_space = 0;
+
+ if (min_spacing_to_set < sec_min_space)
+ min_spacing_to_set = sec_min_space;
+
+ mac->min_space_cfg = ((mac->min_space_cfg &
+ 0xf8) |
+ min_spacing_to_set);
+
+ *val = min_spacing_to_set;
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+ mac->min_space_cfg);
+
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+ }
+ break; }
+ case HW_VAR_SHORTGI_DENSITY:{
+ u8 density_to_set;
+
+ density_to_set = *((u8 *) val);
+ mac->min_space_cfg |= (density_to_set << 3);
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ "Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+ mac->min_space_cfg);
+
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+ mac->min_space_cfg);
+
+ break; }
+ case HW_VAR_AMPDU_FACTOR:{
+ u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9};
+ u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97};
+ u8 factor_toset;
+ u8 *p_regtoset = NULL;
+ u8 index;
+
+ if ((pcipriv->bt_coexist.bt_coexistence) &&
+ (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+ p_regtoset = regtoset_bt;
+ else
+ p_regtoset = regtoset_normal;
+
+ factor_toset = *((u8 *) val);
+ if (factor_toset <= 3) {
+ factor_toset = (1 << (factor_toset + 2));
+ if (factor_toset > 0xf)
+ factor_toset = 0xf;
+
+ for (index = 0; index < 4; index++) {
+ if ((p_regtoset[index] & 0xf0) >
+ (factor_toset << 4))
+ p_regtoset[index] =
+ (p_regtoset[index] & 0x0f) |
+ (factor_toset << 4);
+
+ if ((p_regtoset[index] & 0x0f) >
+ factor_toset)
+ p_regtoset[index] =
+ (p_regtoset[index] & 0xf0) |
+ (factor_toset);
+
+ rtl_write_byte(rtlpriv,
+ (REG_AGGLEN_LMT + index),
+ p_regtoset[index]);
+
+ }
+
+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+ "Set HW_VAR_AMPDU_FACTOR: %#x\n",
+ factor_toset);
+ }
+ break; }
+ case HW_VAR_AC_PARAM:{
+ u8 e_aci = *((u8 *) val);
+ rtl8723ae_dm_init_edca_turbo(hw);
+
+ if (rtlpci->acm_method != eAcmWay2_SW)
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_ACM_CTRL,
+ (u8 *) (&e_aci));
+ break; }
+ case HW_VAR_ACM_CTRL:{
+ u8 e_aci = *((u8 *) val);
+ union aci_aifsn *p_aci_aifsn =
+ (union aci_aifsn *)(&(mac->ac[0].aifs));
+ u8 acm = p_aci_aifsn->f.acm;
+ u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+ acm_ctrl |= ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
+
+ if (acm) {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl |= AcmHw_BeqEn;
+ break;
+ case AC2_VI:
+ acm_ctrl |= AcmHw_ViqEn;
+ break;
+ case AC3_VO:
+ acm_ctrl |= AcmHw_VoqEn;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
+ acm);
+ break;
+ }
+ } else {
+ switch (e_aci) {
+ case AC0_BE:
+ acm_ctrl &= (~AcmHw_BeqEn);
+ break;
+ case AC2_VI:
+ acm_ctrl &= (~AcmHw_ViqEn);
+ break;
+ case AC3_VO:
+ acm_ctrl &= (~AcmHw_BeqEn);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ break;
+ }
+ }
+
+ RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+ "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
+ acm_ctrl);
+ rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+ break; }
+ case HW_VAR_RCR:
+ rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+ rtlpci->receive_config = ((u32 *) (val))[0];
+ break;
+ case HW_VAR_RETRY_LIMIT:{
+ u8 retry_limit = ((u8 *) (val))[0];
+
+ rtl_write_word(rtlpriv, REG_RL,
+ retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+ retry_limit << RETRY_LIMIT_LONG_SHIFT);
+ break; }
+ case HW_VAR_DUAL_TSF_RST:
+ rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+ break;
+ case HW_VAR_EFUSE_BYTES:
+ rtlefuse->efuse_usedbytes = *((u16 *) val);
+ break;
+ case HW_VAR_EFUSE_USAGE:
+ rtlefuse->efuse_usedpercentage = *((u8 *) val);
+ break;
+ case HW_VAR_IO_CMD:
+ rtl8723ae_phy_set_io_cmd(hw, (*(enum io_type *)val));
+ break;
+ case HW_VAR_WPA_CONFIG:
+ rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+ break;
+ case HW_VAR_SET_RPWM:{
+ u8 rpwm_val;
+
+ rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM);
+ udelay(1);
+
+ if (rpwm_val & BIT(7)) {
+ rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+ (*(u8 *) val));
+ } else {
+ rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+ ((*(u8 *) val) | BIT(7)));
+ }
+
+ break; }
+ case HW_VAR_H2C_FW_PWRMODE:{
+ u8 psmode = (*(u8 *) val);
+
+ if (psmode != FW_PS_ACTIVE_MODE)
+ rtl8723ae_dm_rf_saving(hw, true);
+
+ rtl8723ae_set_fw_pwrmode_cmd(hw, (*(u8 *) val));
+ break; }
+ case HW_VAR_FW_PSMODE_STATUS:
+ ppsc->fw_current_inpsmode = *((bool *) val);
+ break;
+ case HW_VAR_H2C_FW_JOINBSSRPT:{
+ u8 mstatus = (*(u8 *) val);
+ u8 tmp_regcr, tmp_reg422;
+ bool recover = false;
+
+ if (mstatus == RT_MEDIA_CONNECT) {
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
+
+ tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr | BIT(0)));
+
+ _rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(3));
+ _rtl8723ae_set_bcn_ctrl_reg(hw, BIT(4), 0);
+
+ tmp_reg422 = rtl_read_byte(rtlpriv,
+ REG_FWHW_TXQ_CTRL + 2);
+ if (tmp_reg422 & BIT(6))
+ recover = true;
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422 & (~BIT(6)));
+
+ rtl8723ae_set_fw_rsvdpagepkt(hw, 0);
+
+ _rtl8723ae_set_bcn_ctrl_reg(hw, BIT(3), 0);
+ _rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(4));
+
+ if (recover)
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+ tmp_reg422);
+
+ rtl_write_byte(rtlpriv, REG_CR + 1,
+ (tmp_regcr & ~(BIT(0))));
+ }
+ rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+
+ break; }
+ case HW_VAR_AID:{
+ u16 u2btmp;
+ u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+ u2btmp &= 0xC000;
+ rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
+ mac->assoc_id));
+ break; }
+ case HW_VAR_CORRECT_TSF:{
+ u8 btype_ibss = ((u8 *) (val))[0];
+
+ if (btype_ibss == true)
+ _rtl8723ae_stop_tx_beacon(hw);
+
+ _rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(3));
+
+ rtl_write_dword(rtlpriv, REG_TSFTR,
+ (u32) (mac->tsf & 0xffffffff));
+ rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+ (u32) ((mac->tsf >> 32) & 0xffffffff));
+
+ _rtl8723ae_set_bcn_ctrl_reg(hw, BIT(3), 0);
+
+ if (btype_ibss == true)
+ _rtl8723ae_resume_tx_beacon(hw);
+ break; }
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ break;
+ }
+}
+
+static bool _rtl8723ae_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ bool status = true;
+ long count = 0;
+ u32 value = _LLT_INIT_ADDR(address) |
+ _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+ rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+
+ do {
+ value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+ if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+ break;
+
+ if (count > POLLING_LLT_THRESHOLD) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Failed to polling write LLT done at address %d!\n",
+ address);
+ status = false;
+ break;
+ }
+ } while (++count);
+
+ return status;
+}
+
+static bool _rtl8723ae_llt_table_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ unsigned short i;
+ u8 txpktbuf_bndy;
+ u8 maxPage;
+ bool status;
+ u8 ubyte;
+
+ maxPage = 255;
+ txpktbuf_bndy = 246;
+
+ rtl_write_byte(rtlpriv, REG_CR, 0x8B);
+
+ rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000);
+
+ rtl_write_dword(rtlpriv, REG_RQPN, 0x80ac1c29);
+ rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x03);
+
+ rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy));
+ rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+ rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+ rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+ rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+ rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+ for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+ status = _rtl8723ae_llt_write(hw, i, i + 1);
+ if (true != status)
+ return status;
+ }
+
+ status = _rtl8723ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+ if (true != status)
+ return status;
+
+ for (i = txpktbuf_bndy; i < maxPage; i++) {
+ status = _rtl8723ae_llt_write(hw, i, (i + 1));
+ if (true != status)
+ return status;
+ }
+
+ status = _rtl8723ae_llt_write(hw, maxPage, txpktbuf_bndy);
+ if (true != status)
+ return status;
+
+ rtl_write_byte(rtlpriv, REG_CR, 0xff);
+ ubyte = rtl_read_byte(rtlpriv, REG_RQPN + 3);
+ rtl_write_byte(rtlpriv, REG_RQPN + 3, ubyte | BIT(7));
+
+ return true;
+}
+
+static void _rtl8723ae_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+ if (rtlpriv->rtlhal.up_first_time)
+ return;
+
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ rtl8723ae_sw_led_on(hw, pLed0);
+ else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+ rtl8723ae_sw_led_on(hw, pLed0);
+ else
+ rtl8723ae_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl8712e_init_mac(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ unsigned char bytetmp;
+ unsigned short wordtmp;
+ u16 retry = 0;
+ u16 tmpu2b;
+ bool mac_func_enable;
+
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+ bytetmp = rtl_read_byte(rtlpriv, REG_CR);
+ if (bytetmp == 0xFF)
+ mac_func_enable = true;
+ else
+ mac_func_enable = false;
+
+
+ /* HW Power on sequence */
+ if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+ PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW))
+ return false;
+
+ bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2);
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp | BIT(4));
+
+ /* eMAC time out function enable, 0x369[7]=1 */
+ bytetmp = rtl_read_byte(rtlpriv, 0x369);
+ rtl_write_byte(rtlpriv, 0x369, bytetmp | BIT(7));
+
+ /* ePHY reg 0x1e bit[4]=1 using MDIO interface,
+ * we should do this before Enabling ASPM backdoor.
+ */
+ do {
+ rtl_write_word(rtlpriv, 0x358, 0x5e);
+ udelay(100);
+ rtl_write_word(rtlpriv, 0x356, 0xc280);
+ rtl_write_word(rtlpriv, 0x354, 0xc290);
+ rtl_write_word(rtlpriv, 0x358, 0x3e);
+ udelay(100);
+ rtl_write_word(rtlpriv, 0x358, 0x5e);
+ udelay(100);
+ tmpu2b = rtl_read_word(rtlpriv, 0x356);
+ retry++;
+ } while (tmpu2b != 0xc290 && retry < 100);
+
+ if (retry >= 100) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "InitMAC(): ePHY configure fail!!!\n");
+ return false;
+ }
+
+ rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+ rtl_write_word(rtlpriv, REG_CR + 1, 0x06);
+
+ if (!mac_func_enable) {
+ if (_rtl8723ae_llt_table_init(hw) == false)
+ return false;
+ }
+
+ rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+ rtl_write_byte(rtlpriv, REG_HISRE, 0xff);
+
+ rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff);
+
+ wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0xf;
+ wordtmp |= 0xF771;
+ rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+ rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF);
+ rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+ rtl_write_byte(rtlpriv, 0x4d0, 0x0);
+
+ rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+ ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) &
+ DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_MGQ_DESA,
+ (u64) rtlpci->tx_ring[MGNT_QUEUE].dma &
+ DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_VOQ_DESA,
+ (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_VIQ_DESA,
+ (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_BEQ_DESA,
+ (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_BKQ_DESA,
+ (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_HQ_DESA,
+ (u64) rtlpci->tx_ring[HIGH_QUEUE].dma &
+ DMA_BIT_MASK(32));
+ rtl_write_dword(rtlpriv, REG_RX_DESA,
+ (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
+ DMA_BIT_MASK(32));
+
+ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x74);
+
+ rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6));
+ do {
+ retry++;
+ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+ } while ((retry < 200) && (bytetmp & BIT(7)));
+
+ _rtl8723ae_gen_refresh_led_state(hw);
+
+ rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+
+ return true;
+}
+
+static void _rtl8723ae_hw_configure(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ u8 reg_bw_opmode;
+ u32 reg_ratr, reg_prsr;
+
+ reg_bw_opmode = BW_OPMODE_20MHZ;
+ reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
+ RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+ reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+
+ rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
+
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+
+ rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr);
+
+ rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+
+ rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0);
+
+ rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80);
+
+ rtl_write_word(rtlpriv, REG_RL, 0x0707);
+
+ rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802);
+
+ rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+
+ rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
+ rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
+ rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
+
+ if ((pcipriv->bt_coexist.bt_coexistence) &&
+ (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431);
+ else
+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
+
+ rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2);
+
+ rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff);
+
+ rtlpci->reg_bcn_ctrl_val = 0x1f;
+ rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
+
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+
+ rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+
+ rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+ rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+
+ if ((pcipriv->bt_coexist.bt_coexistence) &&
+ (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+ rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402);
+ } else {
+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+ }
+
+ if ((pcipriv->bt_coexist.bt_coexistence) &&
+ (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+ rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666);
+ else
+ rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666);
+
+ rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+
+ rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010);
+ rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010);
+
+ rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010);
+
+ rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010);
+
+ rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff);
+ rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff);
+
+ rtl_write_dword(rtlpriv, 0x394, 0x1);
+}
+
+static void _rtl8723ae_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ rtl_write_byte(rtlpriv, 0x34b, 0x93);
+ rtl_write_word(rtlpriv, 0x350, 0x870c);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+
+ if (ppsc->support_backdoor)
+ rtl_write_byte(rtlpriv, 0x349, 0x1b);
+ else
+ rtl_write_byte(rtlpriv, 0x349, 0x03);
+
+ rtl_write_word(rtlpriv, 0x350, 0x2718);
+ rtl_write_byte(rtlpriv, 0x352, 0x1);
+}
+
+void rtl8723ae_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 sec_reg_value;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+ rtlpriv->sec.pairwise_enc_algorithm,
+ rtlpriv->sec.group_enc_algorithm);
+
+ if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "not open hw encryption\n");
+ return;
+ }
+
+ sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable;
+
+ if (rtlpriv->sec.use_defaultkey) {
+ sec_reg_value |= SCR_TxUseDK;
+ sec_reg_value |= SCR_RxUseDK;
+ }
+
+ sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+
+ rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "The SECR-value %x\n", sec_reg_value);
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+
+}
+
+int rtl8723ae_hw_init(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ bool rtstatus = true;
+ int err;
+ u8 tmp_u1b;
+
+ rtlpriv->rtlhal.being_init_adapter = true;
+ rtlpriv->intf_ops->disable_aspm(hw);
+ rtstatus = _rtl8712e_init_mac(hw);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
+ err = 1;
+ return err;
+ }
+
+ err = rtl8723ae_download_fw(hw);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "Failed to download FW. Init HW without FW now..\n");
+ err = 1;
+ rtlhal->fw_ready = false;
+ return err;
+ } else {
+ rtlhal->fw_ready = true;
+ }
+
+ rtlhal->last_hmeboxnum = 0;
+ rtl8723ae_phy_mac_config(hw);
+ /* because the last function modifies RCR, we update
+ * rcr var here, or TP will be unstable as ther receive_config
+ * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
+ * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
+ */
+ rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+ rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+ rtl8723ae_phy_bb_config(hw);
+ rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+ rtl8723ae_phy_rf_config(hw);
+ if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) {
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+ } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+ }
+ rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+ RF_CHNLBW, RFREG_OFFSET_MASK);
+ rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+ RF_CHNLBW, RFREG_OFFSET_MASK);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+ _rtl8723ae_hw_configure(hw);
+ rtl_cam_reset_all_entry(hw);
+ rtl8723ae_enable_hw_security_config(hw);
+
+ ppsc->rfpwr_state = ERFON;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+ _rtl8723ae_enable_aspm_back_door(hw);
+ rtlpriv->intf_ops->enable_aspm(hw);
+
+ rtl8723ae_bt_hw_init(hw);
+
+ if (ppsc->rfpwr_state == ERFON) {
+ rtl8723ae_phy_set_rfpath_switch(hw, 1);
+ if (rtlphy->iqk_initialized) {
+ rtl8723ae_phy_iq_calibrate(hw, true);
+ } else {
+ rtl8723ae_phy_iq_calibrate(hw, false);
+ rtlphy->iqk_initialized = true;
+ }
+
+ rtl8723ae_phy_lc_calibrate(hw);
+ }
+
+ tmp_u1b = efuse_read_1byte(hw, 0x1FA);
+ if (!(tmp_u1b & BIT(0))) {
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n");
+ }
+
+ if (!(tmp_u1b & BIT(4))) {
+ tmp_u1b = rtl_read_byte(rtlpriv, 0x16) & 0x0F;
+ rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80);
+ udelay(10);
+ rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
+ }
+ rtl8723ae_dm_init(hw);
+ rtlpriv->rtlhal.being_init_adapter = false;
+ return err;
+}
+
+static enum version_8723e _rtl8723ae_read_chip_version(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ enum version_8723e version = 0x0000;
+ u32 value32;
+
+ value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+ if (value32 & TRP_VAUX_EN) {
+ version = (enum version_8723e)(version |
+ ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+ /* RTL8723 with BT function. */
+ version = (enum version_8723e)(version |
+ ((value32 & BT_FUNC) ? CHIP_8723 : 0));
+
+ } else {
+ /* Normal mass production chip. */
+ version = (enum version_8723e) NORMAL_CHIP;
+ version = (enum version_8723e)(version |
+ ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+ /* RTL8723 with BT function. */
+ version = (enum version_8723e)(version |
+ ((value32 & BT_FUNC) ? CHIP_8723 : 0));
+ if (IS_CHIP_VENDOR_UMC(version))
+ version = (enum version_8723e)(version |
+ ((value32 & CHIP_VER_RTL_MASK)));/* IC version (CUT) */
+ if (IS_8723_SERIES(version)) {
+ value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
+ /* ROM code version */
+ version = (enum version_8723e)(version |
+ ((value32 & RF_RL_ID)>>20));
+ }
+ }
+
+ if (IS_8723_SERIES(version)) {
+ value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL);
+ rtlphy->polarity_ctl = ((value32 & WL_HWPDN_SL) ?
+ RT_POLARITY_HIGH_ACT :
+ RT_POLARITY_LOW_ACT);
+ }
+ switch (version) {
+ case VERSION_TEST_UMC_CHIP_8723:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Chip Version ID: VERSION_TEST_UMC_CHIP_8723.\n");
+ break;
+ case VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT.\n");
+ break;
+ case VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT.\n");
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Chip Version ID: Unknown. Bug?\n");
+ break;
+ }
+
+ if (IS_8723_SERIES(version))
+ rtlphy->rf_type = RF_1T1R;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n",
+ (rtlphy->rf_type == RF_2T2R) ? "RF_2T2R" : "RF_1T1R");
+
+ return version;
+}
+
+static int _rtl8723ae_set_media_status(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc;
+ enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+
+ rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0);
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
+ "clear 0x550 when set HW_VAR_MEDIA_STATUS\n");
+
+ if (type == NL80211_IFTYPE_UNSPECIFIED ||
+ type == NL80211_IFTYPE_STATION) {
+ _rtl8723ae_stop_tx_beacon(hw);
+ _rtl8723ae_enable_bcn_sufunc(hw);
+ } else if (type == NL80211_IFTYPE_ADHOC ||
+ type == NL80211_IFTYPE_AP) {
+ _rtl8723ae_resume_tx_beacon(hw);
+ _rtl8723ae_disable_bcn_sufunc(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n",
+ type);
+ }
+
+ switch (type) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ bt_msr |= MSR_NOLINK;
+ ledaction = LED_CTL_LINK;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Set Network type to NO LINK!\n");
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ bt_msr |= MSR_ADHOC;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Set Network type to Ad Hoc!\n");
+ break;
+ case NL80211_IFTYPE_STATION:
+ bt_msr |= MSR_INFRA;
+ ledaction = LED_CTL_LINK;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Set Network type to STA!\n");
+ break;
+ case NL80211_IFTYPE_AP:
+ bt_msr |= MSR_AP;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Set Network type to AP!\n");
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Network type %d not supported!\n",
+ type);
+ return 1;
+ break;
+
+ }
+
+ rtl_write_byte(rtlpriv, (MSR), bt_msr);
+ rtlpriv->cfg->ops->led_control(hw, ledaction);
+ if ((bt_msr & 0x03) == MSR_AP)
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+ else
+ rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+ return 0;
+}
+
+void rtl8723ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ u32 reg_rcr = rtlpci->receive_config;
+
+ if (rtlpriv->psc.rfpwr_state != ERFON)
+ return;
+
+ if (check_bssid == true) {
+ reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+ (u8 *)(&reg_rcr));
+ _rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(4));
+ } else if (check_bssid == false) {
+ reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+ _rtl8723ae_set_bcn_ctrl_reg(hw, BIT(4), 0);
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_RCR, (u8 *) (&reg_rcr));
+ }
+}
+
+int rtl8723ae_set_network_type(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (_rtl8723ae_set_media_status(hw, type))
+ return -EOPNOTSUPP;
+
+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+ if (type != NL80211_IFTYPE_AP)
+ rtl8723ae_set_check_bssid(hw, true);
+ } else {
+ rtl8723ae_set_check_bssid(hw, false);
+ }
+ return 0;
+}
+
+/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */
+void rtl8723ae_set_qos(struct ieee80211_hw *hw, int aci)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl8723ae_dm_init_edca_turbo(hw);
+ switch (aci) {
+ case AC1_BK:
+ rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
+ break;
+ case AC0_BE:
+ /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4ac_param); */
+ break;
+ case AC2_VI:
+ rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
+ break;
+ case AC3_VO:
+ rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
+ break;
+ default:
+ RT_ASSERT(false, "invalid aci: %d !\n", aci);
+ break;
+ }
+}
+
+void rtl8723ae_enable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, 0x3a8, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+ rtl_write_dword(rtlpriv, 0x3ac, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+ rtlpci->irq_enabled = true;
+}
+
+void rtl8723ae_disable_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ rtl_write_dword(rtlpriv, 0x3a8, IMR8190_DISABLED);
+ rtl_write_dword(rtlpriv, 0x3ac, IMR8190_DISABLED);
+ rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl8723ae_poweroff_adapter(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 u1tmp;
+
+ /* Combo (PCIe + USB) Card and PCIe-MF Card */
+ /* 1. Run LPS WL RFOFF flow */
+ rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+ PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW);
+
+ /* 2. 0x1F[7:0] = 0 */
+ /* turn off RF */
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+ if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
+ rtl8723ae_firmware_selfreset(hw);
+
+ /* Reset MCU. Suggested by Filen. */
+ u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1tmp & (~BIT(2))));
+
+ /* g. MCUFWDL 0x80[1:0]=0 */
+ /* reset MCU ready status */
+ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+ /* HW card disable configuration. */
+ rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+ PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW);
+
+ /* Reset MCU IO Wrapper */
+ u1tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1tmp & (~BIT(0))));
+ u1tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1tmp | BIT(0));
+
+ /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */
+ /* lock ISO/CLK/Power control register */
+ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
+}
+
+void rtl8723ae_card_disable(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ enum nl80211_iftype opmode;
+
+ mac->link_state = MAC80211_NOLINK;
+ opmode = NL80211_IFTYPE_UNSPECIFIED;
+ _rtl8723ae_set_media_status(hw, opmode);
+ if (rtlpci->driver_is_goingto_unload ||
+ ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ _rtl8723ae_poweroff_adapter(hw);
+
+ /* after power off we should do iqk again */
+ rtlpriv->phy.iqk_initialized = false;
+}
+
+void rtl8723ae_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ *p_inta = rtl_read_dword(rtlpriv, 0x3a0) & rtlpci->irq_mask[0];
+ rtl_write_dword(rtlpriv, 0x3a0, *p_inta);
+}
+
+void rtl8723ae_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval, atim_window;
+
+ bcn_interval = mac->beacon_interval;
+ atim_window = 2; /*FIX MERGE */
+ rtl8723ae_disable_interrupt(hw);
+ rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18);
+ rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18);
+ rtl_write_byte(rtlpriv, 0x606, 0x30);
+ rtl8723ae_enable_interrupt(hw);
+}
+
+void rtl8723ae_set_beacon_interval(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 bcn_interval = mac->beacon_interval;
+
+ RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+ "beacon_interval:%d\n", bcn_interval);
+ rtl8723ae_disable_interrupt(hw);
+ rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+ rtl8723ae_enable_interrupt(hw);
+}
+
+void rtl8723ae_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+ "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr);
+
+ if (add_msr)
+ rtlpci->irq_mask[0] |= add_msr;
+ if (rm_msr)
+ rtlpci->irq_mask[0] &= (~rm_msr);
+ rtl8723ae_disable_interrupt(hw);
+ rtl8723ae_enable_interrupt(hw);
+}
+
+static u8 _rtl8723ae_get_chnl_group(u8 chnl)
+{
+ u8 group;
+
+ if (chnl < 3)
+ group = 0;
+ else if (chnl < 9)
+ group = 1;
+ else
+ group = 2;
+ return group;
+}
+
+static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
+ bool autoload_fail,
+ u8 *hwinfo)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 rf_path, index, tempval;
+ u16 i;
+
+ for (rf_path = 0; rf_path < 1; rf_path++) {
+ for (i = 0; i < 3; i++) {
+ if (!autoload_fail) {
+ rtlefuse->eeprom_chnlarea_txpwr_cck
+ [rf_path][i] =
+ hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i];
+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][i] =
+ hwinfo[EEPROM_TXPOWERHT40_1S + rf_path *
+ 3 + i];
+ } else {
+ rtlefuse->eeprom_chnlarea_txpwr_cck
+ [rf_path][i] =
+ EEPROM_DEFAULT_TXPOWERLEVEL;
+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][i] =
+ EEPROM_DEFAULT_TXPOWERLEVEL;
+ }
+ }
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (!autoload_fail)
+ tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
+ else
+ tempval = EEPROM_DEFAULT_HT40_2SDIFF;
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
+ (tempval & 0xf);
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
+ ((tempval & 0xf0) >> 4);
+ }
+
+ for (rf_path = 0; rf_path < 2; rf_path++)
+ for (i = 0; i < 3; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+ "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path,
+ i, rtlefuse->eeprom_chnlarea_txpwr_cck
+ [rf_path][i]);
+ for (rf_path = 0; rf_path < 2; rf_path++)
+ for (i = 0; i < 3; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+ "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n",
+ rf_path, i,
+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][i]);
+ for (rf_path = 0; rf_path < 2; rf_path++)
+ for (i = 0; i < 3; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+ "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
+ rf_path, i,
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf
+ [rf_path][i]);
+
+ for (rf_path = 0; rf_path < 2; rf_path++) {
+ for (i = 0; i < 14; i++) {
+ index = _rtl8723ae_get_chnl_group((u8) i);
+
+ rtlefuse->txpwrlevel_cck[rf_path][i] =
+ rtlefuse->eeprom_chnlarea_txpwr_cck
+ [rf_path][index];
+ rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][index];
+
+ if ((rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][index] -
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path]
+ [index]) > 0) {
+ rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+ [rf_path][index] -
+ rtlefuse->eprom_chnl_txpwr_ht40_2sdf
+ [rf_path][index];
+ } else {
+ rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
+ }
+ }
+
+ for (i = 0; i < 14; i++) {
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = "
+ "[0x%x / 0x%x / 0x%x]\n", rf_path, i,
+ rtlefuse->txpwrlevel_cck[rf_path][i],
+ rtlefuse->txpwrlevel_ht40_1s[rf_path][i],
+ rtlefuse->txpwrlevel_ht40_2s[rf_path][i]);
+ }
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (!autoload_fail) {
+ rtlefuse->eeprom_pwrlimit_ht40[i] =
+ hwinfo[EEPROM_TXPWR_GROUP + i];
+ rtlefuse->eeprom_pwrlimit_ht20[i] =
+ hwinfo[EEPROM_TXPWR_GROUP + 3 + i];
+ } else {
+ rtlefuse->eeprom_pwrlimit_ht40[i] = 0;
+ rtlefuse->eeprom_pwrlimit_ht20[i] = 0;
+ }
+ }
+
+ for (rf_path = 0; rf_path < 2; rf_path++) {
+ for (i = 0; i < 14; i++) {
+ index = _rtl8723ae_get_chnl_group((u8) i);
+
+ if (rf_path == RF90_PATH_A) {
+ rtlefuse->pwrgroup_ht20[rf_path][i] =
+ (rtlefuse->eeprom_pwrlimit_ht20[index] &
+ 0xf);
+ rtlefuse->pwrgroup_ht40[rf_path][i] =
+ (rtlefuse->eeprom_pwrlimit_ht40[index] &
+ 0xf);
+ } else if (rf_path == RF90_PATH_B) {
+ rtlefuse->pwrgroup_ht20[rf_path][i] =
+ ((rtlefuse->eeprom_pwrlimit_ht20[index] &
+ 0xf0) >> 4);
+ rtlefuse->pwrgroup_ht40[rf_path][i] =
+ ((rtlefuse->eeprom_pwrlimit_ht40[index] &
+ 0xf0) >> 4);
+ }
+
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i,
+ rtlefuse->pwrgroup_ht20[rf_path][i]);
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i,
+ rtlefuse->pwrgroup_ht40[rf_path][i]);
+ }
+ }
+
+ for (i = 0; i < 14; i++) {
+ index = _rtl8723ae_get_chnl_group((u8) i);
+
+ if (!autoload_fail)
+ tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index];
+ else
+ tempval = EEPROM_DEFAULT_HT20_DIFF;
+
+ rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF);
+ rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] =
+ ((tempval >> 4) & 0xF);
+
+ if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3))
+ rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0;
+
+ if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3))
+ rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0;
+
+ index = _rtl8723ae_get_chnl_group((u8) i);
+
+ if (!autoload_fail)
+ tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index];
+ else
+ tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+
+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF);
+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] =
+ ((tempval >> 4) & 0xF);
+ }
+
+ rtlefuse->legacy_ht_txpowerdiff =
+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
+
+ for (i = 0; i < 14; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+ rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
+ for (i = 0; i < 14; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i,
+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
+ for (i = 0; i < 14; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+ rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
+ for (i = 0; i < 14; i++)
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i,
+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
+
+ if (!autoload_fail)
+ rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
+ else
+ rtlefuse->eeprom_regulatory = 0;
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
+
+ if (!autoload_fail)
+ rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
+ else
+ rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "TSSI_A = 0x%x, TSSI_B = 0x%x\n",
+ rtlefuse->eeprom_tssi[RF90_PATH_A],
+ rtlefuse->eeprom_tssi[RF90_PATH_B]);
+
+ if (!autoload_fail)
+ tempval = hwinfo[EEPROM_THERMAL_METER];
+ else
+ tempval = EEPROM_DEFAULT_THERMALMETER;
+ rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
+
+ if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
+ rtlefuse->apk_thermalmeterignore = true;
+
+ rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+ RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+ "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
+}
+
+static void _rtl8723ae_read_adapter_info(struct ieee80211_hw *hw,
+ bool pseudo_test)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u16 i, usvalue;
+ u8 hwinfo[HWSET_MAX_SIZE];
+ u16 eeprom_id;
+
+ if (pseudo_test) {
+ /* need add */
+ return;
+ }
+ if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+ rtl_efuse_shadow_map_update(hw);
+
+ memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+ HWSET_MAX_SIZE);
+ } else if (rtlefuse->epromtype == EEPROM_93C46) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "RTL819X Not boot from eeprom, check it !!");
+ }
+
+ RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
+ hwinfo, HWSET_MAX_SIZE);
+
+ eeprom_id = *((u16 *)&hwinfo[0]);
+ if (eeprom_id != RTL8190_EEPROM_ID) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
+ rtlefuse->autoload_failflag = true;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+ rtlefuse->autoload_failflag = false;
+ }
+
+ if (rtlefuse->autoload_failflag == true)
+ return;
+
+ rtlefuse->eeprom_vid = *(u16 *) &hwinfo[EEPROM_VID];
+ rtlefuse->eeprom_did = *(u16 *) &hwinfo[EEPROM_DID];
+ rtlefuse->eeprom_svid = *(u16 *) &hwinfo[EEPROM_SVID];
+ rtlefuse->eeprom_smid = *(u16 *) &hwinfo[EEPROM_SMID];
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROMId = 0x%4x\n", eeprom_id);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
+
+ for (i = 0; i < 6; i += 2) {
+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+ }
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "dev_addr: %pM\n", rtlefuse->dev_addr);
+
+ _rtl8723ae_read_txpower_info_from_hwpg(hw,
+ rtlefuse->autoload_failflag, hwinfo);
+
+ rtl8723ae_read_bt_coexist_info_from_hwpg(hw,
+ rtlefuse->autoload_failflag, hwinfo);
+
+ rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
+ rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+ rtlefuse->txpwr_fromeprom = true;
+ rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
+
+ /* set channel paln to world wide 13 */
+ rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+
+ if (rtlhal->oem_id == RT_CID_DEFAULT) {
+ switch (rtlefuse->eeprom_oemid) {
+ case EEPROM_CID_DEFAULT:
+ if (rtlefuse->eeprom_did == 0x8176) {
+ if (CHK_SVID_SMID(0x10EC, 0x6151) ||
+ CHK_SVID_SMID(0x10EC, 0x6152) ||
+ CHK_SVID_SMID(0x10EC, 0x6154) ||
+ CHK_SVID_SMID(0x10EC, 0x6155) ||
+ CHK_SVID_SMID(0x10EC, 0x6177) ||
+ CHK_SVID_SMID(0x10EC, 0x6178) ||
+ CHK_SVID_SMID(0x10EC, 0x6179) ||
+ CHK_SVID_SMID(0x10EC, 0x6180) ||
+ CHK_SVID_SMID(0x10EC, 0x8151) ||
+ CHK_SVID_SMID(0x10EC, 0x8152) ||
+ CHK_SVID_SMID(0x10EC, 0x8154) ||
+ CHK_SVID_SMID(0x10EC, 0x8155) ||
+ CHK_SVID_SMID(0x10EC, 0x8181) ||
+ CHK_SVID_SMID(0x10EC, 0x8182) ||
+ CHK_SVID_SMID(0x10EC, 0x8184) ||
+ CHK_SVID_SMID(0x10EC, 0x8185) ||
+ CHK_SVID_SMID(0x10EC, 0x9151) ||
+ CHK_SVID_SMID(0x10EC, 0x9152) ||
+ CHK_SVID_SMID(0x10EC, 0x9154) ||
+ CHK_SVID_SMID(0x10EC, 0x9155) ||
+ CHK_SVID_SMID(0x10EC, 0x9181) ||
+ CHK_SVID_SMID(0x10EC, 0x9182) ||
+ CHK_SVID_SMID(0x10EC, 0x9184) ||
+ CHK_SVID_SMID(0x10EC, 0x9185))
+ rtlhal->oem_id = RT_CID_TOSHIBA;
+ else if (rtlefuse->eeprom_svid == 0x1025)
+ rtlhal->oem_id = RT_CID_819x_Acer;
+ else if (CHK_SVID_SMID(0x10EC, 0x6191) ||
+ CHK_SVID_SMID(0x10EC, 0x6192) ||
+ CHK_SVID_SMID(0x10EC, 0x6193) ||
+ CHK_SVID_SMID(0x10EC, 0x7191) ||
+ CHK_SVID_SMID(0x10EC, 0x7192) ||
+ CHK_SVID_SMID(0x10EC, 0x7193) ||
+ CHK_SVID_SMID(0x10EC, 0x8191) ||
+ CHK_SVID_SMID(0x10EC, 0x8192) ||
+ CHK_SVID_SMID(0x10EC, 0x8193))
+ rtlhal->oem_id = RT_CID_819x_SAMSUNG;
+ else if (CHK_SVID_SMID(0x10EC, 0x8195) ||
+ CHK_SVID_SMID(0x10EC, 0x9195) ||
+ CHK_SVID_SMID(0x10EC, 0x7194) ||
+ CHK_SVID_SMID(0x10EC, 0x8200) ||
+ CHK_SVID_SMID(0x10EC, 0x8201) ||
+ CHK_SVID_SMID(0x10EC, 0x8202) ||
+ CHK_SVID_SMID(0x10EC, 0x9200))
+ rtlhal->oem_id = RT_CID_819x_Lenovo;
+ else if (CHK_SVID_SMID(0x10EC, 0x8197) ||
+ CHK_SVID_SMID(0x10EC, 0x9196))
+ rtlhal->oem_id = RT_CID_819x_CLEVO;
+ else if (CHK_SVID_SMID(0x1028, 0x8194) ||
+ CHK_SVID_SMID(0x1028, 0x8198) ||
+ CHK_SVID_SMID(0x1028, 0x9197) ||
+ CHK_SVID_SMID(0x1028, 0x9198))
+ rtlhal->oem_id = RT_CID_819x_DELL;
+ else if (CHK_SVID_SMID(0x103C, 0x1629))
+ rtlhal->oem_id = RT_CID_819x_HP;
+ else if (CHK_SVID_SMID(0x1A32, 0x2315))
+ rtlhal->oem_id = RT_CID_819x_QMI;
+ else if (CHK_SVID_SMID(0x10EC, 0x8203))
+ rtlhal->oem_id = RT_CID_819x_PRONETS;
+ else if (CHK_SVID_SMID(0x1043, 0x84B5))
+ rtlhal->oem_id =
+ RT_CID_819x_Edimax_ASUS;
+ else
+ rtlhal->oem_id = RT_CID_DEFAULT;
+ } else if (rtlefuse->eeprom_did == 0x8178) {
+ if (CHK_SVID_SMID(0x10EC, 0x6181) ||
+ CHK_SVID_SMID(0x10EC, 0x6182) ||
+ CHK_SVID_SMID(0x10EC, 0x6184) ||
+ CHK_SVID_SMID(0x10EC, 0x6185) ||
+ CHK_SVID_SMID(0x10EC, 0x7181) ||
+ CHK_SVID_SMID(0x10EC, 0x7182) ||
+ CHK_SVID_SMID(0x10EC, 0x7184) ||
+ CHK_SVID_SMID(0x10EC, 0x7185) ||
+ CHK_SVID_SMID(0x10EC, 0x8181) ||
+ CHK_SVID_SMID(0x10EC, 0x8182) ||
+ CHK_SVID_SMID(0x10EC, 0x8184) ||
+ CHK_SVID_SMID(0x10EC, 0x8185) ||
+ CHK_SVID_SMID(0x10EC, 0x9181) ||
+ CHK_SVID_SMID(0x10EC, 0x9182) ||
+ CHK_SVID_SMID(0x10EC, 0x9184) ||
+ CHK_SVID_SMID(0x10EC, 0x9185))
+ rtlhal->oem_id = RT_CID_TOSHIBA;
+ else if (rtlefuse->eeprom_svid == 0x1025)
+ rtlhal->oem_id = RT_CID_819x_Acer;
+ else if (CHK_SVID_SMID(0x10EC, 0x8186))
+ rtlhal->oem_id = RT_CID_819x_PRONETS;
+ else if (CHK_SVID_SMID(0x1043, 0x8486))
+ rtlhal->oem_id =
+ RT_CID_819x_Edimax_ASUS;
+ else
+ rtlhal->oem_id = RT_CID_DEFAULT;
+ } else {
+ rtlhal->oem_id = RT_CID_DEFAULT;
+ }
+ break;
+ case EEPROM_CID_TOSHIBA:
+ rtlhal->oem_id = RT_CID_TOSHIBA;
+ break;
+ case EEPROM_CID_CCX:
+ rtlhal->oem_id = RT_CID_CCX;
+ break;
+ case EEPROM_CID_QMI:
+ rtlhal->oem_id = RT_CID_819x_QMI;
+ break;
+ case EEPROM_CID_WHQL:
+ break;
+ default:
+ rtlhal->oem_id = RT_CID_DEFAULT;
+ break;
+
+ }
+ }
+}
+
+static void _rtl8723ae_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ switch (rtlhal->oem_id) {
+ case RT_CID_819x_HP:
+ pcipriv->ledctl.led_opendrain = true;
+ break;
+ case RT_CID_819x_Lenovo:
+ case RT_CID_DEFAULT:
+ case RT_CID_TOSHIBA:
+ case RT_CID_CCX:
+ case RT_CID_819x_Acer:
+ case RT_CID_WHQL:
+ default:
+ break;
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "RT Customized ID: 0x%02X\n", rtlhal->oem_id);
+}
+
+void rtl8723ae_read_eeprom_info(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 tmp_u1b;
+ u32 value32;
+
+ value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST]);
+ value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
+ rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST], value32);
+
+ rtlhal->version = _rtl8723ae_read_chip_version(hw);
+
+ if (get_rf_type(rtlphy) == RF_1T1R)
+ rtlpriv->dm.rfpath_rxenable[0] = true;
+ else
+ rtlpriv->dm.rfpath_rxenable[0] =
+ rtlpriv->dm.rfpath_rxenable[1] = true;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
+ rtlhal->version);
+
+ tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+ if (tmp_u1b & BIT(4)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
+ rtlefuse->epromtype = EEPROM_93C46;
+ } else {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
+ rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+ }
+ if (tmp_u1b & BIT(5)) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+ rtlefuse->autoload_failflag = false;
+ _rtl8723ae_read_adapter_info(hw, false);
+ } else {
+ rtlefuse->autoload_failflag = true;
+ _rtl8723ae_read_adapter_info(hw, false);
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n");
+ }
+ _rtl8723ae_hal_customized_behavior(hw);
+}
+
+static void rtl8723ae_update_hal_rate_table(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u32 ratr_value;
+ u8 ratr_index = 0;
+ u8 nmode = mac->ht_enable;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+ u8 curtxbw_40mhz = mac->bw_40;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = mac->mode;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_value = sta->supp_rates[1] << 4;
+ else
+ ratr_value = sta->supp_rates[0];
+ if (mac->opmode == NL80211_IFTYPE_ADHOC)
+ ratr_value = 0xfff;
+ ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ if (ratr_value & 0x0000000c)
+ ratr_value &= 0x0000000d;
+ else
+ ratr_value &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_value &= 0x00000FF5;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ nmode = 1;
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ ratr_value &= 0x0007F005;
+ } else {
+ u32 ratr_mask;
+
+ if (get_rf_type(rtlphy) == RF_1T2R ||
+ get_rf_type(rtlphy) == RF_1T1R)
+ ratr_mask = 0x000ff005;
+ else
+ ratr_mask = 0x0f0ff005;
+
+ ratr_value &= ratr_mask;
+ }
+ break;
+ default:
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_value &= 0x000ff0ff;
+ else
+ ratr_value &= 0x0f0ff0ff;
+
+ break;
+ }
+
+ if ((pcipriv->bt_coexist.bt_coexistence) &&
+ (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) &&
+ (pcipriv->bt_coexist.bt_cur_state) &&
+ (pcipriv->bt_coexist.bt_ant_isolation) &&
+ ((pcipriv->bt_coexist.bt_service == BT_SCO) ||
+ (pcipriv->bt_coexist.bt_service == BT_BUSY)))
+ ratr_value &= 0x0fffcfc0;
+ else
+ ratr_value &= 0x0FFFFFFF;
+
+ if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz)))
+ ratr_value |= 0x10000000;
+
+ rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0));
+}
+
+static void rtl8723ae_update_hal_rate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_sta_info *sta_entry = NULL;
+ u32 ratr_bitmap;
+ u8 ratr_index;
+ u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ? 1 : 0;
+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+ 1 : 0;
+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+ 1 : 0;
+ enum wireless_mode wirelessmode = 0;
+ bool shortgi = false;
+ u8 rate_mask[5];
+ u8 macid = 0;
+ u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+ sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+ wirelessmode = sta_entry->wireless_mode;
+ if (mac->opmode == NL80211_IFTYPE_STATION)
+ curtxbw_40mhz = mac->bw_40;
+ else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC)
+ macid = sta->aid + 1;
+
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ ratr_bitmap = sta->supp_rates[1] << 4;
+ else
+ ratr_bitmap = sta->supp_rates[0];
+ if (mac->opmode == NL80211_IFTYPE_ADHOC)
+ ratr_bitmap = 0xfff;
+ ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+ sta->ht_cap.mcs.rx_mask[0] << 12);
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ ratr_index = RATR_INX_WIRELESS_B;
+ if (ratr_bitmap & 0x0000000c)
+ ratr_bitmap &= 0x0000000d;
+ else
+ ratr_bitmap &= 0x0000000f;
+ break;
+ case WIRELESS_MODE_G:
+ ratr_index = RATR_INX_WIRELESS_GB;
+
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00000f00;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x00000ff0;
+ else
+ ratr_bitmap &= 0x00000ff5;
+ break;
+ case WIRELESS_MODE_A:
+ ratr_index = RATR_INX_WIRELESS_A;
+ ratr_bitmap &= 0x00000ff0;
+ break;
+ case WIRELESS_MODE_N_24G:
+ case WIRELESS_MODE_N_5G:
+ ratr_index = RATR_INX_WIRELESS_NGB;
+
+ if (mimo_ps == IEEE80211_SMPS_STATIC) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x00070000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0007f000;
+ else
+ ratr_bitmap &= 0x0007f005;
+ } else {
+ if (rtlphy->rf_type == RF_1T2R ||
+ rtlphy->rf_type == RF_1T1R) {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x000f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x000ff000;
+ else
+ ratr_bitmap &= 0x000ff005;
+ }
+ } else {
+ if (curtxbw_40mhz) {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff015;
+ } else {
+ if (rssi_level == 1)
+ ratr_bitmap &= 0x0f0f0000;
+ else if (rssi_level == 2)
+ ratr_bitmap &= 0x0f0ff000;
+ else
+ ratr_bitmap &= 0x0f0ff005;
+ }
+ }
+ }
+
+ if ((curtxbw_40mhz && curshortgi_40mhz) ||
+ (!curtxbw_40mhz && curshortgi_20mhz)) {
+ if (macid == 0)
+ shortgi = true;
+ else if (macid == 1)
+ shortgi = false;
+ }
+ break;
+ default:
+ ratr_index = RATR_INX_WIRELESS_NGB;
+
+ if (rtlphy->rf_type == RF_1T2R)
+ ratr_bitmap &= 0x000ff0ff;
+ else
+ ratr_bitmap &= 0x0f0ff0ff;
+ break;
+ }
+ sta_entry->ratr_index = ratr_index;
+
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ "ratr_bitmap :%x\n", ratr_bitmap);
+ /* convert ratr_bitmap to le byte array */
+ rate_mask[0] = ratr_bitmap;
+ rate_mask[1] = (ratr_bitmap >>= 8);
+ rate_mask[2] = (ratr_bitmap >>= 8);
+ rate_mask[3] = ((ratr_bitmap >> 8) & 0x0f) | (ratr_index << 4);
+ rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+ "Rate_index:%x, ratr_bitmap: %*phC\n",
+ ratr_index, 5, rate_mask);
+ rtl8723ae_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+}
+
+void rtl8723ae_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->dm.useramask)
+ rtl8723ae_update_hal_rate_mask(hw, sta, rssi_level);
+ else
+ rtl8723ae_update_hal_rate_table(hw, sta);
+}
+
+void rtl8723ae_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u16 sifs_timer;
+
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+ (u8 *)&mac->slot_time);
+ if (!mac->ht_enable)
+ sifs_timer = 0x0a0a;
+ else
+ sifs_timer = 0x1010;
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+ u8 u1tmp;
+ bool actuallyset = false;
+
+ if (rtlpriv->rtlhal.being_init_adapter)
+ return false;
+
+ if (ppsc->swrf_processing)
+ return false;
+
+ spin_lock(&rtlpriv->locks.rf_ps_lock);
+ if (ppsc->rfchange_inprogress) {
+ spin_unlock(&rtlpriv->locks.rf_ps_lock);
+ return false;
+ } else {
+ ppsc->rfchange_inprogress = true;
+ spin_unlock(&rtlpriv->locks.rf_ps_lock);
+ }
+
+ cur_rfstate = ppsc->rfpwr_state;
+
+ rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2,
+ rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1)));
+
+ u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2);
+
+ if (rtlphy->polarity_ctl)
+ e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON;
+ else
+ e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF;
+
+ if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "GPIOChangeRF - HW Radio ON, RF ON\n");
+
+ e_rfpowerstate_toset = ERFON;
+ ppsc->hwradiooff = false;
+ actuallyset = true;
+ } else if ((ppsc->hwradiooff == false)
+ && (e_rfpowerstate_toset == ERFOFF)) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "GPIOChangeRF - HW Radio OFF, RF OFF\n");
+
+ e_rfpowerstate_toset = ERFOFF;
+ ppsc->hwradiooff = true;
+ actuallyset = true;
+ }
+
+ if (actuallyset) {
+ spin_lock(&rtlpriv->locks.rf_ps_lock);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock(&rtlpriv->locks.rf_ps_lock);
+ } else {
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+
+ spin_lock(&rtlpriv->locks.rf_ps_lock);
+ ppsc->rfchange_inprogress = false;
+ spin_unlock(&rtlpriv->locks.rf_ps_lock);
+ }
+
+ *valid = 1;
+ return !ppsc->hwradiooff;
+}
+
+void rtl8723ae_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 *macaddr = p_macaddr;
+ u32 entry_id = 0;
+ bool is_pairwise = false;
+ static u8 cam_const_addr[4][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+ };
+ static u8 cam_const_broad[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ if (clear_all) {
+ u8 idx = 0;
+ u8 cam_offset = 0;
+ u8 clear_number = 5;
+
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
+
+ for (idx = 0; idx < clear_number; idx++) {
+ rtl_cam_mark_invalid(hw, cam_offset + idx);
+ rtl_cam_empty_entry(hw, cam_offset + idx);
+
+ if (idx < 5) {
+ memset(rtlpriv->sec.key_buf[idx], 0,
+ MAX_KEY_LEN);
+ rtlpriv->sec.key_len[idx] = 0;
+ }
+ }
+ } else {
+ switch (enc_algo) {
+ case WEP40_ENCRYPTION:
+ enc_algo = CAM_WEP40;
+ break;
+ case WEP104_ENCRYPTION:
+ enc_algo = CAM_WEP104;
+ break;
+ case TKIP_ENCRYPTION:
+ enc_algo = CAM_TKIP;
+ break;
+ case AESCCMP_ENCRYPTION:
+ enc_algo = CAM_AES;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ enc_algo = CAM_TKIP;
+ break;
+ }
+
+ if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+ macaddr = cam_const_addr[key_index];
+ entry_id = key_index;
+ } else {
+ if (is_group) {
+ macaddr = cam_const_broad;
+ entry_id = key_index;
+ } else {
+ if (mac->opmode == NL80211_IFTYPE_AP) {
+ entry_id = rtl_cam_get_free_entry(hw,
+ macaddr);
+ if (entry_id >= TOTAL_CAM_ENTRY) {
+ RT_TRACE(rtlpriv, COMP_SEC,
+ DBG_EMERG,
+ "Can not find free hw security cam entry\n");
+ return;
+ }
+ } else {
+ entry_id = CAM_PAIRWISE_KEY_POSITION;
+ }
+
+ key_index = PAIRWISE_KEYIDX;
+ is_pairwise = true;
+ }
+ }
+
+ if (rtlpriv->sec.key_len[key_index] == 0) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "delete one entry, entry_id is %d\n",
+ entry_id);
+ if (mac->opmode == NL80211_IFTYPE_AP)
+ rtl_cam_del_entry(hw, p_macaddr);
+ rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "add one entry\n");
+ if (is_pairwise) {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "set Pairwiase key\n");
+
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf[key_index]);
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "set group key\n");
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+ rtl_cam_add_one_entry(hw,
+ rtlefuse->dev_addr,
+ PAIRWISE_KEYIDX,
+ CAM_PAIRWISE_KEY_POSITION,
+ enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf
+ [entry_id]);
+ }
+
+ rtl_cam_add_one_entry(hw, macaddr, key_index,
+ entry_id, enc_algo,
+ CAM_CONFIG_NO_USEDK,
+ rtlpriv->sec.key_buf[entry_id]);
+ }
+
+ }
+ }
+}
+
+static void rtl8723ae_bt_var_init(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ pcipriv->bt_coexist.bt_coexistence =
+ pcipriv->bt_coexist.eeprom_bt_coexist;
+ pcipriv->bt_coexist.bt_ant_num =
+ pcipriv->bt_coexist.eeprom_bt_ant_num;
+ pcipriv->bt_coexist.bt_coexist_type =
+ pcipriv->bt_coexist.eeprom_bt_type;
+
+ pcipriv->bt_coexist.bt_ant_isolation =
+ pcipriv->bt_coexist.eeprom_bt_ant_isol;
+
+ pcipriv->bt_coexist.bt_radio_shared_type =
+ pcipriv->bt_coexist.eeprom_bt_radio_shared;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BT Coexistance = 0x%x\n",
+ pcipriv->bt_coexist.bt_coexistence);
+
+ if (pcipriv->bt_coexist.bt_coexistence) {
+ pcipriv->bt_coexist.bt_busy_traffic = false;
+ pcipriv->bt_coexist.bt_traffic_mode_set = false;
+ pcipriv->bt_coexist.bt_non_traffic_mode_set = false;
+
+ pcipriv->bt_coexist.cstate = 0;
+ pcipriv->bt_coexist.previous_state = 0;
+
+ if (pcipriv->bt_coexist.bt_ant_num == ANT_X2) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_Ant_Num = Antx2\n");
+ } else if (pcipriv->bt_coexist.bt_ant_num == ANT_X1) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_Ant_Num = Antx1\n");
+ }
+
+ switch (pcipriv->bt_coexist.bt_coexist_type) {
+ case BT_2WIRE:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_2Wire\n");
+ break;
+ case BT_ISSC_3WIRE:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_ISSC_3Wire\n");
+ break;
+ case BT_ACCEL:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_ACCEL\n");
+ break;
+ case BT_CSR_BC4:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_CSR_BC4\n");
+ break;
+ case BT_CSR_BC8:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_CSR_BC8\n");
+ break;
+ case BT_RTL8756:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = BT_RTL8756\n");
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_CoexistType = Unknown\n");
+ break;
+ }
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BlueTooth BT_Ant_isolation = %d\n",
+ pcipriv->bt_coexist.bt_ant_isolation);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+ "BT_RadioSharedType = 0x%x\n",
+ pcipriv->bt_coexist.bt_radio_shared_type);
+ pcipriv->bt_coexist.bt_active_zero_cnt = 0;
+ pcipriv->bt_coexist.cur_bt_disabled = false;
+ pcipriv->bt_coexist.pre_bt_disabled = false;
+ }
+}
+
+void rtl8723ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+ bool auto_load_fail, u8 *hwinfo)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 value;
+ u32 tmpu_32;
+
+ if (!auto_load_fail) {
+ tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL);
+ if (tmpu_32 & BIT(18))
+ pcipriv->bt_coexist.eeprom_bt_coexist = 1;
+ else
+ pcipriv->bt_coexist.eeprom_bt_coexist = 0;
+ value = hwinfo[RF_OPTION4];
+ pcipriv->bt_coexist.eeprom_bt_type = BT_RTL8723A;
+ pcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1);
+ pcipriv->bt_coexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4);
+ pcipriv->bt_coexist.eeprom_bt_radio_shared =
+ ((value & 0x20) >> 5);
+ } else {
+ pcipriv->bt_coexist.eeprom_bt_coexist = 0;
+ pcipriv->bt_coexist.eeprom_bt_type = BT_RTL8723A;
+ pcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2;
+ pcipriv->bt_coexist.eeprom_bt_ant_isol = 0;
+ pcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
+ }
+
+ rtl8723ae_bt_var_init(hw);
+}
+
+void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+ /* 0:Low, 1:High, 2:From Efuse. */
+ pcipriv->bt_coexist.reg_bt_iso = 2;
+ /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
+ pcipriv->bt_coexist.reg_bt_sco = 3;
+ /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
+ pcipriv->bt_coexist.reg_bt_sco = 0;
+}
+
+
+void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_suspend(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_resume(struct ieee80211_hw *hw)
+{
+}
+
+/* Turn on AAP (RCR:bit 0) for promicuous mode. */
+void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
+ bool allow_all_da, bool write_into_reg)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ if (allow_all_da) /* Set BIT0 */
+ rtlpci->receive_config |= RCR_AAP;
+ else /* Clear BIT0 */
+ rtlpci->receive_config &= ~RCR_AAP;
+
+ if (write_into_reg)
+ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+
+ RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
+ "receive_config=0x%08X, write_into_reg=%d\n",
+ rtlpci->receive_config, write_into_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
new file mode 100644
index 000000000000..6fa24f79b1d7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_HW_H__
+#define __RTL8723E_HW_H__
+
+#define CHK_SVID_SMID(_val1, _val2) \
+ ((rtlefuse->eeprom_svid == (_val1)) && \
+ (rtlefuse->eeprom_smid == (_val2)))
+
+void rtl8723ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8723ae_read_eeprom_info(struct ieee80211_hw *hw);
+
+void rtl8723ae_interrupt_recognized(struct ieee80211_hw *hw,
+ u32 *p_inta, u32 *p_intb);
+int rtl8723ae_hw_init(struct ieee80211_hw *hw);
+void rtl8723ae_card_disable(struct ieee80211_hw *hw);
+void rtl8723ae_enable_interrupt(struct ieee80211_hw *hw);
+void rtl8723ae_disable_interrupt(struct ieee80211_hw *hw);
+int rtl8723ae_set_network_type(struct ieee80211_hw *hw,
+ enum nl80211_iftype type);
+void rtl8723ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl8723ae_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl8723ae_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl8723ae_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl8723ae_update_interrupt_mask(struct ieee80211_hw *hw,
+ u32 add_msr, u32 rm_msr);
+void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8723ae_update_hal_rate_tbl(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, u8 rssi_level);
+void rtl8723ae_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl8723ae_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl8723ae_set_key(struct ieee80211_hw *hw, u32 key_index,
+ u8 *p_macaddr, bool is_group, u8 enc_algo,
+ bool is_wepkey, bool clear_all);
+
+void rtl8723ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+ bool autoload_fail, u8 *hwinfo);
+void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw);
+void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw);
+void rtl8723ae_suspend(struct ieee80211_hw *hw);
+void rtl8723ae_resume(struct ieee80211_hw *hw);
+void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
+ bool allow_all_da, bool write_into_reg);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
new file mode 100644
index 000000000000..9c4e1d811187
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl8723ae_init_led(struct ieee80211_hw *hw,
+ struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+ pled->hw = hw;
+ pled->ledpin = ledpin;
+ pled->ledon = false;
+}
+
+void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 ledcfg;
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ rtl_write_byte(rtlpriv,
+ REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
+ break;
+ case LED_PIN_LED1:
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ break;
+ }
+ pled->ledon = true;
+}
+
+void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ u8 ledcfg;
+
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+
+ ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+ switch (pled->ledpin) {
+ case LED_PIN_GPIO0:
+ break;
+ case LED_PIN_LED0:
+ ledcfg &= 0xf0;
+ if (pcipriv->ledctl.led_opendrain)
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+ else
+ rtl_write_byte(rtlpriv, REG_LEDCFG2,
+ (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+ break;
+ case LED_PIN_LED1:
+ ledcfg &= 0x0f;
+ rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ break;
+ }
+ pled->ledon = false;
+}
+
+void rtl8723ae_init_sw_leds(struct ieee80211_hw *hw)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+ _rtl8723ae_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+ _rtl8723ae_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void _rtl8723ae_sw_led_control(struct ieee80211_hw *hw,
+ enum led_ctl_mode ledaction)
+{
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+ switch (ledaction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ rtl8723ae_sw_led_on(hw, pLed0);
+ break;
+ case LED_CTL_POWER_OFF:
+ rtl8723ae_sw_led_off(hw, pLed0);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl8723ae_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+ if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+ (ledaction == LED_CTL_TX ||
+ ledaction == LED_CTL_RX ||
+ ledaction == LED_CTL_SITE_SURVEY ||
+ ledaction == LED_CTL_LINK ||
+ ledaction == LED_CTL_NO_LINK ||
+ ledaction == LED_CTL_START_TO_LINK ||
+ ledaction == LED_CTL_POWER_ON)) {
+ return;
+ }
+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction);
+ _rtl8723ae_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/rtlwifi/rtl8723ae/led.h
new file mode 100644
index 000000000000..2cb88e78f62a
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_LED_H__
+#define __RTL92CE_LED_H__
+
+void rtl8723ae_init_sw_leds(struct ieee80211_hw *hw);
+void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723ae_led_control(struct ieee80211_hw *hw,
+ enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
new file mode 100644
index 000000000000..39cc7938eedf
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
@@ -0,0 +1,2044 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+
+/* static forward definitions */
+static u32 _phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset);
+static void _phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath,
+ u32 offset, u32 data);
+static u32 _phy_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset);
+static void _phy_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset, u32 data);
+static u32 _phy_calculate_bit_shift(u32 bitmask);
+static bool _phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
+static bool _phy_cfg_mac_w_header(struct ieee80211_hw *hw);
+static bool _phy_cfg_bb_w_header(struct ieee80211_hw *hw, u8 configtype);
+static bool _phy_cfg_bb_w_pgheader(struct ieee80211_hw *hw, u8 configtype);
+static void _phy_init_bb_rf_reg_def(struct ieee80211_hw *hw);
+static bool _phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+ u32 cmdtableidx, u32 cmdtablesz,
+ enum swchnlcmd_id cmdid,
+ u32 para1, u32 para2,
+ u32 msdelay);
+static bool _phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, u8 channel,
+ u8 *stage, u8 *step, u32 *delay);
+static u8 _phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+ enum wireless_mode wirelessmode,
+ long power_indbm);
+static long _phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+ enum wireless_mode wirelessmode, u8 txpwridx);
+static void rtl8723ae_phy_set_io(struct ieee80211_hw *hw);
+
+u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
+ u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 returnvalue, originalvalue, bitshift;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ bitshift = _phy_calculate_bit_shift(bitmask);
+ returnvalue = (originalvalue & bitmask) >> bitshift;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, regaddr,
+ originalvalue);
+
+ return returnvalue;
+}
+
+void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 originalvalue, bitshift;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr,
+ bitmask, data);
+
+ if (bitmask != MASKDWORD) {
+ originalvalue = rtl_read_dword(rtlpriv, regaddr);
+ bitshift = _phy_calculate_bit_shift(bitmask);
+ data = ((originalvalue & (~bitmask)) | (data << bitshift));
+ }
+
+ rtl_write_dword(rtlpriv, regaddr, data);
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), bitmask(%#x), data(%#x)\n",
+ regaddr, bitmask, data);
+}
+
+u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 original_value, readback_value, bitshift;
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
+ regaddr, rfpath, bitmask);
+
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+ if (rtlphy->rf_mode != RF_OP_BY_FW)
+ original_value = _phy_rf_serial_read(hw, rfpath, regaddr);
+ else
+ original_value = _phy_fw_rf_serial_read(hw, rfpath, regaddr);
+
+ bitshift = _phy_calculate_bit_shift(bitmask);
+ readback_value = (original_value & bitmask) >> bitshift;
+
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
+ regaddr, rfpath, bitmask, original_value);
+
+ return readback_value;
+}
+
+void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 original_value, bitshift;
+ unsigned long flags;
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath);
+
+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+ if (rtlphy->rf_mode != RF_OP_BY_FW) {
+ if (bitmask != RFREG_OFFSET_MASK) {
+ original_value = _phy_rf_serial_read(hw, rfpath,
+ regaddr);
+ bitshift = _phy_calculate_bit_shift(bitmask);
+ data = ((original_value & (~bitmask)) |
+ (data << bitshift));
+ }
+
+ _phy_rf_serial_write(hw, rfpath, regaddr, data);
+ } else {
+ if (bitmask != RFREG_OFFSET_MASK) {
+ original_value = _phy_fw_rf_serial_read(hw, rfpath,
+ regaddr);
+ bitshift = _phy_calculate_bit_shift(bitmask);
+ data = ((original_value & (~bitmask)) |
+ (data << bitshift));
+ }
+ _phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
+ }
+
+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+ "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+ regaddr, bitmask, data, rfpath);
+}
+
+static u32 _phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset)
+{
+ RT_ASSERT(false, "deprecated!\n");
+ return 0;
+}
+
+static void _phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath,
+ u32 offset, u32 data)
+{
+ RT_ASSERT(false, "deprecated!\n");
+}
+
+static u32 _phy_rf_serial_read(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+ u32 newoffset;
+ u32 tmplong, tmplong2;
+ u8 rfpi_enable = 0;
+ u32 retvalue;
+
+ offset &= 0x3f;
+ newoffset = offset;
+ if (RT_CANNOT_IO(hw)) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n");
+ return 0xFFFFFFFF;
+ }
+ tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
+ if (rfpath == RF90_PATH_A)
+ tmplong2 = tmplong;
+ else
+ tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD);
+ tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+ (newoffset << 23) | BLSSIREADEDGE;
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+ tmplong & (~BLSSIREADEDGE));
+ mdelay(1);
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
+ mdelay(1);
+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+ tmplong | BLSSIREADEDGE);
+ mdelay(1);
+ if (rfpath == RF90_PATH_A)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+ BIT(8));
+ else if (rfpath == RF90_PATH_B)
+ rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+ BIT(8));
+ if (rfpi_enable)
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
+ BLSSIREADBACKDATA);
+ else
+ retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
+ BLSSIREADBACKDATA);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
+ rfpath, pphyreg->rf_rb, retvalue);
+ return retvalue;
+}
+
+static void _phy_rf_serial_write(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 offset, u32 data)
+{
+ u32 data_and_addr;
+ u32 newoffset;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ if (RT_CANNOT_IO(hw)) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n");
+ return;
+ }
+ offset &= 0x3f;
+ newoffset = offset;
+ data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+ rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n",
+ rfpath, pphyreg->rf3wire_offset, data_and_addr);
+}
+
+static u32 _phy_calculate_bit_shift(u32 bitmask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((bitmask >> i) & 0x1) == 1)
+ break;
+ }
+ return i;
+}
+
+static void _rtl8723ae_phy_bb_config_1t(struct ieee80211_hw *hw)
+{
+ rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
+ rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
+ rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
+ rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
+ rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
+ rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
+ rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
+ rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
+ rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
+}
+
+bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ bool rtstatus = _phy_cfg_mac_w_header(hw);
+ rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
+ return rtstatus;
+}
+
+bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw)
+{
+ bool rtstatus = true;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmpu1b;
+ u8 reg_hwparafile = 1;
+
+ _phy_init_bb_rf_reg_def(hw);
+
+ /* 1. 0x28[1] = 1 */
+ tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL);
+ udelay(2);
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1)));
+ udelay(2);
+ /* 2. 0x29[7:0] = 0xFF */
+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff);
+ udelay(2);
+
+ /* 3. 0x02[1:0] = 2b'11 */
+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, (tmpu1b |
+ FEN_BB_GLB_RSTn | FEN_BBRSTB));
+
+ /* 4. 0x25[6] = 0 */
+ tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1);
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b&(~BIT(6))));
+
+ /* 5. 0x24[20] = 0 Advised by SD3 Alex Wang. 2011.02.09. */
+ tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2);
+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b&(~BIT(4))));
+
+ /* 6. 0x1f[7:0] = 0x07 */
+ rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07);
+
+ if (reg_hwparafile == 1)
+ rtstatus = _phy_bb8192c_config_parafile(hw);
+ return rtstatus;
+}
+
+bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw)
+{
+ return rtl8723ae_phy_rf6052_config(hw);
+}
+
+static bool _phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ bool rtstatus;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "==>\n");
+ rtstatus = _phy_cfg_bb_w_header(hw, BASEBAND_CONFIG_PHY_REG);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!");
+ return false;
+ }
+
+ if (rtlphy->rf_type == RF_1T2R) {
+ _rtl8723ae_phy_bb_config_1t(hw);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n");
+ }
+ if (rtlefuse->autoload_failflag == false) {
+ rtlphy->pwrgroup_cnt = 0;
+ rtstatus = _phy_cfg_bb_w_pgheader(hw, BASEBAND_CONFIG_PHY_REG);
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!");
+ return false;
+ }
+ rtstatus = _phy_cfg_bb_w_header(hw, BASEBAND_CONFIG_AGC_TAB);
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n");
+ return false;
+ }
+ rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2, 0x200));
+ return true;
+}
+
+static bool _phy_cfg_mac_w_header(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+ u32 arraylength;
+ u32 *ptrarray;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n");
+ arraylength = RTL8723E_MACARRAYLENGTH;
+ ptrarray = RTL8723EMAC_ARRAY;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Img:RTL8192CEMAC_2T_ARRAY\n");
+ for (i = 0; i < arraylength; i = i + 2)
+ rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+ return true;
+}
+
+static bool _phy_cfg_bb_w_header(struct ieee80211_hw *hw, u8 configtype)
+{
+ int i;
+ u32 *phy_regarray_table;
+ u32 *agctab_array_table;
+ u16 phy_reg_arraylen, agctab_arraylen;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH;
+ agctab_array_table = RTL8723EAGCTAB_1TARRAY;
+ phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH;
+ phy_regarray_table = RTL8723EPHY_REG_1TARRAY;
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+ if (phy_regarray_table[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table[i] == 0xf9)
+ udelay(1);
+ rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
+ phy_regarray_table[i + 1]);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "The phy_regarray_table[0] is %x"
+ " Rtl819XPHY_REGArray[1] is %x\n",
+ phy_regarray_table[i],
+ phy_regarray_table[i + 1]);
+ }
+ } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+ for (i = 0; i < agctab_arraylen; i = i + 2) {
+ rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
+ agctab_array_table[i + 1]);
+ udelay(1);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "The agctab_array_table[0] is "
+ "%x Rtl819XPHY_REGArray[1] is %x\n",
+ agctab_array_table[i],
+ agctab_array_table[i + 1]);
+ }
+ }
+ return true;
+}
+
+static void _st_pwrIdx_dfrate_off(struct ieee80211_hw *hw, u32 regaddr,
+ u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ switch (regaddr) {
+ case RTXAGC_A_RATE18_06:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]);
+ break;
+ case RTXAGC_A_RATE54_24:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]);
+ break;
+ case RTXAGC_A_CCK1_MCS32:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]);
+ break;
+ case RTXAGC_B_CCK11_A_CCK2_11:
+ if (bitmask == 0xffffff00) {
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]);
+ }
+ if (bitmask == 0x000000ff) {
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]);
+ }
+ break;
+ case RTXAGC_A_MCS03_MCS00:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]);
+ break;
+ case RTXAGC_A_MCS07_MCS04:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]);
+ break;
+ case RTXAGC_A_MCS11_MCS08:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]);
+ break;
+ case RTXAGC_A_MCS15_MCS12:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]);
+ break;
+ case RTXAGC_B_RATE18_06:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]);
+ break;
+ case RTXAGC_B_RATE54_24:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]);
+ break;
+ case RTXAGC_B_CCK1_55_MCS32:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]);
+ break;
+ case RTXAGC_B_MCS03_MCS00:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]);
+ break;
+ case RTXAGC_B_MCS07_MCS04:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]);
+ break;
+ case RTXAGC_B_MCS11_MCS08:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]);
+ break;
+ case RTXAGC_B_MCS15_MCS12:
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
+ rtlphy->pwrgroup_cnt,
+ rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]);
+ rtlphy->pwrgroup_cnt++;
+ break;
+ }
+}
+
+static bool _phy_cfg_bb_w_pgheader(struct ieee80211_hw *hw, u8 configtype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ u32 *phy_regarray_table_pg;
+ u16 phy_regarray_pg_len;
+
+ phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH;
+ phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG;
+
+ if (configtype == BASEBAND_CONFIG_PHY_REG) {
+ for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+ if (phy_regarray_table_pg[i] == 0xfe)
+ mdelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfd)
+ mdelay(5);
+ else if (phy_regarray_table_pg[i] == 0xfc)
+ mdelay(1);
+ else if (phy_regarray_table_pg[i] == 0xfb)
+ udelay(50);
+ else if (phy_regarray_table_pg[i] == 0xfa)
+ udelay(5);
+ else if (phy_regarray_table_pg[i] == 0xf9)
+ udelay(1);
+
+ _st_pwrIdx_dfrate_off(hw, phy_regarray_table_pg[i],
+ phy_regarray_table_pg[i + 1],
+ phy_regarray_table_pg[i + 2]);
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ "configtype != BaseBand_Config_PHY_REG\n");
+ }
+ return true;
+}
+
+bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+ bool rtstatus = true;
+ u32 *radioa_array_table;
+ u32 *radiob_array_table;
+ u16 radioa_arraylen, radiob_arraylen;
+
+ radioa_arraylen = Rtl8723ERADIOA_1TARRAYLENGTH;
+ radioa_array_table = RTL8723E_RADIOA_1TARRAY;
+ radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH;
+ radiob_array_table = RTL8723E_RADIOB_1TARRAY;
+
+ rtstatus = true;
+
+ switch (rfpath) {
+ case RF90_PATH_A:
+ for (i = 0; i < radioa_arraylen; i = i + 2) {
+ if (radioa_array_table[i] == 0xfe)
+ mdelay(50);
+ else if (radioa_array_table[i] == 0xfd)
+ mdelay(5);
+ else if (radioa_array_table[i] == 0xfc)
+ mdelay(1);
+ else if (radioa_array_table[i] == 0xfb)
+ udelay(50);
+ else if (radioa_array_table[i] == 0xfa)
+ udelay(5);
+ else if (radioa_array_table[i] == 0xf9)
+ udelay(1);
+ else {
+ rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+ RFREG_OFFSET_MASK,
+ radioa_array_table[i + 1]);
+ udelay(1);
+ }
+ }
+ break;
+ case RF90_PATH_B:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ case RF90_PATH_C:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ case RF90_PATH_D:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+ return true;
+}
+
+void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->default_initialgain[0] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
+ rtlphy->default_initialgain[1] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
+ rtlphy->default_initialgain[2] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
+ rtlphy->default_initialgain[3] =
+ (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n",
+ rtlphy->default_initialgain[0],
+ rtlphy->default_initialgain[1],
+ rtlphy->default_initialgain[2],
+ rtlphy->default_initialgain[3]);
+
+ rtlphy->framesync = (u8) rtl_get_bbreg(hw,
+ ROFDM0_RXDETECTOR3, MASKBYTE0);
+ rtlphy->framesync_c34 = rtl_get_bbreg(hw,
+ ROFDM0_RXDETECTOR2, MASKDWORD);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Default framesync (0x%x) = 0x%x\n",
+ ROFDM0_RXDETECTOR3, rtlphy->framesync);
+}
+
+static void _phy_init_bb_rf_reg_def(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+ rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+ rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+ RFPGA0_XA_LSSIPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+ RFPGA0_XB_LSSIPARAMETER;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+ rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
+ rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
+ rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
+ rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+ rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
+
+ rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
+ rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
+}
+
+void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 txpwr_level;
+ long txpwr_dbm;
+
+ txpwr_level = rtlphy->cur_cck_txpwridx;
+ txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, txpwr_level);
+ txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
+ rtlefuse->legacy_ht_txpowerdiff;
+ if (_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) > txpwr_dbm)
+ txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
+ txpwr_level);
+ txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+ if (_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, txpwr_level) >
+ txpwr_dbm)
+ txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
+ txpwr_level);
+ *powerlevel = txpwr_dbm;
+}
+
+static void _rtl8723ae_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+ u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 index = (channel - 1);
+
+ cckpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+ cckpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+ if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+ } else if (get_rf_type(rtlphy) == RF_2T2R) {
+ ofdmpowerlevel[RF90_PATH_A] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+ ofdmpowerlevel[RF90_PATH_B] =
+ rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+ }
+}
+
+static void _rtl8723ae_ccxpower_index_check(struct ieee80211_hw *hw,
+ u8 channel, u8 *cckpowerlevel,
+ u8 *ofdmpowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+ rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+ if (rtlefuse->txpwr_fromeprom == false)
+ return;
+ _rtl8723ae_get_txpower_index(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ _rtl8723ae_ccxpower_index_check(hw, channel, &cckpowerlevel[0],
+ &ofdmpowerlevel[0]);
+ rtl8723ae_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+ rtl8723ae_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
+}
+
+bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 idx;
+ u8 rf_path;
+ u8 ccktxpwridx = _phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_B,
+ power_indbm);
+ u8 ofdmtxpwridx = _phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_N_24G,
+ power_indbm);
+ if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
+ ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
+ else
+ ofdmtxpwridx = 0;
+ RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
+ "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
+ power_indbm, ccktxpwridx, ofdmtxpwridx);
+ for (idx = 0; idx < 14; idx++) {
+ for (rf_path = 0; rf_path < 2; rf_path++) {
+ rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
+ rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
+ ofdmtxpwridx;
+ rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
+ ofdmtxpwridx;
+ }
+ }
+ rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+ return true;
+}
+
+static u8 _phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+ enum wireless_mode wirelessmode,
+ long power_indbm)
+{
+ u8 txpwridx;
+ long offset;
+
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ offset = -7;
+ break;
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G:
+ offset = -8;
+ break;
+ default:
+ offset = -8;
+ break;
+ }
+
+ if ((power_indbm - offset) > 0)
+ txpwridx = (u8) ((power_indbm - offset) * 2);
+ else
+ txpwridx = 0;
+
+ if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
+ txpwridx = MAX_TXPWR_IDX_NMODE_92S;
+
+ return txpwridx;
+}
+
+static long _phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+ enum wireless_mode wirelessmode, u8 txpwridx)
+{
+ long offset;
+ long pwrout_dbm;
+
+ switch (wirelessmode) {
+ case WIRELESS_MODE_B:
+ offset = -7;
+ break;
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G:
+ offset = -8;
+ break;
+ default:
+ offset = -8;
+ break;
+ }
+ pwrout_dbm = txpwridx / 2 + offset;
+ return pwrout_dbm;
+}
+
+void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ enum io_type iotype;
+
+ if (!is_hal_stop(rtlhal)) {
+ switch (operation) {
+ case SCAN_OPT_BACKUP:
+ iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+
+ break;
+ case SCAN_OPT_RESTORE:
+ iotype = IO_CMD_RESUME_DM_BY_SCAN;
+ rtlpriv->cfg->ops->set_hw_reg(hw,
+ HW_VAR_IO_CMD,
+ (u8 *)&iotype);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Unknown Scan Backup operation.\n");
+ break;
+ }
+ }
+}
+
+void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ u8 reg_bw_opmode;
+ u8 reg_prsr_rsc;
+
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ "Switch to %s bandwidth\n",
+ rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+ "20MHz" : "40MHz");
+
+ if (is_hal_stop(rtlhal)) {
+ rtlphy->set_bwmode_inprogress = false;
+ return;
+ }
+
+ reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+ reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ reg_bw_opmode |= BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+ rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+ reg_prsr_rsc =
+ (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
+ rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
+ break;
+ }
+
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+
+ rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
+ (mac->cur_40_prime_sc >> 1));
+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
+
+ rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+ (mac->cur_40_prime_sc ==
+ HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
+ break;
+ }
+ rtl8723ae_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+ rtlphy->set_bwmode_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+}
+
+void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ u8 tmp_bw = rtlphy->current_chan_bw;
+
+ if (rtlphy->set_bwmode_inprogress)
+ return;
+ rtlphy->set_bwmode_inprogress = true;
+ if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+ rtl8723ae_phy_set_bw_mode_callback(hw);
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "FALSE driver sleep or unload\n");
+ rtlphy->set_bwmode_inprogress = false;
+ rtlphy->current_chan_bw = tmp_bw;
+ }
+}
+
+void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 delay;
+
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+ "switch to channel%d\n", rtlphy->current_channel);
+ if (is_hal_stop(rtlhal))
+ return;
+ do {
+ if (!rtlphy->sw_chnl_inprogress)
+ break;
+ if (!_phy_sw_chnl_step_by_step
+ (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
+ &rtlphy->sw_chnl_step, &delay)) {
+ if (delay > 0)
+ mdelay(delay);
+ else
+ continue;
+ } else {
+ rtlphy->sw_chnl_inprogress = false;
+ }
+ break;
+ } while (true);
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+}
+
+u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ if (rtlphy->sw_chnl_inprogress)
+ return 0;
+ if (rtlphy->set_bwmode_inprogress)
+ return 0;
+ RT_ASSERT((rtlphy->current_channel <= 14),
+ "WIRELESS_MODE_G but channel>14");
+ rtlphy->sw_chnl_inprogress = true;
+ rtlphy->sw_chnl_stage = 0;
+ rtlphy->sw_chnl_step = 0;
+ if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+ rtl8723ae_phy_sw_chnl_callback(hw);
+ RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+ "sw_chnl_inprogress false schdule workitem\n");
+ rtlphy->sw_chnl_inprogress = false;
+ } else {
+ RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+ "sw_chnl_inprogress false driver sleep or unload\n");
+ rtlphy->sw_chnl_inprogress = false;
+ }
+ return 1;
+}
+
+static void _rtl8723ae_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+ if (channel == 6 && rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20)
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+ 0x00255);
+ else{
+ u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A,
+ RF_RX_G1, RFREG_OFFSET_MASK);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+ backupRF0x1A);
+ }
+ }
+}
+
+static bool _phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, u8 channel,
+ u8 *stage, u8 *step, u32 *delay)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+ u32 precommoncmdcnt;
+ struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+ u32 postcommoncmdcnt;
+ struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+ u32 rfdependcmdcnt;
+ struct swchnlcmd *currentcmd = NULL;
+ u8 rfpath;
+ u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+ precommoncmdcnt = 0;
+ _phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL,
+ 0, 0, 0);
+ _phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+ postcommoncmdcnt = 0;
+
+ _phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+ MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+ rfdependcmdcnt = 0;
+
+ RT_ASSERT((channel >= 1 && channel <= 14),
+ "illegal channel for Zebra: %d\n", channel);
+
+ _phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+ RF_CHNLBW, channel, 10);
+
+ _phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+ MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0);
+
+ do {
+ switch (*stage) {
+ case 0:
+ currentcmd = &precommoncmd[*step];
+ break;
+ case 1:
+ currentcmd = &rfdependcmd[*step];
+ break;
+ case 2:
+ currentcmd = &postcommoncmd[*step];
+ break;
+ }
+
+ if (currentcmd->cmdid == CMDID_END) {
+ if ((*stage) == 2) {
+ return true;
+ } else {
+ (*stage)++;
+ (*step) = 0;
+ continue;
+ }
+ }
+
+ switch (currentcmd->cmdid) {
+ case CMDID_SET_TXPOWEROWER_LEVEL:
+ rtl8723ae_phy_set_txpower_level(hw, channel);
+ break;
+ case CMDID_WRITEPORT_ULONG:
+ rtl_write_dword(rtlpriv, currentcmd->para1,
+ currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_USHORT:
+ rtl_write_word(rtlpriv, currentcmd->para1,
+ (u16) currentcmd->para2);
+ break;
+ case CMDID_WRITEPORT_UCHAR:
+ rtl_write_byte(rtlpriv, currentcmd->para1,
+ (u8) currentcmd->para2);
+ break;
+ case CMDID_RF_WRITEREG:
+ for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+ rtlphy->rfreg_chnlval[rfpath] =
+ ((rtlphy->rfreg_chnlval[rfpath] &
+ 0xfffffc00) | currentcmd->para2);
+
+ rtl_set_rfreg(hw, (enum radio_path)rfpath,
+ currentcmd->para1,
+ RFREG_OFFSET_MASK,
+ rtlphy->rfreg_chnlval[rfpath]);
+ }
+ _rtl8723ae_phy_sw_rf_seting(hw, channel);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+
+ break;
+ } while (true);
+
+ (*delay) = currentcmd->msdelay;
+ (*step)++;
+ return false;
+}
+
+static bool _phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+ u32 cmdtableidx, u32 cmdtablesz,
+ enum swchnlcmd_id cmdid, u32 para1,
+ u32 para2, u32 msdelay)
+{
+ struct swchnlcmd *pcmd;
+
+ if (cmdtable == NULL) {
+ RT_ASSERT(false, "cmdtable cannot be NULL.\n");
+ return false;
+ }
+
+ if (cmdtableidx >= cmdtablesz)
+ return false;
+
+ pcmd = cmdtable + cmdtableidx;
+ pcmd->cmdid = cmdid;
+ pcmd->para1 = para1;
+ pcmd->para2 = para2;
+ pcmd->msdelay = msdelay;
+ return true;
+}
+
+static u8 _rtl8723ae_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+ u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
+ u8 result = 0x00;
+
+ rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
+ rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
+ rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
+ config_pathb ? 0x28160202 : 0x28160502);
+
+ if (config_pathb) {
+ rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
+ rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
+ rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
+ }
+
+ rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
+ rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
+ rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
+
+ mdelay(IQK_DELAY_TIME);
+
+ reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+ reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
+ reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
+ reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
+
+ if (!(reg_eac & BIT(28)) &&
+ (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+ (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+
+ if (!(reg_eac & BIT(27)) &&
+ (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((reg_eac & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ return result;
+}
+
+static u8 _rtl8723ae_phy_path_b_iqk(struct ieee80211_hw *hw)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+ u8 result = 0x00;
+
+ rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
+ rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
+ mdelay(IQK_DELAY_TIME);
+ reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+ reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
+ reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
+ reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
+ reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
+
+ if (!(reg_eac & BIT(31)) &&
+ (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
+ (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+ if (!(reg_eac & BIT(30)) &&
+ (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+ return result;
+}
+
+static void phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, bool iqk_ok,
+ long result[][8], u8 final_candidate,
+ bool btxonly)
+{
+ u32 oldval_0, x, tx0_a, reg;
+ long y, tx0_c;
+
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqk_ok) {
+ oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+ MASKDWORD) >> 22) & 0x3FF;
+ x = result[final_candidate][0];
+ if ((x & 0x00000200) != 0)
+ x = x | 0xFFFFFC00;
+ tx0_a = (x * oldval_0) >> 8;
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
+ ((x * oldval_0 >> 7) & 0x1));
+ y = result[final_candidate][1];
+ if ((y & 0x00000200) != 0)
+ y = y | 0xFFFFFC00;
+ tx0_c = (y * oldval_0) >> 8;
+ rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
+ ((tx0_c & 0x3C0) >> 6));
+ rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
+ (tx0_c & 0x3F));
+ rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
+ ((y * oldval_0 >> 7) & 0x1));
+ if (btxonly)
+ return;
+ reg = result[final_candidate][2];
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+ reg = result[final_candidate][3] & 0x3F;
+ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+ }
+}
+
+static void phy_save_adda_regs(struct ieee80211_hw *hw,
+ u32 *addareg, u32 *addabackup,
+ u32 registernum)
+{
+ u32 i;
+
+ for (i = 0; i < registernum; i++)
+ addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
+}
+
+static void phy_save_mac_regs(struct ieee80211_hw *hw, u32 *macreg,
+ u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+ macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void phy_reload_adda_regs(struct ieee80211_hw *hw, u32 *addareg,
+ u32 *addabackup, u32 regiesternum)
+{
+ u32 i;
+
+ for (i = 0; i < regiesternum; i++)
+ rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
+}
+
+static void phy_reload_mac_regs(struct ieee80211_hw *hw, u32 *macreg,
+ u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i;
+
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+ rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl8723ae_phy_path_adda_on(struct ieee80211_hw *hw,
+ u32 *addareg, bool is_patha_on,
+ bool is2t)
+{
+ u32 pathOn;
+ u32 i;
+
+ pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
+ if (false == is2t) {
+ pathOn = 0x0bdb25a0;
+ rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
+ } else {
+ rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn);
+ }
+
+ for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+ rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn);
+}
+
+static void _rtl8723ae_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+ u32 *macreg, u32 *macbackup)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 i = 0;
+
+ rtl_write_byte(rtlpriv, macreg[i], 0x3F);
+
+ for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+ rtl_write_byte(rtlpriv, macreg[i],
+ (u8) (macbackup[i] & (~BIT(3))));
+ rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl8723ae_phy_path_a_standby(struct ieee80211_hw *hw)
+{
+ rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
+ rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+ rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+}
+
+static void _rtl8723ae_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+ u32 mode;
+
+ mode = pi_mode ? 0x01000100 : 0x01000000;
+ rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
+ rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
+}
+
+static bool phy_simularity_comp(struct ieee80211_hw *hw, long result[][8],
+ u8 c1, u8 c2)
+{
+ u32 i, j, diff, simularity_bitmap, bound;
+
+ u8 final_candidate[2] = { 0xFF, 0xFF };
+ bool bresult = true;
+
+ bound = 4;
+
+ simularity_bitmap = 0;
+
+ for (i = 0; i < bound; i++) {
+ diff = (result[c1][i] > result[c2][i]) ?
+ (result[c1][i] - result[c2][i]) :
+ (result[c2][i] - result[c1][i]);
+
+ if (diff > MAX_TOLERANCE) {
+ if ((i == 2 || i == 6) && !simularity_bitmap) {
+ if (result[c1][i] + result[c1][i + 1] == 0)
+ final_candidate[(i / 4)] = c2;
+ else if (result[c2][i] + result[c2][i + 1] == 0)
+ final_candidate[(i / 4)] = c1;
+ else
+ simularity_bitmap = simularity_bitmap |
+ (1 << i);
+ } else
+ simularity_bitmap =
+ simularity_bitmap | (1 << i);
+ }
+ }
+
+ if (simularity_bitmap == 0) {
+ for (i = 0; i < (bound / 4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+ result[3][j] =
+ result[final_candidate[i]][j];
+ bresult = false;
+ }
+ }
+ return bresult;
+ } else if (!(simularity_bitmap & 0x0F)) {
+ for (i = 0; i < 4; i++)
+ result[3][i] = result[c1][i];
+ return false;
+ } else {
+ return false;
+ }
+
+}
+
+static void _rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw,
+ long result[][8], u8 t, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 i;
+ u8 patha_ok, pathb_ok;
+ u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ 0x85c, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ 0x522, 0x550, 0x551, 0x040
+ };
+ const u32 retrycount = 2;
+ u32 bbvalue;
+
+ if (t == 0) {
+ bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+
+ phy_save_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16);
+ phy_save_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+ }
+ _rtl8723ae_phy_path_adda_on(hw, adda_reg, true, is2t);
+ if (t == 0) {
+ rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER1,
+ BIT(8));
+ }
+
+ if (!rtlphy->rfpi_enable)
+ _rtl8723ae_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, 0xc04, MASKDWORD, 0x03a05600);
+ rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
+ rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+ if (is2t) {
+ rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+ rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
+ }
+ _rtl8723ae_phy_mac_setting_calibration(hw, iqk_mac_reg,
+ rtlphy->iqk_mac_backup);
+ rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
+ if (is2t)
+ rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
+ rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+ rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
+ rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
+ for (i = 0; i < retrycount; i++) {
+ patha_ok = _rtl8723ae_phy_path_a_iqk(hw, is2t);
+ if (patha_ok == 0x03) {
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && patha_ok == 0x01)
+
+ result[t][0] = (rtl_get_bbreg(hw, 0xe94,
+ MASKDWORD) & 0x3FF0000) >> 16;
+ result[t][1] =
+ (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
+
+ }
+
+ if (is2t) {
+ _rtl8723ae_phy_path_a_standby(hw);
+ _rtl8723ae_phy_path_adda_on(hw, adda_reg, false, is2t);
+ for (i = 0; i < retrycount; i++) {
+ pathb_ok = _rtl8723ae_phy_path_b_iqk(hw);
+ if (pathb_ok == 0x03) {
+ result[t][4] =
+ (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][5] =
+ (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][6] =
+ (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ result[t][7] =
+ (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+ result[t][4] =
+ (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) &
+ 0x3FF0000) >> 16;
+ }
+ result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+ 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)
+ _rtl8723ae_phy_pi_mode_switch(hw, false);
+ phy_reload_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16);
+ phy_reload_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+ }
+}
+
+static void _rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u8 tmpreg;
+ u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+
+ tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+
+ if ((tmpreg & 0x70) != 0)
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+ else
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+
+ if ((tmpreg & 0x70) != 0) {
+ rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
+
+ if (is2t)
+ rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
+ MASK12BITS);
+
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
+ (rf_a_mode & 0x8FFFF) | 0x10000);
+
+ if (is2t)
+ rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+ (rf_b_mode & 0x8FFFF) | 0x10000);
+ }
+ lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
+
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
+
+ mdelay(100);
+
+ if ((tmpreg & 0x70) != 0) {
+ rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
+
+ if (is2t)
+ rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+ rf_b_mode);
+ } else {
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ }
+}
+
+static void _rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw,
+ bool bmain, bool is2t)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ if (is_hal_stop(rtlhal)) {
+ rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
+ rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+ }
+ if (is2t) {
+ if (bmain)
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+ BIT(5) | BIT(6), 0x1);
+ else
+ rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+ BIT(5) | BIT(6), 0x2);
+ } else {
+ if (bmain)
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
+ else
+ rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
+
+ }
+}
+
+#undef IQK_ADDA_REG_NUM
+#undef IQK_DELAY_TIME
+
+void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ long result[4][8];
+ u8 i, final_candidate;
+ bool patha_ok, pathb_ok;
+ long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
+ reg_ecc, reg_tmp = 0;
+ bool is12simular, is13simular, is23simular;
+ bool start_conttx = false, singletone = false;
+ u32 iqk_bb_reg[10] = {
+ ROFDM0_XARXIQIMBALANCE,
+ ROFDM0_XBRXIQIMBALANCE,
+ ROFDM0_ECCATHRESHOLD,
+ ROFDM0_AGCRSSITABLE,
+ ROFDM0_XATXIQIMBALANCE,
+ ROFDM0_XBTXIQIMBALANCE,
+ ROFDM0_XCTXIQIMBALANCE,
+ ROFDM0_XCTXAFE,
+ ROFDM0_XDTXAFE,
+ ROFDM0_RXIQEXTANTA
+ };
+
+ if (recovery) {
+ phy_reload_adda_regs(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 10);
+ return;
+ }
+ if (start_conttx || singletone)
+ return;
+ for (i = 0; i < 8; i++) {
+ result[0][i] = 0;
+ result[1][i] = 0;
+ result[2][i] = 0;
+ result[3][i] = 0;
+ }
+ final_candidate = 0xff;
+ patha_ok = false;
+ pathb_ok = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+ for (i = 0; i < 3; i++) {
+ _rtl8723ae_phy_iq_calibrate(hw, result, i, false);
+ if (i == 1) {
+ is12simular = phy_simularity_comp(hw, result, 0, 1);
+ if (is12simular) {
+ final_candidate = 0;
+ break;
+ }
+ }
+ if (i == 2) {
+ is13simular = phy_simularity_comp(hw, result, 0, 2);
+ if (is13simular) {
+ final_candidate = 0;
+ break;
+ }
+ is23simular = phy_simularity_comp(hw, result, 1, 2);
+ if (is23simular) {
+ final_candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ reg_tmp += result[3][i];
+
+ if (reg_tmp != 0)
+ final_candidate = 3;
+ else
+ final_candidate = 0xFF;
+ }
+ }
+ }
+ for (i = 0; i < 4; i++) {
+ reg_e94 = result[i][0];
+ reg_e9c = result[i][1];
+ reg_ea4 = result[i][2];
+ reg_eac = result[i][3];
+ reg_eb4 = result[i][4];
+ reg_ebc = result[i][5];
+ reg_ec4 = result[i][6];
+ reg_ecc = result[i][7];
+ }
+ if (final_candidate != 0xff) {
+ rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
+ rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
+ reg_ea4 = result[final_candidate][2];
+ reg_eac = result[final_candidate][3];
+ rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
+ rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
+ reg_ec4 = result[final_candidate][6];
+ reg_ecc = result[final_candidate][7];
+ patha_ok = pathb_ok = true;
+ } else {
+ rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
+ rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
+ }
+ if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
+ phy_path_a_fill_iqk_matrix(hw, patha_ok, result,
+ final_candidate, (reg_ea4 == 0));
+ phy_save_adda_regs(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 10);
+}
+
+void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+ bool start_conttx = false, singletone = false;
+
+ if (start_conttx || singletone)
+ return;
+ _rtl8723ae_phy_lc_calibrate(hw, false);
+}
+
+void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
+{
+ _rtl8723ae_phy_set_rfpath_switch(hw, bmain, false);
+}
+
+bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ bool postprocessing = false;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ "-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+ iotype, rtlphy->set_io_inprogress);
+ do {
+ switch (iotype) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ "[IO CMD] Resume DM after scan.\n");
+ postprocessing = true;
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ "[IO CMD] Pause DM before scan.\n");
+ postprocessing = true;
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+ } while (false);
+ if (postprocessing && !rtlphy->set_io_inprogress) {
+ rtlphy->set_io_inprogress = true;
+ rtlphy->current_io_type = iotype;
+ } else {
+ return false;
+ }
+ rtl8723ae_phy_set_io(hw);
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<--IO Type(%#x)\n", iotype);
+ return true;
+}
+
+static void rtl8723ae_phy_set_io(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ "--->Cmd(%#x), set_io_inprogress(%d)\n",
+ rtlphy->current_io_type, rtlphy->set_io_inprogress);
+ switch (rtlphy->current_io_type) {
+ case IO_CMD_RESUME_DM_BY_SCAN:
+ dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+ rtl8723ae_dm_write_dig(hw);
+ rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+ break;
+ case IO_CMD_PAUSE_DM_BY_SCAN:
+ rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
+ dm_digtable->cur_igvalue = 0x17;
+ rtl8723ae_dm_write_dig(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not process\n");
+ break;
+ }
+ rtlphy->set_io_inprogress = false;
+ RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+ "<---(%#x)\n", rtlphy->current_io_type);
+}
+
+static void rtl8723ae_phy_set_rf_on(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+
+static void _rtl8723ae_phy_set_rf_sleep(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 u4b_tmp;
+ u8 delay = 5;
+
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+ while (u4b_tmp != 0 && delay > 0) {
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+ u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+ delay--;
+ }
+ if (delay == 0) {
+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+ "Switch RF timeout !!!.\n");
+ return;
+ }
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+}
+
+static bool _rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ struct rtl8192_tx_ring *ring = NULL;
+ bool bresult = true;
+ u8 i, queue_id;
+
+ switch (rfpwr_state) {
+ case ERFON:
+ if ((ppsc->rfpwr_state == ERFOFF) &&
+ RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+ bool rtstatus;
+ u32 InitializeCount = 0;
+ do {
+ InitializeCount++;
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "IPS Set eRf nic enable\n");
+ rtstatus = rtl_ps_enable_nic(hw);
+ } while ((rtstatus != true) && (InitializeCount < 10));
+ RT_CLEAR_PS_LEVEL(ppsc,
+ RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "Set ERFON sleeped:%d ms\n",
+ jiffies_to_msecs(jiffies -
+ ppsc->last_sleep_jiffies));
+ ppsc->last_awake_jiffies = jiffies;
+ rtl8723ae_phy_set_rf_on(hw);
+ }
+ if (mac->link_state == MAC80211_LINKED) {
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_LINK);
+ } else {
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ }
+ break;
+ case ERFOFF:
+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "IPS Set eRf nic disable\n");
+ rtl_ps_disable_nic(hw);
+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_NO_LINK);
+ } else {
+ rtlpriv->cfg->ops->led_control(hw,
+ LED_CTL_POWER_OFF);
+ }
+ }
+ break;
+ case ERFSLEEP:
+ if (ppsc->rfpwr_state == ERFOFF)
+ break;
+ for (queue_id = 0, i = 0;
+ queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+ ring = &pcipriv->dev.tx_ring[queue_id];
+ if (skb_queue_len(&ring->queue) == 0) {
+ queue_id++;
+ continue;
+ } else {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
+ (i + 1), queue_id,
+ skb_queue_len(&ring->queue));
+
+ udelay(10);
+ i++;
+ }
+ if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
+ MAX_DOZE_WAITING_TIMES_9x,
+ queue_id,
+ skb_queue_len(&ring->queue));
+ break;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+ "Set ERFSLEEP awaked:%d ms\n",
+ jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
+ ppsc->last_sleep_jiffies = jiffies;
+ _rtl8723ae_phy_set_rf_sleep(hw);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "switch case not processed\n");
+ bresult = false;
+ break;
+ }
+ if (bresult)
+ ppsc->rfpwr_state = rfpwr_state;
+ return bresult;
+}
+
+bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state)
+{
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool bresult = false;
+
+ if (rfpwr_state == ppsc->rfpwr_state)
+ return bresult;
+ bresult = _rtl8723ae_phy_set_rf_power_state(hw, rfpwr_state);
+ return bresult;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
new file mode 100644
index 000000000000..e7a59eba351a
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
@@ -0,0 +1,224 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_PHY_H__
+#define __RTL92C_PHY_H__
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define RT_CANNOT_IO(hw) false
+#define HIGHPOWER_RADIOA_ARRAYLEN 22
+
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1
+
+#define APK_BB_REG_NUM 5
+#define APK_AFE_REG_NUM 16
+#define APK_CURVE_REG_NUM 4
+#define PATH_NUM 2
+
+#define LOOP_LIMIT 5
+#define MAX_STALL_TIME 50
+#define AntennaDiversityValue 0x80
+#define MAX_TXPWR_IDX_NMODE_92S 63
+#define Reset_Cnt_Limit 3
+
+#define IQK_MAC_REG_NUM 4
+
+#define RF6052_MAX_PATH 2
+
+#define CT_OFFSET_MAC_ADDR 0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72
+
+#define CT_OFFSET_CHANNEL_PLAH 0x75
+#define CT_OFFSET_THERMAL_METER 0x78
+#define CT_OFFSET_RF_OPTION 0x79
+#define CT_OFFSET_VERSION 0x7E
+#define CT_OFFSET_CUSTOMER_ID 0x7F
+
+#define RTL92C_MAX_PATH_NUM 2
+
+enum swchnlcmd_id {
+ CMDID_END,
+ CMDID_SET_TXPOWEROWER_LEVEL,
+ CMDID_BBREGWRITE10,
+ CMDID_WRITEPORT_ULONG,
+ CMDID_WRITEPORT_USHORT,
+ CMDID_WRITEPORT_UCHAR,
+ CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+ enum swchnlcmd_id cmdid;
+ u32 para1;
+ u32 para2;
+ u32 msdelay;
+};
+
+enum hw90_block_e {
+ HW90_BLOCK_MAC = 0,
+ HW90_BLOCK_PHY0 = 1,
+ HW90_BLOCK_PHY1 = 2,
+ HW90_BLOCK_RF = 3,
+ HW90_BLOCK_MAXIMUM = 4,
+};
+
+enum baseband_config_type {
+ BASEBAND_CONFIG_PHY_REG = 0,
+ BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum ra_offset_area {
+ RA_OFFSET_LEGACY_OFDM1,
+ RA_OFFSET_LEGACY_OFDM2,
+ RA_OFFSET_HT_OFDM1,
+ RA_OFFSET_HT_OFDM2,
+ RA_OFFSET_HT_OFDM3,
+ RA_OFFSET_HT_OFDM4,
+ RA_OFFSET_HT_CCK,
+};
+
+enum antenna_path {
+ ANTENNA_NONE,
+ ANTENNA_D,
+ ANTENNA_C,
+ ANTENNA_CD,
+ ANTENNA_B,
+ ANTENNA_BD,
+ ANTENNA_BC,
+ ANTENNA_BCD,
+ ANTENNA_A,
+ ANTENNA_AD,
+ ANTENNA_AC,
+ ANTENNA_ACD,
+ ANTENNA_AB,
+ ANTENNA_ABD,
+ ANTENNA_ABC,
+ ANTENNA_ABCD
+};
+
+struct r_antenna_select_ofdm {
+ u32 r_tx_antenna:4;
+ u32 r_ant_l:4;
+ u32 r_ant_non_ht:4;
+ u32 r_ant_ht1:4;
+ u32 r_ant_ht2:4;
+ u32 r_ant_ht_s1:4;
+ u32 r_ant_non_ht_s1:4;
+ u32 ofdm_txsc:2;
+ u32 reserved:2;
+};
+
+struct r_antenna_select_cck {
+ u8 r_cckrx_enable_2:2;
+ u8 r_cckrx_enable:2;
+ u8 r_ccktx_enable:4;
+};
+
+struct efuse_contents {
+ u8 mac_addr[ETH_ALEN];
+ u8 cck_tx_power_idx[6];
+ u8 ht40_1s_tx_power_idx[6];
+ u8 ht40_2s_tx_power_idx_diff[3];
+ u8 ht20_tx_power_idx_diff[3];
+ u8 ofdm_tx_power_idx_diff[3];
+ u8 ht40_max_power_offset[3];
+ u8 ht20_max_power_offset[3];
+ u8 channel_plan;
+ u8 thermal_meter;
+ u8 rf_option[5];
+ u8 version;
+ u8 oem_id;
+ u8 regulatory;
+};
+
+struct tx_power_struct {
+ u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 legacy_ht_txpowerdiff;
+ u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+ u8 pwrgroup_cnt;
+ u32 mcs_original_offset[4][16];
+};
+
+extern u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask);
+extern void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw,
+ u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask);
+extern void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask, u32 data);
+extern bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+extern void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw,
+ long *powerlevel);
+extern void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw,
+ u8 channel);
+extern bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw,
+ long power_indbm);
+extern void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw,
+ u8 operation);
+extern void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+extern void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+extern u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
+void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
new file mode 100644
index 000000000000..df6ca9a57f7f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
@@ -0,0 +1,109 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "pwrseqcmd.h"
+#include "pwrseq.h"
+
+/* drivers should parse arrays below and do the corresponding actions */
+
+/*3 Power on Array*/
+struct wlan_pwr_cfg rtl8723A_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_CARDEMU_TO_ACT,
+ RTL8723A_TRANS_END
+};
+
+/*3Radio off GPIO Array */
+struct wlan_pwr_cfg rtl8723A_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_ACT_TO_CARDEMU,
+ RTL8723A_TRANS_END
+};
+
+/*3Card Disable Array*/
+struct wlan_pwr_cfg
+rtl8723A_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_ACT_TO_CARDEMU,
+ RTL8723A_TRANS_CARDEMU_TO_CARDDIS,
+ RTL8723A_TRANS_END
+};
+
+/*3 Card Enable Array*/
+struct wlan_pwr_cfg rtl8723A_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_CARDDIS_TO_CARDEMU,
+ RTL8723A_TRANS_CARDEMU_TO_ACT,
+ RTL8723A_TRANS_END
+};
+
+/*3Suspend Array*/
+struct wlan_pwr_cfg rtl8723A_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_ACT_TO_CARDEMU,
+ RTL8723A_TRANS_CARDEMU_TO_SUS,
+ RTL8723A_TRANS_END
+};
+
+/*3 Resume Array*/
+struct wlan_pwr_cfg rtl8723A_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_SUS_TO_CARDEMU,
+ RTL8723A_TRANS_CARDEMU_TO_ACT,
+ RTL8723A_TRANS_END
+};
+
+/*3HWPDN Array*/
+struct wlan_pwr_cfg rtl8723A_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ RTL8723A_TRANS_ACT_TO_CARDEMU,
+ RTL8723A_TRANS_CARDEMU_TO_PDN,
+ RTL8723A_TRANS_END
+};
+
+/*3 Enter LPS */
+struct wlan_pwr_cfg rtl8723A_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ /*FW behavior*/
+ RTL8723A_TRANS_ACT_TO_LPS,
+ RTL8723A_TRANS_END
+};
+
+/*3 Leave LPS */
+struct wlan_pwr_cfg rtl8723A_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STPS
+ + RTL8723A_TRANS_END_STPS] = {
+ /*FW behavior*/
+ RTL8723A_TRANS_LPS_TO_ACT,
+ RTL8723A_TRANS_END
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
new file mode 100644
index 000000000000..7a46f9fdf558
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
@@ -0,0 +1,322 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_PWRSEQ_H__
+#define __RTL8723E_PWRSEQ_H__
+
+#include "pwrseqcmd.h"
+/*
+ Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd
+ There are 6 HW Power States:
+ 0: POFF--Power Off
+ 1: PDN--Power Down
+ 2: CARDEMU--Card Emulation
+ 3: ACT--Active Mode
+ 4: LPS--Low Power State
+ 5: SUS--Suspend
+
+ The transision from different states are defined below
+ TRANS_CARDEMU_TO_ACT
+ TRANS_ACT_TO_CARDEMU
+ TRANS_CARDEMU_TO_SUS
+ TRANS_SUS_TO_CARDEMU
+ TRANS_CARDEMU_TO_PDN
+ TRANS_ACT_TO_LPS
+ TRANS_LPS_TO_ACT
+
+ TRANS_END
+*/
+
+#define RTL8723A_TRANS_CARDEMU_TO_ACT_STPS 10
+#define RTL8723A_TRANS_ACT_TO_CARDEMU_STPS 10
+#define RTL8723A_TRANS_CARDEMU_TO_SUS_STPS 10
+#define RTL8723A_TRANS_SUS_TO_CARDEMU_STPS 10
+#define RTL8723A_TRANS_CARDEMU_TO_PDN_STPS 10
+#define RTL8723A_TRANS_PDN_TO_CARDEMU_STPS 10
+#define RTL8723A_TRANS_ACT_TO_LPS_STPS 15
+#define RTL8723A_TRANS_LPS_TO_ACT_STPS 15
+#define RTL8723A_TRANS_END_STPS 1
+
+
+#define RTL8723A_TRANS_CARDEMU_TO_ACT \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+ * comments here*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0}, \
+ /* disable SW LPS 0x04[10]=0*/ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
+ /* wait till 0x04[17] = 1 power ready*/ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
+ /* release WLON reset 0x04[16]=1*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \
+ /* disable HWPDN 0x04[15]=0*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0}, \
+ /* disable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
+ /* polling until return 0*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}
+
+#define RTL8723A_TRANS_ACT_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+ * comments here*/ \
+ {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \
+ /*0x1F[7:0] = 0 turn off RF*/ \
+ {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}
+
+#define RTL8723A_TRANS_CARDEMU_TO_SUS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+ * comments here*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), \
+ (BIT(4)|BIT(3))}, \
+ /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK | \
+ PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},\
+ /*0x04[12:11] = 2b'01 enable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
+ PWR_BASEADDR_MAC, \
+ PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)}, \
+ /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, \
+ PWR_CMD_WRITE, BIT(0), BIT(0)}, \
+ /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, \
+ PWR_CMD_POLLING, BIT(1), 0} \
+ /*wait power state to suspend*/
+
+#define RTL8723A_TRANS_SUS_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \
+ /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
+ /*wait power state to suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0} \
+ /*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
+ PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},\
+ /*0x04[12:11] = 2b'01 enable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)}, \
+ /*0x04[10] = 1, enable SW LPS*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
+ /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0} \
+ /*wait power state to suspend*/
+
+#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \
+ /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
+ /*wait power state to suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \
+ /*0x04[12:11] = 2b'00enable WL suspend*/ \
+ {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0} \
+ /*PCIe DMA start*/
+
+#define RTL8723A_TRANS_CARDEMU_TO_PDN \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \
+ /* 0x04[16] = 0*/\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)} \
+ /* 0x04[15] = 1*/
+
+#define RTL8723A_TRANS_PDN_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0} \
+ /* 0x04[15] = 0*/
+
+#define RTL8723A_TRANS_ACT_TO_LPS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \
+ /*PCIe DMA stop*/ \
+ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F}, \
+ /*Tx Pause*/ \
+ {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \
+ /*CCK and OFDM are disabled,and clock are gated*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \
+ /*Delay 1us*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \
+ /*Whole BB is reset*/ \
+ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F}, \
+ /*Reset MAC TRX*/ \
+ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \
+ /*check if removed later*/ \
+ {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)} \
+ /*Respond TxOK to scheduler*/
+
+#define RTL8723A_TRANS_LPS_TO_ACT \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
+ PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, \
+ /*SDIO RPWM*/ \
+ {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \
+ /*USB RPWM*/ \
+ {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \
+ /*PCIe RPWM*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \
+ /*Delay*/ \
+ {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
+ /* 0x08[4] = 0 switch TSF to 40M*/ \
+ {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \
+ /*Polling 0x109[7]=0 TSF in 40M*/ \
+ {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \
+ /*. 0x29[7:6] = 2b'00 enable BB clock*/ \
+ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
+ /*. 0x101[1] = 1*/ \
+ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \
+ /* 0x100[7:0] = 0xFF enable WMAC TRX*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), \
+ BIT(1)|BIT(0)}, \
+ /* 0x02[1:0] = 2b'11 enable BB macro*/ \
+ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0} \
+ /*. 0x522 = 0*/
+
+#define RTL8723A_TRANS_END \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+ {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
+ 0, PWR_CMD_END, 0, 0}
+
+extern struct
+wlan_pwr_cfg rtl8723A_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+ + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STPS
+ + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STPS
+ + RTL8723A_TRANS_END_STPS];
+
+/* RTL8723 Power Configuration CMDs for PCIe interface */
+#define Rtl8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow
+#define Rtl8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow
+#define Rtl8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow
+#define Rtl8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow
+#define Rtl8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow
+#define Rtl8723_NIC_RESUME_FLOW rtl8723A_resume_flow
+#define Rtl8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow
+#define Rtl8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow
+#define Rtl8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c
new file mode 100644
index 000000000000..2044b5936b7f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "pwrseq.h"
+
+/* Description:
+ * This routine deals with the Power Configuration CMD
+ * parsing for RTL8723/RTL8188E Series IC.
+ * Assumption:
+ * We should follow specific format that was released from HW SD.
+ */
+bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+ u8 faversion, u8 interface_type,
+ struct wlan_pwr_cfg pwrcfgcmd[])
+{
+ struct wlan_pwr_cfg cfg_cmd = {0};
+ bool polling_bit = false;
+ u32 ary_idx = 0;
+ u8 value = 0;
+ u32 offset = 0;
+ u32 polling_count = 0;
+ u32 max_polling_cnt = 5000;
+
+ do {
+ cfg_cmd = pwrcfgcmd[ary_idx];
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): offset(%#x),cut_msk(%#x), famsk(%#x),"
+ "interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n",
+ GET_PWR_CFG_OFFSET(cfg_cmd),
+ GET_PWR_CFG_CUT_MASK(cfg_cmd),
+ GET_PWR_CFG_FAB_MASK(cfg_cmd),
+ GET_PWR_CFG_INTF_MASK(cfg_cmd),
+ GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd),
+ GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd));
+
+ if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) &&
+ (GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) &&
+ (GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) {
+ switch (GET_PWR_CFG_CMD(cfg_cmd)) {
+ case PWR_CMD_READ:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n");
+ break;
+ case PWR_CMD_WRITE:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n");
+ offset = GET_PWR_CFG_OFFSET(cfg_cmd);
+
+ /*Read the value from system register*/
+ value = rtl_read_byte(rtlpriv, offset);
+ value &= (~(GET_PWR_CFG_MASK(cfg_cmd)));
+ value |= (GET_PWR_CFG_VALUE(cfg_cmd) &
+ GET_PWR_CFG_MASK(cfg_cmd));
+
+ /*Write the value back to sytem register*/
+ rtl_write_byte(rtlpriv, offset, value);
+ break;
+ case PWR_CMD_POLLING:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
+ polling_bit = false;
+ offset = GET_PWR_CFG_OFFSET(cfg_cmd);
+
+ do {
+ value = rtl_read_byte(rtlpriv, offset);
+
+ value &= GET_PWR_CFG_MASK(cfg_cmd);
+ if (value ==
+ (GET_PWR_CFG_VALUE(cfg_cmd)
+ & GET_PWR_CFG_MASK(cfg_cmd)))
+ polling_bit = true;
+ else
+ udelay(10);
+
+ if (polling_count++ > max_polling_cnt)
+ return false;
+ } while (!polling_bit);
+ break;
+ case PWR_CMD_DELAY:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n");
+ if (GET_PWR_CFG_VALUE(cfg_cmd) ==
+ PWRSEQ_DELAY_US)
+ udelay(GET_PWR_CFG_OFFSET(cfg_cmd));
+ else
+ mdelay(GET_PWR_CFG_OFFSET(cfg_cmd));
+ break;
+ case PWR_CMD_END:
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
+ return true;
+ default:
+ RT_ASSERT(false,
+ "rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
+ break;
+ }
+
+ }
+ ary_idx++;
+ } while (1);
+
+ return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h
new file mode 100644
index 000000000000..6e0f3ea37ec0
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_PWRSEQCMD_H__
+#define __RTL8723E_PWRSEQCMD_H__
+
+#include "../wifi.h"
+/*---------------------------------------------
+ * 3 The value of cmd: 4 bits
+ *---------------------------------------------
+ */
+#define PWR_CMD_READ 0x00
+#define PWR_CMD_WRITE 0x01
+#define PWR_CMD_POLLING 0x02
+#define PWR_CMD_DELAY 0x03
+#define PWR_CMD_END 0x04
+
+/* define the base address of each block */
+#define PWR_BASEADDR_MAC 0x00
+#define PWR_BASEADDR_USB 0x01
+#define PWR_BASEADDR_PCIE 0x02
+#define PWR_BASEADDR_SDIO 0x03
+
+#define PWR_INTF_SDIO_MSK BIT(0)
+#define PWR_INTF_USB_MSK BIT(1)
+#define PWR_INTF_PCI_MSK BIT(2)
+#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define PWR_FAB_TSMC_MSK BIT(0)
+#define PWR_FAB_UMC_MSK BIT(1)
+#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define PWR_CUT_TESTCHIP_MSK BIT(0)
+#define PWR_CUT_A_MSK BIT(1)
+#define PWR_CUT_B_MSK BIT(2)
+#define PWR_CUT_C_MSK BIT(3)
+#define PWR_CUT_D_MSK BIT(4)
+#define PWR_CUT_E_MSK BIT(5)
+#define PWR_CUT_F_MSK BIT(6)
+#define PWR_CUT_G_MSK BIT(7)
+#define PWR_CUT_ALL_MSK 0xFF
+
+enum pwrseq_delay_unit {
+ PWRSEQ_DELAY_US,
+ PWRSEQ_DELAY_MS,
+};
+
+struct wlan_pwr_cfg {
+ u16 offset;
+ u8 cut_msk;
+ u8 fab_msk:4;
+ u8 interface_msk:4;
+ u8 base:4;
+ u8 cmd:4;
+ u8 msk;
+ u8 value;
+};
+
+#define GET_PWR_CFG_OFFSET(__PWR_CMD) (__PWR_CMD.offset)
+#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) (__PWR_CMD.cut_msk)
+#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) (__PWR_CMD.fab_msk)
+#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) (__PWR_CMD.interface_msk)
+#define GET_PWR_CFG_BASE(__PWR_CMD) (__PWR_CMD.base)
+#define GET_PWR_CFG_CMD(__PWR_CMD) (__PWR_CMD.cmd)
+#define GET_PWR_CFG_MASK(__PWR_CMD) (__PWR_CMD.msk)
+#define GET_PWR_CFG_VALUE(__PWR_CMD) (__PWR_CMD.value)
+
+bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+ u8 fab_version, u8 interface_type,
+ struct wlan_pwr_cfg pwrcfgcmd[]);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
new file mode 100644
index 000000000000..199da366c6da
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
@@ -0,0 +1,2097 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_REG_H__
+#define __RTL8723E_REG_H__
+
+#define REG_SYS_ISO_CTRL 0x0000
+#define REG_SYS_FUNC_EN 0x0002
+#define REG_APS_FSMCO 0x0004
+#define REG_SYS_CLKR 0x0008
+#define REG_9346CR 0x000A
+#define REG_EE_VPD 0x000C
+#define REG_AFE_MISC 0x0010
+#define REG_SPS0_CTRL 0x0011
+#define REG_SPS_OCP_CFG 0x0018
+#define REG_RSV_CTRL 0x001C
+#define REG_RF_CTRL 0x001F
+#define REG_LDOA15_CTRL 0x0020
+#define REG_LDOV12D_CTRL 0x0021
+#define REG_LDOHCI12_CTRL 0x0022
+#define REG_LPLDO_CTRL 0x0023
+#define REG_AFE_XTAL_CTRL 0x0024
+#define REG_AFE_PLL_CTRL 0x0028
+#define REG_EFUSE_CTRL 0x0030
+#define REG_EFUSE_TEST 0x0034
+#define REG_PWR_DATA 0x0038
+#define REG_CAL_TIMER 0x003C
+#define REG_ACLK_MON 0x003E
+#define REG_GPIO_MUXCFG 0x0040
+#define REG_GPIO_IO_SEL 0x0042
+#define REG_MAC_PINMUX_CFG 0x0043
+#define REG_GPIO_PIN_CTRL 0x0044
+#define REG_GPIO_INTM 0x0048
+#define REG_LEDCFG0 0x004C
+#define REG_LEDCFG1 0x004D
+#define REG_LEDCFG2 0x004E
+#define REG_LEDCFG3 0x004F
+#define REG_FSIMR 0x0050
+#define REG_FSISR 0x0054
+#define REG_GPIO_PIN_CTRL_2 0x0060
+#define REG_GPIO_IO_SEL_2 0x0062
+#define REG_MULTI_FUNC_CTRL 0x0068
+
+#define REG_MCUFWDL 0x0080
+
+#define REG_HMEBOX_EXT_0 0x0088
+#define REG_HMEBOX_EXT_1 0x008A
+#define REG_HMEBOX_EXT_2 0x008C
+#define REG_HMEBOX_EXT_3 0x008E
+
+#define REG_BIST_SCAN 0x00D0
+#define REG_BIST_RPT 0x00D4
+#define REG_BIST_ROM_RPT 0x00D8
+#define REG_USB_SIE_INTF 0x00E0
+#define REG_PCIE_MIO_INTF 0x00E4
+#define REG_PCIE_MIO_INTD 0x00E8
+#define REG_SYS_CFG 0x00F0
+#define REG_GPIO_OUTSTS 0x00F4
+
+#define REG_CR 0x0100
+#define REG_PBP 0x0104
+#define REG_TRXDMA_CTRL 0x010C
+#define REG_TRXFF_BNDY 0x0114
+#define REG_TRXFF_STATUS 0x0118
+#define REG_RXFF_PTR 0x011C
+#define REG_HIMR 0x0120
+#define REG_HISR 0x0124
+#define REG_HIMRE 0x0128
+#define REG_HISRE 0x012C
+#define REG_CPWM 0x012F
+#define REG_FWIMR 0x0130
+#define REG_FWISR 0x0134
+#define REG_PKTBUF_DBG_CTRL 0x0140
+#define REG_PKTBUF_DBG_DATA_L 0x0144
+#define REG_PKTBUF_DBG_DATA_H 0x0148
+
+#define REG_TC0_CTRL 0x0150
+#define REG_TC1_CTRL 0x0154
+#define REG_TC2_CTRL 0x0158
+#define REG_TC3_CTRL 0x015C
+#define REG_TC4_CTRL 0x0160
+#define REG_TCUNIT_BASE 0x0164
+#define REG_MBIST_START 0x0174
+#define REG_MBIST_DONE 0x0178
+#define REG_MBIST_FAIL 0x017C
+#define REG_C2HEVT_MSG_NORMAL 0x01A0
+#define REG_C2HEVT_MSG_TEST 0x01B8
+#define REG_MCUTST_1 0x01c0
+#define REG_FMETHR 0x01C8
+#define REG_HMETFR 0x01CC
+#define REG_HMEBOX_0 0x01D0
+#define REG_HMEBOX_1 0x01D4
+#define REG_HMEBOX_2 0x01D8
+#define REG_HMEBOX_3 0x01DC
+
+#define REG_LLT_INIT 0x01E0
+#define REG_BB_ACCEESS_CTRL 0x01E8
+#define REG_BB_ACCESS_DATA 0x01EC
+
+#define REG_RQPN 0x0200
+#define REG_FIFOPAGE 0x0204
+#define REG_TDECTRL 0x0208
+#define REG_TXDMA_OFFSET_CHK 0x020C
+#define REG_TXDMA_STATUS 0x0210
+#define REG_RQPN_NPQ 0x0214
+
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define REG_RXPKT_NUM 0x0284
+#define REG_RXDMA_STATUS 0x0288
+
+#define REG_PCIE_CTRL_REG 0x0300
+#define REG_INT_MIG 0x0304
+#define REG_BCNQ_DESA 0x0308
+#define REG_HQ_DESA 0x0310
+#define REG_MGQ_DESA 0x0318
+#define REG_VOQ_DESA 0x0320
+#define REG_VIQ_DESA 0x0328
+#define REG_BEQ_DESA 0x0330
+#define REG_BKQ_DESA 0x0338
+#define REG_RX_DESA 0x0340
+#define REG_DBI 0x0348
+#define REG_MDIO 0x0354
+#define REG_DBG_SEL 0x0360
+#define REG_PCIE_HRPWM 0x0361
+#define REG_PCIE_HCPWM 0x0363
+#define REG_UART_CTRL 0x0364
+#define REG_UART_TX_DESA 0x0370
+#define REG_UART_RX_DESA 0x0378
+
+#define REG_HDAQ_DESA_NODEF 0x0000
+#define REG_CMDQ_DESA_NODEF 0x0000
+
+#define REG_VOQ_INFORMATION 0x0400
+#define REG_VIQ_INFORMATION 0x0404
+#define REG_BEQ_INFORMATION 0x0408
+#define REG_BKQ_INFORMATION 0x040C
+#define REG_MGQ_INFORMATION 0x0410
+#define REG_HGQ_INFORMATION 0x0414
+#define REG_BCNQ_INFORMATION 0x0418
+
+#define REG_CPU_MGQ_INFORMATION 0x041C
+#define REG_FWHW_TXQ_CTRL 0x0420
+#define REG_HWSEQ_CTRL 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY 0x0425
+#define REG_MULTI_BCNQ_EN 0x0426
+#define REG_MULTI_BCNQ_OFFSET 0x0427
+#define REG_SPEC_SIFS 0x0428
+#define REG_RL 0x042A
+#define REG_DARFRC 0x0430
+#define REG_RARFRC 0x0438
+#define REG_RRSR 0x0440
+#define REG_ARFR0 0x0444
+#define REG_ARFR1 0x0448
+#define REG_ARFR2 0x044C
+#define REG_ARFR3 0x0450
+#define REG_AGGLEN_LMT 0x0458
+#define REG_AMPDU_MIN_SPACE 0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
+#define REG_FAST_EDCA_CTRL 0x0460
+#define REG_RD_RESP_PKT_TH 0x0463
+#define REG_INIRTS_RATE_SEL 0x0480
+#define REG_INIDATA_RATE_SEL 0x0484
+#define REG_POWER_STATUS 0x04A4
+#define REG_POWER_STAGE1 0x04B4
+#define REG_POWER_STAGE2 0x04B8
+#define REG_PKT_LIFE_TIME 0x04C0
+#define REG_STBC_SETTING 0x04C4
+#define REG_PROT_MODE_CTRL 0x04C8
+#define REG_BAR_MODE_CTRL 0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
+#define REG_NQOS_SEQ 0x04DC
+#define REG_QOS_SEQ 0x04DE
+#define REG_NEED_CPU_HANDLE 0x04E0
+#define REG_PKT_LOSE_RPT 0x04E1
+#define REG_PTCL_ERR_STATUS 0x04E2
+#define REG_DUMMY 0x04FC
+
+#define REG_EDCA_VO_PARAM 0x0500
+#define REG_EDCA_VI_PARAM 0x0504
+#define REG_EDCA_BE_PARAM 0x0508
+#define REG_EDCA_BK_PARAM 0x050C
+#define REG_BCNTCFG 0x0510
+#define REG_PIFS 0x0512
+#define REG_RDG_PIFS 0x0513
+#define REG_SIFS_CTX 0x0514
+#define REG_SIFS_TRX 0x0516
+#define REG_AGGR_BREAK_TIME 0x051A
+#define REG_SLOT 0x051B
+#define REG_TX_PTCL_CTRL 0x0520
+#define REG_TXPAUSE 0x0522
+#define REG_DIS_TXREQ_CLR 0x0523
+#define REG_RD_CTRL 0x0524
+#define REG_TBTT_PROHIBIT 0x0540
+#define REG_RD_NAV_NXT 0x0544
+#define REG_NAV_PROT_LEN 0x0546
+#define REG_BCN_CTRL 0x0550
+#define REG_USTIME_TSF 0x0551
+#define REG_MBID_NUM 0x0552
+#define REG_DUAL_TSF_RST 0x0553
+#define REG_BCN_INTERVAL 0x0554
+#define REG_MBSSID_BCN_SPACE 0x0554
+#define REG_DRVERLYINT 0x0558
+#define REG_BCNDMATIM 0x0559
+#define REG_ATIMWND 0x055A
+#define REG_BCN_MAX_ERR 0x055D
+#define REG_RXTSF_OFFSET_CCK 0x055E
+#define REG_RXTSF_OFFSET_OFDM 0x055F
+#define REG_TSFTR 0x0560
+#define REG_INIT_TSFTR 0x0564
+#define REG_PSTIMER 0x0580
+#define REG_TIMER0 0x0584
+#define REG_TIMER1 0x0588
+#define REG_ACMHWCTRL 0x05C0
+#define REG_ACMRSTCTRL 0x05C1
+#define REG_ACMAVG 0x05C2
+#define REG_VO_ADMTIME 0x05C4
+#define REG_VI_ADMTIME 0x05C6
+#define REG_BE_ADMTIME 0x05C8
+#define REG_EDCA_RANDOM_GEN 0x05CC
+#define REG_SCH_TXCMD 0x05D0
+
+#define REG_APSD_CTRL 0x0600
+#define REG_BWOPMODE 0x0603
+#define REG_TCR 0x0604
+#define REG_RCR 0x0608
+#define REG_RX_PKT_LIMIT 0x060C
+#define REG_RX_DLK_TIME 0x060D
+#define REG_RX_DRVINFO_SZ 0x060F
+
+#define REG_MACID 0x0610
+#define REG_BSSID 0x0618
+#define REG_MAR 0x0620
+#define REG_MBIDCAMCFG 0x0628
+
+#define REG_USTIME_EDCA 0x0638
+#define REG_MAC_SPEC_SIFS 0x063A
+#define REG_RESP_SIFS_CCK 0x063C
+#define REG_RESP_SIFS_OFDM 0x063E
+#define REG_ACKTO 0x0640
+#define REG_CTS2TO 0x0641
+#define REG_EIFS 0x0642
+
+#define REG_NAV_CTRL 0x0650
+#define REG_BACAMCMD 0x0654
+#define REG_BACAMCONTENT 0x0658
+#define REG_LBDLY 0x0660
+#define REG_FWDLY 0x0661
+#define REG_RXERR_RPT 0x0664
+#define REG_WMAC_TRXPTCL_CTL 0x0668
+
+#define REG_CAMCMD 0x0670
+#define REG_CAMWRITE 0x0674
+#define REG_CAMREAD 0x0678
+#define REG_CAMDBG 0x067C
+#define REG_SECCFG 0x0680
+
+#define REG_WOW_CTRL 0x0690
+#define REG_PSSTATUS 0x0691
+#define REG_PS_RX_INFO 0x0692
+#define REG_LPNAV_CTRL 0x0694
+#define REG_WKFMCAM_CMD 0x0698
+#define REG_WKFMCAM_RWD 0x069C
+#define REG_RXFLTMAP0 0x06A0
+#define REG_RXFLTMAP1 0x06A2
+#define REG_RXFLTMAP2 0x06A4
+#define REG_BCN_PSR_RPT 0x06A8
+#define REG_CALB32K_CTRL 0x06AC
+#define REG_PKT_MON_CTRL 0x06B4
+#define REG_BT_COEX_TABLE 0x06C0
+#define REG_WMAC_RESP_TXINFO 0x06D8
+
+#define REG_USB_INFO 0xFE17
+#define REG_USB_SPECIAL_OPTION 0xFE55
+#define REG_USB_DMA_AGG_TO 0xFE5B
+#define REG_USB_AGG_TO 0xFE5C
+#define REG_USB_AGG_TH 0xFE5D
+
+#define REG_TEST_USB_TXQS 0xFE48
+#define REG_TEST_SIE_VID 0xFE60
+#define REG_TEST_SIE_PID 0xFE62
+#define REG_TEST_SIE_OPTIONAL 0xFE64
+#define REG_TEST_SIE_CHIRP_K 0xFE65
+#define REG_TEST_SIE_PHY 0xFE66
+#define REG_TEST_SIE_MAC_ADDR 0xFE70
+#define REG_TEST_SIE_STRING 0xFE80
+
+#define REG_NORMAL_SIE_VID 0xFE60
+#define REG_NORMAL_SIE_PID 0xFE62
+#define REG_NORMAL_SIE_OPTIONAL 0xFE64
+#define REG_NORMAL_SIE_EP 0xFE65
+#define REG_NORMAL_SIE_PHY 0xFE68
+#define REG_NORMAL_SIE_MAC_ADDR 0xFE70
+#define REG_NORMAL_SIE_STRING 0xFE80
+
+#define CR9346 REG_9346CR
+#define MSR (REG_CR + 2)
+#define ISR REG_HISR
+#define TSFR REG_TSFTR
+
+#define MACIDR0 REG_MACID
+#define MACIDR4 (REG_MACID + 4)
+
+#define PBP REG_PBP
+
+#define IDR0 MACIDR0
+#define IDR4 MACIDR4
+
+#define UNUSED_REGISTER 0x1BF
+#define DCAM UNUSED_REGISTER
+#define PSR UNUSED_REGISTER
+#define BBADDR UNUSED_REGISTER
+#define PHYDATAR UNUSED_REGISTER
+
+#define INVALID_BBRF_VALUE 0x12345678
+
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+#define CMDEEPROM_EN BIT(5)
+#define CMDEEPROM_SEL BIT(4)
+#define CMD9346CR_9356SEL BIT(4)
+#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL)
+#define AUTOLOAD_EFUSE CMDEEPROM_EN
+
+#define GPIOSEL_GPIO 0
+#define GPIOSEL_ENBT BIT(5)
+
+#define GPIO_IN REG_GPIO_PIN_CTRL
+#define GPIO_OUT (REG_GPIO_PIN_CTRL+1)
+#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2)
+#define GPIO_MOD (REG_GPIO_PIN_CTRL+3)
+
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
+#define RRSR_RSC_OFFSET 21
+#define RRSR_SHORT_OFFSET 23
+#define RRSR_RSC_BW_40M 0x600000
+#define RRSR_RSC_UPSUBCHNL 0x400000
+#define RRSR_RSC_LOWSUBCHNL 0x200000
+#define RRSR_SHORT 0x800000
+#define RRSR_1M BIT(0)
+#define RRSR_2M BIT(1)
+#define RRSR_5_5M BIT(2)
+#define RRSR_11M BIT(3)
+#define RRSR_6M BIT(4)
+#define RRSR_9M BIT(5)
+#define RRSR_12M BIT(6)
+#define RRSR_18M BIT(7)
+#define RRSR_24M BIT(8)
+#define RRSR_36M BIT(9)
+#define RRSR_48M BIT(10)
+#define RRSR_54M BIT(11)
+#define RRSR_MCS0 BIT(12)
+#define RRSR_MCS1 BIT(13)
+#define RRSR_MCS2 BIT(14)
+#define RRSR_MCS3 BIT(15)
+#define RRSR_MCS4 BIT(16)
+#define RRSR_MCS5 BIT(17)
+#define RRSR_MCS6 BIT(18)
+#define RRSR_MCS7 BIT(19)
+#define BRSR_ACKSHORTPMB BIT(23)
+
+#define RATR_1M 0x00000001
+#define RATR_2M 0x00000002
+#define RATR_55M 0x00000004
+#define RATR_11M 0x00000008
+#define RATR_6M 0x00000010
+#define RATR_9M 0x00000020
+#define RATR_12M 0x00000040
+#define RATR_18M 0x00000080
+#define RATR_24M 0x00000100
+#define RATR_36M 0x00000200
+#define RATR_48M 0x00000400
+#define RATR_54M 0x00000800
+#define RATR_MCS0 0x00001000
+#define RATR_MCS1 0x00002000
+#define RATR_MCS2 0x00004000
+#define RATR_MCS3 0x00008000
+#define RATR_MCS4 0x00010000
+#define RATR_MCS5 0x00020000
+#define RATR_MCS6 0x00040000
+#define RATR_MCS7 0x00080000
+#define RATR_MCS8 0x00100000
+#define RATR_MCS9 0x00200000
+#define RATR_MCS10 0x00400000
+#define RATR_MCS11 0x00800000
+#define RATR_MCS12 0x01000000
+#define RATR_MCS13 0x02000000
+#define RATR_MCS14 0x04000000
+#define RATR_MCS15 0x08000000
+
+#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\
+ RATR_24M | RATR_36M | RATR_48M | RATR_54M)
+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\
+ RATR_MCS6 | RATR_MCS7)
+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\
+ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\
+ RATR_MCS14 | RATR_MCS15)
+
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
+#define BW_OPMODE_11J BIT(0)
+
+#define CAM_VALID BIT(15)
+#define CAM_NOTVALID 0x0000
+#define CAM_USEDK BIT(5)
+
+#define CAM_NONE 0x0
+#define CAM_WEP40 0x01
+#define CAM_TKIP 0x02
+#define CAM_AES 0x04
+#define CAM_WEP104 0x05
+
+#define TOTAL_CAM_ENTRY 32
+#define HALF_CAM_ENTRY 16
+
+#define CAM_WRITE BIT(16)
+#define CAM_READ 0x00000000
+#define CAM_POLLINIG BIT(31)
+
+#define SCR_USEDK 0x01
+#define SCR_TXSEC_ENABLE 0x02
+#define SCR_RXSEC_ENABLE 0x04
+
+#define WOW_PMEN BIT(0)
+#define WOW_WOMEN BIT(1)
+#define WOW_MAGIC BIT(2)
+#define WOW_UWF BIT(3)
+
+#define IMR8190_DISABLED 0x0
+#define IMR_BCNDMAINT6 BIT(31)
+#define IMR_BCNDMAINT5 BIT(30)
+#define IMR_BCNDMAINT4 BIT(29)
+#define IMR_BCNDMAINT3 BIT(28)
+#define IMR_BCNDMAINT2 BIT(27)
+#define IMR_BCNDMAINT1 BIT(26)
+#define IMR_BCNDOK8 BIT(25)
+#define IMR_BCNDOK7 BIT(24)
+#define IMR_BCNDOK6 BIT(23)
+#define IMR_BCNDOK5 BIT(22)
+#define IMR_BCNDOK4 BIT(21)
+#define IMR_BCNDOK3 BIT(20)
+#define IMR_BCNDOK2 BIT(19)
+#define IMR_BCNDOK1 BIT(18)
+#define IMR_TIMEOUT2 BIT(17)
+#define IMR_TIMEOUT1 BIT(16)
+#define IMR_TXFOVW BIT(15)
+#define IMR_PSTIMEOUT BIT(14)
+#define IMR_BCNINT BIT(13)
+#define IMR_RXFOVW BIT(12)
+#define IMR_RDU BIT(11)
+#define IMR_ATIMEND BIT(10)
+#define IMR_BDOK BIT(9)
+#define IMR_HIGHDOK BIT(8)
+#define IMR_TBDOK BIT(7)
+#define IMR_MGNTDOK BIT(6)
+#define IMR_TBDER BIT(5)
+#define IMR_BKDOK BIT(4)
+#define IMR_BEDOK BIT(3)
+#define IMR_VIDOK BIT(2)
+#define IMR_VODOK BIT(1)
+#define IMR_ROK BIT(0)
+
+#define IMR_TXERR BIT(11)
+#define IMR_RXERR BIT(10)
+#define IMR_CPWM BIT(8)
+#define IMR_OCPINT BIT(1)
+#define IMR_WLANOFF BIT(0)
+
+/* 8723E series PCIE Host IMR/ISR bit */
+/* IMR DW0 Bit 0-31 */
+#define PHIMR_TIMEOUT2 BIT(31)
+#define PHIMR_TIMEOUT1 BIT(30)
+#define PHIMR_PSTIMEOUT BIT(29)
+#define PHIMR_GTINT4 BIT(28)
+#define PHIMR_GTINT3 BIT(27)
+#define PHIMR_TXBCNERR BIT(26)
+#define PHIMR_TXBCNOK BIT(25)
+#define PHIMR_TSF_BIT32_TOGGLE BIT(24)
+#define PHIMR_BCNDMAINT3 BIT(23)
+#define PHIMR_BCNDMAINT2 BIT(22)
+#define PHIMR_BCNDMAINT1 BIT(21)
+#define PHIMR_BCNDMAINT0 BIT(20)
+#define PHIMR_BCNDOK3 BIT(19)
+#define PHIMR_BCNDOK2 BIT(18)
+#define PHIMR_BCNDOK1 BIT(17)
+#define PHIMR_BCNDOK0 BIT(16)
+#define PHIMR_HSISR_IND_ON BIT(15)
+#define PHIMR_BCNDMAINT_E BIT(14)
+#define PHIMR_ATIMEND_E BIT(13)
+#define PHIMR_ATIM_CTW_END BIT(12)
+#define PHIMR_HISRE_IND BIT(11)
+#define PHIMR_C2HCMD BIT(10)
+#define PHIMR_CPWM2 BIT(9)
+#define PHIMR_CPWM BIT(8)
+#define PHIMR_HIGHDOK BIT(7)
+#define PHIMR_MGNTDOK BIT(6)
+#define PHIMR_BKDOK BIT(5)
+#define PHIMR_BEDOK BIT(4)
+#define PHIMR_VIDOK BIT(3)
+#define PHIMR_VODOK BIT(2)
+#define PHIMR_RDU BIT(1)
+#define PHIMR_ROK BIT(0)
+
+/* PCIE Host Interrupt Status Extension bit */
+#define PHIMR_BCNDMAINT7 BIT(23)
+#define PHIMR_BCNDMAINT6 BIT(22)
+#define PHIMR_BCNDMAINT5 BIT(21)
+#define PHIMR_BCNDMAINT4 BIT(20)
+#define PHIMR_BCNDOK7 BIT(19)
+#define PHIMR_BCNDOK6 BIT(18)
+#define PHIMR_BCNDOK5 BIT(17)
+#define PHIMR_BCNDOK4 BIT(16)
+/* bit12-15: RSVD */
+#define PHIMR_TXERR BIT(11)
+#define PHIMR_RXERR BIT(10)
+#define PHIMR_TXFOVW BIT(9)
+#define PHIMR_RXFOVW BIT(8)
+/* bit2-7: RSV */
+#define PHIMR_OCPINT BIT(1)
+
+#define HWSET_MAX_SIZE 256
+#define EFUSE_MAX_SECTION 32
+#define EFUSE_REAL_CONTENT_LEN 512
+#define EFUSE_OOB_PROTECT_BYTES 15
+
+#define EEPROM_DEFAULT_TSSI 0x0
+#define EEPROM_DEFAULT_TXPOWERDIFF 0x0
+#define EEPROM_DEFAULT_CRYSTALCAP 0x5
+#define EEPROM_DEFAULT_BOARDTYPE 0x02
+#define EEPROM_DEFAULT_TXPOWER 0x1010
+#define EEPROM_DEFAULT_HT2T_TXPWR 0x10
+
+#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3
+#define EEPROM_DEFAULT_THERMALMETER 0x12
+#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0
+#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5
+#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22
+#define EEPROM_DEFAULT_HT40_2SDIFF 0x0
+#define EEPROM_DEFAULT_HT20_DIFF 2
+#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0
+
+
+#define EEPROM_DEFAULT_PID 0x1234
+#define EEPROM_DEFAULT_VID 0x5678
+#define EEPROM_DEFAULT_CUSTOMERID 0xAB
+#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD
+#define EEPROM_DEFAULT_VERSION 0
+
+#define EEPROM_CHANNEL_PLAN_FCC 0x0
+#define EEPROM_CHANNEL_PLAN_IC 0x1
+#define EEPROM_CHANNEL_PLAN_ETSI 0x2
+#define EEPROM_CHANNEL_PLAN_SPAIN 0x3
+#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
+#define EEPROM_CHANNEL_PLAN_MKK 0x5
+#define EEPROM_CHANNEL_PLAN_MKK1 0x6
+#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
+#define EEPROM_CHANNEL_PLAN_TELEC 0x8
+#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
+#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
+#define EEPROM_CHANNEL_PLAN_NCC 0xB
+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_TOSHIBA 0x4
+#define EEPROM_CID_CCX 0x10
+#define EEPROM_CID_QMI 0x0D
+#define EEPROM_CID_WHQL 0xFE
+
+#define RTL8192_EEPROM_ID 0x8129
+
+#define RTL8190_EEPROM_ID 0x8129
+#define EEPROM_HPON 0x02
+#define EEPROM_CLK 0x06
+#define EEPROM_TESTR 0x08
+
+#define EEPROM_VID 0x49
+#define EEPROM_DID 0x4B
+#define EEPROM_SVID 0x4D
+#define EEPROM_SMID 0x4F
+
+#define EEPROM_MAC_ADDR 0x67
+
+#define EEPROM_CCK_TX_PWR_INX 0x5A
+#define EEPROM_HT40_1S_TX_PWR_INX 0x60
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66
+#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69
+#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C
+#define EEPROM_HT40_MAX_PWR_OFFSET 0x25
+#define EEPROM_HT20_MAX_PWR_OFFSET 0x22
+
+#define EEPROM_THERMAL_METER 0x2a
+#define EEPROM_XTAL_K 0x78
+#define EEPROM_RF_OPT1 0x79
+#define EEPROM_RF_OPT2 0x7A
+#define EEPROM_RF_OPT3 0x7B
+#define EEPROM_RF_OPT4 0x7C
+#define EEPROM_CHANNEL_PLAN 0x28
+#define EEPROM_VERSION 0x30
+#define EEPROM_CUSTOMER_ID 0x31
+
+#define EEPROM_PWRDIFF 0x54
+
+#define EEPROM_TXPOWERCCK 0x10
+#define EEPROM_TXPOWERHT40_1S 0x16
+#define EEPROM_TXPOWERHT40_2SDIFF 0x66
+#define EEPROM_TXPOWERHT20DIFF 0x1C
+#define EEPROM_TXPOWER_OFDMDIFF 0x1F
+
+#define EEPROM_TXPWR_GROUP 0x22
+
+#define EEPROM_TSSI_A 0x29
+#define EEPROM_TSSI_B 0x77
+
+#define EEPROM_CHANNELPLAN 0x28
+
+#define RF_OPTION1 0x2B
+#define RF_OPTION2 0x2C
+#define RF_OPTION3 0x2D
+#define RF_OPTION4 0x2E
+
+#define STOPBECON BIT(6)
+#define STOPHIGHT BIT(5)
+#define STOPMGT BIT(4)
+#define STOPVO BIT(3)
+#define STOPVI BIT(2)
+#define STOPBE BIT(1)
+#define STOPBK BIT(0)
+
+#define RCR_APPFCS BIT(31)
+#define RCR_APP_MIC BIT(30)
+#define RCR_APP_ICV BIT(29)
+#define RCR_APP_PHYST_RXFF BIT(28)
+#define RCR_APP_BA_SSN BIT(27)
+#define RCR_ENMBID BIT(24)
+#define RCR_LSIGEN BIT(23)
+#define RCR_MFBEN BIT(22)
+#define RCR_HTC_LOC_CTRL BIT(14)
+#define RCR_AMF BIT(13)
+#define RCR_ACF BIT(12)
+#define RCR_ADF BIT(11)
+#define RCR_AICV BIT(9)
+#define RCR_ACRC32 BIT(8)
+#define RCR_CBSSID_BCN BIT(7)
+#define RCR_CBSSID_DATA BIT(6)
+#define RCR_CBSSID RCR_CBSSID_DATA
+#define RCR_APWRMGT BIT(5)
+#define RCR_ADD3 BIT(4)
+#define RCR_AB BIT(3)
+#define RCR_AM BIT(2)
+#define RCR_APM BIT(1)
+#define RCR_AAP BIT(0)
+#define RCR_MXDMA_OFFSET 8
+#define RCR_FIFO_OFFSET 13
+
+#define RSV_CTRL 0x001C
+#define RD_CTRL 0x0524
+
+#define REG_USB_INFO 0xFE17
+#define REG_USB_SPECIAL_OPTION 0xFE55
+#define REG_USB_DMA_AGG_TO 0xFE5B
+#define REG_USB_AGG_TO 0xFE5C
+#define REG_USB_AGG_TH 0xFE5D
+
+#define REG_USB_VID 0xFE60
+#define REG_USB_PID 0xFE62
+#define REG_USB_OPTIONAL 0xFE64
+#define REG_USB_CHIRP_K 0xFE65
+#define REG_USB_PHY 0xFE66
+#define REG_USB_MAC_ADDR 0xFE70
+#define REG_USB_HRPWM 0xFE58
+#define REG_USB_HCPWM 0xFE57
+
+#define SW18_FPWM BIT(3)
+
+#define ISO_MD2PP BIT(0)
+#define ISO_UA2USB BIT(1)
+#define ISO_UD2CORE BIT(2)
+#define ISO_PA2PCIE BIT(3)
+#define ISO_PD2CORE BIT(4)
+#define ISO_IP2MAC BIT(5)
+#define ISO_DIOP BIT(6)
+#define ISO_DIOE BIT(7)
+#define ISO_EB2CORE BIT(8)
+#define ISO_DIOR BIT(9)
+
+#define PWC_EV25V BIT(14)
+#define PWC_EV12V BIT(15)
+
+#define FEN_BBRSTB BIT(0)
+#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_USBA BIT(2)
+#define FEN_UPLL BIT(3)
+#define FEN_USBD BIT(4)
+#define FEN_DIO_PCIE BIT(5)
+#define FEN_PCIEA BIT(6)
+#define FEN_PPLL BIT(7)
+#define FEN_PCIED BIT(8)
+#define FEN_DIOE BIT(9)
+#define FEN_CPUEN BIT(10)
+#define FEN_DCORE BIT(11)
+#define FEN_ELDR BIT(12)
+#define FEN_DIO_RF BIT(13)
+#define FEN_HWPDN BIT(14)
+#define FEN_MREGEN BIT(15)
+
+#define PFM_LDALL BIT(0)
+#define PFM_ALDN BIT(1)
+#define PFM_LDKP BIT(2)
+#define PFM_WOWL BIT(3)
+#define EnPDN BIT(4)
+#define PDN_PL BIT(5)
+#define APFM_ONMAC BIT(8)
+#define APFM_OFF BIT(9)
+#define APFM_RSM BIT(10)
+#define AFSM_HSUS BIT(11)
+#define AFSM_PCIE BIT(12)
+#define APDM_MAC BIT(13)
+#define APDM_HOST BIT(14)
+#define APDM_HPDN BIT(15)
+#define RDY_MACON BIT(16)
+#define SUS_HOST BIT(17)
+#define ROP_ALD BIT(20)
+#define ROP_PWR BIT(21)
+#define ROP_SPS BIT(22)
+#define SOP_MRST BIT(25)
+#define SOP_FUSE BIT(26)
+#define SOP_ABG BIT(27)
+#define SOP_AMB BIT(28)
+#define SOP_RCK BIT(29)
+#define SOP_A8M BIT(30)
+#define XOP_BTCK BIT(31)
+
+#define ANAD16V_EN BIT(0)
+#define ANA8M BIT(1)
+#define MACSLP BIT(4)
+#define LOADER_CLK_EN BIT(5)
+#define _80M_SSC_DIS BIT(7)
+#define _80M_SSC_EN_HO BIT(8)
+#define PHY_SSC_RSTB BIT(9)
+#define SEC_CLK_EN BIT(10)
+#define MAC_CLK_EN BIT(11)
+#define SYS_CLK_EN BIT(12)
+#define RING_CLK_EN BIT(13)
+
+#define BOOT_FROM_EEPROM BIT(4)
+#define EEPROM_EN BIT(5)
+
+#define AFE_BGEN BIT(0)
+#define AFE_MBEN BIT(1)
+#define MAC_ID_EN BIT(7)
+
+#define WLOCK_ALL BIT(0)
+#define WLOCK_00 BIT(1)
+#define WLOCK_04 BIT(2)
+#define WLOCK_08 BIT(3)
+#define WLOCK_40 BIT(4)
+#define R_DIS_PRST_0 BIT(5)
+#define R_DIS_PRST_1 BIT(6)
+#define LOCK_ALL_EN BIT(7)
+
+#define RF_EN BIT(0)
+#define RF_RSTB BIT(1)
+#define RF_SDMRSTB BIT(2)
+
+#define LDA15_EN BIT(0)
+#define LDA15_STBY BIT(1)
+#define LDA15_OBUF BIT(2)
+#define LDA15_REG_VOS BIT(3)
+#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
+
+#define LDV12_EN BIT(0)
+#define LDV12_SDBY BIT(1)
+#define LPLDO_HSM BIT(2)
+#define LPLDO_LSM_DIS BIT(3)
+#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
+
+#define XTAL_EN BIT(0)
+#define XTAL_BSEL BIT(1)
+#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
+#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
+#define XTAL_GATE_USB BIT(8)
+#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
+#define XTAL_GATE_AFE BIT(11)
+#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
+#define XTAL_RF_GATE BIT(14)
+#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
+#define XTAL_GATE_DIG BIT(17)
+#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
+#define XTAL_BT_GATE BIT(20)
+#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
+#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
+
+#define CKDLY_AFE BIT(26)
+#define CKDLY_USB BIT(27)
+#define CKDLY_DIG BIT(28)
+#define CKDLY_BT BIT(29)
+
+#define APLL_EN BIT(0)
+#define APLL_320_EN BIT(1)
+#define APLL_FREF_SEL BIT(2)
+#define APLL_EDGE_SEL BIT(3)
+#define APLL_WDOGB BIT(4)
+#define APLL_LPFEN BIT(5)
+
+#define APLL_REF_CLK_13MHZ 0x1
+#define APLL_REF_CLK_19_2MHZ 0x2
+#define APLL_REF_CLK_20MHZ 0x3
+#define APLL_REF_CLK_25MHZ 0x4
+#define APLL_REF_CLK_26MHZ 0x5
+#define APLL_REF_CLK_38_4MHZ 0x6
+#define APLL_REF_CLK_40MHZ 0x7
+
+#define APLL_320EN BIT(14)
+#define APLL_80EN BIT(15)
+#define APLL_1MEN BIT(24)
+
+#define ALD_EN BIT(18)
+#define EF_PD BIT(19)
+#define EF_FLAG BIT(31)
+
+#define EF_TRPT BIT(7)
+#define LDOE25_EN BIT(31)
+
+#define RSM_EN BIT(0)
+#define Timer_EN BIT(4)
+
+#define TRSW0EN BIT(2)
+#define TRSW1EN BIT(3)
+#define EROM_EN BIT(4)
+#define EnBT BIT(5)
+#define EnUart BIT(8)
+#define Uart_910 BIT(9)
+#define EnPMAC BIT(10)
+#define SIC_SWRST BIT(11)
+#define EnSIC BIT(12)
+#define SIC_23 BIT(13)
+#define EnHDP BIT(14)
+#define SIC_LBK BIT(15)
+
+#define LED0PL BIT(4)
+#define LED1PL BIT(12)
+#define LED0DIS BIT(7)
+
+#define MCUFWDL_EN BIT(0)
+#define MCUFWDL_RDY BIT(1)
+#define FWDL_ChkSum_rpt BIT(2)
+#define MACINI_RDY BIT(3)
+#define BBINI_RDY BIT(4)
+#define RFINI_RDY BIT(5)
+#define WINTINI_RDY BIT(6)
+#define CPRST BIT(23)
+
+#define XCLK_VLD BIT(0)
+#define ACLK_VLD BIT(1)
+#define UCLK_VLD BIT(2)
+#define PCLK_VLD BIT(3)
+#define PCIRSTB BIT(4)
+#define V15_VLD BIT(5)
+#define TRP_B15V_EN BIT(7)
+#define SIC_IDLE BIT(8)
+#define BD_MAC2 BIT(9)
+#define BD_MAC1 BIT(10)
+#define IC_MACPHY_MODE BIT(11)
+#define BT_FUNC BIT(16)
+#define VENDOR_ID BIT(19)
+#define PAD_HWPD_IDN BIT(22)
+#define TRP_VAUX_EN BIT(23)
+#define TRP_BT_EN BIT(24)
+#define BD_PKG_SEL BIT(25)
+#define BD_HCI_SEL BIT(26)
+#define TYPE_ID BIT(27)
+
+#define CHIP_VER_RTL_MASK 0xF000
+#define CHIP_VER_RTL_SHIFT 12
+
+#define REG_LBMODE (REG_CR + 3)
+
+#define HCI_TXDMA_EN BIT(0)
+#define HCI_RXDMA_EN BIT(1)
+#define TXDMA_EN BIT(2)
+#define RXDMA_EN BIT(3)
+#define PROTOCOL_EN BIT(4)
+#define SCHEDULE_EN BIT(5)
+#define MACTXEN BIT(6)
+#define MACRXEN BIT(7)
+#define ENSWBCN BIT(8)
+#define ENSEC BIT(9)
+
+#define _NETTYPE(x) (((x) & 0x3) << 16)
+#define MASK_NETTYPE 0x30000
+#define NT_NO_LINK 0x0
+#define NT_LINK_AD_HOC 0x1
+#define NT_LINK_AP 0x2
+#define NT_AS_AP 0x3
+
+#define _LBMODE(x) (((x) & 0xF) << 24)
+#define MASK_LBMODE 0xF000000
+#define LOOPBACK_NORMAL 0x0
+#define LOOPBACK_IMMEDIATELY 0xB
+#define LOOPBACK_MAC_DELAY 0x3
+#define LOOPBACK_PHY 0x1
+#define LOOPBACK_DMA 0x7
+
+#define GET_RX_PAGE_SIZE(value) ((value) & 0xF)
+#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4)
+#define _PSRX_MASK 0xF
+#define _PSTX_MASK 0xF0
+#define _PSRX(x) (x)
+#define _PSTX(x) ((x) << 4)
+
+#define PBP_64 0x0
+#define PBP_128 0x1
+#define PBP_256 0x2
+#define PBP_512 0x3
+#define PBP_1024 0x4
+
+#define RXDMA_ARBBW_EN BIT(0)
+#define RXSHFT_EN BIT(1)
+#define RXDMA_AGG_EN BIT(2)
+#define QS_VO_QUEUE BIT(8)
+#define QS_VI_QUEUE BIT(9)
+#define QS_BE_QUEUE BIT(10)
+#define QS_BK_QUEUE BIT(11)
+#define QS_MANAGER_QUEUE BIT(12)
+#define QS_HIGH_QUEUE BIT(13)
+
+#define HQSEL_VOQ BIT(0)
+#define HQSEL_VIQ BIT(1)
+#define HQSEL_BEQ BIT(2)
+#define HQSEL_BKQ BIT(3)
+#define HQSEL_MGTQ BIT(4)
+#define HQSEL_HIQ BIT(5)
+
+#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14)
+#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12)
+#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10)
+#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8)
+#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6)
+#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4)
+
+#define QUEUE_LOW 1
+#define QUEUE_NORMAL 2
+#define QUEUE_HIGH 3
+
+#define _LLT_NO_ACTIVE 0x0
+#define _LLT_WRITE_ACCESS 0x1
+#define _LLT_READ_ACCESS 0x2
+
+#define _LLT_INIT_DATA(x) ((x) & 0xFF)
+#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
+#define _LLT_OP(x) (((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
+
+#define BB_WRITE_READ_MASK (BIT(31) | BIT(30))
+#define BB_WRITE_EN BIT(30)
+#define BB_READ_EN BIT(31)
+
+#define _HPQ(x) ((x) & 0xFF)
+#define _LPQ(x) (((x) & 0xFF) << 8)
+#define _PUBQ(x) (((x) & 0xFF) << 16)
+#define _NPQ(x) ((x) & 0xFF)
+
+#define HPQ_PUBLIC_DIS BIT(24)
+#define LPQ_PUBLIC_DIS BIT(25)
+#define LD_RQPN BIT(31)
+
+#define BCN_VALID BIT(16)
+#define BCN_HEAD(x) (((x) & 0xFF) << 8)
+#define BCN_HEAD_MASK 0xFF00
+
+#define BLK_DESC_NUM_SHIFT 4
+#define BLK_DESC_NUM_MASK 0xF
+
+#define DROP_DATA_EN BIT(9)
+
+#define EN_AMPDU_RTY_NEW BIT(7)
+
+#define _INIRTSMCS_SEL(x) ((x) & 0x3F)
+
+#define _SPEC_SIFS_CCK(x) ((x) & 0xFF)
+#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8)
+
+#define RATE_REG_BITMAP_ALL 0xFFFFF
+
+#define _RRSC_BITMAP(x) ((x) & 0xFFFFF)
+
+#define _RRSR_RSC(x) (((x) & 0x3) << 21)
+#define RRSR_RSC_RESERVED 0x0
+#define RRSR_RSC_UPPER_SUBCHANNEL 0x1
+#define RRSR_RSC_LOWER_SUBCHANNEL 0x2
+#define RRSR_RSC_DUPLICATE_MODE 0x3
+
+#define USE_SHORT_G1 BIT(20)
+
+#define _AGGLMT_MCS0(x) ((x) & 0xF)
+#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4)
+#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8)
+#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12)
+#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16)
+#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20)
+#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24)
+#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28)
+
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_LONG_SHIFT 0
+
+#define _DARF_RC1(x) ((x) & 0x1F)
+#define _DARF_RC2(x) (((x) & 0x1F) << 8)
+#define _DARF_RC3(x) (((x) & 0x1F) << 16)
+#define _DARF_RC4(x) (((x) & 0x1F) << 24)
+#define _DARF_RC5(x) ((x) & 0x1F)
+#define _DARF_RC6(x) (((x) & 0x1F) << 8)
+#define _DARF_RC7(x) (((x) & 0x1F) << 16)
+#define _DARF_RC8(x) (((x) & 0x1F) << 24)
+
+#define _RARF_RC1(x) ((x) & 0x1F)
+#define _RARF_RC2(x) (((x) & 0x1F) << 8)
+#define _RARF_RC3(x) (((x) & 0x1F) << 16)
+#define _RARF_RC4(x) (((x) & 0x1F) << 24)
+#define _RARF_RC5(x) ((x) & 0x1F)
+#define _RARF_RC6(x) (((x) & 0x1F) << 8)
+#define _RARF_RC7(x) (((x) & 0x1F) << 16)
+#define _RARF_RC8(x) (((x) & 0x1F) << 24)
+
+#define AC_PARAM_TXOP_LIMIT_OFFSET 16
+#define AC_PARAM_ECW_MAX_OFFSET 12
+#define AC_PARAM_ECW_MIN_OFFSET 8
+#define AC_PARAM_AIFS_OFFSET 0
+
+#define _AIFS(x) (x)
+#define _ECW_MAX_MIN(x) ((x) << 8)
+#define _TXOP_LIMIT(x) ((x) << 16)
+
+#define _BCNIFS(x) ((x) & 0xFF)
+#define _BCNECW(x) ((((x) & 0xF)) << 8)
+
+#define _LRL(x) ((x) & 0x3F)
+#define _SRL(x) (((x) & 0x3F) << 8)
+
+#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
+#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8);
+
+#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
+#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8);
+
+#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
+
+#define DIS_EDCA_CNT_DWN BIT(11)
+
+#define EN_MBSSID BIT(1)
+#define EN_TXBCN_RPT BIT(2)
+#define EN_BCN_FUNCTION BIT(3)
+
+#define TSFTR_RST BIT(0)
+#define TSFTR1_RST BIT(1)
+
+#define STOP_BCNQ BIT(6)
+
+#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4)
+#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
+
+#define AcmHw_HwEn BIT(0)
+#define AcmHw_BeqEn BIT(1)
+#define AcmHw_ViqEn BIT(2)
+#define AcmHw_VoqEn BIT(3)
+#define AcmHw_BeqStatus BIT(4)
+#define AcmHw_ViqStatus BIT(5)
+#define AcmHw_VoqStatus BIT(6)
+
+#define APSDOFF BIT(6)
+#define APSDOFF_STATUS BIT(7)
+
+#define BW_20MHZ BIT(2)
+
+#define RATE_BITMAP_ALL 0xFFFFF
+
+#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1
+
+#define TSFRST BIT(0)
+#define DIS_GCLK BIT(1)
+#define PAD_SEL BIT(2)
+#define PWR_ST BIT(6)
+#define PWRBIT_OW_EN BIT(7)
+#define ACRC BIT(8)
+#define CFENDFORM BIT(9)
+#define ICV BIT(10)
+
+#define AAP BIT(0)
+#define APM BIT(1)
+#define AM BIT(2)
+#define AB BIT(3)
+#define ADD3 BIT(4)
+#define APWRMGT BIT(5)
+#define CBSSID BIT(6)
+#define CBSSID_DATA BIT(6)
+#define CBSSID_BCN BIT(7)
+#define ACRC32 BIT(8)
+#define AICV BIT(9)
+#define ADF BIT(11)
+#define ACF BIT(12)
+#define AMF BIT(13)
+#define HTC_LOC_CTRL BIT(14)
+#define UC_DATA_EN BIT(16)
+#define BM_DATA_EN BIT(17)
+#define MFBEN BIT(22)
+#define LSIGEN BIT(23)
+#define EnMBID BIT(24)
+#define APP_BASSN BIT(27)
+#define APP_PHYSTS BIT(28)
+#define APP_ICV BIT(29)
+#define APP_MIC BIT(30)
+#define APP_FCS BIT(31)
+
+#define _MIN_SPACE(x) ((x) & 0x7)
+#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3)
+
+#define RXERR_TYPE_OFDM_PPDU 0
+#define RXERR_TYPE_OFDM_FALSE_ALARM 1
+#define RXERR_TYPE_OFDM_MPDU_OK 2
+#define RXERR_TYPE_OFDM_MPDU_FAIL 3
+#define RXERR_TYPE_CCK_PPDU 4
+#define RXERR_TYPE_CCK_FALSE_ALARM 5
+#define RXERR_TYPE_CCK_MPDU_OK 6
+#define RXERR_TYPE_CCK_MPDU_FAIL 7
+#define RXERR_TYPE_HT_PPDU 8
+#define RXERR_TYPE_HT_FALSE_ALARM 9
+#define RXERR_TYPE_HT_MPDU_TOTAL 10
+#define RXERR_TYPE_HT_MPDU_OK 11
+#define RXERR_TYPE_HT_MPDU_FAIL 12
+#define RXERR_TYPE_RX_FULL_DROP 15
+
+#define RXERR_COUNTER_MASK 0xFFFFF
+#define RXERR_RPT_RST BIT(27)
+#define _RXERR_RPT_SEL(type) ((type) << 28)
+
+#define SCR_TxUseDK BIT(0)
+#define SCR_RxUseDK BIT(1)
+#define SCR_TxEncEnable BIT(2)
+#define SCR_RxDecEnable BIT(3)
+#define SCR_SKByA2 BIT(4)
+#define SCR_NoSKMC BIT(5)
+#define SCR_TXBCUSEDK BIT(6)
+#define SCR_RXBCUSEDK BIT(7)
+
+#define USB_IS_HIGH_SPEED 0
+#define USB_IS_FULL_SPEED 1
+#define USB_SPEED_MASK BIT(5)
+
+#define USB_NORMAL_SIE_EP_MASK 0xF
+#define USB_NORMAL_SIE_EP_SHIFT 4
+
+#define USB_TEST_EP_MASK 0x30
+#define USB_TEST_EP_SHIFT 4
+
+#define USB_AGG_EN BIT(3)
+
+#define MAC_ADDR_LEN 6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER 255
+
+#define POLLING_LLT_THRESHOLD 20
+#define POLLING_READY_TIMEOUT_COUNT 1000
+
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
+#define EPROM_CMD_CONFIG 0x3
+#define EPROM_CMD_LOAD 1
+
+#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE
+
+#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2)
+
+#define RPMAC_RESET 0x100
+#define RPMAC_TXSTART 0x104
+#define RPMAC_TXLEGACYSIG 0x108
+#define RPMAC_TXHTSIG1 0x10c
+#define RPMAC_TXHTSIG2 0x110
+#define RPMAC_PHYDEBUG 0x114
+#define RPMAC_TXPACKETNUM 0x118
+#define RPMAC_TXIDLE 0x11c
+#define RPMAC_TXMACHEADER0 0x120
+#define RPMAC_TXMACHEADER1 0x124
+#define RPMAC_TXMACHEADER2 0x128
+#define RPMAC_TXMACHEADER3 0x12c
+#define RPMAC_TXMACHEADER4 0x130
+#define RPMAC_TXMACHEADER5 0x134
+#define RPMAC_TXDADATYPE 0x138
+#define RPMAC_TXRANDOMSEED 0x13c
+#define RPMAC_CCKPLCPPREAMBLE 0x140
+#define RPMAC_CCKPLCPHEADER 0x144
+#define RPMAC_CCKCRC16 0x148
+#define RPMAC_OFDMRXCRC32OK 0x170
+#define RPMAC_OFDMRXCRC32Er 0x174
+#define RPMAC_OFDMRXPARITYER 0x178
+#define RPMAC_OFDMRXCRC8ER 0x17c
+#define RPMAC_CCKCRXRC16ER 0x180
+#define RPMAC_CCKCRXRC32ER 0x184
+#define RPMAC_CCKCRXRC32OK 0x188
+#define RPMAC_TXSTATUS 0x18c
+
+#define RFPGA0_RFMOD 0x800
+
+#define RFPGA0_TXINFO 0x804
+#define RFPGA0_PSDFUNCTION 0x808
+
+#define RFPGA0_TXGAINSTAGE 0x80c
+
+#define RFPGA0_RFTIMING1 0x810
+#define RFPGA0_RFTIMING2 0x814
+
+#define RFPGA0_XA_HSSIPARAMETER1 0x820
+#define RFPGA0_XA_HSSIPARAMETER2 0x824
+#define RFPGA0_XB_HSSIPARAMETER1 0x828
+#define RFPGA0_XB_HSSIPARAMETER2 0x82c
+
+#define RFPGA0_XA_LSSIPARAMETER 0x840
+#define RFPGA0_XB_LSSIPARAMETER 0x844
+
+#define RFPGA0_RFWAKEUPPARAMETER 0x850
+#define RFPGA0_RFSLEEPUPPARAMETER 0x854
+
+#define RFPGA0_XAB_SWITCHCONTROL 0x858
+#define RFPGA0_XCD_SWITCHCONTROL 0x85c
+
+#define RFPGA0_XA_RFINTERFACEOE 0x860
+#define RFPGA0_XB_RFINTERFACEOE 0x864
+
+#define RFPGA0_XAB_RFINTERFACESW 0x870
+#define RFPGA0_XCD_RFINTERFACESW 0x874
+
+#define rFPGA0_XAB_RFPARAMETER 0x878
+#define rFPGA0_XCD_RFPARAMETER 0x87c
+
+#define RFPGA0_ANALOGPARAMETER1 0x880
+#define RFPGA0_ANALOGPARAMETER2 0x884
+#define RFPGA0_ANALOGPARAMETER3 0x888
+#define RFPGA0_ANALOGPARAMETER4 0x88c
+
+#define RFPGA0_XA_LSSIREADBACK 0x8a0
+#define RFPGA0_XB_LSSIREADBACK 0x8a4
+#define RFPGA0_XC_LSSIREADBACK 0x8a8
+#define RFPGA0_XD_LSSIREADBACK 0x8ac
+
+#define RFPGA0_PSDREPORT 0x8b4
+#define TRANSCEIVEA_HSPI_READBACK 0x8b8
+#define TRANSCEIVEB_HSPI_READBACK 0x8bc
+#define RFPGA0_XAB_RFINTERFACERB 0x8e0
+#define RFPGA0_XCD_RFINTERFACERB 0x8e4
+
+#define RFPGA1_RFMOD 0x900
+
+#define RFPGA1_TXBLOCK 0x904
+#define RFPGA1_DEBUGSELECT 0x908
+#define RFPGA1_TXINFO 0x90c
+
+#define RCCK0_SYSTEM 0xa00
+
+#define RCCK0_AFESETTING 0xa04
+#define RCCK0_CCA 0xa08
+
+#define RCCK0_RXAGC1 0xa0c
+#define RCCK0_RXAGC2 0xa10
+
+#define RCCK0_RXHP 0xa14
+
+#define RCCK0_DSPPARAMETER1 0xa18
+#define RCCK0_DSPPARAMETER2 0xa1c
+
+#define RCCK0_TXFILTER1 0xa20
+#define RCCK0_TXFILTER2 0xa24
+#define RCCK0_DEBUGPORT 0xa28
+#define RCCK0_FALSEALARMREPORT 0xa2c
+#define RCCK0_TRSSIREPORT 0xa50
+#define RCCK0_RXREPORT 0xa54
+#define RCCK0_FACOUNTERLOWER 0xa5c
+#define RCCK0_FACOUNTERUPPER 0xa58
+
+#define ROFDM0_LSTF 0xc00
+
+#define ROFDM0_TRXPATHENABLE 0xc04
+#define ROFDM0_TRMUXPAR 0xc08
+#define ROFDM0_TRSWISOLATION 0xc0c
+
+#define ROFDM0_XARXAFE 0xc10
+#define ROFDM0_XARXIQIMBALANCE 0xc14
+#define ROFDM0_XBRXAFE 0xc18
+#define ROFDM0_XBRXIQIMBALANCE 0xc1c
+#define ROFDM0_XCRXAFE 0xc20
+#define ROFDM0_XCRXIQIMBANLANCE 0xc24
+#define ROFDM0_XDRXAFE 0xc28
+#define ROFDM0_XDRXIQIMBALANCE 0xc2c
+
+#define ROFDM0_RXDETECTOR1 0xc30
+#define ROFDM0_RXDETECTOR2 0xc34
+#define ROFDM0_RXDETECTOR3 0xc38
+#define ROFDM0_RXDETECTOR4 0xc3c
+
+#define ROFDM0_RXDSP 0xc40
+#define ROFDM0_CFOANDDAGC 0xc44
+#define ROFDM0_CCADROPTHRESHOLD 0xc48
+#define ROFDM0_ECCATHRESHOLD 0xc4c
+
+#define ROFDM0_XAAGCCORE1 0xc50
+#define ROFDM0_XAAGCCORE2 0xc54
+#define ROFDM0_XBAGCCORE1 0xc58
+#define ROFDM0_XBAGCCORE2 0xc5c
+#define ROFDM0_XCAGCCORE1 0xc60
+#define ROFDM0_XCAGCCORE2 0xc64
+#define ROFDM0_XDAGCCORE1 0xc68
+#define ROFDM0_XDAGCCORE2 0xc6c
+
+#define ROFDM0_AGCPARAMETER1 0xc70
+#define ROFDM0_AGCPARAMETER2 0xc74
+#define ROFDM0_AGCRSSITABLE 0xc78
+#define ROFDM0_HTSTFAGC 0xc7c
+
+#define ROFDM0_XATXIQIMBALANCE 0xc80
+#define ROFDM0_XATXAFE 0xc84
+#define ROFDM0_XBTXIQIMBALANCE 0xc88
+#define ROFDM0_XBTXAFE 0xc8c
+#define ROFDM0_XCTXIQIMBALANCE 0xc90
+#define ROFDM0_XCTXAFE 0xc94
+#define ROFDM0_XDTXIQIMBALANCE 0xc98
+#define ROFDM0_XDTXAFE 0xc9c
+
+#define ROFDM0_RXIQEXTANTA 0xca0
+
+#define ROFDM0_RXHPPARAMETER 0xce0
+#define ROFDM0_TXPSEUDONOISEWGT 0xce4
+#define ROFDM0_FRAMESYNC 0xcf0
+#define ROFDM0_DFSREPORT 0xcf4
+#define ROFDM0_TXCOEFF1 0xca4
+#define ROFDM0_TXCOEFF2 0xca8
+#define ROFDM0_TXCOEFF3 0xcac
+#define ROFDM0_TXCOEFF4 0xcb0
+#define ROFDM0_TXCOEFF5 0xcb4
+#define ROFDM0_TXCOEFF6 0xcb8
+
+#define ROFDM1_LSTF 0xd00
+#define ROFDM1_TRXPATHENABLE 0xd04
+
+#define ROFDM1_CF0 0xd08
+#define ROFDM1_CSI1 0xd10
+#define ROFDM1_SBD 0xd14
+#define ROFDM1_CSI2 0xd18
+#define ROFDM1_CFOTRACKING 0xd2c
+#define ROFDM1_TRXMESAURE1 0xd34
+#define ROFDM1_INTFDET 0xd3c
+#define ROFDM1_PSEUDONOISESTATEAB 0xd50
+#define ROFDM1_PSEUDONOISESTATECD 0xd54
+#define ROFDM1_RXPSEUDONOISEWGT 0xd58
+
+#define ROFDM_PHYCOUNTER1 0xda0
+#define ROFDM_PHYCOUNTER2 0xda4
+#define ROFDM_PHYCOUNTER3 0xda8
+
+#define ROFDM_SHORTCFOAB 0xdac
+#define ROFDM_SHORTCFOCD 0xdb0
+#define ROFDM_LONGCFOAB 0xdb4
+#define ROFDM_LONGCFOCD 0xdb8
+#define ROFDM_TAILCF0AB 0xdbc
+#define ROFDM_TAILCF0CD 0xdc0
+#define ROFDM_PWMEASURE1 0xdc4
+#define ROFDM_PWMEASURE2 0xdc8
+#define ROFDM_BWREPORT 0xdcc
+#define ROFDM_AGCREPORT 0xdd0
+#define ROFDM_RXSNR 0xdd4
+#define ROFDM_RXEVMCSI 0xdd8
+#define ROFDM_SIGREPORT 0xddc
+
+#define RTXAGC_A_RATE18_06 0xe00
+#define RTXAGC_A_RATE54_24 0xe04
+#define RTXAGC_A_CCK1_MCS32 0xe08
+#define RTXAGC_A_MCS03_MCS00 0xe10
+#define RTXAGC_A_MCS07_MCS04 0xe14
+#define RTXAGC_A_MCS11_MCS08 0xe18
+#define RTXAGC_A_MCS15_MCS12 0xe1c
+
+#define RTXAGC_B_RATE18_06 0x830
+#define RTXAGC_B_RATE54_24 0x834
+#define RTXAGC_B_CCK1_55_MCS32 0x838
+#define RTXAGC_B_MCS03_MCS00 0x83c
+#define RTXAGC_B_MCS07_MCS04 0x848
+#define RTXAGC_B_MCS11_MCS08 0x84c
+#define RTXAGC_B_MCS15_MCS12 0x868
+#define RTXAGC_B_CCK11_A_CCK2_11 0x86c
+
+#define RZEBRA1_HSSIENABLE 0x0
+#define RZEBRA1_TRXENABLE1 0x1
+#define RZEBRA1_TRXENABLE2 0x2
+#define RZEBRA1_AGC 0x4
+#define RZEBRA1_CHARGEPUMP 0x5
+#define RZEBRA1_CHANNEL 0x7
+
+#define RZEBRA1_TXGAIN 0x8
+#define RZEBRA1_TXLPF 0x9
+#define RZEBRA1_RXLPF 0xb
+#define RZEBRA1_RXHPFCORNER 0xc
+
+#define RGLOBALCTRL 0
+#define RRTL8256_TXLPF 19
+#define RRTL8256_RXLPF 11
+#define RRTL8258_TXLPF 0x11
+#define RRTL8258_RXLPF 0x13
+#define RRTL8258_RSSILPF 0xa
+
+#define RF_AC 0x00
+
+#define RF_IQADJ_G1 0x01
+#define RF_IQADJ_G2 0x02
+#define RF_POW_TRSW 0x05
+
+#define RF_GAIN_RX 0x06
+#define RF_GAIN_TX 0x07
+
+#define RF_TXM_IDAC 0x08
+#define RF_BS_IQGEN 0x0F
+
+#define RF_MODE1 0x10
+#define RF_MODE2 0x11
+
+#define RF_RX_AGC_HP 0x12
+#define RF_TX_AGC 0x13
+#define RF_BIAS 0x14
+#define RF_IPA 0x15
+#define RF_POW_ABILITY 0x17
+#define RF_MODE_AG 0x18
+#define RRFCHANNEL 0x18
+#define RF_CHNLBW 0x18
+#define RF_TOP 0x19
+
+#define RF_RX_G1 0x1A
+#define RF_RX_G2 0x1B
+
+#define RF_RX_BB2 0x1C
+#define RF_RX_BB1 0x1D
+
+#define RF_RCK1 0x1E
+#define RF_RCK2 0x1F
+
+#define RF_TX_G1 0x20
+#define RF_TX_G2 0x21
+#define RF_TX_G3 0x22
+
+#define RF_TX_BB1 0x23
+#define RF_T_METER 0x24
+
+#define RF_SYN_G1 0x25
+#define RF_SYN_G2 0x26
+#define RF_SYN_G3 0x27
+#define RF_SYN_G4 0x28
+#define RF_SYN_G5 0x29
+#define RF_SYN_G6 0x2A
+#define RF_SYN_G7 0x2B
+#define RF_SYN_G8 0x2C
+
+#define RF_RCK_OS 0x30
+#define RF_TXPA_G1 0x31
+#define RF_TXPA_G2 0x32
+#define RF_TXPA_G3 0x33
+
+#define BBBRESETB 0x100
+#define BGLOBALRESETB 0x200
+#define BOFDMTXSTART 0x4
+#define BCCKTXSTART 0x8
+#define BCRC32DEBUG 0x100
+#define BPMACLOOPBACK 0x10
+#define BTXLSIG 0xffffff
+#define BOFDMTXRATE 0xf
+#define BOFDMTXRESERVED 0x10
+#define BOFDMTXLENGTH 0x1ffe0
+#define BOFDMTXPARITY 0x20000
+#define BTXHTSIG1 0xffffff
+#define BTXHTMCSRATE 0x7f
+#define BTXHTBW 0x80
+#define BTXHTLENGTH 0xffff00
+#define BTXHTSIG2 0xffffff
+#define BTXHTSMOOTHING 0x1
+#define BTXHTSOUNDING 0x2
+#define BTXHTRESERVED 0x4
+#define BTXHTAGGREATION 0x8
+#define BTXHTSTBC 0x30
+#define BTXHTADVANCECODING 0x40
+#define BTXHTSHORTGI 0x80
+#define BTXHTNUMBERHT_LTF 0x300
+#define BTXHTCRC8 0x3fc00
+#define BCOUNTERRESET 0x10000
+#define BNUMOFOFDMTX 0xffff
+#define BNUMOFCCKTX 0xffff0000
+#define BTXIDLEINTERVAL 0xffff
+#define BOFDMSERVICE 0xffff0000
+#define BTXMACHEADER 0xffffffff
+#define BTXDATAINIT 0xff
+#define BTXHTMODE 0x100
+#define BTXDATATYPE 0x30000
+#define BTXRANDOMSEED 0xffffffff
+#define BCCKTXPREAMBLE 0x1
+#define BCCKTXSFD 0xffff0000
+#define BCCKTXSIG 0xff
+#define BCCKTXSERVICE 0xff00
+#define BCCKLENGTHEXT 0x8000
+#define BCCKTXLENGHT 0xffff0000
+#define BCCKTXCRC16 0xffff
+#define BCCKTXSTATUS 0x1
+#define BOFDMTXSTATUS 0x2
+#define IS_BB_REG_OFFSET_92S(_Offset) \
+ ((_Offset >= 0x800) && (_Offset <= 0xfff))
+
+#define BRFMOD 0x1
+#define BJAPANMODE 0x2
+#define BCCKTXSC 0x30
+#define BCCKEN 0x1000000
+#define BOFDMEN 0x2000000
+
+#define BOFDMRXADCPHASE 0x10000
+#define BOFDMTXDACPHASE 0x40000
+#define BXATXAGC 0x3f
+
+#define BXBTXAGC 0xf00
+#define BXCTXAGC 0xf000
+#define BXDTXAGC 0xf0000
+
+#define BPASTART 0xf0000000
+#define BTRSTART 0x00f00000
+#define BRFSTART 0x0000f000
+#define BBBSTART 0x000000f0
+#define BBBCCKSTART 0x0000000f
+#define BPAEND 0xf
+#define BTREND 0x0f000000
+#define BRFEND 0x000f0000
+#define BCCAMASK 0x000000f0
+#define BR2RCCAMASK 0x00000f00
+#define BHSSI_R2TDELAY 0xf8000000
+#define BHSSI_T2RDELAY 0xf80000
+#define BCONTXHSSI 0x400
+#define BIGFROMCCK 0x200
+#define BAGCADDRESS 0x3f
+#define BRXHPTX 0x7000
+#define BRXHP2RX 0x38000
+#define BRXHPCCKINI 0xc0000
+#define BAGCTXCODE 0xc00000
+#define BAGCRXCODE 0x300000
+
+#define B3WIREDATALENGTH 0x800
+#define B3WIREADDREAALENGTH 0x400
+
+#define B3WIRERFPOWERDOWN 0x1
+#define B5GPAPEPOLARITY 0x40000000
+#define B2GPAPEPOLARITY 0x80000000
+#define BRFSW_TXDEFAULTANT 0x3
+#define BRFSW_TXOPTIONANT 0x30
+#define BRFSW_RXDEFAULTANT 0x300
+#define BRFSW_RXOPTIONANT 0x3000
+#define BRFSI_3WIREDATA 0x1
+#define BRFSI_3WIRECLOCK 0x2
+#define BRFSI_3WIRELOAD 0x4
+#define BRFSI_3WIRERW 0x8
+#define BRFSI_3WIRE 0xf
+
+#define BRFSI_RFENV 0x10
+
+#define BRFSI_TRSW 0x20
+#define BRFSI_TRSWB 0x40
+#define BRFSI_ANTSW 0x100
+#define BRFSI_ANTSWB 0x200
+#define BRFSI_PAPE 0x400
+#define BRFSI_PAPE5G 0x800
+#define BBANDSELECT 0x1
+#define BHTSIG2_GI 0x80
+#define BHTSIG2_SMOOTHING 0x01
+#define BHTSIG2_SOUNDING 0x02
+#define BHTSIG2_AGGREATON 0x08
+#define BHTSIG2_STBC 0x30
+#define BHTSIG2_ADVCODING 0x40
+#define BHTSIG2_NUMOFHTLTF 0x300
+#define BHTSIG2_CRC8 0x3fc
+#define BHTSIG1_MCS 0x7f
+#define BHTSIG1_BANDWIDTH 0x80
+#define BHTSIG1_HTLENGTH 0xffff
+#define BLSIG_RATE 0xf
+#define BLSIG_RESERVED 0x10
+#define BLSIG_LENGTH 0x1fffe
+#define BLSIG_PARITY 0x20
+#define BCCKRXPHASE 0x4
+
+#define BLSSIREADADDRESS 0x7f800000
+#define BLSSIREADEDGE 0x80000000
+
+#define BLSSIREADBACKDATA 0xfffff
+
+#define BLSSIREADOKFLAG 0x1000
+#define BCCKSAMPLERATE 0x8
+#define BREGULATOR0STANDBY 0x1
+#define BREGULATORPLLSTANDBY 0x2
+#define BREGULATOR1STANDBY 0x4
+#define BPLLPOWERUP 0x8
+#define BDPLLPOWERUP 0x10
+#define BDA10POWERUP 0x20
+#define BAD7POWERUP 0x200
+#define BDA6POWERUP 0x2000
+#define BXTALPOWERUP 0x4000
+#define B40MDCLKPOWERUP 0x8000
+#define BDA6DEBUGMODE 0x20000
+#define BDA6SWING 0x380000
+
+#define BADCLKPHASE 0x4000000
+#define B80MCLKDELAY 0x18000000
+#define BAFEWATCHDOGENABLE 0x20000000
+
+#define BXTALCAP01 0xc0000000
+#define BXTALCAP23 0x3
+#define BXTALCAP92X 0x0f000000
+#define BXTALCAP 0x0f000000
+
+#define BINTDIFCLKENABLE 0x400
+#define BEXTSIGCLKENABLE 0x800
+#define BBANDGAP_MBIAS_POWERUP 0x10000
+#define BAD11SH_GAIN 0xc0000
+#define BAD11NPUT_RANGE 0x700000
+#define BAD110P_CURRENT 0x3800000
+#define BLPATH_LOOPBACK 0x4000000
+#define BQPATH_LOOPBACK 0x8000000
+#define BAFE_LOOPBACK 0x10000000
+#define BDA10_SWING 0x7e0
+#define BDA10_REVERSE 0x800
+#define BDA_CLK_SOURCE 0x1000
+#define BDA7INPUT_RANGE 0x6000
+#define BDA7_GAIN 0x38000
+#define BDA7OUTPUT_CM_MODE 0x40000
+#define BDA7INPUT_CM_MODE 0x380000
+#define BDA7CURRENT 0xc00000
+#define BREGULATOR_ADJUST 0x7000000
+#define BAD11POWERUP_ATTX 0x1
+#define BDA10PS_ATTX 0x10
+#define BAD11POWERUP_ATRX 0x100
+#define BDA10PS_ATRX 0x1000
+#define BCCKRX_AGC_FORMAT 0x200
+#define BPSDFFT_SAMPLE_POINT 0xc000
+#define BPSD_AVERAGE_NUM 0x3000
+#define BIQPATH_CONTROL 0xc00
+#define BPSD_FREQ 0x3ff
+#define BPSD_ANTENNA_PATH 0x30
+#define BPSD_IQ_SWITCH 0x40
+#define BPSD_RX_TRIGGER 0x400000
+#define BPSD_TX_TRIGGER 0x80000000
+#define BPSD_SINE_TONE_SCALE 0x7f000000
+#define BPSD_REPORT 0xffff
+
+#define BOFDM_TXSC 0x30000000
+#define BCCK_TXON 0x1
+#define BOFDM_TXON 0x2
+#define BDEBUG_PAGE 0xfff
+#define BDEBUG_ITEM 0xff
+#define BANTL 0x10
+#define BANT_NONHT 0x100
+#define BANT_HT1 0x1000
+#define BANT_HT2 0x10000
+#define BANT_HT1S1 0x100000
+#define BANT_NONHTS1 0x1000000
+
+#define BCCK_BBMODE 0x3
+#define BCCK_TXPOWERSAVING 0x80
+#define BCCK_RXPOWERSAVING 0x40
+
+#define BCCK_SIDEBAND 0x10
+
+#define BCCK_SCRAMBLE 0x8
+#define BCCK_ANTDIVERSITY 0x8000
+#define BCCK_CARRIER_RECOVERY 0x4000
+#define BCCK_TXRATE 0x3000
+#define BCCK_DCCANCEL 0x0800
+#define BCCK_ISICANCEL 0x0400
+#define BCCK_MATCH_FILTER 0x0200
+#define BCCK_EQUALIZER 0x0100
+#define BCCK_PREAMBLE_DETECT 0x800000
+#define BCCK_FAST_FALSECCAi 0x400000
+#define BCCK_CH_ESTSTARTi 0x300000
+#define BCCK_CCA_COUNTi 0x080000
+#define BCCK_CS_LIM 0x070000
+#define BCCK_BIST_MODEi 0x80000000
+#define BCCK_CCAMASK 0x40000000
+#define BCCK_TX_DAC_PHASE 0x4
+#define BCCK_RX_ADC_PHASE 0x20000000
+#define BCCKR_CP_MODE 0x0100
+#define BCCK_TXDC_OFFSET 0xf0
+#define BCCK_RXDC_OFFSET 0xf
+#define BCCK_CCA_MODE 0xc000
+#define BCCK_FALSECS_LIM 0x3f00
+#define BCCK_CS_RATIO 0xc00000
+#define BCCK_CORGBIT_SEL 0x300000
+#define BCCK_PD_LIM 0x0f0000
+#define BCCK_NEWCCA 0x80000000
+#define BCCK_RXHP_OF_IG 0x8000
+#define BCCK_RXIG 0x7f00
+#define BCCK_LNA_POLARITY 0x800000
+#define BCCK_RX1ST_BAIN 0x7f0000
+#define BCCK_RF_EXTEND 0x20000000
+#define BCCK_RXAGC_SATLEVEL 0x1f000000
+#define BCCK_RXAGC_SATCOUNT 0xe0
+#define bCCKRxRFSettle 0x1f
+#define BCCK_FIXED_RXAGC 0x8000
+#define BCCK_ANTENNA_POLARITY 0x2000
+#define BCCK_TXFILTER_TYPE 0x0c00
+#define BCCK_RXAGC_REPORTTYPE 0x0300
+#define BCCK_RXDAGC_EN 0x80000000
+#define BCCK_RXDAGC_PERIOD 0x20000000
+#define BCCK_RXDAGC_SATLEVEL 0x1f000000
+#define BCCK_TIMING_RECOVERY 0x800000
+#define BCCK_TXC0 0x3f0000
+#define BCCK_TXC1 0x3f000000
+#define BCCK_TXC2 0x3f
+#define BCCK_TXC3 0x3f00
+#define BCCK_TXC4 0x3f0000
+#define BCCK_TXC5 0x3f000000
+#define BCCK_TXC6 0x3f
+#define BCCK_TXC7 0x3f00
+#define BCCK_DEBUGPORT 0xff0000
+#define BCCK_DAC_DEBUG 0x0f000000
+#define BCCK_FALSEALARM_ENABLE 0x8000
+#define BCCK_FALSEALARM_READ 0x4000
+#define BCCK_TRSSI 0x7f
+#define BCCK_RXAGC_REPORT 0xfe
+#define BCCK_RXREPORT_ANTSEL 0x80000000
+#define BCCK_RXREPORT_MFOFF 0x40000000
+#define BCCK_RXREPORT_SQLOSS 0x20000000
+#define BCCK_RXREPORT_PKTLOSS 0x10000000
+#define BCCK_RXREPORT_LOCKEDBIT 0x08000000
+#define BCCK_RXREPORT_RATEERROR 0x04000000
+#define BCCK_RXREPORT_RXRATE 0x03000000
+#define BCCK_RXFA_COUNTER_LOWER 0xff
+#define BCCK_RXFA_COUNTER_UPPER 0xff000000
+#define BCCK_RXHPAGC_START 0xe000
+#define BCCK_RXHPAGC_FINAL 0x1c00
+#define BCCK_RXFALSEALARM_ENABLE 0x8000
+#define BCCK_FACOUNTER_FREEZE 0x4000
+#define BCCK_TXPATH_SEL 0x10000000
+#define BCCK_DEFAULT_RXPATH 0xc000000
+#define BCCK_OPTION_RXPATH 0x3000000
+
+#define BNUM_OFSTF 0x3
+#define BSHIFT_L 0xc0
+#define BGI_TH 0xc
+#define BRXPATH_A 0x1
+#define BRXPATH_B 0x2
+#define BRXPATH_C 0x4
+#define BRXPATH_D 0x8
+#define BTXPATH_A 0x1
+#define BTXPATH_B 0x2
+#define BTXPATH_C 0x4
+#define BTXPATH_D 0x8
+#define BTRSSI_FREQ 0x200
+#define BADC_BACKOFF 0x3000
+#define BDFIR_BACKOFF 0xc000
+#define BTRSSI_LATCH_PHASE 0x10000
+#define BRX_LDC_OFFSET 0xff
+#define BRX_QDC_OFFSET 0xff00
+#define BRX_DFIR_MODE 0x1800000
+#define BRX_DCNF_TYPE 0xe000000
+#define BRXIQIMB_A 0x3ff
+#define BRXIQIMB_B 0xfc00
+#define BRXIQIMB_C 0x3f0000
+#define BRXIQIMB_D 0xffc00000
+#define BDC_DC_NOTCH 0x60000
+#define BRXNB_NOTCH 0x1f000000
+#define BPD_TH 0xf
+#define BPD_TH_OPT2 0xc000
+#define BPWED_TH 0x700
+#define BIFMF_WIN_L 0x800
+#define BPD_OPTION 0x1000
+#define BMF_WIN_L 0xe000
+#define BBW_SEARCH_L 0x30000
+#define BWIN_ENH_L 0xc0000
+#define BBW_TH 0x700000
+#define BED_TH2 0x3800000
+#define BBW_OPTION 0x4000000
+#define BRADIO_TH 0x18000000
+#define BWINDOW_L 0xe0000000
+#define BSBD_OPTION 0x1
+#define BFRAME_TH 0x1c
+#define BFS_OPTION 0x60
+#define BDC_SLOPE_CHECK 0x80
+#define BFGUARD_COUNTER_DC_L 0xe00
+#define BFRAME_WEIGHT_SHORT 0x7000
+#define BSUB_TUNE 0xe00000
+#define BFRAME_DC_LENGTH 0xe000000
+#define BSBD_START_OFFSET 0x30000000
+#define BFRAME_TH_2 0x7
+#define BFRAME_GI2_TH 0x38
+#define BGI2_SYNC_EN 0x40
+#define BSARCH_SHORT_EARLY 0x300
+#define BSARCH_SHORT_LATE 0xc00
+#define BSARCH_GI2_LATE 0x70000
+#define BCFOANTSUM 0x1
+#define BCFOACC 0x2
+#define BCFOSTARTOFFSET 0xc
+#define BCFOLOOPBACK 0x70
+#define BCFOSUMWEIGHT 0x80
+#define BDAGCENABLE 0x10000
+#define BTXIQIMB_A 0x3ff
+#define BTXIQIMB_b 0xfc00
+#define BTXIQIMB_C 0x3f0000
+#define BTXIQIMB_D 0xffc00000
+#define BTXIDCOFFSET 0xff
+#define BTXIQDCOFFSET 0xff00
+#define BTXDFIRMODE 0x10000
+#define BTXPESUDO_NOISEON 0x4000000
+#define BTXPESUDO_NOISE_A 0xff
+#define BTXPESUDO_NOISE_B 0xff00
+#define BTXPESUDO_NOISE_C 0xff0000
+#define BTXPESUDO_NOISE_D 0xff000000
+#define BCCA_DROPOPTION 0x20000
+#define BCCA_DROPTHRES 0xfff00000
+#define BEDCCA_H 0xf
+#define BEDCCA_L 0xf0
+#define BLAMBDA_ED 0x300
+#define BRX_INITIALGAIN 0x7f
+#define BRX_ANTDIV_EN 0x80
+#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00
+#define BRX_HIGHPOWER_FLOW 0x8000
+#define BRX_AGC_FREEZE_THRES 0xc0000
+#define BRX_FREEZESTEP_AGC1 0x300000
+#define BRX_FREEZESTEP_AGC2 0xc00000
+#define BRX_FREEZESTEP_AGC3 0x3000000
+#define BRX_FREEZESTEP_AGC0 0xc000000
+#define BRXRSSI_CMP_EN 0x10000000
+#define BRXQUICK_AGCEN 0x20000000
+#define BRXAGC_FREEZE_THRES_MODE 0x40000000
+#define BRX_OVERFLOW_CHECKTYPE 0x80000000
+#define BRX_AGCSHIFT 0x7f
+#define BTRSW_TRI_ONLY 0x80
+#define BPOWER_THRES 0x300
+#define BRXAGC_EN 0x1
+#define BRXAGC_TOGETHER_EN 0x2
+#define BRXAGC_MIN 0x4
+#define BRXHP_INI 0x7
+#define BRXHP_TRLNA 0x70
+#define BRXHP_RSSI 0x700
+#define BRXHP_BBP1 0x7000
+#define BRXHP_BBP2 0x70000
+#define BRXHP_BBP3 0x700000
+#define BRSSI_H 0x7f0000
+#define BRSSI_GEN 0x7f000000
+#define BRXSETTLE_TRSW 0x7
+#define BRXSETTLE_LNA 0x38
+#define BRXSETTLE_RSSI 0x1c0
+#define BRXSETTLE_BBP 0xe00
+#define BRXSETTLE_RXHP 0x7000
+#define BRXSETTLE_ANTSW_RSSI 0x38000
+#define BRXSETTLE_ANTSW 0xc0000
+#define BRXPROCESS_TIME_DAGC 0x300000
+#define BRXSETTLE_HSSI 0x400000
+#define BRXPROCESS_TIME_BBPPW 0x800000
+#define BRXANTENNA_POWER_SHIFT 0x3000000
+#define BRSSI_TABLE_SELECT 0xc000000
+#define BRXHP_FINAL 0x7000000
+#define BRXHPSETTLE_BBP 0x7
+#define BRXHTSETTLE_HSSI 0x8
+#define BRXHTSETTLE_RXHP 0x70
+#define BRXHTSETTLE_BBPPW 0x80
+#define BRXHTSETTLE_IDLE 0x300
+#define BRXHTSETTLE_RESERVED 0x1c00
+#define BRXHT_RXHP_EN 0x8000
+#define BRXAGC_FREEZE_THRES 0x30000
+#define BRXAGC_TOGETHEREN 0x40000
+#define BRXHTAGC_MIN 0x80000
+#define BRXHTAGC_EN 0x100000
+#define BRXHTDAGC_EN 0x200000
+#define BRXHT_RXHP_BBP 0x1c00000
+#define BRXHT_RXHP_FINAL 0xe0000000
+#define BRXPW_RADIO_TH 0x3
+#define BRXPW_RADIO_EN 0x4
+#define BRXMF_HOLD 0x3800
+#define BRXPD_DELAY_TH1 0x38
+#define BRXPD_DELAY_TH2 0x1c0
+#define BRXPD_DC_COUNT_MAX 0x600
+#define BRXPD_DELAY_TH 0x8000
+#define BRXPROCESS_DELAY 0xf0000
+#define BRXSEARCHRANGE_GI2_EARLY 0x700000
+#define BRXFRAME_FUARD_COUNTER_L 0x3800000
+#define BRXSGI_GUARD_L 0xc000000
+#define BRXSGI_SEARCH_L 0x30000000
+#define BRXSGI_TH 0xc0000000
+#define BDFSCNT0 0xff
+#define BDFSCNT1 0xff00
+#define BDFSFLAG 0xf0000
+#define BMF_WEIGHT_SUM 0x300000
+#define BMINIDX_TH 0x7f000000
+#define BDAFORMAT 0x40000
+#define BTXCH_EMU_ENABLE 0x01000000
+#define BTRSW_ISOLATION_A 0x7f
+#define BTRSW_ISOLATION_B 0x7f00
+#define BTRSW_ISOLATION_C 0x7f0000
+#define BTRSW_ISOLATION_D 0x7f000000
+#define BEXT_LNA_GAIN 0x7c00
+
+#define BSTBC_EN 0x4
+#define BANTENNA_MAPPING 0x10
+#define BNSS 0x20
+#define BCFO_ANTSUM_ID 0x200
+#define BPHY_COUNTER_RESET 0x8000000
+#define BCFO_REPORT_GET 0x4000000
+#define BOFDM_CONTINUE_TX 0x10000000
+#define BOFDM_SINGLE_CARRIER 0x20000000
+#define BOFDM_SINGLE_TONE 0x40000000
+#define BHT_DETECT 0x100
+#define BCFOEN 0x10000
+#define BCFOVALUE 0xfff00000
+#define BSIGTONE_RE 0x3f
+#define BSIGTONE_IM 0x7f00
+#define BCOUNTER_CCA 0xffff
+#define BCOUNTER_PARITYFAIL 0xffff0000
+#define BCOUNTER_RATEILLEGAL 0xffff
+#define BCOUNTER_CRC8FAIL 0xffff0000
+#define BCOUNTER_MCSNOSUPPORT 0xffff
+#define BCOUNTER_FASTSYNC 0xffff
+#define BSHORTCFO 0xfff
+#define BSHORTCFOT_LENGTH 12
+#define BSHORTCFOF_LENGTH 11
+#define BLONGCFO 0x7ff
+#define BLONGCFOT_LENGTH 11
+#define BLONGCFOF_LENGTH 11
+#define BTAILCFO 0x1fff
+#define BTAILCFOT_LENGTH 13
+#define BTAILCFOF_LENGTH 12
+#define BNOISE_EN_PWDB 0xffff
+#define BCC_POWER_DB 0xffff0000
+#define BMOISE_PWDB 0xffff
+#define BPOWERMEAST_LENGTH 10
+#define BPOWERMEASF_LENGTH 3
+#define BRX_HT_BW 0x1
+#define BRXSC 0x6
+#define BRX_HT 0x8
+#define BNB_INTF_DET_ON 0x1
+#define BINTF_WIN_LEN_CFG 0x30
+#define BNB_INTF_TH_CFG 0x1c0
+#define BRFGAIN 0x3f
+#define BTABLESEL 0x40
+#define BTRSW 0x80
+#define BRXSNR_A 0xff
+#define BRXSNR_B 0xff00
+#define BRXSNR_C 0xff0000
+#define BRXSNR_D 0xff000000
+#define BSNR_EVMT_LENGTH 8
+#define BSNR_EVMF_LENGTH 1
+#define BCSI1ST 0xff
+#define BCSI2ND 0xff00
+#define BRXEVM1ST 0xff0000
+#define BRXEVM2ND 0xff000000
+#define BSIGEVM 0xff
+#define BPWDB 0xff00
+#define BSGIEN 0x10000
+
+#define BSFACTOR_QMA1 0xf
+#define BSFACTOR_QMA2 0xf0
+#define BSFACTOR_QMA3 0xf00
+#define BSFACTOR_QMA4 0xf000
+#define BSFACTOR_QMA5 0xf0000
+#define BSFACTOR_QMA6 0xf0000
+#define BSFACTOR_QMA7 0xf00000
+#define BSFACTOR_QMA8 0xf000000
+#define BSFACTOR_QMA9 0xf0000000
+#define BCSI_SCHEME 0x100000
+
+#define BNOISE_LVL_TOP_SET 0x3
+#define BCHSMOOTH 0x4
+#define BCHSMOOTH_CFG1 0x38
+#define BCHSMOOTH_CFG2 0x1c0
+#define BCHSMOOTH_CFG3 0xe00
+#define BCHSMOOTH_CFG4 0x7000
+#define BMRCMODE 0x800000
+#define BTHEVMCFG 0x7000000
+
+#define BLOOP_FIT_TYPE 0x1
+#define BUPD_CFO 0x40
+#define BUPD_CFO_OFFDATA 0x80
+#define BADV_UPD_CFO 0x100
+#define BADV_TIME_CTRL 0x800
+#define BUPD_CLKO 0x1000
+#define BFC 0x6000
+#define BTRACKING_MODE 0x8000
+#define BPHCMP_ENABLE 0x10000
+#define BUPD_CLKO_LTF 0x20000
+#define BCOM_CH_CFO 0x40000
+#define BCSI_ESTI_MODE 0x80000
+#define BADV_UPD_EQZ 0x100000
+#define BUCHCFG 0x7000000
+#define BUPDEQZ 0x8000000
+
+#define BRX_PESUDO_NOISE_ON 0x20000000
+#define BRX_PESUDO_NOISE_A 0xff
+#define BRX_PESUDO_NOISE_B 0xff00
+#define BRX_PESUDO_NOISE_C 0xff0000
+#define BRX_PESUDO_NOISE_D 0xff000000
+#define BRX_PESUDO_NOISESTATE_A 0xffff
+#define BRX_PESUDO_NOISESTATE_B 0xffff0000
+#define BRX_PESUDO_NOISESTATE_C 0xffff
+#define BRX_PESUDO_NOISESTATE_D 0xffff0000
+
+#define BZEBRA1_HSSIENABLE 0x8
+#define BZEBRA1_TRXCONTROL 0xc00
+#define BZEBRA1_TRXGAINSETTING 0x07f
+#define BZEBRA1_RXCOUNTER 0xc00
+#define BZEBRA1_TXCHANGEPUMP 0x38
+#define BZEBRA1_RXCHANGEPUMP 0x7
+#define BZEBRA1_CHANNEL_NUM 0xf80
+#define BZEBRA1_TXLPFBW 0x400
+#define BZEBRA1_RXLPFBW 0x600
+
+#define BRTL8256REG_MODE_CTRL1 0x100
+#define BRTL8256REG_MODE_CTRL0 0x40
+#define BRTL8256REG_TXLPFBW 0x18
+#define BRTL8256REG_RXLPFBW 0x600
+
+#define BRTL8258_TXLPFBW 0xc
+#define BRTL8258_RXLPFBW 0xc00
+#define BRTL8258_RSSILPFBW 0xc0
+
+#define BBYTE0 0x1
+#define BBYTE1 0x2
+#define BBYTE2 0x4
+#define BBYTE3 0x8
+#define BWORD0 0x3
+#define BWORD1 0xc
+#define BWORD 0xf
+
+#define MASKBYTE0 0xff
+#define MASKBYTE1 0xff00
+#define MASKBYTE2 0xff0000
+#define MASKBYTE3 0xff000000
+#define MASKHWORD 0xffff0000
+#define MASKLWORD 0x0000ffff
+#define MASKDWORD 0xffffffff
+#define MASK12BITS 0xfff
+#define MASKH4BITS 0xf0000000
+#define MASKOFDM_D 0xffc00000
+#define MASKCCK 0x3f3f3f3f
+
+#define MASK4BITS 0x0f
+#define MASK20BITS 0xfffff
+#define RFREG_OFFSET_MASK 0xfffff
+
+#define BENABLE 0x1
+#define BDISABLE 0x0
+
+#define LEFT_ANTENNA 0x0
+#define RIGHT_ANTENNA 0x1
+
+#define TCHECK_TXSTATUS 500
+#define TUPDATE_RXCOUNTER 100
+
+/* 2 EFUSE_TEST (For RTL8723 partially) */
+#define EFUSE_SEL(x) (((x) & 0x3) << 8)
+#define EFUSE_SEL_MASK 0x300
+#define EFUSE_WIFI_SEL_0 0x0
+
+/* Enable GPIO[9] as WiFi HW PDn source*/
+#define WL_HWPDN_EN BIT(0)
+/* WiFi HW PDn polarity control*/
+#define WL_HWPDN_SL BIT(1)
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
new file mode 100644
index 000000000000..50dd2fb2c93d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
@@ -0,0 +1,505 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+
+void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ switch (bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+ 0xfffff3ff) | 0x0400);
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+ rtlphy->rfreg_chnlval[0]);
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+ 0xfffff3ff));
+ rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+ rtlphy->rfreg_chnlval[0]);
+ break;
+ default:
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "unknown bandwidth: %#X\n", bandwidth);
+ break;
+ }
+}
+
+void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 tx_agc[2] = {0, 0}, tmpval;
+ bool turbo_scanoff = false;
+ u8 idx1, idx2;
+ u8 *ptr;
+
+ if (rtlefuse->eeprom_regulatory != 0)
+ turbo_scanoff = true;
+
+ if (mac->act_scanning == true) {
+ 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);
+ }
+ }
+ } else {
+ 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 (rtlefuse->eeprom_regulatory == 0) {
+ tmpval = (rtlphy->mcs_offset[0][6]) +
+ (rtlphy->mcs_offset[0][7] << 8);
+ tx_agc[RF90_PATH_A] += tmpval;
+
+ tmpval = (rtlphy->mcs_offset[0][14]) +
+ (rtlphy->mcs_offset[0][15] << 24);
+ tx_agc[RF90_PATH_B] += tmpval;
+ }
+ }
+
+ for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+ ptr = (u8 *) (&(tx_agc[idx1]));
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if (*ptr > RF6052_MAX_TX_PWR)
+ *ptr = RF6052_MAX_TX_PWR;
+ ptr++;
+ }
+ }
+
+ tmpval = tx_agc[RF90_PATH_A] & 0xff;
+ rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_A_CCK1_MCS32);
+
+ tmpval = tx_agc[RF90_PATH_A] >> 8;
+
+ tmpval = tmpval & 0xff00ffff;
+
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11);
+
+ tmpval = tx_agc[RF90_PATH_B] >> 24;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK11_A_CCK2_11);
+
+ tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+ rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+ RTXAGC_B_CCK1_55_MCS32);
+}
+
+static void rtl8723ae_phy_get_power_base(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel,
+ u32 *ofdmbase, u32 *mcsbase)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u32 powerBase0, powerBase1;
+ u8 legacy_pwrdiff, ht20_pwrdiff;
+ u8 i, powerlevel[2];
+
+ for (i = 0; i < 2; i++) {
+ powerlevel[i] = ppowerlevel[i];
+ legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+ powerBase0 = powerlevel[i] + legacy_pwrdiff;
+
+ powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
+ (powerBase0 << 8) | powerBase0;
+ *(ofdmbase + i) = powerBase0;
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ " [OFDM power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+ ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+ powerlevel[i] += ht20_pwrdiff;
+ }
+ powerBase1 = powerlevel[i];
+ powerBase1 = (powerBase1 << 24) |
+ (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+
+ *(mcsbase + i) = powerBase1;
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ " [MCS power base index rf(%c) = 0x%x]\n",
+ ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
+ }
+}
+
+static void rtl8723ae_get_txpwr_val_by_reg(struct ieee80211_hw *hw,
+ u8 channel, u8 index,
+ u32 *powerBase0,
+ u32 *powerBase1,
+ u32 *p_outwriteval)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ u8 i, chnlgroup = 0, pwr_diff_limit[4];
+ u32 writeVal, customer_limit, rf;
+
+ for (rf = 0; rf < 2; rf++) {
+ switch (rtlefuse->eeprom_regulatory) {
+ case 0:
+ chnlgroup = 0;
+
+ writeVal = rtlphy->mcs_offset[chnlgroup]
+ [index + (rf ? 8 : 0)] +
+ ((index < 2) ? powerBase0[rf] :
+ powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "RTK better performance, "
+ "writeVal(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ break;
+ case 1:
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ writeVal = ((index < 2) ? powerBase0[rf] :
+ powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Realtek regulatory, 40MHz, "
+ "writeVal(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ } else {
+ if (rtlphy->pwrgroup_cnt == 1)
+ chnlgroup = 0;
+ if (rtlphy->pwrgroup_cnt >= 3) {
+ if (channel <= 3)
+ chnlgroup = 0;
+ else if (channel >= 4 && channel <= 9)
+ chnlgroup = 1;
+ else if (channel > 9)
+ chnlgroup = 2;
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20)
+ chnlgroup++;
+ else
+ chnlgroup += 4;
+ }
+
+ writeVal = rtlphy->mcs_offset[chnlgroup]
+ [index + (rf ? 8 : 0)] + ((index < 2) ?
+ powerBase0[rf] :
+ powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ }
+ break;
+ case 2:
+ writeVal =
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Better regulatory, writeVal(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ break;
+ case 3:
+ chnlgroup = 0;
+
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "customer's limit, 40MHz rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht40[rf][channel-1]);
+ } else {
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "customer's limit, 20MHz rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'),
+ rtlefuse->pwrgroup_ht20[rf][channel-1]);
+ }
+ for (i = 0; i < 4; i++) {
+ pwr_diff_limit[i] =
+ (u8) ((rtlphy->mcs_offset
+ [chnlgroup][index + (rf ? 8 : 0)] &
+ (0x7f << (i * 8))) >> (i * 8));
+
+ if (rtlphy->current_chan_bw ==
+ HT_CHANNEL_WIDTH_20_40) {
+ if (pwr_diff_limit[i] >
+ rtlefuse->
+ pwrgroup_ht40[rf][channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht40[rf]
+ [channel - 1];
+ } else {
+ if (pwr_diff_limit[i] >
+ rtlefuse->
+ pwrgroup_ht20[rf][channel - 1])
+ pwr_diff_limit[i] =
+ rtlefuse->pwrgroup_ht20[rf]
+ [channel - 1];
+ }
+ }
+
+ customer_limit = (pwr_diff_limit[3] << 24) |
+ (pwr_diff_limit[2] << 16) |
+ (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Customer's limit rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), customer_limit);
+
+ writeVal = customer_limit +
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Customer, writeVal rf(%c)= 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ break;
+ default:
+ chnlgroup = 0;
+ writeVal = rtlphy->mcs_offset[chnlgroup][index +
+ (rf ? 8 : 0)] + ((index < 2) ? powerBase0[rf] :
+ powerBase1[rf]);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "RTK better performance, writeVal rf(%c) = 0x%x\n",
+ ((rf == 0) ? 'A' : 'B'), writeVal);
+ break;
+ }
+
+ if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
+ writeVal = writeVal - 0x06060606;
+ else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+ TXHIGHPWRLEVEL_BT2)
+ writeVal = writeVal - 0x0c0c0c0c;
+ *(p_outwriteval + rf) = writeVal;
+ }
+}
+
+static void _rtl8723ae_write_ofdm_power_reg(struct ieee80211_hw *hw,
+ u8 index, u32 *pValue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ u16 regoffset_a[6] = {
+ RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+ RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+ RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+ };
+ u16 regoffset_b[6] = {
+ RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+ RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+ RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+ };
+ u8 i, rf, pwr_val[4];
+ u32 writeVal;
+ u16 regoffset;
+
+ for (rf = 0; rf < 2; rf++) {
+ writeVal = pValue[rf];
+ for (i = 0; i < 4; i++) {
+ pwr_val[i] = (u8) ((writeVal & (0x7f <<
+ (i * 8))) >> (i * 8));
+
+ if (pwr_val[i] > RF6052_MAX_TX_PWR)
+ pwr_val[i] = RF6052_MAX_TX_PWR;
+ }
+ writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+ (pwr_val[1] << 8) | pwr_val[0];
+
+ if (rf == 0)
+ regoffset = regoffset_a[index];
+ else
+ regoffset = regoffset_b[index];
+ rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
+
+ RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+ "Set 0x%x = %08x\n", regoffset, writeVal);
+
+ if (((get_rf_type(rtlphy) == RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS15_MCS12)) ||
+ ((get_rf_type(rtlphy) != RF_2T2R) &&
+ (regoffset == RTXAGC_A_MCS07_MCS04 ||
+ regoffset == RTXAGC_B_MCS07_MCS04))) {
+
+ writeVal = pwr_val[3];
+ if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+ regoffset == RTXAGC_A_MCS07_MCS04)
+ regoffset = 0xc90;
+ if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+ regoffset == RTXAGC_B_MCS07_MCS04)
+ regoffset = 0xc98;
+
+ for (i = 0; i < 3; i++) {
+ writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+ rtl_write_byte(rtlpriv, (u32) (regoffset + i),
+ (u8) writeVal);
+ }
+ }
+ }
+}
+
+void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel)
+{
+ u32 writeVal[2], powerBase0[2], powerBase1[2];
+ u8 index;
+
+ rtl8723ae_phy_get_power_base(hw, ppowerlevel,
+ channel, &powerBase0[0], &powerBase1[0]);
+
+ for (index = 0; index < 6; index++) {
+ rtl8723ae_get_txpwr_val_by_reg(hw, channel, index,
+ &powerBase0[0],
+ &powerBase1[0],
+ &writeVal[0]);
+
+ _rtl8723ae_write_ofdm_power_reg(hw, index, &writeVal[0]);
+ }
+}
+
+static bool _rtl8723ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u32 u4_regvalue = 0;
+ u8 rfpath;
+ bool rtstatus = true;
+ struct bb_reg_def *pphyreg;
+
+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+
+ pphyreg = &rtlphy->phyreg_def[rfpath];
+
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV << 16);
+ break;
+ }
+
+ rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+
+ rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+ B3WIREADDREAALENGTH, 0x0);
+ udelay(1);
+
+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+
+ switch (rfpath) {
+ case RF90_PATH_A:
+ rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
+ (enum radio_path)rfpath);
+ break;
+ case RF90_PATH_B:
+ rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
+ (enum radio_path)rfpath);
+ break;
+ case RF90_PATH_C:
+ break;
+ case RF90_PATH_D:
+ break;
+ }
+ switch (rfpath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl_set_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV, u4_regvalue);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl_set_bbreg(hw, pphyreg->rfintfs,
+ BRFSI_RFENV << 16, u4_regvalue);
+ break;
+ }
+ if (rtstatus != true) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+ "Radio[%d] Fail!!", rfpath);
+ return false;
+ }
+ }
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
+ return rtstatus;
+}
+
+bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+ if (rtlphy->rf_type == RF_1T1R)
+ rtlphy->num_total_rfpath = 1;
+ else
+ rtlphy->num_total_rfpath = 2;
+
+ return _rtl8723ae_phy_rf6052_config_parafile(hw);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
new file mode 100644
index 000000000000..d0f9dd79abea
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_RF_H__
+#define __RTL8723E_RF_H__
+
+#define RF6052_MAX_TX_PWR 0x3F
+
+extern void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+ u8 bandwidth);
+extern void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+extern void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+extern bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
new file mode 100644
index 000000000000..18b0bc51766b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
@@ -0,0 +1,380 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+
+#include "../core.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "hw.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+#include "table.h"
+#include "hal_btc.h"
+
+static void rtl8723ae_init_aspm_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+ /*close ASPM for AMD defaultly */
+ rtlpci->const_amdpci_aspm = 0;
+
+ /* ASPM PS mode.
+ * 0 - Disable ASPM,
+ * 1 - Enable ASPM without Clock Req,
+ * 2 - Enable ASPM with Clock Req,
+ * 3 - Alwyas Enable ASPM with Clock Req,
+ * 4 - Always Enable ASPM without Clock Req.
+ * set defult to RTL8192CE:3 RTL8192E:2
+ */
+ rtlpci->const_pci_aspm = 3;
+
+ /*Setting for PCI-E device */
+ rtlpci->const_devicepci_aspm_setting = 0x03;
+
+ /*Setting for PCI-E bridge */
+ rtlpci->const_hostpci_aspm_setting = 0x02;
+
+ /* In Hw/Sw Radio Off situation.
+ * 0 - Default,
+ * 1 - From ASPM setting without low Mac Pwr,
+ * 2 - From ASPM setting with low Mac Pwr,
+ * 3 - Bus D3
+ * set default to RTL8192CE:0 RTL8192SE:2
+ */
+ rtlpci->const_hwsw_rfoff_d3 = 0;
+
+ /* This setting works for those device with
+ * backdoor ASPM setting such as EPHY setting.
+ * 0 - Not support ASPM,
+ * 1 - Support ASPM,
+ * 2 - According to chipset.
+ */
+ rtlpci->const_support_pciaspm = 1;
+}
+
+int rtl8723ae_init_sw_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ int err;
+
+ rtl8723ae_bt_reg_init(hw);
+ rtlpriv->dm.dm_initialgain_enable = 1;
+ rtlpriv->dm.dm_flag = 0;
+ rtlpriv->dm.disable_framebursting = 0;
+ rtlpriv->dm.thermalvalue = 0;
+ rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
+
+ /* compatible 5G band 88ce just 2.4G band & smsp */
+ rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
+ rtlpriv->rtlhal.bandset = BAND_ON_2_4G;
+ rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
+
+ rtlpci->receive_config = (RCR_APPFCS |
+ RCR_APP_MIC |
+ RCR_APP_ICV |
+ RCR_APP_PHYST_RXFF |
+ RCR_HTC_LOC_CTRL |
+ RCR_AMF |
+ RCR_ACF |
+ RCR_ADF |
+ RCR_AICV |
+ RCR_AB |
+ RCR_AM |
+ RCR_APM |
+ 0);
+
+ rtlpci->irq_mask[0] =
+ (u32) (PHIMR_ROK |
+ PHIMR_RDU |
+ PHIMR_VODOK |
+ PHIMR_VIDOK |
+ PHIMR_BEDOK |
+ PHIMR_BKDOK |
+ PHIMR_MGNTDOK |
+ PHIMR_HIGHDOK |
+ PHIMR_C2HCMD |
+ PHIMR_HISRE_IND |
+ PHIMR_TSF_BIT32_TOGGLE |
+ PHIMR_TXBCNOK |
+ PHIMR_PSTIMEOUT |
+ 0);
+
+ rtlpci->irq_mask[1] = (u32)(PHIMR_RXFOVW | 0);
+
+ /* for debug level */
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
+ /* for LPS & IPS */
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+ /* for ASPM, you can close aspm through
+ * set const_support_pciaspm = 0
+ */
+ rtl8723ae_init_aspm_vars(hw);
+
+ if (rtlpriv->psc.reg_fwctrl_lps == 1)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+ else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+ rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+ /* for firmware buf */
+ rtlpriv->rtlhal.pfirmware = vmalloc(0x6000);
+ if (!rtlpriv->rtlhal.pfirmware) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Can't alloc buffer for fw.\n");
+ return 1;
+ }
+
+ if (IS_VENDOR_8723_A_CUT(rtlhal->version))
+ rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin";
+ else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+ rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin";
+
+ rtlpriv->max_fw_size = 0x6000;
+ pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+ err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+ rtlpriv->io.dev, GFP_KERNEL, hw,
+ rtl_fw_cb);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Failed to request firmware!\n");
+ return 1;
+ }
+ return 0;
+}
+
+void rtl8723ae_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ if (rtlpriv->rtlhal.pfirmware) {
+ vfree(rtlpriv->rtlhal.pfirmware);
+ rtlpriv->rtlhal.pfirmware = NULL;
+ }
+}
+
+static struct rtl_hal_ops rtl8723ae_hal_ops = {
+ .init_sw_vars = rtl8723ae_init_sw_vars,
+ .deinit_sw_vars = rtl8723ae_deinit_sw_vars,
+ .read_eeprom_info = rtl8723ae_read_eeprom_info,
+ .interrupt_recognized = rtl8723ae_interrupt_recognized,
+ .hw_init = rtl8723ae_hw_init,
+ .hw_disable = rtl8723ae_card_disable,
+ .hw_suspend = rtl8723ae_suspend,
+ .hw_resume = rtl8723ae_resume,
+ .enable_interrupt = rtl8723ae_enable_interrupt,
+ .disable_interrupt = rtl8723ae_disable_interrupt,
+ .set_network_type = rtl8723ae_set_network_type,
+ .set_chk_bssid = rtl8723ae_set_check_bssid,
+ .set_qos = rtl8723ae_set_qos,
+ .set_bcn_reg = rtl8723ae_set_beacon_related_registers,
+ .set_bcn_intv = rtl8723ae_set_beacon_interval,
+ .update_interrupt_mask = rtl8723ae_update_interrupt_mask,
+ .get_hw_reg = rtl8723ae_get_hw_reg,
+ .set_hw_reg = rtl8723ae_set_hw_reg,
+ .update_rate_tbl = rtl8723ae_update_hal_rate_tbl,
+ .fill_tx_desc = rtl8723ae_tx_fill_desc,
+ .fill_tx_cmddesc = rtl8723ae_tx_fill_cmddesc,
+ .query_rx_desc = rtl8723ae_rx_query_desc,
+ .set_channel_access = rtl8723ae_update_channel_access_setting,
+ .radio_onoff_checking = rtl8723ae_gpio_radio_on_off_checking,
+ .set_bw_mode = rtl8723ae_phy_set_bw_mode,
+ .switch_channel = rtl8723ae_phy_sw_chnl,
+ .dm_watchdog = rtl8723ae_dm_watchdog,
+ .scan_operation_backup = rtl8723ae_phy_scan_operation_backup,
+ .set_rf_power_state = rtl8723ae_phy_set_rf_power_state,
+ .led_control = rtl8723ae_led_control,
+ .set_desc = rtl8723ae_set_desc,
+ .get_desc = rtl8723ae_get_desc,
+ .tx_polling = rtl8723ae_tx_polling,
+ .enable_hw_sec = rtl8723ae_enable_hw_security_config,
+ .set_key = rtl8723ae_set_key,
+ .init_sw_leds = rtl8723ae_init_sw_leds,
+ .allow_all_destaddr = rtl8723ae_allow_all_destaddr,
+ .get_bbreg = rtl8723ae_phy_query_bb_reg,
+ .set_bbreg = rtl8723ae_phy_set_bb_reg,
+ .get_rfreg = rtl8723ae_phy_query_rf_reg,
+ .set_rfreg = rtl8723ae_phy_set_rf_reg,
+ .c2h_command_handle = rtl_8723e_c2h_command_handle,
+ .bt_wifi_media_status_notify = rtl_8723e_bt_wifi_media_status_notify,
+ .bt_coex_off_before_lps = rtl8723ae_bt_coex_off_before_lps,
+};
+
+static struct rtl_mod_params rtl8723ae_mod_params = {
+ .sw_crypto = false,
+ .inactiveps = true,
+ .swctrl_lps = false,
+ .fwctrl_lps = true,
+ .debug = DBG_EMERG,
+};
+
+static struct rtl_hal_cfg rtl8723ae_hal_cfg = {
+ .bar_id = 2,
+ .write_readback = true,
+ .name = "rtl8723ae_pci",
+ .fw_name = "rtlwifi/rtl8723aefw.bin",
+ .ops = &rtl8723ae_hal_ops,
+ .mod_params = &rtl8723ae_mod_params,
+ .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+ .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+ .maps[SYS_CLK] = REG_SYS_CLKR,
+ .maps[MAC_RCR_AM] = AM,
+ .maps[MAC_RCR_AB] = AB,
+ .maps[MAC_RCR_ACRC32] = ACRC32,
+ .maps[MAC_RCR_ACF] = ACF,
+ .maps[MAC_RCR_AAP] = AAP,
+ .maps[EFUSE_TEST] = REG_EFUSE_TEST,
+ .maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_CLK] = 0,
+ .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+ .maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+ .maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+ .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+ .maps[EFUSE_ANA8M] = ANA8M,
+ .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+ .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+ .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+ .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
+
+ .maps[RWCAM] = REG_CAMCMD,
+ .maps[WCAMI] = REG_CAMWRITE,
+ .maps[RCAMO] = REG_CAMREAD,
+ .maps[CAMDBG] = REG_CAMDBG,
+ .maps[SECR] = REG_SECCFG,
+ .maps[SEC_CAM_NONE] = CAM_NONE,
+ .maps[SEC_CAM_WEP40] = CAM_WEP40,
+ .maps[SEC_CAM_TKIP] = CAM_TKIP,
+ .maps[SEC_CAM_AES] = CAM_AES,
+ .maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+ .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+ .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+ .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+ .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+ .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+ .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+ .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+ .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+ .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+ .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+ .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+ .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+ .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+ .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+ .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+ .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+ .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW,
+ .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT,
+ .maps[RTL_IMR_BcnInt] = PHIMR_BCNDMAINT0,
+ .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW,
+ .maps[RTL_IMR_RDU] = PHIMR_RDU,
+ .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E,
+ .maps[RTL_IMR_BDOK] = PHIMR_BCNDOK0,
+ .maps[RTL_IMR_MGNTDOK] = PHIMR_MGNTDOK,
+ .maps[RTL_IMR_TBDER] = PHIMR_TXBCNERR,
+ .maps[RTL_IMR_HIGHDOK] = PHIMR_HIGHDOK,
+ .maps[RTL_IMR_TBDOK] = PHIMR_TXBCNOK,
+ .maps[RTL_IMR_BKDOK] = PHIMR_BKDOK,
+ .maps[RTL_IMR_BEDOK] = PHIMR_BEDOK,
+ .maps[RTL_IMR_VIDOK] = PHIMR_VIDOK,
+ .maps[RTL_IMR_VODOK] = PHIMR_VODOK,
+ .maps[RTL_IMR_ROK] = PHIMR_ROK,
+ .maps[RTL_IBSS_INT_MASKS] = (PHIMR_BCNDMAINT0 |
+ PHIMR_TXBCNOK | PHIMR_TXBCNERR),
+ .maps[RTL_IMR_C2HCMD] = PHIMR_C2HCMD,
+
+
+ .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
+ .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
+ .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
+ .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
+ .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
+ .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
+ .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
+ .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
+ .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
+ .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
+ .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
+
+ .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
+ .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
+};
+
+static struct pci_device_id rtl8723ae_pci_ids[] __devinitdata = {
+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8723, rtl8723ae_hal_cfg)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8723ae_pci_ids);
+
+MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8723aefw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723aefw_B.bin");
+
+module_param_named(swenc, rtl8723ae_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl8723ae_mod_params.debug, int, 0444);
+module_param_named(ips, rtl8723ae_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl8723ae_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl8723ae_mod_params.fwctrl_lps, bool, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
+
+static struct pci_driver rtl8723ae_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl8723ae_pci_ids,
+ .probe = rtl_pci_probe,
+ .remove = rtl_pci_disconnect,
+ .driver.pm = &rtlwifi_pm_ops,
+};
+
+module_pci_driver(rtl8723ae_driver);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
new file mode 100644
index 000000000000..fc4fde5e3eb5
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_SW_H__
+#define __RTL8723E_SW_H__
+
+int rtl8723ae_init_sw_vars(struct ieee80211_hw *hw);
+void rtl8723ae_deinit_sw_vars(struct ieee80211_hw *hw);
+void rtl8723ae_init_var_map(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/rtlwifi/rtl8723ae/table.c
new file mode 100644
index 000000000000..9b0b50cc4ade
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/table.c
@@ -0,0 +1,738 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Created on 2010/ 5/18, 1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "table.h"
+
+u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH] = {
+ 0x800, 0x80040000,
+ 0x804, 0x00000003,
+ 0x808, 0x0000fc00,
+ 0x80c, 0x0000000a,
+ 0x810, 0x10005388,
+ 0x814, 0x020c3d10,
+ 0x818, 0x02200385,
+ 0x81c, 0x00000000,
+ 0x820, 0x01000100,
+ 0x824, 0x00390004,
+ 0x828, 0x00000000,
+ 0x82c, 0x00000000,
+ 0x830, 0x00000000,
+ 0x834, 0x00000000,
+ 0x838, 0x00000000,
+ 0x83c, 0x00000000,
+ 0x840, 0x00010000,
+ 0x844, 0x00000000,
+ 0x848, 0x00000000,
+ 0x84c, 0x00000000,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x569a569a,
+ 0x85c, 0x001b25a4,
+ 0x860, 0x66f60110,
+ 0x864, 0x061f0130,
+ 0x868, 0x00000000,
+ 0x86c, 0x32323200,
+ 0x870, 0x07000760,
+ 0x874, 0x22004000,
+ 0x878, 0x00000808,
+ 0x87c, 0x00000000,
+ 0x880, 0xc0083070,
+ 0x884, 0x000004d5,
+ 0x888, 0x00000000,
+ 0x88c, 0xccc000c0,
+ 0x890, 0x00000800,
+ 0x894, 0xfffffffe,
+ 0x898, 0x40302010,
+ 0x89c, 0x00706050,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90c, 0x81121111,
+ 0xa00, 0x00d047c8,
+ 0xa04, 0x80ff000c,
+ 0xa08, 0x8c838300,
+ 0xa0c, 0x2e68120f,
+ 0xa10, 0x9500bb78,
+ 0xa14, 0x11144028,
+ 0xa18, 0x00881117,
+ 0xa1c, 0x89140f00,
+ 0xa20, 0x1a1b0000,
+ 0xa24, 0x090e1317,
+ 0xa28, 0x00000204,
+ 0xa2c, 0x00d30000,
+ 0xa70, 0x101fbf00,
+ 0xa74, 0x00000007,
+ 0xa78, 0x00000900,
+ 0xc00, 0x48071d40,
+ 0xc04, 0x03a05611,
+ 0xc08, 0x000000e4,
+ 0xc0c, 0x6c6c6c6c,
+ 0xc10, 0x08800000,
+ 0xc14, 0x40000100,
+ 0xc18, 0x08800000,
+ 0xc1c, 0x40000100,
+ 0xc20, 0x00000000,
+ 0xc24, 0x00000000,
+ 0xc28, 0x00000000,
+ 0xc2c, 0x00000000,
+ 0xc30, 0x69e9ac44,
+ 0xc34, 0x469652cf,
+ 0xc38, 0x49795994,
+ 0xc3c, 0x0a97971c,
+ 0xc40, 0x1f7c403f,
+ 0xc44, 0x000100b7,
+ 0xc48, 0xec020107,
+ 0xc4c, 0x007f037f,
+ 0xc50, 0x69543420,
+ 0xc54, 0x43bc0094,
+ 0xc58, 0x69543420,
+ 0xc5c, 0x433c0094,
+ 0xc60, 0x00000000,
+ 0xc64, 0x7116848b,
+ 0xc68, 0x47c00bff,
+ 0xc6c, 0x00000036,
+ 0xc70, 0x2c7f000d,
+ 0xc74, 0x018610db,
+ 0xc78, 0x0000001f,
+ 0xc7c, 0x00b91612,
+ 0xc80, 0x40000100,
+ 0xc84, 0x20f60000,
+ 0xc88, 0x40000100,
+ 0xc8c, 0x20200000,
+ 0xc90, 0x00121820,
+ 0xc94, 0x00000000,
+ 0xc98, 0x00121820,
+ 0xc9c, 0x00007f7f,
+ 0xca0, 0x00000000,
+ 0xca4, 0x00000080,
+ 0xca8, 0x00000000,
+ 0xcac, 0x00000000,
+ 0xcb0, 0x00000000,
+ 0xcb4, 0x00000000,
+ 0xcb8, 0x00000000,
+ 0xcbc, 0x28000000,
+ 0xcc0, 0x00000000,
+ 0xcc4, 0x00000000,
+ 0xcc8, 0x00000000,
+ 0xccc, 0x00000000,
+ 0xcd0, 0x00000000,
+ 0xcd4, 0x00000000,
+ 0xcd8, 0x64b22427,
+ 0xcdc, 0x00766932,
+ 0xce0, 0x00222222,
+ 0xce4, 0x00000000,
+ 0xce8, 0x37644302,
+ 0xcec, 0x2f97d40c,
+ 0xd00, 0x00080740,
+ 0xd04, 0x00020401,
+ 0xd08, 0x0000907f,
+ 0xd0c, 0x20010201,
+ 0xd10, 0xa0633333,
+ 0xd14, 0x3333bc43,
+ 0xd18, 0x7a8f5b6b,
+ 0xd2c, 0xcc979975,
+ 0xd30, 0x00000000,
+ 0xd34, 0x80608000,
+ 0xd38, 0x00000000,
+ 0xd3c, 0x00027293,
+ 0xd40, 0x00000000,
+ 0xd44, 0x00000000,
+ 0xd48, 0x00000000,
+ 0xd4c, 0x00000000,
+ 0xd50, 0x6437140a,
+ 0xd54, 0x00000000,
+ 0xd58, 0x00000000,
+ 0xd5c, 0x30032064,
+ 0xd60, 0x4653de68,
+ 0xd64, 0x04518a3c,
+ 0xd68, 0x00002101,
+ 0xd6c, 0x2a201c16,
+ 0xd70, 0x1812362e,
+ 0xd74, 0x322c2220,
+ 0xd78, 0x000e3c24,
+ 0xe00, 0x2a2a2a2a,
+ 0xe04, 0x2a2a2a2a,
+ 0xe08, 0x03902a2a,
+ 0xe10, 0x2a2a2a2a,
+ 0xe14, 0x2a2a2a2a,
+ 0xe18, 0x2a2a2a2a,
+ 0xe1c, 0x2a2a2a2a,
+ 0xe28, 0x00000000,
+ 0xe30, 0x1000dc1f,
+ 0xe34, 0x10008c1f,
+ 0xe38, 0x02140102,
+ 0xe3c, 0x681604c2,
+ 0xe40, 0x01007c00,
+ 0xe44, 0x01004800,
+ 0xe48, 0xfb000000,
+ 0xe4c, 0x000028d1,
+ 0xe50, 0x1000dc1f,
+ 0xe54, 0x10008c1f,
+ 0xe58, 0x02140102,
+ 0xe5c, 0x28160d05,
+ 0xe60, 0x00000008,
+ 0xe68, 0x001b25a4,
+ 0xe6c, 0x631b25a0,
+ 0xe70, 0x631b25a0,
+ 0xe74, 0x081b25a0,
+ 0xe78, 0x081b25a0,
+ 0xe7c, 0x081b25a0,
+ 0xe80, 0x081b25a0,
+ 0xe84, 0x631b25a0,
+ 0xe88, 0x081b25a0,
+ 0xe8c, 0x631b25a0,
+ 0xed0, 0x631b25a0,
+ 0xed4, 0x631b25a0,
+ 0xed8, 0x631b25a0,
+ 0xedc, 0x001b25a0,
+ 0xee0, 0x001b25a0,
+ 0xeec, 0x6b1b25a0,
+ 0xf14, 0x00000003,
+ 0xf4c, 0x00000000,
+ 0xf00, 0x00000300,
+};
+
+u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH] = {
+ 0xe00, 0xffffffff, 0x0a0c0c0c,
+ 0xe04, 0xffffffff, 0x02040608,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x0a0c0d0e,
+ 0xe14, 0xffffffff, 0x02040608,
+ 0xe18, 0xffffffff, 0x0a0c0d0e,
+ 0xe1c, 0xffffffff, 0x02040608,
+ 0x830, 0xffffffff, 0x0a0c0c0c,
+ 0x834, 0xffffffff, 0x02040608,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x0a0c0d0e,
+ 0x848, 0xffffffff, 0x02040608,
+ 0x84c, 0xffffffff, 0x0a0c0d0e,
+ 0x868, 0xffffffff, 0x02040608,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x06060606,
+ 0xe14, 0xffffffff, 0x00020406,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x06060606,
+ 0x848, 0xffffffff, 0x00020406,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x04040404,
+ 0xe04, 0xffffffff, 0x00020204,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x04040404,
+ 0x834, 0xffffffff, 0x00020204,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+ 0xe00, 0xffffffff, 0x00000000,
+ 0xe04, 0xffffffff, 0x00000000,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0x86c, 0xffffff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x00000000,
+ 0xe14, 0xffffffff, 0x00000000,
+ 0xe18, 0xffffffff, 0x00000000,
+ 0xe1c, 0xffffffff, 0x00000000,
+ 0x830, 0xffffffff, 0x00000000,
+ 0x834, 0xffffffff, 0x00000000,
+ 0x838, 0xffffff00, 0x00000000,
+ 0x86c, 0x000000ff, 0x00000000,
+ 0x83c, 0xffffffff, 0x00000000,
+ 0x848, 0xffffffff, 0x00000000,
+ 0x84c, 0xffffffff, 0x00000000,
+ 0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8723E_RADIOA_1TARRAY[Rtl8723ERADIOA_1TARRAYLENGTH] = {
+ 0x000, 0x00030159,
+ 0x001, 0x00031284,
+ 0x002, 0x00098000,
+ 0x003, 0x00018c63,
+ 0x004, 0x000210e7,
+ 0x009, 0x0002044f,
+ 0x00a, 0x0001a3f1,
+ 0x00b, 0x00014787,
+ 0x00c, 0x000896fe,
+ 0x00d, 0x0000e02c,
+ 0x00e, 0x00039ce7,
+ 0x00f, 0x00000451,
+ 0x019, 0x00000000,
+ 0x01a, 0x00030355,
+ 0x01b, 0x00060a00,
+ 0x01c, 0x000fc378,
+ 0x01d, 0x000a1250,
+ 0x01e, 0x0004445f,
+ 0x01f, 0x00080001,
+ 0x020, 0x0000b614,
+ 0x021, 0x0006c000,
+ 0x022, 0x00000000,
+ 0x023, 0x00001558,
+ 0x024, 0x00000060,
+ 0x025, 0x00000483,
+ 0x026, 0x0004f000,
+ 0x027, 0x000ec7d9,
+ 0x028, 0x00057730,
+ 0x029, 0x00004783,
+ 0x02a, 0x00000001,
+ 0x02b, 0x00021334,
+ 0x02a, 0x00000000,
+ 0x02b, 0x00000054,
+ 0x02a, 0x00000001,
+ 0x02b, 0x00000808,
+ 0x02b, 0x00053333,
+ 0x02c, 0x0000000c,
+ 0x02a, 0x00000002,
+ 0x02b, 0x00000808,
+ 0x02b, 0x0005b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000003,
+ 0x02b, 0x00000808,
+ 0x02b, 0x00063333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000004,
+ 0x02b, 0x00000808,
+ 0x02b, 0x0006b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000005,
+ 0x02b, 0x00000808,
+ 0x02b, 0x00073333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000006,
+ 0x02b, 0x00000709,
+ 0x02b, 0x0005b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000007,
+ 0x02b, 0x00000709,
+ 0x02b, 0x00063333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000008,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x0004b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x00000009,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x00053333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x0000000a,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x0005b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x0000000b,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x00063333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x0000000c,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x0006b333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x0000000d,
+ 0x02b, 0x0000060a,
+ 0x02b, 0x00073333,
+ 0x02c, 0x0000000d,
+ 0x02a, 0x0000000e,
+ 0x02b, 0x0000050b,
+ 0x02b, 0x00066666,
+ 0x02c, 0x0000001a,
+ 0x02a, 0x000e0000,
+ 0x010, 0x0004000f,
+ 0x011, 0x000e31fc,
+ 0x010, 0x0006000f,
+ 0x011, 0x000ff9f8,
+ 0x010, 0x0002000f,
+ 0x011, 0x000203f9,
+ 0x010, 0x0003000f,
+ 0x011, 0x000ff500,
+ 0x010, 0x00000000,
+ 0x011, 0x00000000,
+ 0x010, 0x0008000f,
+ 0x011, 0x0003f100,
+ 0x010, 0x0009000f,
+ 0x011, 0x00023100,
+ 0x012, 0x00032000,
+ 0x012, 0x00071000,
+ 0x012, 0x000b0000,
+ 0x012, 0x000fc000,
+ 0x013, 0x000287b3,
+ 0x013, 0x000244b7,
+ 0x013, 0x000204ab,
+ 0x013, 0x0001c49f,
+ 0x013, 0x00018493,
+ 0x013, 0x0001429b,
+ 0x013, 0x00010299,
+ 0x013, 0x0000c29c,
+ 0x013, 0x000081a0,
+ 0x013, 0x000040ac,
+ 0x013, 0x00000020,
+ 0x014, 0x0001944c,
+ 0x014, 0x00059444,
+ 0x014, 0x0009944c,
+ 0x014, 0x000d9444,
+ 0x015, 0x0000f424,
+ 0x015, 0x0004f407,
+ 0x015, 0x0008f424,
+ 0x015, 0x000cf424,
+ 0x016, 0x00000339,
+ 0x016, 0x00040339,
+ 0x016, 0x00080339,
+ 0x016, 0x000c0336,
+ 0x000, 0x00010159,
+ 0x018, 0x0000f401,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01f, 0x00080003,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x01e, 0x00044457,
+ 0x01f, 0x00080000,
+ 0x000, 0x00030159,
+};
+
+
+u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH] = {
+ 0x0,
+};
+
+
+u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH] = {
+ 0x420, 0x00000080,
+ 0x423, 0x00000000,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000004,
+ 0x435, 0x00000005,
+ 0x436, 0x00000006,
+ 0x437, 0x00000007,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43a, 0x00000000,
+ 0x43b, 0x00000001,
+ 0x43c, 0x00000004,
+ 0x43d, 0x00000005,
+ 0x43e, 0x00000006,
+ 0x43f, 0x00000007,
+ 0x440, 0x0000005d,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000015,
+ 0x445, 0x000000f0,
+ 0x446, 0x0000000f,
+ 0x447, 0x00000000,
+ 0x458, 0x00000041,
+ 0x459, 0x000000a8,
+ 0x45a, 0x00000072,
+ 0x45b, 0x000000b9,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x462, 0x00000008,
+ 0x463, 0x00000003,
+ 0x4c8, 0x000000ff,
+ 0x4c9, 0x00000008,
+ 0x4cc, 0x000000ff,
+ 0x4cd, 0x000000ff,
+ 0x4ce, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000a2,
+ 0x502, 0x0000002f,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000a3,
+ 0x506, 0x0000005e,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002b,
+ 0x509, 0x000000a4,
+ 0x50a, 0x0000005e,
+ 0x50b, 0x00000000,
+ 0x50c, 0x0000004f,
+ 0x50d, 0x000000a4,
+ 0x50e, 0x00000000,
+ 0x50f, 0x00000000,
+ 0x512, 0x0000001c,
+ 0x514, 0x0000000a,
+ 0x515, 0x00000010,
+ 0x516, 0x0000000a,
+ 0x517, 0x00000010,
+ 0x51a, 0x00000016,
+ 0x524, 0x0000000f,
+ 0x525, 0x0000004f,
+ 0x546, 0x00000040,
+ 0x547, 0x00000000,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55a, 0x00000002,
+ 0x55d, 0x000000ff,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000e,
+ 0x609, 0x0000002a,
+ 0x652, 0x00000020,
+ 0x63c, 0x0000000a,
+ 0x63d, 0x0000000e,
+ 0x63e, 0x0000000a,
+ 0x63f, 0x0000000e,
+ 0x66e, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70a, 0x00000065,
+ 0x70b, 0x00000087,
+};
+
+u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH] = {
+ 0xc78, 0x7b000001,
+ 0xc78, 0x7b010001,
+ 0xc78, 0x7b020001,
+ 0xc78, 0x7b030001,
+ 0xc78, 0x7b040001,
+ 0xc78, 0x7b050001,
+ 0xc78, 0x7a060001,
+ 0xc78, 0x79070001,
+ 0xc78, 0x78080001,
+ 0xc78, 0x77090001,
+ 0xc78, 0x760a0001,
+ 0xc78, 0x750b0001,
+ 0xc78, 0x740c0001,
+ 0xc78, 0x730d0001,
+ 0xc78, 0x720e0001,
+ 0xc78, 0x710f0001,
+ 0xc78, 0x70100001,
+ 0xc78, 0x6f110001,
+ 0xc78, 0x6e120001,
+ 0xc78, 0x6d130001,
+ 0xc78, 0x6c140001,
+ 0xc78, 0x6b150001,
+ 0xc78, 0x6a160001,
+ 0xc78, 0x69170001,
+ 0xc78, 0x68180001,
+ 0xc78, 0x67190001,
+ 0xc78, 0x661a0001,
+ 0xc78, 0x651b0001,
+ 0xc78, 0x641c0001,
+ 0xc78, 0x631d0001,
+ 0xc78, 0x621e0001,
+ 0xc78, 0x611f0001,
+ 0xc78, 0x60200001,
+ 0xc78, 0x49210001,
+ 0xc78, 0x48220001,
+ 0xc78, 0x47230001,
+ 0xc78, 0x46240001,
+ 0xc78, 0x45250001,
+ 0xc78, 0x44260001,
+ 0xc78, 0x43270001,
+ 0xc78, 0x42280001,
+ 0xc78, 0x41290001,
+ 0xc78, 0x402a0001,
+ 0xc78, 0x262b0001,
+ 0xc78, 0x252c0001,
+ 0xc78, 0x242d0001,
+ 0xc78, 0x232e0001,
+ 0xc78, 0x222f0001,
+ 0xc78, 0x21300001,
+ 0xc78, 0x20310001,
+ 0xc78, 0x06320001,
+ 0xc78, 0x05330001,
+ 0xc78, 0x04340001,
+ 0xc78, 0x03350001,
+ 0xc78, 0x02360001,
+ 0xc78, 0x01370001,
+ 0xc78, 0x00380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x7b400001,
+ 0xc78, 0x7b410001,
+ 0xc78, 0x7b420001,
+ 0xc78, 0x7b430001,
+ 0xc78, 0x7b440001,
+ 0xc78, 0x7b450001,
+ 0xc78, 0x7a460001,
+ 0xc78, 0x79470001,
+ 0xc78, 0x78480001,
+ 0xc78, 0x77490001,
+ 0xc78, 0x764a0001,
+ 0xc78, 0x754b0001,
+ 0xc78, 0x744c0001,
+ 0xc78, 0x734d0001,
+ 0xc78, 0x724e0001,
+ 0xc78, 0x714f0001,
+ 0xc78, 0x70500001,
+ 0xc78, 0x6f510001,
+ 0xc78, 0x6e520001,
+ 0xc78, 0x6d530001,
+ 0xc78, 0x6c540001,
+ 0xc78, 0x6b550001,
+ 0xc78, 0x6a560001,
+ 0xc78, 0x69570001,
+ 0xc78, 0x68580001,
+ 0xc78, 0x67590001,
+ 0xc78, 0x665a0001,
+ 0xc78, 0x655b0001,
+ 0xc78, 0x645c0001,
+ 0xc78, 0x635d0001,
+ 0xc78, 0x625e0001,
+ 0xc78, 0x615f0001,
+ 0xc78, 0x60600001,
+ 0xc78, 0x49610001,
+ 0xc78, 0x48620001,
+ 0xc78, 0x47630001,
+ 0xc78, 0x46640001,
+ 0xc78, 0x45650001,
+ 0xc78, 0x44660001,
+ 0xc78, 0x43670001,
+ 0xc78, 0x42680001,
+ 0xc78, 0x41690001,
+ 0xc78, 0x406a0001,
+ 0xc78, 0x266b0001,
+ 0xc78, 0x256c0001,
+ 0xc78, 0x246d0001,
+ 0xc78, 0x236e0001,
+ 0xc78, 0x226f0001,
+ 0xc78, 0x21700001,
+ 0xc78, 0x20710001,
+ 0xc78, 0x06720001,
+ 0xc78, 0x05730001,
+ 0xc78, 0x04740001,
+ 0xc78, 0x03750001,
+ 0xc78, 0x02760001,
+ 0xc78, 0x01770001,
+ 0xc78, 0x00780001,
+ 0xc78, 0x00790001,
+ 0xc78, 0x007a0001,
+ 0xc78, 0x007b0001,
+ 0xc78, 0x007c0001,
+ 0xc78, 0x007d0001,
+ 0xc78, 0x007e0001,
+ 0xc78, 0x007f0001,
+ 0xc78, 0x3800001e,
+ 0xc78, 0x3801001e,
+ 0xc78, 0x3802001e,
+ 0xc78, 0x3803001e,
+ 0xc78, 0x3804001e,
+ 0xc78, 0x3805001e,
+ 0xc78, 0x3806001e,
+ 0xc78, 0x3807001e,
+ 0xc78, 0x3808001e,
+ 0xc78, 0x3c09001e,
+ 0xc78, 0x3e0a001e,
+ 0xc78, 0x400b001e,
+ 0xc78, 0x440c001e,
+ 0xc78, 0x480d001e,
+ 0xc78, 0x4c0e001e,
+ 0xc78, 0x500f001e,
+ 0xc78, 0x5210001e,
+ 0xc78, 0x5611001e,
+ 0xc78, 0x5a12001e,
+ 0xc78, 0x5e13001e,
+ 0xc78, 0x6014001e,
+ 0xc78, 0x6015001e,
+ 0xc78, 0x6016001e,
+ 0xc78, 0x6217001e,
+ 0xc78, 0x6218001e,
+ 0xc78, 0x6219001e,
+ 0xc78, 0x621a001e,
+ 0xc78, 0x621b001e,
+ 0xc78, 0x621c001e,
+ 0xc78, 0x621d001e,
+ 0xc78, 0x621e001e,
+ 0xc78, 0x621f001e,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/rtlwifi/rtl8723ae/table.h
new file mode 100644
index 000000000000..f5ce71375c20
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/table.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Created on 2010/ 5/18, 1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_TABLE__H_
+#define __RTL8723E_TABLE__H_
+
+#include <linux/types.h>
+
+#define RTL8723E_PHY_REG_1TARRAY_LENGTH 372
+extern u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH];
+#define RTL8723E_PHY_REG_ARRAY_PGLENGTH 336
+extern u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH];
+#define Rtl8723ERADIOA_1TARRAYLENGTH 282
+extern u32 RTL8723E_RADIOA_1TARRAY[Rtl8723ERADIOA_1TARRAYLENGTH];
+#define RTL8723E_RADIOB_1TARRAYLENGTH 1
+extern u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH];
+#define RTL8723E_MACARRAYLENGTH 172
+extern u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH];
+#define RTL8723E_AGCTAB_1TARRAYLENGTH 320
+extern u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
new file mode 100644
index 000000000000..87331d826d73
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -0,0 +1,670 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "../stats.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+
+static u8 _rtl8723ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+ __le16 fc = rtl_get_fc(skb);
+
+ if (unlikely(ieee80211_is_beacon(fc)))
+ return QSLT_BEACON;
+ if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
+ return QSLT_MGNT;
+
+ return skb->priority;
+}
+
+static void _rtl8723ae_query_rxphystatus(struct ieee80211_hw *hw,
+ struct rtl_stats *pstatus, u8 *pdesc,
+ struct rx_fwinfo_8723e *p_drvinfo,
+ bool bpacket_match_bssid,
+ bool bpacket_toself, bool packet_beacon)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ struct phy_sts_cck_8723e_t *cck_buf;
+ s8 rx_pwr_all, rx_pwr[4];
+ u8 rf_rx_num = 0, evm, pwdb_all;
+ u8 i, max_spatial_stream;
+ u32 rssi, total_rssi = 0;
+ bool is_cck = pstatus->is_cck;
+
+ /* Record it for next packet processing */
+ pstatus->packet_matchbssid = bpacket_match_bssid;
+ pstatus->packet_toself = bpacket_toself;
+ pstatus->packet_beacon = packet_beacon;
+ pstatus->rx_mimo_sig_qual[0] = -1;
+ pstatus->rx_mimo_sig_qual[1] = -1;
+
+ if (is_cck) {
+ u8 report, cck_highpwr;
+
+ /* CCK Driver info Structure is not the same as OFDM packet. */
+ cck_buf = (struct phy_sts_cck_8723e_t *)p_drvinfo;
+
+ /* (1)Hardware does not provide RSSI for CCK
+ * (2)PWDB, Average PWDB cacluated by
+ * hardware (for rate adaptive)
+ */
+ if (ppsc->rfpwr_state == ERFON)
+ cck_highpwr = (u8) rtl_get_bbreg(hw,
+ RFPGA0_XA_HSSIPARAMETER2,
+ BIT(9));
+ else
+ cck_highpwr = false;
+
+ if (!cck_highpwr) {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = cck_buf->cck_agc_rpt & 0xc0;
+ report = report >> 6;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+ report = p_drvinfo->cfosho[0] & 0x60;
+ report = report >> 5;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ }
+ }
+
+ pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
+ /* CCK gain is smaller than OFDM/MCS gain,
+ * so we add gain diff. From experience, the val is 6
+ */
+ pwdb_all += 6;
+ if (pwdb_all > 100)
+ pwdb_all = 100;
+ /* modify the offset to make the same
+ * gain index with OFDM.
+ */
+ if (pwdb_all > 34 && pwdb_all <= 42)
+ pwdb_all -= 2;
+ else if (pwdb_all > 26 && pwdb_all <= 34)
+ pwdb_all -= 6;
+ else if (pwdb_all > 14 && pwdb_all <= 26)
+ pwdb_all -= 8;
+ else if (pwdb_all > 4 && pwdb_all <= 14)
+ pwdb_all -= 4;
+
+ pstatus->rx_pwdb_all = pwdb_all;
+ pstatus->recvsignalpower = rx_pwr_all;
+
+ /* (3) Get Signal Quality (EVM) */
+ if (bpacket_match_bssid) {
+ u8 sq;
+
+ if (pstatus->rx_pwdb_all > 40) {
+ sq = 100;
+ } else {
+ sq = cck_buf->sq_rpt;
+ if (sq > 64)
+ sq = 0;
+ else if (sq < 20)
+ sq = 100;
+ else
+ sq = ((64 - sq) * 100) / 44;
+ }
+
+ pstatus->signalquality = sq;
+ pstatus->rx_mimo_sig_qual[0] = sq;
+ pstatus->rx_mimo_sig_qual[1] = -1;
+ }
+ } else {
+ rtlpriv->dm.rfpath_rxenable[0] =
+ rtlpriv->dm.rfpath_rxenable[1] = true;
+
+ /* (1)Get RSSI for HT rate */
+ for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+
+ /* we will judge RF RX path now. */
+ if (rtlpriv->dm.rfpath_rxenable[i])
+ rf_rx_num++;
+
+ rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f)*2) - 110;
+
+ /* Translate DBM to percentage. */
+ rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
+ total_rssi += rssi;
+
+ /* Get Rx snr value in DB */
+ rtlpriv->stats.rx_snr_db[i] = (p_drvinfo->rxsnr[i] / 2);
+
+ /* Record Signal Strength for next packet */
+ if (bpacket_match_bssid)
+ pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
+ }
+
+ /* (2)PWDB, Average PWDB cacluated by
+ * hardware (for rate adaptive)
+ */
+ rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
+
+ pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
+ pstatus->rx_pwdb_all = pwdb_all;
+ pstatus->rxpower = rx_pwr_all;
+ pstatus->recvsignalpower = rx_pwr_all;
+
+ /* (3)EVM of HT rate */
+ if (pstatus->is_ht && pstatus->rate >= DESC92_RATEMCS8 &&
+ pstatus->rate <= DESC92_RATEMCS15)
+ max_spatial_stream = 2;
+ else
+ max_spatial_stream = 1;
+
+ for (i = 0; i < max_spatial_stream; i++) {
+ evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+
+ if (bpacket_match_bssid) {
+ /* Fill value in RFD, Get the first
+ * spatial stream only
+ */
+ if (i == 0)
+ pstatus->signalquality = (evm & 0xff);
+ pstatus->rx_mimo_sig_qual[i] = (evm & 0xff);
+ }
+ }
+ }
+
+ /* UI BSS List signal strength(in percentage),
+ * make it good looking, from 0~100.
+ */
+ if (is_cck)
+ pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+ pwdb_all));
+ else if (rf_rx_num != 0)
+ pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+ total_rssi /= rf_rx_num));
+}
+
+static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+ struct sk_buff *skb, struct rtl_stats *pstatus,
+ u8 *pdesc, struct rx_fwinfo_8723e *p_drvinfo)
+{
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ struct ieee80211_hdr *hdr;
+ u8 *tmp_buf;
+ u8 *praddr;
+ u8 *psaddr;
+ __le16 fc;
+ u16 type;
+ bool packet_matchbssid, packet_toself, packet_beacon;
+
+ tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
+
+ hdr = (struct ieee80211_hdr *)tmp_buf;
+ fc = hdr->frame_control;
+ type = WLAN_FC_GET_TYPE(fc);
+ praddr = hdr->addr1;
+ psaddr = ieee80211_get_SA(hdr);
+
+ packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
+ (!compare_ether_addr(mac->bssid,
+ (le16_to_cpu(fc) & IEEE80211_FCTL_TODS) ?
+ hdr->addr1 : (le16_to_cpu(fc) &
+ IEEE80211_FCTL_FROMDS) ?
+ hdr->addr2 : hdr->addr3)) && (!pstatus->hwerror) &&
+ (!pstatus->crc) && (!pstatus->icv));
+
+ packet_toself = packet_matchbssid &&
+ (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+
+ if (ieee80211_is_beacon(fc))
+ packet_beacon = true;
+
+ _rtl8723ae_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo,
+ packet_matchbssid, packet_toself,
+ packet_beacon);
+
+ rtl_process_phyinfo(hw, tmp_buf, pstatus);
+}
+
+bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
+ struct rtl_stats *status,
+ struct ieee80211_rx_status *rx_status,
+ u8 *pdesc, struct sk_buff *skb)
+{
+ struct rx_fwinfo_8723e *p_drvinfo;
+ struct ieee80211_hdr *hdr;
+ u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+ status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+ status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+ RX_DRV_INFO_SIZE_UNIT;
+ status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+ status->icv = (u16) GET_RX_DESC_ICV(pdesc);
+ status->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+ status->hwerror = (status->crc | status->icv);
+ status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+ status->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+ status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+ status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+ status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+ && (GET_RX_DESC_FAGGR(pdesc) == 1));
+ status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+ status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+ status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
+
+ status->is_cck = RTL8723E_RX_HAL_IS_CCK_RATE(status->rate);
+
+ rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.channel->band;
+
+ hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size
+ + status->rx_bufshift);
+
+ if (status->crc)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+ if (status->rx_is40Mhzpacket)
+ rx_status->flag |= RX_FLAG_40MHZ;
+
+ if (status->is_ht)
+ rx_status->flag |= RX_FLAG_HT;
+
+ rx_status->flag |= RX_FLAG_MACTIME_START;
+
+ /* hw will set status->decrypted true, if it finds the
+ * frame is open data frame or mgmt frame.
+ * Thus hw will not decrypt a robust managment frame
+ * for IEEE80211w but still set status->decrypted
+ * true, so here we should set it back to undecrypted
+ * for IEEE80211w frame, and mac80211 sw will help
+ * to decrypt it
+ */
+ if (status->decrypted) {
+ if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+ (ieee80211_has_protected(hdr->frame_control)))
+ rx_status->flag &= ~RX_FLAG_DECRYPTED;
+ else
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ }
+
+ /* rate_idx: index of data rate into band's
+ * supported rates or MCS index if HT rates
+ * are use (RX_FLAG_HT)
+ */
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht,
+ status->rate, false);
+
+ rx_status->mactime = status->timestamp_low;
+ if (phystatus == true) {
+ p_drvinfo = (struct rx_fwinfo_8723e *)(skb->data +
+ status->rx_bufshift);
+
+ _rtl8723ae_translate_rx_signal_stuff(hw,
+ skb, status, pdesc, p_drvinfo);
+ }
+
+ /*rx_status->qual = status->signal; */
+ rx_status->signal = status->recvsignalpower + 10;
+ /*rx_status->noise = -status->noise; */
+
+ return true;
+}
+
+void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb, u8 hw_queue,
+ struct rtl_tcb_desc *ptcdesc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ bool defaultadapter = true;
+ u8 *pdesc = (u8 *) pdesc_tx;
+ u16 seq_number;
+ __le16 fc = hdr->frame_control;
+ u8 fw_qsel = _rtl8723ae_map_hwqueue_to_fwqueue(skb, hw_queue);
+ bool firstseg = ((hdr->seq_ctrl &
+ cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+ bool lastseg = ((hdr->frame_control &
+ cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+ dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+ skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ u8 bw_40 = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_STATION) {
+ bw_40 = mac->bw_40;
+ } else if (mac->opmode == NL80211_IFTYPE_AP ||
+ mac->opmode == NL80211_IFTYPE_ADHOC) {
+ if (sta)
+ bw_40 = sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+
+ seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+
+ rtl_get_tcb_desc(hw, info, sta, skb, ptcdesc);
+
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723e));
+
+ if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+ firstseg = true;
+ lastseg = true;
+ }
+
+ if (firstseg) {
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+
+ SET_TX_DESC_TX_RATE(pdesc, ptcdesc->hw_rate);
+
+ if (ptcdesc->use_shortgi || ptcdesc->use_shortpreamble)
+ SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ SET_TX_DESC_AGG_BREAK(pdesc, 1);
+ SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
+ }
+ SET_TX_DESC_SEQ(pdesc, seq_number);
+
+ SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcdesc->rts_enable &&
+ !ptcdesc->
+ cts_enable) ? 1 : 0));
+ SET_TX_DESC_HW_RTS_ENABLE(pdesc,
+ ((ptcdesc->rts_enable
+ || ptcdesc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_CTS2SELF(pdesc, ((ptcdesc->cts_enable) ? 1 : 0));
+ SET_TX_DESC_RTS_STBC(pdesc, ((ptcdesc->rts_stbc) ? 1 : 0));
+
+ SET_TX_DESC_RTS_RATE(pdesc, ptcdesc->rts_rate);
+ SET_TX_DESC_RTS_BW(pdesc, 0);
+ SET_TX_DESC_RTS_SC(pdesc, ptcdesc->rts_sc);
+ SET_TX_DESC_RTS_SHORT(pdesc,
+ ((ptcdesc->rts_rate <= DESC92_RATE54M) ?
+ (ptcdesc->rts_use_shortpreamble ? 1 : 0)
+ : (ptcdesc->rts_use_shortgi ? 1 : 0)));
+
+ if (bw_40) {
+ if (ptcdesc->packet_bw) {
+ SET_TX_DESC_DATA_BW(pdesc, 1);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc,
+ mac->cur_40_prime_sc);
+ }
+ } else {
+ SET_TX_DESC_DATA_BW(pdesc, 0);
+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
+ }
+
+ SET_TX_DESC_LINIP(pdesc, 0);
+ SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
+
+ if (sta) {
+ u8 ampdu_density = sta->ht_cap.ampdu_density;
+ SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+ }
+
+ if (info->control.hw_key) {
+ struct ieee80211_key_conf *keyconf =
+ info->control.hw_key;
+
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+ break;
+ default:
+ SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+ break;
+ }
+ }
+
+ SET_TX_DESC_PKT_ID(pdesc, 0);
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
+
+ SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
+ SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
+ SET_TX_DESC_DISABLE_FB(pdesc, 0);
+ SET_TX_DESC_USE_RATE(pdesc, ptcdesc->use_driver_rate ? 1 : 0);
+
+ if (ieee80211_is_data_qos(fc)) {
+ if (mac->rdg_en) {
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+ "Enable RDG function.\n");
+ SET_TX_DESC_RDG_ENABLE(pdesc, 1);
+ SET_TX_DESC_HTC(pdesc, 1);
+ }
+ }
+ }
+
+ SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+ SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
+
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
+
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+
+ if (rtlpriv->dm.useramask) {
+ SET_TX_DESC_RATE_ID(pdesc, ptcdesc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcdesc->mac_id);
+ } else {
+ SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcdesc->ratr_index);
+ SET_TX_DESC_MACID(pdesc, ptcdesc->ratr_index);
+ }
+
+ if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
+ SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1);
+
+ if (!defaultadapter)
+ SET_TX_DESC_HWSEQ_SEL_8723(pdesc, 1);
+ }
+
+ SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+
+ if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+ is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
+ SET_TX_DESC_BMC(pdesc, 1);
+ }
+
+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
+}
+
+void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw,
+ u8 *pdesc, bool firstseg,
+ bool lastseg, struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ u8 fw_queue = QSLT_BEACON;
+ dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+ skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ __le16 fc = hdr->frame_control;
+
+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+
+ if (firstseg)
+ SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
+
+ SET_TX_DESC_SEQ(pdesc, 0);
+
+ SET_TX_DESC_LINIP(pdesc, 0);
+
+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+
+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
+
+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+
+ SET_TX_DESC_RATE_ID(pdesc, 7);
+ SET_TX_DESC_MACID(pdesc, 0);
+
+ SET_TX_DESC_OWN(pdesc, 1);
+
+ SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+
+ SET_TX_DESC_FIRST_SEG(pdesc, 1);
+ SET_TX_DESC_LAST_SEG(pdesc, 1);
+
+ SET_TX_DESC_OFFSET(pdesc, 0x20);
+
+ SET_TX_DESC_USE_RATE(pdesc, 1);
+
+ if (!ieee80211_is_data_qos(fc)) {
+ SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1);
+ /* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */
+ /* SET_TX_DESC_PKT_ID(pdesc, 8); */
+ }
+
+ RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+ "H2C Tx Cmd Content\n",
+ pdesc, TX_DESC_SIZE);
+}
+
+void rtl8723ae_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+ if (istx == true) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ SET_TX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_TX_NEXTDESC_ADDR:
+ SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
+ break;
+ default:
+ RT_ASSERT(false, "ERR txdesc :%d not process\n",
+ desc_name);
+ break;
+ }
+ } else {
+ switch (desc_name) {
+ case HW_DESC_RXOWN:
+ SET_RX_DESC_OWN(pdesc, 1);
+ break;
+ case HW_DESC_RXBUFF_ADDR:
+ SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
+ break;
+ case HW_DESC_RXERO:
+ SET_RX_DESC_EOR(pdesc, 1);
+ break;
+ default:
+ RT_ASSERT(false, "ERR rxdesc :%d not process\n",
+ desc_name);
+ break;
+ }
+ }
+}
+
+u32 rtl8723ae_get_desc(u8 *pdesc, bool istx, u8 desc_name)
+{
+ u32 ret = 0;
+
+ if (istx == true) {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_TX_DESC_OWN(pdesc);
+ break;
+ case HW_DESC_TXBUFF_ADDR:
+ ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc);
+ break;
+ default:
+ RT_ASSERT(false, "ERR txdesc :%d not process\n",
+ desc_name);
+ break;
+ }
+ } else {
+ switch (desc_name) {
+ case HW_DESC_OWN:
+ ret = GET_RX_DESC_OWN(pdesc);
+ break;
+ case HW_DESC_RXPKT_LEN:
+ ret = GET_RX_DESC_PKT_LEN(pdesc);
+ break;
+ default:
+ RT_ASSERT(false, "ERR rxdesc :%d not process\n",
+ desc_name);
+ break;
+ }
+ }
+ return ret;
+}
+
+void rtl8723ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ if (hw_queue == BEACON_QUEUE) {
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
+ } else {
+ rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
+ BIT(0) << (hw_queue));
+ }
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
new file mode 100644
index 000000000000..ad05b54bc0f1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
@@ -0,0 +1,725 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_TRX_H__
+#define __RTL8723E_TRX_H__
+
+#define TX_DESC_SIZE 64
+#define TX_DESC_AGGR_SUBFRAME_SIZE 32
+
+#define RX_DESC_SIZE 32
+#define RX_DRV_INFO_SIZE_UNIT 8
+
+#define TX_DESC_NEXT_DESC_OFFSET 40
+#define USB_HWDESC_HEADER_LEN 32
+#define CRCLENGTH 4
+
+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val)
+#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val)
+#define SET_TX_DESC_BK(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_PKT_ID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val)
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
+#define GET_TX_DESC_PKT_ID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 28, 4)
+
+/* For RTL8723 */
+#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN_8723(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val)
+#define SET_TX_DESC_HWSEQ_SEL_8723(__pTxDesc, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 6, 2, __Value)
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)\
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
+#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 16, 4)
+#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 20, 4)
+#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 24, 4)
+#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 5, 4)
+#define GET_RX_DESC_HWRSVD(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 9, 5)
+#define GET_RX_DESC_PAGGR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
+#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 16, 14)
+#define GET_RX_DESC_NEXT_IND(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 30, 1)
+#define GET_RX_DESC_RSVD(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+8, 31, 1)
+
+#define GET_RX_DESC_RXMCS(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
+#define GET_RX_DESC_SPLCP(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
+#define GET_RX_DESC_HWPC_ERR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+12, 16, 16)
+
+#define GET_RX_DESC_IV1(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \
+ LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \
+do { \
+ if (_size > TX_DESC_NEXT_DESC_OFFSET) \
+ memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \
+ else \
+ memset(__pdesc, 0, _size); \
+} while (0)
+
+#define RTL8723E_RX_HAL_IS_CCK_RATE(rxmcs) \
+ ((rxmcs) == DESC92_RATE1M || \
+ (rxmcs) == DESC92_RATE2M || \
+ (rxmcs) == DESC92_RATE5_5M || \
+ (rxmcs) == DESC92_RATE11M)
+
+struct rx_fwinfo_8723e {
+ u8 gain_trsw[4];
+ u8 pwdb_all;
+ u8 cfosho[4];
+ u8 cfotail[4];
+ char rxevm[2];
+ char rxsnr[4];
+ u8 pdsnr[2];
+ u8 csi_current[2];
+ u8 csi_target[2];
+ u8 sigevm;
+ u8 max_ex_pwr;
+ u8 ex_intf_flag:1;
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 reserve:4;
+} __packed;
+
+struct tx_desc_8723e {
+ u32 pktsize:16;
+ u32 offset:8;
+ u32 bmc:1;
+ u32 htc:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 linip:1;
+ u32 noacm:1;
+ u32 gf:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 agg_en:1;
+ u32 bk:1;
+ u32 rdg_en:1;
+ u32 queuesel:5;
+ u32 rd_nav_ext:1;
+ u32 lsig_txop_en:1;
+ u32 pifs:1;
+ u32 rateid:4;
+ u32 nav_usehdr:1;
+ u32 en_descid:1;
+ u32 sectype:2;
+ u32 pktoffset:8;
+
+ u32 rts_rc:6;
+ u32 data_rc:6;
+ u32 rsvd0:2;
+ u32 bar_retryht:2;
+ u32 rsvd1:1;
+ u32 morefrag:1;
+ u32 raw:1;
+ u32 ccx:1;
+ u32 ampdudensity:3;
+ u32 rsvd2:1;
+ u32 ant_sela:1;
+ u32 ant_selb:1;
+ u32 txant_cck:2;
+ u32 txant_l:2;
+ u32 txant_ht:2;
+
+ u32 nextheadpage:8;
+ u32 tailpage:8;
+ u32 seq:12;
+ u32 pktid:4;
+
+ u32 rtsrate:5;
+ u32 apdcfe:1;
+ u32 qos:1;
+ u32 hwseq_enable:1;
+ u32 userrate:1;
+ u32 dis_rtsfb:1;
+ u32 dis_datafb:1;
+ u32 cts2self:1;
+ u32 rts_en:1;
+ u32 hwrts_en:1;
+ u32 portid:1;
+ u32 rsvd3:3;
+ u32 waitdcts:1;
+ u32 cts2ap_en:1;
+ u32 txsc:2;
+ u32 stbc:2;
+ u32 txshort:1;
+ u32 txbw:1;
+ u32 rtsshort:1;
+ u32 rtsbw:1;
+ u32 rtssc:2;
+ u32 rtsstbc:2;
+
+ u32 txrate:6;
+ u32 shortgi:1;
+ u32 ccxt:1;
+ u32 txrate_fb_lmt:5;
+ u32 rtsrate_fb_lmt:4;
+ u32 retrylmt_en:1;
+ u32 txretrylmt:6;
+ u32 usb_txaggnum:8;
+
+ u32 txagca:5;
+ u32 txagcb:5;
+ u32 usemaxlen:1;
+ u32 maxaggnum:5;
+ u32 mcsg1maxlen:4;
+ u32 mcsg2maxlen:4;
+ u32 mcsg3maxlen:4;
+ u32 mcs7sgimaxlen:4;
+
+ u32 txbuffersize:16;
+ u32 mcsg4maxlen:4;
+ u32 mcsg5maxlen:4;
+ u32 mcsg6maxlen:4;
+ u32 mcsg15sgimaxlen:4;
+
+ u32 txbuffaddr;
+ u32 txbufferaddr64;
+ u32 nextdescaddress;
+ u32 nextdescaddress64;
+
+ u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_8723e {
+ u32 length:14;
+ u32 crc32:1;
+ u32 icverror:1;
+ u32 drv_infosize:4;
+ u32 security:3;
+ u32 qos:1;
+ u32 shift:2;
+ u32 phystatus:1;
+ u32 swdec:1;
+ u32 lastseg:1;
+ u32 firstseg:1;
+ u32 eor:1;
+ u32 own:1;
+
+ u32 macid:5;
+ u32 tid:4;
+ u32 hwrsvd:5;
+ u32 paggr:1;
+ u32 faggr:1;
+ u32 a1_fit:4;
+ u32 a2_fit:4;
+ u32 pam:1;
+ u32 pwr:1;
+ u32 moredata:1;
+ u32 morefrag:1;
+ u32 type:2;
+ u32 mc:1;
+ u32 bc:1;
+
+ u32 seq:12;
+ u32 frag:4;
+ u32 nextpktlen:14;
+ u32 nextind:1;
+ u32 rsvd:1;
+
+ u32 rxmcs:6;
+ u32 rxht:1;
+ u32 amsdu:1;
+ u32 splcp:1;
+ u32 bandwidth:1;
+ u32 htc:1;
+ u32 tcpchk_rpt:1;
+ u32 ipcchk_rpt:1;
+ u32 tcpchk_valid:1;
+ u32 hwpcerr:1;
+ u32 hwpcind:1;
+ u32 iv0:16;
+
+ u32 iv1;
+
+ u32 tsfl;
+
+ u32 bufferaddress;
+ u32 bufferaddress64;
+
+} __packed;
+
+void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
+ struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb, u8 hw_queue,
+ struct rtl_tcb_desc *ptcb_desc);
+bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
+ struct rtl_stats *status,
+ struct ieee80211_rx_status *rx_status,
+ u8 *pdesc, struct sk_buff *skb);
+void rtl8723ae_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl8723ae_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl8723ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+ bool b_firstseg, bool b_lastseg,
+ struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c
new file mode 100644
index 000000000000..8ed31744a054
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/stats.c
@@ -0,0 +1,268 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+#include "wifi.h"
+#include "stats.h"
+#include <linux/export.h>
+
+u8 rtl_query_rxpwrpercentage(char antpower)
+{
+ if ((antpower <= -100) || (antpower >= 20))
+ return 0;
+ else if (antpower >= 0)
+ return 100;
+ else
+ return 100 + antpower;
+}
+EXPORT_SYMBOL(rtl_query_rxpwrpercentage);
+
+u8 rtl_evm_db_to_percentage(char value)
+{
+ char ret_val;
+ ret_val = value;
+
+ if (ret_val >= 0)
+ ret_val = 0;
+ if (ret_val <= -33)
+ ret_val = -33;
+ ret_val = 0 - ret_val;
+ ret_val *= 3;
+ if (ret_val == 99)
+ ret_val = 100;
+
+ return ret_val;
+}
+EXPORT_SYMBOL(rtl_evm_db_to_percentage);
+
+static long rtl_translate_todbm(struct ieee80211_hw *hw,
+ u8 signal_strength_index)
+{
+ long signal_power;
+
+ signal_power = (long)((signal_strength_index + 1) >> 1);
+ signal_power -= 95;
+ return signal_power;
+}
+
+long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
+{
+ long retsig;
+
+ if (currsig >= 61 && currsig <= 100)
+ retsig = 90 + ((currsig - 60) / 4);
+ else if (currsig >= 41 && currsig <= 60)
+ retsig = 78 + ((currsig - 40) / 2);
+ else if (currsig >= 31 && currsig <= 40)
+ retsig = 66 + (currsig - 30);
+ else if (currsig >= 21 && currsig <= 30)
+ retsig = 54 + (currsig - 20);
+ else if (currsig >= 5 && currsig <= 20)
+ retsig = 42 + (((currsig - 5) * 2) / 3);
+ else if (currsig == 4)
+ retsig = 36;
+ else if (currsig == 3)
+ retsig = 27;
+ else if (currsig == 2)
+ retsig = 18;
+ else if (currsig == 1)
+ retsig = 9;
+ else
+ retsig = currsig;
+
+ return retsig;
+}
+EXPORT_SYMBOL(rtl_signal_scale_mapping);
+
+static void rtl_process_ui_rssi(struct ieee80211_hw *hw,
+ struct rtl_stats *pstatus)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &(rtlpriv->phy);
+ u8 rfpath;
+ u32 last_rssi, tmpval;
+
+ rtlpriv->stats.rssi_calculate_cnt++;
+
+ if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX;
+ last_rssi = rtlpriv->stats.ui_rssi.elements[
+ rtlpriv->stats.ui_rssi.index];
+ rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+ }
+ rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength;
+ rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] =
+ pstatus->signalstrength;
+ if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+ rtlpriv->stats.ui_rssi.index = 0;
+ tmpval = rtlpriv->stats.ui_rssi.total_val /
+ rtlpriv->stats.ui_rssi.total_num;
+ rtlpriv->stats.signal_strength = rtl_translate_todbm(hw,
+ (u8) tmpval);
+ pstatus->rssi = rtlpriv->stats.signal_strength;
+
+ if (pstatus->is_cck)
+ return;
+
+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+ rfpath++) {
+ if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ pstatus->rx_mimo_signalstrength[rfpath];
+
+ }
+ if (pstatus->rx_mimo_signalstrength[rfpath] >
+ rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstatus->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
+ } else {
+ rtlpriv->stats.rx_rssi_percentage[rfpath] =
+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstatus->rx_mimo_signalstrength[rfpath])) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw,
+ struct rtl_stats *pstatus)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int weighting = 0;
+
+ if (rtlpriv->stats.recv_signal_power == 0)
+ rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower;
+ if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power)
+ weighting = 5;
+ else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power)
+ weighting = (-5);
+ rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
+ 5 + pstatus->recvsignalpower + weighting) / 6;
+}
+
+static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_sta_info *drv_priv = NULL;
+ struct ieee80211_sta *sta = NULL;
+ long undec_sm_pwdb;
+
+ rcu_read_lock();
+ if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+ sta = rtl_find_sta(hw, pstatus->psaddr);
+
+ /* adhoc or ap mode */
+ if (sta) {
+ drv_priv = (struct rtl_sta_info *) sta->drv_priv;
+ undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
+ } else {
+ undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
+ }
+
+ if (undec_sm_pwdb < 0)
+ undec_sm_pwdb = pstatus->rx_pwdb_all;
+ if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
+ undec_sm_pwdb = (((undec_sm_pwdb) *
+ (RX_SMOOTH_FACTOR - 1)) +
+ (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ undec_sm_pwdb = undec_sm_pwdb + 1;
+ } else {
+ undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) +
+ (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+ }
+
+ if (sta) {
+ drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
+ } else {
+ rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
+ }
+ rcu_read_unlock();
+
+ rtl_update_rxsignalstatistics(hw, pstatus);
+}
+
+static void rtl_process_ui_link_quality(struct ieee80211_hw *hw,
+ struct rtl_stats *pstatus)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 last_evm, n_stream, tmpval;
+
+ if (pstatus->signalquality == 0)
+ return;
+
+ if (rtlpriv->stats.ui_link_quality.total_num++ >=
+ PHY_LINKQUALITY_SLID_WIN_MAX) {
+ rtlpriv->stats.ui_link_quality.total_num =
+ PHY_LINKQUALITY_SLID_WIN_MAX;
+ last_evm = rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index];
+ rtlpriv->stats.ui_link_quality.total_val -= last_evm;
+ }
+ rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality;
+ rtlpriv->stats.ui_link_quality.elements[
+ rtlpriv->stats.ui_link_quality.index++] =
+ pstatus->signalquality;
+ if (rtlpriv->stats.ui_link_quality.index >=
+ PHY_LINKQUALITY_SLID_WIN_MAX)
+ rtlpriv->stats.ui_link_quality.index = 0;
+ tmpval = rtlpriv->stats.ui_link_quality.total_val /
+ rtlpriv->stats.ui_link_quality.total_num;
+ rtlpriv->stats.signal_quality = tmpval;
+ rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+ for (n_stream = 0; n_stream < 2; n_stream++) {
+ if (pstatus->rx_mimo_sig_qual[n_stream] != -1) {
+ if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) {
+ rtlpriv->stats.rx_evm_percentage[n_stream] =
+ pstatus->rx_mimo_sig_qual[n_stream];
+ }
+ rtlpriv->stats.rx_evm_percentage[n_stream] =
+ ((rtlpriv->stats.rx_evm_percentage[n_stream]
+ * (RX_SMOOTH_FACTOR - 1)) +
+ (pstatus->rx_mimo_sig_qual[n_stream] * 1)) /
+ (RX_SMOOTH_FACTOR);
+ }
+ }
+}
+
+void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
+ struct rtl_stats *pstatus)
+{
+
+ if (!pstatus->packet_matchbssid)
+ return;
+
+ rtl_process_ui_rssi(hw, pstatus);
+ rtl_process_pwdb(hw, pstatus);
+ rtl_process_ui_link_quality(hw, pstatus);
+}
+EXPORT_SYMBOL(rtl_process_phyinfo);
diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/rtlwifi/stats.h
new file mode 100644
index 000000000000..0dbdc5203830
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/stats.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * 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 LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL_STATS_H__
+#define __RTL_STATS_H__
+
+#define PHY_RSSI_SLID_WIN_MAX 100
+#define PHY_LINKQUALITY_SLID_WIN_MAX 20
+#define PHY_BEACON_RSSI_SLID_WIN_MAX 10
+
+/* Rx smooth factor */
+#define RX_SMOOTH_FACTOR 20
+
+u8 rtl_query_rxpwrpercentage(char antpower);
+u8 rtl_evm_db_to_percentage(char value);
+long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig);
+void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
+ struct rtl_stats *pstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index e3ea4b346889..29f0969e4ba0 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -940,7 +940,7 @@ static struct rtl_intf_ops rtl_usb_ops = {
.waitq_insert = rtl_usb_tx_chk_waitq_insert,
};
-int __devinit rtl_usb_probe(struct usb_interface *intf,
+int rtl_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int err;
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h
index 43846b329153..5235136f6dd2 100644
--- a/drivers/net/wireless/rtlwifi/usb.h
+++ b/drivers/net/wireless/rtlwifi/usb.h
@@ -156,7 +156,7 @@ struct rtl_usb_priv {
-int __devinit rtl_usb_probe(struct usb_interface *intf,
+int rtl_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id);
void rtl_usb_disconnect(struct usb_interface *intf);
int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index f1b6bc693b0a..21a5f4f4a135 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -198,15 +198,15 @@ struct bb_reg_def {
u32 rftxgain_stage;
u32 rfhssi_para1;
u32 rfhssi_para2;
- u32 rfswitch_control;
+ u32 rfsw_ctrl;
u32 rfagc_control1;
u32 rfagc_control2;
- u32 rfrxiq_imbalance;
+ u32 rfrxiq_imbal;
u32 rfrx_afe;
- u32 rftxiq_imbalance;
+ u32 rftxiq_imbal;
u32 rftx_afe;
- u32 rflssi_readback;
- u32 rflssi_readbackpi;
+ u32 rf_rb; /* rflssi_readback */
+ u32 rf_rbpi; /* rflssi_readbackpi */
};
enum io_type {
@@ -350,6 +350,11 @@ enum rt_oem_id {
RT_CID_819x_WNC_COREGA = 31,
RT_CID_819x_Foxcoon = 32,
RT_CID_819x_DELL = 33,
+ RT_CID_819x_PRONETS = 34,
+ RT_CID_819x_Edimax_ASUS = 35,
+ RT_CID_NETGEAR = 36,
+ RT_CID_PLANEX = 37,
+ RT_CID_CC_C = 38,
};
enum hw_descs {
@@ -505,6 +510,7 @@ enum rtl_var_map {
RTL_IMR_ROK, /*Receive DMA OK Interrupt */
RTL_IBSS_INT_MASKS, /*(RTL_IMR_BcnInt | RTL_IMR_TBDOK |
* RTL_IMR_TBDER) */
+ RTL_IMR_C2HCMD, /*fw interrupt*/
/*CCK Rates, TxHT = 0 */
RTL_RC_CCK_RATE1M,
@@ -661,6 +667,11 @@ enum ba_action {
ACT_DELBA = 2,
};
+enum rt_polarity_ctl {
+ RT_POLARITY_LOW_ACT = 0,
+ RT_POLARITY_HIGH_ACT = 1,
+};
+
struct octet_string {
u8 *octet;
u16 length;
@@ -885,7 +896,7 @@ struct rtl_phy {
u8 pwrgroup_cnt;
u8 cck_high_power;
/* MAX_PG_GROUP groups of pwr diff by rates */
- u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16];
+ u32 mcs_offset[MAX_PG_GROUP][16];
u8 default_initialgain[4];
/* the current Tx power level */
@@ -903,6 +914,8 @@ struct rtl_phy {
u8 num_total_rfpath;
struct phy_parameters hwparam_tables[MAX_TAB];
u16 rf_pathmap;
+
+ enum rt_polarity_ctl polarity_ctl;
};
#define MAX_TID_COUNT 9
@@ -933,7 +946,7 @@ struct rtl_tid_data {
};
struct rssi_sta {
- long undecorated_smoothed_pwdb;
+ long undec_sm_pwdb;
};
struct rtl_sta_info {
@@ -1042,13 +1055,64 @@ struct rtl_mac {
/*QOS & EDCA */
struct ieee80211_tx_queue_params edca_param[RTL_MAC80211_NUM_QUEUE];
struct rtl_qos_parameters ac[AC_MAX];
+
+ /* counters */
+ u64 last_txok_cnt;
+ u64 last_rxok_cnt;
+ u32 last_bt_edca_ul;
+ u32 last_bt_edca_dl;
+};
+
+struct btdm_8723 {
+ bool all_off;
+ bool agc_table_en;
+ bool adc_back_off_on;
+ bool b2_ant_hid_en;
+ bool low_penalty_rate_adaptive;
+ bool rf_rx_lpf_shrink;
+ bool reject_aggre_pkt;
+ bool tra_tdma_on;
+ u8 tra_tdma_nav;
+ u8 tra_tdma_ant;
+ bool tdma_on;
+ u8 tdma_ant;
+ u8 tdma_nav;
+ u8 tdma_dac_swing;
+ u8 fw_dac_swing_lvl;
+ bool ps_tdma_on;
+ u8 ps_tdma_byte[5];
+ bool pta_on;
+ u32 val_0x6c0;
+ u32 val_0x6c8;
+ u32 val_0x6cc;
+ bool sw_dac_swing_on;
+ u32 sw_dac_swing_lvl;
+ u32 wlan_act_hi;
+ u32 wlan_act_lo;
+ u32 bt_retry_index;
+ bool dec_bt_pwr;
+ bool ignore_wlan_act;
+};
+
+struct bt_coexist_8723 {
+ u32 high_priority_tx;
+ u32 high_priority_rx;
+ u32 low_priority_tx;
+ u32 low_priority_rx;
+ u8 c2h_bt_info;
+ bool c2h_bt_info_req_sent;
+ bool c2h_bt_inquiry_page;
+ u32 bt_inq_page_start_time;
+ u8 bt_retry_cnt;
+ u8 c2h_bt_info_original;
+ u8 bt_inquiry_page_cnt;
+ struct btdm_8723 btdm;
};
struct rtl_hal {
struct ieee80211_hw *hw;
-
+ struct bt_coexist_8723 hal_coex_8723;
bool up_first_time;
- bool first_init;
bool being_init_adapter;
bool bbrf_ready;
@@ -1131,9 +1195,9 @@ struct rtl_security {
struct rtl_dm {
/*PHY status for Dynamic Management */
- long entry_min_undecoratedsmoothed_pwdb;
- long undecorated_smoothed_pwdb; /*out dm */
- long entry_max_undecoratedsmoothed_pwdb;
+ long entry_min_undec_sm_pwdb;
+ long undec_sm_pwdb; /*out dm */
+ long entry_max_undec_sm_pwdb;
bool dm_initialgain_enable;
bool dynamic_txpower_enable;
bool current_turbo_edca;
@@ -1209,7 +1273,7 @@ struct rtl_efuse {
u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX];
u8 eeprom_chnlarea_txpwr_cck[2][CHANNEL_GROUP_MAX_2G];
u8 eeprom_chnlarea_txpwr_ht40_1s[2][CHANNEL_GROUP_MAX];
- u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][CHANNEL_GROUP_MAX];
+ u8 eprom_chnl_txpwr_ht40_2sdf[2][CHANNEL_GROUP_MAX];
u8 txpwrlevel_cck[2][CHANNEL_MAX_NUMBER_2G];
u8 txpwrlevel_ht40_1s[2][CHANNEL_MAX_NUMBER]; /*For HT 40MHZ pwr */
u8 txpwrlevel_ht40_2s[2][CHANNEL_MAX_NUMBER]; /*For HT 40MHZ pwr */
@@ -1312,6 +1376,7 @@ struct rtl_ps_ctl {
};
struct rtl_stats {
+ u8 psaddr[ETH_ALEN];
u32 mac_time[2];
s8 rssi;
u8 signal;
@@ -1351,7 +1416,7 @@ struct rtl_stats {
bool rx_is40Mhzpacket;
u32 rx_pwdb_all;
u8 rx_mimo_signalstrength[4]; /*in 0~100 index */
- s8 rx_mimo_signalquality[2];
+ s8 rx_mimo_sig_qual[2];
bool packet_matchbssid;
bool is_cck;
bool is_ht;
@@ -1503,6 +1568,10 @@ struct rtl_hal_ops {
void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t);
void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw);
void (*dm_dynamic_txpower) (struct ieee80211_hw *hw);
+ void (*c2h_command_handle) (struct ieee80211_hw *hw);
+ void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw,
+ bool mstate);
+ void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw);
};
struct rtl_intf_ops {
@@ -1679,7 +1748,7 @@ struct dig_t {
u32 rssi_highthresh;
u32 fa_lowthresh;
u32 fa_highthresh;
- long last_min_undecorated_pwdb_for_dm;
+ long last_min_undec_pwdb_for_dm;
long rssi_highpower_lowthresh;
long rssi_highpower_highthresh;
u32 recover_cnt;
@@ -1692,15 +1761,15 @@ struct dig_t {
u8 dig_twoport_algorithm;
u8 dig_dbgmode;
u8 dig_slgorithm_switch;
- u8 cursta_connectstate;
- u8 presta_connectstate;
- u8 curmultista_connectstate;
- char backoff_val;
- char backoff_val_range_max;
- char backoff_val_range_min;
+ u8 cursta_cstate;
+ u8 presta_cstate;
+ u8 curmultista_cstate;
+ char back_val;
+ char back_range_max;
+ char back_range_min;
u8 rx_gain_range_max;
u8 rx_gain_range_min;
- u8 min_undecorated_pwdb_for_dm;
+ u8 min_undec_pwdb_for_dm;
u8 rssi_val_min;
u8 pre_cck_pd_state;
u8 cur_cck_pd_state;
@@ -1712,10 +1781,10 @@ struct dig_t {
u8 forbidden_igi;
u8 dig_state;
u8 dig_highpwrstate;
- u8 cur_sta_connectstate;
- u8 pre_sta_connectstate;
- u8 cur_ap_connectstate;
- u8 pre_ap_connectstate;
+ u8 cur_sta_cstate;
+ u8 pre_sta_cstate;
+ u8 cur_ap_cstate;
+ u8 pre_ap_cstate;
u8 cur_pd_thstate;
u8 pre_pd_thstate;
u8 cur_cs_ratiostate;
@@ -1781,9 +1850,22 @@ struct rtl_priv {
struct dig_t dm_digtable;
struct ps_t dm_pstable;
- /* data buffer pointer for USB reads */
- __le32 *usb_data;
- int usb_data_index;
+ /* 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;
+ };
+ };
/*This must be the last item so
that it points to the data allocated
@@ -1815,6 +1897,7 @@ enum bt_co_type {
BT_CSR_BC4 = 3,
BT_CSR_BC8 = 4,
BT_RTL8756 = 5,
+ BT_RTL8723A = 6,
};
enum bt_cur_state {
@@ -1846,7 +1929,7 @@ struct bt_coexist_info {
u8 eeprom_bt_coexist;
u8 eeprom_bt_type;
u8 eeprom_bt_ant_num;
- u8 eeprom_bt_ant_isolation;
+ u8 eeprom_bt_ant_isol;
u8 eeprom_bt_radio_shared;
u8 bt_coexistence;
@@ -1873,13 +1956,27 @@ struct bt_coexist_info {
bool fw_coexist_all_off;
bool sw_coexist_all_off;
- u32 current_state;
+ bool hw_coexist_all_off;
+ u32 cstate;
u32 previous_state;
+ u32 cstate_h;
+ u32 previous_state_h;
+
u8 bt_pre_rssi_state;
+ u8 bt_pre_rssi_state1;
u8 reg_bt_iso;
u8 reg_bt_sco;
-
+ bool balance_on;
+ u8 bt_active_zero_cnt;
+ bool cur_bt_disabled;
+ bool pre_bt_disabled;
+
+ u8 bt_profile_case;
+ u8 bt_profile_action;
+ bool bt_busy;
+ bool hold_for_bt_operation;
+ u8 lps_counter;
};
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 441cbccbd381..f47e8b0482ad 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -896,11 +896,13 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
goto out;
skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
- req->ie, req->ie_len);
+ req->ie_len);
if (!skb) {
ret = -ENOMEM;
goto out;
}
+ if (req->ie_len)
+ memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
skb->len);
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c
index 6af35265c900..23289d49dd31 100644
--- a/drivers/net/wireless/ti/wl1251/rx.c
+++ b/drivers/net/wireless/ti/wl1251/rx.c
@@ -81,7 +81,7 @@ static void wl1251_rx_status(struct wl1251 *wl,
status->freq = ieee80211_channel_to_frequency(desc->channel,
status->band);
- status->flag |= RX_FLAG_MACTIME_MPDU;
+ status->flag |= RX_FLAG_MACTIME_START;
if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
index e2750a12c6f1..e57ee48edff6 100644
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -305,7 +305,7 @@ out_free_hw:
return ret;
}
-static void __devexit wl1251_sdio_remove(struct sdio_func *func)
+static void wl1251_sdio_remove(struct sdio_func *func)
{
struct wl1251 *wl = sdio_get_drvdata(func);
struct wl1251_sdio *wl_sdio = wl->if_priv;
@@ -347,7 +347,7 @@ static struct sdio_driver wl1251_sdio_driver = {
.name = "wl1251_sdio",
.id_table = wl1251_devices,
.probe = wl1251_sdio_probe,
- .remove = __devexit_p(wl1251_sdio_remove),
+ .remove = wl1251_sdio_remove,
.drv.pm = &wl1251_sdio_pm_ops,
};
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index 567660cd2fcd..3b266d3231a3 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -237,7 +237,7 @@ static const struct wl1251_if_operations wl1251_spi_ops = {
.power = wl1251_spi_set_power,
};
-static int __devinit wl1251_spi_probe(struct spi_device *spi)
+static int wl1251_spi_probe(struct spi_device *spi)
{
struct wl12xx_platform_data *pdata;
struct ieee80211_hw *hw;
@@ -309,7 +309,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wl1251_spi_remove(struct spi_device *spi)
+static int wl1251_spi_remove(struct spi_device *spi)
{
struct wl1251 *wl = dev_get_drvdata(&spi->dev);
@@ -326,7 +326,7 @@ static struct spi_driver wl1251_spi_driver = {
},
.probe = wl1251_spi_probe,
- .remove = __devexit_p(wl1251_spi_remove),
+ .remove = wl1251_spi_remove,
};
static int __init wl1251_spi_init(void)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index dadf1dbb002a..e5f5f8f39144 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1696,7 +1696,7 @@ static int wl12xx_setup(struct wl1271 *wl)
return 0;
}
-static int __devinit wl12xx_probe(struct platform_device *pdev)
+static int wl12xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
struct ieee80211_hw *hw;
@@ -1725,7 +1725,7 @@ out:
return ret;
}
-static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
+static const struct platform_device_id wl12xx_id_table[] = {
{ "wl12xx", 0 },
{ } /* Terminating Entry */
};
@@ -1733,7 +1733,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
static struct platform_driver wl12xx_driver = {
.probe = wl12xx_probe,
- .remove = __devexit_p(wlcore_remove),
+ .remove = wlcore_remove,
.id_table = wl12xx_id_table,
.driver = {
.name = "wl12xx_driver",
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index a39682a7c25f..8d8c1f8c63b7 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1499,7 +1499,7 @@ static int wl18xx_setup(struct wl1271 *wl)
return 0;
}
-static int __devinit wl18xx_probe(struct platform_device *pdev)
+static int wl18xx_probe(struct platform_device *pdev)
{
struct wl1271 *wl;
struct ieee80211_hw *hw;
@@ -1528,7 +1528,7 @@ out:
return ret;
}
-static const struct platform_device_id wl18xx_id_table[] __devinitconst = {
+static const struct platform_device_id wl18xx_id_table[] = {
{ "wl18xx", 0 },
{ } /* Terminating Entry */
};
@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(platform, wl18xx_id_table);
static struct platform_driver wl18xx_driver = {
.probe = wl18xx_probe,
- .remove = __devexit_p(wlcore_remove),
+ .remove = wlcore_remove,
.id_table = wl18xx_id_table,
.driver = {
.name = "wl18xx_driver",
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index eaef3f41b252..27f83f72a93b 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1038,11 +1038,13 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
- ie, ie_len);
+ ie_len);
if (!skb) {
ret = -ENOMEM;
goto out;
}
+ if (ie_len)
+ memcpy(skb_put(skb, ie_len), ie, ie_len);
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 25530c8760cb..ea9d8e011bc9 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -677,7 +677,7 @@ static void wl12xx_get_vif_count(struct ieee80211_hw *hw,
memset(data, 0, sizeof(*data));
data->cur_vif = cur_vif;
- ieee80211_iterate_active_interfaces(hw,
+ ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
wl12xx_vif_count_iter, data);
}
@@ -3791,7 +3791,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
/* Handle HT information change */
if ((changed & BSS_CHANGED_HT) &&
- (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_information(wl, wlvif,
bss_conf->ht_operation_mode);
if (ret < 0) {
@@ -3905,7 +3905,8 @@ sta_not_found:
u32 rates;
int ieoffset;
wlvif->aid = bss_conf->aid;
- wlvif->channel_type = bss_conf->channel_type;
+ wlvif->channel_type =
+ cfg80211_get_chandef_type(&bss_conf->chandef);
wlvif->beacon_int = bss_conf->beacon_int;
do_join = true;
set_assoc = true;
@@ -4071,7 +4072,7 @@ sta_not_found:
/* Handle new association with HT. Do this after join. */
if (sta_exists) {
if ((changed & BSS_CHANGED_HT) &&
- (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_capabilities(wl,
&sta_ht_cap,
true,
@@ -4098,7 +4099,7 @@ sta_not_found:
/* Handle HT information change. Done after join. */
if ((changed & BSS_CHANGED_HT) &&
- (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_information(wl, wlvif,
bss_conf->ht_operation_mode);
if (ret < 0) {
@@ -5659,7 +5660,7 @@ out:
complete_all(&wl->nvs_loading_complete);
}
-int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
+int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
{
int ret;
@@ -5682,7 +5683,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(wlcore_probe);
-int __devexit wlcore_remove(struct platform_device *pdev)
+int wlcore_remove(struct platform_device *pdev)
{
struct wl1271 *wl = platform_get_drvdata(pdev);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 73ace4b2604e..646f703ae739 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -54,7 +54,7 @@ struct wl12xx_sdio_glue {
struct platform_device *core;
};
-static const struct sdio_device_id wl1271_devices[] __devinitconst = {
+static const struct sdio_device_id wl1271_devices[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
{}
};
@@ -214,7 +214,7 @@ static struct wl1271_if_operations sdio_ops = {
.set_block_size = wl1271_sdio_set_block_size,
};
-static int __devinit wl1271_probe(struct sdio_func *func,
+static int wl1271_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct wl12xx_platform_data *wlan_data;
@@ -319,7 +319,7 @@ out:
return ret;
}
-static void __devexit wl1271_remove(struct sdio_func *func)
+static void wl1271_remove(struct sdio_func *func)
{
struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
@@ -384,7 +384,7 @@ static struct sdio_driver wl1271_sdio_driver = {
.name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
- .remove = __devexit_p(wl1271_remove),
+ .remove = wl1271_remove,
#ifdef CONFIG_PM
.drv = {
.pm = &wl1271_sdio_pm_ops,
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index a519bc3adec1..f06f4770ce02 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -324,7 +324,7 @@ static struct wl1271_if_operations spi_ops = {
.set_block_size = NULL,
};
-static int __devinit wl1271_probe(struct spi_device *spi)
+static int wl1271_probe(struct spi_device *spi)
{
struct wl12xx_spi_glue *glue;
struct wl12xx_platform_data *pdata;
@@ -403,7 +403,7 @@ out:
return ret;
}
-static int __devexit wl1271_remove(struct spi_device *spi)
+static int wl1271_remove(struct spi_device *spi)
{
struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
@@ -422,7 +422,7 @@ static struct spi_driver wl1271_spi_driver = {
},
.probe = wl1271_probe,
- .remove = __devexit_p(wl1271_remove),
+ .remove = wl1271_remove,
};
static int __init wl1271_init(void)
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 68584aa0f2b0..c3884937c007 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -414,8 +414,8 @@ struct wl1271 {
struct completion nvs_loading_complete;
};
-int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
-int __devexit wlcore_remove(struct platform_device *pdev);
+int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
+int wlcore_remove(struct platform_device *pdev);
struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size);
int wlcore_free_hw(struct wl1271 *wl);
int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index ff306d763e37..71ab320fae82 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1155,7 +1155,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
if (r)
goto out;
/* Currently we support IEEE 802.11g for full and high speed USB.
- * It might be discussed, whether we should suppport pure b mode for
+ * It might be discussed, whether we should support pure b mode for
* full speed USB.
*/
r = set_mandatory_rates(chip, 1);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index fc24eb9b3948..c26e28b4bd9f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1311,7 +1311,7 @@ static const struct net_device_ops xennet_netdev_ops = {
#endif
};
-static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
+static struct net_device *xennet_create_dev(struct xenbus_device *dev)
{
int i, err;
struct net_device *netdev;
@@ -1407,8 +1407,8 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
* structures and the ring buffers for communication with the backend, and
* inform the backend of the appropriate details for those.
*/
-static int __devinit netfront_probe(struct xenbus_device *dev,
- const struct xenbus_device_id *id)
+static int netfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
{
int err;
struct net_device *netdev;
@@ -1967,7 +1967,7 @@ static const struct xenbus_device_id netfront_ids[] = {
};
-static int __devexit xennet_remove(struct xenbus_device *dev)
+static int xennet_remove(struct xenbus_device *dev)
{
struct netfront_info *info = dev_get_drvdata(&dev->dev);
@@ -1990,7 +1990,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
static DEFINE_XENBUS_DRIVER(netfront, ,
.probe = netfront_probe,
- .remove = __devexit_p(xennet_remove),
+ .remove = xennet_remove,
.resume = netfront_resume,
.otherend_changed = netback_changed,
);
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index bf05831fdf09..36c359043f54 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -2,7 +2,7 @@
# Makefile for nfc devices
#
-obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o
+obj-$(CONFIG_PN544_HCI_NFC) += pn544/
obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 30ae18a03a9c..ada681b01a17 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -84,6 +84,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_LISTEN_TIME 2
/* frame definitions */
+#define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI)
+ 254 (DATA)
+ 2 (DCS, postamble) */
+
#define PN533_FRAME_TAIL_SIZE 2
#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
PN533_FRAME_TAIL_SIZE)
@@ -1166,8 +1170,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev,
pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
}
-static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
- u8 *params, int params_len)
+static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len)
{
struct pn533_poll_response *resp;
int rc;
@@ -1305,8 +1308,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work)
}
#define ATR_REQ_GB_OFFSET 17
-static int pn533_init_target_complete(struct pn533 *dev, void *arg,
- u8 *params, int params_len)
+static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len)
{
struct pn533_cmd_init_target_response *resp;
u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
@@ -1403,9 +1405,9 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg,
if (cur_mod->len == 0) {
del_timer(&dev->listen_timer);
- return pn533_init_target_complete(dev, arg, params, params_len);
+ return pn533_init_target_complete(dev, params, params_len);
} else {
- rc = pn533_start_poll_complete(dev, arg, params, params_len);
+ rc = pn533_start_poll_complete(dev, params, params_len);
if (!rc)
return rc;
}
@@ -2376,9 +2378,9 @@ static int pn533_probe(struct usb_interface *interface,
goto error;
}
- dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL);
+ dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL);
dev->in_urb = usb_alloc_urb(0, GFP_KERNEL);
- dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL);
+ dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL);
dev->out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->in_frame || !dev->out_frame ||
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile
new file mode 100644
index 000000000000..725733881eb3
--- /dev/null
+++ b/drivers/nfc/pn544/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for PN544 HCI based NFC driver
+#
+
+obj-$(CONFIG_PN544_HCI_NFC) += pn544_i2c.o
+
+pn544_i2c-y := pn544.o i2c.o
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
new file mode 100644
index 000000000000..7da9071b68b6
--- /dev/null
+++ b/drivers/nfc/pn544/i2c.c
@@ -0,0 +1,500 @@
+/*
+ * I2C Link Layer for PN544 HCI based Driver
+ *
+ * Copyright (C) 2012 Intel 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/crc-ccitt.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/platform_data/pn544.h>
+
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "pn544.h"
+
+#define PN544_I2C_FRAME_HEADROOM 1
+#define PN544_I2C_FRAME_TAILROOM 2
+
+/* framing in HCI mode */
+#define PN544_HCI_I2C_LLC_LEN 1
+#define PN544_HCI_I2C_LLC_CRC 2
+#define PN544_HCI_I2C_LLC_LEN_CRC (PN544_HCI_I2C_LLC_LEN + \
+ PN544_HCI_I2C_LLC_CRC)
+#define PN544_HCI_I2C_LLC_MIN_SIZE (1 + PN544_HCI_I2C_LLC_LEN_CRC)
+#define PN544_HCI_I2C_LLC_MAX_PAYLOAD 29
+#define PN544_HCI_I2C_LLC_MAX_SIZE (PN544_HCI_I2C_LLC_LEN_CRC + 1 + \
+ PN544_HCI_I2C_LLC_MAX_PAYLOAD)
+
+static struct i2c_device_id pn544_hci_i2c_id_table[] = {
+ {"pn544", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table);
+
+#define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c"
+
+struct pn544_i2c_phy {
+ struct i2c_client *i2c_dev;
+ struct nfc_hci_dev *hdev;
+
+ unsigned int gpio_en;
+ unsigned int gpio_irq;
+ unsigned int gpio_fw;
+ unsigned int en_polarity;
+
+ int powered;
+
+ int hard_fault; /*
+ * < 0 if hardware error occured (e.g. i2c err)
+ * and prevents normal operation.
+ */
+};
+
+#define I2C_DUMP_SKB(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, 0); \
+} while (0)
+
+static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
+{
+ int polarity, retry, ret;
+ char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 };
+ int count = sizeof(rset_cmd);
+
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+ dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n");
+
+ /* Disable fw download */
+ gpio_set_value(phy->gpio_fw, 0);
+
+ for (polarity = 0; polarity < 2; polarity++) {
+ phy->en_polarity = polarity;
+ retry = 3;
+ while (retry--) {
+ /* power off */
+ gpio_set_value(phy->gpio_en, !phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ /* power on */
+ gpio_set_value(phy->gpio_en, phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ /* send reset */
+ dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n");
+ ret = i2c_master_send(phy->i2c_dev, rset_cmd, count);
+ if (ret == count) {
+ dev_info(&phy->i2c_dev->dev,
+ "nfc_en polarity : active %s\n",
+ (polarity == 0 ? "low" : "high"));
+ goto out;
+ }
+ }
+ }
+
+ dev_err(&phy->i2c_dev->dev,
+ "Could not detect nfc_en polarity, fallback to active high\n");
+
+out:
+ gpio_set_value(phy->gpio_en, !phy->en_polarity);
+}
+
+static int pn544_hci_i2c_enable(void *phy_id)
+{
+ struct pn544_i2c_phy *phy = phy_id;
+
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+
+ gpio_set_value(phy->gpio_fw, 0);
+ gpio_set_value(phy->gpio_en, phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ phy->powered = 1;
+
+ return 0;
+}
+
+static void pn544_hci_i2c_disable(void *phy_id)
+{
+ struct pn544_i2c_phy *phy = phy_id;
+
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+
+ gpio_set_value(phy->gpio_fw, 0);
+ gpio_set_value(phy->gpio_en, !phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ gpio_set_value(phy->gpio_en, phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ gpio_set_value(phy->gpio_en, !phy->en_polarity);
+ usleep_range(10000, 15000);
+
+ phy->powered = 0;
+}
+
+static void pn544_hci_i2c_add_len_crc(struct sk_buff *skb)
+{
+ u16 crc;
+ int len;
+
+ len = skb->len + 2;
+ *skb_push(skb, 1) = len;
+
+ crc = crc_ccitt(0xffff, skb->data, skb->len);
+ crc = ~crc;
+ *skb_put(skb, 1) = crc & 0xff;
+ *skb_put(skb, 1) = crc >> 8;
+}
+
+static void pn544_hci_i2c_remove_len_crc(struct sk_buff *skb)
+{
+ skb_pull(skb, PN544_I2C_FRAME_HEADROOM);
+ skb_trim(skb, PN544_I2C_FRAME_TAILROOM);
+}
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int pn544_hci_i2c_write(void *phy_id, struct sk_buff *skb)
+{
+ int r;
+ struct pn544_i2c_phy *phy = phy_id;
+ struct i2c_client *client = phy->i2c_dev;
+
+ if (phy->hard_fault != 0)
+ return phy->hard_fault;
+
+ usleep_range(3000, 6000);
+
+ pn544_hci_i2c_add_len_crc(skb);
+
+ I2C_DUMP_SKB("i2c frame written", skb);
+
+ r = i2c_master_send(client, skb->data, skb->len);
+
+ if (r == -EREMOTEIO) { /* Retry, chip was in standby */
+ usleep_range(6000, 10000);
+ r = i2c_master_send(client, skb->data, skb->len);
+ }
+
+ if (r >= 0) {
+ if (r != skb->len)
+ r = -EREMOTEIO;
+ else
+ r = 0;
+ }
+
+ pn544_hci_i2c_remove_len_crc(skb);
+
+ return r;
+}
+
+static int check_crc(u8 *buf, int buflen)
+{
+ int len;
+ u16 crc;
+
+ len = buf[0] + 1;
+ crc = crc_ccitt(0xffff, buf, len - 2);
+ crc = ~crc;
+
+ if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) {
+ pr_err(PN544_HCI_I2C_DRIVER_NAME
+ ": CRC error 0x%x != 0x%x 0x%x\n",
+ crc, buf[len - 1], buf[len - 2]);
+
+ pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
+ print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
+ 16, 2, buf, buflen, false);
+ return -EPERM;
+ }
+ return 0;
+}
+
+/*
+ * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
+ * that i2c bus will be flushed and that next read will start on a new frame.
+ * returned skb contains only LLC header and payload.
+ * returns:
+ * -EREMOTEIO : i2c read error (fatal)
+ * -EBADMSG : frame was incorrect and discarded
+ * -ENOMEM : cannot allocate skb, frame dropped
+ */
+static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb)
+{
+ int r;
+ u8 len;
+ u8 tmp[PN544_HCI_I2C_LLC_MAX_SIZE - 1];
+ struct i2c_client *client = phy->i2c_dev;
+
+ r = i2c_master_recv(client, &len, 1);
+ if (r != 1) {
+ dev_err(&client->dev, "cannot read len byte\n");
+ return -EREMOTEIO;
+ }
+
+ if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) ||
+ (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) {
+ dev_err(&client->dev, "invalid len byte\n");
+ r = -EBADMSG;
+ goto flush;
+ }
+
+ *skb = alloc_skb(1 + len, GFP_KERNEL);
+ if (*skb == NULL) {
+ r = -ENOMEM;
+ goto flush;
+ }
+
+ *skb_put(*skb, 1) = len;
+
+ r = i2c_master_recv(client, skb_put(*skb, len), len);
+ if (r != len) {
+ kfree_skb(*skb);
+ return -EREMOTEIO;
+ }
+
+ I2C_DUMP_SKB("i2c frame read", *skb);
+
+ r = check_crc((*skb)->data, (*skb)->len);
+ if (r != 0) {
+ kfree_skb(*skb);
+ r = -EBADMSG;
+ goto flush;
+ }
+
+ skb_pull(*skb, 1);
+ skb_trim(*skb, (*skb)->len - 2);
+
+ usleep_range(3000, 6000);
+
+ return 0;
+
+flush:
+ if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
+ r = -EREMOTEIO;
+
+ usleep_range(3000, 6000);
+
+ return r;
+}
+
+/*
+ * Reads an shdlc frame from the chip. This is not as straightforward as it
+ * seems. There are cases where we could loose the frame start synchronization.
+ * The frame format is len-data-crc, and corruption can occur anywhere while
+ * transiting on i2c bus, such that we could read an invalid len.
+ * In order to recover synchronization with the next frame, we must be sure
+ * to read the real amount of data without using the len byte. We do this by
+ * assuming the following:
+ * - the chip will always present only one single complete frame on the bus
+ * before triggering the interrupt
+ * - the chip will not present a new frame until we have completely read
+ * the previous one (or until we have handled the interrupt).
+ * The tricky case is when we read a corrupted len that is less than the real
+ * len. We must detect this here in order to determine that we need to flush
+ * the bus. This is the reason why we check the crc here.
+ */
+static irqreturn_t pn544_hci_i2c_irq_thread_fn(int irq, void *phy_id)
+{
+ struct pn544_i2c_phy *phy = phy_id;
+ struct i2c_client *client;
+ struct sk_buff *skb = NULL;
+ int r;
+
+ if (!phy || irq != phy->i2c_dev->irq) {
+ WARN_ON_ONCE(1);
+ return IRQ_NONE;
+ }
+
+ client = phy->i2c_dev;
+ dev_dbg(&client->dev, "IRQ\n");
+
+ if (phy->hard_fault != 0)
+ return IRQ_HANDLED;
+
+ r = pn544_hci_i2c_read(phy, &skb);
+ if (r == -EREMOTEIO) {
+ phy->hard_fault = r;
+
+ nfc_hci_recv_frame(phy->hdev, NULL);
+
+ return IRQ_HANDLED;
+ } else if ((r == -ENOMEM) || (r == -EBADMSG)) {
+ return IRQ_HANDLED;
+ }
+
+ nfc_hci_recv_frame(phy->hdev, skb);
+
+ return IRQ_HANDLED;
+}
+
+static struct nfc_phy_ops i2c_phy_ops = {
+ .write = pn544_hci_i2c_write,
+ .enable = pn544_hci_i2c_enable,
+ .disable = pn544_hci_i2c_disable,
+};
+
+static int __devinit pn544_hci_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pn544_i2c_phy *phy;
+ struct pn544_nfc_platform_data *pdata;
+ int r = 0;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "Need I2C_FUNC_I2C\n");
+ return -ENODEV;
+ }
+
+ phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL);
+ if (!phy) {
+ dev_err(&client->dev,
+ "Cannot allocate memory for pn544 i2c phy.\n");
+ r = -ENOMEM;
+ goto err_phy_alloc;
+ }
+
+ phy->i2c_dev = client;
+ i2c_set_clientdata(client, phy);
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&client->dev, "No platform data\n");
+ r = -EINVAL;
+ goto err_pdata;
+ }
+
+ if (pdata->request_resources == NULL) {
+ dev_err(&client->dev, "request_resources() missing\n");
+ r = -EINVAL;
+ goto err_pdata;
+ }
+
+ r = pdata->request_resources(client);
+ if (r) {
+ dev_err(&client->dev, "Cannot get platform resources\n");
+ goto err_pdata;
+ }
+
+ phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
+ phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
+ phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
+
+ pn544_hci_i2c_platform_init(phy);
+
+ r = request_threaded_irq(client->irq, NULL, pn544_hci_i2c_irq_thread_fn,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ PN544_HCI_I2C_DRIVER_NAME, phy);
+ if (r < 0) {
+ dev_err(&client->dev, "Unable to register IRQ handler\n");
+ goto err_rti;
+ }
+
+ r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
+ PN544_I2C_FRAME_HEADROOM, PN544_I2C_FRAME_TAILROOM,
+ PN544_HCI_I2C_LLC_MAX_PAYLOAD, &phy->hdev);
+ if (r < 0)
+ goto err_hci;
+
+ return 0;
+
+err_hci:
+ free_irq(client->irq, phy);
+
+err_rti:
+ if (pdata->free_resources != NULL)
+ pdata->free_resources();
+
+err_pdata:
+ kfree(phy);
+
+err_phy_alloc:
+ return r;
+}
+
+static __devexit int pn544_hci_i2c_remove(struct i2c_client *client)
+{
+ struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
+ struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ pn544_hci_remove(phy->hdev);
+
+ if (phy->powered)
+ pn544_hci_i2c_disable(phy);
+
+ free_irq(client->irq, phy);
+ if (pdata->free_resources)
+ pdata->free_resources();
+
+ kfree(phy);
+
+ return 0;
+}
+
+static struct i2c_driver pn544_hci_i2c_driver = {
+ .driver = {
+ .name = PN544_HCI_I2C_DRIVER_NAME,
+ },
+ .probe = pn544_hci_i2c_probe,
+ .id_table = pn544_hci_i2c_id_table,
+ .remove = __devexit_p(pn544_hci_i2c_remove),
+};
+
+static int __init pn544_hci_i2c_init(void)
+{
+ int r;
+
+ pr_debug(DRIVER_DESC ": %s\n", __func__);
+
+ r = i2c_add_driver(&pn544_hci_i2c_driver);
+ if (r) {
+ pr_err(PN544_HCI_I2C_DRIVER_NAME
+ ": driver registration failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static void __exit pn544_hci_i2c_exit(void)
+{
+ i2c_del_driver(&pn544_hci_i2c_driver);
+}
+
+module_init(pn544_hci_i2c_init);
+module_exit(pn544_hci_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544/pn544.c
index c9c8570273ab..cc666de3b8e5 100644
--- a/drivers/nfc/pn544_hci.c
+++ b/drivers/nfc/pn544/pn544.c
@@ -18,47 +18,21 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <linux/crc-ccitt.h>
-#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/miscdevice.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
#include <linux/nfc.h>
#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
-#include <linux/nfc/pn544.h>
-
-#define DRIVER_DESC "HCI NFC driver for PN544"
-
-#define PN544_HCI_DRIVER_NAME "pn544_hci"
+#include "pn544.h"
/* Timing restrictions (ms) */
#define PN544_HCI_RESETVEN_TIME 30
-static struct i2c_device_id pn544_hci_id_table[] = {
- {"pn544", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, pn544_hci_id_table);
-
#define HCI_MODE 0
#define FW_MODE 1
-/* framing in HCI mode */
-#define PN544_HCI_LLC_LEN 1
-#define PN544_HCI_LLC_CRC 2
-#define PN544_HCI_LLC_LEN_CRC (PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC)
-#define PN544_HCI_LLC_MIN_SIZE (1 + PN544_HCI_LLC_LEN_CRC)
-#define PN544_HCI_LLC_MAX_PAYLOAD 29
-#define PN544_HCI_LLC_MAX_SIZE (PN544_HCI_LLC_LEN_CRC + 1 + \
- PN544_HCI_LLC_MAX_PAYLOAD)
-
enum pn544_state {
PN544_ST_COLD,
PN544_ST_FW_READY,
@@ -100,6 +74,10 @@ enum pn544_state {
#define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02
#define PN544_POLLING_LOOP_MGMT_GATE 0x94
+#define PN544_DEP_MODE 0x01
+#define PN544_DEP_ATR_REQ 0x02
+#define PN544_DEP_ATR_RES 0x03
+#define PN544_DEP_MERGE 0x0D
#define PN544_PL_RDPHASES 0x06
#define PN544_PL_EMULATION 0x07
#define PN544_PL_NFCT_DEACTIVATED 0x09
@@ -108,6 +86,15 @@ enum pn544_state {
#define PN544_NFC_WI_MGMT_GATE 0xA1
+#define PN544_HCI_EVT_SND_DATA 0x01
+#define PN544_HCI_EVT_ACTIVATED 0x02
+#define PN544_HCI_EVT_DEACTIVATED 0x03
+#define PN544_HCI_EVT_RCV_DATA 0x04
+#define PN544_HCI_EVT_CONTINUE_MI 0x05
+
+#define PN544_HCI_CMD_ATTREQUEST 0x12
+#define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13
+
static struct nfc_hci_gate pn544_gates[] = {
{NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE},
{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
@@ -128,259 +115,22 @@ static struct nfc_hci_gate pn544_gates[] = {
/* Largest headroom needed for outgoing custom commands */
#define PN544_CMDS_HEADROOM 2
-#define PN544_FRAME_HEADROOM 1
-#define PN544_FRAME_TAILROOM 2
struct pn544_hci_info {
- struct i2c_client *i2c_dev;
+ struct nfc_phy_ops *phy_ops;
+ void *phy_id;
+
struct nfc_hci_dev *hdev;
enum pn544_state state;
struct mutex info_lock;
- unsigned int gpio_en;
- unsigned int gpio_irq;
- unsigned int gpio_fw;
- unsigned int en_polarity;
-
- int hard_fault; /*
- * < 0 if hardware error occured (e.g. i2c err)
- * and prevents normal operation.
- */
int async_cb_type;
data_exchange_cb_t async_cb;
void *async_cb_context;
};
-static void pn544_hci_platform_init(struct pn544_hci_info *info)
-{
- int polarity, retry, ret;
- char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 };
- int count = sizeof(rset_cmd);
-
- pr_info(DRIVER_DESC ": %s\n", __func__);
- dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n");
-
- /* Disable fw download */
- gpio_set_value(info->gpio_fw, 0);
-
- for (polarity = 0; polarity < 2; polarity++) {
- info->en_polarity = polarity;
- retry = 3;
- while (retry--) {
- /* power off */
- gpio_set_value(info->gpio_en, !info->en_polarity);
- usleep_range(10000, 15000);
-
- /* power on */
- gpio_set_value(info->gpio_en, info->en_polarity);
- usleep_range(10000, 15000);
-
- /* send reset */
- dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n");
- ret = i2c_master_send(info->i2c_dev, rset_cmd, count);
- if (ret == count) {
- dev_info(&info->i2c_dev->dev,
- "nfc_en polarity : active %s\n",
- (polarity == 0 ? "low" : "high"));
- goto out;
- }
- }
- }
-
- dev_err(&info->i2c_dev->dev,
- "Could not detect nfc_en polarity, fallback to active high\n");
-
-out:
- gpio_set_value(info->gpio_en, !info->en_polarity);
-}
-
-static int pn544_hci_enable(struct pn544_hci_info *info, int mode)
-{
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- gpio_set_value(info->gpio_fw, 0);
- gpio_set_value(info->gpio_en, info->en_polarity);
- usleep_range(10000, 15000);
-
- return 0;
-}
-
-static void pn544_hci_disable(struct pn544_hci_info *info)
-{
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- gpio_set_value(info->gpio_fw, 0);
- gpio_set_value(info->gpio_en, !info->en_polarity);
- usleep_range(10000, 15000);
-
- gpio_set_value(info->gpio_en, info->en_polarity);
- usleep_range(10000, 15000);
-
- gpio_set_value(info->gpio_en, !info->en_polarity);
- usleep_range(10000, 15000);
-}
-
-static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len)
-{
- int r;
-
- usleep_range(3000, 6000);
-
- r = i2c_master_send(client, buf, len);
-
- if (r == -EREMOTEIO) { /* Retry, chip was in standby */
- usleep_range(6000, 10000);
- r = i2c_master_send(client, buf, len);
- }
-
- if (r >= 0) {
- if (r != len)
- return -EREMOTEIO;
- else
- return 0;
- }
-
- return r;
-}
-
-static int check_crc(u8 *buf, int buflen)
-{
- int len;
- u16 crc;
-
- len = buf[0] + 1;
- crc = crc_ccitt(0xffff, buf, len - 2);
- crc = ~crc;
-
- if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) {
- pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n",
- crc, buf[len - 1], buf[len - 2]);
-
- pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
- print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
- 16, 2, buf, buflen, false);
- return -EPERM;
- }
- return 0;
-}
-
-/*
- * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
- * that i2c bus will be flushed and that next read will start on a new frame.
- * returned skb contains only LLC header and payload.
- * returns:
- * -EREMOTEIO : i2c read error (fatal)
- * -EBADMSG : frame was incorrect and discarded
- * -ENOMEM : cannot allocate skb, frame dropped
- */
-static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb)
-{
- int r;
- u8 len;
- u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1];
-
- r = i2c_master_recv(client, &len, 1);
- if (r != 1) {
- dev_err(&client->dev, "cannot read len byte\n");
- return -EREMOTEIO;
- }
-
- if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) ||
- (len > (PN544_HCI_LLC_MAX_SIZE - 1))) {
- dev_err(&client->dev, "invalid len byte\n");
- r = -EBADMSG;
- goto flush;
- }
-
- *skb = alloc_skb(1 + len, GFP_KERNEL);
- if (*skb == NULL) {
- r = -ENOMEM;
- goto flush;
- }
-
- *skb_put(*skb, 1) = len;
-
- r = i2c_master_recv(client, skb_put(*skb, len), len);
- if (r != len) {
- kfree_skb(*skb);
- return -EREMOTEIO;
- }
-
- r = check_crc((*skb)->data, (*skb)->len);
- if (r != 0) {
- kfree_skb(*skb);
- r = -EBADMSG;
- goto flush;
- }
-
- skb_pull(*skb, 1);
- skb_trim(*skb, (*skb)->len - 2);
-
- usleep_range(3000, 6000);
-
- return 0;
-
-flush:
- if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
- r = -EREMOTEIO;
-
- usleep_range(3000, 6000);
-
- return r;
-}
-
-/*
- * Reads an shdlc frame from the chip. This is not as straightforward as it
- * seems. There are cases where we could loose the frame start synchronization.
- * The frame format is len-data-crc, and corruption can occur anywhere while
- * transiting on i2c bus, such that we could read an invalid len.
- * In order to recover synchronization with the next frame, we must be sure
- * to read the real amount of data without using the len byte. We do this by
- * assuming the following:
- * - the chip will always present only one single complete frame on the bus
- * before triggering the interrupt
- * - the chip will not present a new frame until we have completely read
- * the previous one (or until we have handled the interrupt).
- * The tricky case is when we read a corrupted len that is less than the real
- * len. We must detect this here in order to determine that we need to flush
- * the bus. This is the reason why we check the crc here.
- */
-static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id)
-{
- struct pn544_hci_info *info = dev_id;
- struct i2c_client *client;
- struct sk_buff *skb = NULL;
- int r;
-
- if (!info || irq != info->i2c_dev->irq) {
- WARN_ON_ONCE(1);
- return IRQ_NONE;
- }
-
- client = info->i2c_dev;
- dev_dbg(&client->dev, "IRQ\n");
-
- if (info->hard_fault != 0)
- return IRQ_HANDLED;
-
- r = pn544_hci_i2c_read(client, &skb);
- if (r == -EREMOTEIO) {
- info->hard_fault = r;
-
- nfc_hci_recv_frame(info->hdev, NULL);
-
- return IRQ_HANDLED;
- } else if ((r == -ENOMEM) || (r == -EBADMSG)) {
- return IRQ_HANDLED;
- }
-
- nfc_hci_recv_frame(info->hdev, skb);
-
- return IRQ_HANDLED;
-}
-
static int pn544_hci_open(struct nfc_hci_dev *hdev)
{
struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
@@ -393,7 +143,7 @@ static int pn544_hci_open(struct nfc_hci_dev *hdev)
goto out;
}
- r = pn544_hci_enable(info, HCI_MODE);
+ r = info->phy_ops->enable(info->phy_id);
if (r == 0)
info->state = PN544_ST_READY;
@@ -412,7 +162,7 @@ static void pn544_hci_close(struct nfc_hci_dev *hdev)
if (info->state == PN544_ST_COLD)
goto out;
- pn544_hci_disable(info);
+ info->phy_ops->disable(info->phy_id);
info->state = PN544_ST_COLD;
@@ -587,40 +337,11 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev)
return 0;
}
-static void pn544_hci_add_len_crc(struct sk_buff *skb)
-{
- u16 crc;
- int len;
-
- len = skb->len + 2;
- *skb_push(skb, 1) = len;
-
- crc = crc_ccitt(0xffff, skb->data, skb->len);
- crc = ~crc;
- *skb_put(skb, 1) = crc & 0xff;
- *skb_put(skb, 1) = crc >> 8;
-}
-
-static void pn544_hci_remove_len_crc(struct sk_buff *skb)
-{
- skb_pull(skb, PN544_FRAME_HEADROOM);
- skb_trim(skb, PN544_FRAME_TAILROOM);
-}
-
static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
{
struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
- struct i2c_client *client = info->i2c_dev;
- int r;
- if (info->hard_fault != 0)
- return info->hard_fault;
-
- pn544_hci_add_len_crc(skb);
- r = pn544_hci_i2c_write(client, skb->data, skb->len);
- pn544_hci_remove_len_crc(skb);
-
- return r;
+ return info->phy_ops->write(info->phy_id, skb);
}
static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
@@ -630,6 +351,9 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
int r;
u8 duration[2];
u8 activated;
+ u8 i_mode = 0x3f; /* Enable all supported modes */
+ u8 t_mode = 0x0f;
+ u8 t_merge = 0x01; /* Enable merge by default */
pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
__func__, im_protocols, tm_protocols);
@@ -667,6 +391,61 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
if (r < 0)
return r;
+ if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
+ hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
+ &hdev->gb_len);
+ pr_debug("generate local bytes %p", hdev->gb);
+ if (hdev->gb == NULL || hdev->gb_len == 0) {
+ im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+ tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+ }
+ }
+
+ if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ r = nfc_hci_send_event(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_set_param(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ PN544_DEP_MODE, &i_mode, 1);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_set_param(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_send_event(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+ if (r < 0)
+ nfc_hci_send_event(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+ }
+
+ if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+ PN544_DEP_MODE, &t_mode, 1);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+ PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+ PN544_DEP_MERGE, &t_merge, 1);
+ if (r < 0)
+ return r;
+ }
+
r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
if (r < 0)
@@ -676,6 +455,43 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
return r;
}
+static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev,
+ struct nfc_target *target, u8 comm_mode,
+ u8 *gb, size_t gb_len)
+{
+ struct sk_buff *rgb_skb = NULL;
+ int r;
+
+ r = nfc_hci_get_param(hdev, target->hci_reader_gate,
+ PN544_DEP_ATR_RES, &rgb_skb);
+ if (r < 0)
+ return r;
+
+ if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) {
+ r = -EPROTO;
+ goto exit;
+ }
+ print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET,
+ 16, 1, rgb_skb->data, rgb_skb->len, true);
+
+ r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data,
+ rgb_skb->len);
+
+ if (r == 0)
+ r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode,
+ NFC_RF_INITIATOR);
+exit:
+ kfree_skb(rgb_skb);
+ return r;
+}
+
+static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev)
+{
+
+ return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+}
+
static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target)
{
@@ -687,6 +503,9 @@ static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
target->supported_protocols = NFC_PROTO_JEWEL_MASK;
target->sens_res = 0x0c00;
break;
+ case PN544_RF_READER_NFCIP1_INITIATOR_GATE:
+ target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+ break;
default:
return -EPROTO;
}
@@ -701,7 +520,18 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
struct sk_buff *uid_skb;
int r = 0;
- if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+ if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE)
+ return r;
+
+ if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ r = nfc_hci_send_cmd(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL);
+ if (r < 0)
+ return r;
+
+ target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE;
+ } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
target->nfcid1_len != 10)
return -EPROTO;
@@ -724,6 +554,16 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
PN544_RF_READER_CMD_ACTIVATE_NEXT,
uid_skb->data, uid_skb->len, NULL);
kfree_skb(uid_skb);
+
+ r = nfc_hci_send_cmd(hdev,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ PN544_HCI_CMD_CONTINUE_ACTIVATION,
+ NULL, 0, NULL);
+ if (r < 0)
+ return r;
+
+ target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE;
+ target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
} else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) {
/*
* TODO: maybe other ISO 14443 require some kind of continue
@@ -769,7 +609,7 @@ static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb,
* <= 0: driver handled the data exchange
* 1: driver doesn't especially handle, please do standard processing
*/
-static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev,
+static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev,
struct nfc_target *target,
struct sk_buff *skb, data_exchange_cb_t cb,
void *cb_context)
@@ -822,17 +662,110 @@ static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev,
return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
PN544_JEWEL_RAW_CMD, skb->data,
skb->len, cb, cb_context);
+ case PN544_RF_READER_NFCIP1_INITIATOR_GATE:
+ *skb_push(skb, 1) = 0;
+
+ return nfc_hci_send_event(hdev, target->hci_reader_gate,
+ PN544_HCI_EVT_SND_DATA, skb->data,
+ skb->len);
default:
return 1;
}
}
+static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+ /* Set default false for multiple information chaining */
+ *skb_push(skb, 1) = 0;
+
+ return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+ PN544_HCI_EVT_SND_DATA, skb->data, skb->len);
+}
+
static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
struct nfc_target *target)
{
- return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
- PN544_RF_READER_CMD_PRESENCE_CHECK,
- NULL, 0, NULL);
+ pr_debug("supported protocol %d", target->supported_protocols);
+ if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK |
+ NFC_PROTO_ISO14443_B_MASK)) {
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_RF_READER_CMD_PRESENCE_CHECK,
+ NULL, 0, NULL);
+ } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+ if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
+ target->nfcid1_len != 10)
+ return -EOPNOTSUPP;
+
+ return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+ PN544_RF_READER_CMD_ACTIVATE_NEXT,
+ target->nfcid1, target->nfcid1_len, NULL);
+ } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) {
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_JEWEL_RAW_CMD, NULL, 0, NULL);
+ } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) {
+ return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE,
+ PN544_FELICA_RAW, NULL, 0, NULL);
+ } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_HCI_CMD_ATTREQUEST,
+ NULL, 0, NULL);
+ }
+
+ return 0;
+}
+
+static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
+ u8 event, struct sk_buff *skb)
+{
+ struct sk_buff *rgb_skb = NULL;
+ int r = 0;
+
+ pr_debug("hci event %d", event);
+ switch (event) {
+ case PN544_HCI_EVT_ACTIVATED:
+ if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE)
+ nfc_hci_target_discovered(hdev, gate);
+ else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) {
+ r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ,
+ &rgb_skb);
+
+ if (r < 0)
+ goto exit;
+
+ nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+ NFC_COMM_PASSIVE, rgb_skb->data,
+ rgb_skb->len);
+
+ kfree_skb(rgb_skb);
+ }
+
+ break;
+ case PN544_HCI_EVT_DEACTIVATED:
+ nfc_hci_send_event(hdev, gate,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+ break;
+ case PN544_HCI_EVT_RCV_DATA:
+ if (skb->len < 2) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ if (skb->data[0] != 0) {
+ pr_debug("data0 %d", skb->data[0]);
+ r = -EPROTO;
+ goto exit;
+ }
+
+ skb_pull(skb, 2);
+ nfc_tm_data_received(hdev->ndev, skb);
+
+ return;
+ default:
+ break;
+ }
+
+exit:
+ kfree_skb(skb);
}
static struct nfc_hci_ops pn544_hci_ops = {
@@ -841,74 +774,36 @@ static struct nfc_hci_ops pn544_hci_ops = {
.hci_ready = pn544_hci_ready,
.xmit = pn544_hci_xmit,
.start_poll = pn544_hci_start_poll,
+ .dep_link_up = pn544_hci_dep_link_up,
+ .dep_link_down = pn544_hci_dep_link_down,
.target_from_gate = pn544_hci_target_from_gate,
.complete_target_discovered = pn544_hci_complete_target_discovered,
- .data_exchange = pn544_hci_data_exchange,
+ .im_transceive = pn544_hci_im_transceive,
+ .tm_send = pn544_hci_tm_send,
.check_presence = pn544_hci_check_presence,
+ .event_received = pn544_hci_event_received,
};
-static int __devinit pn544_hci_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
+ int phy_headroom, int phy_tailroom, int phy_payload,
+ struct nfc_hci_dev **hdev)
{
struct pn544_hci_info *info;
- struct pn544_nfc_platform_data *pdata;
- int r = 0;
u32 protocols;
struct nfc_hci_init_data init_data;
-
- dev_dbg(&client->dev, "%s\n", __func__);
- dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "Need I2C_FUNC_I2C\n");
- return -ENODEV;
- }
+ int r;
info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL);
if (!info) {
- dev_err(&client->dev,
- "Cannot allocate memory for pn544_hci_info.\n");
+ pr_err("Cannot allocate memory for pn544_hci_info.\n");
r = -ENOMEM;
goto err_info_alloc;
}
- info->i2c_dev = client;
+ info->phy_ops = phy_ops;
+ info->phy_id = phy_id;
info->state = PN544_ST_COLD;
mutex_init(&info->info_lock);
- i2c_set_clientdata(client, info);
-
- pdata = client->dev.platform_data;
- if (pdata == NULL) {
- dev_err(&client->dev, "No platform data\n");
- r = -EINVAL;
- goto err_pdata;
- }
-
- if (pdata->request_resources == NULL) {
- dev_err(&client->dev, "request_resources() missing\n");
- r = -EINVAL;
- goto err_pdata;
- }
-
- r = pdata->request_resources(client);
- if (r) {
- dev_err(&client->dev, "Cannot get platform resources\n");
- goto err_pdata;
- }
-
- info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
- info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
- info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
-
- pn544_hci_platform_init(info);
-
- r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- PN544_HCI_DRIVER_NAME, info);
- if (r < 0) {
- dev_err(&client->dev, "Unable to register IRQ handler\n");
- goto err_rti;
- }
init_data.gate_count = ARRAY_SIZE(pn544_gates);
@@ -928,13 +823,11 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
NFC_PROTO_NFC_DEP_MASK;
info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data,
- protocols, LLC_SHDLC_NAME,
- PN544_FRAME_HEADROOM +
- PN544_CMDS_HEADROOM,
- PN544_FRAME_TAILROOM,
- PN544_HCI_LLC_MAX_PAYLOAD);
+ protocols, llc_name,
+ phy_headroom + PN544_CMDS_HEADROOM,
+ phy_tailroom, phy_payload);
if (!info->hdev) {
- dev_err(&client->dev, "Cannot allocate nfc hdev.\n");
+ pr_err("Cannot allocate nfc hdev.\n");
r = -ENOMEM;
goto err_alloc_hdev;
}
@@ -945,79 +838,25 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
if (r)
goto err_regdev;
+ *hdev = info->hdev;
+
return 0;
err_regdev:
nfc_hci_free_device(info->hdev);
err_alloc_hdev:
- free_irq(client->irq, info);
-
-err_rti:
- if (pdata->free_resources != NULL)
- pdata->free_resources();
-
-err_pdata:
kfree(info);
err_info_alloc:
return r;
}
-static __devexit int pn544_hci_remove(struct i2c_client *client)
+void pn544_hci_remove(struct nfc_hci_dev *hdev)
{
- struct pn544_hci_info *info = i2c_get_clientdata(client);
- struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
-
- dev_dbg(&client->dev, "%s\n", __func__);
-
- nfc_hci_free_device(info->hdev);
-
- if (info->state != PN544_ST_COLD) {
- if (pdata->disable)
- pdata->disable();
- }
-
- free_irq(client->irq, info);
- if (pdata->free_resources)
- pdata->free_resources();
+ struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+ nfc_hci_unregister_device(hdev);
+ nfc_hci_free_device(hdev);
kfree(info);
-
- return 0;
}
-
-static struct i2c_driver pn544_hci_driver = {
- .driver = {
- .name = PN544_HCI_DRIVER_NAME,
- },
- .probe = pn544_hci_probe,
- .id_table = pn544_hci_id_table,
- .remove = __devexit_p(pn544_hci_remove),
-};
-
-static int __init pn544_hci_init(void)
-{
- int r;
-
- pr_debug(DRIVER_DESC ": %s\n", __func__);
-
- r = i2c_add_driver(&pn544_hci_driver);
- if (r) {
- pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n");
- return r;
- }
-
- return 0;
-}
-
-static void __exit pn544_hci_exit(void)
-{
- i2c_del_driver(&pn544_hci_driver);
-}
-
-module_init(pn544_hci_init);
-module_exit(pn544_hci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/pn544/pn544.h b/drivers/nfc/pn544/pn544.h
new file mode 100644
index 000000000000..f47c6454914b
--- /dev/null
+++ b/drivers/nfc/pn544/pn544.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 - 2012 Intel Corporation. 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LOCAL_PN544_H_
+#define __LOCAL_PN544_H_
+
+#include <net/nfc/hci.h>
+
+#define DRIVER_DESC "HCI NFC driver for PN544"
+
+int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
+ int phy_headroom, int phy_tailroom, int phy_payload,
+ struct nfc_hci_dev **hdev);
+void pn544_hci_remove(struct nfc_hci_dev *hdev);
+
+#endif /* __LOCAL_PN544_H_ */
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index a543746fb354..ad6a8b635692 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
int retval;
pci_fixup_device(pci_fixup_final, dev);
+
+ retval = pcibios_add_device(dev);
+ if (retval)
+ return retval;
+
retval = device_add(&dev->dev);
if (retval)
return retval;
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 2eca902a4283..3c6bbdd059a4 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
module_init(ioapic_init);
module_exit(ioapic_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index aeccc911abb8..bafd2bbcaf65 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
virtfn->resource[i].name = pci_name(virtfn);
virtfn->resource[i].flags = res->flags;
size = resource_size(res);
- do_div(size, iov->total);
+ do_div(size, iov->total_VFs);
virtfn->resource[i].start = res->start + size * id;
virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
rc = request_resource(res, &virtfn->resource[i]);
@@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
u16 status;
struct pci_sriov *iov = dev->sriov;
- if (!iov->nr_virtfn)
+ if (!iov->num_VFs)
return 0;
if (!(iov->cap & PCI_SRIOV_CAP_VFM))
@@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
u16 status;
struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
- for (i = iov->initial; i < iov->nr_virtfn; i++) {
+ for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_MI) {
writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
@@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
resource_size_t pa;
struct pci_sriov *iov = dev->sriov;
- if (nr_virtfn <= iov->initial)
+ if (nr_virtfn <= iov->initial_VFs)
return 0;
pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
@@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
if (!nr_virtfn)
return 0;
- if (iov->nr_virtfn)
+ if (iov->num_VFs)
return -EINVAL;
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
- if (initial > iov->total ||
- (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
+ if (initial > iov->total_VFs ||
+ (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
return -EIO;
- if (nr_virtfn < 0 || nr_virtfn > iov->total ||
+ if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL;
@@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
msleep(100);
pci_cfg_access_unlock(dev);
- iov->initial = initial;
+ iov->initial_VFs = initial;
if (nr_virtfn < initial)
initial = nr_virtfn;
@@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
}
kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
- iov->nr_virtfn = nr_virtfn;
+ iov->num_VFs = nr_virtfn;
return 0;
@@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
int i;
struct pci_sriov *iov = dev->sriov;
- if (!iov->nr_virtfn)
+ if (!iov->num_VFs)
return;
if (iov->cap & PCI_SRIOV_CAP_VFM)
sriov_disable_migration(dev);
- for (i = 0; i < iov->nr_virtfn; i++)
+ for (i = 0; i < iov->num_VFs; i++)
virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
@@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev)
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
- iov->nr_virtfn = 0;
+ iov->num_VFs = 0;
}
static int sriov_init(struct pci_dev *dev, int pos)
@@ -496,7 +496,7 @@ found:
iov->pos = pos;
iov->nres = nres;
iov->ctrl = ctrl;
- iov->total = total;
+ iov->total_VFs = total;
iov->offset = offset;
iov->stride = stride;
iov->pgsz = pgsz;
@@ -529,7 +529,7 @@ failed:
static void sriov_release(struct pci_dev *dev)
{
- BUG_ON(dev->sriov->nr_virtfn);
+ BUG_ON(dev->sriov->num_VFs);
if (dev != dev->sriov->dev)
pci_dev_put(dev->sriov->dev);
@@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev)
pci_update_resource(dev, i);
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
- pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn);
+ pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
msleep(100);
@@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
if (!dev->is_physfn)
continue;
- busnr = virtfn_bus(dev, dev->sriov->total - 1);
+ busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
if (busnr > max)
max = busnr;
}
@@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
*/
int pci_num_vf(struct pci_dev *dev)
{
- if (!dev || !dev->is_physfn)
+ if (!dev->is_physfn)
return 0;
- else
- return dev->sriov->nr_virtfn;
+
+ return dev->sriov->num_VFs;
}
EXPORT_SYMBOL_GPL(pci_num_vf);
+
+/**
+ * pci_sriov_set_totalvfs -- reduce the TotalVFs available
+ * @dev: the PCI PF device
+ * numvfs: number that should be used for TotalVFs supported
+ *
+ * Should be called from PF driver's probe routine with
+ * device's mutex held.
+ *
+ * Returns 0 if PF is an SRIOV-capable device and
+ * value of numvfs valid. If not a PF with VFS, return -EINVAL;
+ * if VFs already enabled, return -EBUSY.
+ */
+int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+ if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
+ return -EINVAL;
+
+ /* Shouldn't change if VFs already enabled */
+ if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
+ return -EBUSY;
+ else
+ dev->sriov->driver_max_VFs = numvfs;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
+
+/**
+ * pci_sriov_get_totalvfs -- get total VFs supported on this devic3
+ * @dev: the PCI PF device
+ *
+ * For a PCIe device with SRIOV support, return the PCIe
+ * SRIOV capability value of TotalVFs or the value of driver_max_VFs
+ * if the driver reduced it. Otherwise, -EINVAL.
+ */
+int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+ if (!dev->is_physfn)
+ return -EINVAL;
+
+ if (dev->sriov->driver_max_VFs)
+ return dev->sriov->driver_max_VFs;
+
+ return dev->sriov->total_VFs;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c
index e5f69a43b1b1..b008cf86b9c3 100644
--- a/drivers/pci/irq.c
+++ b/drivers/pci/irq.c
@@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
{
struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
- dev_printk(KERN_ERR, &pdev->dev,
- "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
- dev_name(&parent->dev), parent->vendor, parent->device);
- dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
- dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
+ dev_err(&pdev->dev,
+ "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
+ dev_name(&parent->dev), parent->vendor, parent->device);
+ dev_err(&pdev->dev, "%s\n", reason);
+ dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
WARN_ON(1);
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 1dc78c5cabf8..f79cbcd3944b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -248,31 +248,26 @@ struct drv_dev_and_id {
static long local_pci_probe(void *_ddi)
{
struct drv_dev_and_id *ddi = _ddi;
- struct device *dev = &ddi->dev->dev;
- struct device *parent = dev->parent;
+ struct pci_dev *pci_dev = ddi->dev;
+ struct pci_driver *pci_drv = ddi->drv;
+ struct device *dev = &pci_dev->dev;
int rc;
- /* The parent bridge must be in active state when probing */
- if (parent)
- pm_runtime_get_sync(parent);
- /* Unbound PCI devices are always set to disabled and suspended.
- * During probe, the device is set to enabled and active and the
- * usage count is incremented. If the driver supports runtime PM,
- * it should call pm_runtime_put_noidle() in its probe routine and
- * pm_runtime_get_noresume() in its remove routine.
+ /*
+ * Unbound PCI devices are always put in D0, regardless of
+ * runtime PM status. During probe, the device is set to
+ * active and the usage count is incremented. If the driver
+ * supports runtime PM, it should call pm_runtime_put_noidle()
+ * in its probe routine and pm_runtime_get_noresume() in its
+ * remove routine.
*/
- pm_runtime_get_noresume(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
-
- rc = ddi->drv->probe(ddi->dev, ddi->id);
+ pm_runtime_get_sync(dev);
+ pci_dev->driver = pci_drv;
+ rc = pci_drv->probe(pci_dev, ddi->id);
if (rc) {
- pm_runtime_disable(dev);
- pm_runtime_set_suspended(dev);
- pm_runtime_put_noidle(dev);
+ pci_dev->driver = NULL;
+ pm_runtime_put_sync(dev);
}
- if (parent)
- pm_runtime_put(parent);
return rc;
}
@@ -322,10 +317,8 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
id = pci_match_device(drv, pci_dev);
if (id)
error = pci_call_probe(drv, pci_dev, id);
- if (error >= 0) {
- pci_dev->driver = drv;
+ if (error >= 0)
error = 0;
- }
}
return error;
}
@@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
}
/* Undo the runtime PM settings in local_pci_probe() */
- pm_runtime_disable(dev);
- pm_runtime_set_suspended(dev);
- pm_runtime_put_noidle(dev);
+ pm_runtime_put_sync(dev);
/*
* If the device is still on, set the power state as "unknown",
@@ -986,6 +977,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
pci_power_t prev = pci_dev->current_state;
int error;
+ /*
+ * If pci_dev->driver is not set (unbound), the device should
+ * always remain in D0 regardless of the runtime PM status
+ */
+ if (!pci_dev->driver)
+ return 0;
+
if (!pm || !pm->runtime_suspend)
return -ENOSYS;
@@ -1007,10 +1005,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
return 0;
}
- if (!pci_dev->state_saved)
+ if (!pci_dev->state_saved) {
pci_save_state(pci_dev);
-
- pci_finish_runtime_suspend(pci_dev);
+ pci_finish_runtime_suspend(pci_dev);
+ }
return 0;
}
@@ -1021,6 +1019,13 @@ static int pci_pm_runtime_resume(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ /*
+ * If pci_dev->driver is not set (unbound), the device should
+ * always remain in D0 regardless of the runtime PM status
+ */
+ if (!pci_dev->driver)
+ return 0;
+
if (!pm || !pm->runtime_resume)
return -ENOSYS;
@@ -1038,8 +1043,16 @@ static int pci_pm_runtime_resume(struct device *dev)
static int pci_pm_runtime_idle(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ /*
+ * If pci_dev->driver is not set (unbound), the device should
+ * always remain in D0 regardless of the runtime PM status
+ */
+ if (!pci_dev->driver)
+ goto out;
+
if (!pm)
return -ENOSYS;
@@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
return ret;
}
+out:
pm_runtime_suspend(dev);
-
return 0;
}
diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c
index 775e933c2225..6e47c519c510 100644
--- a/drivers/pci/pci-stub.c
+++ b/drivers/pci/pci-stub.c
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
- dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
+ dev_info(&dev->dev, "claimed by stub\n");
return 0;
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 68d56f02e721..05b78b16d20b 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -401,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
}
#endif
+#ifdef CONFIG_PCI_IOV
+static ssize_t sriov_totalvfs_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
+}
+
+
+static ssize_t sriov_numvfs_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
+}
+
+/*
+ * num_vfs > 0; number of vfs to enable
+ * num_vfs = 0; disable all vfs
+ *
+ * Note: SRIOV spec doesn't allow partial VF
+ * disable, so its all or none.
+ */
+static ssize_t sriov_numvfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int num_vfs_enabled = 0;
+ int num_vfs;
+ int ret = 0;
+ u16 total;
+
+ if (kstrtoint(buf, 0, &num_vfs) < 0)
+ return -EINVAL;
+
+ /* is PF driver loaded w/callback */
+ if (!pdev->driver || !pdev->driver->sriov_configure) {
+ dev_info(&pdev->dev,
+ "Driver doesn't support SRIOV configuration via sysfs\n");
+ return -ENOSYS;
+ }
+
+ /* if enabling vf's ... */
+ total = pci_sriov_get_totalvfs(pdev);
+ /* Requested VFs to enable < totalvfs and none enabled already */
+ if ((num_vfs > 0) && (num_vfs <= total)) {
+ if (pdev->sriov->num_VFs == 0) {
+ num_vfs_enabled =
+ pdev->driver->sriov_configure(pdev, num_vfs);
+ if ((num_vfs_enabled >= 0) &&
+ (num_vfs_enabled != num_vfs)) {
+ dev_warn(&pdev->dev,
+ "Only %d VFs enabled\n",
+ num_vfs_enabled);
+ return count;
+ } else if (num_vfs_enabled < 0)
+ /* error code from driver callback */
+ return num_vfs_enabled;
+ } else if (num_vfs == pdev->sriov->num_VFs) {
+ dev_warn(&pdev->dev,
+ "%d VFs already enabled; no enable action taken\n",
+ num_vfs);
+ return count;
+ } else {
+ dev_warn(&pdev->dev,
+ "%d VFs already enabled. Disable before enabling %d VFs\n",
+ pdev->sriov->num_VFs, num_vfs);
+ return -EINVAL;
+ }
+ }
+
+ /* disable vfs */
+ if (num_vfs == 0) {
+ if (pdev->sriov->num_VFs != 0) {
+ ret = pdev->driver->sriov_configure(pdev, 0);
+ return ret ? ret : count;
+ } else {
+ dev_warn(&pdev->dev,
+ "All VFs disabled; no disable action taken\n");
+ return count;
+ }
+ }
+
+ dev_err(&pdev->dev,
+ "Invalid value for number of VFs to enable: %d\n", num_vfs);
+
+ return -EINVAL;
+}
+
+static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
+static struct device_attribute sriov_numvfs_attr =
+ __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
+ sriov_numvfs_show, sriov_numvfs_store);
+#endif /* CONFIG_PCI_IOV */
+
struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
@@ -1262,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
pdev->rom_attr = attr;
}
- if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- retval = device_create_file(&pdev->dev, &vga_attr);
- if (retval)
- goto err_rom_file;
- }
-
/* add platform-specific attributes */
retval = pcibios_add_platform_entries(pdev);
if (retval)
- goto err_vga_file;
+ goto err_rom_file;
/* add sysfs entries for various capabilities */
retval = pci_create_capabilities_sysfs(pdev);
if (retval)
- goto err_vga_file;
+ goto err_rom_file;
pci_create_firmware_label_files(pdev);
return 0;
-err_vga_file:
- if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- device_remove_file(&pdev->dev, &vga_attr);
err_rom_file:
if (rom_size) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
@@ -1370,3 +1461,62 @@ static int __init pci_sysfs_init(void)
}
late_initcall(pci_sysfs_init);
+
+static struct attribute *pci_dev_dev_attrs[] = {
+ &vga_attr.attr,
+ NULL,
+};
+
+static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (a == &vga_attr.attr)
+ if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+ return 0;
+
+ return a->mode;
+}
+
+#ifdef CONFIG_PCI_IOV
+static struct attribute *sriov_dev_attrs[] = {
+ &sriov_totalvfs_attr.attr,
+ &sriov_numvfs_attr.attr,
+ NULL,
+};
+
+static umode_t sriov_attrs_are_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+
+ if (!dev_is_pf(dev))
+ return 0;
+
+ return a->mode;
+}
+
+static struct attribute_group sriov_dev_attr_group = {
+ .attrs = sriov_dev_attrs,
+ .is_visible = sriov_attrs_are_visible,
+};
+#endif /* CONFIG_PCI_IOV */
+
+static struct attribute_group pci_dev_attr_group = {
+ .attrs = pci_dev_dev_attrs,
+ .is_visible = pci_dev_attrs_are_visible,
+};
+
+static const struct attribute_group *pci_dev_attr_groups[] = {
+ &pci_dev_attr_group,
+#ifdef CONFIG_PCI_IOV
+ &sriov_dev_attr_group,
+#endif
+ NULL,
+};
+
+struct device_type pci_dev_type = {
+ .groups = pci_dev_attr_groups,
+};
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bdf66b500f22..5cb5820fae40 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
dr->pinned = 1;
}
+/*
+ * pcibios_add_device - provide arch specific hooks when adding device dev
+ * @dev: the PCI device being added
+ *
+ * Permits the platform to provide architecture specific functionality when
+ * devices are added. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+int __weak pcibios_add_device (struct pci_dev *dev)
+{
+ return 0;
+}
+
/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
@@ -1578,15 +1591,25 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
- /* PCI (as opposed to PCIe) PME requires that the device have
- its PME# line hooked up correctly. Not all hardware vendors
- do this, so the PME never gets delivered and the device
- remains asleep. The easiest way around this is to
- periodically walk the list of suspended devices and check
- whether any have their PME flag set. The assumption is that
- we'll wake up often enough anyway that this won't be a huge
- hit, and the power savings from the devices will still be a
- win. */
+ /*
+ * PCI (as opposed to PCIe) PME requires that the device have
+ * its PME# line hooked up correctly. Not all hardware vendors
+ * do this, so the PME never gets delivered and the device
+ * remains asleep. The easiest way around this is to
+ * periodically walk the list of suspended devices and check
+ * whether any have their PME flag set. The assumption is that
+ * we'll wake up often enough anyway that this won't be a huge
+ * hit, and the power savings from the devices will still be a
+ * win.
+ *
+ * Although PCIe uses in-band PME message instead of PME# line
+ * to report PME, PME does not work for some PCIe devices in
+ * reality. For example, there are devices that set their PME
+ * status bits, but don't really bother to send a PME message;
+ * there are PCI Express Root Ports that don't bother to
+ * trigger interrupts when they receive PME messages from the
+ * devices below. So PME poll is used for PCIe devices too.
+ */
if (dev->pme_poll) {
struct pci_pme_device *pme_dev;
@@ -1900,6 +1923,8 @@ void pci_pm_init(struct pci_dev *dev)
u16 pmc;
pm_runtime_forbid(&dev->dev);
+ pm_runtime_set_active(&dev->dev);
+ pm_runtime_enable(&dev->dev);
device_enable_async_suspend(&dev->dev);
dev->wakeup_prepared = false;
@@ -3865,14 +3890,13 @@ static void pci_no_domains(void)
}
/**
- * pci_ext_cfg_enabled - can we access extended PCI config space?
- * @dev: The PCI device of the root bridge.
+ * pci_ext_cfg_avail - can we access extended PCI config space?
*
* Returns 1 if we can access PCI extended config space (offsets
* greater than 0xff). This is the default implementation. Architecture
* implementations can override this.
*/
-int __weak pci_ext_cfg_avail(struct pci_dev *dev)
+int __weak pci_ext_cfg_avail(void)
{
return 1;
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index e253881c4275..e8518292826f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -158,6 +158,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
}
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[];
+extern struct device_type pci_dev_type;
extern struct bus_attribute pci_bus_attrs[];
@@ -229,13 +230,14 @@ struct pci_sriov {
int nres; /* number of resources */
u32 cap; /* SR-IOV Capabilities */
u16 ctrl; /* SR-IOV Control */
- u16 total; /* total VFs associated with the PF */
- u16 initial; /* initial VFs associated with the PF */
- u16 nr_virtfn; /* number of VFs available */
+ u16 total_VFs; /* total VFs associated with the PF */
+ u16 initial_VFs; /* initial VFs associated with the PF */
+ u16 num_VFs; /* number of VFs available */
u16 offset; /* first VF Routing ID offset */
u16 stride; /* following VF stride */
u32 pgsz; /* page size for BAR alignment */
u8 link; /* Function Dependency Link */
+ u16 driver_max_VFs; /* max num VFs driver supports */
struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for VF bus */
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 94a7598eb262..22f840f4dda1 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -87,6 +87,9 @@ struct aer_broadcast_data {
static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new)
{
+ if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
+ return PCI_ERS_RESULT_NO_AER_DRIVER;
+
if (new == PCI_ERS_RESULT_NONE)
return orig;
@@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
break;
case PCI_ERS_RESULT_DISCONNECT:
if (new == PCI_ERS_RESULT_NEED_RESET)
- orig = new;
+ orig = PCI_ERS_RESULT_NEED_RESET;
break;
default:
break;
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index af4e31cd3a3b..421bbc5fee32 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
dev->driver ?
"no AER-aware driver" : "no driver");
}
- goto out;
+
+ /*
+ * If there's any device in the subtree that does not
+ * have an error_detected callback, returning
+ * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of
+ * the subsequent mmio_enabled/slot_reset/resume
+ * callbacks of "any" device in the subtree. All the
+ * devices in the subtree are left in the error state
+ * without recovery.
+ */
+
+ if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+ vote = PCI_ERS_RESULT_NO_AER_DRIVER;
+ else
+ vote = PCI_ERS_RESULT_NONE;
+ } else {
+ err_handler = dev->driver->err_handler;
+ vote = err_handler->error_detected(dev, result_data->state);
}
- err_handler = dev->driver->err_handler;
- vote = err_handler->error_detected(dev, result_data->state);
result_data->result = merge_result(result_data->result, vote);
-out:
device_unlock(&dev->dev);
return 0;
}
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 213753b283a6..b52630b8eada 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
return;
/* Training failed. Restore common clock configurations */
- dev_printk(KERN_ERR, &parent->dev,
- "ASPM: Could not configure common clock\n");
+ dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
list_for_each_entry(child, &linkbus->devices, bus_list)
pcie_capability_write_word(child, PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]);
@@ -427,7 +426,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{
- pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val);
+ pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC, val);
}
static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
@@ -442,12 +442,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
return;
/* Convert ASPM state to upstream/downstream ASPM register state */
if (state & ASPM_STATE_L0S_UP)
- dwstream |= PCIE_LINK_STATE_L0S;
+ dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L0S_DW)
- upstream |= PCIE_LINK_STATE_L0S;
+ upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L1) {
- upstream |= PCIE_LINK_STATE_L1;
- dwstream |= PCIE_LINK_STATE_L1;
+ upstream |= PCI_EXP_LNKCTL_ASPM_L1;
+ dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
}
/*
* Spec 2.0 suggests all functions should be configured the
@@ -507,9 +507,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
*/
pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
- dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
- " on pre-1.1 PCIe device. You can enable it"
- " with 'pcie_aspm=force'\n");
+ dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n");
return -EINVAL;
}
}
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index ed129b414624..b42133afca98 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -120,8 +120,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
* the value in this field indicates which MSI-X Table entry is
* used to generate the interrupt message."
*/
- pos = pci_pcie_cap(dev);
- pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
+ pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
if (entry >= nr_entries)
goto Error;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3683f6094e3f..6186f03d84f3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = {
void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
{
- bus->cur_bus_speed = pcie_link_speed[linksta & 0xf];
+ bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
}
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
@@ -579,14 +579,16 @@ static void pci_set_bus_speed(struct pci_bus *bus)
if (pos) {
u16 status;
enum pci_bus_speed max;
- pci_read_config_word(bridge, pos + 2, &status);
- if (status & 0x8000) {
+ pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS,
+ &status);
+
+ if (status & PCI_X_SSTATUS_533MHZ) {
max = PCI_SPEED_133MHz_PCIX_533;
- } else if (status & 0x4000) {
+ } else if (status & PCI_X_SSTATUS_266MHZ) {
max = PCI_SPEED_133MHz_PCIX_266;
- } else if (status & 0x0002) {
- if (((status >> 12) & 0x3) == 2) {
+ } else if (status & PCI_X_SSTATUS_133MHZ) {
+ if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
max = PCI_SPEED_133MHz_PCIX_ECC;
} else {
max = PCI_SPEED_133MHz_PCIX;
@@ -596,7 +598,8 @@ static void pci_set_bus_speed(struct pci_bus *bus)
}
bus->max_bus_speed = max;
- bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf];
+ bus->cur_bus_speed = pcix_bus_speed[
+ (status & PCI_X_SSTATUS_FREQ) >> 6];
return;
}
@@ -607,7 +610,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
u16 linksta;
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
- bus->max_bus_speed = pcie_link_speed[linkcap & 0xf];
+ bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
pcie_update_link_speed(bus, linksta);
@@ -975,6 +978,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->sysdata = dev->bus->sysdata;
dev->dev.parent = dev->bus->bridge;
dev->dev.bus = &pci_bus_type;
+ dev->dev.type = &pci_dev_type;
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
@@ -1889,6 +1893,28 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
return max;
}
+/**
+ * pci_rescan_bus - scan a PCI bus for devices.
+ * @bus: PCI bus to scan
+ *
+ * Scan a PCI bus and child buses for new devices, adds them,
+ * and enables them.
+ *
+ * Returns the max number of subordinate bus discovered.
+ */
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+{
+ unsigned int max;
+
+ max = pci_scan_child_bus(bus);
+ pci_assign_unassigned_bus_resources(bus);
+ pci_enable_bridges(bus);
+ pci_bus_add_devices(bus);
+
+ return max;
+}
+EXPORT_SYMBOL_GPL(pci_rescan_bus);
+
EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 22ad3ee0cf0b..8f7a6344e79e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1790,6 +1790,45 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
quirk_tc86c001_ide);
+/*
+ * PLX PCI 9050 PCI Target bridge controller has an errata that prevents the
+ * local configuration registers accessible via BAR0 (memory) or BAR1 (i/o)
+ * being read correctly if bit 7 of the base address is set.
+ * The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128).
+ * Re-allocate the regions to a 256-byte boundary if necessary.
+ */
+static void quirk_plx_pci9050(struct pci_dev *dev)
+{
+ unsigned int bar;
+
+ /* Fixed in revision 2 (PCI 9052). */
+ if (dev->revision >= 2)
+ return;
+ for (bar = 0; bar <= 1; bar++)
+ if (pci_resource_len(dev, bar) == 0x80 &&
+ (pci_resource_start(dev, bar) & 0x80)) {
+ struct resource *r = &dev->resource[bar];
+ dev_info(&dev->dev,
+ "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
+ bar);
+ r->start = 0;
+ r->end = 0xff;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ quirk_plx_pci9050);
+/*
+ * The following Meilhaus (vendor ID 0x1402) device IDs (amongst others)
+ * may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b,
+ * 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c,
+ * 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b.
+ *
+ * Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq"
+ * driver.
+ */
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050);
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050);
+
static void quirk_netmos(struct pci_dev *dev)
{
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 513972f3ed13..7c0fd9252e6f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
pci_remove_bus_device(dev);
}
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
+
+void pci_stop_root_bus(struct pci_bus *bus)
+{
+ struct pci_dev *child, *tmp;
+ struct pci_host_bridge *host_bridge;
+
+ if (!pci_is_root_bus(bus))
+ return;
+
+ host_bridge = to_pci_host_bridge(bus->bridge);
+ list_for_each_entry_safe_reverse(child, tmp,
+ &bus->devices, bus_list)
+ pci_stop_bus_device(child);
+
+ /* stop the host bridge */
+ device_del(&host_bridge->dev);
+}
+
+void pci_remove_root_bus(struct pci_bus *bus)
+{
+ struct pci_dev *child, *tmp;
+ struct pci_host_bridge *host_bridge;
+
+ if (!pci_is_root_bus(bus))
+ return;
+
+ host_bridge = to_pci_host_bridge(bus->bridge);
+ list_for_each_entry_safe(child, tmp,
+ &bus->devices, bus_list)
+ pci_remove_bus_device(child);
+ pci_remove_bus(bus);
+ host_bridge->bus = NULL;
+
+ /* remove the host bridge */
+ put_device(&host_bridge->dev);
+}
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 0b3037ab8b93..ab886b7ee327 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
void __iomem *rom;
/*
+ * Some devices may provide ROMs via a source other than the BAR
+ */
+ if (pdev->rom && pdev->romlen) {
+ *size = pdev->romlen;
+ return phys_to_virt(pdev->rom);
+ /*
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
* memory map if the VGA enable bit of the Bridge Control register is
* set for embedded VGA.
*/
- if (res->flags & IORESOURCE_ROM_SHADOW) {
+ } else if (res->flags & IORESOURCE_ROM_SHADOW) {
/* primary video rom always starts here */
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
@@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;
- iounmap(rom);
+ if (!pdev->rom || !pdev->romlen)
+ iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1e808ca338f8..6d3591d57ea0 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1550,25 +1550,12 @@ enable_all:
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
-#ifdef CONFIG_HOTPLUG
-/**
- * pci_rescan_bus - scan a PCI bus for devices.
- * @bus: PCI bus to scan
- *
- * Scan a PCI bus and child buses for new devices, adds them,
- * and enables them.
- *
- * Returns the max number of subordinate bus discovered.
- */
-unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
{
- unsigned int max;
struct pci_dev *dev;
LIST_HEAD(add_list); /* list of resources that
want additional resources */
- max = pci_scan_child_bus(bus);
-
down_read(&pci_bus_sem);
list_for_each_entry(dev, &bus->devices, bus_list)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
up_read(&pci_bus_sem);
__pci_bus_assign_resources(bus, &add_list, NULL);
BUG_ON(!list_empty(&add_list));
-
- pci_enable_bridges(bus);
- pci_bus_add_devices(bus);
-
- return max;
}
-EXPORT_SYMBOL_GPL(pci_rescan_bus);
-#endif
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index db542f4196a4..966abc6054d7 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -1068,13 +1068,16 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
case XenbusStateInitialising:
case XenbusStateInitWait:
case XenbusStateInitialised:
- case XenbusStateClosed:
break;
case XenbusStateConnected:
pcifront_try_connect(pdev);
break;
+ case XenbusStateClosed:
+ if (xdev->state == XenbusStateClosed)
+ break;
+ /* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
dev_warn(&xdev->dev, "backend going away!\n");
pcifront_try_disconnect(pdev);
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index ffe74b27d66d..40c9c3eecd94 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -22,22 +22,22 @@
#include "pinctrl-mvebu.h"
-#define DOVE_SB_REGS_VIRT_BASE 0xfde00000
-#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfde00000)
+#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200)
#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
#define DOVE_AU0_AC97_SEL BIT(16)
-#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
#define DOVE_TWSI_ENABLE_OPTION1 BIT(7)
-#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
#define DOVE_TWSI_ENABLE_OPTION2 BIT(20)
#define DOVE_TWSI_ENABLE_OPTION3 BIT(21)
#define DOVE_TWSI_OPTION3_GPIO BIT(22)
-#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE + 0xe8034)
#define DOVE_SSP_ON_AU1 BIT(0)
-#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xe803c)
#define DOVE_AU1_SPDIFO_GPIO_EN BIT(1)
#define DOVE_NAND_GPIO_EN BIT(0)
-#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0400)
#define DOVE_MPP_CTRL4_VIRT_BASE (DOVE_GPIO_LO_VIRT_BASE + 0x40)
#define DOVE_SPI_GPIO_SEL BIT(5)
#define DOVE_UART1_GPIO_SEL BIT(4)
@@ -234,6 +234,14 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+ /*
+ * clear all audio1 related bits before configure
+ */
+ gcfg2 &= ~DOVE_TWSI_OPTION3_GPIO;
+ gmpp &= ~DOVE_AU1_SPDIFO_GPIO_EN;
+ sspc1 &= ~DOVE_SSP_ON_AU1;
+ mpp4 &= ~DOVE_AU1_GPIO_SEL;
+
if (config & BIT(0))
gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
if (config & BIT(1))
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 9a74ef674a0e..fa6ce31c94d9 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -21,340 +21,341 @@
#include "pinctrl-mvebu.h"
-#define V(f6180, f6190, f6192, f6281, f6282) \
+#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
- (f6281 << 3) | (f6282 << 4))
+ (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
enum kirkwood_variant {
- VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
- VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
- VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
- VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
- VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
+ VARIANT_MV88F6180 = V(1, 0, 0, 0, 0, 0),
+ VARIANT_MV88F6190 = V(0, 1, 0, 0, 0, 0),
+ VARIANT_MV88F6192 = V(0, 0, 1, 0, 0, 0),
+ VARIANT_MV88F6281 = V(0, 0, 0, 1, 0, 0),
+ VARIANT_MV88F6282 = V(0, 0, 0, 0, 1, 0),
+ VARIANT_MV98DX4122 = V(0, 0, 0, 0, 0, 1),
};
static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
MPP_MODE(0,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1))),
MPP_MODE(1,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1))),
MPP_MODE(2,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1))),
MPP_MODE(3,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1))),
MPP_MODE(4,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0))),
MPP_MODE(5,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(6,
- MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
MPP_MODE(7,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(8,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
MPP_MODE(9,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
MPP_MODE(10,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
MPP_MODE(11,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0))),
MPP_MODE(12,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1)),
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(13,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(14,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
MPP_MODE(15,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(16,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
MPP_MODE(17,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(18,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(19,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1, 1))),
MPP_MODE(20,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0, 0))),
MPP_MODE(21,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(22,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(23,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(24,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(25,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(26,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(27,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(28,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(29,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(30,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(31,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(32,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(33,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(34,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(35,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1, 0))),
MPP_MODE(36,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(37,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(38,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(39,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(40,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(41,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(42,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(43,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(44,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(45,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(46,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(47,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(48,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1, 0))),
MPP_MODE(49,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1, 0))),
};
static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
@@ -433,12 +434,23 @@ static struct mvebu_pinctrl_soc_info mv88f6282_info = {
.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
};
+static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
+ .variant = VARIANT_MV98DX4122,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
{ .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+ { .compatible = "marvell,98dx4122-pinctrl", .data = &mv98dx4122_info },
{ }
};
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 8ef3e85cb011..ef66f98e9202 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -31,9 +31,8 @@
/* Since we request GPIOs from ourself */
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/pinctrl-nomadik.h>
-
#include <asm/mach/irq.h>
-
+#include <mach/irqs.h>
#include "pinctrl-nomadik.h"
/*
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 49a893972318..b1d956d81f0c 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -335,6 +335,9 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
help
Say Y to enable battery temperature measurements using
thermistor connected on BATCTRL ADC.
+
+source "drivers/power/reset/Kconfig"
+
endif # POWER_SUPPLY
source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b949cf85590c..f1d99f4a0bc3 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
+obj-$(CONFIG_POWER_RESET) += reset/
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
index d0fed2c5cf2c..a17d08411723 100644
--- a/drivers/power/avs/smartreflex.c
+++ b/drivers/power/avs/smartreflex.c
@@ -130,24 +130,21 @@ static irqreturn_t sr_interrupt(int irq, void *data)
static void sr_set_clk_length(struct omap_sr *sr)
{
- struct clk *sys_ck;
- u32 sys_clk_speed;
+ struct clk *fck;
+ u32 fclk_speed;
- if (cpu_is_omap34xx())
- sys_ck = clk_get(NULL, "sys_ck");
- else
- sys_ck = clk_get(NULL, "sys_clkin_ck");
+ fck = clk_get(&sr->pdev->dev, "fck");
- if (IS_ERR(sys_ck)) {
- dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
- __func__);
+ if (IS_ERR(fck)) {
+ dev_err(&sr->pdev->dev, "%s: unable to get fck for device %s\n",
+ __func__, dev_name(&sr->pdev->dev));
return;
}
- sys_clk_speed = clk_get_rate(sys_ck);
- clk_put(sys_ck);
+ fclk_speed = clk_get_rate(fck);
+ clk_put(fck);
- switch (sys_clk_speed) {
+ switch (fclk_speed) {
case 12000000:
sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
break;
@@ -164,34 +161,12 @@ static void sr_set_clk_length(struct omap_sr *sr)
sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
break;
default:
- dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
- __func__, sys_clk_speed);
+ dev_err(&sr->pdev->dev, "%s: Invalid fclk rate: %d\n",
+ __func__, fclk_speed);
break;
}
}
-static void sr_set_regfields(struct omap_sr *sr)
-{
- /*
- * For time being these values are defined in smartreflex.h
- * and populated during init. May be they can be moved to board
- * file or pmic specific data structure. In that case these structure
- * fields will have to be populated using the pdata or pmic structure.
- */
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- sr->err_weight = OMAP3430_SR_ERRWEIGHT;
- sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
- sr->accum_data = OMAP3430_SR_ACCUMDATA;
- if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
- sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
- sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
- } else {
- sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
- sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
- }
- }
-}
-
static void sr_start_vddautocomp(struct omap_sr *sr)
{
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
@@ -924,8 +899,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr_info->nvalue_count = pdata->nvalue_count;
sr_info->senn_mod = pdata->senn_mod;
sr_info->senp_mod = pdata->senp_mod;
+ sr_info->err_weight = pdata->err_weight;
+ sr_info->err_maxlimit = pdata->err_maxlimit;
+ sr_info->accum_data = pdata->accum_data;
+ sr_info->senn_avgweight = pdata->senn_avgweight;
+ sr_info->senp_avgweight = pdata->senp_avgweight;
sr_info->autocomp_active = false;
sr_info->ip_type = pdata->ip_type;
+
sr_info->base = ioremap(mem->start, resource_size(mem));
if (!sr_info->base) {
dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -937,7 +918,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr_info->irq = irq->start;
sr_set_clk_length(sr_info);
- sr_set_regfields(sr_info);
list_add(&sr_info->node, &sr_list);
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
new file mode 100644
index 000000000000..6461b489fb09
--- /dev/null
+++ b/drivers/power/reset/Kconfig
@@ -0,0 +1,15 @@
+menuconfig POWER_RESET
+ bool "Board level reset or power off"
+ help
+ Provides a number of drivers which either reset a complete board
+ or shut it down, by manipulating the main power supply on the board.
+
+ Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+ bool "GPIO power-off driver"
+ depends on OF_GPIO && POWER_RESET
+ help
+ This driver supports turning off your board via a GPIO line.
+ If your board needs a GPIO high/low to power down, say Y and
+ create a binding in your devicetree.
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
new file mode 100644
index 000000000000..751488a4a0c5
--- /dev/null
+++ b/drivers/power/reset/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
new file mode 100644
index 000000000000..0491e5335d02
--- /dev/null
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -0,0 +1,129 @@
+/*
+ * Toggles a GPIO pin to power down a device
+ *
+ * Jamie Lentin <jm@lentin.co.uk>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Copyright (C) 2012 Jamie Lentin
+ *
+ * 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/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+
+/*
+ * Hold configuration here, cannot be more than one instance of the driver
+ * since pm_power_off itself is global.
+ */
+static int gpio_num = -1;
+static int gpio_active_low;
+
+static void gpio_poweroff_do_poweroff(void)
+{
+ BUG_ON(gpio_num == -1);
+
+ /* drive it active */
+ gpio_direction_output(gpio_num, !gpio_active_low);
+ mdelay(100);
+ /* rising edge or drive inactive */
+ gpio_set_value(gpio_num, gpio_active_low);
+ mdelay(100);
+ /* falling edge */
+ gpio_set_value(gpio_num, !gpio_active_low);
+
+ /* give it some time */
+ mdelay(3000);
+
+ WARN_ON(1);
+}
+
+static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
+{
+ enum of_gpio_flags flags;
+ bool input = false;
+ int ret;
+
+ /* If a pm_power_off function has already been added, leave it alone */
+ if (pm_power_off != NULL) {
+ pr_err("%s: pm_power_off function already registered",
+ __func__);
+ return -EBUSY;
+ }
+
+ gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+ if (gpio_num < 0) {
+ pr_err("%s: Could not get GPIO configuration: %d",
+ __func__, gpio_num);
+ return -ENODEV;
+ }
+ gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ if (of_get_property(pdev->dev.of_node, "input", NULL))
+ input = true;
+
+ ret = gpio_request(gpio_num, "poweroff-gpio");
+ if (ret) {
+ pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
+ return ret;
+ }
+ if (input) {
+ if (gpio_direction_input(gpio_num)) {
+ pr_err("Could not set direction of GPIO %d to input",
+ gpio_num);
+ goto err;
+ }
+ } else {
+ if (gpio_direction_output(gpio_num, gpio_active_low)) {
+ pr_err("Could not set direction of GPIO %d", gpio_num);
+ goto err;
+ }
+ }
+
+ pm_power_off = &gpio_poweroff_do_poweroff;
+ return 0;
+
+err:
+ gpio_free(gpio_num);
+ return -ENODEV;
+}
+
+static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+{
+ if (gpio_num != -1)
+ gpio_free(gpio_num);
+ if (pm_power_off == &gpio_poweroff_do_poweroff)
+ pm_power_off = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id of_gpio_poweroff_match[] = {
+ { .compatible = "gpio-poweroff", },
+ {},
+};
+
+static struct platform_driver gpio_poweroff_driver = {
+ .probe = gpio_poweroff_probe,
+ .remove = __devexit_p(gpio_poweroff_remove),
+ .driver = {
+ .name = "poweroff-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_gpio_poweroff_match,
+ },
+};
+
+module_platform_driver(gpio_poweroff_driver);
+
+MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
+MODULE_DESCRIPTION("GPIO poweroff driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:poweroff-gpio");
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
index 258ca596e1bc..982d16b5a846 100644
--- a/drivers/pps/Kconfig
+++ b/drivers/pps/Kconfig
@@ -6,7 +6,6 @@ menu "PPS support"
config PPS
tristate "PPS support"
- depends on EXPERIMENTAL
---help---
PPS (Pulse Per Second) is a special pulse provided by some GPS
antennae. Userland can use it to get a high-precision time
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index ffdf712f9a67..1ea6f1dbbedd 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -4,13 +4,9 @@
menu "PTP clock support"
-comment "Enable Device Drivers -> PPS to see the PTP clock options."
- depends on PPS=n
-
config PTP_1588_CLOCK
tristate "PTP clock support"
- depends on EXPERIMENTAL
- depends on PPS
+ select PPS
help
The IEEE 1588 standard defines a method to precisely
synchronize distributed clocks over Ethernet networks. The
@@ -29,8 +25,9 @@ config PTP_1588_CLOCK
config PTP_1588_CLOCK_GIANFAR
tristate "Freescale eTSEC as PTP clock"
- depends on PTP_1588_CLOCK
depends on GIANFAR
+ select PTP_1588_CLOCK
+ default y
help
This driver adds support for using the eTSEC as a PTP
clock. This clock is only useful if your PTP programs are
@@ -42,8 +39,9 @@ config PTP_1588_CLOCK_GIANFAR
config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock"
- depends on PTP_1588_CLOCK
depends on IXP4XX_ETH
+ select PTP_1588_CLOCK
+ default y
help
This driver adds support for using the IXP46X as a PTP
clock. This clock is only useful if your PTP programs are
@@ -54,13 +52,13 @@ config PTP_1588_CLOCK_IXP46X
will be called ptp_ixp46x.
comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
- depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
+ depends on PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n
config DP83640_PHY
tristate "Driver for the National Semiconductor DP83640 PHYTER"
- depends on PTP_1588_CLOCK
depends on NETWORK_PHY_TIMESTAMPING
depends on PHYLIB
+ select PTP_1588_CLOCK
---help---
Supports the DP83640 PHYTER with IEEE 1588 features.
@@ -74,8 +72,7 @@ config DP83640_PHY
config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
- depends on PTP_1588_CLOCK
- depends on PCH_GBE
+ select PTP_1588_CLOCK
help
This driver adds support for using the PCH EG20T as a PTP
clock. The hardware supports time stamping of PTP packets
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index e7f301da2902..34a0c607318e 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -21,6 +21,7 @@
#include <linux/posix-clock.h>
#include <linux/poll.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include "ptp_private.h"
@@ -33,9 +34,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
{
struct ptp_clock_caps caps;
struct ptp_clock_request req;
+ struct ptp_sys_offset *sysoff = NULL;
struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
struct ptp_clock_info *ops = ptp->info;
+ struct ptp_clock_time *pct;
+ struct timespec ts;
int enable, err = 0;
+ unsigned int i;
switch (cmd) {
@@ -88,10 +93,45 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
err = ops->enable(ops, &req, enable);
break;
+ case PTP_SYS_OFFSET:
+ sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
+ if (!sysoff) {
+ err = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(sysoff, (void __user *)arg,
+ sizeof(*sysoff))) {
+ err = -EFAULT;
+ break;
+ }
+ if (sysoff->n_samples > PTP_MAX_SAMPLES) {
+ err = -EINVAL;
+ break;
+ }
+ pct = &sysoff->ts[0];
+ for (i = 0; i < sysoff->n_samples; i++) {
+ getnstimeofday(&ts);
+ pct->sec = ts.tv_sec;
+ pct->nsec = ts.tv_nsec;
+ pct++;
+ ptp->info->gettime(ptp->info, &ts);
+ pct->sec = ts.tv_sec;
+ pct->nsec = ts.tv_nsec;
+ pct++;
+ }
+ getnstimeofday(&ts);
+ pct->sec = ts.tv_sec;
+ pct->nsec = ts.tv_nsec;
+ if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff)))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOTTY;
break;
}
+
+ kfree(sysoff);
return err;
}
@@ -104,20 +144,23 @@ unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
}
+#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
+
ssize_t ptp_read(struct posix_clock *pc,
uint rdflags, char __user *buf, size_t cnt)
{
struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
struct timestamp_event_queue *queue = &ptp->tsevq;
- struct ptp_extts_event event[PTP_BUF_TIMESTAMPS];
+ struct ptp_extts_event *event;
unsigned long flags;
size_t qcnt, i;
+ int result;
if (cnt % sizeof(struct ptp_extts_event) != 0)
return -EINVAL;
- if (cnt > sizeof(event))
- cnt = sizeof(event);
+ if (cnt > EXTTS_BUFSIZE)
+ cnt = EXTTS_BUFSIZE;
cnt = cnt / sizeof(struct ptp_extts_event);
@@ -135,6 +178,12 @@ ssize_t ptp_read(struct posix_clock *pc,
return -ENODEV;
}
+ event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
+ if (!event) {
+ mutex_unlock(&ptp->tsevq_mux);
+ return -ENOMEM;
+ }
+
spin_lock_irqsave(&queue->lock, flags);
qcnt = queue_cnt(queue);
@@ -153,8 +202,10 @@ ssize_t ptp_read(struct posix_clock *pc,
mutex_unlock(&ptp->tsevq_mux);
+ result = cnt;
if (copy_to_user(buf, event, cnt))
- return -EFAULT;
+ result = -EFAULT;
- return cnt;
+ kfree(event);
+ return result;
}
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 1c5ab0172ea2..2b557119adad 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
#define pm8607_regulator_dt_init(x, y, z) (-1)
#endif
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+static int pm8607_regulator_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm8607_regulator_info *info = NULL;
@@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+static int pm8607_regulator_remove(struct platform_device *pdev)
{
struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = pm8607_regulator_probe,
- .remove = __devexit_p(pm8607_regulator_remove),
+ .remove = pm8607_regulator_remove,
.id_table = pm8607_regulator_driver_ids,
};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 67d47b59a66d..551a22b07538 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -109,6 +109,16 @@ config REGULATOR_DA9052
This driver supports the voltage regulators of DA9052-BC and
DA9053-AA/Bx PMIC.
+config REGULATOR_DA9055
+ tristate "Dialog Semiconductor DA9055 regulators"
+ depends on MFD_DA9055
+ help
+ Say y here to support the BUCKs and LDOs regulators found on
+ Dialog Semiconductor DA9055 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called da9055-regulator.
+
config REGULATOR_FAN53555
tristate "Fairchild FAN53555 Regulator"
depends on I2C
@@ -204,6 +214,16 @@ config REGULATOR_MAX8952
via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
modes ranging from 0.77V to 1.40V by 0.01V steps.
+config REGULATOR_MAX8973
+ tristate "Maxim MAX8973 voltage regulator "
+ depends on I2C
+ select REGMAP_I2C
+ help
+ The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
+ switching regulator delievers up to 9A of output current. Each
+ phase operates at a 2MHz fixed frequency with a 120 deg shift
+ from the adjacent phase, allowing the use of small magnetic component.
+
config REGULATOR_MAX8997
tristate "Maxim 8997/8966 regulator"
depends on MFD_MAX8997
@@ -335,6 +355,17 @@ config REGULATOR_PALMAS
on the muxing. This is handled automatically in the driver by
reading the mux info from OTP.
+config REGULATOR_TPS51632
+ tristate "TI TPS51632 Power Regulator"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This driver supports TPS51632 voltage regulator chip.
+ The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+ with Serial VID control and DVFS.
+ The voltage output can be configure through I2C interface or PWM
+ interface.
+
config REGULATOR_TPS6105X
tristate "TI TPS6105X Power regulators"
depends on TPS6105X
@@ -415,6 +446,15 @@ config REGULATOR_TPS65912
help
This driver supports TPS65912 voltage regulator chip.
+config REGULATOR_TPS80031
+ tristate "TI TPS80031/TPS80032 power regualtor driver"
+ depends on MFD_TPS80031
+ help
+ TPS80031/ TPS80032 Fully Integrated Power Management with Power
+ Path and Battery Charger. It has 5 configurable step-down
+ converters, 11 general purpose LDOs, VBUS generator and digital
+ output to control regulators.
+
config REGULATOR_TWL4030
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
depends on TWL4030_CORE
@@ -422,6 +462,13 @@ config REGULATOR_TWL4030
This driver supports the voltage regulators provided by
this family of companion chips.
+config REGULATOR_VEXPRESS
+ tristate "Versatile Express regulators"
+ depends on VEXPRESS_CONFIG
+ help
+ This driver provides support for voltage regulators available
+ on the ARM Ltd's Versatile Express platform.
+
config REGULATOR_WM831X
tristate "Wolfson Microelectronics WM831x PMIC regulators"
depends on MFD_WM831X
@@ -450,5 +497,12 @@ config REGULATOR_WM8994
This driver provides support for the voltage regulators on the
WM8994 CODEC.
+config REGULATOR_AS3711
+ tristate "AS3711 PMIC"
+ depends on MFD_AS3711
+ help
+ This driver provides support for the voltage regulators on the
+ AS3711 PMIC
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e431eed8a878..b802b0c7fb02 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
+obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
+obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
+obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
@@ -41,6 +44,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
@@ -56,7 +60,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 167c93f21981..8b5876356db9 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+static int aat2870_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = aat2870_regulator_probe,
- .remove = __devexit_p(aat2870_regulator_remove),
+ .remove = aat2870_regulator_remove,
};
static int __init aat2870_regulator_init(void)
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index df4ad8927f0c..111ec69a3e94 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
* for all the different regulators.
*/
-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
+static int ab3100_regulators_probe(struct platform_device *pdev)
{
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
struct regulator_config config = { };
@@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
+static int ab3100_regulators_remove(struct platform_device *pdev)
{
int i;
@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
.owner = THIS_MODULE,
},
.probe = ab3100_regulators_probe,
- .remove = __devexit_p(ab3100_regulators_remove),
+ .remove = ab3100_regulators_remove,
};
static __init int ab3100_regulators_init(void)
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index e3d1d063025a..09014f38a948 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16),
};
-static __devinit int
+static int
ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
{
int err;
@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
return 0;
}
-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+static int ab8500_regulator_register(struct platform_device *pdev,
struct regulator_init_data *init_data,
int id,
struct device_node *np)
@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
{ .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, },
};
-static __devinit int
+static int
ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
{
int err, i;
@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
return 0;
}
-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
+static int ab8500_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *pdata;
@@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
return 0;
}
-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+static int ab8500_regulator_remove(struct platform_device *pdev)
{
int i;
@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
static struct platform_driver ab8500_regulator_driver = {
.probe = ab8500_regulator_probe,
- .remove = __devexit_p(ab8500_regulator_remove),
+ .remove = ab8500_regulator_remove,
.driver = {
.name = "ab8500-regulator",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index f123f7e3b752..6b981b5faa70 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ad5398_id);
-static int __devinit ad5398_probe(struct i2c_client *client,
+static int ad5398_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regulator_init_data *init_data = client->dev.platform_data;
@@ -256,7 +256,7 @@ err:
return ret;
}
-static int __devexit ad5398_remove(struct i2c_client *client)
+static int ad5398_remove(struct i2c_client *client)
{
struct ad5398_chip_info *chip = i2c_get_clientdata(client);
@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
static struct i2c_driver ad5398_driver = {
.probe = ad5398_probe,
- .remove = __devexit_p(ad5398_remove),
+ .remove = ad5398_remove,
.driver = {
.name = "ad5398",
},
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 1af97686f444..0199eeea63b1 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -48,36 +48,21 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
unsigned selector)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- u32 val, mask;
if (!anatop_reg->control_reg)
return -ENOTSUPP;
- val = anatop_reg->min_bit_val + selector;
- dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
- mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
- anatop_reg->vol_bit_shift;
- val <<= anatop_reg->vol_bit_shift;
- regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
- mask, val);
-
- return 0;
+ return regulator_set_voltage_sel_regmap(reg, selector);
}
static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- u32 val, mask;
if (!anatop_reg->control_reg)
return -ENOTSUPP;
- regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
- mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
- anatop_reg->vol_bit_shift;
- val = (val & mask) >> anatop_reg->vol_bit_shift;
-
- return val - anatop_reg->min_bit_val;
+ return regulator_get_voltage_sel_regmap(reg);
}
static struct regulator_ops anatop_rops = {
@@ -87,7 +72,7 @@ static struct regulator_ops anatop_rops = {
.map_voltage = regulator_map_voltage_linear,
};
-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
+static int anatop_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
@@ -158,15 +143,20 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
goto anatop_probe_end;
}
- rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
- / 25000 + 1;
+ rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1
+ + sreg->min_bit_val;
rdesc->min_uV = sreg->min_voltage;
rdesc->uV_step = 25000;
+ rdesc->linear_min_sel = sreg->min_bit_val;
+ rdesc->vsel_reg = sreg->control_reg;
+ rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
+ sreg->vol_bit_shift;
config.dev = &pdev->dev;
config.init_data = initdata;
config.driver_data = sreg;
config.of_node = pdev->dev.of_node;
+ config.regmap = sreg->anatop;
/* register regulator */
rdev = regulator_register(rdesc, &config);
@@ -186,7 +176,7 @@ anatop_probe_end:
return ret;
}
-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
+static int anatop_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
@@ -210,7 +200,7 @@ static struct platform_driver anatop_regulator_driver = {
.of_match_table = of_anatop_regulator_match_tbl,
},
.probe = anatop_regulator_probe,
- .remove = __devexit_p(anatop_regulator_remove),
+ .remove = anatop_regulator_remove,
};
static int __init anatop_regulator_init(void)
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index d184aa35abcb..ed7beec53af8 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -34,6 +34,108 @@ struct arizona_ldo1 {
struct regulator_init_data init_data;
};
+static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+
+ if (selector == rdev->desc->n_voltages - 1)
+ return 1800000;
+ else
+ return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int sel;
+
+ sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+ if (sel >= rdev->desc->n_voltages)
+ sel = rdev->desc->n_voltages - 1;
+
+ return sel;
+}
+
+static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned sel)
+{
+ struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+ struct regmap *regmap = ldo->arizona->regmap;
+ unsigned int val;
+ int ret;
+
+ if (sel == rdev->desc->n_voltages - 1)
+ val = ARIZONA_LDO1_HI_PWR;
+ else
+ val = 0;
+
+ ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
+ ARIZONA_LDO1_HI_PWR, val);
+ if (ret != 0)
+ return ret;
+
+ ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
+ ARIZONA_SUBSYS_MAX_FREQ, val);
+ if (ret != 0)
+ return ret;
+
+ if (val)
+ return 0;
+
+ val = sel << ARIZONA_LDO1_VSEL_SHIFT;
+
+ return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
+ ARIZONA_LDO1_VSEL_MASK, val);
+}
+
+static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+ struct regmap *regmap = ldo->arizona->regmap;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
+ if (ret != 0)
+ return ret;
+
+ if (val & ARIZONA_LDO1_HI_PWR)
+ return rdev->desc->n_voltages - 1;
+
+ ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
+ if (ret != 0)
+ return ret;
+
+ return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+}
+
+static struct regulator_ops arizona_ldo1_hc_ops = {
+ .list_voltage = arizona_ldo1_hc_list_voltage,
+ .map_voltage = arizona_ldo1_hc_map_voltage,
+ .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
+ .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
+ .get_bypass = regulator_get_bypass_regmap,
+ .set_bypass = regulator_set_bypass_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1_hc = {
+ .name = "LDO1",
+ .supply_name = "LDOVDD",
+ .type = REGULATOR_VOLTAGE,
+ .ops = &arizona_ldo1_hc_ops,
+
+ .bypass_reg = ARIZONA_LDO1_CONTROL_1,
+ .bypass_mask = ARIZONA_LDO1_BYPASS,
+ .min_uV = 900000,
+ .uV_step = 50000,
+ .n_voltages = 8,
+ .enable_time = 500,
+
+ .owner = THIS_MODULE,
+};
+
static struct regulator_ops arizona_ldo1_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
.bypass_mask = ARIZONA_LDO1_BYPASS,
.min_uV = 900000,
.uV_step = 50000,
- .n_voltages = 6,
+ .n_voltages = 7,
+ .enable_time = 500,
.owner = THIS_MODULE,
};
+static const struct regulator_init_data arizona_ldo1_dvfs = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 1800000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+ REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = 1,
+};
+
static const struct regulator_init_data arizona_ldo1_default = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
.num_consumer_supplies = 1,
};
-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+static int arizona_ldo1_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ const struct regulator_desc *desc;
struct regulator_config config = { };
struct arizona_ldo1 *ldo1;
int ret;
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
* default init_data for it. This will be overridden with
* platform data if provided.
*/
- ldo1->init_data = arizona_ldo1_default;
+ switch (arizona->type) {
+ case WM5102:
+ desc = &arizona_ldo1_hc;
+ ldo1->init_data = arizona_ldo1_dvfs;
+ break;
+ default:
+ desc = &arizona_ldo1;
+ ldo1->init_data = arizona_ldo1_default;
+ break;
+ }
+
ldo1->init_data.consumer_supplies = &ldo1->supply;
ldo1->supply.supply = "DCVDD";
ldo1->supply.dev_name = dev_name(arizona->dev);
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
else
config.init_data = &ldo1->init_data;
- ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+ ldo1->regulator = regulator_register(desc, &config);
if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator);
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
return 0;
}
-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+static int arizona_ldo1_remove(struct platform_device *pdev)
{
struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
@@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
static struct platform_driver arizona_ldo1_driver = {
.probe = arizona_ldo1_probe,
- .remove = __devexit_p(arizona_ldo1_remove),
+ .remove = arizona_ldo1_remove,
.driver = {
.name = "arizona-ldo1",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index d9b1f82cc5bd..a6d040cbf8ac 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
.bypass_mask = ARIZONA_CPMIC_BYPASS,
+ .enable_time = 3000,
+
.owner = THIS_MODULE,
};
@@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
.num_consumer_supplies = 1,
};
-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+static int arizona_micsupp_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
@@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
return 0;
}
-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+static int arizona_micsupp_remove(struct platform_device *pdev)
{
struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
@@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
static struct platform_driver arizona_micsupp_driver = {
.probe = arizona_micsupp_probe,
- .remove = __devexit_p(arizona_micsupp_remove),
+ .remove = arizona_micsupp_remove,
.driver = {
.name = "arizona-micsupp",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
new file mode 100644
index 000000000000..2f1341db38a0
--- /dev/null
+++ b/drivers/regulator/as3711-regulator.c
@@ -0,0 +1,369 @@
+/*
+ * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/as3711.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+struct as3711_regulator_info {
+ struct regulator_desc desc;
+ unsigned int max_uV;
+};
+
+struct as3711_regulator {
+ struct as3711_regulator_info *reg_info;
+ struct regulator_dev *rdev;
+};
+
+static int as3711_list_voltage_sd(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+
+ if (!selector)
+ return 0;
+ if (selector < 0x41)
+ return 600000 + selector * 12500;
+ if (selector < 0x71)
+ return 1400000 + (selector - 0x40) * 25000;
+ return 2600000 + (selector - 0x70) * 50000;
+}
+
+static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+
+ if (selector < 0x10)
+ return 1200000 + selector * 50000;
+ return 1800000 + (selector - 0x10) * 100000;
+}
+
+static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (selector >= rdev->desc->n_voltages ||
+ (selector > 0x10 && selector < 0x20))
+ return -EINVAL;
+
+ if (selector < 0x11)
+ return 900000 + selector * 50000;
+ return 1750000 + (selector - 0x20) * 50000;
+}
+
+static int as3711_bound_check(struct regulator_dev *rdev,
+ int *min_uV, int *max_uV)
+{
+ struct as3711_regulator *reg = rdev_get_drvdata(rdev);
+ struct as3711_regulator_info *info = reg->reg_info;
+
+ dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
+ *min_uV, rdev->desc->min_uV, info->max_uV);
+
+ if (*max_uV < *min_uV ||
+ *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
+ return -EINVAL;
+
+ if (rdev->desc->n_voltages == 1)
+ return 0;
+
+ if (*max_uV > info->max_uV)
+ *max_uV = info->max_uV;
+
+ if (*min_uV < rdev->desc->min_uV)
+ *min_uV = rdev->desc->min_uV;
+
+ return *min_uV;
+}
+
+static int as3711_sel_check(int min, int max, int bottom, int step)
+{
+ int sel, voltage;
+
+ /* Round up min, when dividing: keeps us within the range */
+ sel = DIV_ROUND_UP(min - bottom, step);
+ voltage = sel * step + bottom;
+ pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
+ min, max, bottom, step, sel);
+ if (voltage > max)
+ return -EINVAL;
+
+ return sel;
+}
+
+static int as3711_map_voltage_sd(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret;
+
+ ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+ if (ret <= 0)
+ return ret;
+
+ if (min_uV <= 1400000)
+ return as3711_sel_check(min_uV, max_uV, 600000, 12500);
+
+ if (min_uV <= 2600000)
+ return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
+
+ return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
+}
+
+/*
+ * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
+ * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
+ * FAST: sdX_fast=1
+ * NORMAL: low_noise=1
+ * IDLE: low_noise=0
+ */
+
+static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
+{
+ unsigned int fast_bit = rdev->desc->enable_mask,
+ low_noise_bit = fast_bit << 4;
+ u8 val;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = fast_bit | low_noise_bit;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = low_noise_bit;
+ break;
+ case REGULATOR_MODE_IDLE:
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
+ low_noise_bit | fast_bit, val);
+}
+
+static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
+{
+ unsigned int fast_bit = rdev->desc->enable_mask,
+ low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
+ unsigned int val;
+ int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
+
+ if (ret < 0)
+ return ret;
+
+ if ((val & mask) == mask)
+ return REGULATOR_MODE_FAST;
+
+ if ((val & mask) == low_noise_bit)
+ return REGULATOR_MODE_NORMAL;
+
+ if (!(val & mask))
+ return REGULATOR_MODE_IDLE;
+
+ return -EINVAL;
+}
+
+static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret;
+
+ ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+ if (ret <= 0)
+ return ret;
+
+ if (min_uV <= 1800000)
+ return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
+
+ return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
+}
+
+static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret;
+
+ ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+ if (ret <= 0)
+ return ret;
+
+ if (min_uV <= 1700000)
+ return as3711_sel_check(min_uV, max_uV, 900000, 50000);
+
+ return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
+}
+
+static struct regulator_ops as3711_sd_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = as3711_list_voltage_sd,
+ .map_voltage = as3711_map_voltage_sd,
+ .get_mode = as3711_get_mode_sd,
+ .set_mode = as3711_set_mode_sd,
+};
+
+static struct regulator_ops as3711_aldo_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = as3711_list_voltage_aldo,
+ .map_voltage = as3711_map_voltage_aldo,
+};
+
+static struct regulator_ops as3711_dldo_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = as3711_list_voltage_dldo,
+ .map_voltage = as3711_map_voltage_dldo,
+};
+
+#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \
+ [AS3711_REGULATOR_ ## _id] = { \
+ .desc = { \
+ .name = "as3711-regulator-" # _id, \
+ .id = AS3711_REGULATOR_ ## _id, \
+ .n_voltages = (_vmask + 1), \
+ .ops = &as3711_ ## _sfx ## _ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \
+ .vsel_mask = _vmask << _vshift, \
+ .enable_reg = AS3711_ ## _en_reg, \
+ .enable_mask = BIT(_en_bit), \
+ .min_uV = _min_uV, \
+ }, \
+ .max_uV = _max_uV, \
+}
+
+static struct as3711_regulator_info as3711_reg_info[] = {
+ AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
+ AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
+ AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
+ AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
+ AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+ AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+ AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+ /* StepUp output voltage depends on supplying regulator */
+};
+
+#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+
+static int as3711_regulator_probe(struct platform_device *pdev)
+{
+ struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
+ struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_init_data *reg_data;
+ struct regulator_config config = {.dev = &pdev->dev,};
+ struct as3711_regulator *reg = NULL;
+ struct as3711_regulator *regs;
+ struct regulator_dev *rdev;
+ struct as3711_regulator_info *ri;
+ int ret;
+ int id;
+
+ if (!pdata)
+ dev_dbg(&pdev->dev, "No platform data...\n");
+
+ regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
+ sizeof(struct as3711_regulator), GFP_KERNEL);
+ if (!regs) {
+ dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+ return -ENOMEM;
+ }
+
+ for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
+ reg_data = pdata ? pdata->init_data[id] : NULL;
+
+ /* No need to register if there is no regulator data */
+ if (!ri->desc.name)
+ continue;
+
+ reg = &regs[id];
+ reg->reg_info = ri;
+
+ config.init_data = reg_data;
+ config.driver_data = reg;
+ config.regmap = as3711->regmap;
+
+ rdev = regulator_register(&ri->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register regulator %s\n",
+ ri->desc.name);
+ ret = PTR_ERR(rdev);
+ goto eregreg;
+ }
+ reg->rdev = rdev;
+ }
+ platform_set_drvdata(pdev, regs);
+ return 0;
+
+eregreg:
+ while (--id >= 0)
+ regulator_unregister(regs[id].rdev);
+
+ return ret;
+}
+
+static int as3711_regulator_remove(struct platform_device *pdev)
+{
+ struct as3711_regulator *regs = platform_get_drvdata(pdev);
+ int id;
+
+ for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
+ regulator_unregister(regs[id].rdev);
+ return 0;
+}
+
+static struct platform_driver as3711_regulator_driver = {
+ .driver = {
+ .name = "as3711-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = as3711_regulator_probe,
+ .remove = as3711_regulator_remove,
+};
+
+static int __init as3711_regulator_init(void)
+{
+ return platform_driver_register(&as3711_regulator_driver);
+}
+subsys_initcall(as3711_regulator_init);
+
+static void __exit as3711_regulator_exit(void)
+{
+ platform_driver_unregister(&as3711_regulator_driver);
+}
+module_exit(as3711_regulator_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 regulator driver");
+MODULE_ALIAS("platform:as3711-regulator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e872c8be080e..0f65b246cc0c 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
*min_uV = regulator->min_uV;
}
- if (*min_uV > *max_uV)
+ if (*min_uV > *max_uV) {
+ dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
+ regulator->min_uV, regulator->max_uV);
return -EINVAL;
+ }
return 0;
}
@@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
/* final: [min_uV..max_uV] valid iff constraints valid */
if (max_uV < min_uV) {
- rdev_err(rdev, "unsupportable voltage constraints\n");
+ rdev_err(rdev,
+ "unsupportable voltage constraints %u-%uuV\n",
+ min_uV, max_uV);
return -EINVAL;
}
@@ -1867,6 +1872,28 @@ int regulator_is_enabled(struct regulator *regulator)
EXPORT_SYMBOL_GPL(regulator_is_enabled);
/**
+ * regulator_can_change_voltage - check if regulator can change voltage
+ * @regulator: regulator source
+ *
+ * Returns positive if the regulator driver backing the source/client
+ * can change its voltage, false otherwise. Usefull for detecting fixed
+ * or dummy regulators and disabling voltage change logic in the client
+ * driver.
+ */
+int regulator_can_change_voltage(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+
+ if (rdev->constraints &&
+ rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
+ (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
+
+/**
* regulator_count_voltages - count regulator_list_voltage() selectors
* @regulator: regulator source
*
@@ -1897,6 +1924,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
{
if (selector >= rdev->desc->n_voltages)
return -EINVAL;
+ if (selector < rdev->desc->linear_min_sel)
+ return 0;
+
+ selector -= rdev->desc->linear_min_sel;
return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
}
@@ -1985,6 +2016,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
return ret;
}
+ /* Any voltage within constrains range is fine? */
+ if (rdev->desc->continuous_voltage_range)
+ return min_uV >= rdev->constraints->min_uV &&
+ max_uV <= rdev->constraints->max_uV;
+
ret = regulator_count_voltages(regulator);
if (ret < 0)
return ret;
@@ -2120,6 +2156,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
if (ret < 0)
return ret;
+ ret += rdev->desc->linear_min_sel;
+
/* Map back into a voltage to verify we're still in bounds */
voltage = rdev->desc->ops->list_voltage(rdev, ret);
if (voltage < min_uV || voltage > max_uV)
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 36c5b92fe0af..2afa5730f324 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
return NULL;
}
-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+static int da903x_regulator_probe(struct platform_device *pdev)
{
struct da903x_regulator_info *ri = NULL;
struct regulator_dev *rdev;
@@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+static int da903x_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = da903x_regulator_probe,
- .remove = __devexit_p(da903x_regulator_remove),
+ .remove = da903x_regulator_remove,
};
static int __init da903x_regulator_init(void)
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 27355b1199e5..d0963090442d 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
else if (offset == 0)
row = 1;
- if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
- max_uA < da9052_current_limits[row][DA9052_MIN_UA])
- return -EINVAL;
-
for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
- if (da9052_current_limits[row][i] <= max_uA) {
+ if ((min_uA <= da9052_current_limits[row][i]) &&
+ (da9052_current_limits[row][i] <= max_uA)) {
reg_val = i;
break;
}
}
+ if (i < 0)
+ return -EINVAL;
+
/* Determine the even or odd position of the buck current limit
* register field
*/
@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
return NULL;
}
-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+static int da9052_regulator_probe(struct platform_device *pdev)
{
struct regulator_config config = { };
struct da9052_regulator *regulator;
@@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+static int da9052_regulator_remove(struct platform_device *pdev)
{
struct da9052_regulator *regulator = platform_get_drvdata(pdev);
@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
static struct platform_driver da9052_regulator_driver = {
.probe = da9052_regulator_probe,
- .remove = __devexit_p(da9052_regulator_remove),
+ .remove = da9052_regulator_remove,
.driver = {
.name = "da9052-regulator",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
new file mode 100644
index 000000000000..a4b9cb8c4317
--- /dev/null
+++ b/drivers/regulator/da9055-regulator.c
@@ -0,0 +1,641 @@
+/*
+* Regulator driver for DA9055 PMIC
+*
+* Copyright(c) 2012 Dialog Semiconductor Ltd.
+*
+* Author: David Dajun Chen <dchen@diasemi.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/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_MIN_UA 0
+#define DA9055_MAX_UA 3
+
+#define DA9055_LDO_MODE_SYNC 0
+#define DA9055_LDO_MODE_SLEEP 1
+
+#define DA9055_BUCK_MODE_SLEEP 1
+#define DA9055_BUCK_MODE_SYNC 2
+#define DA9055_BUCK_MODE_AUTO 3
+
+/* DA9055 REGULATOR IDs */
+#define DA9055_ID_BUCK1 0
+#define DA9055_ID_BUCK2 1
+#define DA9055_ID_LDO1 2
+#define DA9055_ID_LDO2 3
+#define DA9055_ID_LDO3 4
+#define DA9055_ID_LDO4 5
+#define DA9055_ID_LDO5 6
+#define DA9055_ID_LDO6 7
+
+/* DA9055 BUCK current limit */
+static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+
+struct da9055_conf_reg {
+ int reg;
+ int sel_mask;
+ int en_mask;
+};
+
+struct da9055_volt_reg {
+ int reg_a;
+ int reg_b;
+ int sl_shift;
+ int v_mask;
+ int v_shift;
+};
+
+struct da9055_mode_reg {
+ int reg;
+ int mask;
+ int shift;
+};
+
+struct da9055_regulator_info {
+ struct regulator_desc reg_desc;
+ struct da9055_conf_reg conf;
+ struct da9055_volt_reg volt;
+ struct da9055_mode_reg mode;
+};
+
+struct da9055_regulator {
+ struct da9055 *da9055;
+ struct da9055_regulator_info *info;
+ struct regulator_dev *rdev;
+ enum gpio_select reg_rselect;
+};
+
+static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int ret, mode = 0;
+
+ ret = da9055_reg_read(regulator->da9055, info->mode.reg);
+ if (ret < 0)
+ return ret;
+
+ switch ((ret & info->mode.mask) >> info->mode.shift) {
+ case DA9055_BUCK_MODE_SYNC:
+ mode = REGULATOR_MODE_FAST;
+ break;
+ case DA9055_BUCK_MODE_AUTO:
+ mode = REGULATOR_MODE_NORMAL;
+ break;
+ case DA9055_BUCK_MODE_SLEEP:
+ mode = REGULATOR_MODE_STANDBY;
+ break;
+ }
+
+ return mode;
+}
+
+static int da9055_buck_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int val = 0;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
+ break;
+ }
+
+ return da9055_reg_update(regulator->da9055, info->mode.reg,
+ info->mode.mask, val);
+}
+
+static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int ret;
+
+ ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
+ if (ret < 0)
+ return ret;
+
+ if (ret >> info->volt.sl_shift)
+ return REGULATOR_MODE_STANDBY;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ struct da9055_volt_reg volt = info->volt;
+ int val = 0;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ case REGULATOR_MODE_FAST:
+ val = DA9055_LDO_MODE_SYNC;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val = DA9055_LDO_MODE_SLEEP;
+ break;
+ }
+
+ return da9055_reg_update(regulator->da9055, volt.reg_b,
+ 1 << volt.sl_shift,
+ val << volt.sl_shift);
+}
+
+static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int ret;
+
+ ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
+ if (ret < 0)
+ return ret;
+
+ ret &= info->mode.mask;
+ return da9055_current_limits[ret >> info->mode.shift];
+}
+
+static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
+ int max_uA)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int i;
+
+ for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
+ if ((min_uA <= da9055_current_limits[i]) &&
+ (da9055_current_limits[i] <= max_uA))
+ return da9055_reg_update(regulator->da9055,
+ DA9055_REG_BUCK_LIM,
+ info->mode.mask,
+ i << info->mode.shift);
+ }
+
+ return -EINVAL;
+}
+
+static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ struct da9055_volt_reg volt = info->volt;
+ int ret, sel;
+
+ /*
+ * There are two voltage register set A & B for voltage ramping but
+ * either one of then can be active therefore we first determine
+ * the active register set.
+ */
+ ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+ if (ret < 0)
+ return ret;
+
+ ret &= info->conf.sel_mask;
+
+ /* Get the voltage for the active register set A/B */
+ if (ret == DA9055_REGUALTOR_SET_A)
+ ret = da9055_reg_read(regulator->da9055, volt.reg_a);
+ else
+ ret = da9055_reg_read(regulator->da9055, volt.reg_b);
+
+ if (ret < 0)
+ return ret;
+
+ sel = (ret & volt.v_mask);
+ return sel;
+}
+
+static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int ret;
+
+ /*
+ * Regulator register set A/B is not selected through GPIO therefore
+ * we use default register set A for voltage ramping.
+ */
+ if (regulator->reg_rselect == NO_GPIO) {
+ /* Select register set A */
+ ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+ info->conf.sel_mask, DA9055_SEL_REG_A);
+ if (ret < 0)
+ return ret;
+
+ /* Set the voltage */
+ return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+ info->volt.v_mask, selector);
+ }
+
+ /*
+ * Here regulator register set A/B is selected through GPIO.
+ * Therefore we first determine the selected register set A/B and
+ * then set the desired voltage for that register set A/B.
+ */
+ ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+ if (ret < 0)
+ return ret;
+
+ ret &= info->conf.sel_mask;
+
+ /* Set the voltage */
+ if (ret == DA9055_REGUALTOR_SET_A)
+ return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+ info->volt.v_mask, selector);
+ else
+ return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+ info->volt.v_mask, selector);
+}
+
+static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
+ int uV)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+ int ret;
+
+ /* Select register set B for suspend voltage ramping. */
+ if (regulator->reg_rselect == NO_GPIO) {
+ ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+ info->conf.sel_mask, DA9055_SEL_REG_B);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = regulator_map_voltage_linear(rdev, uV, uV);
+ if (ret < 0)
+ return ret;
+
+ return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+ info->volt.v_mask, ret);
+}
+
+static int da9055_suspend_enable(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+
+ /* Select register set B for voltage ramping. */
+ if (regulator->reg_rselect == NO_GPIO)
+ return da9055_reg_update(regulator->da9055, info->conf.reg,
+ info->conf.sel_mask, DA9055_SEL_REG_B);
+ else
+ return 0;
+}
+
+static int da9055_suspend_disable(struct regulator_dev *rdev)
+{
+ struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+ struct da9055_regulator_info *info = regulator->info;
+
+ /* Diselect register set B. */
+ if (regulator->reg_rselect == NO_GPIO)
+ return da9055_reg_update(regulator->da9055, info->conf.reg,
+ info->conf.sel_mask, DA9055_SEL_REG_A);
+ else
+ return 0;
+}
+
+static struct regulator_ops da9055_buck_ops = {
+ .get_mode = da9055_buck_get_mode,
+ .set_mode = da9055_buck_set_mode,
+
+ .get_current_limit = da9055_buck_get_current_limit,
+ .set_current_limit = da9055_buck_set_current_limit,
+
+ .get_voltage_sel = da9055_regulator_get_voltage_sel,
+ .set_voltage_sel = da9055_regulator_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+
+ .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+ .set_suspend_enable = da9055_suspend_enable,
+ .set_suspend_disable = da9055_suspend_disable,
+ .set_suspend_mode = da9055_buck_set_mode,
+};
+
+static struct regulator_ops da9055_ldo_ops = {
+ .get_mode = da9055_ldo_get_mode,
+ .set_mode = da9055_ldo_set_mode,
+
+ .get_voltage_sel = da9055_regulator_get_voltage_sel,
+ .set_voltage_sel = da9055_regulator_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+
+ .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+ .set_suspend_enable = da9055_suspend_enable,
+ .set_suspend_disable = da9055_suspend_disable,
+ .set_suspend_mode = da9055_ldo_set_mode,
+
+};
+
+#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
+{\
+ .reg_desc = {\
+ .name = #_id,\
+ .ops = &da9055_ldo_ops,\
+ .type = REGULATOR_VOLTAGE,\
+ .id = DA9055_ID_##_id,\
+ .n_voltages = (max - min) / step + 1 + (voffset), \
+ .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+ .enable_mask = 1, \
+ .min_uV = (min) * 1000,\
+ .uV_step = (step) * 1000,\
+ .linear_min_sel = (voffset),\
+ .owner = THIS_MODULE,\
+ },\
+ .conf = {\
+ .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+ .sel_mask = (1 << 4),\
+ .en_mask = 1,\
+ },\
+ .volt = {\
+ .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+ .sl_shift = 7,\
+ .v_mask = (1 << (vbits)) - 1,\
+ .v_shift = (vbits),\
+ },\
+}
+
+#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
+{\
+ .reg_desc = {\
+ .name = #_id,\
+ .ops = &da9055_buck_ops,\
+ .type = REGULATOR_VOLTAGE,\
+ .id = DA9055_ID_##_id,\
+ .n_voltages = (max - min) / step + 1 + (voffset), \
+ .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+ .enable_mask = 1,\
+ .min_uV = (min) * 1000,\
+ .uV_step = (step) * 1000,\
+ .linear_min_sel = (voffset),\
+ .owner = THIS_MODULE,\
+ },\
+ .conf = {\
+ .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+ .sel_mask = (1 << 4),\
+ .en_mask = 1,\
+ },\
+ .volt = {\
+ .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+ .sl_shift = 7,\
+ .v_mask = (1 << (vbits)) - 1,\
+ .v_shift = (vbits),\
+ },\
+ .mode = {\
+ .reg = DA9055_REG_BCORE_MODE,\
+ .mask = (mbits),\
+ .shift = (sbits),\
+ },\
+}
+
+static struct da9055_regulator_info da9055_regulator_info[] = {
+ DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
+ DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
+ DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
+ DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
+ DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
+ DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
+ DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
+ DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
+};
+
+/*
+ * Configures regulator to be controlled either through GPIO 1 or 2.
+ * GPIO can control regulator state and/or select the regulator register
+ * set A/B for voltage ramping.
+ */
+static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
+ struct regulator_config *config,
+ struct da9055_pdata *pdata, int id)
+{
+ struct da9055_regulator_info *info = regulator->info;
+ int ret = 0;
+
+ if (pdata->gpio_ren && pdata->gpio_ren[id]) {
+ char name[18];
+ int gpio_mux = pdata->gpio_ren[id];
+
+ config->ena_gpio = pdata->ena_gpio[id];
+ config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+ config->ena_gpio_invert = 1;
+
+ /*
+ * GPI pin is muxed with regulator to control the
+ * regulator state.
+ */
+ sprintf(name, "DA9055 GPI %d", gpio_mux);
+ ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+ name);
+ if (ret < 0)
+ goto err;
+
+ /*
+ * Let the regulator know that its state is controlled
+ * through GPI.
+ */
+ ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+ DA9055_E_GPI_MASK,
+ pdata->reg_ren[id]
+ << DA9055_E_GPI_SHIFT);
+ if (ret < 0)
+ goto err;
+ }
+
+ if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
+ char name[18];
+ int gpio_mux = pdata->gpio_rsel[id];
+
+ regulator->reg_rselect = pdata->reg_rsel[id];
+
+ /*
+ * GPI pin is muxed with regulator to select the
+ * regulator register set A/B for voltage ramping.
+ */
+ sprintf(name, "DA9055 GPI %d", gpio_mux);
+ ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+ name);
+ if (ret < 0)
+ goto err;
+
+ /*
+ * Let the regulator know that its register set A/B
+ * will be selected through GPI for voltage ramping.
+ */
+ ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+ DA9055_V_GPI_MASK,
+ pdata->reg_rsel[id]
+ << DA9055_V_GPI_SHIFT);
+ }
+
+err:
+ return ret;
+}
+
+static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
+{
+ struct da9055_regulator *regulator = data;
+
+ regulator_notifier_call_chain(regulator->rdev,
+ REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static inline struct da9055_regulator_info *find_regulator_info(int id)
+{
+ struct da9055_regulator_info *info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
+ info = &da9055_regulator_info[i];
+ if (info->reg_desc.id == id)
+ return info;
+ }
+
+ return NULL;
+}
+
+static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = { };
+ struct da9055_regulator *regulator;
+ struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+ struct da9055_pdata *pdata = da9055->dev->platform_data;
+ int ret, irq;
+
+ if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
+ return -ENODEV;
+
+ regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
+ GFP_KERNEL);
+ if (!regulator)
+ return -ENOMEM;
+
+ regulator->info = find_regulator_info(pdev->id);
+ if (regulator->info == NULL) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ return -EINVAL;
+ }
+
+ regulator->da9055 = da9055;
+ config.dev = &pdev->dev;
+ config.driver_data = regulator;
+ config.regmap = da9055->regmap;
+
+ if (pdata && pdata->regulators)
+ config.init_data = pdata->regulators[pdev->id];
+
+ ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
+ if (ret < 0)
+ return ret;
+
+ regulator->rdev = regulator_register(&regulator->info->reg_desc,
+ &config);
+ if (IS_ERR(regulator->rdev)) {
+ dev_err(&pdev->dev, "Failed to register regulator %s\n",
+ regulator->info->reg_desc.name);
+ ret = PTR_ERR(regulator->rdev);
+ return ret;
+ }
+
+ /* Only LDO 5 and 6 has got the over current interrupt */
+ if (pdev->id == DA9055_ID_LDO5 || pdev->id == DA9055_ID_LDO6) {
+ irq = platform_get_irq_byname(pdev, "REGULATOR");
+ irq = regmap_irq_get_virq(da9055->irq_data, irq);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ da9055_ldo5_6_oc_irq,
+ IRQF_TRIGGER_HIGH |
+ IRQF_ONESHOT |
+ IRQF_PROBE_SHARED,
+ pdev->name, regulator);
+ if (ret != 0) {
+ if (ret != -EBUSY) {
+ dev_err(&pdev->dev,
+ "Failed to request Regulator IRQ %d: %d\n",
+ irq, ret);
+ goto err_regulator;
+ }
+ }
+ }
+
+ platform_set_drvdata(pdev, regulator);
+
+ return 0;
+
+err_regulator:
+ regulator_unregister(regulator->rdev);
+ return ret;
+}
+
+static int __devexit da9055_regulator_remove(struct platform_device *pdev)
+{
+ struct da9055_regulator *regulator = platform_get_drvdata(pdev);
+
+ regulator_unregister(regulator->rdev);
+
+ return 0;
+}
+
+static struct platform_driver da9055_regulator_driver = {
+ .probe = da9055_regulator_probe,
+ .remove = __devexit_p(da9055_regulator_remove),
+ .driver = {
+ .name = "da9055-regulator",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9055_regulator_init(void)
+{
+ return platform_driver_register(&da9055_regulator_driver);
+}
+subsys_initcall(da9055_regulator_init);
+
+static void __exit da9055_regulator_exit(void)
+{
+ platform_driver_unregister(&da9055_regulator_driver);
+}
+module_exit(da9055_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-regulator");
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 359f8d18fc3f..219d162b651e 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
},
};
-static __devinit int db8500_regulator_register(struct platform_device *pdev,
+static int db8500_regulator_register(struct platform_device *pdev,
struct regulator_init_data *init_data,
int id,
struct device_node *np)
@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
{ .name = "db8500_esram34_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
};
-static __devinit int
+static int
db8500_regulator_of_probe(struct platform_device *pdev,
struct device_node *np)
{
@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
return 0;
}
-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
+static int db8500_regulator_probe(struct platform_device *pdev)
{
struct regulator_init_data *db8500_init_data =
dev_get_platdata(&pdev->dev);
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index f2e5ecdc5864..261f3d2299bc 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
return 0;
}
-int __devinit
+int
ux500_regulator_debug_init(struct platform_device *pdev,
struct dbx500_regulator_info *regulator_info,
int num_regulators)
@@ -230,7 +230,7 @@ exit_no_debugfs:
return -ENOMEM;
}
-int __devexit ux500_regulator_debug_exit(void)
+int ux500_regulator_debug_exit(void)
{
debugfs_remove_recursive(rdebug.dir);
kfree(rdebug.state_after_suspend);
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 03a1d7c11ef2..df9f42524abb 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
.ops = &dummy_ops,
};
-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+static int dummy_regulator_probe(struct platform_device *pdev)
{
struct regulator_config config = { };
int ret;
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 339f4d732e97..9165b0c40ed3 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
.val_bits = 8,
};
-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+static int fan53555_regulator_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fan53555_device_info *di;
@@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
}
-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+static int fan53555_regulator_remove(struct i2c_client *client)
{
struct fan53555_device_info *di = i2c_get_clientdata(client);
@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
.name = "fan53555-regulator",
},
.probe = fan53555_regulator_probe,
- .remove = __devexit_p(fan53555_regulator_remove),
+ .remove = fan53555_regulator_remove,
.id_table = fan53555_id,
};
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 185468c4d38f..48d5b7608b00 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
.list_voltage = fixed_voltage_list_voltage,
};
-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
+static int reg_fixed_voltage_probe(struct platform_device *pdev)
{
struct fixed_voltage_config *config;
struct fixed_voltage_data *drvdata;
@@ -234,7 +234,7 @@ err:
return ret;
}
-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
+static int reg_fixed_voltage_remove(struct platform_device *pdev)
{
struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
static struct platform_driver regulator_fixed_voltage_driver = {
.probe = reg_fixed_voltage_probe,
- .remove = __devexit_p(reg_fixed_voltage_remove),
+ .remove = reg_fixed_voltage_remove,
.driver = {
.name = "reg-fixed-voltage",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 8b5944f2d7d1..8ae288fc150b 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -28,9 +28,12 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/regulator/gpio-regulator.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
struct gpio_regulator_data {
struct regulator_desc desc;
@@ -79,7 +82,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value(data->gpios[ptr].gpio, state);
+ gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
}
data->state = target;
@@ -116,7 +119,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value(data->gpios[ptr].gpio, state);
+ gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
}
data->state = target;
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
.list_voltage = gpio_regulator_list_voltage,
};
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+ struct gpio_regulator_config *config;
+ struct property *prop;
+ const char *regtype;
+ int proplen, gpio, i;
+
+ config = devm_kzalloc(dev,
+ sizeof(struct gpio_regulator_config),
+ GFP_KERNEL);
+ if (!config)
+ return ERR_PTR(-ENOMEM);
+
+ config->init_data = of_get_regulator_init_data(dev, np);
+ if (!config->init_data)
+ return ERR_PTR(-EINVAL);
+
+ config->supply_name = config->init_data->constraints.name;
+
+ if (of_property_read_bool(np, "enable-active-high"))
+ config->enable_high = true;
+
+ if (of_property_read_bool(np, "enable-at-boot"))
+ config->enabled_at_boot = true;
+
+ of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+ config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+ /* Fetch GPIOs. */
+ for (i = 0; ; i++)
+ if (of_get_named_gpio(np, "gpios", i) < 0)
+ break;
+ config->nr_gpios = i;
+
+ config->gpios = devm_kzalloc(dev,
+ sizeof(struct gpio) * config->nr_gpios,
+ GFP_KERNEL);
+ if (!config->gpios)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < config->nr_gpios; i++) {
+ gpio = of_get_named_gpio(np, "gpios", i);
+ if (gpio < 0)
+ break;
+ config->gpios[i].gpio = gpio;
+ }
+
+ /* Fetch states. */
+ prop = of_find_property(np, "states", NULL);
+ if (!prop) {
+ dev_err(dev, "No 'states' property found\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ proplen = prop->length / sizeof(int);
+
+ config->states = devm_kzalloc(dev,
+ sizeof(struct gpio_regulator_state)
+ * (proplen / 2),
+ GFP_KERNEL);
+ if (!config->states)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < proplen / 2; i++) {
+ config->states[i].value =
+ be32_to_cpup((int *)prop->value + (i * 2));
+ config->states[i].gpios =
+ be32_to_cpup((int *)prop->value + (i * 2 + 1));
+ }
+ config->nr_states = i;
+
+ of_property_read_string(np, "regulator-type", &regtype);
+
+ if (!strncmp("voltage", regtype, 7))
+ config->type = REGULATOR_VOLTAGE;
+ else if (!strncmp("current", regtype, 7))
+ config->type = REGULATOR_CURRENT;
+
+ return config;
+}
+
static struct regulator_ops gpio_regulator_current_ops = {
.get_current_limit = gpio_regulator_get_value,
.set_current_limit = gpio_regulator_set_current_limit,
};
-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+static int gpio_regulator_probe(struct platform_device *pdev)
{
struct gpio_regulator_config *config = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
struct gpio_regulator_data *drvdata;
struct regulator_config cfg = { };
int ptr, ret, state;
+ if (np) {
+ config = of_get_gpio_regulator_config(&pdev->dev, np);
+ if (IS_ERR(config))
+ return PTR_ERR(config);
+ }
+
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL);
if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
cfg.dev = &pdev->dev;
cfg.init_data = config->init_data;
cfg.driver_data = drvdata;
+ cfg.of_node = np;
if (config->enable_gpio >= 0)
cfg.ena_gpio = config->enable_gpio;
@@ -254,7 +348,7 @@ err:
return ret;
}
-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+static int gpio_regulator_remove(struct platform_device *pdev)
{
struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
@@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_OF)
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+ { .compatible = "regulator-gpio", },
+ {},
+};
+#endif
+
static struct platform_driver gpio_regulator_driver = {
.probe = gpio_regulator_probe,
- .remove = __devexit_p(gpio_regulator_remove),
+ .remove = gpio_regulator_remove,
.driver = {
.name = "gpio-regulator",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(regulator_gpio_of_match),
},
};
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index d8ecf49a5777..d1e5bee2a26b 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
},
};
-static int __devinit isl6271a_probe(struct i2c_client *i2c,
+static int isl6271a_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regulator_config config = { };
@@ -151,7 +151,7 @@ error:
return err;
}
-static int __devexit isl6271a_remove(struct i2c_client *i2c)
+static int isl6271a_remove(struct i2c_client *i2c)
{
struct isl_pmic *pmic = i2c_get_clientdata(i2c);
int i;
@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = isl6271a_probe,
- .remove = __devexit_p(isl6271a_remove),
+ .remove = isl6271a_remove,
.id_table = isl6271a_id,
};
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 7c6e3b8ff484..5f68ff11a298 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
return ret;
}
-static int __devinit setup_regulators(struct lp3971 *lp3971,
+static int setup_regulators(struct lp3971 *lp3971,
struct lp3971_platform_data *pdata)
{
int i, err;
@@ -429,7 +429,7 @@ err_nomem:
return err;
}
-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
+static int lp3971_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct lp3971 *lp3971;
@@ -472,7 +472,7 @@ err_detect:
return ret;
}
-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
+static int lp3971_i2c_remove(struct i2c_client *i2c)
{
struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
int i;
@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lp3971_i2c_probe,
- .remove = __devexit_p(lp3971_i2c_remove),
+ .remove = lp3971_i2c_remove,
.id_table = lp3971_i2c_id,
};
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 3cdc755d9b22..69c42c318b87 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
},
};
-static int __devinit setup_regulators(struct lp3972 *lp3972,
+static int setup_regulators(struct lp3972 *lp3972,
struct lp3972_platform_data *pdata)
{
int i, err;
@@ -523,7 +523,7 @@ err_nomem:
return err;
}
-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
+static int lp3972_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct lp3972 *lp3972;
@@ -569,7 +569,7 @@ err_detect:
return ret;
}
-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
+static int lp3972_i2c_remove(struct i2c_client *i2c)
{
struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
int i;
@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lp3972_i2c_probe,
- .remove = __devexit_p(lp3972_i2c_remove),
+ .remove = lp3972_i2c_remove,
.id_table = lp3972_i2c_id,
};
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 708f4b6a17dc..9289ead715ca 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -893,7 +893,7 @@ err_dev:
return ret;
}
-static int __devexit lp872x_remove(struct i2c_client *cl)
+static int lp872x_remove(struct i2c_client *cl)
{
struct lp872x *lp = i2c_get_clientdata(cl);
@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
.owner = THIS_MODULE,
},
.probe = lp872x_probe,
- .remove = __devexit_p(lp872x_remove),
+ .remove = lp872x_remove,
.id_table = lp872x_ids,
};
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index ba3e0aa402de..aef3f2b0c5ea 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -429,18 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
},
};
-static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
-{
- struct device *dev = buck->lp->dev;
-
- if (!gpio_is_valid(gpio)) {
- dev_err(dev, "invalid gpio: %d\n", gpio);
- return -EINVAL;
- }
-
- return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
-}
-
static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
enum lp8788_buck_id id)
{
@@ -452,7 +440,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
switch (id) {
case BUCK1:
gpio = pdata->buck1_dvs->gpio;
- ret = _gpio_request(buck, gpio, b1_name);
+ ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW,
+ b1_name);
if (ret)
return ret;
@@ -461,7 +450,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
case BUCK2:
for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
gpio = pdata->buck2_dvs->gpio[i];
- ret = _gpio_request(buck, gpio, b2_name[i]);
+ ret = devm_gpio_request_one(buck->lp->dev, gpio,
+ DVS_LOW, b2_name[i]);
if (ret)
return ret;
}
@@ -504,7 +494,7 @@ set_default_dvs_mode:
default_dvs_mode[id]);
}
-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+static int lp8788_buck_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
int id = pdev->id;
@@ -542,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+static int lp8788_buck_remove(struct platform_device *pdev)
{
struct lp8788_buck *buck = platform_get_drvdata(pdev);
@@ -554,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
static struct platform_driver lp8788_buck_driver = {
.probe = lp8788_buck_probe,
- .remove = __devexit_p(lp8788_buck_remove),
+ .remove = lp8788_buck_remove,
.driver = {
.name = LP8788_DEV_BUCK,
.owner = THIS_MODULE,
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 6796eeb47dc6..3792741708ce 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -126,7 +126,7 @@ struct lp8788_ldo {
};
/* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
@@ -662,14 +662,6 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
[EN_DLDO7] = LP8788_EN_SEL_DLDO7_M,
[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
};
- u8 val[] = {
- [EN_ALDO1] = 0 << 5,
- [EN_ALDO234] = 0 << 4,
- [EN_ALDO5] = 0 << 3,
- [EN_ALDO7] = 0 << 2,
- [EN_DLDO7] = 0 << 1,
- [EN_DLDO911] = 0 << 0,
- };
switch (id) {
case DLDO7:
@@ -708,11 +700,10 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
return ret;
set_default_ldo_enable_mode:
- return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
- val[enable_id]);
+ return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
}
-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+static int lp8788_dldo_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
int id = pdev->id;
@@ -749,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+static int lp8788_dldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
@@ -761,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
static struct platform_driver lp8788_dldo_driver = {
.probe = lp8788_dldo_probe,
- .remove = __devexit_p(lp8788_dldo_remove),
+ .remove = lp8788_dldo_remove,
.driver = {
.name = LP8788_DEV_DLDO,
.owner = THIS_MODULE,
},
};
-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+static int lp8788_aldo_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
int id = pdev->id;
@@ -805,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+static int lp8788_aldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
@@ -817,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
static struct platform_driver lp8788_aldo_driver = {
.probe = lp8788_aldo_probe,
- .remove = __devexit_p(lp8788_aldo_remove),
+ .remove = lp8788_aldo_remove,
.driver = {
.name = LP8788_DEV_ALDO,
.owner = THIS_MODULE,
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index f67af3c1b963..8c5a54f541b5 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -44,6 +44,9 @@ struct max1586_data {
unsigned int min_uV;
unsigned int max_uV;
+ unsigned int v3_curr_sel;
+ unsigned int v6_curr_sel;
+
struct regulator_dev *rdev[0];
};
@@ -63,31 +66,60 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
* R24 and R25=100kOhm as described in the data sheet.
* The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
*/
+static int max1586_v3_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+ return max1586->v3_curr_sel;
+}
+
static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
unsigned selector)
{
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
struct i2c_client *client = max1586->client;
+ int ret;
u8 v3_prog;
dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
regulator_list_voltage_linear(rdev, selector) / 1000);
v3_prog = I2C_V3_SELECT | (u8) selector;
- return i2c_smbus_write_byte(client, v3_prog);
+ ret = i2c_smbus_write_byte(client, v3_prog);
+ if (ret)
+ return ret;
+
+ max1586->v3_curr_sel = selector;
+
+ return 0;
+}
+
+static int max1586_v6_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+ return max1586->v6_curr_sel;
}
static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
- struct i2c_client *client = rdev_get_drvdata(rdev);
+ struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+ struct i2c_client *client = max1586->client;
u8 v6_prog;
+ int ret;
dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
rdev->desc->volt_table[selector] / 1000);
v6_prog = I2C_V6_SELECT | (u8) selector;
- return i2c_smbus_write_byte(client, v6_prog);
+ ret = i2c_smbus_write_byte(client, v6_prog);
+ if (ret)
+ return ret;
+
+ max1586->v6_curr_sel = selector;
+
+ return 0;
}
/*
@@ -95,12 +127,14 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
* the set up value.
*/
static struct regulator_ops max1586_v3_ops = {
+ .get_voltage_sel = max1586_v3_get_voltage_sel,
.set_voltage_sel = max1586_v3_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
};
static struct regulator_ops max1586_v6_ops = {
+ .get_voltage_sel = max1586_v6_get_voltage_sel,
.set_voltage_sel = max1586_v6_set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
};
@@ -125,7 +159,7 @@ static struct regulator_desc max1586_reg[] = {
},
};
-static int __devinit max1586_pmic_probe(struct i2c_client *client,
+static int max1586_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct regulator_dev **rdev;
@@ -148,6 +182,10 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000;
max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000;
+ /* Set curr_sel to default voltage on power-up */
+ max1586->v3_curr_sel = 24; /* 1.3V */
+ max1586->v6_curr_sel = 0;
+
rdev = max1586->rdev;
for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
id = pdata->subdevs[i].id;
@@ -188,7 +226,7 @@ err:
return ret;
}
-static int __devexit max1586_pmic_remove(struct i2c_client *client)
+static int max1586_pmic_remove(struct i2c_client *client)
{
struct max1586_data *max1586 = i2c_get_clientdata(client);
int i;
@@ -207,7 +245,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
static struct i2c_driver max1586_pmic_driver = {
.probe = max1586_pmic_probe,
- .remove = __devexit_p(max1586_pmic_remove),
+ .remove = max1586_pmic_remove,
.driver = {
.name = "max1586",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index 2a67d08658ad..b85040caaea3 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -67,8 +67,94 @@ enum max77686_ramp_rate {
struct max77686_data {
struct regulator_dev *rdev[MAX77686_REGULATORS];
+ unsigned int opmode[MAX77686_REGULATORS];
};
+/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
+static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+ if (rdev->desc->id == MAX77686_BUCK1)
+ val = 0x1;
+ else
+ val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+
+ max77686->opmode[rdev->desc->id] = val;
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ val);
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+ unsigned int val;
+
+ /* BUCK[5-9] doesn't support this feature */
+ if (rdev->desc->id >= MAX77686_BUCK5)
+ return 0;
+
+ switch (mode) {
+ case REGULATOR_MODE_IDLE: /* ON in LP Mode */
+ val = 0x2 << MAX77686_OPMODE_SHIFT;
+ break;
+ case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
+ val = 0x3 << MAX77686_OPMODE_SHIFT;
+ break;
+ default:
+ pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+ rdev->desc->name, mode);
+ return -EINVAL;
+ }
+
+ max77686->opmode[rdev->desc->id] = val;
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ val);
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ unsigned int val;
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+ switch (mode) {
+ case REGULATOR_MODE_STANDBY: /* switch off */
+ val = 0x1 << MAX77686_OPMODE_SHIFT;
+ break;
+ case REGULATOR_MODE_IDLE: /* ON in LP Mode */
+ val = 0x2 << MAX77686_OPMODE_SHIFT;
+ break;
+ case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
+ val = 0x3 << MAX77686_OPMODE_SHIFT;
+ break;
+ default:
+ pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+ rdev->desc->name, mode);
+ return -EINVAL;
+ }
+
+ max77686->opmode[rdev->desc->id] = val;
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ val);
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ max77686->opmode[rdev->desc->id]);
+}
+
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
{
unsigned int ramp_value = RAMP_RATE_NO_CTRL;
@@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap,
- .enable = regulator_enable_regmap,
+ .enable = max77686_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_mode = max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = max77686_enable,
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_mode = max77686_ldo_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = max77686_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_disable = max77686_buck_set_suspend_disable,
};
static struct regulator_ops max77686_buck_dvs_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap,
- .enable = regulator_enable_regmap,
+ .enable = max77686_enable,
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77686_set_ramp_delay,
+ .set_suspend_disable = max77686_buck_set_suspend_disable,
};
#define regulator_desc_ldo(num) { \
@@ -133,9 +245,41 @@ static struct regulator_ops max77686_buck_dvs_ops = {
.enable_mask = MAX77686_OPMODE_MASK \
<< MAX77686_OPMODE_SHIFT, \
}
+#define regulator_desc_lpm_ldo(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
+ .ops = &max77686_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = MAX77686_LDO_MINUV, \
+ .uV_step = MAX77686_LDO_UVSTEP, \
+ .ramp_delay = MAX77686_RAMP_DELAY, \
+ .n_voltages = MAX77686_VSEL_MASK + 1, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = MAX77686_VSEL_MASK, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = MAX77686_OPMODE_MASK \
+ << MAX77686_OPMODE_SHIFT, \
+}
#define regulator_desc_ldo_low(num) { \
.name = "LDO"#num, \
.id = MAX77686_LDO##num, \
+ .ops = &max77686_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = MAX77686_LDO_LOW_MINUV, \
+ .uV_step = MAX77686_LDO_LOW_UVSTEP, \
+ .ramp_delay = MAX77686_RAMP_DELAY, \
+ .n_voltages = MAX77686_VSEL_MASK + 1, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = MAX77686_VSEL_MASK, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = MAX77686_OPMODE_MASK \
+ << MAX77686_OPMODE_SHIFT, \
+}
+#define regulator_desc_ldo1_low(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
.ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
@@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
#define regulator_desc_buck1(num) { \
.name = "BUCK"#num, \
.id = MAX77686_BUCK##num, \
- .ops = &max77686_ops, \
+ .ops = &max77686_buck1_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = MAX77686_BUCK_MINUV, \
@@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
static struct regulator_desc regulators[] = {
- regulator_desc_ldo_low(1),
+ regulator_desc_ldo1_low(1),
regulator_desc_ldo_low(2),
regulator_desc_ldo(3),
regulator_desc_ldo(4),
@@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
regulator_desc_ldo_low(7),
regulator_desc_ldo_low(8),
regulator_desc_ldo(9),
- regulator_desc_ldo(10),
- regulator_desc_ldo(11),
- regulator_desc_ldo(12),
+ regulator_desc_lpm_ldo(10),
+ regulator_desc_lpm_ldo(11),
+ regulator_desc_lpm_ldo(12),
regulator_desc_ldo(13),
- regulator_desc_ldo(14),
+ regulator_desc_lpm_ldo(14),
regulator_desc_ldo_low(15),
- regulator_desc_ldo(16),
+ regulator_desc_lpm_ldo(16),
regulator_desc_ldo(17),
regulator_desc_ldo(18),
regulator_desc_ldo(19),
@@ -280,7 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
}
#endif /* CONFIG_OF */
-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+static int max77686_pmic_probe(struct platform_device *pdev)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
config.dev = &pdev->dev;
config.regmap = iodev->regmap;
+ config.driver_data = max77686;
platform_set_drvdata(pdev, max77686);
for (i = 0; i < MAX77686_REGULATORS; i++) {
config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].of_node;
+ max77686->opmode[i] = regulators[i].enable_mask;
max77686->rdev[i] = regulator_register(&regulators[i], &config);
if (IS_ERR(max77686->rdev[i])) {
ret = PTR_ERR(max77686->rdev[i]);
@@ -337,7 +483,7 @@ err:
return ret;
}
-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+static int max77686_pmic_remove(struct platform_device *pdev)
{
struct max77686_data *max77686 = platform_get_drvdata(pdev);
int i;
@@ -360,7 +506,7 @@ static struct platform_driver max77686_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max77686_pmic_probe,
- .remove = __devexit_p(max77686_pmic_remove),
+ .remove = max77686_pmic_remove,
.id_table = max77686_pmic_id,
};
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 9d540cd02dab..3ca14380f22d 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
.val_bits = 8,
};
-static int __devinit max8649_regulator_probe(struct i2c_client *client,
+static int max8649_regulator_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max8649_platform_data *pdata = client->dev.platform_data;
@@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
return 0;
}
-static int __devexit max8649_regulator_remove(struct i2c_client *client)
+static int max8649_regulator_remove(struct i2c_client *client)
{
struct max8649_regulator_info *info = i2c_get_clientdata(client);
@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
static struct i2c_driver max8649_driver = {
.probe = max8649_regulator_probe,
- .remove = __devexit_p(max8649_regulator_remove),
+ .remove = max8649_regulator_remove,
.driver = {
.name = "max8649",
},
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 8d531742f593..4d7c635c36c2 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
},
};
-static int __devinit max8660_probe(struct i2c_client *client,
+static int max8660_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct regulator_dev **rdev;
@@ -420,7 +420,7 @@ err_out:
return ret;
}
-static int __devexit max8660_remove(struct i2c_client *client)
+static int max8660_remove(struct i2c_client *client)
{
struct max8660 *max8660 = i2c_get_clientdata(client);
int i;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
static struct i2c_driver max8660_driver = {
.probe = max8660_probe,
- .remove = __devexit_p(max8660_remove),
+ .remove = max8660_remove,
.driver = {
.name = "max8660",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index af7607515ab9..d1a77512d83e 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
}
#endif
-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
+static int max8907_regulator_probe(struct platform_device *pdev)
{
struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
@@ -368,7 +368,7 @@ err_unregister_regulator:
return ret;
}
-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
+static int max8907_regulator_remove(struct platform_device *pdev)
{
struct max8907_regulator *pmic = platform_get_drvdata(pdev);
int i;
@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = max8907_regulator_probe,
- .remove = __devexit_p(max8907_regulator_remove),
+ .remove = max8907_regulator_remove,
};
static int __init max8907_regulator_init(void)
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index 9bb0be37495f..446a85445553 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -17,6 +17,8 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
#define SD1_DVM_VMIN 850000
#define SD1_DVM_VMAX 1000000
@@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
.enable_reg = MAX8925_LDOCTL##_id, \
}
+#ifdef CONFIG_OF
+static struct of_regulator_match max8925_regulator_matches[] = {
+ { .name = "SDV1",},
+ { .name = "SDV2",},
+ { .name = "SDV3",},
+ { .name = "LDO1",},
+ { .name = "LDO2",},
+ { .name = "LDO3",},
+ { .name = "LDO4",},
+ { .name = "LDO5",},
+ { .name = "LDO6",},
+ { .name = "LDO7",},
+ { .name = "LDO8",},
+ { .name = "LDO9",},
+ { .name = "LDO10",},
+ { .name = "LDO11",},
+ { .name = "LDO12",},
+ { .name = "LDO13",},
+ { .name = "LDO14",},
+ { .name = "LDO15",},
+ { .name = "LDO16",},
+ { .name = "LDO17",},
+ { .name = "LDO18",},
+ { .name = "LDO19",},
+ { .name = "LDO20",},
+};
+#endif
+
static struct max8925_regulator_info max8925_regulator_info[] = {
MAX8925_SDV(1, 637.5, 1425, 12.5),
MAX8925_SDV(2, 650, 2225, 25),
@@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
MAX8925_LDO(20, 750, 3900, 50),
};
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8925_regulator_dt_init(struct platform_device *pdev,
+ struct max8925_regulator_info *info,
+ struct regulator_config *config,
+ int ridx)
+{
+ struct device_node *nproot, *np;
+ int rcount;
+ nproot = pdev->dev.parent->of_node;
+ if (!nproot)
+ return -ENODEV;
+ np = of_find_node_by_name(nproot, "regulators");
+ if (!np) {
+ dev_err(&pdev->dev, "failed to find regulators node\n");
+ return -ENODEV;
+ }
+
+ rcount = of_regulator_match(&pdev->dev, np,
+ &max8925_regulator_matches[ridx], 1);
+ if (rcount < 0)
+ return -ENODEV;
+ config->init_data = max8925_regulator_matches[ridx].init_data;
+ config->of_node = max8925_regulator_matches[ridx].of_node;
+
+ return 0;
+}
+#else
+#define max8925_regulator_dt_init(w, x, y, z) (-1)
+#endif
+
+static int max8925_regulator_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct regulator_init_data *pdata = pdev->dev.platform_data;
@@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
struct max8925_regulator_info *ri;
struct resource *res;
struct regulator_dev *rdev;
- int i;
+ int i, regulator_idx;
res = platform_get_resource(pdev, IORESOURCE_REG, 0);
if (!res) {
@@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
}
for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
ri = &max8925_regulator_info[i];
- if (ri->vol_reg == res->start)
+ if (ri->vol_reg == res->start) {
+ regulator_idx = i;
break;
+ }
}
+
if (i == ARRAY_SIZE(max8925_regulator_info)) {
dev_err(&pdev->dev, "Failed to find regulator %llu\n",
(unsigned long long)res->start);
@@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
ri->chip = chip;
config.dev = &pdev->dev;
- config.init_data = pdata;
config.driver_data = ri;
+ if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+ if (pdata)
+ config.init_data = pdata;
+
rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+static int max8925_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = max8925_regulator_probe,
- .remove = __devexit_p(max8925_regulator_remove),
+ .remove = max8925_regulator_remove,
};
static int __init max8925_regulator_init(void)
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 355ca7bad9d5..fc7935a19e3a 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
.owner = THIS_MODULE,
};
-static int __devinit max8952_pmic_probe(struct i2c_client *client,
+static int max8952_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
return 0;
}
-static int __devexit max8952_pmic_remove(struct i2c_client *client)
+static int max8952_pmic_remove(struct i2c_client *client)
{
struct max8952_data *max8952 = i2c_get_clientdata(client);
struct max8952_platform_data *pdata = max8952->pdata;
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
static struct i2c_driver max8952_pmic_driver = {
.probe = max8952_pmic_probe,
- .remove = __devexit_p(max8952_pmic_remove),
+ .remove = max8952_pmic_remove,
.driver = {
.name = "max8952",
},
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
new file mode 100644
index 000000000000..3ee26387b121
--- /dev/null
+++ b/drivers/regulator/max8973-regulator.c
@@ -0,0 +1,505 @@
+/*
+ * max8973-regulator.c -- Maxim max8973
+ *
+ * Regulator driver for MAXIM 8973 DC-DC step-down switching regulator.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8973-regulator.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+/* Register definitions */
+#define MAX8973_VOUT 0x0
+#define MAX8973_VOUT_DVS 0x1
+#define MAX8973_CONTROL1 0x2
+#define MAX8973_CONTROL2 0x3
+#define MAX8973_CHIPID1 0x4
+#define MAX8973_CHIPID2 0x5
+
+#define MAX8973_MAX_VOUT_REG 2
+
+/* MAX8973_VOUT */
+#define MAX8973_VOUT_ENABLE BIT(7)
+#define MAX8973_VOUT_MASK 0x7F
+
+/* MAX8973_VOUT_DVS */
+#define MAX8973_DVS_VOUT_MASK 0x7F
+
+/* MAX8973_CONTROL1 */
+#define MAX8973_SNS_ENABLE BIT(7)
+#define MAX8973_FPWM_EN_M BIT(6)
+#define MAX8973_NFSR_ENABLE BIT(5)
+#define MAX8973_AD_ENABLE BIT(4)
+#define MAX8973_BIAS_ENABLE BIT(3)
+#define MAX8973_FREQSHIFT_9PER BIT(2)
+
+#define MAX8973_RAMP_12mV_PER_US 0x0
+#define MAX8973_RAMP_25mV_PER_US 0x1
+#define MAX8973_RAMP_50mV_PER_US 0x2
+#define MAX8973_RAMP_200mV_PER_US 0x3
+
+/* MAX8973_CONTROL2 */
+#define MAX8973_WDTMR_ENABLE BIT(6)
+#define MAX8973_DISCH_ENBABLE BIT(5)
+#define MAX8973_FT_ENABLE BIT(4)
+
+#define MAX8973_CKKADV_TRIP_DISABLE 0xC
+#define MAX8973_CKKADV_TRIP_75mV_PER_US 0x0
+#define MAX8973_CKKADV_TRIP_150mV_PER_US 0x4
+#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
+#define MAX8973_CONTROL_CLKADV_TRIP_MASK 0x00030000
+
+#define MAX8973_INDUCTOR_MIN_30_PER 0x0
+#define MAX8973_INDUCTOR_NOMINAL 0x1
+#define MAX8973_INDUCTOR_PLUS_30_PER 0x2
+#define MAX8973_INDUCTOR_PLUS_60_PER 0x3
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK 0x00300000
+
+#define MAX8973_MIN_VOLATGE 606250
+#define MAX8973_MAX_VOLATGE 1400000
+#define MAX8973_VOLATGE_STEP 6250
+#define MAX8973_BUCK_N_VOLTAGE 0x80
+
+/* Maxim 8973 chip information */
+struct max8973_chip {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ bool enable_external_control;
+ int dvs_gpio;
+ int lru_index[MAX8973_MAX_VOUT_REG];
+ int curr_vout_val[MAX8973_MAX_VOUT_REG];
+ int curr_vout_reg;
+ int curr_gpio_val;
+ bool valid_dvs_gpio;
+};
+
+/*
+ * find_voltage_set_register: Find new voltage configuration register (VOUT).
+ * The finding of the new VOUT register will be based on the LRU mechanism.
+ * Each VOUT register will have different voltage configured . This
+ * Function will look if any of the VOUT register have requested voltage set
+ * or not.
+ * - If it is already there then it will make that register as most
+ * recently used and return as found so that caller need not to set
+ * the VOUT register but need to set the proper gpios to select this
+ * VOUT register.
+ * - If requested voltage is not found then it will use the least
+ * recently mechanism to get new VOUT register for new configuration
+ * and will return not_found so that caller need to set new VOUT
+ * register and then gpios (both).
+ */
+static bool find_voltage_set_register(struct max8973_chip *tps,
+ int req_vsel, int *vout_reg, int *gpio_val)
+{
+ int i;
+ bool found = false;
+ int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1];
+ int found_index = MAX8973_MAX_VOUT_REG - 1;
+
+ for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) {
+ if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) {
+ new_vout_reg = tps->lru_index[i];
+ found_index = i;
+ found = true;
+ goto update_lru_index;
+ }
+ }
+
+update_lru_index:
+ for (i = found_index; i > 0; i--)
+ tps->lru_index[i] = tps->lru_index[i - 1];
+
+ tps->lru_index[0] = new_vout_reg;
+ *gpio_val = new_vout_reg;
+ *vout_reg = MAX8973_VOUT + new_vout_reg;
+ return found;
+}
+
+static int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct max8973_chip *max = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(max->regmap, max->curr_vout_reg, &data);
+ if (ret < 0) {
+ dev_err(max->dev, "register %d read failed, err = %d\n",
+ max->curr_vout_reg, ret);
+ return ret;
+ }
+ return data & MAX8973_VOUT_MASK;
+}
+
+static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned vsel)
+{
+ struct max8973_chip *max = rdev_get_drvdata(rdev);
+ int ret;
+ bool found = false;
+ int vout_reg = max->curr_vout_reg;
+ int gpio_val = max->curr_gpio_val;
+
+ /*
+ * If gpios are available to select the VOUT register then least
+ * recently used register for new configuration.
+ */
+ if (max->valid_dvs_gpio)
+ found = find_voltage_set_register(max, vsel,
+ &vout_reg, &gpio_val);
+
+ if (!found) {
+ ret = regmap_update_bits(max->regmap, vout_reg,
+ MAX8973_VOUT_MASK, vsel);
+ if (ret < 0) {
+ dev_err(max->dev, "register %d update failed, err %d\n",
+ vout_reg, ret);
+ return ret;
+ }
+ max->curr_vout_reg = vout_reg;
+ max->curr_vout_val[gpio_val] = vsel;
+ }
+
+ /* Select proper VOUT register vio gpios */
+ if (max->valid_dvs_gpio) {
+ gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
+ max->curr_gpio_val = gpio_val;
+ }
+ return 0;
+}
+
+static int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct max8973_chip *max = rdev_get_drvdata(rdev);
+ int ret;
+ int pwm;
+
+ /* Enable force PWM mode in FAST mode only. */
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ pwm = MAX8973_FPWM_EN_M;
+ break;
+
+ case REGULATOR_MODE_NORMAL:
+ pwm = 0;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
+ MAX8973_FPWM_EN_M, pwm);
+ if (ret < 0)
+ dev_err(max->dev, "register %d update failed, err %d\n",
+ MAX8973_CONTROL1, ret);
+ return ret;
+}
+
+static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
+{
+ struct max8973_chip *max = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
+ if (ret < 0) {
+ dev_err(max->dev, "register %d read failed, err %d\n",
+ MAX8973_CONTROL1, ret);
+ return ret;
+ }
+ return (data & MAX8973_FPWM_EN_M) ?
+ REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops max8973_dcdc_ops = {
+ .get_voltage_sel = max8973_dcdc_get_voltage_sel,
+ .set_voltage_sel = max8973_dcdc_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_mode = max8973_dcdc_set_mode,
+ .get_mode = max8973_dcdc_get_mode,
+};
+
+static int __devinit max8973_init_dcdc(struct max8973_chip *max,
+ struct max8973_regulator_platform_data *pdata)
+{
+ int ret;
+ uint8_t control1 = 0;
+ uint8_t control2 = 0;
+
+ if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
+ control1 |= MAX8973_SNS_ENABLE;
+
+ if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
+ control1 |= MAX8973_NFSR_ENABLE;
+
+ if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
+ control1 |= MAX8973_AD_ENABLE;
+
+ if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
+ control1 |= MAX8973_BIAS_ENABLE;
+
+ if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
+ control1 |= MAX8973_FREQSHIFT_9PER;
+
+ /* Set ramp delay */
+ if (pdata->reg_init_data &&
+ pdata->reg_init_data->constraints.ramp_delay) {
+ if (pdata->reg_init_data->constraints.ramp_delay < 25000)
+ control1 = MAX8973_RAMP_12mV_PER_US;
+ else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
+ control1 = MAX8973_RAMP_25mV_PER_US;
+ else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
+ control1 = MAX8973_RAMP_50mV_PER_US;
+ else
+ control1 = MAX8973_RAMP_200mV_PER_US;
+ } else {
+ control1 = MAX8973_RAMP_12mV_PER_US;
+ max->desc.ramp_delay = 12500;
+ }
+
+ if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
+ control2 |= MAX8973_DISCH_ENBABLE;
+
+ /* Clock advance trip configuration */
+ switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
+ case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
+ control2 |= MAX8973_CKKADV_TRIP_DISABLE;
+ break;
+
+ case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
+ control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
+ break;
+
+ case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
+ control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
+ break;
+
+ case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
+ control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
+ break;
+ }
+
+ /* Configure inductor value */
+ switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
+ case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
+ control2 |= MAX8973_INDUCTOR_NOMINAL;
+ break;
+
+ case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
+ control2 |= MAX8973_INDUCTOR_MIN_30_PER;
+ break;
+
+ case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
+ control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
+ break;
+
+ case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
+ control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
+ break;
+ }
+
+ ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
+ if (ret < 0) {
+ dev_err(max->dev, "register %d write failed, err = %d",
+ MAX8973_CONTROL1, ret);
+ return ret;
+ }
+
+ ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
+ if (ret < 0) {
+ dev_err(max->dev, "register %d write failed, err = %d",
+ MAX8973_CONTROL2, ret);
+ return ret;
+ }
+
+ /* If external control is enabled then disable EN bit */
+ if (max->enable_external_control) {
+ ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
+ MAX8973_VOUT_ENABLE, 0);
+ if (ret < 0)
+ dev_err(max->dev, "register %d update failed, err = %d",
+ MAX8973_VOUT, ret);
+ }
+ return ret;
+}
+
+static const struct regmap_config max8973_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX8973_CHIPID2,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max8973_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max8973_regulator_platform_data *pdata;
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+ struct max8973_chip *max;
+ int ret;
+
+ pdata = client->dev.platform_data;
+ if (!pdata) {
+ dev_err(&client->dev, "No Platform data");
+ return -EIO;
+ }
+
+ max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
+ if (!max) {
+ dev_err(&client->dev, "Memory allocation for max failed\n");
+ return -ENOMEM;
+ }
+
+ max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
+ if (IS_ERR(max->regmap)) {
+ ret = PTR_ERR(max->regmap);
+ dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(client, max);
+ max->dev = &client->dev;
+ max->desc.name = id->name;
+ max->desc.id = 0;
+ max->desc.ops = &max8973_dcdc_ops;
+ max->desc.type = REGULATOR_VOLTAGE;
+ max->desc.owner = THIS_MODULE;
+ max->desc.min_uV = MAX8973_MIN_VOLATGE;
+ max->desc.uV_step = MAX8973_VOLATGE_STEP;
+ max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
+
+ if (!pdata->enable_ext_control) {
+ max->desc.enable_reg = MAX8973_VOUT;
+ max->desc.enable_mask = MAX8973_VOUT_ENABLE;
+ max8973_dcdc_ops.enable = regulator_enable_regmap;
+ max8973_dcdc_ops.disable = regulator_disable_regmap;
+ max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap;
+ }
+
+ max->enable_external_control = pdata->enable_ext_control;
+ max->dvs_gpio = pdata->dvs_gpio;
+ max->curr_gpio_val = pdata->dvs_def_state;
+ max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
+ max->lru_index[0] = max->curr_vout_reg;
+ max->valid_dvs_gpio = false;
+
+ if (gpio_is_valid(max->dvs_gpio)) {
+ int gpio_flags;
+ int i;
+
+ gpio_flags = (pdata->dvs_def_state) ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
+ gpio_flags, "max8973-dvs");
+ if (ret) {
+ dev_err(&client->dev,
+ "gpio_request for gpio %d failed, err = %d\n",
+ max->dvs_gpio, ret);
+ return ret;
+ }
+ max->valid_dvs_gpio = true;
+
+ /*
+ * Initialize the lru index with vout_reg id
+ * The index 0 will be most recently used and
+ * set with the max->curr_vout_reg */
+ for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
+ max->lru_index[i] = i;
+ max->lru_index[0] = max->curr_vout_reg;
+ max->lru_index[max->curr_vout_reg] = 0;
+ }
+
+ ret = max8973_init_dcdc(max, pdata);
+ if (ret < 0) {
+ dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
+ return ret;
+ }
+
+ config.dev = &client->dev;
+ config.init_data = pdata->reg_init_data;
+ config.driver_data = max;
+ config.of_node = client->dev.of_node;
+ config.regmap = max->regmap;
+
+ /* Register the regulators */
+ rdev = regulator_register(&max->desc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(max->dev, "regulator register failed, err %d\n", ret);
+ return ret;
+ }
+
+ max->rdev = rdev;
+ return 0;
+}
+
+static int __devexit max8973_remove(struct i2c_client *client)
+{
+ struct max8973_chip *max = i2c_get_clientdata(client);
+
+ regulator_unregister(max->rdev);
+ return 0;
+}
+
+static const struct i2c_device_id max8973_id[] = {
+ {.name = "max8973",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, max8973_id);
+
+static struct i2c_driver max8973_i2c_driver = {
+ .driver = {
+ .name = "max8973",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8973_probe,
+ .remove = __devexit_p(max8973_remove),
+ .id_table = max8973_id,
+};
+
+static int __init max8973_init(void)
+{
+ return i2c_add_driver(&max8973_i2c_driver);
+}
+subsys_initcall(max8973_init);
+
+static void __exit max8973_cleanup(void)
+{
+ i2c_del_driver(&max8973_i2c_driver);
+}
+module_exit(max8973_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("MAX8973 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index e39a0c7260dc..df0eafb0dc7e 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -24,6 +24,7 @@
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -31,6 +32,7 @@
#include <linux/regulator/machine.h>
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
+#include <linux/regulator/of_regulator.h>
struct max8997_data {
struct device *dev;
@@ -933,22 +935,163 @@ static struct regulator_desc regulators[] = {
max8997_charger_fixedstate_ops),
};
-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata,
+ struct device_node *pmic_np)
+{
+ int i, gpio;
+
+ for (i = 0; i < 3; i++) {
+ gpio = of_get_named_gpio(pmic_np,
+ "max8997,pmic-buck125-dvs-gpios", i);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+ return -EINVAL;
+ }
+ pdata->buck125_gpios[i] = gpio;
+ }
+ return 0;
+}
+
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata)
+{
+ struct device_node *pmic_np, *regulators_np, *reg_np;
+ struct max8997_regulator_data *rdata;
+ unsigned int i, dvs_voltage_nr = 1, ret;
+
+ pmic_np = iodev->dev->of_node;
+ if (!pmic_np) {
+ dev_err(iodev->dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "regulators");
+ if (!regulators_np) {
+ dev_err(iodev->dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ /* count the number of regulators to be supported in pmic */
+ pdata->num_regulators = 0;
+ for_each_child_of_node(regulators_np, reg_np)
+ pdata->num_regulators++;
+
+ rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+ pdata->num_regulators, GFP_KERNEL);
+ if (!rdata) {
+ dev_err(iodev->dev, "could not allocate memory for "
+ "regulator data\n");
+ return -ENOMEM;
+ }
+
+ pdata->regulators = rdata;
+ for_each_child_of_node(regulators_np, reg_np) {
+ for (i = 0; i < ARRAY_SIZE(regulators); i++)
+ if (!of_node_cmp(reg_np->name, regulators[i].name))
+ break;
+
+ if (i == ARRAY_SIZE(regulators)) {
+ dev_warn(iodev->dev, "don't know how to configure "
+ "regulator %s\n", reg_np->name);
+ continue;
+ }
+
+ rdata->id = i;
+ rdata->initdata = of_get_regulator_init_data(
+ iodev->dev, reg_np);
+ rdata->reg_node = reg_np;
+ rdata++;
+ }
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
+ pdata->buck1_gpiodvs = true;
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
+ pdata->buck2_gpiodvs = true;
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
+ pdata->buck5_gpiodvs = true;
+
+ if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+ pdata->buck5_gpiodvs) {
+ ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+ if (ret)
+ return -EINVAL;
+
+ if (of_property_read_u32(pmic_np,
+ "max8997,pmic-buck125-default-dvs-idx",
+ &pdata->buck125_default_idx)) {
+ pdata->buck125_default_idx = 0;
+ } else {
+ if (pdata->buck125_default_idx >= 8) {
+ pdata->buck125_default_idx = 0;
+ dev_info(iodev->dev, "invalid value for "
+ "default dvs index, using 0 instead\n");
+ }
+ }
+
+ if (of_get_property(pmic_np,
+ "max8997,pmic-ignore-gpiodvs-side-effect", NULL))
+ pdata->ignore_gpiodvs_side_effect = true;
+
+ dvs_voltage_nr = 8;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck1-dvs-voltage",
+ pdata->buck1_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck1 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck2-dvs-voltage",
+ pdata->buck2_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck2 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck5-dvs-voltage",
+ pdata->buck5_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck5 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static int max8997_pmic_probe(struct platform_device *pdev)
{
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_platform_data *pdata = iodev->pdata;
struct regulator_config config = { };
struct regulator_dev **rdev;
struct max8997_data *max8997;
struct i2c_client *i2c;
- int i, ret, size;
+ int i, ret, size, nr_dvs;
u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
- if (!pdata) {
+ if (IS_ERR_OR_NULL(pdata)) {
dev_err(pdev->dev.parent, "No platform init data supplied.\n");
return -ENODEV;
}
+ if (iodev->dev->of_node) {
+ ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+ if (ret)
+ return ret;
+ }
+
max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
GFP_KERNEL);
if (!max8997)
@@ -973,7 +1116,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3);
max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect;
- for (i = 0; i < 8; i++) {
+ nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+ pdata->buck5_gpiodvs) ? 8 : 1;
+
+ for (i = 0; i < nr_dvs; i++) {
max8997->buck1_vol[i] = ret =
max8997_get_voltage_proper_val(
&buck1245_voltage_map_desc,
@@ -1019,6 +1165,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
max_buck5, 0x3f);
}
+ /* Initialize all the DVS related BUCK registers */
+ for (i = 0; i < nr_dvs; i++) {
+ max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
+ max8997->buck1_vol[i],
+ 0x3f);
+ max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
+ max8997->buck2_vol[i],
+ 0x3f);
+ max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
+ max8997->buck5_vol[i],
+ 0x3f);
+ }
+
/*
* If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
* If at least one of them cares, set gpios.
@@ -1068,19 +1227,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
(1 << 1) : (0 << 1), 1 << 1);
- /* Initialize all the DVS related BUCK registers */
- for (i = 0; i < 8; i++) {
- max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
- max8997->buck1_vol[i],
- 0x3f);
- max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
- max8997->buck2_vol[i],
- 0x3f);
- max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
- max8997->buck5_vol[i],
- 0x3f);
- }
-
/* Misc Settings */
max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
@@ -1101,6 +1247,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
config.dev = max8997->dev;
config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8997;
+ config.of_node = pdata->regulators[i].reg_node;
rdev[i] = regulator_register(&regulators[id], &config);
if (IS_ERR(rdev[i])) {
@@ -1120,7 +1267,7 @@ err_out:
return ret;
}
-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+static int max8997_pmic_remove(struct platform_device *pdev)
{
struct max8997_data *max8997 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = max8997->rdev;
@@ -1143,7 +1290,7 @@ static struct platform_driver max8997_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_pmic_probe,
- .remove = __devexit_p(max8997_pmic_remove),
+ .remove = max8997_pmic_remove,
.id_table = max8997_pmic_id,
};
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 5dfa920ff0c8..b821d08eb64a 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
}
};
-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
+static int max8998_pmic_probe(struct platform_device *pdev)
{
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -818,7 +818,7 @@ err_out:
return ret;
}
-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
+static int max8998_pmic_remove(struct platform_device *pdev)
{
struct max8998_data *max8998 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = max8998->rdev;
@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8998_pmic_probe,
- .remove = __devexit_p(max8998_pmic_remove),
+ .remove = max8998_pmic_remove,
.id_table = max8998_pmic_id,
};
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 0801a6d0c122..c46c6705cd74 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
};
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+static int mc13783_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -445,7 +445,7 @@ err:
return ret;
}
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+static int mc13783_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13xxx_regulator_platform_data *pdata =
@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
.name = "mc13783-regulator",
.owner = THIS_MODULE,
},
- .remove = __devexit_p(mc13783_regulator_remove),
+ .remove = mc13783_regulator_remove,
.probe = mc13783_regulator_probe,
};
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 1fa63812f7ac..0d84b1f33199 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
}
-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
+static int mc13892_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
@@ -588,7 +588,7 @@ err_unlock:
return ret;
}
-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
+static int mc13892_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
int i;
@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
.name = "mc13892-regulator",
.owner = THIS_MODULE,
},
- .remove = __devexit_p(mc13892_regulator_remove),
+ .remove = mc13892_regulator_remove,
.probe = mc13892_regulator_probe,
};
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 88cbb832d555..4ed89c654110 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
#ifdef CONFIG_OF
-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
{
struct device_node *parent, *child;
int num = 0;
@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
+struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
int num_regulators)
{
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 07aee694ba92..e915629a25cf 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -309,68 +309,22 @@ static int palmas_list_voltage_smps(struct regulator_dev *dev,
int id = rdev_get_id(dev);
int mult = 1;
- if (!selector)
- return 0;
-
/* Read the multiplier set in VSEL register to return
* the correct voltage.
*/
if (pmic->range[id])
mult = 2;
- /* Voltage is (0.49V + (selector * 0.01V)) * RANGE
- * as defined in data sheet. RANGE is either x1 or x2
- */
- return (490000 + (selector * 10000)) * mult;
-}
-
-static int palmas_get_voltage_smps_sel(struct regulator_dev *dev)
-{
- struct palmas_pmic *pmic = rdev_get_drvdata(dev);
- int id = rdev_get_id(dev);
- int selector;
- unsigned int reg;
- unsigned int addr;
-
- addr = palmas_regs_info[id].vsel_addr;
-
- palmas_smps_read(pmic->palmas, addr, &reg);
-
- selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
-
- /* Adjust selector to match list_voltage ranges */
- if ((selector > 0) && (selector < 6))
- selector = 6;
- if (!selector)
- selector = 5;
- if (selector > 121)
- selector = 121;
- selector -= 5;
-
- return selector;
-}
-
-static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
- unsigned selector)
-{
- struct palmas_pmic *pmic = rdev_get_drvdata(dev);
- int id = rdev_get_id(dev);
- unsigned int reg = 0;
- unsigned int addr;
-
- addr = palmas_regs_info[id].vsel_addr;
-
- /* Make sure we don't change the value of RANGE */
- if (pmic->range[id])
- reg |= PALMAS_SMPS12_VOLTAGE_RANGE;
-
- /* Adjust the linux selector into range used in VSEL register */
- if (selector)
- reg |= selector + 5;
-
- palmas_smps_write(pmic->palmas, addr, reg);
-
- return 0;
+ if (selector == 0)
+ return 0;
+ else if (selector < 6)
+ return 500000 * mult;
+ else
+ /* Voltage is linear mapping starting from selector 6,
+ * volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE
+ * RANGE is either x1 or x2
+ */
+ return (490000 + ((selector - 5) * 10000)) * mult;
}
static int palmas_map_voltage_smps(struct regulator_dev *rdev,
@@ -386,11 +340,11 @@ static int palmas_map_voltage_smps(struct regulator_dev *rdev,
if (pmic->range[id]) { /* RANGE is x2 */
if (min_uV < 1000000)
min_uV = 1000000;
- ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
+ ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6;
} else { /* RANGE is x1 */
if (min_uV < 500000)
min_uV = 500000;
- ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
+ ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6;
}
/* Map back into a voltage to verify we're still in bounds */
@@ -407,8 +361,8 @@ static struct regulator_ops palmas_ops_smps = {
.disable = palmas_disable_smps,
.set_mode = palmas_set_mode_smps,
.get_mode = palmas_get_mode_smps,
- .get_voltage_sel = palmas_get_voltage_smps_sel,
- .set_voltage_sel = palmas_set_voltage_smps_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = palmas_list_voltage_smps,
.map_voltage = palmas_map_voltage_smps,
};
@@ -436,44 +390,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)
return !!(reg);
}
-static int palmas_list_voltage_ldo(struct regulator_dev *dev,
- unsigned selector)
-{
- if (!selector)
- return 0;
-
- /* voltage is 0.85V + (selector * 0.05v) */
- return 850000 + (selector * 50000);
-}
-
-static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int ret, voltage;
-
- if (min_uV == 0)
- return 0;
-
- if (min_uV < 900000)
- min_uV = 900000;
- ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;
-
- /* Map back into a voltage to verify we're still in bounds */
- voltage = palmas_list_voltage_ldo(rdev, ret);
- if (voltage < min_uV || voltage > max_uV)
- return -EINVAL;
-
- return ret;
-}
-
static struct regulator_ops palmas_ops_ldo = {
.is_enabled = palmas_is_enabled_ldo,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .list_voltage = palmas_list_voltage_ldo,
- .map_voltage = palmas_map_voltage_ldo,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
};
/*
@@ -595,7 +519,7 @@ static struct of_regulator_match palmas_matches[] = {
{ .name = "ldousb", },
};
-static void __devinit palmas_dt_to_pdata(struct device *dev,
+static void palmas_dt_to_pdata(struct device *dev,
struct device_node *node,
struct palmas_pmic_platform_data *pdata)
{
@@ -663,7 +587,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
}
-static __devinit int palmas_probe(struct platform_device *pdev)
+static int palmas_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -733,6 +657,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
continue;
}
+ /* Initialise sleep/init values from platform data */
+ if (pdata && pdata->reg_init[id]) {
+ reg_init = pdata->reg_init[id];
+ ret = palmas_smps_init(palmas, id, reg_init);
+ if (ret)
+ goto err_unregister_regulator;
+ }
+
/* Register the regulators */
pmic->desc[id].name = palmas_regs_info[id].name;
pmic->desc[id].id = id;
@@ -753,29 +685,11 @@ static __devinit int palmas_probe(struct platform_device *pdev)
pmic->desc[id].uV_step = 1250000;
break;
default:
- pmic->desc[id].ops = &palmas_ops_smps;
- pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
- }
-
- pmic->desc[id].type = REGULATOR_VOLTAGE;
- pmic->desc[id].owner = THIS_MODULE;
-
- /* Initialise sleep/init values from platform data */
- if (pdata) {
- reg_init = pdata->reg_init[id];
- if (reg_init) {
- ret = palmas_smps_init(palmas, id, reg_init);
- if (ret)
- goto err_unregister_regulator;
- }
- }
-
- /*
- * read and store the RANGE bit for later use
- * This must be done before regulator is probed otherwise
- * we error in probe with unsuportable ranges.
- */
- if (id != PALMAS_REG_SMPS10) {
+ /*
+ * Read and store the RANGE bit for later use
+ * This must be done before regulator is probed,
+ * otherwise we error in probe with unsupportable ranges.
+ */
addr = palmas_regs_info[id].vsel_addr;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
@@ -783,8 +697,19 @@ static __devinit int palmas_probe(struct platform_device *pdev)
goto err_unregister_regulator;
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1;
+
+ pmic->desc[id].ops = &palmas_ops_smps;
+ pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+ pmic->desc[id].vsel_reg =
+ PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ palmas_regs_info[id].vsel_addr);
+ pmic->desc[id].vsel_mask =
+ PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
}
+ pmic->desc[id].type = REGULATOR_VOLTAGE;
+ pmic->desc[id].owner = THIS_MODULE;
+
if (pdata)
config.init_data = pdata->reg_data[id];
else
@@ -821,6 +746,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
pmic->desc[id].type = REGULATOR_VOLTAGE;
pmic->desc[id].owner = THIS_MODULE;
+ pmic->desc[id].min_uV = 900000;
+ pmic->desc[id].uV_step = 50000;
+ pmic->desc[id].linear_min_sel = 1;
pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
palmas_regs_info[id].vsel_addr);
pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
@@ -868,7 +796,7 @@ err_unregister_regulator:
return ret;
}
-static int __devexit palmas_remove(struct platform_device *pdev)
+static int palmas_remove(struct platform_device *pdev)
{
struct palmas_pmic *pmic = platform_get_drvdata(pdev);
int id;
@@ -890,7 +818,7 @@ static struct platform_driver palmas_driver = {
.owner = THIS_MODULE,
},
.probe = palmas_probe,
- .remove = __devexit_p(palmas_remove),
+ .remove = palmas_remove,
};
static int __init palmas_init(void)
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index 68777acc099f..4899342f1fc1 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
};
-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+static int pcap_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
void *pcap = dev_get_drvdata(pdev->dev.parent);
@@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+static int pcap_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = pcap_regulator_probe,
- .remove = __devexit_p(pcap_regulator_remove),
+ .remove = pcap_regulator_remove,
};
static int __init pcap_regulator_init(void)
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
index 092e5cb848a1..534075e13d6d 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -24,12 +24,15 @@
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/pmic.h>
-#define PCF50633_REGULATOR(_name, _id, _n) \
+#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
{ \
.name = _name, \
.id = PCF50633_REGULATOR_##_id, \
.ops = &pcf50633_regulator_ops, \
.n_voltages = _n, \
+ .min_uV = _min_uV, \
+ .uV_step = _uV_step, \
+ .linear_min_sel = _min_sel, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.vsel_reg = PCF50633_REG_##_id##OUT, \
@@ -38,165 +41,42 @@
.enable_mask = PCF50633_REGULATOR_ON, \
}
-/* Bits from voltage value */
-static u8 auto_voltage_bits(unsigned int millivolts)
-{
- if (millivolts < 1800)
- return 0x2f;
- if (millivolts > 3800)
- return 0xff;
-
- millivolts -= 625;
-
- return millivolts / 25;
-}
-
-static u8 down_voltage_bits(unsigned int millivolts)
-{
- if (millivolts < 625)
- return 0;
- else if (millivolts > 3000)
- return 0xff;
-
- millivolts -= 625;
-
- return millivolts / 25;
-}
-
-static u8 ldo_voltage_bits(unsigned int millivolts)
-{
- if (millivolts < 900)
- return 0;
- else if (millivolts > 3600)
- return 0x1f;
-
- millivolts -= 900;
- return millivolts / 100;
-}
-
-/* Obtain voltage value from bits */
-static unsigned int auto_voltage_value(u8 bits)
-{
- /* AUTOOUT: 00000000 to 00101110 are reserved.
- * Return 0 for bits in reserved range, which means this selector code
- * can't be used on this system */
- if (bits < 0x2f)
- return 0;
-
- return 625 + (bits * 25);
-}
-
-
-static unsigned int down_voltage_value(u8 bits)
-{
- return 625 + (bits * 25);
-}
-
-
-static unsigned int ldo_voltage_value(u8 bits)
-{
- bits &= 0x1f;
-
- return 900 + (bits * 100);
-}
-
-static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- struct pcf50633 *pcf;
- int regulator_id, millivolts;
- u8 volt_bits;
-
- pcf = rdev_get_drvdata(rdev);
-
- regulator_id = rdev_get_id(rdev);
- if (regulator_id >= PCF50633_NUM_REGULATORS)
- return -EINVAL;
-
- millivolts = min_uV / 1000;
-
- switch (regulator_id) {
- case PCF50633_REGULATOR_AUTO:
- volt_bits = auto_voltage_bits(millivolts);
- break;
- case PCF50633_REGULATOR_DOWN1:
- case PCF50633_REGULATOR_DOWN2:
- volt_bits = down_voltage_bits(millivolts);
- break;
- case PCF50633_REGULATOR_LDO1:
- case PCF50633_REGULATOR_LDO2:
- case PCF50633_REGULATOR_LDO3:
- case PCF50633_REGULATOR_LDO4:
- case PCF50633_REGULATOR_LDO5:
- case PCF50633_REGULATOR_LDO6:
- case PCF50633_REGULATOR_HCLDO:
- case PCF50633_REGULATOR_MEMLDO:
- volt_bits = ldo_voltage_bits(millivolts);
- break;
- default:
- return -EINVAL;
- }
-
- return volt_bits;
-}
-
-static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
- unsigned int index)
-{
- int regulator_id = rdev_get_id(rdev);
-
- int millivolts;
-
- switch (regulator_id) {
- case PCF50633_REGULATOR_AUTO:
- millivolts = auto_voltage_value(index);
- break;
- case PCF50633_REGULATOR_DOWN1:
- case PCF50633_REGULATOR_DOWN2:
- millivolts = down_voltage_value(index);
- break;
- case PCF50633_REGULATOR_LDO1:
- case PCF50633_REGULATOR_LDO2:
- case PCF50633_REGULATOR_LDO3:
- case PCF50633_REGULATOR_LDO4:
- case PCF50633_REGULATOR_LDO5:
- case PCF50633_REGULATOR_LDO6:
- case PCF50633_REGULATOR_HCLDO:
- case PCF50633_REGULATOR_MEMLDO:
- millivolts = ldo_voltage_value(index);
- break;
- default:
- return -EINVAL;
- }
-
- return millivolts * 1000;
-}
-
static struct regulator_ops pcf50633_regulator_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
- .list_voltage = pcf50633_regulator_list_voltage,
- .map_voltage = pcf50633_regulator_map_voltage,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_desc regulators[] = {
- [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
- [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
- [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
- [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
- [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
- [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
- [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
- [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
- [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
- [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
- [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
+ [PCF50633_REGULATOR_AUTO] =
+ PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
+ [PCF50633_REGULATOR_DOWN1] =
+ PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
+ [PCF50633_REGULATOR_DOWN2] =
+ PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
+ [PCF50633_REGULATOR_LDO1] =
+ PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_LDO2] =
+ PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_LDO3] =
+ PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_LDO4] =
+ PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_LDO5] =
+ PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_LDO6] =
+ PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_HCLDO] =
+ PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
+ [PCF50633_REGULATOR_MEMLDO] =
+ PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
};
-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+static int pcf50633_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
struct pcf50633 *pcf;
@@ -222,7 +102,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+static int pcf50633_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -237,7 +117,7 @@ static struct platform_driver pcf50633_regulator_driver = {
.name = "pcf50633-regltr",
},
.probe = pcf50633_regulator_probe,
- .remove = __devexit_p(pcf50633_regulator_remove),
+ .remove = pcf50633_regulator_remove,
};
static int __init pcf50633_regulator_init(void)
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
index 8bf4e8c9de9a..9e6f78694bf1 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
};
-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+static int rc5t583_regulator_probe(struct platform_device *pdev)
{
struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -198,7 +198,7 @@ clean_exit:
return ret;
}
-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+static int rc5t583_regulator_remove(struct platform_device *pdev)
{
struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
int id;
@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = rc5t583_regulator_probe,
- .remove = __devexit_p(rc5t583_regulator_remove),
+ .remove = rc5t583_regulator_remove,
};
static int __init rc5t583_regulator_init(void)
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 926f9c8f2fac..bd062a2ffbe2 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
regulator_desc_buck10,
};
-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+static int s2mps11_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
if (ramp_enable) {
if (s2mps11->buck2_ramp)
- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
}
ramp_reg &= 0x00;
- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
@@ -307,7 +307,7 @@ err:
return ret;
}
-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+static int s2mps11_pmic_remove(struct platform_device *pdev)
{
struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
int i;
@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s2mps11_pmic_probe,
- .remove = __devexit_p(s2mps11_pmic_remove),
+ .remove = s2mps11_pmic_remove,
.id_table = s2mps11_pmic_id,
};
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index abe64a32aedf..9f991f2c525a 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -168,7 +168,7 @@ static unsigned int s5m8767_opmode_reg[][4] = {
static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
int *enable_ctrl)
{
- int reg_id = rdev_get_id(rdev);
+ int i, reg_id = rdev_get_id(rdev);
unsigned int mode;
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
@@ -195,8 +195,17 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
return -EINVAL;
}
- mode = s5m8767->opmode[reg_id].mode;
- *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+ for (i = 0; i < s5m8767->num_regulators; i++) {
+ if (s5m8767->opmode[i].id == reg_id) {
+ mode = s5m8767->opmode[i].mode;
+ break;
+ }
+ }
+
+ if (i < s5m8767->num_regulators)
+ *enable_ctrl =
+ s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+
return 0;
}
@@ -263,17 +272,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
reg = S5M8767_REG_BUCK1CTRL2;
break;
case S5M8767_BUCK2:
- reg = S5M8767_REG_BUCK2DVS2;
+ reg = S5M8767_REG_BUCK2DVS1;
if (s5m8767->buck2_gpiodvs)
reg += s5m8767->buck_gpioindex;
break;
case S5M8767_BUCK3:
- reg = S5M8767_REG_BUCK3DVS2;
+ reg = S5M8767_REG_BUCK3DVS1;
if (s5m8767->buck3_gpiodvs)
reg += s5m8767->buck_gpioindex;
break;
case S5M8767_BUCK4:
- reg = S5M8767_REG_BUCK4DVS2;
+ reg = S5M8767_REG_BUCK4DVS1;
if (s5m8767->buck4_gpiodvs)
reg += s5m8767->buck_gpioindex;
break;
@@ -499,7 +508,7 @@ static struct regulator_desc regulators[] = {
s5m8767_regulator_desc(BUCK9),
};
-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+static int s5m8767_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -547,7 +556,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
rdev = s5m8767->rdev;
s5m8767->dev = &pdev->dev;
s5m8767->iodev = iodev;
- s5m8767->num_regulators = S5M8767_REG_MAX - 2;
+ s5m8767->num_regulators = pdata->num_regulators;
platform_set_drvdata(pdev, s5m8767);
s5m8767->buck_gpioindex = pdata->buck_default_idx;
@@ -617,9 +626,16 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
}
}
- if (gpio_is_valid(pdata->buck_gpios[0]) &&
- gpio_is_valid(pdata->buck_gpios[1]) &&
- gpio_is_valid(pdata->buck_gpios[2])) {
+ if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
+ pdata->buck4_gpiodvs) {
+
+ if (!gpio_is_valid(pdata->buck_gpios[0]) ||
+ !gpio_is_valid(pdata->buck_gpios[1]) ||
+ !gpio_is_valid(pdata->buck_gpios[2])) {
+ dev_err(&pdev->dev, "GPIO NOT VALID\n");
+ return -EINVAL;
+ }
+
ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
"S5M8767 SET1");
if (ret)
@@ -644,10 +660,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
/* SET3 GPIO */
gpio_direction_output(pdata->buck_gpios[2],
(s5m8767->buck_gpioindex >> 0) & 0x1);
- } else {
- dev_err(&pdev->dev, "GPIO NOT VALID\n");
- ret = -EINVAL;
- return ret;
}
ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
@@ -773,7 +785,7 @@ err:
return ret;
}
-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+static int s5m8767_pmic_remove(struct platform_device *pdev)
{
struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = s5m8767->rdev;
@@ -798,7 +810,7 @@ static struct platform_driver s5m8767_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s5m8767_pmic_probe,
- .remove = __devexit_p(s5m8767_pmic_remove),
+ .remove = s5m8767_pmic_remove,
.id_table = s5m8767_pmic_id,
};
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644
index 000000000000..ab21133e6784
--- /dev/null
+++ b/drivers/regulator/tps51632-regulator.c
@@ -0,0 +1,342 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG 0x0
+#define TPS51632_VOLTAGE_BASE_REG 0x1
+#define TPS51632_OFFSET_REG 0x2
+#define TPS51632_IMON_REG 0x3
+#define TPS51632_VMAX_REG 0x4
+#define TPS51632_DVFS_CONTROL_REG 0x5
+#define TPS51632_POWER_STATE_REG 0x6
+#define TPS51632_SLEW_REGS 0x7
+#define TPS51632_FAULT_REG 0x14
+
+#define TPS51632_MAX_REG 0x15
+
+#define TPS51632_VOUT_MASK 0x7F
+#define TPS51632_VOUT_OFFSET_MASK 0x1F
+#define TPS51632_VMAX_MASK 0x7F
+#define TPS51632_VMAX_LOCK 0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN 0x1
+#define TPS51632_DVFS_STEP_20 0x2
+#define TPS51632_DVFS_VMAX_PG 0x4
+#define TPS51632_DVFS_PWMRST 0x8
+#define TPS51632_DVFS_OCA_EN 0x10
+#define TPS51632_DVFS_FCCM 0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK 0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM 0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM 0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM 0x2
+
+#define TPS51632_MIN_VOLATGE 500000
+#define TPS51632_MAX_VOLATGE 1520000
+#define TPS51632_VOLATGE_STEP_10mV 10000
+#define TPS51632_VOLATGE_STEP_20mV 20000
+#define TPS51632_MAX_VSEL 0x7F
+#define TPS51632_MIN_VSEL 0x19
+#define TPS51632_DEFAULT_RAMP_DELAY 6000
+#define TPS51632_VOLT_VSEL(uV) \
+ (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE, \
+ TPS51632_VOLATGE_STEP_10mV) + \
+ TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret;
+ unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+ int vsel;
+
+ if (tps->enable_pwm_dvfs)
+ reg = TPS51632_VOLTAGE_BASE_REG;
+
+ ret = regmap_read(tps->regmap, reg, &data);
+ if (ret < 0) {
+ dev_err(tps->dev, "reg read failed, err %d\n", ret);
+ return ret;
+ }
+
+ vsel = data & TPS51632_VOUT_MASK;
+ return vsel;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ int ret;
+ unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+ if (tps->enable_pwm_dvfs)
+ reg = TPS51632_VOLTAGE_BASE_REG;
+
+ if (selector > TPS51632_MAX_VSEL)
+ return -EINVAL;
+
+ ret = regmap_write(tps->regmap, reg, selector);
+ if (ret < 0)
+ dev_err(tps->dev, "reg write failed, err %d\n", ret);
+ return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+ int ramp_delay)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ int bit = ramp_delay/6000;
+ int ret;
+
+ if (bit)
+ bit--;
+ ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+ if (ret < 0)
+ dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+ return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+ .get_voltage_sel = tps51632_dcdc_get_voltage_sel,
+ .set_voltage_sel = tps51632_dcdc_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = tps51632_dcdc_set_ramp_delay,
+};
+
+static int tps51632_init_dcdc(struct tps51632_chip *tps,
+ struct tps51632_regulator_platform_data *pdata)
+{
+ int ret;
+ uint8_t control = 0;
+ int vsel;
+
+ if (!pdata->enable_pwm_dvfs)
+ goto skip_pwm_config;
+
+ control |= TPS51632_DVFS_PWMEN;
+ tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+ vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+ ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+ if (ret < 0) {
+ dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+ return ret;
+ }
+
+ if (pdata->dvfs_step_20mV)
+ control |= TPS51632_DVFS_STEP_20;
+
+ if (pdata->max_voltage_uV) {
+ unsigned int vmax;
+ /**
+ * TPS51632 hw behavior: VMAX register can be write only
+ * once as it get locked after first write. The lock get
+ * reset only when device is power-reset.
+ * Write register only when lock bit is not enabled.
+ */
+ ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+ if (ret < 0) {
+ dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+ return ret;
+ }
+ if (!(vmax & TPS51632_VMAX_LOCK)) {
+ vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+ ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+ vsel);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "VMAX write failed, err %d\n", ret);
+ return ret;
+ }
+ }
+ }
+
+skip_pwm_config:
+ ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+ if (ret < 0)
+ dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+ return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+ if ((reg >= 0x8) && (reg <= 0x10))
+ return false;
+ return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg,
+ .readable_reg = rd_wr_reg,
+ .max_register = TPS51632_MAX_REG - 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int tps51632_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tps51632_regulator_platform_data *pdata;
+ struct regulator_dev *rdev;
+ struct tps51632_chip *tps;
+ int ret;
+ struct regulator_config config = { };
+
+ pdata = client->dev.platform_data;
+ if (!pdata) {
+ dev_err(&client->dev, "No Platform data\n");
+ return -EINVAL;
+ }
+
+ if (pdata->enable_pwm_dvfs) {
+ if ((pdata->base_voltage_uV < TPS51632_MIN_VOLATGE) ||
+ (pdata->base_voltage_uV > TPS51632_MAX_VOLATGE)) {
+ dev_err(&client->dev, "Invalid base_voltage_uV setting\n");
+ return -EINVAL;
+ }
+
+ if ((pdata->max_voltage_uV) &&
+ ((pdata->max_voltage_uV < TPS51632_MIN_VOLATGE) ||
+ (pdata->max_voltage_uV > TPS51632_MAX_VOLATGE))) {
+ dev_err(&client->dev, "Invalid max_voltage_uV setting\n");
+ return -EINVAL;
+ }
+ }
+
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps) {
+ dev_err(&client->dev, "Memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ tps->dev = &client->dev;
+ tps->desc.name = id->name;
+ tps->desc.id = 0;
+ tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+ tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+ tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+ tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+ tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+ tps->desc.ops = &tps51632_dcdc_ops;
+ tps->desc.type = REGULATOR_VOLTAGE;
+ tps->desc.owner = THIS_MODULE;
+
+ tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+ if (IS_ERR(tps->regmap)) {
+ ret = PTR_ERR(tps->regmap);
+ dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+ return ret;
+ }
+ i2c_set_clientdata(client, tps);
+
+ ret = tps51632_init_dcdc(tps, pdata);
+ if (ret < 0) {
+ dev_err(tps->dev, "Init failed, err = %d\n", ret);
+ return ret;
+ }
+
+ /* Register the regulators */
+ config.dev = &client->dev;
+ config.init_data = pdata->reg_init_data;
+ config.driver_data = tps;
+ config.regmap = tps->regmap;
+ config.of_node = client->dev.of_node;
+
+ rdev = regulator_register(&tps->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(tps->dev, "regulator register failed\n");
+ return PTR_ERR(rdev);
+ }
+
+ tps->rdev = rdev;
+ return 0;
+}
+
+static int tps51632_remove(struct i2c_client *client)
+{
+ struct tps51632_chip *tps = i2c_get_clientdata(client);
+
+ regulator_unregister(tps->rdev);
+ return 0;
+}
+
+static const struct i2c_device_id tps51632_id[] = {
+ {.name = "tps51632",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+ .driver = {
+ .name = "tps51632",
+ .owner = THIS_MODULE,
+ },
+ .probe = tps51632_probe,
+ .remove = tps51632_remove,
+ .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+ return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+ i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index 1378409efaec..ec9453ffb77f 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
/*
* Registers the chip as a voltage regulator
*/
-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+static int tps6105x_regulator_probe(struct platform_device *pdev)
{
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
struct tps6105x_platform_data *pdata = tps6105x->pdata;
@@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+static int tps6105x_regulator_remove(struct platform_device *pdev)
{
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
regulator_unregister(tps6105x->regulator);
@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = tps6105x_regulator_probe,
- .remove = __devexit_p(tps6105x_regulator_remove),
+ .remove = tps6105x_regulator_remove,
};
static __init int tps6105x_regulator_init(void)
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 68729a7c8709..acbd63fde415 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
.get_mode = tps62360_get_mode,
};
-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
+static int tps62360_init_dcdc(struct tps62360_chip *tps,
struct tps62360_regulator_platform_data *pdata)
{
int ret;
@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
MODULE_DEVICE_TABLE(of, tps62360_of_match);
#endif
-static int __devinit tps62360_probe(struct i2c_client *client,
+static int tps62360_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regulator_config config = { };
@@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
*
* Unregister TPS driver as an i2c client device driver
*/
-static int __devexit tps62360_remove(struct i2c_client *client)
+static int tps62360_remove(struct i2c_client *client)
{
struct tps62360_chip *tps = i2c_get_clientdata(client);
@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
.of_match_table = of_match_ptr(tps62360_of_match),
},
.probe = tps62360_probe,
- .remove = __devexit_p(tps62360_remove),
+ .remove = tps62360_remove,
.shutdown = tps62360_shutdown,
.id_table = tps62360_id,
};
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 6998d579d07b..9b9af6d889c8 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
.val_bits = 8,
};
-static int __devinit tps_65023_probe(struct i2c_client *client,
+static int tps_65023_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct tps_driver_data *drv_data = (void *)id->driver_data;
@@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
return error;
}
-static int __devexit tps_65023_remove(struct i2c_client *client)
+static int tps_65023_remove(struct i2c_client *client)
{
struct tps_pmic *tps = i2c_get_clientdata(client);
int i;
@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = tps_65023_probe,
- .remove = __devexit_p(tps_65023_remove),
+ .remove = tps_65023_remove,
.id_table = tps_65023_id,
};
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 07d01ccdf308..0233cfb56560 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
.list_voltage = regulator_list_voltage_table,
};
-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
+static int tps6507x_pmic_probe(struct platform_device *pdev)
{
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
struct tps_info *info = &tps6507x_pmic_regs[0];
@@ -439,7 +439,7 @@ fail:
return error;
}
-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
+static int tps6507x_pmic_remove(struct platform_device *pdev)
{
struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
struct tps6507x_pmic *tps = tps6507x_dev->pmic;
@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = tps6507x_pmic_probe,
- .remove = __devexit_p(tps6507x_pmic_remove),
+ .remove = tps6507x_pmic_remove,
};
static int __init tps6507x_pmic_init(void)
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 001ad554ac62..41c391789c97 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -18,119 +18,240 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
struct tps65090_regulator {
- int id;
- /* used by regulator core */
- struct regulator_desc desc;
-
- /* Device */
struct device *dev;
+ struct regulator_desc *desc;
+ struct regulator_dev *rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
};
-static struct regulator_ops tps65090_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
};
-#define tps65090_REG(_id) \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops) \
{ \
- .id = TPS65090_ID_##_id, \
- .desc = { \
- .name = tps65090_rails(_id), \
- .id = TPS65090_ID_##_id, \
- .ops = &tps65090_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- .enable_reg = (TPS65090_ID_##_id) + 12, \
- .enable_mask = BIT(0), \
- }, \
+ .name = "TPS65090_RAILS"#_id, \
+ .supply_name = _sname, \
+ .id = TPS65090_REGULATOR_##_id, \
+ .ops = &_ops, \
+ .enable_reg = _en_reg, \
+ .enable_mask = BIT(0), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
}
-static struct tps65090_regulator TPS65090_regulator[] = {
- tps65090_REG(DCDC1),
- tps65090_REG(DCDC2),
- tps65090_REG(DCDC3),
- tps65090_REG(FET1),
- tps65090_REG(FET2),
- tps65090_REG(FET3),
- tps65090_REG(FET4),
- tps65090_REG(FET5),
- tps65090_REG(FET6),
- tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+ tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops),
+ tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops),
};
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
{
- struct tps65090_regulator *ri;
- int i;
+ switch (id) {
+ case TPS65090_REGULATOR_DCDC1:
+ case TPS65090_REGULATOR_DCDC2:
+ case TPS65090_REGULATOR_DCDC3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int tps65090_config_ext_control(
+ struct tps65090_regulator *ri, bool enable)
+{
+ int ret;
+ struct device *parent = ri->dev->parent;
+ unsigned int reg_en_reg = ri->desc->enable_reg;
+
+ if (enable)
+ ret = tps65090_set_bits(parent, reg_en_reg, 1);
+ else
+ ret = tps65090_clr_bits(parent, reg_en_reg, 1);
+ if (ret < 0)
+ dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+ return ret;
+}
+
+static int tps65090_regulator_disable_ext_control(
+ struct tps65090_regulator *ri,
+ struct tps65090_regulator_plat_data *tps_pdata)
+{
+ int ret = 0;
+ struct device *parent = ri->dev->parent;
+ unsigned int reg_en_reg = ri->desc->enable_reg;
+
+ /*
+ * First enable output for internal control if require.
+ * And then disable external control.
+ */
+ if (tps_pdata->reg_init_data->constraints.always_on ||
+ tps_pdata->reg_init_data->constraints.boot_on) {
+ ret = tps65090_set_bits(parent, reg_en_reg, 0);
+ if (ret < 0) {
+ dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+ return ret;
+ }
+ }
+ return tps65090_config_ext_control(ri, false);
+}
+
+static void tps65090_configure_regulator_config(
+ struct tps65090_regulator_plat_data *tps_pdata,
+ struct regulator_config *config)
+{
+ if (gpio_is_valid(tps_pdata->gpio)) {
+ int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+ if (tps_pdata->reg_init_data->constraints.always_on ||
+ tps_pdata->reg_init_data->constraints.boot_on)
+ gpio_flag = GPIOF_OUT_INIT_HIGH;
- for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
- ri = &TPS65090_regulator[i];
- if (ri->desc.id == id)
- return ri;
+ config->ena_gpio = tps_pdata->gpio;
+ config->ena_gpio_flags = gpio_flag;
}
- return NULL;
}
-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+static int tps65090_regulator_probe(struct platform_device *pdev)
{
struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
struct tps65090_regulator *ri = NULL;
struct regulator_config config = { };
struct regulator_dev *rdev;
- struct tps65090_regulator_platform_data *tps_pdata;
- int id = pdev->id;
+ struct tps65090_regulator_plat_data *tps_pdata;
+ struct tps65090_regulator *pmic;
+ struct tps65090_platform_data *tps65090_pdata;
+ int num;
+ int ret;
- dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+ dev_dbg(&pdev->dev, "Probing regulator\n");
- ri = find_regulator_info(id);
- if (ri == NULL) {
- dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps65090_pdata) {
+ dev_err(&pdev->dev, "Platform data missing\n");
return -EINVAL;
}
- tps_pdata = pdev->dev.platform_data;
- ri->dev = &pdev->dev;
-
- config.dev = &pdev->dev;
- config.init_data = &tps_pdata->regulator;
- config.driver_data = ri;
- config.regmap = tps65090_mfd->rmap;
-
- rdev = regulator_register(&ri->desc, &config);
- if (IS_ERR(rdev)) {
- dev_err(&pdev->dev, "failed to register regulator %s\n",
- ri->desc.name);
- return PTR_ERR(rdev);
+
+ pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+ GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+ return -ENOMEM;
+ }
+
+ for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+ tps_pdata = tps65090_pdata->reg_pdata[num];
+
+ ri = &pmic[num];
+ ri->dev = &pdev->dev;
+ ri->desc = &tps65090_regulator_desc[num];
+
+ /*
+ * TPS5090 DCDC support the control from external digital input.
+ * Configure it as per platform data.
+ */
+ if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+ if (tps_pdata->enable_ext_control) {
+ tps65090_configure_regulator_config(
+ tps_pdata, &config);
+ ri->desc->ops = &tps65090_ext_control_ops;
+ } else {
+ ret = tps65090_regulator_disable_ext_control(
+ ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "failed disable ext control\n");
+ goto scrub;
+ }
+ }
+ }
+
+ config.dev = &pdev->dev;
+ config.driver_data = ri;
+ config.regmap = tps65090_mfd->rmap;
+ if (tps_pdata)
+ config.init_data = tps_pdata->reg_init_data;
+ else
+ config.init_data = NULL;
+
+ rdev = regulator_register(ri->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->desc->name);
+ ret = PTR_ERR(rdev);
+ goto scrub;
+ }
+ ri->rdev = rdev;
+
+ /* Enable external control if it is require */
+ if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
+ tps_pdata->enable_ext_control) {
+ ret = tps65090_config_ext_control(ri, true);
+ if (ret < 0) {
+ /* Increment num to get unregister rdev */
+ num++;
+ goto scrub;
+ }
+ }
}
- platform_set_drvdata(pdev, rdev);
+ platform_set_drvdata(pdev, pmic);
return 0;
+
+scrub:
+ while (--num >= 0) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
+ return ret;
}
-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+static int tps65090_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+ struct tps65090_regulator *ri;
+ int num;
- regulator_unregister(rdev);
+ for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
return 0;
}
static struct platform_driver tps65090_regulator_driver = {
.driver = {
- .name = "tps65090-regulator",
+ .name = "tps65090-pmic",
.owner = THIS_MODULE,
},
.probe = tps65090_regulator_probe,
- .remove = __devexit_p(tps65090_regulator_remove),
+ .remove = tps65090_regulator_remove,
};
static int __init tps65090_regulator_init(void)
@@ -148,3 +269,4 @@ module_exit(tps65090_regulator_exit);
MODULE_DESCRIPTION("tps65090 regulator driver");
MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65090-pmic");
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index ab00cab905b7..73dce7664126 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
}
#endif
-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
+static int tps65217_regulator_probe(struct platform_device *pdev)
{
struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
struct tps65217_board *pdata = dev_get_platdata(tps->dev);
@@ -397,7 +397,7 @@ err_unregister_regulator:
return ret;
}
-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
+static int tps65217_regulator_remove(struct platform_device *pdev)
{
struct tps65217 *tps = platform_get_drvdata(pdev);
unsigned int i;
@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
.name = "tps65217-pmic",
},
.probe = tps65217_regulator_probe,
- .remove = __devexit_p(tps65217_regulator_remove),
+ .remove = tps65217_regulator_remove,
};
static int __init tps65217_regulator_init(void)
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 058d2f2675e9..843ee0a9bb92 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
return 0;
}
-static int __devinit pmic_probe(struct spi_device *spi)
+static int pmic_probe(struct spi_device *spi)
{
struct tps6524x *hw;
struct device *dev = &spi->dev;
@@ -649,7 +649,7 @@ fail:
static struct spi_driver pmic_driver = {
.probe = pmic_probe,
- .remove = __devexit_p(pmic_remove),
+ .remove = pmic_remove,
.driver = {
.name = "tps6524x",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index ce1e7cb8d513..f86da672c758 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -17,10 +17,12 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/of.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/mfd/tps6586x.h>
/* supply control and voltage setting */
@@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
1 << ri->enable_bit[1]);
}
-static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
+static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
+ int id, struct regulator_init_data *p)
{
struct device *parent = pdev->dev.parent;
- struct regulator_init_data *p = pdev->dev.platform_data;
struct tps6586x_settings *setting = p->driver_data;
uint8_t reg;
@@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
return 0;
/* only SM0 and SM1 can have the slew rate settings */
- switch (pdev->id) {
+ switch (id) {
case TPS6586X_ID_SM_0:
reg = TPS6586X_SM0SL;
break;
@@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
return NULL;
}
-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct of_regulator_match tps6586x_matches[] = {
+ { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
+ { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
+ { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
+ { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
+ { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
+ { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
+ { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
+ { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
+ { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
+ { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
+ { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
+ { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
+ { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
+ { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
+ { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
+};
+
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+ struct platform_device *pdev,
+ struct of_regulator_match **tps6586x_reg_matches)
+{
+ const unsigned int num = ARRAY_SIZE(tps6586x_matches);
+ struct device_node *np = pdev->dev.parent->of_node;
+ struct device_node *regs;
+ const char *sys_rail = NULL;
+ unsigned int i;
+ struct tps6586x_platform_data *pdata;
+ int err;
+
+ regs = of_find_node_by_name(np, "regulators");
+ if (!regs) {
+ dev_err(&pdev->dev, "regulator node not found\n");
+ return NULL;
+ }
+
+ err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
+ of_node_put(regs);
+ return NULL;
+ }
+
+ of_node_put(regs);
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "Memory alloction failed\n");
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ int id;
+ if (!tps6586x_matches[i].init_data)
+ continue;
+
+ pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
+ id = (int)tps6586x_matches[i].driver_data;
+ if (id == TPS6586X_ID_SYS)
+ sys_rail = pdata->reg_init_data[i]->constraints.name;
+
+ if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
+ pdata->reg_init_data[i]->supply_regulator = sys_rail;
+ }
+ *tps6586x_reg_matches = tps6586x_matches;
+ return pdata;
+}
+#else
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+ struct platform_device *pdev,
+ struct of_regulator_match **tps6586x_reg_matches)
+{
+ *tps6586x_reg_matches = NULL;
+ return NULL;
+}
+#endif
+
+static int tps6586x_regulator_probe(struct platform_device *pdev)
{
struct tps6586x_regulator *ri = NULL;
struct regulator_config config = { };
- struct regulator_dev *rdev;
- int id = pdev->id;
+ struct regulator_dev **rdev;
+ struct regulator_init_data *reg_data;
+ struct tps6586x_platform_data *pdata;
+ struct of_regulator_match *tps6586x_reg_matches = NULL;
+ int id;
int err;
- dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+ dev_dbg(&pdev->dev, "Probing regulator\n");
- ri = find_regulator_info(id);
- if (ri == NULL) {
- dev_err(&pdev->dev, "invalid regulator ID specified\n");
- return -EINVAL;
- }
+ pdata = dev_get_platdata(pdev->dev.parent);
+ if ((!pdata) && (pdev->dev.parent->of_node))
+ pdata = tps6586x_parse_regulator_dt(pdev,
+ &tps6586x_reg_matches);
- err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
- if (err)
- return err;
+ if (!pdata) {
+ dev_err(&pdev->dev, "Platform data not available, exiting\n");
+ return -ENODEV;
+ }
- config.dev = pdev->dev.parent;
- config.of_node = pdev->dev.of_node;
- config.init_data = pdev->dev.platform_data;
- config.driver_data = ri;
+ rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
+ sizeof(*rdev), GFP_KERNEL);
+ if (!rdev) {
+ dev_err(&pdev->dev, "Mmemory alloc failed\n");
+ return -ENOMEM;
+ }
- rdev = regulator_register(&ri->desc, &config);
- if (IS_ERR(rdev)) {
- dev_err(&pdev->dev, "failed to register regulator %s\n",
- ri->desc.name);
- return PTR_ERR(rdev);
+ for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
+ reg_data = pdata->reg_init_data[id];
+
+ ri = find_regulator_info(id);
+ if (!ri) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ err = -EINVAL;
+ goto fail;
+ }
+
+ err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
+ if (err) {
+ dev_err(&pdev->dev,
+ "regulator %d preinit failed, e %d\n", id, err);
+ goto fail;
+ }
+
+ config.dev = pdev->dev.parent;
+ config.init_data = reg_data;
+ config.driver_data = ri;
+
+ if (tps6586x_reg_matches)
+ config.of_node = tps6586x_reg_matches[id].of_node;
+
+ rdev[id] = regulator_register(&ri->desc, &config);
+ if (IS_ERR(rdev[id])) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->desc.name);
+ err = PTR_ERR(rdev[id]);
+ goto fail;
+ }
+
+ if (reg_data) {
+ err = tps6586x_regulator_set_slew_rate(pdev, id,
+ reg_data);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Slew rate config failed, e %d\n", err);
+ regulator_unregister(rdev[id]);
+ goto fail;
+ }
+ }
}
platform_set_drvdata(pdev, rdev);
+ return 0;
- return tps6586x_regulator_set_slew_rate(pdev);
+fail:
+ while (--id >= 0)
+ regulator_unregister(rdev[id]);
+ return err;
}
-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
+static int tps6586x_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct regulator_dev **rdev = platform_get_drvdata(pdev);
+ int id = TPS6586X_ID_MAX_REGULATOR;
+
+ while (--id >= 0)
+ regulator_unregister(rdev[id]);
- regulator_unregister(rdev);
return 0;
}
static struct platform_driver tps6586x_regulator_driver = {
.driver = {
- .name = "tps6586x-regulator",
+ .name = "tps6586x-pmic",
.owner = THIS_MODULE,
},
.probe = tps6586x_regulator_probe,
- .remove = __devexit_p(tps6586x_regulator_remove),
+ .remove = tps6586x_regulator_remove,
};
static int __init tps6586x_regulator_init(void)
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 793adda560c3..59c3770fa77d 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
/* VSEL tables for TPS65910 specific LDOs and dcdc's */
+/* supported VRTC voltages in microvolts */
+static const unsigned int VRTC_VSEL_table[] = {
+ 1800000,
+};
+
/* supported VDD3 voltages in microvolts */
static const unsigned int VDD3_VSEL_table[] = {
5000000,
@@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
{
.name = "vrtc",
.vin_name = "vcc7",
+ .n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
+ .voltage_table = VRTC_VSEL_table,
.enable_time_us = 2200,
},
{
@@ -1026,7 +1033,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
}
#endif
-static __devinit int tps65910_probe(struct platform_device *pdev)
+static int tps65910_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
@@ -1184,7 +1191,7 @@ err_unregister_regulator:
return err;
}
-static int __devexit tps65910_remove(struct platform_device *pdev)
+static int tps65910_remove(struct platform_device *pdev)
{
struct tps65910_reg *pmic = platform_get_drvdata(pdev);
int i;
@@ -1231,7 +1238,7 @@ static struct platform_driver tps65910_driver = {
.owner = THIS_MODULE,
},
.probe = tps65910_probe,
- .remove = __devexit_p(tps65910_remove),
+ .remove = tps65910_remove,
.shutdown = tps65910_shutdown,
};
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 18b2a1dcb4b5..17e994e47dc1 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
.list_voltage = tps65912_list_voltage,
};
-static __devinit int tps65912_probe(struct platform_device *pdev)
+static int tps65912_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
@@ -525,7 +525,7 @@ err:
return err;
}
-static int __devexit tps65912_remove(struct platform_device *pdev)
+static int tps65912_remove(struct platform_device *pdev)
{
struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
int i;
@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
.owner = THIS_MODULE,
},
.probe = tps65912_probe,
- .remove = __devexit_p(tps65912_remove),
+ .remove = tps65912_remove,
};
static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
new file mode 100644
index 000000000000..b15d711bc8c6
--- /dev/null
+++ b/drivers/regulator/tps80031-regulator.c
@@ -0,0 +1,788 @@
+/*
+ * tps80031-regulator.c -- TI TPS80031 regulator driver.
+ *
+ * Regulator driver for TI TPS80031/TPS80032 Fully Integrated Power
+ * Management with Power Path and Battery Charger.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+/* Flags for DCDC Voltage reading */
+#define DCDC_OFFSET_EN BIT(0)
+#define DCDC_EXTENDED_EN BIT(1)
+#define TRACK_MODE_ENABLE BIT(2)
+
+#define SMPS_MULTOFFSET_VIO BIT(1)
+#define SMPS_MULTOFFSET_SMPS1 BIT(3)
+#define SMPS_MULTOFFSET_SMPS2 BIT(4)
+#define SMPS_MULTOFFSET_SMPS3 BIT(6)
+#define SMPS_MULTOFFSET_SMPS4 BIT(0)
+
+#define SMPS_CMD_MASK 0xC0
+#define SMPS_VSEL_MASK 0x3F
+#define LDO_VSEL_MASK 0x1F
+#define LDO_TRACK_VSEL_MASK 0x3F
+
+#define MISC2_LDOUSB_IN_VSYS BIT(4)
+#define MISC2_LDOUSB_IN_PMID BIT(3)
+#define MISC2_LDOUSB_IN_MASK 0x18
+
+#define MISC2_LDO3_SEL_VIB_VAL BIT(0)
+#define MISC2_LDO3_SEL_VIB_MASK 0x1
+
+#define BOOST_HW_PWR_EN BIT(5)
+#define BOOST_HW_PWR_EN_MASK BIT(5)
+
+#define OPA_MODE_EN BIT(6)
+#define OPA_MODE_EN_MASK BIT(6)
+
+#define USB_VBUS_CTRL_SET 0x04
+#define USB_VBUS_CTRL_CLR 0x05
+#define VBUS_DISCHRG 0x20
+
+struct tps80031_regulator_info {
+ /* Regulator register address.*/
+ u8 trans_reg;
+ u8 state_reg;
+ u8 force_reg;
+ u8 volt_reg;
+ u8 volt_id;
+
+ /*Power request bits */
+ int preq_bit;
+
+ /* used by regulator core */
+ struct regulator_desc desc;
+
+};
+
+struct tps80031_regulator {
+ struct device *dev;
+ struct regulator_dev *rdev;
+ struct tps80031_regulator_info *rinfo;
+
+ u8 device_flags;
+ unsigned int config_flags;
+ unsigned int ext_ctrl_flag;
+};
+
+static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
+{
+ return rdev_get_dev(rdev)->parent->parent;
+}
+
+static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ u8 reg_val;
+ int ret;
+
+ if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+ return true;
+
+ ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+ &reg_val);
+ if (ret < 0) {
+ dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
+ ri->rinfo->state_reg, ret);
+ return ret;
+ }
+ return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
+}
+
+static int tps80031_reg_enable(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret;
+
+ if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+ return 0;
+
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+ TPS80031_STATE_ON, TPS80031_STATE_MASK);
+ if (ret < 0) {
+ dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+ ri->rinfo->state_reg, ret);
+ return ret;
+ }
+ return ret;
+}
+
+static int tps80031_reg_disable(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret;
+
+ if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+ return 0;
+
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+ TPS80031_STATE_OFF, TPS80031_STATE_MASK);
+ if (ret < 0)
+ dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+ ri->rinfo->state_reg, ret);
+ return ret;
+}
+
+/* DCDC voltages for the selector of 58 to 63 */
+static int tps80031_dcdc_voltages[4][5] = {
+ { 1350, 1500, 1800, 1900, 2100},
+ { 1350, 1500, 1800, 1900, 2100},
+ { 2084, 2315, 2778, 2932, 3241},
+ { 4167, 2315, 2778, 2932, 3241},
+};
+
+static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ int volt_index = ri->device_flags & 0x3;
+
+ if (sel == 0)
+ return 0;
+ else if (sel < 58)
+ return regulator_list_voltage_linear(rdev, sel - 1);
+ else
+ return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
+}
+
+static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned vsel)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret;
+ u8 reg_val;
+
+ if (ri->rinfo->force_reg) {
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->force_reg, &reg_val);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ ri->rinfo->force_reg, ret);
+ return ret;
+ }
+ if (!(reg_val & SMPS_CMD_MASK)) {
+ ret = tps80031_update(parent, ri->rinfo->volt_id,
+ ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
+ if (ret < 0)
+ dev_err(ri->dev,
+ "reg 0x%02x update failed, e = %d\n",
+ ri->rinfo->force_reg, ret);
+ return ret;
+ }
+ }
+ ret = tps80031_update(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
+ if (ret < 0)
+ dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
+ ri->rinfo->volt_reg, ret);
+ return ret;
+}
+
+static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ uint8_t vsel = 0;
+ int ret;
+
+ if (ri->rinfo->force_reg) {
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->force_reg, &vsel);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ ri->rinfo->force_reg, ret);
+ return ret;
+ }
+
+ if (!(vsel & SMPS_CMD_MASK))
+ return vsel & SMPS_VSEL_MASK;
+ }
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, &vsel);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ ri->rinfo->volt_reg, ret);
+ return ret;
+ }
+ return vsel & SMPS_VSEL_MASK;
+}
+
+static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned sel)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret;
+
+ /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+ if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+ (ri->device_flags & TRACK_MODE_ENABLE)) {
+ unsigned nvsel = (sel) & 0x1F;
+ if (((tps80031_get_chip_info(parent) == TPS80031) ||
+ ((tps80031_get_chip_info(parent) == TPS80032) &&
+ (tps80031_get_pmu_version(parent) == 0x0))) &&
+ ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
+ dev_err(ri->dev,
+ "Invalid sel %d in track mode LDO2\n",
+ nvsel);
+ return -EINVAL;
+ }
+ }
+
+ ret = tps80031_write(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, sel);
+ if (ret < 0)
+ dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
+ ri->rinfo->volt_reg, ret);
+ return ret;
+}
+
+static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ uint8_t vsel;
+ int ret;
+
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, &vsel);
+ if (ret < 0) {
+ dev_err(ri->dev, "Error in writing the Voltage register\n");
+ return ret;
+ }
+ return vsel & rdev->desc->vsel_mask;
+}
+
+static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret = -EIO;
+ uint8_t ctrl1 = 0;
+ uint8_t ctrl3 = 0;
+
+ ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL1, &ctrl1);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL1, ret);
+ return ret;
+ }
+ ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL3, &ctrl3);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL3, ret);
+ return ret;
+ }
+ if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
+ return 1;
+ return ret;
+}
+
+static int tps80031_vbus_enable(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret;
+
+ ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL1, ret);
+ return ret;
+ }
+
+ ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL3, ret);
+ return ret;
+ }
+ return ret;
+}
+
+static int tps80031_vbus_disable(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps80031_dev(rdev);
+ int ret = 0;
+
+ if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+ ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+ USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+ USB_VBUS_CTRL_SET, ret);
+ return ret;
+ }
+ }
+
+ ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL1, ret);
+ return ret;
+ }
+
+ ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+ TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+ TPS80031_CHARGERUSB_CTRL3, ret);
+ return ret;
+ }
+
+ mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
+ if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+ ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+ USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+ if (ret < 0) {
+ dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+ USB_VBUS_CTRL_CLR, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static struct regulator_ops tps80031_dcdc_ops = {
+ .list_voltage = tps80031_dcdc_list_voltage,
+ .set_voltage_sel = tps80031_dcdc_set_voltage_sel,
+ .get_voltage_sel = tps80031_dcdc_get_voltage_sel,
+ .enable = tps80031_reg_enable,
+ .disable = tps80031_reg_disable,
+ .is_enabled = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = tps80031_ldo_set_voltage_sel,
+ .get_voltage_sel = tps80031_ldo_get_voltage_sel,
+ .enable = tps80031_reg_enable,
+ .disable = tps80031_reg_disable,
+ .is_enabled = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_sw_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = tps80031_vbus_enable,
+ .disable = tps80031_vbus_disable,
+ .is_enabled = tps80031_vbus_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_hw_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+};
+
+static struct regulator_ops tps80031_ext_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = tps80031_reg_enable,
+ .disable = tps80031_reg_disable,
+ .is_enabled = tps80031_reg_is_enabled,
+};
+
+/* Non-exiting default definition for some register */
+#define TPS80031_SMPS3_CFG_FORCE 0
+#define TPS80031_SMPS4_CFG_FORCE 0
+
+#define TPS80031_VBUS_CFG_TRANS 0
+#define TPS80031_VBUS_CFG_STATE 0
+
+#define TPS80031_REG_SMPS(_id, _volt_id, _pbit) \
+{ \
+ .trans_reg = TPS80031_##_id##_CFG_TRANS, \
+ .state_reg = TPS80031_##_id##_CFG_STATE, \
+ .force_reg = TPS80031_##_id##_CFG_FORCE, \
+ .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \
+ .volt_id = TPS80031_SLAVE_##_volt_id, \
+ .preq_bit = _pbit, \
+ .desc = { \
+ .name = "tps80031_"#_id, \
+ .id = TPS80031_REGULATOR_##_id, \
+ .n_voltages = 63, \
+ .ops = &tps80031_dcdc_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .enable_time = 500, \
+ }, \
+}
+
+#define TPS80031_REG_LDO(_id, _preq_bit) \
+{ \
+ .trans_reg = TPS80031_##_id##_CFG_TRANS, \
+ .state_reg = TPS80031_##_id##_CFG_STATE, \
+ .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \
+ .volt_id = TPS80031_SLAVE_ID1, \
+ .preq_bit = _preq_bit, \
+ .desc = { \
+ .owner = THIS_MODULE, \
+ .name = "tps80031_"#_id, \
+ .id = TPS80031_REGULATOR_##_id, \
+ .ops = &tps80031_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .min_uV = 1000000, \
+ .uV_step = 100000, \
+ .linear_min_sel = 1, \
+ .n_voltages = 25, \
+ .vsel_mask = LDO_VSEL_MASK, \
+ .enable_time = 500, \
+ }, \
+}
+
+#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit) \
+{ \
+ .trans_reg = TPS80031_##_id##_CFG_TRANS, \
+ .state_reg = TPS80031_##_id##_CFG_STATE, \
+ .volt_id = TPS80031_SLAVE_ID1, \
+ .preq_bit = _pbit, \
+ .desc = { \
+ .name = "tps80031_"#_id, \
+ .id = TPS80031_REGULATOR_##_id, \
+ .min_uV = max_mV * 1000, \
+ .n_voltages = 1, \
+ .ops = &_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .enable_time = _delay, \
+ }, \
+}
+
+static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
+ TPS80031_REG_SMPS(VIO, ID0, 4),
+ TPS80031_REG_SMPS(SMPS1, ID0, 0),
+ TPS80031_REG_SMPS(SMPS2, ID0, 1),
+ TPS80031_REG_SMPS(SMPS3, ID1, 2),
+ TPS80031_REG_SMPS(SMPS4, ID1, 3),
+ TPS80031_REG_LDO(VANA, -1),
+ TPS80031_REG_LDO(LDO1, 8),
+ TPS80031_REG_LDO(LDO2, 9),
+ TPS80031_REG_LDO(LDO3, 10),
+ TPS80031_REG_LDO(LDO4, 11),
+ TPS80031_REG_LDO(LDO5, 12),
+ TPS80031_REG_LDO(LDO6, 13),
+ TPS80031_REG_LDO(LDO7, 14),
+ TPS80031_REG_LDO(LDOLN, 15),
+ TPS80031_REG_LDO(LDOUSB, 5),
+ TPS80031_REG_FIXED(VBUS, 5000, tps80031_vbus_hw_ops, 100000, -1),
+ TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
+ TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
+ TPS80031_REG_FIXED(SYSEN, 3300, tps80031_ext_reg_ops, 0, 18),
+};
+
+static int tps80031_power_req_config(struct device *parent,
+ struct tps80031_regulator *ri,
+ struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+ int ret = 0;
+
+ if (ri->rinfo->preq_bit < 0)
+ goto skip_pwr_req_config;
+
+ ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+ ri->rinfo->preq_bit, ri->rinfo->state_reg,
+ ri->rinfo->trans_reg);
+ if (ret < 0) {
+ dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
+ return ret;
+ }
+
+skip_pwr_req_config:
+ if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+ ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
+ TPS80031_TRANS_SLEEP_MASK);
+ if (ret < 0) {
+ dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
+ ri->rinfo->trans_reg, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int tps80031_regulator_config(struct device *parent,
+ struct tps80031_regulator *ri,
+ struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+ int ret = 0;
+
+ switch (ri->rinfo->desc.id) {
+ case TPS80031_REGULATOR_LDOUSB:
+ if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
+ TPS80031_USBLDO_INPUT_PMID)) {
+ unsigned val = 0;
+ if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
+ val = MISC2_LDOUSB_IN_VSYS;
+ else
+ val = MISC2_LDOUSB_IN_PMID;
+
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+ TPS80031_MISC2, val,
+ MISC2_LDOUSB_IN_MASK);
+ if (ret < 0) {
+ dev_err(ri->dev,
+ "LDOUSB config failed, e= %d\n", ret);
+ return ret;
+ }
+ }
+ break;
+
+ case TPS80031_REGULATOR_LDO3:
+ if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+ TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
+ MISC2_LDO3_SEL_VIB_MASK);
+ if (ret < 0) {
+ dev_err(ri->dev,
+ "LDO3 config failed, e = %d\n", ret);
+ return ret;
+ }
+ }
+ break;
+
+ case TPS80031_REGULATOR_VBUS:
+ /* Provide SW control Ops if VBUS is SW control */
+ if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
+ ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
+ break;
+ default:
+ break;
+ }
+
+ /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
+ ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
+ TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
+ TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
+ TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
+ if (ret < 0) {
+ dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int check_smps_mode_mult(struct device *parent,
+ struct tps80031_regulator *ri)
+{
+ int mult_offset;
+ int ret;
+ u8 smps_offset;
+ u8 smps_mult;
+
+ ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+ TPS80031_SMPS_OFFSET, &smps_offset);
+ if (ret < 0) {
+ dev_err(parent, "Error in reading smps offset register\n");
+ return ret;
+ }
+
+ ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+ TPS80031_SMPS_MULT, &smps_mult);
+ if (ret < 0) {
+ dev_err(parent, "Error in reading smps mult register\n");
+ return ret;
+ }
+
+ switch (ri->rinfo->desc.id) {
+ case TPS80031_REGULATOR_VIO:
+ mult_offset = SMPS_MULTOFFSET_VIO;
+ break;
+ case TPS80031_REGULATOR_SMPS1:
+ mult_offset = SMPS_MULTOFFSET_SMPS1;
+ break;
+ case TPS80031_REGULATOR_SMPS2:
+ mult_offset = SMPS_MULTOFFSET_SMPS2;
+ break;
+ case TPS80031_REGULATOR_SMPS3:
+ mult_offset = SMPS_MULTOFFSET_SMPS3;
+ break;
+ case TPS80031_REGULATOR_SMPS4:
+ mult_offset = SMPS_MULTOFFSET_SMPS4;
+ break;
+ case TPS80031_REGULATOR_LDO2:
+ ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
+ /* TRACK mode the ldo2 varies from 600mV to 1300mV */
+ if (ri->device_flags & TRACK_MODE_ENABLE) {
+ ri->rinfo->desc.min_uV = 600000;
+ ri->rinfo->desc.uV_step = 12500;
+ ri->rinfo->desc.n_voltages = 57;
+ ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+
+ ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
+ ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
+ switch (ri->device_flags) {
+ case 0:
+ ri->rinfo->desc.min_uV = 607700;
+ ri->rinfo->desc.uV_step = 12660;
+ break;
+ case DCDC_OFFSET_EN:
+ ri->rinfo->desc.min_uV = 700000;
+ ri->rinfo->desc.uV_step = 12500;
+ break;
+ case DCDC_EXTENDED_EN:
+ ri->rinfo->desc.min_uV = 1852000;
+ ri->rinfo->desc.uV_step = 38600;
+ break;
+ case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
+ ri->rinfo->desc.min_uV = 2161000;
+ ri->rinfo->desc.uV_step = 38600;
+ break;
+ }
+ return 0;
+}
+
+static int tps80031_regulator_probe(struct platform_device *pdev)
+{
+ struct tps80031_platform_data *pdata;
+ struct tps80031_regulator_platform_data *tps_pdata;
+ struct tps80031_regulator *ri;
+ struct tps80031_regulator *pmic;
+ struct regulator_dev *rdev;
+ struct regulator_config config = { };
+ int ret;
+ int num;
+
+ pdata = dev_get_platdata(pdev->dev.parent);
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
+ pmic = devm_kzalloc(&pdev->dev,
+ TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+ return -ENOMEM;
+ }
+
+ for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+ tps_pdata = pdata->regulator_pdata[num];
+ ri = &pmic[num];
+ ri->rinfo = &tps80031_rinfo[num];
+ ri->dev = &pdev->dev;
+
+ check_smps_mode_mult(pdev->dev.parent, ri);
+ config.dev = &pdev->dev;
+ config.init_data = NULL;
+ config.driver_data = ri;
+ if (tps_pdata) {
+ config.init_data = tps_pdata->reg_init_data;
+ ri->config_flags = tps_pdata->config_flags;
+ ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+ ret = tps80031_regulator_config(pdev->dev.parent,
+ ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "regulator config failed, e %d\n", ret);
+ goto fail;
+ }
+
+ ret = tps80031_power_req_config(pdev->dev.parent,
+ ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "pwr_req config failed, err %d\n", ret);
+ goto fail;
+ }
+ }
+ rdev = regulator_register(&ri->rinfo->desc, &config);
+ if (IS_ERR_OR_NULL(rdev)) {
+ dev_err(&pdev->dev,
+ "register regulator failed %s\n",
+ ri->rinfo->desc.name);
+ ret = PTR_ERR(rdev);
+ goto fail;
+ }
+ ri->rdev = rdev;
+ }
+
+ platform_set_drvdata(pdev, pmic);
+ return 0;
+fail:
+ while (--num >= 0) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
+ return ret;
+}
+
+static int tps80031_regulator_remove(struct platform_device *pdev)
+{
+ struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+ struct tps80031_regulator *ri = NULL;
+ int num;
+
+ for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
+ return 0;
+}
+
+static struct platform_driver tps80031_regulator_driver = {
+ .driver = {
+ .name = "tps80031-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = tps80031_regulator_probe,
+ .remove = tps80031_regulator_remove,
+};
+
+static int __init tps80031_regulator_init(void)
+{
+ return platform_driver_register(&tps80031_regulator_driver);
+}
+subsys_initcall(tps80031_regulator_init);
+
+static void __exit tps80031_regulator_exit(void)
+{
+ platform_driver_unregister(&tps80031_regulator_driver);
+}
+module_exit(tps80031_regulator_exit);
+
+MODULE_ALIAS("platform:tps80031-regulator");
+MODULE_DESCRIPTION("Regulator Driver for TI TPS80031/TPS80032 PMIC");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 7eb986a40746..493c8c6a241f 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
};
MODULE_DEVICE_TABLE(of, twl_of_match);
-static int __devinit twlreg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
{
int i, id;
struct twlreg_info *info;
@@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit twlreg_remove(struct platform_device *pdev)
+static int twlreg_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct twlreg_info *info = rdev->reg_data;
@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
static struct platform_driver twlreg_driver = {
.probe = twlreg_probe,
- .remove = __devexit_p(twlreg_remove),
+ .remove = twlreg_remove,
/* NOTE: short name, to work around driver model truncation of
* "twl_regulator.12" (and friends) to "twl_regulator.1".
*/
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644
index 000000000000..4668c7f8133d
--- /dev/null
+++ b/drivers/regulator/vexpress.c
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+ struct regulator_desc desc;
+ struct regulator_dev *regdev;
+ struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+ struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+ u32 uV;
+ int err = vexpress_config_read(reg->func, 0, &uV);
+
+ return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+ return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+ .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+ .get_voltage = vexpress_regulator_get_voltage,
+ .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+ int err;
+ struct vexpress_regulator *reg;
+ struct regulator_init_data *init_data;
+ struct regulator_config config = { };
+
+ reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+ if (!reg) {
+ err = -ENOMEM;
+ goto error_kzalloc;
+ }
+
+ reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+ if (!reg->func) {
+ err = -ENXIO;
+ goto error_get_func;
+ }
+
+ reg->desc.name = dev_name(&pdev->dev);
+ reg->desc.type = REGULATOR_VOLTAGE;
+ reg->desc.owner = THIS_MODULE;
+ reg->desc.continuous_voltage_range = true;
+
+ init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+ if (!init_data) {
+ err = -EINVAL;
+ goto error_get_regulator_init_data;
+ }
+
+ init_data->constraints.apply_uV = 0;
+ if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+ reg->desc.ops = &vexpress_regulator_ops;
+ else
+ reg->desc.ops = &vexpress_regulator_ops_ro;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.driver_data = reg;
+ config.of_node = pdev->dev.of_node;
+
+ reg->regdev = regulator_register(&reg->desc, &config);
+ if (IS_ERR(reg->regdev)) {
+ err = PTR_ERR(reg->regdev);
+ goto error_regulator_register;
+ }
+
+ platform_set_drvdata(pdev, reg);
+
+ return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+ vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+ return err;
+}
+
+static int vexpress_regulator_remove(struct platform_device *pdev)
+{
+ struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+
+ vexpress_config_func_put(reg->func);
+ regulator_unregister(reg->regdev);
+
+ return 0;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+ { .compatible = "arm,vexpress-volt", },
+ { }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+ .probe = vexpress_regulator_probe,
+ .remove = vexpress_regulator_remove,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = vexpress_regulator_of_match,
+ },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index c038e7422538..01c66e9712a4 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
.attrs = regulator_virtual_attributes,
};
-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
+static int regulator_virtual_probe(struct platform_device *pdev)
{
char *reg_id = pdev->dev.platform_data;
struct virtual_consumer_data *drvdata;
@@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+static int regulator_virtual_remove(struct platform_device *pdev)
{
struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
static struct platform_driver regulator_virtual_consumer_driver = {
.probe = regulator_virtual_probe,
- .remove = __devexit_p(regulator_virtual_remove),
+ .remove = regulator_virtual_remove,
.driver = {
.name = "reg-virt-consumer",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 782c228a19bd..0af6898bcd79 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -223,7 +223,7 @@ static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
if (min_uV < 600000)
vsel = 0;
else if (min_uV <= 1800000)
- vsel = ((min_uV - 600000) / 12500) + 8;
+ vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8;
else
return -EINVAL;
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
if (vsel > dcdc->dvs_vsel) {
ret = wm831x_set_bits(wm831x, dvs_reg,
WM831X_DC1_DVS_VSEL_MASK,
- dcdc->dvs_vsel);
+ vsel);
if (ret == 0)
dcdc->dvs_vsel = vsel;
else
@@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
* Set up DVS control. We just log errors since we can still run
* (with reduced performance) if we fail.
*/
-static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
struct wm831x_buckv_pdata *pdata)
{
struct wm831x *wm831x = dcdc->wm831x;
@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
}
}
-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
+static int wm831x_buckv_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -562,7 +562,7 @@ err:
return ret;
}
-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+static int wm831x_buckv_remove(struct platform_device *pdev)
{
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
struct wm831x *wm831x = dcdc->wm831x;
@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
static struct platform_driver wm831x_buckv_driver = {
.probe = wm831x_buckv_probe,
- .remove = __devexit_p(wm831x_buckv_remove),
+ .remove = wm831x_buckv_remove,
.driver = {
.name = "wm831x-buckv",
.owner = THIS_MODULE,
@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
};
-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
+static int wm831x_buckp_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -710,7 +710,7 @@ err:
return ret;
}
-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+static int wm831x_buckp_remove(struct platform_device *pdev)
{
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
static struct platform_driver wm831x_buckp_driver = {
.probe = wm831x_buckp_probe,
- .remove = __devexit_p(wm831x_buckp_remove),
+ .remove = wm831x_buckp_remove,
.driver = {
.name = "wm831x-buckp",
.owner = THIS_MODULE,
@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
.disable = regulator_disable_regmap,
};
-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
+static int wm831x_boostp_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -845,7 +845,7 @@ err:
return ret;
}
-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+static int wm831x_boostp_remove(struct platform_device *pdev)
{
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
static struct platform_driver wm831x_boostp_driver = {
.probe = wm831x_boostp_probe,
- .remove = __devexit_p(wm831x_boostp_remove),
+ .remove = wm831x_boostp_remove,
.driver = {
.name = "wm831x-boostp",
.owner = THIS_MODULE,
@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
.get_status = wm831x_dcdc_get_status,
};
-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
+static int wm831x_epe_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -936,7 +936,7 @@ err:
return ret;
}
-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+static int wm831x_epe_remove(struct platform_device *pdev)
{
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
static struct platform_driver wm831x_epe_driver = {
.probe = wm831x_epe_probe,
- .remove = __devexit_p(wm831x_epe_remove),
+ .remove = wm831x_epe_remove,
.driver = {
.name = "wm831x-epe",
.owner = THIS_MODULE,
@@ -993,4 +993,5 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:wm831x-buckv");
MODULE_ALIAS("platform:wm831x-buckp");
+MODULE_ALIAS("platform:wm831x-boostp");
MODULE_ALIAS("platform:wm831x-epe");
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 2646a1902b33..68586ee3e1cb 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
}
-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
+static int wm831x_isink_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -221,7 +221,7 @@ err:
return ret;
}
-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+static int wm831x_isink_remove(struct platform_device *pdev)
{
struct wm831x_isink *isink = platform_get_drvdata(pdev);
@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
static struct platform_driver wm831x_isink_driver = {
.probe = wm831x_isink_probe,
- .remove = __devexit_p(wm831x_isink_remove),
+ .remove = wm831x_isink_remove,
.driver = {
.name = "wm831x-isink",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index c2dc03993dc7..1ec379a9a95c 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
.disable = regulator_disable_regmap,
};
-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
+static int wm831x_gp_ldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -334,7 +334,7 @@ err:
return ret;
}
-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+static int wm831x_gp_ldo_remove(struct platform_device *pdev)
{
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
static struct platform_driver wm831x_gp_ldo_driver = {
.probe = wm831x_gp_ldo_probe,
- .remove = __devexit_p(wm831x_gp_ldo_remove),
+ .remove = wm831x_gp_ldo_remove,
.driver = {
.name = "wm831x-ldo",
.owner = THIS_MODULE,
@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
.disable = regulator_disable_regmap,
};
-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
+static int wm831x_aldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -590,7 +590,7 @@ err:
return ret;
}
-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+static int wm831x_aldo_remove(struct platform_device *pdev)
{
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
static struct platform_driver wm831x_aldo_driver = {
.probe = wm831x_aldo_probe,
- .remove = __devexit_p(wm831x_aldo_remove),
+ .remove = wm831x_aldo_remove,
.driver = {
.name = "wm831x-aldo",
.owner = THIS_MODULE,
@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
.disable = regulator_disable_regmap,
};
-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
+static int wm831x_alive_ldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -737,7 +737,7 @@ err:
return ret;
}
-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+static int wm831x_alive_ldo_remove(struct platform_device *pdev)
{
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
static struct platform_driver wm831x_alive_ldo_driver = {
.probe = wm831x_alive_ldo_probe,
- .remove = __devexit_p(wm831x_alive_ldo_remove),
+ .remove = wm831x_alive_ldo_remove,
.driver = {
.name = "wm831x-alive-ldo",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 27c746ef0636..c6a32ea80b9d 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
},
};
-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
+static int wm8400_regulator_probe(struct platform_device *pdev)
{
struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
struct regulator_config config = { };
@@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+static int wm8400_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
.name = "wm8400-regulator",
},
.probe = wm8400_regulator_probe,
- .remove = __devexit_p(wm8400_regulator_remove),
+ .remove = wm8400_regulator_remove,
};
/**
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 86bb48db149e..6ff872342648 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
},
};
-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+static int wm8994_ldo_probe(struct platform_device *pdev)
{
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -142,7 +142,7 @@ err:
return ret;
}
-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+static int wm8994_ldo_remove(struct platform_device *pdev)
{
struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
static struct platform_driver wm8994_ldo_driver = {
.probe = wm8994_ldo_probe,
- .remove = __devexit_p(wm8994_ldo_remove),
+ .remove = wm8994_ldo_remove,
.driver = {
.name = "wm8994-ldo",
.owner = THIS_MODULE,
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index e1f89d649733..0d36f94ab51d 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -66,13 +66,13 @@ rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
return -EINVAL;
}
- /* We assume the firmware has the same endianess as the host */
+ /* We assume the firmware has the same endianness as the host */
# ifdef __LITTLE_ENDIAN
if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
# else /* BIG ENDIAN */
if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
# endif
- dev_err(dev, "Unsupported firmware endianess\n");
+ dev_err(dev, "Unsupported firmware endianness\n");
return -EINVAL;
}
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 26c81f233606..afb7cfa85ccc 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -118,7 +118,7 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
return ret;
}
-/* simple check to see wether we have a isl1208 */
+/* simple check to see whether we have a isl1208 */
static int
isl1208_i2c_validate_client(struct i2c_client *client)
{
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 77823d21d314..a7a2a998fa91 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -186,7 +186,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);
- /* the only way to work out wether the system was mid-update
+ /* the only way to work out whether the system was mid-update
* when we read it is to check the second counter, and if it
* is zero, then we re-try the entire read
*/
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index b2b8c18eeced..20cfd028edcf 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1344,7 +1344,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
/*
* Set / reset given feature.
- * Flag indicates wether to set (!=0) or the reset (=0) the feature.
+ * Flag indicates whether to set (!=0) or the reset (=0) the feature.
*/
int
dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index a0a4afe537d0..5c70a6599578 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -3018,10 +3018,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
{
struct claw_privbk *priv;
- BUG_ON(!cgdev);
CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
priv = dev_get_drvdata(&cgdev->dev);
- BUG_ON(!priv);
dev_info(&cgdev->dev, " will be removed.\n");
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 98ea9cc6f1aa..817b68925ddd 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1691,8 +1691,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
{
struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
- BUG_ON(priv == NULL);
-
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"removing device %p, proto : %d",
cgdev, priv->protocol);
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 05b734a2b5b7..2dbc77b5137b 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -1367,7 +1367,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
struct mpc_group *grp;
struct channel *wch;
- BUG_ON(dev == NULL);
CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name);
priv = dev->ml_priv;
@@ -1472,8 +1471,6 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
struct channel *wch;
struct channel *rch;
- BUG_ON(dev == NULL);
-
priv = dev->ml_priv;
grp = priv->mpcg;
wch = priv->channel[CTCM_WRITE];
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index fa7adad6f9ba..480fbeab0256 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -933,6 +933,7 @@ int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
+void qeth_trace_features(struct qeth_card *);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 4d6ba00d0047..638a57f4d8a1 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -73,13 +73,13 @@ static inline const char *qeth_get_cardname(struct qeth_card *card)
if (card->info.guestlan) {
switch (card->info.type) {
case QETH_CARD_TYPE_OSD:
- return " Guest LAN QDIO";
+ return " Virtual NIC QDIO";
case QETH_CARD_TYPE_IQD:
- return " Guest LAN Hiper";
+ return " Virtual NIC Hiper";
case QETH_CARD_TYPE_OSM:
- return " Guest LAN QDIO - OSM";
+ return " Virtual NIC QDIO - OSM";
case QETH_CARD_TYPE_OSX:
- return " Guest LAN QDIO - OSX";
+ return " Virtual NIC QDIO - OSX";
default:
return " unknown";
}
@@ -108,13 +108,13 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
if (card->info.guestlan) {
switch (card->info.type) {
case QETH_CARD_TYPE_OSD:
- return "GuestLAN QDIO";
+ return "Virt.NIC QDIO";
case QETH_CARD_TYPE_IQD:
- return "GuestLAN Hiper";
+ return "Virt.NIC Hiper";
case QETH_CARD_TYPE_OSM:
- return "GuestLAN OSM";
+ return "Virt.NIC OSM";
case QETH_CARD_TYPE_OSX:
- return "GuestLAN OSX";
+ return "Virt.NIC OSX";
default:
return "unknown";
}
@@ -383,7 +383,7 @@ static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
qeth_release_skbs(c);
c = f->next_pending;
- BUG_ON(head->next_pending != f);
+ WARN_ON_ONCE(head->next_pending != f);
head->next_pending = c;
kmem_cache_free(qeth_qdio_outbuf_cache, f);
} else {
@@ -415,13 +415,12 @@ static inline void qeth_qdio_handle_aob(struct qeth_card *card,
buffer = (struct qeth_qdio_out_buffer *) aob->user1;
QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
- BUG_ON(buffer == NULL);
-
if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
notification = TX_NOTIFY_OK;
} else {
- BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+ WARN_ON_ONCE(atomic_read(&buffer->state) !=
+ QETH_QDIO_BUF_PENDING);
atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
notification = TX_NOTIFY_DELAYED_OK;
}
@@ -1131,7 +1130,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
notify_general_error = 1;
/* release may never happen from within CQ tasklet scope */
- BUG_ON(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
+ WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
skb = skb_dequeue(&buf->skb_list);
while (skb) {
@@ -2280,7 +2279,6 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
{
struct qeth_cmd_buffer *iob;
- int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
@@ -2296,7 +2294,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
iob->rc = -EMLINK;
}
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
- return rc;
+ return 0;
}
static int qeth_ulp_setup(struct qeth_card *card)
@@ -2401,7 +2399,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
card->qdio.out_qs[i]->queue_no = i;
/* give outbound qeth_qdio_buffers their qdio_buffers */
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
- BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+ WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
goto out_freeoutqbufs;
}
@@ -2969,9 +2967,6 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
} else
QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
"\n", dev_name(&card->gdev->dev));
- QETH_DBF_TEXT(SETUP, 2, "suppenbl");
- QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
- QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
return 0;
}
@@ -3569,7 +3564,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
if (queue->bufstates &&
(queue->bufstates[bidx].flags &
QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
- BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+ WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);
if (atomic_cmpxchg(&buffer->state,
QETH_QDIO_BUF_PRIMED,
@@ -3583,7 +3578,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
QETH_CARD_TEXT(queue->card, 5, "aob");
QETH_CARD_TEXT_(queue->card, 5, "%lx",
virt_to_phys(buffer->aob));
- BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
if (qeth_init_qdio_out_buf(queue, bidx)) {
QETH_CARD_TEXT(card, 2, "outofbuf");
qeth_schedule_recovery(card);
@@ -4731,6 +4725,19 @@ static void qeth_core_free_card(struct qeth_card *card)
kfree(card);
}
+void qeth_trace_features(struct qeth_card *card)
+{
+ QETH_CARD_TEXT(card, 2, "features");
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+}
+EXPORT_SYMBOL_GPL(qeth_trace_features);
+
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
.driver_info = QETH_CARD_TYPE_OSD},
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index fddb62654b6a..73195553f84b 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -411,7 +411,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
unsigned int len;
*done = 0;
- BUG_ON(!budget);
+ WARN_ON_ONCE(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
&card->qdio.in_q->bufs[card->rx.b_index],
@@ -973,7 +973,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
int rc = 0;
enum qeth_card_states recover_flag;
- BUG_ON(!card);
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -986,6 +985,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
rc = -ENODEV;
goto out_remove;
}
+ qeth_trace_features(card);
if (!card->dev && qeth_l2_setup_netdev(card)) {
rc = -ENODEV;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 5ba390658498..6e5eef01e667 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1939,7 +1939,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
__u16 magic;
*done = 0;
- BUG_ON(!budget);
+ WARN_ON_ONCE(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
&card->qdio.in_q->bufs[card->rx.b_index],
@@ -3334,7 +3334,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
int rc = 0;
enum qeth_card_states recover_flag;
- BUG_ON(!card);
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -3347,6 +3346,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
rc = -ENODEV;
goto out_remove;
}
+ qeth_trace_features(card);
if (!card->dev && qeth_l3_setup_netdev(card)) {
rc = -ENODEV;
@@ -3714,9 +3714,9 @@ static void qeth_l3_unregister_notifiers(void)
{
QETH_DBF_TEXT(SETUP, 5, "unregnot");
- BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
+ WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
#ifdef CONFIG_QETH_IPV6
- BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
+ WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
#endif /* QETH_IPV6 */
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 6d6eee42ac7d..ef60afa94d0e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -296,7 +296,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
ofld_req3.flags |= (interface->vlan_enabled <<
FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
- /* C2_VALID and ACK flags are not set as they are not suppported */
+ /* C2_VALID and ACK flags are not set as they are not supported */
/* Initialize offload request 4 structure */
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index efc6e72f09f3..aec2e0da5016 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1800,7 +1800,7 @@ out:
* @dev:domain device to be detect.
* @src_dev: the device which originated BROADCAST(CHANGE).
*
- * Add self-configuration expander suport. Suppose two expander cascading,
+ * Add self-configuration expander support. Suppose two expander cascading,
* when the first level expander is self-configuring, hotplug the disks in
* second level expander, BROADCAST(CHANGE) will not only be originated
* in the second level expander, but also be originated in the first level
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5733811ce8e7..9d1c7b56090a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -251,7 +251,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
/* Read all mbox registers? */
mboxes = (1 << ha->mbx_count) - 1;
if (!ha->mcp)
- ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERRROR.\n");
+ ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
else
mboxes = ha->mcp->in_mb;
@@ -2318,7 +2318,7 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
/* Read all mbox registers? */
mboxes = (1 << ha->mbx_count) - 1;
if (!ha->mcp)
- ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n");
+ ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
else
mboxes = ha->mcp->in_mb;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 14cd361742fa..f5e297c6b684 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -955,7 +955,7 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
}
if (loops >= 50000) {
ql_log(ql_log_fatal, vha, 0x00b9,
- "Failed to aquire SEM2 lock.\n");
+ "Failed to acquire SEM2 lock.\n");
return -1;
}
ret = qla82xx_do_rom_fast_read(ha, addr, valp);
@@ -1122,7 +1122,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
long data;
};
- /* Halt all the indiviual PEGs and other blocks of the ISP */
+ /* Halt all the individual PEGs and other blocks of the ISP */
qla82xx_rom_lock(ha);
/* disable all I2Q */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 62aa5584f644..b49d21779a24 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -73,7 +73,7 @@ enum fcp_resp_rsp_codes {
#define FCP_PTA_SIMPLE 0 /* simple task attribute */
#define FCP_PTA_HEADQ 1 /* head of queue task attribute */
#define FCP_PTA_ORDERED 2 /* ordered task attribute */
-#define FCP_PTA_ACA 4 /* auto. contigent allegiance */
+#define FCP_PTA_ACA 4 /* auto. contingent allegiance */
#define FCP_PTA_MASK 7 /* mask for task attribute field */
#define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */
#define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */
@@ -3980,7 +3980,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a,
"qla_target(%d): System error async event %#x "
- "occured", vha->vp_idx, code);
+ "occurred", vha->vp_idx, code);
break;
case MBA_WAKEUP_THRES: /* Request Queue Wake-up. */
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -3989,7 +3989,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_LOOP_UP:
{
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b,
- "qla_target(%d): Async LOOP_UP occured "
+ "qla_target(%d): Async LOOP_UP occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4006,7 +4006,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_LIP_RESET:
case MBA_RSCN_UPDATE:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
- "qla_target(%d): Async event %#x occured "
+ "qla_target(%d): Async event %#x occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4015,7 +4015,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_PORT_UPDATE:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d,
"qla_target(%d): Port update async event %#x "
- "occured: updating the ports database (m[0]=%x, m[1]=%x, "
+ "occurred: updating the ports database (m[0]=%x, m[1]=%x, "
"m[2]=%x, m[3]=%x)", vha->vp_idx, code,
le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4031,7 +4031,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf040,
- "qla_target(%d): Async event %#x occured: "
+ "qla_target(%d): Async event %#x occurred: "
"ignore (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
code, le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 3d74f2f39ae1..4372e32bc95f 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -367,7 +367,7 @@ static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(
nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL);
if (!nacl) {
- pr_err("Unable to alocate struct tcm_qla2xxx_nacl\n");
+ pr_err("Unable to allocate struct tcm_qla2xxx_nacl\n");
return NULL;
}
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index 266aa1648a02..19396dc4ee47 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -37,6 +37,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index e9d2ca11283b..95c33a05f434 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -4,6 +4,7 @@
*
* Copyright 2005, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -12,6 +13,7 @@
#include <linux/ssb/ssb_regs.h>
#include <linux/export.h>
#include <linux/pci.h>
+#include <linux/bcm47xx_wdt.h>
#include "ssb_private.h"
@@ -280,6 +282,69 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
cc->fast_pwrup_delay = tmp;
}
+static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc)
+{
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
+ return ssb_pmu_get_alp_clock(cc);
+
+ return 20000000;
+}
+
+static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc)
+{
+ u32 nb;
+
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+ if (cc->dev->id.revision < 26)
+ nb = 16;
+ else
+ nb = (cc->dev->id.revision >= 37) ? 32 : 24;
+ } else {
+ nb = 28;
+ }
+ if (nb == 32)
+ return 0xffffffff;
+ else
+ return (1 << nb) - 1;
+}
+
+u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
+{
+ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
+
+ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
+ return 0;
+
+ return ssb_chipco_watchdog_timer_set(cc, ticks);
+}
+
+u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
+{
+ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
+ u32 ticks;
+
+ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
+ return 0;
+
+ ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
+ return ticks / cc->ticks_per_ms;
+}
+
+static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+ /* based on 32KHz ILP clock */
+ return 32;
+ } else {
+ if (cc->dev->id.revision < 18)
+ return ssb_clockspeed(bus) / 1000;
+ else
+ return ssb_chipco_alp_clock(cc) / 1000;
+ }
+}
+
void ssb_chipcommon_init(struct ssb_chipcommon *cc)
{
if (!cc->dev)
@@ -297,6 +362,11 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
chipco_powercontrol_init(cc);
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
calc_fast_powerup_delay(cc);
+
+ if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
+ cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
+ cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
+ }
}
void ssb_chipco_suspend(struct ssb_chipcommon *cc)
@@ -395,10 +465,27 @@ void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
}
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
-void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
+u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
{
- /* instant NMI */
- chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ u32 maxt;
+ enum ssb_clkmode clkmode;
+
+ maxt = ssb_chipco_watchdog_get_max_timer(cc);
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+ if (ticks == 1)
+ ticks = 2;
+ else if (ticks > maxt)
+ ticks = maxt;
+ chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks);
+ } else {
+ clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC;
+ ssb_chipco_set_clockmode(cc, clkmode);
+ if (ticks > maxt)
+ ticks = maxt;
+ /* instant NMI */
+ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ }
+ return ticks;
}
void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
@@ -473,12 +560,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
chipco_read32(cc, SSB_CHIPCO_CORECTL)
| SSB_CHIPCO_CORECTL_UARTCLK0);
} else if ((ccrev >= 11) && (ccrev != 15)) {
- /* Fixed ALP clock */
- baud_base = 20000000;
- if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
- /* FIXME: baud_base is different for devices with a PMU */
- SSB_WARN_ON(1);
- }
+ baud_base = ssb_chipco_alp_clock(cc);
div = 1;
if (ccrev >= 21) {
/* Turn off UART clock before switching clocksource. */
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index b58fef780ea0..a43415a7fbed 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
}
break;
+ case 43222:
+ break;
default:
ssb_printk(KERN_ERR PFX
"ERROR: PLL init unknown for device %04X\n",
@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
min_msk = 0xCBB;
break;
case 0x4322:
+ case 43222:
/* We keep the default settings:
* min_msk = 0xCBB
* max_msk = 0x7FFFF
@@ -615,6 +618,33 @@ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
+static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
+{
+ u32 crystalfreq;
+ const struct pmu0_plltab_entry *e = NULL;
+
+ crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
+ SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
+ e = pmu0_plltab_find_entry(crystalfreq);
+ BUG_ON(!e);
+ return e->freq * 1000;
+}
+
+u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+
+ switch (bus->chip_id) {
+ case 0x5354:
+ ssb_pmu_get_alp_clock_clk0(cc);
+ default:
+ ssb_printk(KERN_ERR PFX
+ "ERROR: PMU alp clock unknown for device %04X\n",
+ bus->chip_id);
+ return 0;
+ }
+}
+
u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
{
struct ssb_bus *bus = cc->dev->bus;
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index dc47f30e9cf7..553227a3062d 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -112,10 +112,30 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
*m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
}
-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
- u32 ticks)
+u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
{
+ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
+
+ return ssb_extif_watchdog_timer_set(extif, ticks);
+}
+
+u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
+{
+ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
+ u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms;
+
+ ticks = ssb_extif_watchdog_timer_set(extif, ticks);
+
+ return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK;
+}
+
+u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
+{
+ if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER)
+ ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER;
extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
+
+ return ticks;
}
u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index c6250867a95d..5bd05b136d22 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
{
struct ssb_bus *bus = mcore->dev->bus;
- if (bus->extif.dev)
+ if (ssb_extif_available(&bus->extif))
mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
- else if (bus->chipco.dev)
+ else if (ssb_chipco_available(&bus->chipco))
mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports);
else
mcore->nr_serial_ports = 0;
@@ -191,10 +191,11 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
struct ssb_bus *bus = mcore->dev->bus;
/* When there is no chipcommon on the bus there is 4MB flash */
- if (!bus->chipco.dev) {
- mcore->flash_buswidth = 2;
- mcore->flash_window = SSB_FLASH1;
- mcore->flash_window_size = SSB_FLASH1_SZ;
+ if (!ssb_chipco_available(&bus->chipco)) {
+ mcore->pflash.present = true;
+ mcore->pflash.buswidth = 2;
+ mcore->pflash.window = SSB_FLASH1;
+ mcore->pflash.window_size = SSB_FLASH1_SZ;
return;
}
@@ -206,13 +207,14 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
break;
case SSB_CHIPCO_FLASHT_PARA:
pr_debug("Found parallel flash\n");
- mcore->flash_window = SSB_FLASH2;
- mcore->flash_window_size = SSB_FLASH2_SZ;
+ mcore->pflash.present = true;
+ mcore->pflash.window = SSB_FLASH2;
+ mcore->pflash.window_size = SSB_FLASH2_SZ;
if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
& SSB_CHIPCO_CFG_DS16) == 0)
- mcore->flash_buswidth = 1;
+ mcore->pflash.buswidth = 1;
else
- mcore->flash_buswidth = 2;
+ mcore->pflash.buswidth = 2;
break;
}
}
@@ -225,9 +227,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
return ssb_pmu_get_cpu_clock(&bus->chipco);
- if (bus->extif.dev) {
+ if (ssb_extif_available(&bus->extif)) {
ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
- } else if (bus->chipco.dev) {
+ } else if (ssb_chipco_available(&bus->chipco)) {
ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
} else
return 0;
@@ -263,9 +265,9 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
hz = 100000000;
ns = 1000000000 / hz;
- if (bus->extif.dev)
+ if (ssb_extif_available(&bus->extif))
ssb_extif_timing_init(&bus->extif, ns);
- else if (bus->chipco.dev)
+ else if (ssb_chipco_available(&bus->chipco))
ssb_chipco_timing_init(&bus->chipco, ns);
/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index 9ef124f9ee2d..bb18d76f9f2c 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -4,11 +4,13 @@
*
* Copyright 2005-2008, Broadcom Corporation
* Copyright 2006-2008, Michael Buesch <m@bues.ch>
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/export.h>
+#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/ssb/ssb_driver_pci.h>
@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
}
EXPORT_SYMBOL(ssb_watchdog_timer_set);
+int ssb_watchdog_register(struct ssb_bus *bus)
+{
+ struct bcm47xx_wdt wdt = {};
+ struct platform_device *pdev;
+
+ if (ssb_chipco_available(&bus->chipco)) {
+ wdt.driver_data = &bus->chipco;
+ wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
+ wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
+ wdt.max_timer_ms = bus->chipco.max_timer_ms;
+ } else if (ssb_extif_available(&bus->extif)) {
+ wdt.driver_data = &bus->extif;
+ wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
+ wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
+ wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
+ } else {
+ return -ENODEV;
+ }
+
+ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
+ bus->busnumber, &wdt,
+ sizeof(wdt));
+ if (IS_ERR(pdev)) {
+ ssb_dprintk(KERN_INFO PFX
+ "can not register watchdog device, err: %li\n",
+ PTR_ERR(pdev));
+ return PTR_ERR(pdev);
+ }
+
+ bus->watchdog = pdev;
+ return 0;
+}
+
u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
{
unsigned long flags;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index df0f145c22fc..6e0daaa0e04b 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_regs.h>
#include <linux/ssb/ssb_driver_gige.h>
@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struct ssb_bus *bus)
if (sdev->dev)
device_unregister(sdev->dev);
}
+
+#ifdef CONFIG_SSB_EMBEDDED
+ if (bus->bustype == SSB_BUSTYPE_SSB)
+ platform_device_unregister(bus->watchdog);
+#endif
}
void ssb_bus_unregister(struct ssb_bus *bus)
@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_buses(void)
if (err)
goto error;
ssb_pcicore_init(&bus->pcicore);
+ if (bus->bustype == SSB_BUSTYPE_SSB)
+ ssb_watchdog_register(bus);
ssb_bus_may_powerdown(bus);
err = ssb_devices_register(bus);
@@ -1118,8 +1126,7 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
case SSB_IDLOW_SSBREV_27: /* same here */
return SSB_TMSLOW_REJECT; /* this is a guess */
default:
- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
- WARN_ON(1);
+ WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
}
return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index a305550b4b65..8942db1d855a 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -3,6 +3,7 @@
#include <linux/ssb/ssb.h>
#include <linux/types.h>
+#include <linux/bcm47xx_wdt.h>
#define PFX "ssb: "
@@ -210,5 +211,35 @@ static inline void b43_pci_ssb_bridge_exit(void)
/* driver_chipcommon_pmu.c */
extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
+extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
+
+extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
+ u32 ticks);
+extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
+
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks);
+extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
+#else
+static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
+ u32 ticks)
+{
+ return 0;
+}
+static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt,
+ u32 ms)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SSB_EMBEDDED
+extern int ssb_watchdog_register(struct ssb_bus *bus);
+#else /* CONFIG_SSB_EMBEDDED */
+static inline int ssb_watchdog_register(struct ssb_bus *bus)
+{
+ return 0;
+}
+#endif /* CONFIG_SSB_EMBEDDED */
#endif /* LINUX_SSB_PRIVATE_H_ */
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 78f3a2e013c4..17b45ebb0553 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -73,7 +73,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
* And loads of cleaning up, in particular streamlining the
* bulk transfers.
* 1.1: moved EP4 transfers to EP1 to make space for a PWM output on EP4
- * 1.2: added PWM suport via EP4
+ * 1.2: added PWM support via EP4
* 2.0: PWM seems to be stable and is not interfering with the other functions
* 2.1: changed PWM API
* 2.2: added firmware kernel request to fix an udev problem
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index 294e9b40f516..737f4a9d86a3 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -736,7 +736,7 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
case 4:
break;
default:
- /* alignment value not suportted */
+ /* alignment value not supportted */
status = -EPERM;
break;
}
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index ff6fd4fb624d..0f03b7919d7c 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -235,7 +235,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
* iSER/SCTP (TODO, software emulation with osc-iwarp)
* iSER/IB (TODO, hardware available)
*
- * can be enabled with atributes under
+ * can be enabled with attributes under
* sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/
*
*/
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 8aacf611b86d..8e6298cc8839 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -410,11 +410,11 @@ static int iscsit_dataout_pre_datapduinorder_yes(
/*
* For DataSequenceInOrder=Yes: If the offset is greater than the global
* DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
- * occured and fail the connection.
+ * occurred and fail the connection.
*
* For DataSequenceInOrder=No: If the offset is greater than the per
* sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
- * error has occured and fail the connection.
+ * error has occurred and fail the connection.
*/
if (conn->sess->sess_ops->DataSequenceInOrder) {
if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
@@ -801,7 +801,7 @@ void iscsit_start_time2retain_handler(struct iscsi_session *sess)
{
int tpg_active;
/*
- * Only start Time2Retain timer when the assoicated TPG is still in
+ * Only start Time2Retain timer when the associated TPG is still in
* an ACTIVE (eg: not disabled or shutdown) state.
*/
spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 90b740048f26..1bf7432bfcbc 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -1432,6 +1432,7 @@ static struct iscsi_param *iscsi_check_key(
break;
case PHASE_OPERATIONAL:
pr_debug("Operational phase.\n");
+ break;
default:
pr_debug("Unknown phase.\n");
}
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 1a91195ab619..69e0cfd98870 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -684,7 +684,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
void iscsit_free_cmd(struct iscsi_cmd *cmd)
{
/*
- * Determine if a struct se_cmd is assoicated with
+ * Determine if a struct se_cmd is associated with
* this struct iscsi_cmd.
*/
switch (cmd->iscsi_opcode) {
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 8636fae1f7ec..c2c77d1ac499 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -98,7 +98,7 @@ config EXYNOS_THERMAL
depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
depends on CPU_THERMAL
help
- If you say yes here you get support for TMU (Thermal Managment
+ If you say yes here you get support for TMU (Thermal Management
Unit) on SAMSUNG EXYNOS series of SoC.
config DB8500_THERMAL
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index be1a9a1e749e..cd69b48f6dfd 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -178,7 +178,7 @@ static int hvc_opal_probe(struct platform_device *dev)
proto = HV_PROTOCOL_HVSI;
ops = &hvc_opal_hvsi_ops;
} else {
- pr_err("hvc_opal: Unkown protocol for %s\n",
+ pr_err("hvc_opal: Unknown protocol for %s\n",
dev->dev.of_node->full_name);
return -ENXIO;
}
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index ed6f5f1f5a55..0c629807610e 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -313,7 +313,7 @@ static int hvc_vio_probe(struct vio_dev *vdev,
proto = HV_PROTOCOL_HVSI;
ops = &hvterm_hvsi_ops;
} else {
- pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+ pr_err("hvc_vio: Unknown protocol for %s\n", vdev->dev.of_node->full_name);
return -ENXIO;
}
diff --git a/drivers/tty/ipwireless/setup_protocol.h b/drivers/tty/ipwireless/setup_protocol.h
index 9d6bcc77c73c..002c34e72521 100644
--- a/drivers/tty/ipwireless/setup_protocol.h
+++ b/drivers/tty/ipwireless/setup_protocol.h
@@ -59,7 +59,7 @@ struct tl_setup_config_done_msg {
unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
} __attribute__ ((__packed__));
-/* Asyncronous messages */
+/* Asynchronous messages */
struct tl_setup_open_msg {
unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */
unsigned char port_no;
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3d283f2e3aa..c31133a6ea8e 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -271,7 +271,7 @@ config SERIAL_8250_DW
present in the Synopsys DesignWare APB UART.
config SERIAL_8250_EM
- tristate "Support for Emma Mobile intergrated serial port"
+ tristate "Support for Emma Mobile integrated serial port"
depends on SERIAL_8250 && ARM && HAVE_CLK
help
Selecting this option will add support for the integrated serial
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index e6a008f4939f..2e2b2c1cb722 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -815,7 +815,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
lcr = WLS(5);
break;
default:
- printk(KERN_ERR "%s: word lengh not supported\n",
+ printk(KERN_ERR "%s: word length not supported\n",
__func__);
}
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 6197a69adb4d..72b6334bcf1a 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -505,7 +505,7 @@ static void load_code(struct icom_port *icom_port)
/* Stop processor */
stop_processor(icom_port);
- dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
+ dev_err(&icom_port->adapter->pci_dev->dev,"Port not operational\n");
}
if (new_page != NULL)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 88dde95b6795..d938b2b99e31 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -222,7 +222,7 @@ static int usb_probe_device(struct device *dev)
/* TODO: Add real matching code */
/* The device should always appear to be in use
- * unless the driver suports autosuspend.
+ * unless the driver supports autosuspend.
*/
if (!udriver->supports_autosuspend)
error = usb_autoresume_device(udev);
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 59dcea2f6957..f4a21f6f081f 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -51,7 +51,7 @@
* full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
* at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
*
- * This driver expects the board has been wired with two GPIOs suppporting
+ * This driver expects the board has been wired with two GPIOs supporting
* a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the
* testing hasn't covered such cases.)
*
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 09699f6e87f8..8bfe990caf1a 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -44,7 +44,7 @@
#include <asm/unaligned.h>
#include <asm/mach-types.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <mach/usb.h>
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index f74794c93152..a7d1f5b4c4ed 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -14,6 +14,9 @@
#include <linux/mbus.h>
#include <linux/clk.h>
#include <linux/platform_data/usb-ehci-orion.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
@@ -167,6 +170,8 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
}
}
+static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32);
+
static int ehci_orion_drv_probe(struct platform_device *pdev)
{
struct orion_ehci_data *pd = pdev->dev.platform_data;
@@ -177,13 +182,17 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
struct clk *clk;
void __iomem *regs;
int irq, err;
+ enum orion_ehci_phy_ver phy_version;
if (usb_disabled())
return -ENODEV;
pr_debug("Initializing Orion-SoC USB Host Controller\n");
- irq = platform_get_irq(pdev, 0);
+ if (pdev->dev.of_node)
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ else
+ irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
@@ -201,6 +210,14 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
goto err1;
}
+ /*
+ * Right now device-tree probed devices don't get dma_mask
+ * set. Since shared usb code relies on it, set it here for
+ * now. Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &ehci_orion_dma_mask;
+
if (!request_mem_region(res->start, resource_size(res),
ehci_orion_hc_driver.description)) {
dev_dbg(&pdev->dev, "controller already in use\n");
@@ -248,7 +265,12 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
/*
* setup Orion USB controller.
*/
- switch (pd->phy_version) {
+ if (pdev->dev.of_node)
+ phy_version = EHCI_PHY_NA;
+ else
+ phy_version = pd->phy_version;
+
+ switch (phy_version) {
case EHCI_PHY_NA: /* dont change USB phy settings */
break;
case EHCI_PHY_ORION:
@@ -303,9 +325,19 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
MODULE_ALIAS("platform:orion-ehci");
+static const struct of_device_id ehci_orion_dt_ids[] __devinitdata = {
+ { .compatible = "marvell,orion-ehci", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
+
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
.remove = __exit_p(ehci_orion_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
- .driver.name = "orion-ehci",
+ .driver = {
+ .name = "orion-ehci",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ehci_orion_dt_ids),
+ },
};
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 9716850a4309..98df17c984a8 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "musb_core.h"
#include "tusb6010.h"
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index ea5f2586fbdd..6c3586a4c956 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -883,7 +883,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
} else {
US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
chip->proto_handler_backup(srb, us);
- /* Check wether card is plugged in */
+ /* Check whether card is plugged in */
if (srb->cmnd[0] == TEST_UNIT_READY) {
if (srb->result == SAM_STAT_GOOD) {
SET_LUN_READY(chip, srb->device->lun);
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 7f93f34b7f91..ebd08b21b234 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -30,9 +30,10 @@
#include "vhost.h"
-static int experimental_zcopytx;
+static int experimental_zcopytx = 1;
module_param(experimental_zcopytx, int, 0444);
-MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
+MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
+ " 1 -Enable; 0 - Disable");
/* Max number of bytes transferred before requeueing the job.
* Using this limit prevents one virtqueue from starving others. */
@@ -42,6 +43,21 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
#define VHOST_MAX_PEND 128
#define VHOST_GOODCOPY_LEN 256
+/*
+ * For transmit, used buffer len is unused; we override it to track buffer
+ * status internally; used for zerocopy tx only.
+ */
+/* Lower device DMA failed */
+#define VHOST_DMA_FAILED_LEN 3
+/* Lower device DMA done */
+#define VHOST_DMA_DONE_LEN 2
+/* Lower device DMA in progress */
+#define VHOST_DMA_IN_PROGRESS 1
+/* Buffer unused */
+#define VHOST_DMA_CLEAR_LEN 0
+
+#define VHOST_DMA_IS_DONE(len) ((len) >= VHOST_DMA_DONE_LEN)
+
enum {
VHOST_NET_VQ_RX = 0,
VHOST_NET_VQ_TX = 1,
@@ -62,8 +78,39 @@ struct vhost_net {
* We only do this when socket buffer fills up.
* Protected by tx vq lock. */
enum vhost_net_poll_state tx_poll_state;
+ /* Number of TX recently submitted.
+ * Protected by tx vq lock. */
+ unsigned tx_packets;
+ /* Number of times zerocopy TX recently failed.
+ * Protected by tx vq lock. */
+ unsigned tx_zcopy_err;
+ /* Flush in progress. Protected by tx vq lock. */
+ bool tx_flush;
};
+static void vhost_net_tx_packet(struct vhost_net *net)
+{
+ ++net->tx_packets;
+ if (net->tx_packets < 1024)
+ return;
+ net->tx_packets = 0;
+ net->tx_zcopy_err = 0;
+}
+
+static void vhost_net_tx_err(struct vhost_net *net)
+{
+ ++net->tx_zcopy_err;
+}
+
+static bool vhost_net_tx_select_zcopy(struct vhost_net *net)
+{
+ /* TX flush waits for outstanding DMAs to be done.
+ * Don't start new DMAs.
+ */
+ return !net->tx_flush &&
+ net->tx_packets / 64 >= net->tx_zcopy_err;
+}
+
static bool vhost_sock_zcopy(struct socket *sock)
{
return unlikely(experimental_zcopytx) &&
@@ -126,6 +173,55 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
net->tx_poll_state = VHOST_NET_POLL_STARTED;
}
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+static int vhost_zerocopy_signal_used(struct vhost_net *net,
+ struct vhost_virtqueue *vq)
+{
+ int i;
+ int j = 0;
+
+ for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+ if (vq->heads[i].len == VHOST_DMA_FAILED_LEN)
+ vhost_net_tx_err(net);
+ if (VHOST_DMA_IS_DONE(vq->heads[i].len)) {
+ vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+ vhost_add_used_and_signal(vq->dev, vq,
+ vq->heads[i].id, 0);
+ ++j;
+ } else
+ break;
+ }
+ if (j)
+ vq->done_idx = i;
+ return j;
+}
+
+static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
+{
+ struct vhost_ubuf_ref *ubufs = ubuf->ctx;
+ struct vhost_virtqueue *vq = ubufs->vq;
+ int cnt = atomic_read(&ubufs->kref.refcount);
+
+ /*
+ * Trigger polling thread if guest stopped submitting new buffers:
+ * in this case, the refcount after decrement will eventually reach 1
+ * so here it is 2.
+ * We also trigger polling periodically after each 16 packets
+ * (the value 16 here is more or less arbitrary, it's tuned to trigger
+ * less than 10% of times).
+ */
+ if (cnt <= 2 || !(cnt % 16))
+ vhost_poll_queue(&vq->poll);
+ /* set len to mark this desc buffers done DMA */
+ vq->heads[ubuf->desc].len = success ?
+ VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
+ vhost_ubuf_put(ubufs);
+}
+
/* Expects to be always run from workqueue - which acts as
* read-size critical section for our kind of RCU. */
static void handle_tx(struct vhost_net *net)
@@ -146,7 +242,7 @@ static void handle_tx(struct vhost_net *net)
size_t hdr_size;
struct socket *sock;
struct vhost_ubuf_ref *uninitialized_var(ubufs);
- bool zcopy;
+ bool zcopy, zcopy_used;
/* TODO: check that we are running from vhost_worker? */
sock = rcu_dereference_check(vq->private_data, 1);
@@ -172,7 +268,7 @@ static void handle_tx(struct vhost_net *net)
for (;;) {
/* Release DMAs done buffers first */
if (zcopy)
- vhost_zerocopy_signal_used(vq);
+ vhost_zerocopy_signal_used(net, vq);
head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
ARRAY_SIZE(vq->iov),
@@ -224,10 +320,14 @@ static void handle_tx(struct vhost_net *net)
iov_length(vq->hdr, s), hdr_size);
break;
}
+ zcopy_used = zcopy && (len >= VHOST_GOODCOPY_LEN ||
+ vq->upend_idx != vq->done_idx);
+
/* use msg_control to pass vhost zerocopy ubuf info to skb */
- if (zcopy) {
+ if (zcopy_used) {
vq->heads[vq->upend_idx].id = head;
- if (len < VHOST_GOODCOPY_LEN) {
+ if (!vhost_net_tx_select_zcopy(net) ||
+ len < VHOST_GOODCOPY_LEN) {
/* copy don't need to wait for DMA done */
vq->heads[vq->upend_idx].len =
VHOST_DMA_DONE_LEN;
@@ -237,7 +337,8 @@ static void handle_tx(struct vhost_net *net)
} else {
struct ubuf_info *ubuf = &vq->ubuf_info[head];
- vq->heads[vq->upend_idx].len = len;
+ vq->heads[vq->upend_idx].len =
+ VHOST_DMA_IN_PROGRESS;
ubuf->callback = vhost_zerocopy_callback;
ubuf->ctx = vq->ubufs;
ubuf->desc = vq->upend_idx;
@@ -251,7 +352,7 @@ static void handle_tx(struct vhost_net *net)
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
- if (zcopy) {
+ if (zcopy_used) {
if (ubufs)
vhost_ubuf_put(ubufs);
vq->upend_idx = ((unsigned)vq->upend_idx - 1) %
@@ -265,11 +366,12 @@ static void handle_tx(struct vhost_net *net)
if (err != len)
pr_debug("Truncated TX packet: "
" len %d != %zd\n", err, len);
- if (!zcopy)
+ if (!zcopy_used)
vhost_add_used_and_signal(&net->dev, vq, head, 0);
else
- vhost_zerocopy_signal_used(vq);
+ vhost_zerocopy_signal_used(net, vq);
total_len += len;
+ vhost_net_tx_packet(net);
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
break;
@@ -587,6 +689,17 @@ static void vhost_net_flush(struct vhost_net *n)
{
vhost_net_flush_vq(n, VHOST_NET_VQ_TX);
vhost_net_flush_vq(n, VHOST_NET_VQ_RX);
+ if (n->dev.vqs[VHOST_NET_VQ_TX].ubufs) {
+ mutex_lock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+ n->tx_flush = true;
+ mutex_unlock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+ /* Wait for all lower device DMAs done. */
+ vhost_ubuf_put_and_wait(n->dev.vqs[VHOST_NET_VQ_TX].ubufs);
+ mutex_lock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+ n->tx_flush = false;
+ kref_init(&n->dev.vqs[VHOST_NET_VQ_TX].ubufs->kref);
+ mutex_unlock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+ }
}
static int vhost_net_release(struct inode *inode, struct file *f)
@@ -597,6 +710,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
vhost_net_stop(n, &tx_sock, &rx_sock);
vhost_net_flush(n);
+ vhost_dev_stop(&n->dev);
vhost_dev_cleanup(&n->dev, false);
if (tx_sock)
fput(tx_sock->file);
@@ -722,6 +836,10 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
r = vhost_init_used(vq);
if (r)
goto err_vq;
+
+ n->tx_packets = 0;
+ n->tx_zcopy_err = 0;
+ n->tx_flush = false;
}
mutex_unlock(&vq->mutex);
@@ -729,7 +847,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
if (oldubufs) {
vhost_ubuf_put_and_wait(oldubufs);
mutex_lock(&vq->mutex);
- vhost_zerocopy_signal_used(vq);
+ vhost_zerocopy_signal_used(n, vq);
mutex_unlock(&vq->mutex);
}
@@ -838,8 +956,11 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
return vhost_net_reset_owner(n);
default:
mutex_lock(&n->dev.mutex);
- r = vhost_dev_ioctl(&n->dev, ioctl, arg);
- vhost_net_flush(n);
+ r = vhost_dev_ioctl(&n->dev, ioctl, argp);
+ if (r == -ENOIOCTLCMD)
+ r = vhost_vring_ioctl(&n->dev, ioctl, argp);
+ else
+ vhost_net_flush(n);
mutex_unlock(&n->dev.mutex);
return r;
}
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index aa31692064dd..d670130ee687 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -34,7 +34,6 @@
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/eventfd.h>
-#include <linux/vhost.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/unaligned.h>
@@ -231,7 +230,7 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl(
nacl = kzalloc(sizeof(struct tcm_vhost_nacl), GFP_KERNEL);
if (!nacl) {
- pr_err("Unable to alocate struct tcm_vhost_nacl\n");
+ pr_err("Unable to allocate struct tcm_vhost_nacl\n");
return NULL;
}
@@ -415,14 +414,12 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
{
struct tcm_vhost_cmd *tv_cmd;
struct tcm_vhost_nexus *tv_nexus;
- struct se_session *se_sess;
tv_nexus = tv_tpg->tpg_nexus;
if (!tv_nexus) {
pr_err("Unable to locate active struct tcm_vhost_nexus\n");
return ERR_PTR(-EIO);
}
- se_sess = tv_nexus->tvn_se_sess;
tv_cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC);
if (!tv_cmd) {
@@ -895,6 +892,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
vhost_scsi_clear_endpoint(s, &backend);
}
+ vhost_dev_stop(&s->dev);
vhost_dev_cleanup(&s->dev, false);
kfree(s);
return 0;
@@ -970,7 +968,10 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
return vhost_scsi_set_features(vs, features);
default:
mutex_lock(&vs->dev.mutex);
- r = vhost_dev_ioctl(&vs->dev, ioctl, arg);
+ r = vhost_dev_ioctl(&vs->dev, ioctl, argp);
+ /* TODO: flush backend after dev ioctl. */
+ if (r == -ENOIOCTLCMD)
+ r = vhost_vring_ioctl(&vs->dev, ioctl, argp);
mutex_unlock(&vs->dev.mutex);
return r;
}
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index dedaf81d8f36..34389f75fe65 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -26,10 +26,6 @@
#include <linux/kthread.h>
#include <linux/cgroup.h>
-#include <linux/net.h>
-#include <linux/if_packet.h>
-#include <linux/if_arp.h>
-
#include "vhost.h"
enum {
@@ -414,28 +410,16 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
return 0;
}
-/* In case of DMA done not in order in lower device driver for some reason.
- * upend_idx is used to track end of used idx, done_idx is used to track head
- * of used idx. Once lower device DMA done contiguously, we will signal KVM
- * guest used idx.
- */
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+void vhost_dev_stop(struct vhost_dev *dev)
{
int i;
- int j = 0;
-
- for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
- if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
- vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
- vhost_add_used_and_signal(vq->dev, vq,
- vq->heads[i].id, 0);
- ++j;
- } else
- break;
+
+ for (i = 0; i < dev->nvqs; ++i) {
+ if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
+ vhost_poll_stop(&dev->vqs[i].poll);
+ vhost_poll_flush(&dev->vqs[i].poll);
+ }
}
- if (j)
- vq->done_idx = i;
- return j;
}
/* Caller should have device mutex if and only if locked is set */
@@ -444,17 +428,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
int i;
for (i = 0; i < dev->nvqs; ++i) {
- if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
- vhost_poll_stop(&dev->vqs[i].poll);
- vhost_poll_flush(&dev->vqs[i].poll);
- }
- /* Wait for all lower device DMAs done. */
- if (dev->vqs[i].ubufs)
- vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
-
- /* Signal guest as appropriate. */
- vhost_zerocopy_signal_used(&dev->vqs[i]);
-
if (dev->vqs[i].error_ctx)
eventfd_ctx_put(dev->vqs[i].error_ctx);
if (dev->vqs[i].error)
@@ -634,7 +607,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
return 0;
}
-static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
+long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
{
struct file *eventfp, *filep = NULL;
bool pollstart = false, pollstop = false;
@@ -829,9 +802,8 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
}
/* Caller must have device mutex */
-long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
+long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
{
- void __user *argp = (void __user *)arg;
struct file *eventfp, *filep = NULL;
struct eventfd_ctx *ctx = NULL;
u64 p;
@@ -902,7 +874,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
fput(filep);
break;
default:
- r = vhost_set_vring(d, ioctl, argp);
+ r = -ENOIOCTLCMD;
break;
}
done:
@@ -1599,14 +1571,3 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
kfree(ubufs);
}
-
-void vhost_zerocopy_callback(struct ubuf_info *ubuf)
-{
- struct vhost_ubuf_ref *ubufs = ubuf->ctx;
- struct vhost_virtqueue *vq = ubufs->vq;
-
- vhost_poll_queue(&vq->poll);
- /* set len = 1 to mark this desc buffers done DMA */
- vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
- kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
-}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 1125af3d27d1..2639c58b23ab 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -7,17 +7,11 @@
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/file.h>
-#include <linux/skbuff.h>
#include <linux/uio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ring.h>
#include <linux/atomic.h>
-/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
- * done */
-#define VHOST_DMA_DONE_LEN 1
-#define VHOST_DMA_CLEAR_LEN 0
-
struct vhost_device;
struct vhost_work;
@@ -70,6 +64,8 @@ struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
void vhost_ubuf_put(struct vhost_ubuf_ref *);
void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
+struct ubuf_info;
+
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
@@ -167,7 +163,9 @@ long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs);
long vhost_dev_check_owner(struct vhost_dev *);
long vhost_dev_reset_owner(struct vhost_dev *);
void vhost_dev_cleanup(struct vhost_dev *, bool locked);
-long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
+void vhost_dev_stop(struct vhost_dev *);
+long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
+long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp);
int vhost_vq_access_ok(struct vhost_virtqueue *vq);
int vhost_log_access_ok(struct vhost_dev *);
@@ -191,8 +189,6 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
-void vhost_zerocopy_callback(struct ubuf_info *);
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
#define vq_err(vq, fmt, ...) do { \
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index c39d6e46f8c5..b52f62595f65 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -31,7 +31,7 @@
#include <linux/gfp.h>
#include <mach/lcdc.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 1b5ee8ec192a..e31f5b33b501 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -30,7 +30,7 @@
#include <linux/uaccess.h>
#include <linux/module.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index c510a4457398..d4e7684e7045 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -25,7 +25,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <plat-omap/dma-omap.h>
+#include <linux/omap-dma.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 05e1be85fdee..dc42e44b6bc1 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -32,6 +32,7 @@
#include <linux/timer.h>
#include <linux/bitops.h>
#include <linux/uaccess.h>
+#include <linux/of.h>
#include "at91sam9_wdt.h"
@@ -302,11 +303,21 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
return res;
}
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_wdt_dt_ids[] __initconst = {
+ { .compatible = "atmel,at91sam9260-wdt" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
+#endif
+
static struct platform_driver at91wdt_driver = {
.remove = __exit_p(at91wdt_remove),
.driver = {
.name = "at91_wdt",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_wdt_dt_ids),
},
};
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 5b06d31ab6a9..c0bc92d8e438 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -212,7 +212,7 @@ static long booke_wdt_ioctl(struct file *file,
return 0;
}
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
static unsigned long wdt_is_active;
static int booke_wdt_open(struct inode *inode, struct file *file)
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 43cc1a1e25d4..3e3ebbc83faf 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -45,8 +45,6 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
-#include <mach/hardware.h>
-
#include <linux/platform_data/omap-wd-timer.h>
#include "omap_wdt.h"
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 961d664e2d2f..68dcc59cd287 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -360,7 +360,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
if (!dev_data->pci_saved_state)
dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
else {
- dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+ dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
__pci_reset_function_locked(dev);
pci_restore_state(dev);
}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index c72ead869507..596617ecd329 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -413,7 +413,7 @@ struct btrfs_root_backup {
__le64 bytes_used;
__le64 num_devices;
/* future */
- __le64 unsed_64[4];
+ __le64 unused_64[4];
u8 tree_root_level;
u8 chunk_root_level;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3d3e2c17d8d1..06b2635073f3 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3888,7 +3888,7 @@ static int flush_space(struct btrfs_root *root,
* @root - the root we're allocating for
* @block_rsv - the block_rsv we're allocating for
* @orig_bytes - the number of bytes we want
- * @flush - wether or not we can flush to make our reservation
+ * @flush - whether or not we can flush to make our reservation
*
* This will reserve orgi_bytes number of bytes from the space info associated
* with the block_rsv. If there is not enough space it will make an attempt to
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index b8cbc8d5c7f7..ce9f79216723 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -234,12 +234,11 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
}
/**
- * unpint_extent_cache - unpin an extent from the cache
+ * unpin_extent_cache - unpin an extent from the cache
* @tree: tree to unpin the extent in
* @start: logical offset in the file
* @len: length of the extent
* @gen: generation that this extent has been modified in
- * @prealloc: if this is set we need to clear the prealloc flag
*
* Called after an extent has been written to disk properly. Set the generation
* to the generation that actually added the file item to the inode so we know
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index dd27a0b46a37..853fc7beedfa 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -76,7 +76,7 @@ struct btrfs_ordered_sum {
#define BTRFS_ORDERED_IOERR 6 /* We had an io error when writing this out */
-#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates wether this ordered extent
+#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates whether this ordered extent
* has done its due diligence in updating
* the isize. */
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 0f5ebb72a5ea..e3c6ee3cc2ba 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4294,7 +4294,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
rcu_read_lock();
name = rcu_dereference(dev->name);
- pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu "
+ pr_debug("btrfs_map_bio: rw %d, sector=%llu, dev=%lu "
"(%s id %llu), size=%u\n", rw,
(u64)bio->bi_sector, (u_long)dev->bdev->bd_dev,
name->str, dev->devid, bio->bi_size);
diff --git a/fs/cifs/README b/fs/cifs/README
index 22ab7b5b8da7..2d5622f60e11 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -480,7 +480,7 @@ A partial list of the supported mount options follows:
Unicode on the wire.
nomapchars Do not translate any of these seven characters (default).
nocase Request case insensitive path name matching (case
- sensitive is the default if the server suports it).
+ sensitive is the default if the server supports it).
(mount option "ignorecase" is identical to "nocase")
posixpaths If CIFS Unix extensions are supported, attempt to
negotiate posix path name support which allows certain
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3c20de1d59d0..df163da388c9 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2455,7 +2455,7 @@ TAS_BUFFER_FNS(Uninit, uninit)
BUFFER_FNS(Da_Mapped, da_mapped)
/*
- * Add new method to test wether block and inode bitmaps are properly
+ * Add new method to test whether block and inode bitmaps are properly
* initialized. With uninit_bg reading the block from disk is not enough
* to mark the bitmap uptodate. We need to also zero-out the bitmap
*/
diff --git a/fs/fhandle.c b/fs/fhandle.c
index f775bfdd6e4a..cccdc874bb55 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -22,7 +22,7 @@ static long do_sys_name_to_handle(struct path *path,
struct file_handle *handle = NULL;
/*
- * We need t make sure wether the file system
+ * We need to make sure whether the file system
* support decoding of the file handle
*/
if (!path->dentry->d_sb->s_export_op ||
@@ -40,7 +40,7 @@ static long do_sys_name_to_handle(struct path *path,
if (!handle)
return -ENOMEM;
- /* convert handle size to multiple of sizeof(u32) */
+ /* convert handle size to multiple of sizeof(u32) */
handle_dwords = f_handle.handle_bytes >> 2;
/* we ask for a non connected handle */
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 4a55f35a6ced..78bde32ea951 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1,7 +1,7 @@
/*
* hugetlbpage-backed filesystem. Based on ramfs.
*
- * William Irwin, 2002
+ * Nadia Yvette Chambers, 2002
*
* Copyright (C) 2002 Linus Torvalds.
*/
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 7f5120bf0ec2..071d6905f0dd 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1259,7 +1259,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
goto not_jbd;
}
- /* keep track of wether or not this transaction modified us */
+ /* keep track of whether or not this transaction modified us */
was_modified = jh->b_modified;
/*
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index a74ba4659549..d8da40e99d84 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1261,7 +1261,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
goto not_jbd;
}
- /* keep track of wether or not this transaction modified us */
+ /* keep track of whether or not this transaction modified us */
was_modified = jh->b_modified;
/*
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index adb90116d36b..af49e2d6941a 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -33,7 +33,7 @@
* are being written out - and waiting for GC to make progress, naturally.
*
* So we cannot just call iget() or some variant of it, but first have to check
- * wether the inode in question might be in I_FREEING state. Therefore we
+ * whether the inode in question might be in I_FREEING state. Therefore we
* maintain our own per-sb list of "almost deleted" inodes and check against
* that list first. Normally this should be at most 1-2 entries long.
*
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index be20a7e171a0..63d14a99483d 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -89,7 +89,7 @@ static int ncp_file_mmap_fault(struct vm_area_struct *area,
/*
* If I understand ncp_read_kernel() properly, the above always
* fetches from the network, here the analogue of disk.
- * -- wli
+ * -- nyc
*/
count_vm_event(PGMAJFAULT);
mem_cgroup_count_vm_event(area->vm_mm, PGMAJFAULT);
diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig
index 7dceff005a67..e5f911bd80d2 100644
--- a/fs/notify/fanotify/Kconfig
+++ b/fs/notify/fanotify/Kconfig
@@ -4,7 +4,7 @@ config FANOTIFY
select ANON_INODES
default n
---help---
- Say Y here to enable fanotify suport. fanotify is a file access
+ Say Y here to enable fanotify support. fanotify is a file access
notification system which differs from inotify in that it sends
an open file descriptor to the userspace listener along with
the event.
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index c887b1378f7e..48cb994e4922 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -18,7 +18,7 @@
/*
* Basic idea behind the notification queue: An fsnotify group (like inotify)
- * sends the userspace notification about events asyncronously some time after
+ * sends the userspace notification about events asynchronously some time after
* the event happened. When inotify gets an event it will need to add that
* event to the group notify queue. Since a single event might need to be on
* multiple group's notification queues we can't add the event directly to each
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a781bdf06694..701580ddfcc3 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -378,12 +378,13 @@ static int test_perm(int mode, int op)
return -EACCES;
}
-static int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
+static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
{
+ struct ctl_table_root *root = head->root;
int mode;
if (root->permissions)
- mode = root->permissions(root, current->nsproxy, table);
+ mode = root->permissions(head, table);
else
mode = table->mode;
@@ -491,7 +492,7 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
* and won't be until we finish.
*/
error = -EPERM;
- if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
+ if (sysctl_perm(head, table, write ? MAY_WRITE : MAY_READ))
goto out;
/* if that can happen at all, it should be -EINVAL, not -EISDIR */
@@ -717,7 +718,7 @@ static int proc_sys_permission(struct inode *inode, int mask)
if (!table) /* global root - r-xr-xr-x */
error = mask & MAY_WRITE ? -EACCES : 0;
else /* Use the permissions on the sysctl table entry */
- error = sysctl_perm(head->root, table, mask & ~MAY_NOT_BLOCK);
+ error = sysctl_perm(head, table, mask & ~MAY_NOT_BLOCK);
sysctl_head_finish(head);
return error;
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index bb145e4b935e..8b1d7a6a9695 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle);
/* ACPI PCI Interrupt Routing (pci_irq.c) */
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus);
-void acpi_pci_irq_del_prt(struct pci_bus *bus);
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt(int segment, int bus);
/* ACPI PCI Device Binding (pci_bind.c) */
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 6e3f54f37844..fcdd81bd5314 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -22,6 +22,8 @@
#define ATH9K_PLAT_EEP_MAX_WORDS 2048
struct ath9k_platform_data {
+ const char *eeprom_name;
+
u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
u8 *macaddr;
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 22ef21c33d0c..c1da539f5e28 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -99,6 +99,7 @@ struct atm_vcc {
struct atm_dev *dev; /* device back pointer */
struct atm_qos qos; /* QOS */
struct atm_sap sap; /* SAP */
+ void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
int (*push_oam)(struct atm_vcc *vcc,void *cell);
@@ -106,6 +107,7 @@ struct atm_vcc {
void *dev_data; /* per-device data */
void *proto_data; /* per-protocol data */
struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
+ struct module *owner; /* owner of ->push function */
/* SVC part --- may move later ------------------------------------- */
short itf; /* interface number */
struct sockaddr_atmsvc local;
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 4eb31752e2b7..deb0ae58b99b 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -5,10 +5,16 @@
#include <linux/list.h>
#include <linux/io.h>
+struct atmel_ssc_platform_data {
+ int use_dma;
+};
+
struct ssc_device {
struct list_head list;
+ resource_size_t phybase;
void __iomem *regs;
struct platform_device *pdev;
+ struct atmel_ssc_platform_data *pdata;
struct clk *clk;
int user;
int irq;
diff --git a/include/linux/bcm47xx_wdt.h b/include/linux/bcm47xx_wdt.h
new file mode 100644
index 000000000000..e5dfc256485b
--- /dev/null
+++ b/include/linux/bcm47xx_wdt.h
@@ -0,0 +1,19 @@
+#ifndef LINUX_BCM47XX_WDT_H_
+#define LINUX_BCM47XX_WDT_H_
+
+#include <linux/types.h>
+
+
+struct bcm47xx_wdt {
+ u32 (*timer_set)(struct bcm47xx_wdt *, u32);
+ u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32);
+ u32 max_timer_ms;
+
+ void *driver_data;
+};
+
+static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt)
+{
+ return wdt->driver_data;
+}
+#endif /* LINUX_BCM47XX_WDT_H_ */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 4180eb78d575..93b1e091b1e9 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -157,6 +157,7 @@ struct bcma_host_ops {
/* Chip IDs of SoCs */
#define BCMA_CHIP_ID_BCM4706 0x5300
+#define BCMA_PKG_ID_BCM4706L 1
#define BCMA_CHIP_ID_BCM4716 0x4716
#define BCMA_PKG_ID_BCM4716 8
#define BCMA_PKG_ID_BCM4717 9
@@ -166,7 +167,11 @@ struct bcma_host_ops {
#define BCMA_CHIP_ID_BCM4749 0x4749
#define BCMA_CHIP_ID_BCM5356 0x5356
#define BCMA_CHIP_ID_BCM5357 0x5357
+#define BCMA_PKG_ID_BCM5358 9
+#define BCMA_PKG_ID_BCM47186 10
+#define BCMA_PKG_ID_BCM5357 11
#define BCMA_CHIP_ID_BCM53572 53572
+#define BCMA_PKG_ID_BCM47188 9
struct bcma_device {
struct bcma_bus *bus;
@@ -251,7 +256,7 @@ struct bcma_bus {
u8 num;
struct bcma_drv_cc drv_cc;
- struct bcma_drv_pci drv_pci;
+ struct bcma_drv_pci drv_pci[2];
struct bcma_drv_mips drv_mips;
struct bcma_drv_gmac_cmn drv_gmac_cmn;
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 1cf1749440ac..e51359180b6f 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -1,6 +1,8 @@
#ifndef LINUX_BCMA_DRIVER_CC_H_
#define LINUX_BCMA_DRIVER_CC_H_
+#include <linux/platform_device.h>
+
/** ChipCommon core registers. **/
#define BCMA_CC_ID 0x0000
#define BCMA_CC_ID_ID 0x0000FFFF
@@ -510,6 +512,7 @@ struct bcma_chipcommon_pmu {
#ifdef CONFIG_BCMA_DRIVER_MIPS
struct bcma_pflash {
+ bool present;
u8 buswidth;
u32 window;
u32 window_size;
@@ -532,6 +535,7 @@ struct mtd_info;
struct bcma_nflash {
bool present;
+ bool boot; /* This is the flash the SoC boots from */
struct mtd_info *mtd;
};
@@ -552,6 +556,7 @@ struct bcma_drv_cc {
u32 capabilities;
u32 capabilities_ext;
u8 setup_done:1;
+ u8 early_setup_done:1;
/* Fast Powerup Delay constant */
u16 fast_pwrup_delay;
struct bcma_chipcommon_pmu pmu;
@@ -567,6 +572,8 @@ struct bcma_drv_cc {
int nr_serial_ports;
struct bcma_serial_port serial_ports[4];
#endif /* CONFIG_BCMA_DRIVER_MIPS */
+ u32 ticks_per_ms;
+ struct platform_device *watchdog;
};
/* Register access */
@@ -583,14 +590,14 @@ struct bcma_drv_cc {
bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
+extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
-extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
- u32 ticks);
+extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
@@ -606,6 +613,7 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
/* PMU support */
extern void bcma_pmu_init(struct bcma_drv_cc *cc);
+extern void bcma_pmu_early_init(struct bcma_drv_cc *cc);
extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
u32 value);
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
index c0043645cdcb..0baf8a56b794 100644
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -35,13 +35,16 @@ struct bcma_device;
struct bcma_drv_mips {
struct bcma_device *core;
u8 setup_done:1;
+ u8 early_setup_done:1;
unsigned int assigned_irqs;
};
#ifdef CONFIG_BCMA_DRIVER_MIPS
extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
#else
static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
+static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
#endif
extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index 6c9cb93ae3de..7e8104bb7a7e 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -85,6 +85,9 @@
* (2 ZettaBytes), high 32 bits
*/
-#define BCMA_SFLASH 0x1c000000
+#define BCMA_SOC_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
+#define BCMA_SOC_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */
+#define BCMA_SOC_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
+#define BCMA_SOC_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
#endif /* LINUX_BCMA_REGS_H_ */
diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/include/linux/clk/zynq.h
index a129fd1222fb..56be7cd9aa8b 100644
--- a/arch/arm/mach-vt8500/include/mach/irqs.h
+++ b/include/linux/clk/zynq.h
@@ -1,7 +1,5 @@
/*
- * arch/arm/mach-vt8500/include/mach/irqs.h
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ * Copyright (C) 2012 National Instruments
*
* 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
@@ -18,5 +16,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* This value is just to make the core happy, never used otherwise */
-#define NR_IRQS 128
+#ifndef __LINUX_CLK_ZYNQ_H_
+#define __LINUX_CLK_ZYNQ_H_
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr);
+
+#endif
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1d47dcce11e1..d02da2c6fc1a 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -98,7 +98,7 @@ int dlm_release_lockspace(dlm_lockspace_t *lockspace, int force);
/*
* dlm_lock
*
- * Make an asyncronous request to acquire or convert a lock on a named
+ * Make an asynchronous request to acquire or convert a lock on a named
* resource.
*
* lockspace: context for the request
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c47ec36f3f39..b02099d0b4fc 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -196,6 +196,77 @@ typedef struct {
void *create_event_ex;
} efi_boot_services_t;
+typedef enum {
+ EfiPciIoWidthUint8,
+ EfiPciIoWidthUint16,
+ EfiPciIoWidthUint32,
+ EfiPciIoWidthUint64,
+ EfiPciIoWidthFifoUint8,
+ EfiPciIoWidthFifoUint16,
+ EfiPciIoWidthFifoUint32,
+ EfiPciIoWidthFifoUint64,
+ EfiPciIoWidthFillUint8,
+ EfiPciIoWidthFillUint16,
+ EfiPciIoWidthFillUint32,
+ EfiPciIoWidthFillUint64,
+ EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+typedef enum {
+ EfiPciIoAttributeOperationGet,
+ EfiPciIoAttributeOperationSet,
+ EfiPciIoAttributeOperationEnable,
+ EfiPciIoAttributeOperationDisable,
+ EfiPciIoAttributeOperationSupported,
+ EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+
+typedef struct {
+ void *read;
+ void *write;
+} efi_pci_io_protocol_access_t;
+
+typedef struct {
+ void *poll_mem;
+ void *poll_io;
+ efi_pci_io_protocol_access_t mem;
+ efi_pci_io_protocol_access_t io;
+ efi_pci_io_protocol_access_t pci;
+ void *copy_mem;
+ void *map;
+ void *unmap;
+ void *allocate_buffer;
+ void *free_buffer;
+ void *flush;
+ void *get_location;
+ void *attributes;
+ void *get_bar_attributes;
+ void *set_bar_attributes;
+ uint64_t romsize;
+ void *romimage;
+} efi_pci_io_protocol;
+
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
+
/*
* Types and defines for EFI ResetSystem
*/
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index b006ba0a9f42..243eea1e33d8 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -51,6 +51,26 @@ extern struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
#define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
+/* Reserved Ethernet Addresses per IEEE 802.1Q */
+static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+
+/**
+ * is_link_local_ether_addr - Determine if given Ethernet address is link-local
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
+ * IEEE 802.1Q 8.6.3 Frame filtering.
+ */
+static inline bool is_link_local_ether_addr(const u8 *addr)
+{
+ __be16 *a = (__be16 *)addr;
+ static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
+ static const __be16 m = cpu_to_be16(0xfff0);
+
+ return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
+}
+
/**
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
* @addr: Pointer to a six-byte array containing the Ethernet address
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 24d251f3bab0..c45eabc135e1 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -45,6 +45,7 @@ extern void sk_unattached_filter_destroy(struct sk_filter *fp);
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
extern int sk_detach_filter(struct sock *sk);
extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
+extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
#ifdef CONFIG_BPF_JIT
extern void bpf_jit_compile(struct sk_filter *fp);
@@ -123,6 +124,8 @@ enum {
BPF_S_ANC_CPU,
BPF_S_ANC_ALU_XOR_X,
BPF_S_ANC_SECCOMP_LD_W,
+ BPF_S_ANC_VLAN_TAG,
+ BPF_S_ANC_VLAN_TAG_PRESENT,
};
#endif /* __LINUX_FILTER_H__ */
diff --git a/include/linux/hash.h b/include/linux/hash.h
index 24df9e70406f..61c97ae22e01 100644
--- a/include/linux/hash.h
+++ b/include/linux/hash.h
@@ -1,7 +1,7 @@
#ifndef _LINUX_HASH_H
#define _LINUX_HASH_H
/* Fast hashing routine for ints, longs and pointers.
- (C) 2002 William Lee Irwin III, IBM */
+ (C) 2002 Nadia Yvette Chambers, IBM */
/*
* Knuth recommends primes in approximately golden ratio to the maximum
diff --git a/include/linux/hdlc/Kbuild b/include/linux/hdlc/Kbuild
index 1fb26448faa9..e69de29bb2d1 100644
--- a/include/linux/hdlc/Kbuild
+++ b/include/linux/hdlc/Kbuild
@@ -1 +0,0 @@
-header-y += ioctl.h
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h
index ca8d7e94eb3c..55f277372fed 100644
--- a/include/linux/hid-sensor-ids.h
+++ b/include/linux/hid-sensor-ids.h
@@ -19,7 +19,6 @@
#ifndef _HID_SENSORS_IDS_H
#define _HID_SENSORS_IDS_H
-#define HID_UP_SENSOR 0x00200000
#define HID_MAX_PHY_DEVICES 0xFF
/* Accel 3D (200073) */
diff --git a/include/linux/hid.h b/include/linux/hid.h
index c076041a069e..7330a0fef0c0 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -167,6 +167,7 @@ struct hid_item {
#define HID_UP_MSVENDOR 0xff000000
#define HID_UP_CUSTOM 0x00ff0000
#define HID_UP_LOGIVENDOR 0xffbc0000
+#define HID_UP_SENSOR 0x00200000
#define HID_USAGE 0x0000ffff
@@ -292,6 +293,7 @@ struct hid_item {
*/
#define HID_GROUP_GENERIC 0x0001
#define HID_GROUP_MULTITOUCH 0x0002
+#define HID_GROUP_SENSOR_HUB 0x0003
/*
* This is the global environment of the parser. This information is
@@ -342,6 +344,7 @@ struct hid_collection {
struct hid_usage {
unsigned hid; /* hid usage code */
unsigned collection_index; /* index into collection array */
+ unsigned usage_index; /* index into usage array */
/* hidinput data */
__u16 code; /* input driver code */
__u8 type; /* input driver type */
@@ -684,6 +687,7 @@ struct hid_ll_driver {
extern int hid_debug;
+extern bool hid_ignore(struct hid_device *);
extern int hid_add_device(struct hid_device *);
extern void hid_destroy_device(struct hid_device *);
@@ -706,6 +710,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
struct hid_field *hidinput_get_led_field(struct hid_device *hid);
unsigned int hidinput_count_leds(struct hid_device *hid);
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
void hid_output_report(struct hid_report *report, __u8 *data);
struct hid_device *hid_allocate_device(void);
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
@@ -716,6 +721,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask);
void hid_disconnect(struct hid_device *hid);
const struct hid_device_id *hid_match_id(struct hid_device *hdev,
const struct hid_device_id *id);
+s32 hid_snto32(__u32 value, unsigned n);
/**
* hid_map_usage - map usage input bits
diff --git a/include/linux/i2c/i2c-hid.h b/include/linux/i2c/i2c-hid.h
new file mode 100644
index 000000000000..60e411d764d4
--- /dev/null
+++ b/include/linux/i2c/i2c-hid.h
@@ -0,0 +1,35 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ *
+ * 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_I2C_HID_H
+#define __LINUX_I2C_HID_H
+
+#include <linux/types.h>
+
+/**
+ * struct i2chid_platform_data - used by hid over i2c implementation.
+ * @hid_descriptor_address: i2c register where the HID descriptor is stored.
+ *
+ * Note that it is the responsibility of the platform driver (or the acpi 5.0
+ * driver) to setup the irq related to the gpio in the struct i2c_board_info.
+ * The platform driver should also setup the gpio according to the device:
+ *
+ * A typical example is the following:
+ * irq = gpio_to_irq(intr_gpio);
+ * hkdk4412_i2c_devs5[0].irq = irq; // store the irq in i2c_board_info
+ * gpio_request(intr_gpio, "elan-irq");
+ * s3c_gpio_setpull(intr_gpio, S3C_GPIO_PULL_UP);
+ */
+struct i2c_hid_platform_data {
+ u16 hid_descriptor_address;
+};
+
+#endif /* __LINUX_I2C_HID_H */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 2385119f8bb0..f0859cc73861 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -131,6 +131,8 @@
#define IEEE80211_MAX_MESH_ID_LEN 32
+#define IEEE80211_NUM_TIDS 16
+
#define IEEE80211_QOS_CTL_LEN 2
/* 1d tag mask */
#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
@@ -666,6 +668,21 @@ struct ieee80211_meshconf_ie {
} __attribute__ ((packed));
/**
+ * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags
+ *
+ * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
+ * additional mesh peerings with other mesh STAs
+ * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
+ * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
+ * is ongoing
+ */
+enum mesh_config_capab_flags {
+ IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01,
+ IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08,
+ IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20,
+};
+
+/**
* struct ieee80211_rann_ie
*
* This structure refers to "Root Announcement information element"
@@ -905,6 +922,38 @@ struct ieee80211_tdls_data {
} u;
} __packed;
+/*
+ * Peer-to-Peer IE attribute related definitions.
+ */
+/**
+ * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute.
+ */
+enum ieee80211_p2p_attr_id {
+ IEEE80211_P2P_ATTR_STATUS = 0,
+ IEEE80211_P2P_ATTR_MINOR_REASON,
+ IEEE80211_P2P_ATTR_CAPABILITY,
+ IEEE80211_P2P_ATTR_DEVICE_ID,
+ IEEE80211_P2P_ATTR_GO_INTENT,
+ IEEE80211_P2P_ATTR_GO_CONFIG_TIMEOUT,
+ IEEE80211_P2P_ATTR_LISTEN_CHANNEL,
+ IEEE80211_P2P_ATTR_GROUP_BSSID,
+ IEEE80211_P2P_ATTR_EXT_LISTEN_TIMING,
+ IEEE80211_P2P_ATTR_INTENDED_IFACE_ADDR,
+ IEEE80211_P2P_ATTR_MANAGABILITY,
+ IEEE80211_P2P_ATTR_CHANNEL_LIST,
+ IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+ IEEE80211_P2P_ATTR_DEVICE_INFO,
+ IEEE80211_P2P_ATTR_GROUP_INFO,
+ IEEE80211_P2P_ATTR_GROUP_ID,
+ IEEE80211_P2P_ATTR_INTERFACE,
+ IEEE80211_P2P_ATTR_OPER_CHANNEL,
+ IEEE80211_P2P_ATTR_INVITE_FLAGS,
+ /* 19 - 220: Reserved */
+ IEEE80211_P2P_ATTR_VENDOR_SPECIFIC = 221,
+
+ IEEE80211_P2P_ATTR_MAX
+};
+
/**
* struct ieee80211_bar - HT Block Ack Request
*
@@ -1107,20 +1156,6 @@ struct ieee80211_ht_operation {
#define WLAN_HT_SMPS_CONTROL_STATIC 1
#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3
-#define VHT_MCS_SUPPORTED_SET_SIZE 8
-
-struct ieee80211_vht_capabilities {
- __le32 vht_capabilities_info;
- u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE];
-} __packed;
-
-struct ieee80211_vht_operation {
- u8 vht_op_info_chwidth;
- u8 vht_op_info_chan_center_freq_seg1_idx;
- u8 vht_op_info_chan_center_freq_seg2_idx;
- __le16 vht_basic_mcs_set;
-} __packed;
-
/**
* struct ieee80211_vht_mcs_info - VHT MCS information
* @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
@@ -1128,11 +1163,13 @@ struct ieee80211_vht_operation {
* STA can receive. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest RX data rate supported.
+ * The top 3 bits of this field are reserved.
* @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
* @tx_highest: Indicates highest long GI VHT PPDU data rate
* STA can transmit. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest TX data rate supported.
+ * The top 3 bits of this field are reserved.
*/
struct ieee80211_vht_mcs_info {
__le16 rx_mcs_map;
@@ -1141,38 +1178,107 @@ struct ieee80211_vht_mcs_info {
__le16 tx_highest;
} __packed;
+/**
+ * enum ieee80211_vht_mcs_support - VHT MCS support definitions
+ * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
+ * number of streams
+ * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported
+ * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported
+ * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported
+ *
+ * These definitions are used in each 2-bit subfield of the @rx_mcs_map
+ * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are
+ * both split into 8 subfields by number of streams. These values indicate
+ * which MCSes are supported for the number of streams the value appears
+ * for.
+ */
+enum ieee80211_vht_mcs_support {
+ IEEE80211_VHT_MCS_SUPPORT_0_7 = 0,
+ IEEE80211_VHT_MCS_SUPPORT_0_8 = 1,
+ IEEE80211_VHT_MCS_SUPPORT_0_9 = 2,
+ IEEE80211_VHT_MCS_NOT_SUPPORTED = 3,
+};
+
+/**
+ * struct ieee80211_vht_cap - VHT capabilities
+ *
+ * This structure is the "VHT capabilities element" as
+ * described in 802.11ac D3.0 8.4.2.160
+ * @vht_cap_info: VHT capability info
+ * @supp_mcs: VHT MCS supported rates
+ */
+struct ieee80211_vht_cap {
+ __le32 vht_cap_info;
+ struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+/**
+ * enum ieee80211_vht_chanwidth - VHT channel width
+ * @IEEE80211_VHT_CHANWIDTH_USE_HT: use the HT operation IE to
+ * determine the channel width (20 or 40 MHz)
+ * @IEEE80211_VHT_CHANWIDTH_80MHZ: 80 MHz bandwidth
+ * @IEEE80211_VHT_CHANWIDTH_160MHZ: 160 MHz bandwidth
+ * @IEEE80211_VHT_CHANWIDTH_80P80MHZ: 80+80 MHz bandwidth
+ */
+enum ieee80211_vht_chanwidth {
+ IEEE80211_VHT_CHANWIDTH_USE_HT = 0,
+ IEEE80211_VHT_CHANWIDTH_80MHZ = 1,
+ IEEE80211_VHT_CHANWIDTH_160MHZ = 2,
+ IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3,
+};
+
+/**
+ * struct ieee80211_vht_operation - VHT operation IE
+ *
+ * This structure is the "VHT operation element" as
+ * described in 802.11ac D3.0 8.4.2.161
+ * @chan_width: Operating channel width
+ * @center_freq_seg1_idx: center freq segment 1 index
+ * @center_freq_seg2_idx: center freq segment 2 index
+ * @basic_mcs_set: VHT Basic MCS rate set
+ */
+struct ieee80211_vht_operation {
+ u8 chan_width;
+ u8 center_freq_seg1_idx;
+ u8 center_freq_seg2_idx;
+ __le16 basic_mcs_set;
+} __packed;
+
+
#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2
#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
/* 802.11ac VHT Capabilities */
-#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
-#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
-#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
-#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
-#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
-#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
-#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
-#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
-#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
-#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
-#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
-#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
-#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
-#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
-#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
-#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
-#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
-#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
-#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
-#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
-#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
-#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000
-#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
-#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
-#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
-#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
+#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
+#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
+#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
+#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
+#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
+#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
+#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
+#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
+#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
+#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
+#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
+#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
+#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23
+#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \
+ (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT)
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
+#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
+#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
@@ -1440,8 +1546,6 @@ enum ieee80211_eid {
WLAN_EID_RSN = 48,
WLAN_EID_MMIE = 76,
- WLAN_EID_WPA = 221,
- WLAN_EID_GENERIC = 221,
WLAN_EID_VENDOR_SPECIFIC = 221,
WLAN_EID_QOS_PARAMETER = 222,
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 1cc595a67cc9..f4e56ecd0b1a 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -4,5 +4,22 @@
#include <linux/ip.h>
#include <linux/in6.h>
#include <uapi/linux/if_tunnel.h>
+#include <linux/u64_stats_sync.h>
+
+/*
+ * Locking : hash tables are protected by RCU and RTNL
+ */
+
+#define for_each_ip_tunnel_rcu(pos, start) \
+ for (pos = rcu_dereference(start); pos; pos = rcu_dereference(pos->next))
+
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
#endif /* _IF_TUNNEL_H_ */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index d032780d0ce5..a9d828976a77 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -171,6 +171,9 @@ struct in_ifaddr {
extern int register_inetaddr_notifier(struct notifier_block *nb);
extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+extern void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+ struct ipv4_devconf *devconf);
+
extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
{
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index cc5cca774bab..2e86bd0bfba1 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -69,6 +69,12 @@ static inline bool input_mt_is_active(const struct input_mt_slot *slot)
return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
}
+static inline bool input_mt_is_used(const struct input_mt *mt,
+ const struct input_mt_slot *slot)
+{
+ return slot->frame == mt->frame;
+}
+
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
unsigned int flags);
void input_mt_destroy_slots(struct input_dev *dev);
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 58b82a22a52b..492bc6513533 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -25,6 +25,11 @@ static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
return (struct iphdr *)skb_network_header(skb);
}
+static inline struct iphdr *inner_ip_hdr(const struct sk_buff *skb)
+{
+ return (struct iphdr *)skb_inner_network_header(skb);
+}
+
static inline struct iphdr *ipip_hdr(const struct sk_buff *skb)
{
return (struct iphdr *)skb_transport_header(skb);
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index fcb5d44ea635..8ea3fe0b9759 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -216,7 +216,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf);
/*
* The lower layer reports received messages through this interface.
- * The data_size should be zero if this is an asyncronous message. If
+ * The data_size should be zero if this is an asynchronous message. If
* the lower layer gets an error sending a message, it should format
* an error response in the message response.
*/
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index bcba48a97868..faed1e357dd6 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -47,6 +47,7 @@ struct ipv6_devconf {
__s32 disable_ipv6;
__s32 accept_dad;
__s32 force_tllao;
+ __s32 ndisc_notify;
void *sysctl;
};
@@ -66,6 +67,11 @@ static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
return (struct ipv6hdr *)skb_network_header(skb);
}
+static inline struct ipv6hdr *inner_ipv6_hdr(const struct sk_buff *skb)
+{
+ return (struct ipv6hdr *)skb_inner_network_header(skb);
+}
+
static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb)
{
return (struct ipv6hdr *)skb_transport_header(skb);
@@ -363,20 +369,22 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
#define inet_v6_ipv6only(__sk) 0
#endif /* IS_ENABLED(CONFIG_IPV6) */
-#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
- (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
- ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
- ((__sk)->sk_family == AF_INET6) && \
- ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
- ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-
-#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
- (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
- (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports)) && \
- ((__sk)->sk_family == PF_INET6) && \
- (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr))) && \
- (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->inet_portpair == (__ports)) && \
+ ((__sk)->sk_family == AF_INET6) && \
+ ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
+ ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
+
+#define INET6_TW_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
+ ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
+ ((__sk)->sk_family == AF_INET6) && \
+ ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)) && \
+ ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
#endif /* _IPV6_H */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 06177ba10a16..e83512f63df5 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -282,6 +282,25 @@ static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
return cmp1.tv64 == cmp2.tv64;
}
+/**
+ * ktime_compare - Compares two ktime_t variables for less, greater or equal
+ * @cmp1: comparable1
+ * @cmp2: comparable2
+ *
+ * Returns ...
+ * cmp1 < cmp2: return <0
+ * cmp1 == cmp2: return 0
+ * cmp1 > cmp2: return >0
+ */
+static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
+{
+ if (cmp1.tv64 < cmp2.tv64)
+ return -1;
+ if (cmp1.tv64 > cmp2.tv64)
+ return 1;
+ return 0;
+}
+
static inline s64 ktime_to_us(const ktime_t kt)
{
struct timeval tv = ktime_to_timeval(kt);
diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h
index 7a71ffad037c..cafc7f99e124 100644
--- a/include/linux/lru_cache.h
+++ b/include/linux/lru_cache.h
@@ -52,8 +52,8 @@ We replicate IO (more or less synchronously) to local and remote disk.
For crash recovery after replication node failure,
we need to resync all regions that have been target of in-flight WRITE IO
- (in use, or "hot", regions), as we don't know wether or not those WRITEs have
- made it to stable storage.
+ (in use, or "hot", regions), as we don't know whether or not those WRITEs
+ have made it to stable storage.
To avoid a "full resync", we need to persistently track these regions.
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index dd231ac0bb1f..a580363a7d29 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -78,6 +78,8 @@ enum arizona_type {
#define ARIZONA_NUM_IRQ 50
+struct snd_soc_dapm_context;
+
struct arizona {
struct regmap *regmap;
struct device *dev;
@@ -98,6 +100,8 @@ struct arizona {
struct mutex clk_lock;
int clk32k_ref;
+
+ struct snd_soc_dapm_context *dapm;
};
int arizona_clk32k_enable(struct arizona *arizona);
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h
index 7ab442905a57..8b1d1daaae16 100644
--- a/include/linux/mfd/arizona/pdata.h
+++ b/include/linux/mfd/arizona/pdata.h
@@ -62,6 +62,9 @@
#define ARIZONA_MAX_OUTPUT 6
+#define ARIZONA_HAP_ACT_ERM 0
+#define ARIZONA_HAP_ACT_LRA 2
+
#define ARIZONA_MAX_PDM_SPK 2
struct regulator_init_data;
@@ -114,6 +117,9 @@ struct arizona_pdata {
/** PDM speaker format */
unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
+
+ /** Haptic actuator type */
+ unsigned int hap_act;
};
#endif
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 7671a287dfee..ba26e99c388d 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -76,6 +76,7 @@
#define ARIZONA_RATE_ESTIMATOR_3 0x154
#define ARIZONA_RATE_ESTIMATOR_4 0x155
#define ARIZONA_RATE_ESTIMATOR_5 0x156
+#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1 0x161
#define ARIZONA_FLL1_CONTROL_1 0x171
#define ARIZONA_FLL1_CONTROL_2 0x172
#define ARIZONA_FLL1_CONTROL_3 0x173
@@ -110,6 +111,7 @@
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200
#define ARIZONA_LDO1_CONTROL_1 0x210
+#define ARIZONA_LDO1_CONTROL_2 0x212
#define ARIZONA_LDO2_CONTROL_1 0x213
#define ARIZONA_MIC_BIAS_CTRL_1 0x218
#define ARIZONA_MIC_BIAS_CTRL_2 0x219
@@ -1574,6 +1576,13 @@
#define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH 5 /* SAMPLE_RATE_DETECT_D - [4:0] */
/*
+ * R353 (0x161) - Dynamic Frequency Scaling 1
+ */
+#define ARIZONA_SUBSYS_MAX_FREQ 0x0001 /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT 0 /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH 1 /* SUBSYS_MAX_FREQ */
+
+/*
* R369 (0x171) - FLL1 Control 1
*/
#define ARIZONA_FLL1_FREERUN 0x0002 /* FLL1_FREERUN */
@@ -1889,6 +1898,13 @@
#define ARIZONA_LDO1_ENA_WIDTH 1 /* LDO1_ENA */
/*
+ * R530 (0x212) - LDO1 Control 2
+ */
+#define ARIZONA_LDO1_HI_PWR 0x0001 /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_SHIFT 0 /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_WIDTH 1 /* LDO1_HI_PWR */
+
+/*
* R531 (0x213) - LDO2 Control 1
*/
#define ARIZONA_LDO2_VSEL_MASK 0x07E0 /* LDO2_VSEL - [10:5] */
diff --git a/include/linux/mfd/da9055/pdata.h b/include/linux/mfd/da9055/pdata.h
index 147293b4471d..f87a6c172a91 100644
--- a/include/linux/mfd/da9055/pdata.h
+++ b/include/linux/mfd/da9055/pdata.h
@@ -25,8 +25,29 @@ struct da9055_pdata {
int gpio_base;
struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
- bool reset_enable; /* Enable RTC in RESET Mode */
- enum gpio_select *gpio_rsel; /* Select regulator set thru GPIO 1/2 */
- enum gpio_select *gpio_ren; /* Enable regulator thru GPIO 1/2 */
+ /* Enable RTC in RESET Mode */
+ bool reset_enable;
+ /*
+ * GPI muxed pin to control
+ * regulator state A/B, 0 if not available.
+ */
+ int *gpio_ren;
+ /*
+ * GPI muxed pin to control
+ * regulator set, 0 if not available.
+ */
+ int *gpio_rsel;
+ /*
+ * Regulator mode control bits value (GPI offset) that
+ * that controls the regulator state, 0 if not available.
+ */
+ enum gpio_select *reg_ren;
+ /*
+ * Regulator mode control bits value (GPI offset) that
+ * controls the regulator set A/B, 0 if not available.
+ */
+ enum gpio_select *reg_rsel;
+ /* GPIOs to enable regulator, 0 if not available */
+ int *ena_gpio;
};
#endif /* __DA9055_PDATA_H */
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index 830152cfae33..6ae21bf47d64 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -316,6 +316,7 @@ enum max8997_irq {
#define MAX8997_NUM_GPIO 12
struct max8997_dev {
struct device *dev;
+ struct max8997_platform_data *pdata;
struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
struct i2c_client *rtc; /* slave addr 0x0c */
struct i2c_client *haptic; /* slave addr 0x90 */
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h
index 328d8e24b533..1d4a4fe6ac33 100644
--- a/include/linux/mfd/max8997.h
+++ b/include/linux/mfd/max8997.h
@@ -75,6 +75,7 @@ enum max8998_regulators {
struct max8997_regulator_data {
int id;
struct regulator_init_data *initdata;
+ struct device_node *reg_node;
};
enum max8997_muic_usb_type {
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
index 6bc31d854626..804e280c1e1d 100644
--- a/include/linux/mfd/tps65090.h
+++ b/include/linux/mfd/tps65090.h
@@ -24,6 +24,25 @@
#include <linux/irq.h>
+/* TPS65090 Regulator ID */
+enum {
+ TPS65090_REGULATOR_DCDC1,
+ TPS65090_REGULATOR_DCDC2,
+ TPS65090_REGULATOR_DCDC3,
+ TPS65090_REGULATOR_FET1,
+ TPS65090_REGULATOR_FET2,
+ TPS65090_REGULATOR_FET3,
+ TPS65090_REGULATOR_FET4,
+ TPS65090_REGULATOR_FET5,
+ TPS65090_REGULATOR_FET6,
+ TPS65090_REGULATOR_FET7,
+ TPS65090_REGULATOR_LDO1,
+ TPS65090_REGULATOR_LDO2,
+
+ /* Last entry for maximum ID */
+ TPS65090_REGULATOR_MAX,
+};
+
struct tps65090 {
struct mutex lock;
struct device *dev;
@@ -41,10 +60,26 @@ struct tps65090_subdev_info {
void *platform_data;
};
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ * DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ * gpio.
+ */
+struct tps65090_regulator_plat_data {
+ struct regulator_init_data *reg_init_data;
+ bool enable_ext_control;
+ int gpio;
+};
+
struct tps65090_platform_data {
int irq_base;
int num_subdevs;
struct tps65090_subdev_info *subdevs;
+ struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
};
/*
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index 2dd123194958..f8da0e152567 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -29,6 +29,7 @@ enum {
TPS6586X_ID_LDO_8,
TPS6586X_ID_LDO_9,
TPS6586X_ID_LDO_RTC,
+ TPS6586X_ID_MAX_REGULATOR,
};
enum {
@@ -79,6 +80,8 @@ struct tps6586x_platform_data {
int gpio_base;
int irq_base;
bool pm_off;
+
+ struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
};
/*
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index 1f173306bf05..ae5c249530b4 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -19,6 +19,8 @@
#include <linux/interrupt.h>
#include <linux/regmap.h>
+#include <linux/mfd/wm8994/pdata.h>
+
enum wm8994_type {
WM8994 = 0,
WM8958 = 1,
@@ -55,6 +57,8 @@ struct regulator_bulk_data;
struct wm8994 {
struct mutex irq_lock;
+ struct wm8994_pdata pdata;
+
enum wm8994_type type;
int revision;
int cust_id;
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index fc87be4fdc25..8e21a094836d 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -176,6 +176,11 @@ struct wm8994_pdata {
unsigned int lineout1fb:1;
unsigned int lineout2fb:1;
+ /* Delay between detecting a jack and starting microphone
+ * detect (specified in ms)
+ */
+ int micdet_delay;
+
/* IRQ for microphone detection if brought out directly as a
* signal.
*/
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index de201203bc7c..adfe8c058f29 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -15,6 +15,7 @@
#define MICREL_PHY_ID_MASK 0x00fffff0
+#define PHY_ID_KSZ8873MLL 0x000e7237
#define PHY_ID_KSZ9021 0x00221610
#define PHY_ID_KS8737 0x00221720
#define PHY_ID_KSZ8021 0x00221555
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a848ffc327f4..02e0f6b156c3 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -369,7 +369,7 @@ typedef enum gro_result gro_result_t;
*
* If the rx_handler consider the skb should be ignored, it should return
* RX_HANDLER_EXACT. The skb will only be delivered to protocol handlers that
- * are registred on exact device (ptype->dev == skb->dev).
+ * are registered on exact device (ptype->dev == skb->dev).
*
* If the rx_handler didn't changed skb->dev, but want the skb to be normally
* delivered, it should return RX_HANDLER_PASS.
@@ -887,6 +887,10 @@ struct netdev_fcoe_hbainfo {
* struct net_device *dev, int idx)
* Used to add FDB entries to dump requests. Implementers should add
* entries to skb and update idx with the number of entries.
+ *
+ * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
+ * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
+ * struct net_device *dev)
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
@@ -998,6 +1002,12 @@ struct net_device_ops {
struct netlink_callback *cb,
struct net_device *dev,
int idx);
+
+ int (*ndo_bridge_setlink)(struct net_device *dev,
+ struct nlmsghdr *nlh);
+ int (*ndo_bridge_getlink)(struct sk_buff *skb,
+ u32 pid, u32 seq,
+ struct net_device *dev);
};
/*
@@ -1053,6 +1063,12 @@ struct net_device {
netdev_features_t wanted_features;
/* mask of features inheritable by VLAN devices */
netdev_features_t vlan_features;
+ /* mask of features inherited by encapsulating devices
+ * This field indicates what encapsulation offloads
+ * the hardware is capable of doing, and drivers will
+ * need to set them appropriately.
+ */
+ netdev_features_t hw_enc_features;
/* Interface index. Unique device identifier */
int ifindex;
@@ -1502,16 +1518,25 @@ struct packet_type {
struct net_device *,
struct packet_type *,
struct net_device *);
+ bool (*id_match)(struct packet_type *ptype,
+ struct sock *sk);
+ void *af_packet_priv;
+ struct list_head list;
+};
+
+struct offload_callbacks {
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
netdev_features_t features);
int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff **(*gro_receive)(struct sk_buff **head,
struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb);
- bool (*id_match)(struct packet_type *ptype,
- struct sock *sk);
- void *af_packet_priv;
- struct list_head list;
+};
+
+struct packet_offload {
+ __be16 type; /* This is really htons(ether_type). */
+ struct offload_callbacks callbacks;
+ struct list_head list;
};
#include <linux/notifier.h>
@@ -1551,6 +1576,8 @@ extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
extern rwlock_t dev_base_lock; /* Device list lock */
+extern seqlock_t devnet_rename_seq; /* Device rename lock */
+
#define for_each_netdev(net, d) \
list_for_each_entry(d, &(net)->dev_base_head, dev_list)
@@ -1608,6 +1635,9 @@ extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short
extern void dev_add_pack(struct packet_type *pt);
extern void dev_remove_pack(struct packet_type *pt);
extern void __dev_remove_pack(struct packet_type *pt);
+extern void dev_add_offload(struct packet_offload *po);
+extern void dev_remove_offload(struct packet_offload *po);
+extern void __dev_remove_offload(struct packet_offload *po);
extern struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
unsigned short mask);
@@ -2132,16 +2162,10 @@ extern void dev_kfree_skb_any(struct sk_buff *skb);
extern int netif_rx(struct sk_buff *skb);
extern int netif_rx_ni(struct sk_buff *skb);
extern int netif_receive_skb(struct sk_buff *skb);
-extern gro_result_t dev_gro_receive(struct napi_struct *napi,
- struct sk_buff *skb);
-extern gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
extern gro_result_t napi_gro_receive(struct napi_struct *napi,
struct sk_buff *skb);
extern void napi_gro_flush(struct napi_struct *napi, bool flush_old);
extern struct sk_buff * napi_get_frags(struct napi_struct *napi);
-extern gro_result_t napi_frags_finish(struct napi_struct *napi,
- struct sk_buff *skb,
- gro_result_t ret);
extern gro_result_t napi_gro_frags(struct napi_struct *napi);
static inline void napi_free_frags(struct napi_struct *napi)
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 5f84c6229dc6..610208b18c05 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -47,15 +47,6 @@ ip6t_ext_hdr(u8 nexthdr)
(nexthdr == IPPROTO_DSTOPTS);
}
-enum {
- IP6T_FH_F_FRAG = (1 << 0),
- IP6T_FH_F_AUTH = (1 << 1),
-};
-
-/* find specified header and get offset to it */
-extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
- int target, unsigned short *fragoff, int *fragflg);
-
#ifdef CONFIG_COMPAT
#include <net/compat.h>
diff --git a/include/linux/nfc/pn544.h b/include/linux/nfc/pn544.h
deleted file mode 100644
index 9890bbaf4328..000000000000
--- a/include/linux/nfc/pn544.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Driver include for the PN544 NFC chip.
- *
- * Copyright (C) Nokia Corporation
- *
- * Author: Jari Vanhala <ext-jari.vanhala@nokia.com>
- * Contact: Matti Aaltoenn <matti.j.aaltonen@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _PN544_H_
-#define _PN544_H_
-
-#include <linux/i2c.h>
-
-#define PN544_DRIVER_NAME "pn544"
-#define PN544_MAXWINDOW_SIZE 7
-#define PN544_WINDOW_SIZE 4
-#define PN544_RETRIES 10
-#define PN544_MAX_I2C_TRANSFER 0x0400
-#define PN544_MSG_MAX_SIZE 0x21 /* at normal HCI mode */
-
-/* ioctl */
-#define PN544_CHAR_BASE 'P'
-#define PN544_IOR(num, dtype) _IOR(PN544_CHAR_BASE, num, dtype)
-#define PN544_IOW(num, dtype) _IOW(PN544_CHAR_BASE, num, dtype)
-#define PN544_GET_FW_MODE PN544_IOW(1, unsigned int)
-#define PN544_SET_FW_MODE PN544_IOW(2, unsigned int)
-#define PN544_GET_DEBUG PN544_IOW(3, unsigned int)
-#define PN544_SET_DEBUG PN544_IOW(4, unsigned int)
-
-/* Timing restrictions (ms) */
-#define PN544_RESETVEN_TIME 30 /* 7 */
-#define PN544_PVDDVEN_TIME 0
-#define PN544_VBATVEN_TIME 0
-#define PN544_GPIO4VEN_TIME 0
-#define PN544_WAKEUP_ACK 5
-#define PN544_WAKEUP_GUARD (PN544_WAKEUP_ACK + 1)
-#define PN544_INACTIVITY_TIME 1000
-#define PN544_INTERFRAME_DELAY 200 /* us */
-#define PN544_BAUDRATE_CHANGE 150 /* us */
-
-/* Debug bits */
-#define PN544_DEBUG_BUF 0x01
-#define PN544_DEBUG_READ 0x02
-#define PN544_DEBUG_WRITE 0x04
-#define PN544_DEBUG_IRQ 0x08
-#define PN544_DEBUG_CALLS 0x10
-#define PN544_DEBUG_MODE 0x20
-
-/* Normal (HCI) mode */
-#define PN544_LLC_HCI_OVERHEAD 3 /* header + crc (to length) */
-#define PN544_LLC_MIN_SIZE (1 + PN544_LLC_HCI_OVERHEAD) /* length + */
-#define PN544_LLC_MAX_DATA (PN544_MSG_MAX_SIZE - 2)
-#define PN544_LLC_MAX_HCI_SIZE (PN544_LLC_MAX_DATA - 2)
-
-struct pn544_llc_packet {
- unsigned char length; /* of rest of packet */
- unsigned char header;
- unsigned char data[PN544_LLC_MAX_DATA]; /* includes crc-ccitt */
-};
-
-/* Firmware upgrade mode */
-#define PN544_FW_HEADER_SIZE 3
-/* max fw transfer is 1024bytes, but I2C limits it to 0xC0 */
-#define PN544_MAX_FW_DATA (PN544_MAX_I2C_TRANSFER - PN544_FW_HEADER_SIZE)
-
-struct pn544_fw_packet {
- unsigned char command; /* status in answer */
- unsigned char length[2]; /* big-endian order (msf) */
- unsigned char data[PN544_MAX_FW_DATA];
-};
-
-#ifdef __KERNEL__
-enum {
- NFC_GPIO_ENABLE,
- NFC_GPIO_FW_RESET,
- NFC_GPIO_IRQ
-};
-
-/* board config */
-struct pn544_nfc_platform_data {
- int (*request_resources) (struct i2c_client *client);
- void (*free_resources) (void);
- void (*enable) (int fw);
- int (*test) (void);
- void (*disable) (void);
- int (*get_gpio)(int type);
-};
-#endif /* __KERNEL__ */
-
-#endif /* _PN544_H_ */
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index eb475a8ea25b..7af25a9c9c51 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -19,4 +19,370 @@ static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
}
#endif
+/*
+ * Legacy OMAP DMA handling defines and functions
+ *
+ * NOTE: Do not use these any longer.
+ *
+ * Use the generic dmaengine functions as defined in
+ * include/linux/dmaengine.h.
+ *
+ * Copyright (C) 2003 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+
+#define INT_DMA_LCD 25
+
+#define OMAP1_DMA_TOUT_IRQ (1 << 0)
+#define OMAP_DMA_DROP_IRQ (1 << 1)
+#define OMAP_DMA_HALF_IRQ (1 << 2)
+#define OMAP_DMA_FRAME_IRQ (1 << 3)
+#define OMAP_DMA_LAST_IRQ (1 << 4)
+#define OMAP_DMA_BLOCK_IRQ (1 << 5)
+#define OMAP1_DMA_SYNC_IRQ (1 << 6)
+#define OMAP2_DMA_PKT_IRQ (1 << 7)
+#define OMAP2_DMA_TRANS_ERR_IRQ (1 << 8)
+#define OMAP2_DMA_SECURE_ERR_IRQ (1 << 9)
+#define OMAP2_DMA_SUPERVISOR_ERR_IRQ (1 << 10)
+#define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11)
+
+#define OMAP_DMA_CCR_EN (1 << 7)
+#define OMAP_DMA_CCR_RD_ACTIVE (1 << 9)
+#define OMAP_DMA_CCR_WR_ACTIVE (1 << 10)
+#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC (1 << 24)
+#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25)
+
+#define OMAP_DMA_DATA_TYPE_S8 0x00
+#define OMAP_DMA_DATA_TYPE_S16 0x01
+#define OMAP_DMA_DATA_TYPE_S32 0x02
+
+#define OMAP_DMA_SYNC_ELEMENT 0x00
+#define OMAP_DMA_SYNC_FRAME 0x01
+#define OMAP_DMA_SYNC_BLOCK 0x02
+#define OMAP_DMA_SYNC_PACKET 0x03
+
+#define OMAP_DMA_DST_SYNC_PREFETCH 0x02
+#define OMAP_DMA_SRC_SYNC 0x01
+#define OMAP_DMA_DST_SYNC 0x00
+
+#define OMAP_DMA_PORT_EMIFF 0x00
+#define OMAP_DMA_PORT_EMIFS 0x01
+#define OMAP_DMA_PORT_OCP_T1 0x02
+#define OMAP_DMA_PORT_TIPB 0x03
+#define OMAP_DMA_PORT_OCP_T2 0x04
+#define OMAP_DMA_PORT_MPUI 0x05
+
+#define OMAP_DMA_AMODE_CONSTANT 0x00
+#define OMAP_DMA_AMODE_POST_INC 0x01
+#define OMAP_DMA_AMODE_SINGLE_IDX 0x02
+#define OMAP_DMA_AMODE_DOUBLE_IDX 0x03
+
+#define DMA_DEFAULT_FIFO_DEPTH 0x10
+#define DMA_DEFAULT_ARB_RATE 0x01
+/* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */
+#define DMA_THREAD_RESERVE_NORM (0x00 << 12) /* Def */
+#define DMA_THREAD_RESERVE_ONET (0x01 << 12)
+#define DMA_THREAD_RESERVE_TWOT (0x02 << 12)
+#define DMA_THREAD_RESERVE_THREET (0x03 << 12)
+#define DMA_THREAD_FIFO_NONE (0x00 << 14) /* Def */
+#define DMA_THREAD_FIFO_75 (0x01 << 14)
+#define DMA_THREAD_FIFO_25 (0x02 << 14)
+#define DMA_THREAD_FIFO_50 (0x03 << 14)
+
+/* DMA4_OCP_SYSCONFIG bits */
+#define DMA_SYSCONFIG_MIDLEMODE_MASK (3 << 12)
+#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK (3 << 8)
+#define DMA_SYSCONFIG_EMUFREE (1 << 5)
+#define DMA_SYSCONFIG_SIDLEMODE_MASK (3 << 3)
+#define DMA_SYSCONFIG_SOFTRESET (1 << 2)
+#define DMA_SYSCONFIG_AUTOIDLE (1 << 0)
+
+#define DMA_SYSCONFIG_MIDLEMODE(n) ((n) << 12)
+#define DMA_SYSCONFIG_SIDLEMODE(n) ((n) << 3)
+
+#define DMA_IDLEMODE_SMARTIDLE 0x2
+#define DMA_IDLEMODE_NO_IDLE 0x1
+#define DMA_IDLEMODE_FORCE_IDLE 0x0
+
+/* Chaining modes*/
+#ifndef CONFIG_ARCH_OMAP1
+#define OMAP_DMA_STATIC_CHAIN 0x1
+#define OMAP_DMA_DYNAMIC_CHAIN 0x2
+#define OMAP_DMA_CHAIN_ACTIVE 0x1
+#define OMAP_DMA_CHAIN_INACTIVE 0x0
+#endif
+
+#define DMA_CH_PRIO_HIGH 0x1
+#define DMA_CH_PRIO_LOW 0x0 /* Def */
+
+/* Errata handling */
+#define IS_DMA_ERRATA(id) (errata & (id))
+#define SET_DMA_ERRATA(id) (errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING BIT(0x0)
+#define DMA_ERRATA_PARALLEL_CHANNELS BIT(0x1)
+#define DMA_ERRATA_i378 BIT(0x2)
+#define DMA_ERRATA_i541 BIT(0x3)
+#define DMA_ERRATA_i88 BIT(0x4)
+#define DMA_ERRATA_3_3 BIT(0x5)
+#define DMA_ROMCODE_BUG BIT(0x6)
+
+/* Attributes for OMAP DMA Contrller */
+#define DMA_LINKED_LCH BIT(0x0)
+#define GLOBAL_PRIORITY BIT(0x1)
+#define RESERVE_CHANNEL BIT(0x2)
+#define IS_CSSA_32 BIT(0x3)
+#define IS_CDSA_32 BIT(0x4)
+#define IS_RW_PRIORITY BIT(0x5)
+#define ENABLE_1510_MODE BIT(0x6)
+#define SRC_PORT BIT(0x7)
+#define DST_PORT BIT(0x8)
+#define SRC_INDEX BIT(0x9)
+#define DST_INDEX BIT(0xa)
+#define IS_BURST_ONLY4 BIT(0xb)
+#define CLEAR_CSR_ON_READ BIT(0xc)
+#define IS_WORD_16 BIT(0xd)
+#define ENABLE_16XX_MODE BIT(0xe)
+#define HS_CHANNELS_RESERVED BIT(0xf)
+
+/* Defines for DMA Capabilities */
+#define DMA_HAS_TRANSPARENT_CAPS (0x1 << 18)
+#define DMA_HAS_CONSTANT_FILL_CAPS (0x1 << 19)
+#define DMA_HAS_DESCRIPTOR_CAPS (0x3 << 20)
+
+enum omap_reg_offsets {
+
+GCR, GSCR, GRST1, HW_ID,
+PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
+PCHD_ID, CAPS_0, CAPS_1, CAPS_2,
+CAPS_3, CAPS_4, PCH2_SR, PCH0_SR,
+PCH1_SR, PCHD_SR, REVISION, IRQSTATUS_L0,
+IRQSTATUS_L1, IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0,
+IRQENABLE_L1, IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS,
+OCP_SYSCONFIG,
+
+/* omap1+ specific */
+CPC, CCR2, LCH_CTRL,
+
+/* Common registers for all omap's */
+CSDP, CCR, CICR, CSR,
+CEN, CFN, CSFI, CSEI,
+CSAC, CDAC, CDEI,
+CDFI, CLNK_CTRL,
+
+/* Channel specific registers */
+CSSA, CDSA, COLOR,
+CCEN, CCFN,
+
+/* omap3630 and omap4 specific */
+CDP, CNDP, CCDN,
+
+};
+
+enum omap_dma_burst_mode {
+ OMAP_DMA_DATA_BURST_DIS = 0,
+ OMAP_DMA_DATA_BURST_4,
+ OMAP_DMA_DATA_BURST_8,
+ OMAP_DMA_DATA_BURST_16,
+};
+
+enum end_type {
+ OMAP_DMA_LITTLE_ENDIAN = 0,
+ OMAP_DMA_BIG_ENDIAN
+};
+
+enum omap_dma_color_mode {
+ OMAP_DMA_COLOR_DIS = 0,
+ OMAP_DMA_CONSTANT_FILL,
+ OMAP_DMA_TRANSPARENT_COPY
+};
+
+enum omap_dma_write_mode {
+ OMAP_DMA_WRITE_NON_POSTED = 0,
+ OMAP_DMA_WRITE_POSTED,
+ OMAP_DMA_WRITE_LAST_NON_POSTED
+};
+
+enum omap_dma_channel_mode {
+ OMAP_DMA_LCH_2D = 0,
+ OMAP_DMA_LCH_G,
+ OMAP_DMA_LCH_P,
+ OMAP_DMA_LCH_PD
+};
+
+struct omap_dma_channel_params {
+ int data_type; /* data type 8,16,32 */
+ int elem_count; /* number of elements in a frame */
+ int frame_count; /* number of frames in a element */
+
+ int src_port; /* Only on OMAP1 REVISIT: Is this needed? */
+ int src_amode; /* constant, post increment, indexed,
+ double indexed */
+ unsigned long src_start; /* source address : physical */
+ int src_ei; /* source element index */
+ int src_fi; /* source frame index */
+
+ int dst_port; /* Only on OMAP1 REVISIT: Is this needed? */
+ int dst_amode; /* constant, post increment, indexed,
+ double indexed */
+ unsigned long dst_start; /* source address : physical */
+ int dst_ei; /* source element index */
+ int dst_fi; /* source frame index */
+
+ int trigger; /* trigger attached if the channel is
+ synchronized */
+ int sync_mode; /* sycn on element, frame , block or packet */
+ int src_or_dst_synch; /* source synch(1) or destination synch(0) */
+
+ int ie; /* interrupt enabled */
+
+ unsigned char read_prio;/* read priority */
+ unsigned char write_prio;/* write priority */
+
+#ifndef CONFIG_ARCH_OMAP1
+ enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */
+#endif
+};
+
+struct omap_dma_lch {
+ int next_lch;
+ int dev_id;
+ u16 saved_csr;
+ u16 enabled_irqs;
+ const char *dev_name;
+ void (*callback)(int lch, u16 ch_status, void *data);
+ void *data;
+ long flags;
+ /* required for Dynamic chaining */
+ int prev_linked_ch;
+ int next_linked_ch;
+ int state;
+ int chain_id;
+ int status;
+};
+
+struct omap_dma_dev_attr {
+ u32 dev_caps;
+ u16 lch_count;
+ u16 chan_count;
+ struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+ struct omap_dma_dev_attr *dma_attr;
+ u32 errata;
+ void (*disable_irq_lch)(int lch);
+ void (*show_dma_caps)(void);
+ void (*clear_lch_regs)(int lch);
+ void (*clear_dma)(int lch);
+ void (*dma_write)(u32 val, int reg, int lch);
+ u32 (*dma_read)(int reg, int lch);
+};
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+#define dma_omap2plus() 1
+#else
+#define dma_omap2plus() 0
#endif
+#define dma_omap1() (!dma_omap2plus())
+#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
+#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
+
+extern void omap_set_dma_priority(int lch, int dst_port, int priority);
+extern int omap_request_dma(int dev_id, const char *dev_name,
+ void (*callback)(int lch, u16 ch_status, void *data),
+ void *data, int *dma_ch);
+extern void omap_enable_dma_irq(int ch, u16 irq_bits);
+extern void omap_disable_dma_irq(int ch, u16 irq_bits);
+extern void omap_free_dma(int ch);
+extern void omap_start_dma(int lch);
+extern void omap_stop_dma(int lch);
+extern void omap_set_dma_transfer_params(int lch, int data_type,
+ int elem_count, int frame_count,
+ int sync_mode,
+ int dma_trigger, int src_or_dst_synch);
+extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
+ u32 color);
+extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
+extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode);
+
+extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
+ unsigned long src_start,
+ int src_ei, int src_fi);
+extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
+extern void omap_set_dma_src_data_pack(int lch, int enable);
+extern void omap_set_dma_src_burst_mode(int lch,
+ enum omap_dma_burst_mode burst_mode);
+
+extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
+ unsigned long dest_start,
+ int dst_ei, int dst_fi);
+extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
+extern void omap_set_dma_dest_data_pack(int lch, int enable);
+extern void omap_set_dma_dest_burst_mode(int lch,
+ enum omap_dma_burst_mode burst_mode);
+
+extern void omap_set_dma_params(int lch,
+ struct omap_dma_channel_params *params);
+
+extern void omap_dma_link_lch(int lch_head, int lch_queue);
+extern void omap_dma_unlink_lch(int lch_head, int lch_queue);
+
+extern int omap_set_dma_callback(int lch,
+ void (*callback)(int lch, u16 ch_status, void *data),
+ void *data);
+extern dma_addr_t omap_get_dma_src_pos(int lch);
+extern dma_addr_t omap_get_dma_dst_pos(int lch);
+extern void omap_clear_dma(int lch);
+extern int omap_get_dma_active_status(int lch);
+extern int omap_dma_running(void);
+extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
+ int tparams);
+extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
+ unsigned char write_prio);
+extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype);
+extern void omap_set_dma_src_endian_type(int lch, enum end_type etype);
+extern int omap_get_dma_index(int lch, int *ei, int *fi);
+
+void omap_dma_global_context_save(void);
+void omap_dma_global_context_restore(void);
+
+extern void omap_dma_disable_irq(int lch);
+
+/* Chaining APIs */
+#ifndef CONFIG_ARCH_OMAP1
+extern int omap_request_dma_chain(int dev_id, const char *dev_name,
+ void (*callback) (int lch, u16 ch_status,
+ void *data),
+ int *chain_id, int no_of_chans,
+ int chain_mode,
+ struct omap_dma_channel_params params);
+extern int omap_free_dma_chain(int chain_id);
+extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
+ int dest_start, int elem_count,
+ int frame_count, void *callbk_data);
+extern int omap_start_dma_chain_transfers(int chain_id);
+extern int omap_stop_dma_chain_transfers(int chain_id);
+extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
+extern int omap_get_dma_chain_dst_pos(int chain_id);
+extern int omap_get_dma_chain_src_pos(int chain_id);
+
+extern int omap_modify_dma_chain_params(int chain_id,
+ struct omap_dma_channel_params params);
+extern int omap_dma_chain_status(int chain_id);
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
+#include <mach/lcd_dma.h>
+#else
+static inline int omap_lcd_dma_running(void)
+{
+ return 0;
+}
+#endif
+
+#endif /* __LINUX_OMAP_DMA_H */
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index eb1efa54fe84..d42e174bd0c8 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -243,6 +243,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_ICMPV6, /* struct ovs_key_icmpv6 */
OVS_KEY_ATTR_ARP, /* struct ovs_key_arp */
OVS_KEY_ATTR_ND, /* struct ovs_key_nd */
+ OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */
__OVS_KEY_ATTR_MAX
};
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d03d2463efac..15472d691ee6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -333,6 +333,8 @@ struct pci_dev {
};
struct pci_ats *ats; /* Address Translation Service */
#endif
+ phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
+ size_t romlen; /* Length of ROM if it's not from the BAR */
};
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@ -538,6 +540,9 @@ enum pci_ers_result {
/* Device driver is fully recovered and operational */
PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5,
+
+ /* No AER capabilities registered for the driver */
+ PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
};
/* PCI bus error event callbacks */
@@ -573,6 +578,7 @@ struct pci_driver {
int (*resume_early) (struct pci_dev *dev);
int (*resume) (struct pci_dev *dev); /* Device woken up */
void (*shutdown) (struct pci_dev *dev);
+ int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */
const struct pci_error_handlers *err_handler;
struct device_driver driver;
struct pci_dynids dynids;
@@ -604,6 +610,20 @@ struct pci_driver {
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
/**
+ * PCI_DEVICE_SUB - macro used to describe a specific pci device with subsystem
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ * @subvend: the 16 bit PCI Subvendor ID
+ * @subdev: the 16 bit PCI Subdevice ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific device with subsystem information.
+ */
+#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
+ .vendor = (vend), .device = (dev), \
+ .subvendor = (subvend), .subdevice = (subdev)
+
+/**
* PCI_DEVICE_CLASS - macro used to describe a specific pci device class
* @dev_class: the class, subclass, prog-if triple for this device
* @dev_class_mask: the class mask for this device
@@ -712,6 +732,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
extern void pci_dev_put(struct pci_dev *dev);
extern void pci_remove_bus(struct pci_bus *b);
extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+void pci_stop_root_bus(struct pci_bus *bus);
+void pci_remove_root_bus(struct pci_bus *bus);
void pci_setup_cardbus(struct pci_bus *bus);
extern void pci_sort_breadthfirst(void);
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
@@ -956,6 +978,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void);
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
void pdev_enable_device(struct pci_dev *);
int pci_enable_resources(struct pci_dev *, int mask);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
@@ -1590,6 +1613,7 @@ void pcibios_disable_device(struct pci_dev *dev);
void pcibios_set_master(struct pci_dev *dev);
int pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state);
+int pcibios_add_device(struct pci_dev *dev);
#ifdef CONFIG_PCI_MMCONFIG
extern void __init pci_mmcfg_early_init(void);
@@ -1599,7 +1623,7 @@ static inline void pci_mmcfg_early_init(void) { }
static inline void pci_mmcfg_late_init(void) { }
#endif
-int pci_ext_cfg_avail(struct pci_dev *dev);
+int pci_ext_cfg_avail(void);
void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
@@ -1608,6 +1632,8 @@ extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
extern void pci_disable_sriov(struct pci_dev *dev);
extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
extern int pci_num_vf(struct pci_dev *dev);
+extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
+extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
#else
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{
@@ -1624,6 +1650,14 @@ static inline int pci_num_vf(struct pci_dev *dev)
{
return 0;
}
+static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+ return 0;
+}
+static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+ return 0;
+}
#endif
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h
index aa9875f77c40..88272591a895 100644
--- a/include/linux/platform_data/asoc-s3c.h
+++ b/include/linux/platform_data/asoc-s3c.h
@@ -38,12 +38,6 @@ struct samsung_i2s {
#define QUIRK_NEED_RSTCLR (1 << 3)
/* Quirks of the I2S controller */
u32 quirks;
-
- /*
- * Array of clock names that can be used to generate I2S signals.
- * Also corresponds to clocks of I2SMOD[10]
- */
- const char **src_clk;
dma_addr_t idma_addr;
};
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/include/linux/platform_data/clocksource-nomadik-mtu.h
index 582641f3dc01..80088973b734 100644
--- a/arch/arm/plat-nomadik/include/plat/mtu.h
+++ b/include/linux/platform_data/clocksource-nomadik-mtu.h
@@ -1,7 +1,7 @@
#ifndef __PLAT_MTU_H
#define __PLAT_MTU_H
-void nmdk_timer_init(void __iomem *base);
+void nmdk_timer_init(void __iomem *base, int irq);
void nmdk_clkevt_reset(void);
void nmdk_clksrc_reset(void);
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index c4e23d029498..24368a2e8b87 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -18,9 +18,7 @@
#include <linux/if_ether.h>
struct cpsw_slave_data {
- u32 slave_reg_ofs;
- u32 sliver_reg_ofs;
- const char *phy_id;
+ char phy_id[MII_BUS_ID_SIZE];
int phy_if;
u8 mac_addr[ETH_ALEN];
};
@@ -28,27 +26,14 @@ struct cpsw_slave_data {
struct cpsw_platform_data {
u32 ss_reg_ofs; /* Subsystem control register offset */
u32 channels; /* number of cpdma channels (symmetric) */
- u32 cpdma_reg_ofs; /* cpdma register offset */
- u32 cpdma_sram_ofs; /* cpdma sram offset */
-
u32 slaves; /* number of slave cpgmac ports */
struct cpsw_slave_data *slave_data;
-
- u32 ale_reg_ofs; /* address lookup engine reg offset */
+ u32 cpts_active_slave; /* time stamping slave */
+ u32 cpts_clock_mult; /* convert input clock ticks to nanoseconds */
+ u32 cpts_clock_shift; /* convert input clock ticks to nanoseconds */
u32 ale_entries; /* ale table size */
-
- u32 host_port_reg_ofs; /* cpsw cpdma host port registers */
- u32 host_port_num; /* The port number for the host port */
-
- u32 hw_stats_reg_ofs; /* cpsw hardware statistics counters */
-
- u32 bd_ram_ofs; /* embedded buffer descriptor RAM offset*/
u32 bd_ram_size; /*buffer descriptor ram size */
- u32 hw_ram_addr; /*if the HW address for BD RAM is different */
- bool no_bd_ram; /* no embedded BD ram*/
-
u32 rx_descs; /* Number of Rx Descriptios */
-
u32 mac_control; /* Mac control register */
};
diff --git a/include/linux/platform_data/crypto-ux500.h b/include/linux/platform_data/crypto-ux500.h
index 5b2d0817e26a..94df96d9a336 100644
--- a/include/linux/platform_data/crypto-ux500.h
+++ b/include/linux/platform_data/crypto-ux500.h
@@ -7,7 +7,7 @@
#ifndef _CRYPTO_UX500_H
#define _CRYPTO_UX500_H
#include <linux/dmaengine.h>
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
struct hash_platform_data {
void *mem_to_engine;
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index d0c5825876f8..8db5ae03b6e3 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -16,12 +16,13 @@
#ifndef __DAVINCI_ASP_H
#define __DAVINCI_ASP_H
+#include <linux/genalloc.h>
+
struct snd_platform_data {
u32 tx_dma_offset;
u32 rx_dma_offset;
int asp_chan_q; /* event queue number for ASP channel */
int ram_chan_q; /* event queue number for RAM channel */
- unsigned int codec_fmt;
/*
* Allowing this is more efficient and eliminates left and right swaps
* caused by underruns, but will swap the left and right channels
@@ -30,6 +31,7 @@ struct snd_platform_data {
unsigned enable_channel_combine:1;
unsigned sram_size_playback;
unsigned sram_size_capture;
+ struct gen_pool *sram_pool;
/*
* If McBSP peripheral gets the clock from an external pin,
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index 9ff93b065686..9ff93b065686 100644
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h
index b081c7245ec8..044a124bfbbc 100644
--- a/include/linux/platform_data/macb.h
+++ b/include/linux/platform_data/macb.h
@@ -12,6 +12,7 @@ struct macb_platform_data {
u32 phy_mask;
int phy_irq_pin; /* PHY IRQ */
u8 is_rmii; /* using RMII interface? */
+ u8 rev_eth_addr; /* reverse Ethernet address byte order */
};
#endif /* __MACB_PDATA_H__ */
diff --git a/include/linux/platform_data/omap-twl4030.h b/include/linux/platform_data/omap-twl4030.h
index c7bef788daab..ee60ef79d792 100644
--- a/include/linux/platform_data/omap-twl4030.h
+++ b/include/linux/platform_data/omap-twl4030.h
@@ -25,8 +25,34 @@
#ifndef _OMAP_TWL4030_H_
#define _OMAP_TWL4030_H_
+/* To select if only one channel is connected in a stereo port */
+#define OMAP_TWL4030_LEFT (1 << 0)
+#define OMAP_TWL4030_RIGHT (1 << 1)
+
struct omap_tw4030_pdata {
const char *card_name;
+ /* Voice port is connected to McBSP3 */
+ bool voice_connected;
+
+ /* The driver will parse the connection flags if this flag is set */
+ bool custom_routing;
+ /* Flags to indicate connected audio ports. */
+ u8 has_hs;
+ u8 has_hf;
+ u8 has_predriv;
+ u8 has_carkit;
+ bool has_ear;
+
+ bool has_mainmic;
+ bool has_submic;
+ bool has_hsmic;
+ bool has_carkitmic;
+ bool has_digimic0;
+ bool has_digimic1;
+ u8 has_linein;
+
+ /* Jack detect GPIO or <= 0 if it is not implemented */
+ int jack_detect;
};
#endif /* _OMAP_TWL4030_H_ */
diff --git a/include/linux/platform_data/pn544.h b/include/linux/platform_data/pn544.h
new file mode 100644
index 000000000000..713bfd703342
--- /dev/null
+++ b/include/linux/platform_data/pn544.h
@@ -0,0 +1,44 @@
+/*
+ * Driver include for the PN544 NFC chip.
+ *
+ * Copyright (C) Nokia Corporation
+ *
+ * Author: Jari Vanhala <ext-jari.vanhala@nokia.com>
+ * Contact: Matti Aaltoenn <matti.j.aaltonen@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _PN544_H_
+#define _PN544_H_
+
+#include <linux/i2c.h>
+
+enum {
+ NFC_GPIO_ENABLE,
+ NFC_GPIO_FW_RESET,
+ NFC_GPIO_IRQ
+};
+
+/* board config */
+struct pn544_nfc_platform_data {
+ int (*request_resources) (struct i2c_client *client);
+ void (*free_resources) (void);
+ void (*enable) (int fw);
+ int (*test) (void);
+ void (*disable) (void);
+ int (*get_gpio)(int type);
+};
+
+#endif /* _PN544_H_ */
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
index 4a496ebc7d73..c0f44c2b006d 100644
--- a/include/linux/power/smartreflex.h
+++ b/include/linux/power/smartreflex.h
@@ -260,8 +260,13 @@ struct omap_sr_nvalue_table {
*
* @name: instance name
* @ip_type: Smartreflex IP type.
- * @senp_mod: SENPENABLE value for the sr
- * @senn_mod: SENNENABLE value for sr
+ * @senp_mod: SENPENABLE value of the sr CONFIG register
+ * @senn_mod: SENNENABLE value for sr CONFIG register
+ * @err_weight ERRWEIGHT value of the sr ERRCONFIG register
+ * @err_maxlimit ERRMAXLIMIT value of the sr ERRCONFIG register
+ * @accum_data ACCUMDATA value of the sr CONFIG register
+ * @senn_avgweight SENNAVGWEIGHT value of the sr AVGWEIGHT register
+ * @senp_avgweight SENPAVGWEIGHT value of the sr AVGWEIGHT register
* @nvalue_count: Number of distinct nvalues in the nvalue table
* @enable_on_init: whether this sr module needs to enabled at
* boot up or not.
@@ -274,6 +279,11 @@ struct omap_sr_data {
int ip_type;
u32 senp_mod;
u32 senn_mod;
+ u32 err_weight;
+ u32 err_maxlimit;
+ u32 accum_data;
+ u32 senn_avgweight;
+ u32 senp_avgweight;
int nvalue_count;
bool enable_on_init;
struct omap_sr_nvalue_table *nvalue_table;
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index c43cd3556b1f..7bc732ce6e50 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -160,6 +160,7 @@ int regulator_bulk_force_disable(int num_consumers,
void regulator_bulk_free(int num_consumers,
struct regulator_bulk_data *consumers);
+int regulator_can_change_voltage(struct regulator *regulator);
int regulator_count_voltages(struct regulator *regulator);
int regulator_list_voltage(struct regulator *regulator, unsigned selector);
int regulator_is_supported_voltage(struct regulator *regulator,
@@ -358,6 +359,10 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
{
}
+static inline int regulator_count_voltages(struct regulator *regulator)
+{
+ return 0;
+}
#endif
static inline int regulator_set_voltage_tol(struct regulator *regulator,
@@ -367,4 +372,12 @@ static inline int regulator_set_voltage_tol(struct regulator *regulator,
new_uV - tol_uV, new_uV + tol_uV);
}
+static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
+ int target_uV, int tol_uV)
+{
+ return regulator_is_supported_voltage(regulator,
+ target_uV - tol_uV,
+ target_uV + tol_uV);
+}
+
#endif
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 7932a3bf21bd..d10bb0f39c5e 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -181,10 +181,13 @@ enum regulator_type {
* @type: Indicates if the regulator is a voltage or current regulator.
* @owner: Module providing the regulator, used for refcounting.
*
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ * voltage within constrains range.
* @n_voltages: Number of selectors available for ops.list_voltage().
*
* @min_uV: Voltage given by the lowest selector (if linear mapping)
* @uV_step: Voltage increase with each selector (if linear mapping)
+ * @linear_min_sel: Minimal selector for starting linear mapping
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
* @volt_table: Voltage mapping table (if table based mapping)
*
@@ -199,6 +202,7 @@ struct regulator_desc {
const char *name;
const char *supply_name;
int id;
+ bool continuous_voltage_range;
unsigned n_voltages;
struct regulator_ops *ops;
int irq;
@@ -207,6 +211,7 @@ struct regulator_desc {
unsigned int min_uV;
unsigned int uV_step;
+ unsigned int linear_min_sel;
unsigned int ramp_delay;
const unsigned int *volt_table;
diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h
new file mode 100644
index 000000000000..f8acc052e353
--- /dev/null
+++ b/include/linux/regulator/max8973-regulator.h
@@ -0,0 +1,72 @@
+/*
+ * max8973-regulator.h -- MAXIM 8973 regulator
+ *
+ * Interface for regulator driver for MAXIM 8973 DC-DC step-down
+ * switching regulator.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8973_H
+#define __LINUX_REGULATOR_MAX8973_H
+
+/*
+ * Control flags for configuration of the device.
+ * Client need to pass this information with ORed
+ */
+#define MAX8973_CONTROL_REMOTE_SENSE_ENABLE 0x00000001
+#define MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE 0x00000002
+#define MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE 0x00000004
+#define MAX8973_CONTROL_BIAS_ENABLE 0x00000008
+#define MAX8973_CONTROL_PULL_DOWN_ENABLE 0x00000010
+#define MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE 0x00000020
+
+#define MAX8973_CONTROL_CLKADV_TRIP_DISABLED 0x00000000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US 0x00010000
+#define MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US 0x00020000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS 0x00030000
+
+#define MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL 0x00000000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER 0x00100000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER 0x00200000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER 0x00300000
+
+/*
+ * struct max8973_regulator_platform_data - max8973 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @control_flags: Control flags which are ORed value of above flags to
+ * configure device.
+ * @enable_ext_control: Enable the voltage enable/disable through external
+ * control signal from EN input pin. If it is false then
+ * voltage output will be enabled/disabled through EN bit of
+ * device register.
+ * @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
+ * @dvs_def_state: Default state of dvs. 1 if it is high else 0.
+ */
+struct max8973_regulator_platform_data {
+ struct regulator_init_data *reg_init_data;
+ unsigned long control_flags;
+ bool enable_ext_control;
+ int dvs_gpio;
+ unsigned dvs_def_state:1;
+};
+
+#endif /* __LINUX_REGULATOR_MAX8973_H */
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644
index 000000000000..d00841e1a75a
--- /dev/null
+++ b/include/linux/regulator/tps51632-regulator.h
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+ struct regulator_init_data *reg_init_data;
+ bool enable_pwm_dvfs;
+ bool dvfs_step_20mV;
+ int max_voltage_uV;
+ int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644
index 0fa04b64db3e..000000000000
--- a/include/linux/regulator/tps65090-regulator.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, 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/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
- TPS65090_ID_DCDC1,
- TPS65090_ID_DCDC2,
- TPS65090_ID_DCDC3,
- TPS65090_ID_FET1,
- TPS65090_ID_FET2,
- TPS65090_ID_FET3,
- TPS65090_ID_FET4,
- TPS65090_ID_FET5,
- TPS65090_ID_FET6,
- TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
- struct regulator_init_data regulator;
-};
-
-#endif /* __REGULATOR_TPS65090_H */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 7002bbfd5d4a..489dd7bb28ec 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -69,4 +69,7 @@ extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
int idx);
+
+extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev, u16 mode);
#endif /* __LINUX_RTNETLINK_H */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6a2c34e6d962..320e976d5ab8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -235,11 +235,13 @@ enum {
/*
* The callback notifies userspace to release buffers when skb DMA is done in
* lower device, the skb last reference should be 0 when calling this.
+ * The zerocopy_success argument is true if zero copy transmit occurred,
+ * false on data copy or out of memory error caused by data copy attempt.
* The ctx field is used to track device context.
* The desc field is used to track userspace buffer index.
*/
struct ubuf_info {
- void (*callback)(struct ubuf_info *);
+ void (*callback)(struct ubuf_info *, bool zerocopy_success);
void *ctx;
unsigned long desc;
};
@@ -374,6 +376,8 @@ typedef unsigned char *sk_buff_data_t;
* @mark: Generic packet mark
* @dropcount: total number of sk_receive_queue overflows
* @vlan_tci: vlan tag control information
+ * @inner_transport_header: Inner transport layer header (encapsulation)
+ * @inner_network_header: Network layer header (encapsulation)
* @transport_header: Transport layer header
* @network_header: Network layer header
* @mac_header: Link layer header
@@ -469,7 +473,13 @@ struct sk_buff {
__u8 wifi_acked:1;
__u8 no_fcs:1;
__u8 head_frag:1;
- /* 8/10 bit hole (depending on ndisc_nodetype presence) */
+ /* Encapsulation protocol and NIC drivers should use
+ * this flag to indicate to each other if the skb contains
+ * encapsulated packet or not and maybe use the inner packet
+ * headers if needed
+ */
+ __u8 encapsulation:1;
+ /* 7/9 bit hole (depending on ndisc_nodetype presence) */
kmemcheck_bitfield_end(flags2);
#ifdef CONFIG_NET_DMA
@@ -484,6 +494,8 @@ struct sk_buff {
__u32 avail_size;
};
+ sk_buff_data_t inner_transport_header;
+ sk_buff_data_t inner_network_header;
sk_buff_data_t transport_header;
sk_buff_data_t network_header;
sk_buff_data_t mac_header;
@@ -566,6 +578,7 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
}
extern void kfree_skb(struct sk_buff *skb);
+extern void skb_tx_error(struct sk_buff *skb);
extern void consume_skb(struct sk_buff *skb);
extern void __kfree_skb(struct sk_buff *skb);
extern struct kmem_cache *skbuff_head_cache;
@@ -643,7 +656,7 @@ extern unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
extern void __skb_get_rxhash(struct sk_buff *skb);
static inline __u32 skb_get_rxhash(struct sk_buff *skb)
{
- if (!skb->rxhash)
+ if (!skb->l4_rxhash)
__skb_get_rxhash(skb);
return skb->rxhash;
@@ -1432,12 +1445,53 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
skb->tail += len;
}
+static inline void skb_reset_inner_headers(struct sk_buff *skb)
+{
+ skb->inner_network_header = skb->network_header;
+ skb->inner_transport_header = skb->transport_header;
+}
+
static inline void skb_reset_mac_len(struct sk_buff *skb)
{
skb->mac_len = skb->network_header - skb->mac_header;
}
#ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_inner_transport_header(const struct sk_buff
+ *skb)
+{
+ return skb->head + skb->inner_transport_header;
+}
+
+static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
+{
+ skb->inner_transport_header = skb->data - skb->head;
+}
+
+static inline void skb_set_inner_transport_header(struct sk_buff *skb,
+ const int offset)
+{
+ skb_reset_inner_transport_header(skb);
+ skb->inner_transport_header += offset;
+}
+
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+ return skb->head + skb->inner_network_header;
+}
+
+static inline void skb_reset_inner_network_header(struct sk_buff *skb)
+{
+ skb->inner_network_header = skb->data - skb->head;
+}
+
+static inline void skb_set_inner_network_header(struct sk_buff *skb,
+ const int offset)
+{
+ skb_reset_inner_network_header(skb);
+ skb->inner_network_header += offset;
+}
+
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
return skb->head + skb->transport_header;
@@ -1493,6 +1547,38 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
}
#else /* NET_SKBUFF_DATA_USES_OFFSET */
+static inline unsigned char *skb_inner_transport_header(const struct sk_buff
+ *skb)
+{
+ return skb->inner_transport_header;
+}
+
+static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
+{
+ skb->inner_transport_header = skb->data;
+}
+
+static inline void skb_set_inner_transport_header(struct sk_buff *skb,
+ const int offset)
+{
+ skb->inner_transport_header = skb->data + offset;
+}
+
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+ return skb->inner_network_header;
+}
+
+static inline void skb_reset_inner_network_header(struct sk_buff *skb)
+{
+ skb->inner_network_header = skb->data;
+}
+
+static inline void skb_set_inner_network_header(struct sk_buff *skb,
+ const int offset)
+{
+ skb->inner_network_header = skb->data + offset;
+}
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
@@ -1571,11 +1657,21 @@ static inline u32 skb_network_header_len(const struct sk_buff *skb)
return skb->transport_header - skb->network_header;
}
+static inline u32 skb_inner_network_header_len(const struct sk_buff *skb)
+{
+ return skb->inner_transport_header - skb->inner_network_header;
+}
+
static inline int skb_network_offset(const struct sk_buff *skb)
{
return skb_network_header(skb) - skb->data;
}
+static inline int skb_inner_network_offset(const struct sk_buff *skb)
+{
+ return skb_inner_network_header(skb) - skb->data;
+}
+
static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
{
return pskb_may_pull(skb, skb_network_offset(skb) + len);
diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h
index ce718cbce435..f4bf16e16e16 100644
--- a/include/linux/smscphy.h
+++ b/include/linux/smscphy.h
@@ -4,6 +4,7 @@
#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
#define MII_LAN83C185_IM 30 /* Interrupt Mask */
#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+#define MII_LAN83C185_SPECIAL_MODES 18 /* Special Modes Register */
#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
@@ -22,4 +23,8 @@
#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
#define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
+#define MII_LAN83C185_MODE_MASK 0xE0
+#define MII_LAN83C185_MODE_POWERDOWN 0xC0 /* Power Down mode */
+#define MII_LAN83C185_MODE_ALL 0xE0 /* All capable mode */
+
#endif /* __LINUX_SMSCPHY_H__ */
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index bb674c02f306..1f64e3f1f22b 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -8,6 +8,7 @@
#include <linux/pci.h>
#include <linux/mod_devicetable.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
#include <linux/ssb/ssb_regs.h>
@@ -432,6 +433,7 @@ struct ssb_bus {
#ifdef CONFIG_SSB_EMBEDDED
/* Lock for GPIO register access. */
spinlock_t gpio_lock;
+ struct platform_device *watchdog;
#endif /* EMBEDDED */
/* Internal-only stuff follows. Do not touch. */
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index c2b02a5c86ae..38339fd68a5f 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -591,6 +591,8 @@ struct ssb_chipcommon {
/* Fast Powerup Delay constant */
u16 fast_pwrup_delay;
struct ssb_chipcommon_pmu pmu;
+ u32 ticks_per_ms;
+ u32 max_timer_ms;
};
static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
@@ -630,8 +632,7 @@ enum ssb_clkmode {
extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
enum ssb_clkmode mode);
-extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
- u32 ticks);
+extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks);
void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h
index 91161f0aa22b..99511d0e931d 100644
--- a/include/linux/ssb/ssb_driver_extif.h
+++ b/include/linux/ssb/ssb_driver_extif.h
@@ -152,6 +152,9 @@
/* watchdog */
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
+#define SSB_EXTIF_WATCHDOG_MAX_TIMER ((1 << 28) - 1)
+#define SSB_EXTIF_WATCHDOG_MAX_TIMER_MS (SSB_EXTIF_WATCHDOG_MAX_TIMER \
+ / (SSB_EXTIF_WATCHDOG_CLK / 1000))
#ifdef CONFIG_SSB_DRIVER_EXTIF
@@ -171,8 +174,7 @@ extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
extern void ssb_extif_timing_init(struct ssb_extif *extif,
unsigned long ns);
-extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
- u32 ticks);
+extern u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks);
/* Extif GPIO pin access */
u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
@@ -205,10 +207,52 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
}
static inline
-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
- u32 ticks)
+void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns)
{
}
+static inline
+u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
+{
+ return 0;
+}
+
+static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
+{
+ return 0;
+}
+
+static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask,
+ u32 value)
+{
+ return 0;
+}
+
+static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask,
+ u32 value)
+{
+ return 0;
+}
+
+static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask,
+ u32 value)
+{
+ return 0;
+}
+
+static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask,
+ u32 value)
+{
+ return 0;
+}
+
+#ifdef CONFIG_SSB_SERIAL
+static inline int ssb_extif_serial_init(struct ssb_extif *extif,
+ struct ssb_serial_port *ports)
+{
+ return 0;
+}
+#endif /* CONFIG_SSB_SERIAL */
+
#endif /* CONFIG_SSB_DRIVER_EXTIF */
#endif /* LINUX_SSB_EXTIFCORE_H_ */
diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h
index 5f44e9740cd2..07a9c7a2e088 100644
--- a/include/linux/ssb/ssb_driver_mips.h
+++ b/include/linux/ssb/ssb_driver_mips.h
@@ -13,6 +13,12 @@ struct ssb_serial_port {
unsigned int reg_shift;
};
+struct ssb_pflash {
+ bool present;
+ u8 buswidth;
+ u32 window;
+ u32 window_size;
+};
struct ssb_mipscore {
struct ssb_device *dev;
@@ -20,9 +26,7 @@ struct ssb_mipscore {
int nr_serial_ports;
struct ssb_serial_port serial_ports[4];
- u8 flash_buswidth;
- u32 flash_window;
- u32 flash_window_size;
+ struct ssb_pflash pflash;
};
extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index a0525019e1d1..6ecfa02ddbac 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -485,7 +485,7 @@
#define SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT 4
#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL 0x0020
#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT 5
-#define SSB_SPROM8_TEMPDELTA 0x00BA
+#define SSB_SPROM8_TEMPDELTA 0x00BC
#define SSB_SPROM8_TEMPDELTA_PHYCAL 0x00ff
#define SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT 0
#define SSB_SPROM8_TEMPDELTA_PERIOD 0x0f00
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index a1547ea3920d..c1b3ed3fb787 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -61,7 +61,7 @@
#define STMMAC_CSR_I_16 0xE /* clk_csr_i/16 */
#define STMMAC_CSR_I_18 0xF /* clk_csr_i/18 */
-/* AXI DMA Burst length suported */
+/* AXI DMA Burst length supported */
#define DMA_AXI_BLEN_4 (1 << 1)
#define DMA_AXI_BLEN_8 (1 << 2)
#define DMA_AXI_BLEN_16 (1 << 3)
@@ -104,6 +104,7 @@ struct plat_stmmacenet_data {
int bugged_jumbo;
int pmt;
int force_sf_dma_mode;
+ int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index cd844a6a8d5f..14a8ff2de11e 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -158,8 +158,7 @@ struct ctl_table_root {
struct ctl_table_set default_set;
struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
struct nsproxy *namespaces);
- int (*permissions)(struct ctl_table_root *root,
- struct nsproxy *namespaces, struct ctl_table *table);
+ int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
};
/* struct ctl_path describes where in the hierarchy a table is added */
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 60b7aac15e0e..4e1d2283e3cc 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -35,6 +35,16 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
return tcp_hdr(skb)->doff * 4;
}
+static inline struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb)
+{
+ return (struct tcphdr *)skb_inner_transport_header(skb);
+}
+
+static inline unsigned int inner_tcp_hdrlen(const struct sk_buff *skb)
+{
+ return inner_tcp_hdr(skb)->doff * 4;
+}
+
static inline unsigned int tcp_optlen(const struct sk_buff *skb)
{
return (tcp_hdr(skb)->doff - 5) * 4;
diff --git a/include/linux/timecompare.h b/include/linux/timecompare.h
deleted file mode 100644
index 546e2234e4b3..000000000000
--- a/include/linux/timecompare.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Utility code which helps transforming between two different time
- * bases, called "source" and "target" time in this code.
- *
- * Source time has to be provided via the timecounter API while target
- * time is accessed via a function callback whose prototype
- * intentionally matches ktime_get() and ktime_get_real(). These
- * interfaces where chosen like this so that the code serves its
- * initial purpose without additional glue code.
- *
- * This purpose is synchronizing a hardware clock in a NIC with system
- * time, in order to implement the Precision Time Protocol (PTP,
- * IEEE1588) with more accurate hardware assisted time stamping. In
- * that context only synchronization against system time (=
- * ktime_get_real()) is currently needed. But this utility code might
- * become useful in other situations, which is why it was written as
- * general purpose utility code.
- *
- * The source timecounter is assumed to return monotonically
- * increasing time (but this code does its best to compensate if that
- * is not the case) whereas target time may jump.
- *
- * The target time corresponding to a source time is determined by
- * reading target time, reading source time, reading target time
- * again, then assuming that average target time corresponds to source
- * time. In other words, the assumption is that reading the source
- * time is slow and involves equal time for sending the request and
- * receiving the reply, whereas reading target time is assumed to be
- * fast.
- *
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef _LINUX_TIMECOMPARE_H
-#define _LINUX_TIMECOMPARE_H
-
-#include <linux/clocksource.h>
-#include <linux/ktime.h>
-
-/**
- * struct timecompare - stores state and configuration for the two clocks
- *
- * Initialize to zero, then set source/target/num_samples.
- *
- * Transformation between source time and target time is done with:
- * target_time = source_time + offset +
- * (source_time - last_update) * skew /
- * TIMECOMPARE_SKEW_RESOLUTION
- *
- * @source: used to get source time stamps via timecounter_read()
- * @target: function returning target time (for example, ktime_get
- * for monotonic time, or ktime_get_real for wall clock)
- * @num_samples: number of times that source time and target time are to
- * be compared when determining their offset
- * @offset: (target time - source time) at the time of the last update
- * @skew: average (target time - source time) / delta source time *
- * TIMECOMPARE_SKEW_RESOLUTION
- * @last_update: last source time stamp when time offset was measured
- */
-struct timecompare {
- struct timecounter *source;
- ktime_t (*target)(void);
- int num_samples;
-
- s64 offset;
- s64 skew;
- u64 last_update;
-};
-
-/**
- * timecompare_transform - transform source time stamp into target time base
- * @sync: context for time sync
- * @source_tstamp: the result of timecounter_read() or
- * timecounter_cyc2time()
- */
-extern ktime_t timecompare_transform(struct timecompare *sync,
- u64 source_tstamp);
-
-/**
- * timecompare_offset - measure current (target time - source time) offset
- * @sync: context for time sync
- * @offset: average offset during sample period returned here
- * @source_tstamp: average source time during sample period returned here
- *
- * Returns number of samples used. Might be zero (= no result) in the
- * unlikely case that target time was monotonically decreasing for all
- * samples (= broken).
- */
-extern int timecompare_offset(struct timecompare *sync,
- s64 *offset,
- u64 *source_tstamp);
-
-extern void __timecompare_update(struct timecompare *sync,
- u64 source_tstamp);
-
-/**
- * timecompare_update - update offset and skew by measuring current offset
- * @sync: context for time sync
- * @source_tstamp: the result of timecounter_read() or
- * timecounter_cyc2time(), pass zero to force update
- *
- * Updates are only done at most once per second.
- */
-static inline void timecompare_update(struct timecompare *sync,
- u64 source_tstamp)
-{
- if (!source_tstamp ||
- (s64)(source_tstamp - sync->last_update) >= NSEC_PER_SEC)
- __timecompare_update(sync, source_tstamp);
-}
-
-#endif /* _LINUX_TIMECOMPARE_H */
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 0b67d7793520..9d81de123c90 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -27,6 +27,11 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
return (struct udphdr *)skb_transport_header(skb);
}
+static inline struct udphdr *inner_udp_hdr(const struct sk_buff *skb)
+{
+ return (struct udphdr *)skb_inner_transport_header(skb);
+}
+
#define UDP_HTABLE_SIZE_MIN (CONFIG_BASE_SMALL ? 128 : 256)
static inline int udp_hashfn(struct net *net, unsigned num, unsigned mask)
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
new file mode 100644
index 000000000000..3b8f9d4fc3fe
--- /dev/null
+++ b/include/linux/usb/cdc_ncm.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) ST-Ericsson 2010-2012
+ * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
+ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
+ *
+ * USB Host Driver for Network Control Model (NCM)
+ * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ *
+ * The NCM encoding, decoding and initialization logic
+ * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose this file to be licensed under the terms
+ * of the GNU General Public License (GPL) Version 2 or the 2-clause
+ * BSD license listed below:
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 CDC_NCM_COMM_ALTSETTING_NCM 0
+#define CDC_NCM_COMM_ALTSETTING_MBIM 1
+
+#define CDC_NCM_DATA_ALTSETTING_NCM 1
+#define CDC_NCM_DATA_ALTSETTING_MBIM 2
+
+/* CDC NCM subclass 3.2.1 */
+#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10
+
+/* Maximum NTB length */
+#define CDC_NCM_NTB_MAX_SIZE_TX 32768 /* bytes */
+#define CDC_NCM_NTB_MAX_SIZE_RX 32768 /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
+#define CDC_NCM_MIN_DATAGRAM_SIZE 1514 /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 8.1.3 */
+#define CDC_MBIM_MIN_DATAGRAM_SIZE 2048 /* bytes */
+
+#define CDC_NCM_MIN_TX_PKT 512 /* bytes */
+
+/* Default value for MaxDatagramSize */
+#define CDC_NCM_MAX_DATAGRAM_SIZE 8192 /* bytes */
+
+/*
+ * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
+ * the last NULL entry.
+ */
+#define CDC_NCM_DPT_DATAGRAMS_MAX 40
+
+/* Restart the timer, if amount of datagrams is less than given value */
+#define CDC_NCM_RESTART_TIMER_DATAGRAM_CNT 3
+#define CDC_NCM_TIMER_PENDING_CNT 2
+#define CDC_NCM_TIMER_INTERVAL (400UL * NSEC_PER_USEC)
+
+/* The following macro defines the minimum header space */
+#define CDC_NCM_MIN_HDR_SIZE \
+ (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
+ (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define CDC_NCM_NDP_SIZE \
+ (sizeof(struct usb_cdc_ncm_ndp16) + \
+ (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
+ (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
+#define cdc_ncm_data_intf_is_mbim(x) ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
+
+struct cdc_ncm_ctx {
+ struct usb_cdc_ncm_ntb_parameters ncm_parm;
+ struct hrtimer tx_timer;
+ struct tasklet_struct bh;
+
+ const struct usb_cdc_ncm_desc *func_desc;
+ const struct usb_cdc_mbim_desc *mbim_desc;
+ const struct usb_cdc_header_desc *header_desc;
+ const struct usb_cdc_union_desc *union_desc;
+ const struct usb_cdc_ether_desc *ether_desc;
+
+ struct net_device *netdev;
+ struct usb_device *udev;
+ struct usb_host_endpoint *in_ep;
+ struct usb_host_endpoint *out_ep;
+ struct usb_host_endpoint *status_ep;
+ struct usb_interface *intf;
+ struct usb_interface *control;
+ struct usb_interface *data;
+
+ struct sk_buff *tx_curr_skb;
+ struct sk_buff *tx_rem_skb;
+ __le32 tx_rem_sign;
+
+ spinlock_t mtx;
+ atomic_t stop;
+
+ u32 tx_timer_pending;
+ u32 tx_curr_frame_num;
+ u32 rx_speed;
+ u32 tx_speed;
+ u32 rx_max;
+ u32 tx_max;
+ u32 max_datagram_size;
+ u16 tx_max_datagrams;
+ u16 tx_remainder;
+ u16 tx_modulus;
+ u16 tx_ndp_modulus;
+ u16 tx_seq;
+ u16 rx_seq;
+ u16 connected;
+};
+
+extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
+extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
+extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
+extern int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
+extern int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index ddbbb7de894b..9bbeabf66c54 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -163,6 +163,16 @@ extern int usbnet_resume(struct usb_interface *);
extern void usbnet_disconnect(struct usb_interface *);
extern void usbnet_device_suggests_idle(struct usbnet *dev);
+extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+ u16 value, u16 index, const void *data, u16 size);
/* Drivers that reuse some of the standard USB CDC infrastructure
* (notably, using multiple interfaces according to the CDC
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 0ee42d9acdc0..2c02f3a8d2ba 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -78,7 +78,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
* This function acquires VGA resources for the given
* card and mark those resources locked. If the resource requested
* are "normal" (and not legacy) resources, the arbiter will first check
- * wether the card is doing legacy decoding for that type of resource. If
+ * whether the card is doing legacy decoding for that type of resource. If
* yes, the lock is "converted" into a legacy resource lock.
* The arbiter will first look for all VGA cards that might conflict
* and disable their IOs and/or Memory access, including VGA forwarding
@@ -89,7 +89,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
* This function will block if some conflicting card is already locking
* one of the required resources (or any resource on a different bus
* segment, since P2P bridges don't differenciate VGA memory and IO
- * afaik). You can indicate wether this blocking should be interruptible
+ * afaik). You can indicate whether this blocking should be interruptible
* by a signal (for userland interface) or not.
* Must not be called at interrupt time or in atomic context.
* If the card already owns the resources, the function succeeds.
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index b7f45d48b2de..87490ac4bd87 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -105,7 +105,7 @@ struct watchdog_device {
#define WATCHDOG_NOWAYOUT_INIT_STATUS 0
#endif
-/* Use the following function to check wether or not the watchdog is active */
+/* Use the following function to check whether or not the watchdog is active */
static inline bool watchdog_active(struct watchdog_device *wdd)
{
return test_bit(WDOG_ACTIVE, &wdd->status);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 9e63e76b20e7..df4ef9453384 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -172,6 +172,9 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
extern int register_inet6addr_notifier(struct notifier_block *nb);
extern int unregister_inet6addr_notifier(struct notifier_block *nb);
+extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+ struct ipv6_devconf *devconf);
+
/**
* __in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index b5f8988e4283..0a996a3517ed 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -53,7 +53,6 @@ struct unix_sock {
struct path path;
struct mutex readlock;
struct sock *peer;
- struct sock *other;
struct list_head link;
atomic_long_t inflight;
spinlock_t lock;
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6a76e0a0705e..42f21766c538 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -19,13 +19,25 @@
#define A2MP_FEAT_EXT 0x8000
+enum amp_mgr_state {
+ READ_LOC_AMP_INFO,
+ READ_LOC_AMP_ASSOC,
+ READ_LOC_AMP_ASSOC_FINAL,
+};
+
struct amp_mgr {
+ struct list_head list;
struct l2cap_conn *l2cap_conn;
struct l2cap_chan *a2mp_chan;
+ struct l2cap_chan *bredr_chan;
struct kref kref;
__u8 ident;
__u8 handle;
+ enum amp_mgr_state state;
unsigned long flags;
+
+ struct list_head amp_ctrls;
+ struct mutex amp_ctrls_lock;
};
struct a2mp_cmd {
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
-void amp_mgr_get(struct amp_mgr *mgr);
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 000000000000..7ea3db77ba89
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2011,2012 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 __AMP_H
+#define __AMP_H
+
+struct amp_ctrl {
+ struct list_head list;
+ struct kref kref;
+ __u8 id;
+ __u16 assoc_len_so_far;
+ __u16 assoc_rem_len;
+ __u16 assoc_len;
+ __u8 *assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+void amp_ctrl_get(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+ u8 remote_id, bool out);
+
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+ struct hci_conn *hcon);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
+void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon);
+void amp_create_logical_link(struct l2cap_chan *chan);
+void amp_disconnect_logical_link(struct hci_chan *hchan);
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ede036977ae8..2554b3f5222a 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
}
void baswap(bdaddr_t *dst, bdaddr_t *src);
-char *batostr(bdaddr_t *ba);
/* Common socket structures and functions */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 76b2b6bdcf36..45eee08157bb 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -33,6 +33,8 @@
#define HCI_LINK_KEY_SIZE 16
#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+#define HCI_MAX_AMP_ASSOC_SIZE 672
+
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
@@ -113,6 +115,7 @@ enum {
HCI_SSP_ENABLED,
HCI_HS_ENABLED,
HCI_LE_ENABLED,
+ HCI_LE_PERIPHERAL,
HCI_CONNECTABLE,
HCI_DISCOVERABLE,
HCI_LINK_SECURITY,
@@ -151,7 +154,7 @@ enum {
#define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */
#define HCI_INIT_TIMEOUT msecs_to_jiffies(10000) /* 10 seconds */
-#define HCI_CMD_TIMEOUT msecs_to_jiffies(1000) /* 1 second */
+#define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
@@ -196,6 +199,7 @@ enum {
#define ACL_START_NO_FLUSH 0x00
#define ACL_CONT 0x01
#define ACL_START 0x02
+#define ACL_COMPLETE 0x03
#define ACL_ACTIVE_BCAST 0x04
#define ACL_PICO_BCAST 0x08
@@ -205,6 +209,7 @@ enum {
#define ESCO_LINK 0x02
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
+#define AMP_LINK 0x81
/* LMP features */
#define LMP_3SLOT 0x01
@@ -314,6 +319,9 @@ enum {
#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00
#define HCI_FLOW_CTL_MODE_BLOCK_BASED 0x01
+/* The core spec defines 127 as the "not available" value */
+#define HCI_TX_POWER_INVALID 127
+
/* Extended Inquiry Response field types */
#define EIR_FLAGS 0x01 /* flags */
#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
@@ -330,6 +338,13 @@ enum {
#define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */
#define EIR_DEVICE_ID 0x10 /* device ID */
+/* Low Energy Advertising Flags */
+#define LE_AD_LIMITED 0x01 /* Limited Discoverable */
+#define LE_AD_GENERAL 0x02 /* General Discoverable */
+#define LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */
+#define LE_AD_SIM_LE_BREDR_CTRL 0x08 /* Simultaneous LE & BR/EDR Controller */
+#define LE_AD_SIM_LE_BREDR_HOST 0x10 /* Simultaneous LE & BR/EDR Host */
+
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
@@ -556,12 +571,46 @@ struct hci_cp_accept_phy_link {
__u8 key[HCI_AMP_LINK_KEY_SIZE];
} __packed;
-#define HCI_OP_DISCONN_PHY_LINK 0x0437
+#define HCI_OP_DISCONN_PHY_LINK 0x0437
struct hci_cp_disconn_phy_link {
__u8 phy_handle;
__u8 reason;
} __packed;
+struct ext_flow_spec {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+struct hci_cp_create_accept_logical_link {
+ __u8 phy_handle;
+ struct ext_flow_spec tx_flow_spec;
+ struct ext_flow_spec rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+struct hci_cp_disconn_logical_link {
+ __le16 log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+struct hci_cp_logical_link_cancel {
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
@@ -894,6 +943,22 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;
+#define HCI_OP_LE_READ_ADV_TX_POWER 0x2007
+struct hci_rp_le_read_adv_tx_power {
+ __u8 status;
+ __s8 tx_power;
+} __packed;
+
+#define HCI_MAX_AD_LENGTH 31
+
+#define HCI_OP_LE_SET_ADV_DATA 0x2008
+struct hci_cp_le_set_adv_data {
+ __u8 length;
+ __u8 data[HCI_MAX_AD_LENGTH];
+} __packed;
+
+#define HCI_OP_LE_SET_ADV_ENABLE 0x200a
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e7d454609881..014a2eaa5389 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -73,6 +73,7 @@ struct discovery_state {
struct hci_conn_hash {
struct list_head list;
unsigned int acl_num;
+ unsigned int amp_num;
unsigned int sco_num;
unsigned int le_num;
};
@@ -124,6 +125,14 @@ struct le_scan_params {
#define HCI_MAX_SHORT_NAME_LENGTH 10
+struct amp_assoc {
+ __u16 len;
+ __u16 offset;
+ __u16 rem_len;
+ __u16 len_so_far;
+ __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -177,6 +186,8 @@ struct hci_dev {
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
+ struct amp_assoc loc_assoc;
+
__u8 flow_ctl_mode;
unsigned int auto_accept_delay;
@@ -252,8 +263,6 @@ struct hci_dev {
struct sk_buff_head driver_init;
- void *core_data;
-
atomic_t promisc;
struct dentry *debugfs;
@@ -269,6 +278,10 @@ struct hci_dev {
struct work_struct le_scan;
struct le_scan_params le_scan_params;
+ __s8 adv_tx_power;
+ __u8 adv_data[HCI_MAX_AD_LENGTH];
+ __u8 adv_data_len;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
@@ -277,6 +290,8 @@ struct hci_dev {
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
};
+#define HCI_PHY_HANDLE(handle) (handle & 0xff)
+
struct hci_conn {
struct list_head list;
@@ -310,6 +325,7 @@ struct hci_conn {
__u8 remote_cap;
__u8 remote_auth;
+ __u8 remote_id;
bool flush_key;
unsigned int sent;
@@ -339,10 +355,11 @@ struct hci_conn {
struct hci_chan {
struct list_head list;
-
+ __u16 handle;
struct hci_conn *conn;
struct sk_buff_head data_q;
unsigned int sent;
+ __u8 state;
};
extern struct list_head hci_dev_list;
@@ -359,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
u16 flags);
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -438,6 +455,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num++;
break;
+ case AMP_LINK:
+ h->amp_num++;
+ break;
case LE_LINK:
h->le_num++;
break;
@@ -459,6 +479,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num--;
break;
+ case AMP_LINK:
+ h->amp_num--;
+ break;
case LE_LINK:
h->le_num--;
break;
@@ -475,6 +498,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
switch (type) {
case ACL_LINK:
return h->acl_num;
+ case AMP_LINK:
+ return h->amp_num;
case LE_LINK:
return h->le_num;
case SCO_LINK:
@@ -552,10 +577,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
+void hci_conn_accept(struct hci_conn *conn, int mask);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn);
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type);
@@ -584,7 +611,10 @@ static inline void hci_conn_put(struct hci_conn *conn)
if (atomic_dec_and_test(&conn->refcnt)) {
unsigned long timeo;
- if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
del_timer(&conn->idle_timer);
if (conn->state == BT_CONNECTED) {
timeo = conn->disc_timeout;
@@ -593,12 +623,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
} else {
timeo = msecs_to_jiffies(10);
}
- } else {
+ break;
+
+ case AMP_LINK:
+ timeo = conn->disc_timeout;
+ break;
+
+ default:
timeo = msecs_to_jiffies(10);
+ break;
}
+
cancel_delayed_work(&conn->disc_work);
queue_delayed_work(conn->hdev->workqueue,
- &conn->disc_work, timeo);
+ &conn->disc_work, timeo);
}
}
@@ -650,7 +688,7 @@ static inline uint8_t __hci_num_ctrl(void)
}
struct hci_dev *hci_dev_get(int index);
-struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src);
struct hci_dev *hci_alloc_dev(void);
void hci_free_dev(struct hci_dev *hdev);
@@ -699,6 +737,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_update_ad(struct hci_dev *hdev);
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct sk_buff *skb);
@@ -715,22 +755,51 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
/* ----- LMP capabilities ----- */
-#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev) ((dev)->features[0] & LMP_HOLD)
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_park_capable(dev) ((dev)->features[1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev) ((dev)->features[3] & LMP_RSSI_INQ)
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
+#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
-#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev) ((dev)->features[7] & LMP_EXTFEATURES)
/* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP)
+#define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
+
+/* returns true if at least one AMP active */
+static inline bool hci_amp_capable(void)
+{
+ struct hci_dev *hdev;
+ bool ret = false;
+
+ read_lock(&hci_dev_list_lock);
+ list_for_each_entry(hdev, &hci_dev_list, list)
+ if (hdev->amp_type == HCI_AMP &&
+ test_bit(HCI_UP, &hdev->flags))
+ ret = true;
+ read_unlock(&hci_dev_list_lock);
+
+ return ret;
+}
/* ----- HCI protocols ----- */
+#define HCI_PROTO_DEFER 0x01
+
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type)
+ __u8 type, __u8 *flags)
{
switch (type) {
case ACL_LINK:
@@ -738,7 +807,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
case SCO_LINK:
case ESCO_LINK:
- return sco_connect_ind(hdev, bdaddr);
+ return sco_connect_ind(hdev, bdaddr, flags);
default:
BT_ERR("unknown link type %d", type);
@@ -789,6 +858,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
sco_disconn_cfm(conn, reason);
break;
+ /* L2CAP would be handled for BREDR chan */
+ case AMP_LINK:
+ break;
+
default:
BT_ERR("unknown link type %d", conn->type);
break;
@@ -841,7 +914,7 @@ struct hci_cb {
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
- struct list_head *p;
+ struct hci_cb *cb;
__u8 encrypt;
hci_proto_auth_cfm(conn, status);
@@ -852,8 +925,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
@@ -863,7 +935,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt)
{
- struct list_head *p;
+ struct hci_cb *cb;
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;
@@ -874,8 +946,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
hci_proto_encrypt_cfm(conn, status, encrypt);
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
@@ -884,11 +955,10 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
- struct list_head *p;
+ struct hci_cb *cb;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
}
@@ -898,11 +968,10 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
__u8 role)
{
- struct list_head *p;
+ struct hci_cb *cb;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
}
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ed8e356425a..7588ef44ebaf 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -32,13 +32,14 @@
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
-#define L2CAP_DEFAULT_FLUSH_TO 0xffff
+#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
+#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
#define L2CAP_DEFAULT_TX_WINDOW 63
#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
+#define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
@@ -51,6 +52,8 @@
#define L2CAP_ENC_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
+#define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000)
+#define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000)
#define L2CAP_A2MP_DEFAULT_MTU 670
@@ -433,6 +436,8 @@ struct l2cap_chan {
struct sock *sk;
struct l2cap_conn *conn;
+ struct hci_conn *hs_hcon;
+ struct hci_chan *hs_hchan;
struct kref kref;
__u8 state;
@@ -476,6 +481,12 @@ struct l2cap_chan {
unsigned long conn_state;
unsigned long flags;
+ __u8 remote_amp_id;
+ __u8 local_amp_id;
+ __u8 move_id;
+ __u8 move_state;
+ __u8 move_role;
+
__u16 next_tx_seq;
__u16 expected_ack_seq;
__u16 expected_tx_seq;
@@ -538,6 +549,7 @@ struct l2cap_ops {
void (*state_change) (struct l2cap_chan *chan,
int state);
void (*ready) (struct l2cap_chan *chan);
+ void (*defer) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long len, int nb);
};
@@ -599,7 +611,7 @@ enum {
CONF_MTU_DONE,
CONF_MODE_DONE,
CONF_CONNECT_PEND,
- CONF_NO_FCS_RECV,
+ CONF_RECV_NO_FCS,
CONF_STATE2_DEVICE,
CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
@@ -640,6 +652,9 @@ enum {
enum {
L2CAP_RX_STATE_RECV,
L2CAP_RX_STATE_SREJ_SENT,
+ L2CAP_RX_STATE_MOVE,
+ L2CAP_RX_STATE_WAIT_P,
+ L2CAP_RX_STATE_WAIT_F,
};
enum {
@@ -670,6 +685,25 @@ enum {
L2CAP_EV_RECV_FRAME,
};
+enum {
+ L2CAP_MOVE_ROLE_NONE,
+ L2CAP_MOVE_ROLE_INITIATOR,
+ L2CAP_MOVE_ROLE_RESPONDER,
+};
+
+enum {
+ L2CAP_MOVE_STABLE,
+ L2CAP_MOVE_WAIT_REQ,
+ L2CAP_MOVE_WAIT_RSP,
+ L2CAP_MOVE_WAIT_RSP_SUCCESS,
+ L2CAP_MOVE_WAIT_CONFIRM,
+ L2CAP_MOVE_WAIT_CONFIRM_RSP,
+ L2CAP_MOVE_WAIT_LOGICAL_COMP,
+ L2CAP_MOVE_WAIT_LOGICAL_CFM,
+ L2CAP_MOVE_WAIT_LOCAL_BUSY,
+ L2CAP_MOVE_WAIT_PREPARE,
+};
+
void l2cap_chan_hold(struct l2cap_chan *c);
void l2cap_chan_put(struct l2cap_chan *c);
@@ -745,6 +779,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
{
}
+static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
+{
+}
+
extern bool disable_ertm;
int l2cap_init_sockets(void);
@@ -767,6 +805,12 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
+void l2cap_move_start(struct l2cap_chan *chan);
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+ u8 status);
+void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
#endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d5b6000378b..8e6a6b73b9c9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -58,6 +58,8 @@
* structures here describe these capabilities in detail.
*/
+struct wiphy;
+
/*
* wireless hardware capability structures
*/
@@ -306,6 +308,104 @@ struct key_params {
};
/**
+ * struct cfg80211_chan_def - channel definition
+ * @chan: the (control) channel
+ * @width: channel width
+ * @center_freq1: center frequency of first segment
+ * @center_freq2: center frequency of second segment
+ * (only with 80+80 MHz)
+ */
+struct cfg80211_chan_def {
+ struct ieee80211_channel *chan;
+ enum nl80211_chan_width width;
+ u32 center_freq1;
+ u32 center_freq2;
+};
+
+/**
+ * cfg80211_get_chandef_type - return old channel type from chandef
+ * @chandef: the channel definition
+ *
+ * Returns the old channel type (NOHT, HT20, HT40+/-) from a given
+ * chandef, which must have a bandwidth allowing this conversion.
+ */
+static inline enum nl80211_channel_type
+cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef)
+{
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return NL80211_CHAN_NO_HT;
+ case NL80211_CHAN_WIDTH_20:
+ return NL80211_CHAN_HT20;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ return NL80211_CHAN_HT40PLUS;
+ return NL80211_CHAN_HT40MINUS;
+ default:
+ WARN_ON(1);
+ return NL80211_CHAN_NO_HT;
+ }
+}
+
+/**
+ * cfg80211_chandef_create - create channel definition using channel type
+ * @chandef: the channel definition struct to fill
+ * @channel: the control channel
+ * @chantype: the channel type
+ *
+ * Given a channel type, create a channel definition.
+ */
+void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type chantype);
+
+/**
+ * cfg80211_chandef_identical - check if two channel definitions are identical
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %true if the channels defined by the channel definitions are
+ * identical, %false otherwise.
+ */
+static inline bool
+cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
+ const struct cfg80211_chan_def *chandef2)
+{
+ return (chandef1->chan == chandef2->chan &&
+ chandef1->width == chandef2->width &&
+ chandef1->center_freq1 == chandef2->center_freq1 &&
+ chandef1->center_freq2 == chandef2->center_freq2);
+}
+
+/**
+ * cfg80211_chandef_compatible - check if two channel definitions are compatible
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %NULL if the given channel definitions are incompatible,
+ * chandef1 or chandef2 otherwise.
+ */
+const struct cfg80211_chan_def *
+cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
+ const struct cfg80211_chan_def *chandef2);
+
+/**
+ * cfg80211_chandef_valid - check if a channel definition is valid
+ * @chandef: the channel definition to check
+ */
+bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
+
+/**
+ * cfg80211_chandef_usable - check if secondary channels can be used
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ * @prohibited_flags: the regulatory chanenl flags that must not be set
+ */
+bool cfg80211_chandef_usable(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 prohibited_flags);
+
+/**
* enum survey_info_flags - survey information flags
*
* @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -426,8 +526,7 @@ struct cfg80211_beacon_data {
*
* Used to configure an AP interface.
*
- * @channel: the channel to start the AP on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
* @beacon: beacon data
* @beacon_interval: beacon interval
* @dtim_period: DTIM period
@@ -439,10 +538,11 @@ struct cfg80211_beacon_data {
* @privacy: the BSS uses privacy
* @auth_type: Authentication type (algorithm)
* @inactivity_timeout: time in seconds to determine station's inactivity.
+ * @p2p_ctwindow: P2P CT Window
+ * @p2p_opp_ps: P2P opportunistic PS
*/
struct cfg80211_ap_settings {
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
struct cfg80211_beacon_data beacon;
@@ -454,6 +554,8 @@ struct cfg80211_ap_settings {
bool privacy;
enum nl80211_auth_type auth_type;
int inactivity_timeout;
+ u8 p2p_ctwindow;
+ bool p2p_opp_ps;
};
/**
@@ -498,6 +600,7 @@ enum station_parameters_apply_mask {
* @plink_action: plink action to take
* @plink_state: set the peer link state for a station
* @ht_capa: HT capabilities of station
+ * @vht_capa: VHT capabilities of station
* @uapsd_queues: bitmap of queues configured for uapsd. same format
* as the AC bitmap in the QoS info field
* @max_sp: max Service Period. same format as the MAX_SP in the
@@ -517,6 +620,7 @@ struct station_parameters {
u8 plink_action;
u8 plink_state;
struct ieee80211_ht_cap *ht_capa;
+ struct ieee80211_vht_cap *vht_capa;
u8 uapsd_queues;
u8 max_sp;
};
@@ -580,16 +684,24 @@ enum station_info_flags {
* Used by the driver to indicate the specific rate transmission
* type for 802.11n transmissions.
*
- * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
- * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
+ * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission
+ * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission
+ * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission
+ * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
- * @RATE_INFO_FLAGS_60G: 60gHz MCS
+ * @RATE_INFO_FLAGS_60G: 60GHz MCS
*/
enum rate_info_flags {
- RATE_INFO_FLAGS_MCS = 1<<0,
- RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
- RATE_INFO_FLAGS_SHORT_GI = 1<<2,
- RATE_INFO_FLAGS_60G = 1<<3,
+ RATE_INFO_FLAGS_MCS = BIT(0),
+ RATE_INFO_FLAGS_VHT_MCS = BIT(1),
+ RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2),
+ RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3),
+ RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4),
+ RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5),
+ RATE_INFO_FLAGS_SHORT_GI = BIT(6),
+ RATE_INFO_FLAGS_60G = BIT(7),
};
/**
@@ -600,11 +712,13 @@ enum rate_info_flags {
* @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes a 802.11n bitrate
* @legacy: bitrate in 100kbit/s for 802.11abg
+ * @nss: number of streams (VHT only)
*/
struct rate_info {
u8 flags;
u8 mcs;
u16 legacy;
+ u8 nss;
};
/**
@@ -803,6 +917,8 @@ struct mpath_info {
* @ap_isolate: do not forward packets between connected stations
* @ht_opmode: HT Operation mode
* (u16 = opmode, -1 = do not change)
+ * @p2p_ctwindow: P2P CT Window (-1 = no change)
+ * @p2p_opp_ps: P2P opportunistic PS (-1 = no change)
*/
struct bss_parameters {
int use_cts_prot;
@@ -812,6 +928,7 @@ struct bss_parameters {
u8 basic_rates_len;
int ap_isolate;
int ht_opmode;
+ s8 p2p_ctwindow, p2p_opp_ps;
};
/**
@@ -907,8 +1024,7 @@ struct mesh_config {
/**
* struct mesh_setup - 802.11s mesh setup configuration
- * @channel: the channel to start the mesh network on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
* @mesh_id: the mesh ID
* @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
* @sync_method: which synchronization method to use
@@ -923,8 +1039,7 @@ struct mesh_config {
* These parameters are fixed when the mesh is created.
*/
struct mesh_setup {
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
const u8 *mesh_id;
u8 mesh_id_len;
u8 sync_method;
@@ -955,9 +1070,6 @@ struct ieee80211_txq_params {
u8 aifs;
};
-/* from net/wireless.h */
-struct wiphy;
-
/**
* DOC: Scanning and BSS list handling
*
@@ -1000,8 +1112,10 @@ struct cfg80211_ssid {
* @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
+ * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
@@ -1012,6 +1126,7 @@ struct cfg80211_scan_request {
u32 n_channels;
const u8 *ie;
size_t ie_len;
+ u32 flags;
u32 rates[IEEE80211_NUM_BANDS];
@@ -1019,6 +1134,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
+ unsigned long scan_start;
bool aborted;
bool no_cck;
@@ -1044,6 +1160,7 @@ struct cfg80211_match_set {
* @interval: interval between each scheduled scan cycle
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
* @match_sets: sets of parameters to be matched for a scan result
* entry to be considered valid and to be passed to the host
* (others are filtered out).
@@ -1061,6 +1178,7 @@ struct cfg80211_sched_scan_request {
u32 interval;
const u8 *ie;
size_t ie_len;
+ u32 flags;
struct cfg80211_match_set *match_sets;
int n_match_sets;
s32 rssi_thold;
@@ -1068,6 +1186,7 @@ struct cfg80211_sched_scan_request {
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
+ unsigned long scan_start;
/* keep last */
struct ieee80211_channel *channels[0];
@@ -1087,6 +1206,18 @@ enum cfg80211_signal_type {
};
/**
+ * struct cfg80211_bss_ie_data - BSS entry IE data
+ * @rcu_head: internal use, for freeing
+ * @len: length of the IEs
+ * @data: IE data
+ */
+struct cfg80211_bss_ies {
+ struct rcu_head rcu_head;
+ int len;
+ u8 data[];
+};
+
+/**
* struct cfg80211_bss - BSS description
*
* This structure describes a BSS (which may also be a mesh network)
@@ -1097,36 +1228,34 @@ enum cfg80211_signal_type {
* @tsf: timestamp of last received update
* @beacon_interval: the beacon interval as from the frame
* @capability: the capability field in host byte order
- * @information_elements: the information elements (Note that there
+ * @ies: the information elements (Note that there
* is no guarantee that these are well-formed!); this is a pointer to
* either the beacon_ies or proberesp_ies depending on whether Probe
* Response frame has been received
- * @len_information_elements: total length of the information elements
* @beacon_ies: the information elements from the last Beacon frame
- * @len_beacon_ies: total length of the beacon_ies
* @proberesp_ies: the information elements from the last Probe Response frame
- * @len_proberesp_ies: total length of the proberesp_ies
* @signal: signal strength value (type depends on the wiphy's signal_type)
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/
struct cfg80211_bss {
+ u64 tsf;
+
struct ieee80211_channel *channel;
- u8 bssid[ETH_ALEN];
- u64 tsf;
+ const struct cfg80211_bss_ies __rcu *ies;
+ const struct cfg80211_bss_ies __rcu *beacon_ies;
+ const struct cfg80211_bss_ies __rcu *proberesp_ies;
+
+ void (*free_priv)(struct cfg80211_bss *bss);
+
+ s32 signal;
+
u16 beacon_interval;
u16 capability;
- u8 *information_elements;
- size_t len_information_elements;
- u8 *beacon_ies;
- size_t len_beacon_ies;
- u8 *proberesp_ies;
- size_t len_proberesp_ies;
- s32 signal;
+ u8 bssid[ETH_ALEN];
- void (*free_priv)(struct cfg80211_bss *bss);
u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
};
@@ -1134,6 +1263,9 @@ struct cfg80211_bss {
* ieee80211_bss_get_ie - find IE with given ID
* @bss: the bss to search
* @ie: the IE ID
+ *
+ * Note that the return value is an RCU-protected pointer, so
+ * rcu_read_lock() must be held when calling this function.
* Returns %NULL if not found.
*/
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
@@ -1152,6 +1284,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
+ * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
+ * Authentication transaction sequence number field.
+ * @sae_data_len: Length of sae_data buffer in octets
*/
struct cfg80211_auth_request {
struct cfg80211_bss *bss;
@@ -1160,6 +1295,8 @@ struct cfg80211_auth_request {
enum nl80211_auth_type auth_type;
const u8 *key;
u8 key_len, key_idx;
+ const u8 *sae_data;
+ size_t sae_data_len;
};
/**
@@ -1252,8 +1389,7 @@ struct cfg80211_disassoc_request {
* @ssid_len: The length of the SSID, will always be non-zero.
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
* search for IBSSs with a different BSSID.
- * @channel: The channel to use if no IBSS can be found to join.
- * @channel_type: channel type (HT mode)
+ * @chandef: defines the channel to use if no other IBSS to join can be found
* @channel_fixed: The channel should be fixed -- do not search for
* IBSSs to join on other channels.
* @ie: information element(s) to include in the beacon
@@ -1271,8 +1407,7 @@ struct cfg80211_disassoc_request {
struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
@@ -1531,13 +1666,19 @@ struct cfg80211_gtk_rekey_data {
* to a merge.
* @leave_ibss: Leave the IBSS.
*
+ * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
+ * MESH mode)
+ *
* @set_wiphy_params: Notify that wiphy parameters have changed;
* @changed bitfield (see &enum wiphy_params_flags) describes which values
* have changed. The actual parameter values are available in
* struct wiphy. If returning an error, no value should be changed.
*
* @set_tx_power: set the transmit power according to the parameters,
- * the power passed is in mBm, to get dBm use MBM_TO_DBM().
+ * the power passed is in mBm, to get dBm use MBM_TO_DBM(). The
+ * wdev may be %NULL if power was set for the wiphy, and will
+ * always be %NULL unless the driver supports per-vif TX power
+ * (as advertised by the nl80211 feature flag.)
* @get_tx_power: store the current TX power into the dbm variable;
* return 0 if successful
*
@@ -1708,8 +1849,7 @@ struct cfg80211_ops {
struct ieee80211_channel *chan);
int (*set_monitor_channel)(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type);
+ struct cfg80211_chan_def *chandef);
int (*scan)(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
@@ -1732,11 +1872,15 @@ struct cfg80211_ops {
struct cfg80211_ibss_params *params);
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
+ int (*set_mcast_rate)(struct wiphy *wiphy, struct net_device *dev,
+ int rate[IEEE80211_NUM_BANDS]);
+
int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
- int (*set_tx_power)(struct wiphy *wiphy,
+ int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm);
- int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+ int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ int *dbm);
int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr);
@@ -1767,7 +1911,6 @@ struct cfg80211_ops {
int (*remain_on_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie);
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
@@ -1776,10 +1919,8 @@ struct cfg80211_ops {
int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie);
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie);
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
struct wireless_dev *wdev,
u64 cookie);
@@ -1834,10 +1975,9 @@ struct cfg80211_ops {
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
u32 sset, u8 *data);
- struct ieee80211_channel *
- (*get_channel)(struct wiphy *wiphy,
+ int (*get_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
- enum nl80211_channel_type *type);
+ struct cfg80211_chan_def *chandef);
int (*start_p2p_device)(struct wiphy *wiphy,
struct wireless_dev *wdev);
@@ -2445,8 +2585,7 @@ struct wireless_dev {
spinlock_t event_lock;
struct cfg80211_internal_bss *current_bss; /* associated / joined */
- struct ieee80211_channel *preset_chan;
- enum nl80211_channel_type preset_chantype;
+ struct cfg80211_chan_def preset_chandef;
/* for AP and mesh channel tracking */
struct ieee80211_channel *channel;
@@ -3326,14 +3465,12 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
* @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
* @duration: Duration in milliseconds that the driver intents to remain on the
* channel
* @gfp: allocation flags
*/
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp);
/**
@@ -3341,12 +3478,10 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
* @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
* @gfp: allocation flags
*/
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
gfp_t gfp);
@@ -3536,7 +3671,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
* @len: length of the frame
* @freq: frequency the frame was received on
* @sig_dbm: signal strength in mBm, or 0 if unknown
- * @gfp: allocation flags
*
* Use this function to report to userspace when a beacon was
* received. It is not useful to call this when there is no
@@ -3544,31 +3678,47 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
*/
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
- int freq, int sig_dbm, gfp_t gfp);
+ int freq, int sig_dbm);
/**
- * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
+ * cfg80211_reg_can_beacon - check if beaconing is allowed
* @wiphy: the wiphy
- * @chan: main channel
- * @channel_type: HT mode
+ * @chandef: the channel definition
*
* This function returns true if there is no secondary channel or the secondary
- * channel can be used for beaconing (i.e. is not a radar channel etc.)
+ * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
*/
-bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type);
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef);
/*
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
* @dev: the device which switched channels
- * @freq: new channel frequency (in MHz)
- * @type: channel type
+ * @chandef: the new channel definition
*
* Acquires wdev_lock, so must only be called from sleepable driver context!
*/
-void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
- enum nl80211_channel_type type);
+void cfg80211_ch_switch_notify(struct net_device *dev,
+ struct cfg80211_chan_def *chandef);
+
+/*
+ * cfg80211_tdls_oper_request - request userspace to perform TDLS operation
+ * @dev: the device on which the operation is requested
+ * @peer: the MAC address of the peer device
+ * @oper: the requested TDLS operation (NL80211_TDLS_SETUP or
+ * NL80211_TDLS_TEARDOWN)
+ * @reason_code: the reason code for teardown request
+ * @gfp: allocation flags
+ *
+ * This function is used to request userspace to perform TDLS operation that
+ * requires knowledge of keys, i.e., link setup or teardown when the AP
+ * connection uses encryption. This is optional mechanism for the driver to use
+ * if it can automatically determine when a TDLS link could be useful (e.g.,
+ * based on traffic and signal strength for a peer).
+ */
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+ enum nl80211_tdls_operation oper,
+ u16 reason_code, gfp_t gfp);
/*
* cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
@@ -3594,6 +3744,26 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
*/
void cfg80211_unregister_wdev(struct wireless_dev *wdev);
+/**
+ * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
+ * @ies: the input IE buffer
+ * @len: the input length
+ * @attr: the attribute ID to find
+ * @buf: output buffer, can be %NULL if the data isn't needed, e.g.
+ * if the function is only called to get the needed buffer size
+ * @bufsize: size of the output buffer
+ *
+ * The function finds a given P2P attribute in the (vendor) IEs and
+ * copies its contents to the given buffer.
+ *
+ * The return value is a negative error code (-%EILSEQ or -%ENOENT) if
+ * the data is malformed or the attribute can't be found (respectively),
+ * or the length of the found attribute (which can be zero).
+ */
+int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
+ enum ieee80211_p2p_attr_id attr,
+ u8 *buf, unsigned int bufsize);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index b6a6eeb3905f..2581638f4a3d 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -24,12 +24,12 @@ struct cgroup_cls_state
u32 classid;
};
-extern void sock_update_classid(struct sock *sk);
+extern void sock_update_classid(struct sock *sk, struct task_struct *task);
#if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
static inline u32 task_cls_classid(struct task_struct *p)
{
- int classid;
+ u32 classid;
if (in_interrupt())
return 0;
@@ -61,7 +61,7 @@ static inline u32 task_cls_classid(struct task_struct *p)
}
#endif
#else /* !CGROUP_NET_CLS_CGROUP */
-static inline void sock_update_classid(struct sock *sk)
+static inline void sock_update_classid(struct sock *sk, struct task_struct *task)
{
}
diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h
index 4fd8a4b4b7ee..e5062c955ea6 100644
--- a/include/net/gro_cells.h
+++ b/include/net/gro_cells.h
@@ -17,7 +17,6 @@ struct gro_cells {
static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
{
- unsigned long flags;
struct gro_cell *cell = gcells->cells;
struct net_device *dev = skb->dev;
@@ -35,32 +34,37 @@ static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *s
return;
}
- spin_lock_irqsave(&cell->napi_skbs.lock, flags);
+ /* We run in BH context */
+ spin_lock(&cell->napi_skbs.lock);
__skb_queue_tail(&cell->napi_skbs, skb);
if (skb_queue_len(&cell->napi_skbs) == 1)
napi_schedule(&cell->napi);
- spin_unlock_irqrestore(&cell->napi_skbs.lock, flags);
+ spin_unlock(&cell->napi_skbs.lock);
}
+/* called unser BH context */
static inline int gro_cell_poll(struct napi_struct *napi, int budget)
{
struct gro_cell *cell = container_of(napi, struct gro_cell, napi);
struct sk_buff *skb;
int work_done = 0;
+ spin_lock(&cell->napi_skbs.lock);
while (work_done < budget) {
- skb = skb_dequeue(&cell->napi_skbs);
+ skb = __skb_dequeue(&cell->napi_skbs);
if (!skb)
break;
-
+ spin_unlock(&cell->napi_skbs.lock);
napi_gro_receive(napi, skb);
work_done++;
+ spin_lock(&cell->napi_skbs.lock);
}
if (work_done < budget)
napi_complete(napi);
+ spin_unlock(&cell->napi_skbs.lock);
return work_done;
}
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 7f0df133d119..c3999632e616 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -186,6 +186,10 @@ struct ieee80211_radiotap_header {
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
*
* Contains the AMPDU information for the subframe.
+ *
+ * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
+ *
+ * Contains VHT information about this frame.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
@@ -209,6 +213,7 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
+ IEEE80211_RADIOTAP_VHT = 21,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -282,6 +287,25 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
+/* For IEEE80211_RADIOTAP_VHT */
+#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
+#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
+#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
+#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
+#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
+#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
+#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
+#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
+#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
+
+#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
+#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
+#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
+#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
+#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
+#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
+
+
/* helpers */
static inline int ieee80211_get_radiotap_len(unsigned char *data)
{
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 54be0287eb98..67a8fa098e3a 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -277,7 +277,6 @@ static inline struct sock *inet_lookup_listener(struct net *net,
On 64bit targets we combine comparisons with pair of adjacent __be32
fields in the same way.
*/
-typedef __u32 __bitwise __portpair;
#ifdef __BIG_ENDIAN
#define INET_COMBINED_PORTS(__sport, __dport) \
((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
@@ -287,7 +286,6 @@ typedef __u32 __bitwise __portpair;
#endif
#if (BITS_PER_LONG == 64)
-typedef __u64 __bitwise __addrpair;
#ifdef __BIG_ENDIAN
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const __addrpair __name = (__force __addrpair) ( \
@@ -299,30 +297,34 @@ typedef __u64 __bitwise __addrpair;
(((__force __u64)(__be32)(__daddr)) << 32) | \
((__force __u64)(__be32)(__saddr)));
#endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie)) && \
- ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
- ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->inet_portpair == (__ports)) && \
+ (inet_sk(__sk)->inet_addrpair == (__cookie)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)\
+ ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
+ (inet_twsk(__sk)->tw_addrpair == (__cookie)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
#else /* 32-bit arch */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- (inet_sk(__sk)->inet_daddr == (__saddr)) && \
- (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
- ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
- (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
- ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->inet_portpair == (__ports)) && \
+ (inet_sk(__sk)->inet_daddr == (__saddr)) && \
+ (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
+ (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
+ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
#endif /* 64-bit arch */
/*
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 256c1ed2d69a..a4196cbc84ec 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -144,9 +144,11 @@ struct inet_sock {
/* Socket demultiplex comparisons on incoming packets. */
#define inet_daddr sk.__sk_common.skc_daddr
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
+#define inet_addrpair sk.__sk_common.skc_addrpair
+#define inet_dport sk.__sk_common.skc_dport
+#define inet_num sk.__sk_common.skc_num
+#define inet_portpair sk.__sk_common.skc_portpair
- __be16 inet_dport;
- __u16 inet_num;
__be32 inet_saddr;
__s16 uc_ttl;
__u16 cmsg_flags;
@@ -154,6 +156,7 @@ struct inet_sock {
__u16 inet_id;
struct ip_options_rcu __rcu *inet_opt;
+ int rx_dst_ifindex;
__u8 tos;
__u8 min_ttl;
__u8 mc_ttl;
@@ -170,7 +173,6 @@ struct inet_sock {
int uc_index;
int mc_index;
__be32 mc_addr;
- int rx_dst_ifindex;
struct ip_mc_socklist __rcu *mc_list;
struct inet_cork_full cork;
};
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index ba52c830a7a5..7d658d577368 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -112,6 +112,11 @@ struct inet_timewait_sock {
#define tw_net __tw_common.skc_net
#define tw_daddr __tw_common.skc_daddr
#define tw_rcv_saddr __tw_common.skc_rcv_saddr
+#define tw_addrpair __tw_common.skc_addrpair
+#define tw_dport __tw_common.skc_dport
+#define tw_num __tw_common.skc_num
+#define tw_portpair __tw_common.skc_portpair
+
int tw_timeout;
volatile unsigned char tw_substate;
unsigned char tw_rcv_wscale;
@@ -119,8 +124,6 @@ struct inet_timewait_sock {
/* Socket demultiplex comparisons on incoming packets. */
/* these three are in inet_sock */
__be16 tw_sport;
- __be16 tw_dport;
- __u16 tw_num;
kmemcheck_bitfield_begin(flags);
/* And these are ours. */
unsigned int tw_ipv6only : 1,
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index bc1b0fda2b04..652d3d309357 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -31,6 +31,8 @@
#include <net/ip.h>
#include <asm/checksum.h>
#include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
#ifndef _HAVE_ARCH_IPV6_CSUM
@@ -91,4 +93,37 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
}
#endif
+
+static __inline__ __sum16 tcp_v6_check(int len,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __wsum base)
+{
+ return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
+}
+
+static inline void __tcp_v6_send_check(struct sk_buff *skb,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr)
+{
+ struct tcphdr *th = tcp_hdr(skb);
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct tcphdr, check);
+ } else {
+ th->check = tcp_v6_check(skb->len, saddr, daddr,
+ csum_partial(th, th->doff << 2,
+ skb->csum));
+ }
+}
+
+static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
#endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8a2a203eb15d..fdc48a94a063 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,8 @@ struct fib6_config {
unsigned long fc_expires;
struct nlattr *fc_mx;
int fc_mx_len;
+ int fc_mp_len;
+ struct nlattr *fc_mp;
struct nl_info fc_nlinfo;
};
@@ -99,6 +101,14 @@ struct rt6_info {
struct in6_addr rt6i_gateway;
+ /* Multipath routes:
+ * siblings is a list of rt6_info that have the the same metric/weight,
+ * destination, but not the same gateway. nsiblings is just a cache
+ * to speed up lookup.
+ */
+ struct list_head rt6i_siblings;
+ unsigned int rt6i_nsiblings;
+
atomic_t rt6i_ref;
/* These are in a separate cache line. */
@@ -107,7 +117,6 @@ struct rt6_info {
struct rt6key rt6i_src;
struct rt6key rt6i_prefsrc;
u32 rt6i_metric;
- u32 rt6i_peer_genid;
struct inet6_dev *rt6i_idev;
unsigned long _rt6i_peer;
@@ -203,6 +212,15 @@ static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
dst_hold(new);
}
+static inline void ip6_rt_put(struct rt6_info *rt)
+{
+ /* dst_release() accepts a NULL parameter.
+ * We rely on dst being first structure in struct rt6_info
+ */
+ BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
+ dst_release(&rt->dst);
+}
+
struct fib6_walker_t {
struct list_head lh;
struct fib6_node *root, *node;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5fa2af00634a..27d83183e615 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -1,9 +1,6 @@
#ifndef _NET_IP6_ROUTE_H
#define _NET_IP6_ROUTE_H
-#define IP6_RT_PRIO_USER 1024
-#define IP6_RT_PRIO_ADDRCONF 256
-
struct route_info {
__u8 type;
__u8 length;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index ee75ccdf5188..68c69d54d392 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -22,7 +22,10 @@
#include <linux/ip.h>
#include <linux/ipv6.h> /* for struct ipv6hdr */
#include <net/ipv6.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_IP_VS_IPV6)
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack.h>
#endif
#include <net/net_namespace.h> /* Netw namespace */
@@ -103,30 +106,117 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
/* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size;
-
struct ip_vs_iphdr {
- int len;
- __u8 protocol;
+ __u32 len; /* IPv4 simply where L4 starts
+ IPv6 where L4 Transport Header starts */
+ __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
+ __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
+ __s16 protocol;
+ __s32 flags;
union nf_inet_addr saddr;
union nf_inet_addr daddr;
};
+/* Dependency to module: nf_defrag_ipv6 */
+#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return skb->nfct_reasm;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+ int len, void *buffer,
+ const struct ip_vs_iphdr *ipvsh)
+{
+ if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
+ return skb_header_pointer(skb_nfct_reasm(skb),
+ ipvsh->thoff_reasm, len, buffer);
+
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+#else
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return NULL;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+ int len, void *buffer,
+ const struct ip_vs_iphdr *ipvsh)
+{
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+#endif
+
static inline void
-ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
+ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
+{
+ const struct iphdr *iph = nh;
+
+ iphdr->len = iph->ihl * 4;
+ iphdr->fragoffs = 0;
+ iphdr->protocol = iph->protocol;
+ iphdr->saddr.ip = iph->saddr;
+ iphdr->daddr.ip = iph->daddr;
+}
+
+/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6.
+ * IPv6 requires some extra work, as finding proper header position,
+ * depend on the IPv6 extension headers.
+ */
+static inline void
+ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
- const struct ipv6hdr *iph = nh;
- iphdr->len = sizeof(struct ipv6hdr);
- iphdr->protocol = iph->nexthdr;
+ const struct ipv6hdr *iph =
+ (struct ipv6hdr *)skb_network_header(skb);
iphdr->saddr.in6 = iph->saddr;
iphdr->daddr.in6 = iph->daddr;
+ /* ipv6_find_hdr() updates len, flags, thoff_reasm */
+ iphdr->thoff_reasm = 0;
+ iphdr->len = 0;
+ iphdr->flags = 0;
+ iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
+ &iphdr->fragoffs,
+ &iphdr->flags);
+ /* get proto from re-assembled packet and it's offset */
+ if (skb_nfct_reasm(skb))
+ iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
+ &iphdr->thoff_reasm,
+ -1, NULL, NULL);
+
} else
#endif
{
- const struct iphdr *iph = nh;
- iphdr->len = iph->ihl * 4;
- iphdr->protocol = iph->protocol;
+ const struct iphdr *iph =
+ (struct iphdr *)skb_network_header(skb);
+ iphdr->len = iph->ihl * 4;
+ iphdr->fragoffs = 0;
+ iphdr->protocol = iph->protocol;
+ iphdr->saddr.ip = iph->saddr;
+ iphdr->daddr.ip = iph->daddr;
+ }
+}
+
+/* This function is a faster version of ip_vs_fill_iph_skb().
+ * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()).
+ * This is used by the some of the ip_vs_*_schedule() functions.
+ * (Mostly done to avoid ABI breakage of external schedulers)
+ */
+static inline void
+ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb,
+ struct ip_vs_iphdr *iphdr)
+{
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6) {
+ const struct ipv6hdr *iph =
+ (struct ipv6hdr *)skb_network_header(skb);
+ iphdr->saddr.in6 = iph->saddr;
+ iphdr->daddr.in6 = iph->daddr;
+ } else
+#endif
+ {
+ const struct iphdr *iph =
+ (struct iphdr *)skb_network_header(skb);
iphdr->saddr.ip = iph->saddr;
iphdr->daddr.ip = iph->daddr;
}
@@ -165,7 +255,7 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
int len;
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
- len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+ len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",
&addr->in6) + 1;
else
#endif
@@ -398,27 +488,26 @@ struct ip_vs_protocol {
int (*conn_schedule)(int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp);
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph);
struct ip_vs_conn *
(*conn_in_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
struct ip_vs_conn *
(*conn_out_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
- int (*snat_handler)(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+ int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
- int (*dnat_handler)(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+ int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
int (*csum_check)(int af, struct sk_buff *skb,
struct ip_vs_protocol *pp);
@@ -518,7 +607,7 @@ struct ip_vs_conn {
NF_ACCEPT can be returned when destination is local.
*/
int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp);
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
/* Note: we can group the following members into a structure,
in order to save more space, and the following members are
@@ -769,13 +858,11 @@ struct ip_vs_app {
struct ip_vs_conn *
(*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app,
- const struct iphdr *iph, unsigned int proto_off,
- int inverse);
+ const struct iphdr *iph, int inverse);
struct ip_vs_conn *
(*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app,
- const struct iphdr *iph, unsigned int proto_off,
- int inverse);
+ const struct iphdr *iph, int inverse);
int (*state_transition)(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb,
@@ -1074,14 +1161,12 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
/* put back the conn without restarting its timer */
@@ -1254,9 +1339,10 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
extern struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd, int *ignored);
+ struct ip_vs_proto_data *pd, int *ignored,
+ struct ip_vs_iphdr *iph);
extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd);
+ struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
@@ -1315,33 +1401,38 @@ extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
/*
* Various IPVS packet transmitters (from ip_vs_xmit.c)
*/
-extern int ip_vs_null_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_bypass_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
#ifdef CONFIG_IP_VS_IPV6
-extern int ip_vs_bypass_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
#endif
#ifdef CONFIG_SYSCTL
diff --git a/include/net/ipip.h b/include/net/ipip.h
index ddc077c51f32..21947cf4fa46 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -48,25 +48,27 @@ struct ip_tunnel_prl_entry {
struct rcu_head rcu_head;
};
-#define __IPTUNNEL_XMIT(stats1, stats2) do { \
- int err; \
- int pkt_len = skb->len - skb_transport_offset(skb); \
- \
- skb->ip_summed = CHECKSUM_NONE; \
- ip_select_ident(iph, &rt->dst, NULL); \
- \
- err = ip_local_out(skb); \
- if (likely(net_xmit_eval(err) == 0)) { \
- u64_stats_update_begin(&(stats1)->syncp); \
- (stats1)->tx_bytes += pkt_len; \
- (stats1)->tx_packets++; \
- u64_stats_update_end(&(stats1)->syncp); \
- } else { \
- (stats2)->tx_errors++; \
- (stats2)->tx_aborted_errors++; \
- } \
-} while (0)
+static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int err;
+ struct iphdr *iph = ip_hdr(skb);
+ int pkt_len = skb->len - skb_transport_offset(skb);
+ struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
-#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+ nf_reset(skb);
+ skb->ip_summed = CHECKSUM_NONE;
+ ip_select_ident(iph, skb_dst(skb), NULL);
+
+ err = ip_local_out(skb);
+ if (likely(net_xmit_eval(err) == 0)) {
+ u64_stats_update_begin(&tstats->syncp);
+ tstats->tx_bytes += pkt_len;
+ tstats->tx_packets++;
+ u64_stats_update_end(&tstats->syncp);
+ } else {
+ dev->stats.tx_errors++;
+ dev->stats.tx_aborted_errors++;
+ }
+}
#endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 979bf6c13141..5af66b26ebdd 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -271,6 +271,15 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
+static inline bool ipv6_accept_ra(struct inet6_dev *idev)
+{
+ /* If forwarding is enabled, RA are not accepted unless the special
+ * hybrid mode (accept_ra=2) is enabled.
+ */
+ return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
+ idev->cnf.accept_ra;
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static inline int ip6_frag_nqueues(struct net *net)
{
@@ -630,6 +639,16 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
extern bool ipv6_ext_hdr(u8 nexthdr);
+enum {
+ IP6_FH_F_FRAG = (1 << 0),
+ IP6_FH_F_AUTH = (1 << 1),
+ IP6_FH_F_SKIP_RH = (1 << 2),
+};
+
+/* find specified header and get offset to it */
+extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff, int *fragflg);
+
extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index fff11b7fe8a4..591f78631f13 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -134,7 +134,7 @@ typedef struct {
} CACHE_ENTRY;
/*
- * Information about each registred IrLAP layer
+ * Information about each registered IrLAP layer
*/
struct lap_cb {
irda_queue_t queue; /* Must be first */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82558c8decf8..ee50c5eba50c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -144,6 +144,39 @@ struct ieee80211_low_level_stats {
};
/**
+ * enum ieee80211_chanctx_change - change flag for channel context
+ * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
+ * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
+ */
+enum ieee80211_chanctx_change {
+ IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
+ IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
+};
+
+/**
+ * struct ieee80211_chanctx_conf - channel context that vifs may be tuned to
+ *
+ * This is the driver-visible part. The ieee80211_chanctx
+ * that contains it is visible in mac80211 only.
+ *
+ * @def: the channel definition
+ * @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
+ * after RTS/CTS handshake to receive SMPS MIMO transmissions;
+ * this will always be >= @rx_chains_static.
+ * @drv_priv: data area for driver use, will always be aligned to
+ * sizeof(void *), size is determined in hw information.
+ */
+struct ieee80211_chanctx_conf {
+ struct cfg80211_chan_def def;
+
+ u8 rx_chains_static, rx_chains_dynamic;
+
+ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+/**
* enum ieee80211_bss_change - BSS change notification flags
*
* These flags are used with the bss_info_changed() callback
@@ -172,6 +205,9 @@ struct ieee80211_low_level_stats {
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
+ * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
+ * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS)
+ * changed (currently only in P2P client mode, GO mode will be later)
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
@@ -192,6 +228,8 @@ enum ieee80211_bss_change {
BSS_CHANGED_SSID = 1<<15,
BSS_CHANGED_AP_PROBE_RESP = 1<<16,
BSS_CHANGED_PS = 1<<17,
+ BSS_CHANGED_TXPOWER = 1<<18,
+ BSS_CHANGED_P2P_PS = 1<<19,
/* when adding here, make sure to change ieee80211_reconfig */
};
@@ -223,6 +261,7 @@ enum ieee80211_rssi_event {
* @assoc: association status
* @ibss_joined: indicates whether this station is part of an IBSS
* or not
+ * @ibss_creator: indicates if a new IBSS network is being created
* @aid: association ID number, valid only when @assoc is true
* @use_cts_prot: use CTS protection
* @use_short_preamble: use 802.11b short preamble;
@@ -247,9 +286,8 @@ enum ieee80211_rssi_event {
* @mcast_rate: per-band multicast rate index + 1 (0: disabled)
* @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not
- * @channel_type: Channel type for this BSS -- the hardware might be
- * configured for HT40+ while this BSS only uses no-HT, for
- * example.
+ * @chandef: Channel definition for this BSS -- the hardware might be
+ * configured a higher bandwidth than this BSS uses, for example.
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
* This field is only valid when the channel type is one of the HT types.
* @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@@ -273,11 +311,15 @@ enum ieee80211_rssi_event {
* @ssid: The SSID of the current vif. Only valid in AP-mode.
* @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
+ * @txpower: TX power in dBm
+ * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
+ * @p2p_oppps: P2P opportunistic PS is enabled
*/
struct ieee80211_bss_conf {
const u8 *bssid;
/* association related data */
bool assoc, ibss_joined;
+ bool ibss_creator;
u16 aid;
/* erp related data */
bool use_cts_prot;
@@ -294,7 +336,7 @@ struct ieee80211_bss_conf {
u16 ht_operation_mode;
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
u8 arp_addr_cnt;
bool arp_filter_enabled;
@@ -304,6 +346,9 @@ struct ieee80211_bss_conf {
u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
bool hidden_ssid;
+ int txpower;
+ u8 p2p_ctwindow;
+ bool p2p_oppps;
};
/**
@@ -454,9 +499,14 @@ enum mac80211_tx_control_flags {
* This is set if the current BSS requires ERP protection.
* @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @IEEE80211_TX_RC_MCS: HT rate.
+ * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
+ * into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
* Greenfield mode.
* @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
+ * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
+ * (80+80 isn't supported yet)
* @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
* adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
@@ -467,12 +517,15 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
- /* rate index is an MCS rate number instead of an index */
+ /* rate index is an HT/VHT MCS instead of an index */
IEEE80211_TX_RC_MCS = BIT(3),
IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
IEEE80211_TX_RC_DUP_DATA = BIT(6),
IEEE80211_TX_RC_SHORT_GI = BIT(7),
+ IEEE80211_TX_RC_VHT_MCS = BIT(8),
+ IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9),
+ IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10),
};
@@ -515,10 +568,32 @@ enum mac80211_rate_control_flags {
*/
struct ieee80211_tx_rate {
s8 idx;
- u8 count;
- u8 flags;
+ u16 count:5,
+ flags:11;
} __packed;
+#define IEEE80211_MAX_TX_RETRY 31
+
+static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
+ u8 mcs, u8 nss)
+{
+ WARN_ON(mcs & ~0xF);
+ WARN_ON(nss & ~0x7);
+ rate->idx = (nss << 4) | mcs;
+}
+
+static inline u8
+ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
+{
+ return rate->idx & 0xF;
+}
+
+static inline u8
+ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
+{
+ return rate->idx >> 4;
+}
+
/**
* struct ieee80211_tx_info - skb transmit information
*
@@ -663,13 +738,20 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* the frame.
* @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
* the frame.
- * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
+ * @RX_FLAG_MACTIME_START: The timestamp passed in the RX status (@mactime
* field) is valid and contains the time the first symbol of the MPDU
* was received. This is useful in monitor mode and for proper IBSS
* merging.
+ * @RX_FLAG_MACTIME_END: The timestamp passed in the RX status (@mactime
+ * field) is valid and contains the time the last symbol of the MPDU
+ * (including FCS) was received.
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
+ * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
+ * @RX_FLAG_80MHZ: 80 MHz was used
+ * @RX_FLAG_80P80MHZ: 80+80 MHz was used
+ * @RX_FLAG_160MHZ: 160 MHz was used
* @RX_FLAG_SHORT_GI: Short guard interval was used
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
* Valid only for data frames (mainly A-MPDU)
@@ -697,7 +779,7 @@ enum mac80211_rx_flags {
RX_FLAG_IV_STRIPPED = BIT(4),
RX_FLAG_FAILED_FCS_CRC = BIT(5),
RX_FLAG_FAILED_PLCP_CRC = BIT(6),
- RX_FLAG_MACTIME_MPDU = BIT(7),
+ RX_FLAG_MACTIME_START = BIT(7),
RX_FLAG_SHORTPRE = BIT(8),
RX_FLAG_HT = BIT(9),
RX_FLAG_40MHZ = BIT(10),
@@ -711,6 +793,11 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_IS_LAST = BIT(18),
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
+ RX_FLAG_MACTIME_END = BIT(21),
+ RX_FLAG_VHT = BIT(22),
+ RX_FLAG_80MHZ = BIT(23),
+ RX_FLAG_80P80MHZ = BIT(24),
+ RX_FLAG_160MHZ = BIT(25),
};
/**
@@ -731,25 +818,39 @@ enum mac80211_rx_flags {
* @IEEE80211_HW_SIGNAL_*
* @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates or MCS index if
- * HT rates are use (RX_FLAG_HT)
+ * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
+ * @vht_nss: number of streams (VHT only)
* @flag: %RX_FLAG_*
* @rx_flags: internal RX flags for mac80211
* @ampdu_reference: A-MPDU reference number, must be a different value for
* each A-MPDU but the same for each subframe within one A-MPDU
* @ampdu_delimiter_crc: A-MPDU delimiter CRC
+ * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
+ * @vendor_radiotap_len: radiotap vendor namespace length
+ * @vendor_radiotap_align: radiotap vendor namespace alignment. Note
+ * that the actual data must be at the start of the SKB data
+ * already.
+ * @vendor_radiotap_oui: radiotap vendor namespace OUI
+ * @vendor_radiotap_subns: radiotap vendor sub namespace
*/
struct ieee80211_rx_status {
u64 mactime;
u32 device_timestamp;
u32 ampdu_reference;
u32 flag;
+ u32 vendor_radiotap_bitmap;
+ u16 vendor_radiotap_len;
u16 freq;
u8 rate_idx;
+ u8 vht_nss;
u8 rx_flags;
u8 band;
u8 antenna;
s8 signal;
u8 ampdu_delimiter_crc;
+ u8 vendor_radiotap_align;
+ u8 vendor_radiotap_oui[3];
+ u8 vendor_radiotap_subns;
};
/**
@@ -794,6 +895,8 @@ enum ieee80211_conf_flags {
* @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
* @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ * Note that this is only valid if channel contexts are not used,
+ * otherwise each channel context has the number of chains listed.
*/
enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_SMPS = BIT(1),
@@ -845,7 +948,8 @@ enum ieee80211_smps_mode {
* powersave documentation below. This variable is valid only when
* the CONF_PS flag is set.
*
- * @power_level: requested transmit power (in dBm)
+ * @power_level: requested transmit power (in dBm), backward compatibility
+ * value only that is set to the minimum of all interfaces
*
* @channel: the channel to tune to
* @channel_type: the channel (HT) type
@@ -859,7 +963,9 @@ enum ieee80211_smps_mode {
*
* @smps_mode: spatial multiplexing powersave mode; note that
* %IEEE80211_SMPS_STATIC is used when the device is not
- * configured for an HT channel
+ * configured for an HT channel.
+ * Note that this is only valid if channel contexts are not used,
+ * otherwise each channel context has the number of chains listed.
*/
struct ieee80211_conf {
u32 flags;
@@ -931,6 +1037,11 @@ enum ieee80211_vif_flags {
* at runtime, mac80211 will never touch this field
* @hw_queue: hardware queue for each AC
* @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
+ * @chanctx_conf: The channel context this interface is assigned to, or %NULL
+ * when it is not assigned. This pointer is RCU-protected due to the TX
+ * path needing to access it; even though the netdev carrier will always
+ * be off when it is %NULL there can still be races and packets could be
+ * processed after it switches back to %NULL.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *).
*/
@@ -943,6 +1054,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
+ struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+
u32 driver_flags;
/* must be last */
@@ -1076,6 +1189,8 @@ enum ieee80211_sta_state {
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
* @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
+ * of remote STA. Taking as is.
* @wme: indicates whether the STA supports WME. Only valid during AP-mode.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
@@ -1088,6 +1203,7 @@ struct ieee80211_sta {
u8 addr[ETH_ALEN];
u16 aid;
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
bool wme;
u8 uapsd_queues;
u8 max_sp;
@@ -1253,6 +1369,10 @@ struct ieee80211_tx_control {
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* P2P Interface. This will be honoured even if more than one interface
* is supported.
+ *
+ * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session
+ * should be tear down once BAR frame will not be acked.
+ *
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1281,6 +1401,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26,
};
/**
@@ -1325,6 +1446,8 @@ enum ieee80211_hw_flags {
* within &struct ieee80211_vif.
* @sta_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_sta.
+ * @chanctx_data_size: size (in bytes) of the drv_priv data area
+ * within &struct ieee80211_chanctx_conf.
*
* @max_rates: maximum number of alternate rate retry stages the hw
* can handle.
@@ -1355,6 +1478,10 @@ enum ieee80211_hw_flags {
* include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
* adding _BW is supported today.
*
+ * @radiotap_vht_details: lists which VHT MCS information the HW reports,
+ * the default is _GI | _BANDWIDTH.
+ * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
+ *
* @netdev_features: netdev features to be set in each netdev created
* from this HW. Note only HW checksum features are currently
* compatible with mac80211. Other feature bits will be rejected.
@@ -1369,6 +1496,7 @@ struct ieee80211_hw {
int channel_change_time;
int vif_data_size;
int sta_data_size;
+ int chanctx_data_size;
int napi_weight;
u16 queues;
u16 max_listen_interval;
@@ -1380,6 +1508,7 @@ struct ieee80211_hw {
u8 max_tx_aggregation_subframes;
u8 offchannel_tx_hw_queue;
u8 radiotap_mcs_details;
+ u16 radiotap_vht_details;
netdev_features_t netdev_features;
};
@@ -2126,6 +2255,14 @@ enum ieee80211_rate_control_changed {
* @sta_remove: Notifies low level driver about removal of an associated
* station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
*
+ * @sta_add_debugfs: Drivers can use this callback to add debugfs files
+ * when a station is added to mac80211's station list. This callback
+ * and @sta_remove_debugfs should be within a CONFIG_MAC80211_DEBUGFS
+ * conditional. This callback can sleep.
+ *
+ * @sta_remove_debugfs: Remove the debugfs files which were added using
+ * @sta_add_debugfs. This callback can sleep.
+ *
* @sta_notify: Notifies low level driver about power state transition of an
* associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating
* in AP mode, this callback will not be called when the flag
@@ -2317,6 +2454,27 @@ enum ieee80211_rate_control_changed {
* The callback will be called before each transmission and upon return
* mac80211 will transmit the frame right away.
* The callback is optional and can (should!) sleep.
+ *
+ * @add_chanctx: Notifies device driver about new channel context creation.
+ * @remove_chanctx: Notifies device driver about channel context destruction.
+ * @change_chanctx: Notifies device driver about channel context changes that
+ * may happen when combining different virtual interfaces on the same
+ * channel context with different settings
+ * @assign_vif_chanctx: Notifies device driver about channel context being bound
+ * to vif. Possible use is for hw queue remapping.
+ * @unassign_vif_chanctx: Notifies device driver about channel context being
+ * unbound from vif.
+ * @start_ap: Start operation on the AP interface, this is called after all the
+ * information in bss_conf is set and beacon can be retrieved. A channel
+ * context is bound before this is called. Note that if the driver uses
+ * software scan or ROC, this (and @stop_ap) isn't called when the AP is
+ * just "paused" for scanning/ROC, which is indicated by the beacon being
+ * disabled/enabled via @bss_info_changed.
+ * @stop_ap: Stop operation on the AP interface.
+ *
+ * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
+ * reconfiguration has completed. This can help the driver implement the
+ * reconfiguration step. This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -2342,6 +2500,9 @@ struct ieee80211_ops {
struct ieee80211_bss_conf *info,
u32 changed);
+ int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+ void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+
u64 (*prepare_multicast)(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list);
void (*configure_filter)(struct ieee80211_hw *hw,
@@ -2383,6 +2544,16 @@ struct ieee80211_ops {
struct ieee80211_sta *sta);
int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+#ifdef CONFIG_MAC80211_DEBUGFS
+ void (*sta_add_debugfs)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
+ void (*sta_remove_debugfs)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
+#endif
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -2424,8 +2595,8 @@ struct ieee80211_ops {
int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
int (*remain_on_channel)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
int duration);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
@@ -2461,6 +2632,22 @@ struct ieee80211_ops {
void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+
+ int (*add_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*remove_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*change_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx,
+ u32 changed);
+ int (*assign_vif_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx);
+
+ void (*restart_complete)(struct ieee80211_hw *hw);
};
/**
@@ -2962,8 +3149,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @ssid: SSID buffer
* @ssid_len: length of SSID
- * @ie: buffer containing all IEs except SSID for the template
- * @ie_len: length of the IE buffer
+ * @tailroom: tailroom to reserve at end of SKB for IEs
*
* Creates a Probe Request template which can, for example, be uploaded to
* hardware.
@@ -2971,7 +3157,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
+ size_t tailroom);
/**
* ieee80211_rts_get - RTS frame generation function
@@ -3145,6 +3331,19 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
struct sk_buff *skb, u8 *p2k);
/**
+ * ieee80211_aes_cmac_calculate_k1_k2 - calculate the AES-CMAC sub keys
+ *
+ * This function computes the two AES-CMAC sub-keys, based on the
+ * previously installed master key.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @k1: a buffer to be filled with the 1st sub-key
+ * @k2: a buffer to be filled with the 2nd sub-key
+ */
+void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
+ u8 *k1, u8 *k2);
+
+/**
* struct ieee80211_key_seq - key sequence counter
*
* @tkip: TKIP data, containing IV32 and IV16 in host byte order
@@ -3294,6 +3493,21 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
/**
+ * enum ieee80211_interface_iteration_flags - interface iteration flags
+ * @IEEE80211_IFACE_ITER_NORMAL: Iterate over all interfaces that have
+ * been added to the driver; However, note that during hardware
+ * reconfiguration (after restart_hw) it will iterate over a new
+ * interface and over all the existing interfaces even if they
+ * haven't been re-added to the driver yet.
+ * @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
+ * interfaces, even if they haven't been re-added to the driver yet.
+ */
+enum ieee80211_interface_iteration_flags {
+ IEEE80211_IFACE_ITER_NORMAL = 0,
+ IEEE80211_IFACE_ITER_RESUME_ALL = BIT(0),
+};
+
+/**
* ieee80211_iterate_active_interfaces - iterate active interfaces
*
* This function iterates over the interfaces associated with a given
@@ -3301,13 +3515,15 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
* This function allows the iterator function to sleep, when the iterator
* function is atomic @ieee80211_iterate_active_interfaces_atomic can
* be used.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
*
* @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
* @iterator: the iterator function to call
* @data: first argument of the iterator function
*/
void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+ u32 iter_flags,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data);
@@ -3319,13 +3535,15 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
* hardware that are currently active and calls the callback for them.
* This function requires the iterator callback function to be atomic,
* if that is not desired, use @ieee80211_iterate_active_interfaces instead.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
*
* @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
* @iterator: the iterator function to call, cannot sleep
* @data: first argument of the iterator function
*/
void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
+ u32 iter_flags,
void (*iterator)(void *data,
u8 *mac,
struct ieee80211_vif *vif),
@@ -3524,6 +3742,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
void *iter_data);
/**
+ * ieee80211_iter_chan_contexts_atomic - iterate channel contexts
+ * @hw: pointre obtained from ieee80211_alloc_hw().
+ * @iter: iterator function
+ * @iter_data: data passed to iterator function
+ *
+ * Iterate all active channel contexts. This function is atomic and
+ * doesn't acquire any locks internally that might be held in other
+ * places while calling into the driver.
+ *
+ * The iterator will not find a context that's being added (during
+ * the driver callback to add it) but will find it while it's being
+ * removed.
+ */
+void ieee80211_iter_chan_contexts_atomic(
+ struct ieee80211_hw *hw,
+ void (*iter)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ void *data),
+ void *iter_data);
+
+/**
* ieee80211_ap_probereq_get - retrieve a Probe Request template
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 980d263765cf..7af1ea893038 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -190,21 +190,6 @@ extern void ndisc_send_redirect(struct sk_buff *skb,
extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
struct net_device *dev, int dir);
-extern struct sk_buff *ndisc_build_skb(struct net_device *dev,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h,
- const struct in6_addr *target,
- int llinfo);
-
-extern void ndisc_send_skb(struct sk_buff *skb,
- struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h);
-
-
/*
* IGMP
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 95e646641184..c5a43f56b796 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -23,6 +23,7 @@
#endif
#include <net/netns/xfrm.h>
+struct user_namespace;
struct proc_dir_entry;
struct net_device;
struct sock;
@@ -53,6 +54,8 @@ struct net {
struct list_head cleanup_list; /* namespaces on death row */
struct list_head exit_list; /* Use only net_mutex */
+ struct user_namespace *user_ns; /* Owning user namespace */
+
struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
@@ -126,16 +129,21 @@ struct net {
/* Init's network namespace */
extern struct net init_net;
-#ifdef CONFIG_NET
-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
-
-#else /* CONFIG_NET */
-static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+#ifdef CONFIG_NET_NS
+extern struct net *copy_net_ns(unsigned long flags,
+ struct user_namespace *user_ns, struct net *old_net);
+
+#else /* CONFIG_NET_NS */
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+static inline struct net *copy_net_ns(unsigned long flags,
+ struct user_namespace *user_ns, struct net *old_net)
{
- /* There is nothing to copy so this is a noop */
- return net_ns;
+ if (flags & CLONE_NEWNET)
+ return ERR_PTR(-EINVAL);
+ return old_net;
}
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET_NS */
extern struct list_head net_namespace_list;
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f1494feba79f..caca0c4d6b4b 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -182,7 +182,7 @@ __nf_conntrack_find(struct net *net, u16 zone,
extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
extern void nf_ct_delete_from_lists(struct nf_conn *ct);
-extern void nf_ct_insert_dying_list(struct nf_conn *ct);
+extern void nf_ct_dying_timeout(struct nf_conn *ct);
extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index bd8eea720f2e..ad14a799fd2e 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -68,4 +68,19 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
#endif
}
+static inline bool nf_nat_oif_changed(unsigned int hooknum,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn_nat *nat,
+ const struct net_device *out)
+{
+#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+ IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE)
+ return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
+ CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
+ nat->masq_index != out->ifindex;
+#else
+ return false;
+#endif
+}
+
#endif
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 252fd1010b77..fb1c0be38b6d 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -21,14 +21,10 @@ struct nf_queue_entry {
struct nf_queue_handler {
int (*outfn)(struct nf_queue_entry *entry,
unsigned int queuenum);
- char *name;
};
-extern int nf_register_queue_handler(u_int8_t pf,
- const struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(u_int8_t pf,
- const struct nf_queue_handler *qh);
-extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
+void nf_register_queue_handler(const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(void);
extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
#endif /* _NF_QUEUE_H */
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 5e5eb1f9f14b..3573a81815ad 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -62,6 +62,9 @@ struct netns_sctp {
/* Whether Cookie Preservative is enabled(1) or not(0) */
int cookie_preserve_enable;
+ /* The namespace default hmac alg */
+ char *sctp_hmac_alg;
+
/* Valid.Cookie.Life - 60 seconds */
unsigned int valid_cookie_life;
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index e900072950cb..671953e11575 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -24,6 +24,12 @@
#include <net/nfc/nfc.h>
+struct nfc_phy_ops {
+ int (*write)(void *dev_id, struct sk_buff *skb);
+ int (*enable)(void *dev_id);
+ void (*disable)(void *dev_id);
+};
+
struct nfc_hci_dev;
struct nfc_hci_ops {
@@ -38,15 +44,21 @@ struct nfc_hci_ops {
int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*start_poll) (struct nfc_hci_dev *hdev,
u32 im_protocols, u32 tm_protocols);
+ int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
+ u8 comm_mode, u8 *gb, size_t gb_len);
+ int (*dep_link_down)(struct nfc_hci_dev *hdev);
int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
- int (*data_exchange) (struct nfc_hci_dev *hdev,
+ int (*im_transceive) (struct nfc_hci_dev *hdev,
struct nfc_target *target, struct sk_buff *skb,
data_exchange_cb_t cb, void *cb_context);
+ int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*check_presence)(struct nfc_hci_dev *hdev,
struct nfc_target *target);
+ void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+ struct sk_buff *skb);
};
/* Pipes */
@@ -114,6 +126,9 @@ struct nfc_hci_dev {
int async_cb_type;
data_exchange_cb_t async_cb;
void *async_cb_context;
+
+ u8 *gb;
+ size_t gb_len;
};
/* hci device allocation */
@@ -134,6 +149,8 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
+int nfc_hci_result_to_errno(u8 result);
+
/* Host IDs */
#define NFC_HCI_HOST_CONTROLLER_ID 0x00
#define NFC_HCI_TERMINAL_HOST_ID 0x01
@@ -219,5 +236,7 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
const u8 *param, size_t param_len);
int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
const u8 *param, size_t param_len);
+int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate);
+u32 nfc_hci_sak_to_protocol(u8 sak);
#endif /* __NET_HCI_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index f05b10682c9d..fce80b2f9be7 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -95,7 +95,7 @@ struct nfc_genl_data {
};
struct nfc_dev {
- unsigned int idx;
+ int idx;
u32 target_next_idx;
struct nfc_target *targets;
int n_targets;
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 929528c73fe8..047c0476c0a0 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -25,9 +25,11 @@
#define _PROTOCOL_H
#include <linux/in6.h>
+#include <linux/skbuff.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
+#include <linux/netdevice.h>
/* This is one larger than the largest protocol value that can be
* found in an ipv4 or ipv6 header. Since in both cases the protocol
@@ -40,12 +42,6 @@ struct net_protocol {
void (*early_demux)(struct sk_buff *skb);
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
- int (*gso_send_check)(struct sk_buff *skb);
- struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- netdev_features_t features);
- struct sk_buff **(*gro_receive)(struct sk_buff **head,
- struct sk_buff *skb);
- int (*gro_complete)(struct sk_buff *skb);
unsigned int no_policy:1,
netns_ok:1;
};
@@ -60,23 +56,20 @@ struct inet6_protocol {
struct inet6_skb_parm *opt,
u8 type, u8 code, int offset,
__be32 info);
-
- int (*gso_send_check)(struct sk_buff *skb);
- struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- netdev_features_t features);
- struct sk_buff **(*gro_receive)(struct sk_buff **head,
- struct sk_buff *skb);
- int (*gro_complete)(struct sk_buff *skb);
-
unsigned int flags; /* INET6_PROTO_xxx */
};
#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
-/* This should be set for any extension header which is compatible with GSO. */
-#define INET6_PROTO_GSO_EXTHDR 0x4
#endif
+struct net_offload {
+ struct offload_callbacks callbacks;
+ unsigned int flags; /* Flags used by IPv6 for now */
+};
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x1
+
/* This is used to register socket interfaces for IP protocols. */
struct inet_protosw {
struct list_head list;
@@ -96,6 +89,8 @@ struct inet_protosw {
#define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? */
extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
#if IS_ENABLED(CONFIG_IPV6)
extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
@@ -103,6 +98,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num);
extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern int inet_add_offload(const struct net_offload *prot, unsigned char num);
+extern int inet_del_offload(const struct net_offload *prot, unsigned char num);
extern void inet_register_protosw(struct inet_protosw *p);
extern void inet_unregister_protosw(struct inet_protosw *p);
@@ -112,5 +109,7 @@ extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char n
extern int inet6_register_protosw(struct inet_protosw *p);
extern void inet6_unregister_protosw(struct inet_protosw *p);
#endif
+extern int inet6_add_offload(const struct net_offload *prot, unsigned char num);
+extern int inet6_del_offload(const struct net_offload *prot, unsigned char num);
#endif /* _PROTOCOL_H */
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index b01d8dd9ee7c..a51dbd17c2de 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -49,13 +49,16 @@ struct request_sock_ops {
struct request_sock *req);
};
+extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
+
/* struct request_sock - mini sock to represent a connection request
*/
struct request_sock {
struct request_sock *dl_next; /* Must be first member! */
u16 mss;
- u8 retrans;
- u8 cookie_ts; /* syncookie: encode tcpopts in timestamp */
+ u8 num_retrans; /* number of retransmits */
+ u8 cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
+ u8 num_timeout:7; /* number of timeouts */
/* The following two fields can be easily recomputed I think -AK */
u32 window_clamp; /* window clamp at creation time */
u32 rcv_wnd; /* rcv_wnd offered first time */
@@ -231,7 +234,7 @@ static inline int reqsk_queue_removed(struct request_sock_queue *queue,
{
struct listen_sock *lopt = queue->listen_opt;
- if (req->retrans == 0)
+ if (req->num_timeout == 0)
--lopt->qlen_young;
return --lopt->qlen;
@@ -269,7 +272,8 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
struct listen_sock *lopt = queue->listen_opt;
req->expires = jiffies + timeout;
- req->retrans = 0;
+ req->num_retrans = 0;
+ req->num_timeout = 0;
req->sk = NULL;
req->dl_next = lopt->syn_table[hash];
diff --git a/include/net/route.h b/include/net/route.h
index bc40b633a5c4..2ea40c1b5e00 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -198,10 +198,13 @@ struct in_ifaddr;
extern void fib_add_ifaddr(struct in_ifaddr *);
extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
-static inline void ip_rt_put(struct rtable * rt)
+static inline void ip_rt_put(struct rtable *rt)
{
- if (rt)
- dst_release(&rt->dst);
+ /* dst_release() accepts a NULL parameter.
+ * We rely on dst being first structure in struct rtable
+ */
+ BUILD_BUG_ON(offsetof(struct rtable, dst) != 0);
+ dst_release(&rt->dst);
}
#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 6b00c4fc4291..5a15fabd6a75 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -125,7 +125,7 @@ extern void rtnl_af_unregister(struct rtnl_af_ops *ops);
extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
-extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+extern struct net_device *rtnl_create_link(struct net *net,
char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
extern int rtnl_configure_link(struct net_device *dev,
const struct ifinfomsg *ifm);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 4616f468d599..1540f9c2fcf4 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -50,6 +50,13 @@ struct Qdisc {
#define TCQ_F_INGRESS 2
#define TCQ_F_CAN_BYPASS 4
#define TCQ_F_MQROOT 8
+#define TCQ_F_ONETXQUEUE 0x10 /* dequeue_skb() can assume all skbs are for
+ * q->dev_queue : It can test
+ * netif_xmit_frozen_or_stopped() before
+ * dequeueing next packet.
+ * Its true for MQ/MQPRIO slaves, or non
+ * multiqueue device.
+ */
#define TCQ_F_WARN_NONWC (1 << 16)
int padded;
const struct Qdisc_ops *ops;
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 712b3bebeda7..35247271e557 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -130,8 +130,6 @@ typedef union {
__be16 err;
sctp_state_t state;
sctp_event_timeout_t to;
- unsigned long zero;
- void *ptr;
struct sctp_chunk *chunk;
struct sctp_association *asoc;
struct sctp_transport *transport;
@@ -154,23 +152,15 @@ typedef union {
* which takes an __s32 and returns a sctp_arg_t containing the
* __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg.
*/
-static inline sctp_arg_t SCTP_NULL(void)
-{
- sctp_arg_t retval; retval.ptr = NULL; return retval;
-}
-static inline sctp_arg_t SCTP_NOFORCE(void)
-{
- sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
-}
-static inline sctp_arg_t SCTP_FORCE(void)
-{
- sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
-}
#define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
static inline sctp_arg_t \
SCTP_## name (type arg) \
-{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
+{ sctp_arg_t retval;\
+ memset(&retval, 0, sizeof(sctp_arg_t));\
+ retval.elt = arg;\
+ return retval;\
+}
SCTP_ARG_CONSTRUCTOR(I32, __s32, i32)
SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
-SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk)
SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg)
+static inline sctp_arg_t SCTP_FORCE(void)
+{
+ return SCTP_I32(1);
+}
+
+static inline sctp_arg_t SCTP_NOFORCE(void)
+{
+ return SCTP_I32(0);
+}
+
+static inline sctp_arg_t SCTP_NULL(void)
+{
+ sctp_arg_t retval;
+ memset(&retval, 0, sizeof(sctp_arg_t));
+ return retval;
+}
+
typedef struct {
sctp_arg_t obj;
sctp_verb_t verb;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index d053d2e99876..c29707d654c0 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -312,14 +312,6 @@ enum { SCTP_MAX_GABS = 16 };
* functions simpler to write.
*/
-#if defined (CONFIG_SCTP_HMAC_MD5)
-#define SCTP_COOKIE_HMAC_ALG "hmac(md5)"
-#elif defined (CONFIG_SCTP_HMAC_SHA1)
-#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)"
-#else
-#define SCTP_COOKIE_HMAC_ALG NULL
-#endif
-
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 9c6414f553f9..7fdf298a47ef 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -272,6 +272,18 @@ struct sctp_mib {
unsigned long mibs[SCTP_MIB_MAX];
};
+/* helper function to track stats about max rto and related transport */
+static inline void sctp_max_rto(struct sctp_association *asoc,
+ struct sctp_transport *trans)
+{
+ if (asoc->stats.max_obs_rto < (__u64)trans->rto) {
+ asoc->stats.max_obs_rto = trans->rto;
+ memset(&asoc->stats.obs_rto_ipaddr, 0,
+ sizeof(struct sockaddr_storage));
+ memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr,
+ trans->af_specific->sockaddr_len);
+ }
+}
/* Print debugging messages. */
#if SCTP_DEBUG
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index b5887e1677e4..2a82d1384706 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -234,6 +234,8 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
const struct sctp_chunk *,
struct sctp_paramhdr *);
+struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *,
+ const struct sctp_chunk *);
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *);
struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 64158aa1bb5f..fdeb85a970fc 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -177,6 +177,7 @@ struct sctp_sock {
/* Access to HMAC transform. */
struct crypto_hash *hmac;
+ char *sctp_hmac_alg;
/* What is our base endpointer? */
struct sctp_endpoint *ep;
@@ -948,6 +949,8 @@ struct sctp_transport {
/* 64-bit random number sent with heartbeat. */
__u64 hb_nonce;
+
+ struct rcu_head rcu;
};
struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
@@ -1311,6 +1314,40 @@ struct sctp_inithdr_host {
__u32 initial_tsn;
};
+/* SCTP_GET_ASSOC_STATS counters */
+struct sctp_priv_assoc_stats {
+ /* Maximum observed rto in the association during subsequent
+ * observations. Value is set to 0 if no RTO measurement took place
+ * The transport where the max_rto was observed is returned in
+ * obs_rto_ipaddr
+ */
+ struct sockaddr_storage obs_rto_ipaddr;
+ __u64 max_obs_rto;
+ /* Total In and Out SACKs received and sent */
+ __u64 isacks;
+ __u64 osacks;
+ /* Total In and Out packets received and sent */
+ __u64 opackets;
+ __u64 ipackets;
+ /* Total retransmitted chunks */
+ __u64 rtxchunks;
+ /* TSN received > next expected */
+ __u64 outofseqtsns;
+ /* Duplicate Chunks received */
+ __u64 idupchunks;
+ /* Gap Ack Blocks received */
+ __u64 gapcnt;
+ /* Unordered data chunks sent and received */
+ __u64 ouodchunks;
+ __u64 iuodchunks;
+ /* Ordered data chunks sent and received */
+ __u64 oodchunks;
+ __u64 iodchunks;
+ /* Control chunks sent and received */
+ __u64 octrlchunks;
+ __u64 ictrlchunks;
+};
+
/* RFC2960
*
* 12. Recommended Transmission Control Block (TCB) Parameters
@@ -1829,6 +1866,8 @@ struct sctp_association {
__u8 need_ecne:1, /* Need to send an ECNE Chunk? */
temp:1; /* Is it a temporary association? */
+
+ struct sctp_priv_assoc_stats stats;
};
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 2e5ee0d8458d..ff1b8ba73ab1 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
/* Perform partial delivery. */
-void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t);
/* Abort the partial delivery. */
void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 1b02d7ad453b..9a0ae091366d 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -107,6 +107,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */
#define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
#define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
+#define SCTP_GET_ASSOC_STATS 112 /* Read only */
/*
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
@@ -719,6 +720,32 @@ struct sctp_getaddrs {
__u8 addrs[0]; /*output, variable size*/
};
+/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
+ * association stats. All stats are counts except sas_maxrto and
+ * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since
+ * the last call. Will return 0 when RTO was not update since last call
+ */
+struct sctp_assoc_stats {
+ sctp_assoc_t sas_assoc_id; /* Input */
+ /* Transport of observed max RTO */
+ struct sockaddr_storage sas_obs_rto_ipaddr;
+ __u64 sas_maxrto; /* Maximum Observed RTO for period */
+ __u64 sas_isacks; /* SACKs received */
+ __u64 sas_osacks; /* SACKs sent */
+ __u64 sas_opackets; /* Packets sent */
+ __u64 sas_ipackets; /* Packets received */
+ __u64 sas_rtxchunks; /* Retransmitted Chunks */
+ __u64 sas_outofseqtsns;/* TSN received > next expected */
+ __u64 sas_idupchunks; /* Dups received (ordered+unordered) */
+ __u64 sas_gapcnt; /* Gap Acknowledgements Received */
+ __u64 sas_ouodchunks; /* Unordered data chunks sent */
+ __u64 sas_iuodchunks; /* Unordered data chunks received */
+ __u64 sas_oodchunks; /* Ordered data chunks sent */
+ __u64 sas_iodchunks; /* Ordered data chunks received */
+ __u64 sas_octrlchunks; /* Control chunks sent */
+ __u64 sas_ictrlchunks; /* Control chunks received */
+};
+
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */
enum sctp_msg_flags {
diff --git a/include/net/sock.h b/include/net/sock.h
index c945fba4f543..93a6745bfdb2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -126,12 +126,17 @@ struct sock;
struct proto;
struct net;
+typedef __u32 __bitwise __portpair;
+typedef __u64 __bitwise __addrpair;
+
/**
* struct sock_common - minimal network layer representation of sockets
* @skc_daddr: Foreign IPv4 addr
* @skc_rcv_saddr: Bound local IPv4 addr
* @skc_hash: hash value used with various protocol lookup tables
* @skc_u16hashes: two u16 hash values used by UDP lookup tables
+ * @skc_dport: placeholder for inet_dport/tw_dport
+ * @skc_num: placeholder for inet_num/tw_num
* @skc_family: network address family
* @skc_state: Connection state
* @skc_reuse: %SO_REUSEADDR setting
@@ -149,16 +154,29 @@ struct net;
* for struct sock and struct inet_timewait_sock.
*/
struct sock_common {
- /* skc_daddr and skc_rcv_saddr must be grouped :
- * cf INET_MATCH() and INET_TW_MATCH()
+ /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned
+ * address on 64bit arches : cf INET_MATCH() and INET_TW_MATCH()
*/
- __be32 skc_daddr;
- __be32 skc_rcv_saddr;
-
+ union {
+ __addrpair skc_addrpair;
+ struct {
+ __be32 skc_daddr;
+ __be32 skc_rcv_saddr;
+ };
+ };
union {
unsigned int skc_hash;
__u16 skc_u16hashes[2];
};
+ /* skc_dport && skc_num must be grouped as well */
+ union {
+ __portpair skc_portpair;
+ struct {
+ __be16 skc_dport;
+ __u16 skc_num;
+ };
+ };
+
unsigned short skc_family;
volatile unsigned char skc_state;
unsigned char skc_reuse;
@@ -213,7 +231,7 @@ struct cg_proto;
* @sk_sndbuf: size of send buffer in bytes
* @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
* %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
- * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+ * @sk_no_check: %SO_NO_CHECK setting, whether or not checkup packets
* @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
* @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
* @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 4af45e33105d..aed42c785153 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -369,7 +369,6 @@ extern void tcp_shutdown (struct sock *sk, int how);
extern void tcp_v4_early_demux(struct sk_buff *skb);
extern int tcp_v4_rcv(struct sk_buff *skb);
-extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t size);
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index 6df30ed1581c..e69de29bb2d1 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -1,10 +0,0 @@
-header-y += asequencer.h
-header-y += asound.h
-header-y += asound_fm.h
-header-y += emu10k1.h
-header-y += hdsp.h
-header-y += hdspm.h
-header-y += sb16_csp.h
-header-y += sfnt_info.h
-header-y += compress_params.h
-header-y += compress_offload.h
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 1505e6d5ef82..75935ce739c5 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -22,294 +22,9 @@
#ifndef __SOUND_ASEQUENCER_H
#define __SOUND_ASEQUENCER_H
-#ifdef __KERNEL__
#include <linux/ioctl.h>
#include <sound/asound.h>
-#endif
-
-/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
-
-/**
- * definition of sequencer event types
- */
-
-/** system messages
- * event data type = #snd_seq_result
- */
-#define SNDRV_SEQ_EVENT_SYSTEM 0
-#define SNDRV_SEQ_EVENT_RESULT 1
-
-/** note messages (channel specific)
- * event data type = #snd_seq_ev_note
- */
-#define SNDRV_SEQ_EVENT_NOTE 5
-#define SNDRV_SEQ_EVENT_NOTEON 6
-#define SNDRV_SEQ_EVENT_NOTEOFF 7
-#define SNDRV_SEQ_EVENT_KEYPRESS 8
-
-/** control messages (channel specific)
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_CONTROLLER 10
-#define SNDRV_SEQ_EVENT_PGMCHANGE 11
-#define SNDRV_SEQ_EVENT_CHANPRESS 12
-#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */
-#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */
-#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
-
-/** synchronisation messages
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */
-#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */
-#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */
-#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */
-#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */
-
-/** timer messages
- * event data type = snd_seq_ev_queue_control
- */
-#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */
-#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */
-#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */
-#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */
-#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */
-#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */
-#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */
-#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */
-#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */
-
-/** others
- * event data type = none
- */
-#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */
-#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */
-#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */
-
-/** echo back, kernel private messages
- * event data type = any type
- */
-#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */
-#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */
-
-/** system status messages (broadcast for subscribers)
- * event data type = snd_seq_addr
- */
-#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */
-#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */
-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */
-#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */
-#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */
-#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */
-
-/** port connection changes
- * event data type = snd_seq_connect
- */
-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
-
-/* 70-89: synthesizer events - obsoleted */
-
-/** user-defined events with fixed length
- * event data type = any
- */
-#define SNDRV_SEQ_EVENT_USR0 90
-#define SNDRV_SEQ_EVENT_USR1 91
-#define SNDRV_SEQ_EVENT_USR2 92
-#define SNDRV_SEQ_EVENT_USR3 93
-#define SNDRV_SEQ_EVENT_USR4 94
-#define SNDRV_SEQ_EVENT_USR5 95
-#define SNDRV_SEQ_EVENT_USR6 96
-#define SNDRV_SEQ_EVENT_USR7 97
-#define SNDRV_SEQ_EVENT_USR8 98
-#define SNDRV_SEQ_EVENT_USR9 99
-
-/* 100-118: instrument layer - obsoleted */
-/* 119-129: reserved */
-
-/* 130-139: variable length events
- * event data type = snd_seq_ev_ext
- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
- */
-#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */
-#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */
-/* 132-134: reserved */
-#define SNDRV_SEQ_EVENT_USR_VAR0 135
-#define SNDRV_SEQ_EVENT_USR_VAR1 136
-#define SNDRV_SEQ_EVENT_USR_VAR2 137
-#define SNDRV_SEQ_EVENT_USR_VAR3 138
-#define SNDRV_SEQ_EVENT_USR_VAR4 139
-
-/* 150-151: kernel events with quote - DO NOT use in user clients */
-#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */
-
-/* 152-191: reserved */
-
-/* 192-254: hardware specific events */
-
-/* 255: special event */
-#define SNDRV_SEQ_EVENT_NONE 255
-
-
-typedef unsigned char snd_seq_event_type_t;
-
-/** event address */
-struct snd_seq_addr {
- unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */
- unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */
-};
-
-/** port connection */
-struct snd_seq_connect {
- struct snd_seq_addr sender;
- struct snd_seq_addr dest;
-};
-
-
-#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */
-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */
-#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */
-#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */
-
- /* event mode flag - NOTE: only 8 bits available! */
-#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */
-#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */
-#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0)
-
-#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */
-#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */
-#define SNDRV_SEQ_TIME_MODE_MASK (1<<1)
-
-#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */
-#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2)
-
-#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */
-#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */
-#define SNDRV_SEQ_PRIORITY_MASK (1<<4)
-
-
- /* note event */
-struct snd_seq_ev_note {
- unsigned char channel;
- unsigned char note;
- unsigned char velocity;
- unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */
- unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */
-};
-
- /* controller event */
-struct snd_seq_ev_ctrl {
- unsigned char channel;
- unsigned char unused1, unused2, unused3; /* pad */
- unsigned int param;
- signed int value;
-};
-
- /* generic set of bytes (12x8 bit) */
-struct snd_seq_ev_raw8 {
- unsigned char d[12]; /* 8 bit value */
-};
-
- /* generic set of integers (3x32 bit) */
-struct snd_seq_ev_raw32 {
- unsigned int d[3]; /* 32 bit value */
-};
-
- /* external stored data */
-struct snd_seq_ev_ext {
- unsigned int len; /* length of data */
- void *ptr; /* pointer to data (note: maybe 64-bit) */
-} __attribute__((packed));
-
-struct snd_seq_result {
- int event; /* processed event type */
- int result;
-};
-
-
-struct snd_seq_real_time {
- unsigned int tv_sec; /* seconds */
- unsigned int tv_nsec; /* nanoseconds */
-};
-
-typedef unsigned int snd_seq_tick_time_t; /* midi ticks */
-
-union snd_seq_timestamp {
- snd_seq_tick_time_t tick;
- struct snd_seq_real_time time;
-};
-
-struct snd_seq_queue_skew {
- unsigned int value;
- unsigned int base;
-};
-
- /* queue timer control */
-struct snd_seq_ev_queue_control {
- unsigned char queue; /* affected queue */
- unsigned char pad[3]; /* reserved */
- union {
- signed int value; /* affected value (e.g. tempo) */
- union snd_seq_timestamp time; /* time */
- unsigned int position; /* sync position */
- struct snd_seq_queue_skew skew;
- unsigned int d32[2];
- unsigned char d8[8];
- } param;
-};
-
- /* quoted event - inside the kernel only */
-struct snd_seq_ev_quote {
- struct snd_seq_addr origin; /* original sender */
- unsigned short value; /* optional data */
- struct snd_seq_event *event; /* quoted event */
-} __attribute__((packed));
-
-
- /* sequencer event */
-struct snd_seq_event {
- snd_seq_event_type_t type; /* event type */
- unsigned char flags; /* event flags */
- char tag;
-
- unsigned char queue; /* schedule queue */
- union snd_seq_timestamp time; /* schedule time */
-
-
- struct snd_seq_addr source; /* source address */
- struct snd_seq_addr dest; /* destination address */
-
- union { /* event data... */
- struct snd_seq_ev_note note;
- struct snd_seq_ev_ctrl control;
- struct snd_seq_ev_raw8 raw8;
- struct snd_seq_ev_raw32 raw32;
- struct snd_seq_ev_ext ext;
- struct snd_seq_ev_queue_control queue;
- union snd_seq_timestamp time;
- struct snd_seq_addr addr;
- struct snd_seq_connect connect;
- struct snd_seq_result result;
- struct snd_seq_ev_quote quote;
- } data;
-};
-
-
-/*
- * bounce event - stored as variable size data
- */
-struct snd_seq_event_bounce {
- int err;
- struct snd_seq_event event;
- /* external data follows here. */
-};
-
-#ifdef __KERNEL__
+#include <uapi/sound/asequencer.h>
/* helper macro */
#define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
@@ -368,311 +83,4 @@ struct snd_seq_event_bounce {
/* queue sync port */
#define snd_seq_queue_sync_port(q) ((q) + 16)
-#endif /* __KERNEL__ */
-
- /* system information */
-struct snd_seq_system_info {
- int queues; /* maximum queues count */
- int clients; /* maximum clients count */
- int ports; /* maximum ports per client */
- int channels; /* maximum channels per port */
- int cur_clients; /* current clients */
- int cur_queues; /* current queues */
- char reserved[24];
-};
-
-
- /* system running information */
-struct snd_seq_running_info {
- unsigned char client; /* client id */
- unsigned char big_endian; /* 1 = big-endian */
- unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */
- unsigned char pad; /* reserved */
- unsigned char reserved[12];
-};
-
-
- /* known client numbers */
-#define SNDRV_SEQ_CLIENT_SYSTEM 0
- /* internal client numbers */
-#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */
-#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */
-
-
- /* client types */
-typedef int __bitwise snd_seq_client_type_t;
-#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
-#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
-#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
-
- /* event filter flags */
-#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */
-#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */
-#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */
-#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */
-
-struct snd_seq_client_info {
- int client; /* client number to inquire */
- snd_seq_client_type_t type; /* client type */
- char name[64]; /* client name */
- unsigned int filter; /* filter flags */
- unsigned char multicast_filter[8]; /* multicast filter bitmap */
- unsigned char event_filter[32]; /* event filter bitmap */
- int num_ports; /* RO: number of ports */
- int event_lost; /* number of lost events */
- char reserved[64]; /* for future use */
-};
-
-
-/* client pool size */
-struct snd_seq_client_pool {
- int client; /* client number to inquire */
- int output_pool; /* outgoing (write) pool size */
- int input_pool; /* incoming (read) pool size */
- int output_room; /* minimum free pool size for select/blocking mode */
- int output_free; /* unused size */
- int input_free; /* unused size */
- char reserved[64];
-};
-
-
-/* Remove events by specified criteria */
-
-#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */
-#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */
-#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */
-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */
-#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */
-#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */
-#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */
-#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */
-#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */
-#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */
-
-struct snd_seq_remove_events {
- unsigned int remove_mode; /* Flags that determine what gets removed */
-
- union snd_seq_timestamp time;
-
- unsigned char queue; /* Queue for REMOVE_DEST */
- struct snd_seq_addr dest; /* Address for REMOVE_DEST */
- unsigned char channel; /* Channel for REMOVE_DEST */
-
- int type; /* For REMOVE_EVENT_TYPE */
- char tag; /* Tag for REMOVE_TAG */
-
- int reserved[10]; /* To allow for future binary compatibility */
-
-};
-
-
- /* known port numbers */
-#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0
-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
-
- /* port capabilities (32 bits) */
-#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */
-#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */
-
-#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2)
-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3)
-
-#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4)
-
-#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */
-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */
-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */
-
- /* port type */
-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */
-
-/* other standards...*/
-#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */
-#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */
-/*...*/
-#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */
-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */
-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */
-#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */
-#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */
-
-/* misc. conditioning flags */
-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0)
-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
-#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
-
-struct snd_seq_port_info {
- struct snd_seq_addr addr; /* client/port numbers */
- char name[64]; /* port name */
-
- unsigned int capability; /* port capability bits */
- unsigned int type; /* port type bits */
- int midi_channels; /* channels per MIDI port */
- int midi_voices; /* voices per MIDI port */
- int synth_voices; /* voices per SYNTH port */
-
- int read_use; /* R/O: subscribers for output (from this port) */
- int write_use; /* R/O: subscribers for input (to this port) */
-
- void *kernel; /* reserved for kernel use (must be NULL) */
- unsigned int flags; /* misc. conditioning */
- unsigned char time_queue; /* queue # for timestamping */
- char reserved[59]; /* for future use */
-};
-
-
-/* queue flags */
-#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */
-
-/* queue information */
-struct snd_seq_queue_info {
- int queue; /* queue id */
-
- /*
- * security settings, only owner of this queue can start/stop timer
- * etc. if the queue is locked for other clients
- */
- int owner; /* client id for owner of the queue */
- unsigned locked:1; /* timing queue locked for other queues */
- char name[64]; /* name of this queue */
- unsigned int flags; /* flags */
- char reserved[60]; /* for future use */
-
-};
-
-/* queue info/status */
-struct snd_seq_queue_status {
- int queue; /* queue id */
- int events; /* read-only - queue size */
- snd_seq_tick_time_t tick; /* current tick */
- struct snd_seq_real_time time; /* current time */
- int running; /* running state of queue */
- int flags; /* various flags */
- char reserved[64]; /* for the future */
-};
-
-
-/* queue tempo */
-struct snd_seq_queue_tempo {
- int queue; /* sequencer queue */
- unsigned int tempo; /* current tempo, us/tick */
- int ppq; /* time resolution, ticks/quarter */
- unsigned int skew_value; /* queue skew */
- unsigned int skew_base; /* queue skew base */
- char reserved[24]; /* for the future */
-};
-
-
-/* sequencer timer sources */
-#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */
-#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */
-#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */
-
-/* queue timer info */
-struct snd_seq_queue_timer {
- int queue; /* sequencer queue */
- int type; /* source timer type */
- union {
- struct {
- struct snd_timer_id id; /* ALSA's timer ID */
- unsigned int resolution; /* resolution in Hz */
- } alsa;
- } u;
- char reserved[64]; /* for the future use */
-};
-
-
-struct snd_seq_queue_client {
- int queue; /* sequencer queue */
- int client; /* sequencer client */
- int used; /* queue is used with this client
- (must be set for accepting events) */
- /* per client watermarks */
- char reserved[64]; /* for future use */
-};
-
-
-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */
-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1)
-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2)
-
-struct snd_seq_port_subscribe {
- struct snd_seq_addr sender; /* sender address */
- struct snd_seq_addr dest; /* destination address */
- unsigned int voices; /* number of voices to be allocated (0 = don't care) */
- unsigned int flags; /* modes */
- unsigned char queue; /* input time-stamp queue (optional) */
- unsigned char pad[3]; /* reserved */
- char reserved[64];
-};
-
-/* type of query subscription */
-#define SNDRV_SEQ_QUERY_SUBS_READ 0
-#define SNDRV_SEQ_QUERY_SUBS_WRITE 1
-
-struct snd_seq_query_subs {
- struct snd_seq_addr root; /* client/port id to be searched */
- int type; /* READ or WRITE */
- int index; /* 0..N-1 */
- int num_subs; /* R/O: number of subscriptions on this port */
- struct snd_seq_addr addr; /* R/O: result */
- unsigned char queue; /* R/O: result */
- unsigned int flags; /* R/O: result */
- char reserved[64]; /* for future use */
-};
-
-
-/*
- * IOCTL commands
- */
-
-#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
-#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer)
-/* XXX
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
-*/
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info)
-
#endif /* __SOUND_ASEQUENCER_H */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index dfe7d441748c..c2dff5369d33 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -19,13 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-
#ifndef __SOUND_ASOUND_H
#define __SOUND_ASOUND_H
-#include <linux/types.h>
-
-#ifdef __KERNEL__
#include <linux/ioctl.h>
#include <linux/time.h>
#include <asm/byteorder.h>
@@ -40,934 +36,5 @@
#endif
#endif
-#endif /* __KERNEL__ **/
-
-/*
- * protocol version
- */
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
- (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
- (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
- SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-/****************************************************************************
- * *
- * Digital audio interface *
- * *
- ****************************************************************************/
-
-struct snd_aes_iec958 {
- unsigned char status[24]; /* AES/IEC958 channel status bits */
- unsigned char subcode[147]; /* AES/IEC958 subcode bits */
- unsigned char pad; /* nothing */
- unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
-};
-
-/****************************************************************************
- * *
- * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
- * *
- ****************************************************************************/
-
-struct snd_cea_861_aud_if {
- unsigned char db1_ct_cc; /* coding type and channel count */
- unsigned char db2_sf_ss; /* sample frequency and size */
- unsigned char db3; /* not used, all zeros */
- unsigned char db4_ca; /* channel allocation code */
- unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
-};
-
-/****************************************************************************
- * *
- * Section for driver hardware dependent interface - /dev/snd/hw? *
- * *
- ****************************************************************************/
-
-#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
- SNDRV_HWDEP_IFACE_OPL2 = 0,
- SNDRV_HWDEP_IFACE_OPL3,
- SNDRV_HWDEP_IFACE_OPL4,
- SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
- SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
- SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
- SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
- SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
- SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
- SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
- SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
- SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
- SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
- SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
- SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
- SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
- SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
- SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
-
- /* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
-};
-
-struct snd_hwdep_info {
- unsigned int device; /* WR: device number */
- int card; /* R: card number */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* hwdep name */
- int iface; /* hwdep interface */
- unsigned char reserved[64]; /* reserved for future */
-};
-
-/* generic DSP loader */
-struct snd_hwdep_dsp_status {
- unsigned int version; /* R: driver-specific version */
- unsigned char id[32]; /* R: driver-specific ID string */
- unsigned int num_dsps; /* R: number of DSP images to transfer */
- unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
- unsigned int chip_ready; /* R: 1 = initialization finished */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-struct snd_hwdep_dsp_image {
- unsigned int index; /* W: DSP index */
- unsigned char name[64]; /* W: ID (e.g. file name) */
- unsigned char __user *image; /* W: binary image */
- size_t length; /* W: size of image in bytes */
- unsigned long driver_data; /* W: driver-specific data */
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-/*****************************************************************************
- * *
- * Digital Audio (PCM) interface - /dev/snd/pcm?? *
- * *
- *****************************************************************************/
-
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
- SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
- SNDRV_PCM_CLASS_MULTI, /* multichannel device */
- SNDRV_PCM_CLASS_MODEM, /* software modem class */
- SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
- /* Don't forget to change the following: */
- SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
- SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
- SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
- /* Don't forget to change the following: */
- SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
- SNDRV_PCM_STREAM_PLAYBACK = 0,
- SNDRV_PCM_STREAM_CAPTURE,
- SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
-#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
-#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
-#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
-#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
-#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
-#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
-#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
-#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
-#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
-#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
-#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
-#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
-#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
-#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
-#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
-#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
-#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
-#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
-#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
-#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
-#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
-#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
-#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
-#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
-#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
-#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
-#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
-#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
-#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
-#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
-#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
-#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
-#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
-#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
-#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
-#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
-#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
-#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
-#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
-#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
-#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
-#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
-#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
-#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
-
-typedef int __bitwise snd_pcm_state_t;
-#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
-#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
-#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
-#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
-#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
-#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
-#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
-#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
-#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
- SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
- SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
- SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
- unsigned char id[16];
- unsigned short id16[8];
- unsigned int id32[4];
-};
-
-struct snd_pcm_info {
- unsigned int device; /* RO/WR (control): device number */
- unsigned int subdevice; /* RO/WR (control): subdevice number */
- int stream; /* RO/WR (control): stream direction */
- int card; /* R: card number */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* name of this device */
- unsigned char subname[32]; /* subdevice name */
- int dev_class; /* SNDRV_PCM_CLASS_* */
- int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- union snd_pcm_sync_id sync; /* hardware synchronization ID */
- unsigned char reserved[64]; /* reserved for future... */
-};
-
-typedef int snd_pcm_hw_param_t;
-#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
-#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
-#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
-#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
-#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
-#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
-#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
-#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
-#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
- * interrupts in us
- */
-#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
- * interrupts
- */
-#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
- * interrupts
- */
-#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
- * buffer
- */
-#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
- * in us
- */
-#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
-#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
-#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
-#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
-
-struct snd_interval {
- unsigned int min, max;
- unsigned int openmin:1,
- openmax:1,
- integer:1,
- empty:1;
-};
-
-#define SNDRV_MASK_MAX 256
-
-struct snd_mask {
- __u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
- unsigned int flags;
- struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
- SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
- struct snd_mask mres[5]; /* reserved masks */
- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
- SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct snd_interval ires[9]; /* reserved intervals */
- unsigned int rmask; /* W: requested masks */
- unsigned int cmask; /* R: changed masks */
- unsigned int info; /* R: Info flags for returned setup */
- unsigned int msbits; /* R: used most significant bits */
- unsigned int rate_num; /* R: rate numerator */
- unsigned int rate_den; /* R: rate denominator */
- snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
- unsigned char reserved[64]; /* reserved for future */
-};
-
-enum {
- SNDRV_PCM_TSTAMP_NONE = 0,
- SNDRV_PCM_TSTAMP_ENABLE,
- SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
- int tstamp_mode; /* timestamp mode */
- unsigned int period_step;
- unsigned int sleep_min; /* min ticks to sleep */
- snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
- snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
- snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
- snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
- snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
- snd_pcm_uframes_t silence_size; /* silence block size */
- snd_pcm_uframes_t boundary; /* pointers wrap point */
- unsigned char reserved[64]; /* reserved for future */
-};
-
-struct snd_pcm_channel_info {
- unsigned int channel;
- __kernel_off_t offset; /* mmap offset */
- unsigned int first; /* offset to first sample in bits */
- unsigned int step; /* samples distance in bits */
-};
-
-struct snd_pcm_status {
- snd_pcm_state_t state; /* stream state */
- struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
- struct timespec tstamp; /* reference timestamp */
- snd_pcm_uframes_t appl_ptr; /* appl ptr */
- snd_pcm_uframes_t hw_ptr; /* hw ptr */
- snd_pcm_sframes_t delay; /* current delay in frames */
- snd_pcm_uframes_t avail; /* number of frames available */
- snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
- snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
- snd_pcm_state_t suspended_state; /* suspended stream state */
- unsigned char reserved[60]; /* must be filled with zero */
-};
-
-struct snd_pcm_mmap_status {
- snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
- int pad1; /* Needed for 64 bit alignment */
- snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
- struct timespec tstamp; /* Timestamp */
- snd_pcm_state_t suspended_state; /* RO: suspended stream state */
-};
-
-struct snd_pcm_mmap_control {
- snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
- snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
-#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
-
-struct snd_pcm_sync_ptr {
- unsigned int flags;
- union {
- struct snd_pcm_mmap_status status;
- unsigned char reserved[64];
- } s;
- union {
- struct snd_pcm_mmap_control control;
- unsigned char reserved[64];
- } c;
-};
-
-struct snd_xferi {
- snd_pcm_sframes_t result;
- void __user *buf;
- snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
- snd_pcm_sframes_t result;
- void __user * __user *bufs;
- snd_pcm_uframes_t frames;
-};
-
-enum {
- SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
- SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
-};
-
-/* channel positions */
-enum {
- SNDRV_CHMAP_UNKNOWN = 0,
- SNDRV_CHMAP_NA, /* N/A, silent */
- SNDRV_CHMAP_MONO, /* mono stream */
- /* this follows the alsa-lib mixer channel value + 3 */
- SNDRV_CHMAP_FL, /* front left */
- SNDRV_CHMAP_FR, /* front right */
- SNDRV_CHMAP_RL, /* rear left */
- SNDRV_CHMAP_RR, /* rear right */
- SNDRV_CHMAP_FC, /* front center */
- SNDRV_CHMAP_LFE, /* LFE */
- SNDRV_CHMAP_SL, /* side left */
- SNDRV_CHMAP_SR, /* side right */
- SNDRV_CHMAP_RC, /* rear center */
- /* new definitions */
- SNDRV_CHMAP_FLC, /* front left center */
- SNDRV_CHMAP_FRC, /* front right center */
- SNDRV_CHMAP_RLC, /* rear left center */
- SNDRV_CHMAP_RRC, /* rear right center */
- SNDRV_CHMAP_FLW, /* front left wide */
- SNDRV_CHMAP_FRW, /* front right wide */
- SNDRV_CHMAP_FLH, /* front left high */
- SNDRV_CHMAP_FCH, /* front center high */
- SNDRV_CHMAP_FRH, /* front right high */
- SNDRV_CHMAP_TC, /* top center */
- SNDRV_CHMAP_TFL, /* top front left */
- SNDRV_CHMAP_TFR, /* top front right */
- SNDRV_CHMAP_TFC, /* top front center */
- SNDRV_CHMAP_TRL, /* top rear left */
- SNDRV_CHMAP_TRR, /* top rear right */
- SNDRV_CHMAP_TRC, /* top rear center */
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
-
-#define SNDRV_CHMAP_POSITION_MASK 0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
-
-#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
-
-/*****************************************************************************
- * *
- * MIDI v1.0 interface *
- * *
- *****************************************************************************/
-
-/*
- * Raw MIDI section - /dev/snd/midi??
- */
-
-#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
- SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
- SNDRV_RAWMIDI_STREAM_INPUT,
- SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
-
-struct snd_rawmidi_info {
- unsigned int device; /* RO/WR (control): device number */
- unsigned int subdevice; /* RO/WR (control): subdevice number */
- int stream; /* WR: stream */
- int card; /* R: card number */
- unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* name of device */
- unsigned char subname[32]; /* name of active or selected subdevice */
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- unsigned char reserved[64]; /* reserved for future use */
-};
-
-struct snd_rawmidi_params {
- int stream;
- size_t buffer_size; /* queue size in bytes */
- size_t avail_min; /* minimum avail bytes for wakeup */
- unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-struct snd_rawmidi_status {
- int stream;
- struct timespec tstamp; /* Timestamp */
- size_t avail; /* available bytes */
- size_t xruns; /* count of overruns since last status (in bytes) */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
-
-/*
- * Timer section - /dev/snd/timer
- */
-
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
- SNDRV_TIMER_CLASS_NONE = -1,
- SNDRV_TIMER_CLASS_SLAVE = 0,
- SNDRV_TIMER_CLASS_GLOBAL,
- SNDRV_TIMER_CLASS_CARD,
- SNDRV_TIMER_CLASS_PCM,
- SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-/* slave timer classes */
-enum {
- SNDRV_TIMER_SCLASS_NONE = 0,
- SNDRV_TIMER_SCLASS_APPLICATION,
- SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
- SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
- SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-/* global timers (device member) */
-#define SNDRV_TIMER_GLOBAL_SYSTEM 0
-#define SNDRV_TIMER_GLOBAL_RTC 1
-#define SNDRV_TIMER_GLOBAL_HPET 2
-#define SNDRV_TIMER_GLOBAL_HRTIMER 3
-
-/* info flags */
-#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
-
-struct snd_timer_id {
- int dev_class;
- int dev_sclass;
- int card;
- int device;
- int subdevice;
-};
-
-struct snd_timer_ginfo {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
- int card; /* card number */
- unsigned char id[64]; /* timer identification */
- unsigned char name[80]; /* timer name */
- unsigned long reserved0; /* reserved for future use */
- unsigned long resolution; /* average period resolution in ns */
- unsigned long resolution_min; /* minimal period resolution in ns */
- unsigned long resolution_max; /* maximal period resolution in ns */
- unsigned int clients; /* active timer clients */
- unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
- unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
- unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned long resolution; /* current period resolution in ns */
- unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
- unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
- unsigned char reserved[32];
-};
-
-struct snd_timer_select {
- struct snd_timer_id id; /* bind to timer ID */
- unsigned char reserved[32]; /* reserved */
-};
-
-struct snd_timer_info {
- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
- int card; /* card number */
- unsigned char id[64]; /* timer identificator */
- unsigned char name[80]; /* timer name */
- unsigned long reserved0; /* reserved for future use */
- unsigned long resolution; /* average period resolution in ns */
- unsigned char reserved[64]; /* reserved */
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
-
-struct snd_timer_params {
- unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */
- unsigned int ticks; /* requested resolution in ticks */
- unsigned int queue_size; /* total size of queue (32-1024) */
- unsigned int reserved0; /* reserved, was: failure locations */
- unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
- unsigned char reserved[60]; /* reserved */
-};
-
-struct snd_timer_status {
- struct timespec tstamp; /* Timestamp - last update */
- unsigned int resolution; /* current period resolution in ns */
- unsigned int lost; /* counter of master tick lost */
- unsigned int overrun; /* count of read queue overruns */
- unsigned int queue; /* used queue size */
- unsigned char reserved[64]; /* reserved */
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
-/* The following four ioctls are changed since 1.0.9 due to confliction */
-#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
-
-struct snd_timer_read {
- unsigned int resolution;
- unsigned int ticks;
-};
-
-enum {
- SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_TICK, /* val = ticks */
- SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_STOP, /* val = 0 */
- SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
- SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
- SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
- SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
- /* master timer events for slave timer instances */
- SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
- SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
- SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
- SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
- SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
- SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
- int event;
- struct timespec tstamp;
- unsigned int val;
-};
-
-/****************************************************************************
- * *
- * Section for driver control interface - /dev/snd/control? *
- * *
- ****************************************************************************/
-
-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
-
-struct snd_ctl_card_info {
- int card; /* card number */
- int pad; /* reserved for future (was type) */
- unsigned char id[16]; /* ID of card (user selectable) */
- unsigned char driver[16]; /* Driver name */
- unsigned char name[32]; /* Short name of soundcard */
- unsigned char longname[80]; /* name + info text about soundcard */
- unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
- unsigned char mixername[80]; /* visual mixer identification */
- unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
-#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
-#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
-#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
-#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
-#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
-#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
-#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
-#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
-#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
-#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
-#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
-#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
-#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
-#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
-#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
-#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
-#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
-/* bits 30 and 31 are obsoleted (for indirect access) */
-
-/* for further details see the ACPI and PCI power management specification */
-#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
-#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
-#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
-#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
-#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
-#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
-
-struct snd_ctl_elem_id {
- unsigned int numid; /* numeric identifier, zero = invalid */
- snd_ctl_elem_iface_t iface; /* interface identifier */
- unsigned int device; /* device/client number */
- unsigned int subdevice; /* subdevice (substream) number */
- unsigned char name[44]; /* ASCII name of item */
- unsigned int index; /* index of item */
-};
-
-struct snd_ctl_elem_list {
- unsigned int offset; /* W: first element ID to get */
- unsigned int space; /* W: count of element IDs to get */
- unsigned int used; /* R: count of element IDs set */
- unsigned int count; /* R: count of all elements */
- struct snd_ctl_elem_id __user *pids; /* R: IDs */
- unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
- struct snd_ctl_elem_id id; /* W: element ID */
- snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
- unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
- unsigned int count; /* count of values */
- __kernel_pid_t owner; /* owner's PID of this control */
- union {
- struct {
- long min; /* R: minimum value */
- long max; /* R: maximum value */
- long step; /* R: step (0 variable) */
- } integer;
- struct {
- long long min; /* R: minimum value */
- long long max; /* R: maximum value */
- long long step; /* R: step (0 variable) */
- } integer64;
- struct {
- unsigned int items; /* R: number of items */
- unsigned int item; /* W: item number */
- char name[64]; /* R: value name */
- __u64 names_ptr; /* W: names list (ELEM_ADD only) */
- unsigned int names_length;
- } enumerated;
- unsigned char reserved[128];
- } value;
- union {
- unsigned short d[4]; /* dimensions */
- unsigned short *d_ptr; /* indirect - obsoleted */
- } dimen;
- unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
- struct snd_ctl_elem_id id; /* W: element ID */
- unsigned int indirect: 1; /* W: indirect access - obsoleted */
- union {
- union {
- long value[128];
- long *value_ptr; /* obsoleted */
- } integer;
- union {
- long long value[64];
- long long *value_ptr; /* obsoleted */
- } integer64;
- union {
- unsigned int item[128];
- unsigned int *item_ptr; /* obsoleted */
- } enumerated;
- union {
- unsigned char data[512];
- unsigned char *data_ptr; /* obsoleted */
- } bytes;
- struct snd_aes_iec958 iec958;
- } value; /* RO */
- struct timespec tstamp;
- unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
- unsigned int numid; /* control element numeric identification */
- unsigned int length; /* in bytes aligned to 4 */
- unsigned int tlv[0]; /* first TLV */
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
-
-/*
- * Read interface.
- */
-
-enum sndrv_ctl_event_type {
- SNDRV_CTL_EVENT_ELEM = 0,
- SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
-#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
-#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
-#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
-#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
-
-struct snd_ctl_event {
- int type; /* event type - SNDRV_CTL_EVENT_* */
- union {
- struct {
- unsigned int mask;
- struct snd_ctl_elem_id id;
- } elem;
- unsigned char data8[60];
- } data;
-};
-
-/*
- * Control names
- */
-
-#define SNDRV_CTL_NAME_NONE ""
-#define SNDRV_CTL_NAME_PLAYBACK "Playback "
-#define SNDRV_CTL_NAME_CAPTURE "Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE ""
-#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
-#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
+#include <uapi/sound/asound.h>
#endif /* __SOUND_ASOUND_H */
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h
index 50a059e7d116..6d9e15ed1dcf 100644
--- a/include/sound/cs4271.h
+++ b/include/sound/cs4271.h
@@ -19,6 +19,7 @@
struct cs4271_platform_data {
int gpio_nreset; /* GPIO driving Reset pin, if any */
+ int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
};
#endif /* __CS4271_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 1a33f48ebe78..f841ba4bacb8 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1,8 +1,3 @@
-#ifndef __SOUND_EMU10K1_H
-#define __SOUND_EMU10K1_H
-
-#include <linux/types.h>
-
/*
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Creative Labs, Inc.
@@ -24,8 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+#ifndef __SOUND_EMU10K1_H
+#define __SOUND_EMU10K1_H
-#ifdef __KERNEL__
#include <sound/pcm.h>
#include <sound/rawmidi.h>
@@ -36,8 +32,10 @@
#include <sound/timer.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
+#include <linux/firmware.h>
#include <asm/io.h>
+#include <uapi/sound/emu10k1.h>
/* ------------------- DEFINES -------------------- */
@@ -1788,6 +1786,8 @@ struct snd_emu10k1 {
unsigned int efx_voices_mask[2];
unsigned int next_free_voice;
+ const struct firmware *firmware;
+
#ifdef CONFIG_PM_SLEEP
unsigned int *saved_ptr;
unsigned int *saved_gpr;
@@ -1796,6 +1796,7 @@ struct snd_emu10k1 {
unsigned int *saved_icode;
unsigned int *p16v_saved;
unsigned int saved_a_iocfg, saved_hcfg;
+ bool suspend;
#endif
};
@@ -1899,350 +1900,4 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_irq *irq);
-#endif /* __KERNEL__ */
-
-/*
- * ---- FX8010 ----
- */
-
-#define EMU10K1_CARD_CREATIVE 0x00000000
-#define EMU10K1_CARD_EMUAPS 0x00000001
-
-#define EMU10K1_FX8010_PCM_COUNT 8
-
-/* instruction set */
-#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */
-#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */
-#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */
-#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */
-#define iMACINT0 0x04 /* R = A + X * Y ; saturation */
-#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */
-#define iACC3 0x06 /* R = A + X + Y ; saturation */
-#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */
-#define iANDXOR 0x08 /* R = (A & X) ^ Y */
-#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */
-#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */
-#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */
-#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
-#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
-#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */
-#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */
-
-/* GPRs */
-#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
-#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
-#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
-#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
- /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
-
-#define C_00000000 0x40
-#define C_00000001 0x41
-#define C_00000002 0x42
-#define C_00000003 0x43
-#define C_00000004 0x44
-#define C_00000008 0x45
-#define C_00000010 0x46
-#define C_00000020 0x47
-#define C_00000100 0x48
-#define C_00010000 0x49
-#define C_00080000 0x4a
-#define C_10000000 0x4b
-#define C_20000000 0x4c
-#define C_40000000 0x4d
-#define C_80000000 0x4e
-#define C_7fffffff 0x4f
-#define C_ffffffff 0x50
-#define C_fffffffe 0x51
-#define C_c0000000 0x52
-#define C_4f1bbcdc 0x53
-#define C_5a7ef9db 0x54
-#define C_00100000 0x55 /* ?? */
-#define GPR_ACCU 0x56 /* ACCUM, accumulator */
-#define GPR_COND 0x57 /* CCR, condition register */
-#define GPR_NOISE0 0x58 /* noise source */
-#define GPR_NOISE1 0x59 /* noise source */
-#define GPR_IRQ 0x5a /* IRQ register */
-#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */
-#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-
-#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-
-#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
-#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
-#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
-#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
-#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
-#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
-#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
-#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
-#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
-#define A_GPR(x) (A_FXGPREGBASE + (x))
-
-/* cc_reg constants */
-#define CC_REG_NORMALIZED C_00000001
-#define CC_REG_BORROW C_00000002
-#define CC_REG_MINUS C_00000004
-#define CC_REG_ZERO C_00000008
-#define CC_REG_SATURATE C_00000010
-#define CC_REG_NONZERO C_00000100
-
-/* FX buses */
-#define FXBUS_PCM_LEFT 0x00
-#define FXBUS_PCM_RIGHT 0x01
-#define FXBUS_PCM_LEFT_REAR 0x02
-#define FXBUS_PCM_RIGHT_REAR 0x03
-#define FXBUS_MIDI_LEFT 0x04
-#define FXBUS_MIDI_RIGHT 0x05
-#define FXBUS_PCM_CENTER 0x06
-#define FXBUS_PCM_LFE 0x07
-#define FXBUS_PCM_LEFT_FRONT 0x08
-#define FXBUS_PCM_RIGHT_FRONT 0x09
-#define FXBUS_MIDI_REVERB 0x0c
-#define FXBUS_MIDI_CHORUS 0x0d
-#define FXBUS_PCM_LEFT_SIDE 0x0e
-#define FXBUS_PCM_RIGHT_SIDE 0x0f
-#define FXBUS_PT_LEFT 0x14
-#define FXBUS_PT_RIGHT 0x15
-
-/* Inputs */
-#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
-#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
-#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */
-#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */
-#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */
-#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */
-#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */
-#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */
-#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */
-#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */
-#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */
-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
-#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */
-#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */
-
-/* Outputs */
-#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */
-#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */
-#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */
-#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */
-#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */
-#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */
-#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */
-#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */
-#define EXTOUT_REAR_L 0x08 /* Rear channel - left */
-#define EXTOUT_REAR_R 0x09 /* Rear channel - right */
-#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */
-#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */
-#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */
-#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */
-#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */
-#define EXTOUT_ACENTER 0x11 /* Analog Center */
-#define EXTOUT_ALFE 0x12 /* Analog LFE */
-
-/* Audigy Inputs */
-#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
-#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
-#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */
-#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */
-#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */
-#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */
-#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */
-#define A_EXTIN_LINE2_R 0x09 /* right */
-#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */
-#define A_EXTIN_ADC_R 0x0b /* right */
-#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */
-#define A_EXTIN_AUX2_R 0x0d /* - right */
-
-/* Audigiy Outputs */
-#define A_EXTOUT_FRONT_L 0x00 /* digital front left */
-#define A_EXTOUT_FRONT_R 0x01 /* right */
-#define A_EXTOUT_CENTER 0x02 /* digital front center */
-#define A_EXTOUT_LFE 0x03 /* digital front lfe */
-#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */
-#define A_EXTOUT_HEADPHONE_R 0x05 /* right */
-#define A_EXTOUT_REAR_L 0x06 /* digital rear left */
-#define A_EXTOUT_REAR_R 0x07 /* right */
-#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */
-#define A_EXTOUT_AFRONT_R 0x09 /* right */
-#define A_EXTOUT_ACENTER 0x0a /* analog center */
-#define A_EXTOUT_ALFE 0x0b /* analog LFE */
-#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */
-#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */
-#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */
-#define A_EXTOUT_AREAR_R 0x0f /* right */
-#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */
-#define A_EXTOUT_AC97_R 0x11 /* right */
-#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R 0x17 /* right */
-#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */
-
-/* Audigy constants */
-#define A_C_00000000 0xc0
-#define A_C_00000001 0xc1
-#define A_C_00000002 0xc2
-#define A_C_00000003 0xc3
-#define A_C_00000004 0xc4
-#define A_C_00000008 0xc5
-#define A_C_00000010 0xc6
-#define A_C_00000020 0xc7
-#define A_C_00000100 0xc8
-#define A_C_00010000 0xc9
-#define A_C_00000800 0xca
-#define A_C_10000000 0xcb
-#define A_C_20000000 0xcc
-#define A_C_40000000 0xcd
-#define A_C_80000000 0xce
-#define A_C_7fffffff 0xcf
-#define A_C_ffffffff 0xd0
-#define A_C_fffffffe 0xd1
-#define A_C_c0000000 0xd2
-#define A_C_4f1bbcdc 0xd3
-#define A_C_5a7ef9db 0xd4
-#define A_C_00100000 0xd5
-#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */
-#define A_GPR_COND 0xd7 /* CCR, condition register */
-#define A_GPR_NOISE0 0xd8 /* noise source */
-#define A_GPR_NOISE1 0xd9 /* noise source */
-#define A_GPR_IRQ 0xda /* IRQ register */
-#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */
-#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */
-
-/* definitions for debug register */
-#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */
-#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */
-#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */
-#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */
-#define EMU10K1_DBG_STEP 0x00004000 /* start single step */
-#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */
-#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */
-
-/* tank memory address line */
-#ifndef __KERNEL__
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */
-#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */
-#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */
-#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */
-#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
-#endif
-
-struct snd_emu10k1_fx8010_info {
- unsigned int internal_tram_size; /* in samples */
- unsigned int external_tram_size; /* in samples */
- char fxbus_names[16][32]; /* names of FXBUSes */
- char extin_names[16][32]; /* names of external inputs */
- char extout_names[32][32]; /* names of external outputs */
- unsigned int gpr_controls; /* count of GPR controls */
-};
-
-#define EMU10K1_GPR_TRANSLATION_NONE 0
-#define EMU10K1_GPR_TRANSLATION_TABLE100 1
-#define EMU10K1_GPR_TRANSLATION_BASS 2
-#define EMU10K1_GPR_TRANSLATION_TREBLE 3
-#define EMU10K1_GPR_TRANSLATION_ONOFF 4
-
-struct snd_emu10k1_fx8010_control_gpr {
- struct snd_ctl_elem_id id; /* full control ID definition */
- unsigned int vcount; /* visible count */
- unsigned int count; /* count of GPR (1..16) */
- unsigned short gpr[32]; /* GPR number(s) */
- unsigned int value[32]; /* initial values */
- unsigned int min; /* minimum range */
- unsigned int max; /* maximum range */
- unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
- const unsigned int *tlv;
-};
-
-/* old ABI without TLV support */
-struct snd_emu10k1_fx8010_control_old_gpr {
- struct snd_ctl_elem_id id;
- unsigned int vcount;
- unsigned int count;
- unsigned short gpr[32];
- unsigned int value[32];
- unsigned int min;
- unsigned int max;
- unsigned int translation;
-};
-
-struct snd_emu10k1_fx8010_code {
- char name[128];
-
- DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
- __u32 __user *gpr_map; /* initializers */
-
- unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
- struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
-
- unsigned int gpr_del_control_count; /* count of GPR controls to remove */
- struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
-
- unsigned int gpr_list_control_count; /* count of GPR controls to list */
- unsigned int gpr_list_control_total; /* total count of GPR controls */
- struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
-
- DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
- __u32 __user *tram_data_map; /* data initializers */
- __u32 __user *tram_addr_map; /* map initializers */
-
- DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
- __u32 __user *code; /* one instruction - 64 bits */
-};
-
-struct snd_emu10k1_fx8010_tram {
- unsigned int address; /* 31.bit == 1 -> external TRAM */
- unsigned int size; /* size in samples (4 bytes) */
- unsigned int *samples; /* pointer to samples (20-bit) */
- /* NULL->clear memory */
-};
-
-struct snd_emu10k1_fx8010_pcm_rec {
- unsigned int substream; /* substream number */
- unsigned int res1; /* reserved */
- unsigned int channels; /* 16-bit channels count, zero = remove this substream */
- unsigned int tram_start; /* ring buffer position in TRAM (in samples) */
- unsigned int buffer_size; /* count of buffered samples */
- unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */
- unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
- unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */
- unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */
- unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */
- unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */
- unsigned char pad; /* reserved */
- unsigned char etram[32]; /* external TRAM address & data (one per channel) */
- unsigned int res2; /* reserved */
-};
-
-#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
-#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
-#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
-#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
-
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
#endif /* __SOUND_EMU10K1_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 6268a4192d5c..45c1981c9ca2 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -71,6 +71,8 @@ struct snd_pcm_ops {
int (*prepare)(struct snd_pcm_substream *substream);
int (*trigger)(struct snd_pcm_substream *substream, int cmd);
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
+ int (*wall_clock)(struct snd_pcm_substream *substream,
+ struct timespec *audio_ts);
int (*copy)(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos,
void __user *buf, snd_pcm_uframes_t count);
@@ -281,6 +283,7 @@ struct snd_pcm_runtime {
unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
+ u64 hw_ptr_wrap; /* offset for hw_ptr due to boundary wrap-around */
/* -- HW params -- */
snd_pcm_access_t access; /* access mode */
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index 7e950560e591..c7c7788005e4 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -1,6 +1,3 @@
-#ifndef __SOUND_SB16_CSP_H
-#define __SOUND_SB16_CSP_H
-
/*
* Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
* Takashi Iwai <tiwai@suse.de>
@@ -22,106 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+#ifndef __SOUND_SB16_CSP_H
+#define __SOUND_SB16_CSP_H
-/* CSP modes */
-#define SNDRV_SB_CSP_MODE_NONE 0x00
-#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */
-#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */
-#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */
-
-/* CSP load flags */
-#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01
-#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02
-
-/* CSP sample width */
-#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01
-#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02
-
-/* CSP channels */
-#define SNDRV_SB_CSP_MONO 0x01
-#define SNDRV_SB_CSP_STEREO 0x02
-
-/* CSP rates */
-#define SNDRV_SB_CSP_RATE_8000 0x01
-#define SNDRV_SB_CSP_RATE_11025 0x02
-#define SNDRV_SB_CSP_RATE_22050 0x04
-#define SNDRV_SB_CSP_RATE_44100 0x08
-#define SNDRV_SB_CSP_RATE_ALL 0x0f
-
-/* CSP running state */
-#define SNDRV_SB_CSP_ST_IDLE 0x00
-#define SNDRV_SB_CSP_ST_LOADED 0x01
-#define SNDRV_SB_CSP_ST_RUNNING 0x02
-#define SNDRV_SB_CSP_ST_PAUSED 0x04
-#define SNDRV_SB_CSP_ST_AUTO 0x08
-#define SNDRV_SB_CSP_ST_QSOUND 0x10
-
-/* maximum QSound value (180 degrees right) */
-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20
-
-/* maximum microcode RIFF file size */
-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000
-
-/* microcode header */
-struct snd_sb_csp_mc_header {
- char codec_name[16]; /* id name of codec */
- unsigned short func_req; /* requested function */
-};
-
-/* microcode to be loaded */
-struct snd_sb_csp_microcode {
- struct snd_sb_csp_mc_header info;
- unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-};
-
-/* start CSP with sample_width in mono/stereo */
-struct snd_sb_csp_start {
- int sample_width; /* sample width, look above */
- int channels; /* channels, look above */
-};
-
-/* CSP information */
-struct snd_sb_csp_info {
- char codec_name[16]; /* id name of codec */
- unsigned short func_nr; /* function number */
- unsigned int acc_format; /* accepted PCM formats */
- unsigned short acc_channels; /* accepted channels */
- unsigned short acc_width; /* accepted sample width */
- unsigned short acc_rates; /* accepted sample rates */
- unsigned short csp_mode; /* CSP mode, see above */
- unsigned short run_channels; /* current channels */
- unsigned short run_width; /* current sample width */
- unsigned short version; /* version id: 0x10 - 0x1f */
- unsigned short state; /* state bits */
-};
-
-/* HWDEP controls */
-/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info)
-/* load microcode to CSP */
-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
- * defined for some architectures like MIPS, and it leads to build errors.
- * (x86 and co have 14-bit size, thus it's valid, though.)
- * As a workaround for skipping the size-limit check, here we don't use the
- * normal _IOW() macro but _IOC() with the manual argument.
- */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \
- _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
-/* unload microcode from CSP */
-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
-/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start)
-/* stop CSP */
-#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
-/* pause CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15)
-/* restart CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16)
-
-#ifdef __KERNEL__
#include <sound/sb.h>
#include <sound/hwdep.h>
#include <linux/firmware.h>
+#include <uapi/sound/sb16_csp.h>
struct snd_sb_csp;
@@ -183,6 +87,4 @@ struct snd_sb_csp {
};
int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
-#endif
-
#endif /* __SOUND_SB16_CSP */
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 906010344dd7..cc1c919c6436 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -26,6 +26,7 @@
* A: inversion
* B: format mode
* C: chip specific
+ * D: clock selecter if master mode
*/
/* A: clock inversion */
@@ -44,6 +45,11 @@
#define SH_FSI_OPTION_MASK 0x00000F00
#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */
+/* D: clock selecter if master mode */
+#define SH_FSI_CLK_MASK 0x0000F000
+#define SH_FSI_CLK_EXTERNAL (0 << 12)
+#define SH_FSI_CLK_CPG (1 << 12) /* FSIxCK + FSI-DIV */
+
/*
* set_rate return value
*
diff --git a/include/sound/tlv320aic32x4.h b/include/sound/tlv320aic32x4.h
index c009f70b4029..24e5d991f148 100644
--- a/include/sound/tlv320aic32x4.h
+++ b/include/sound/tlv320aic32x4.h
@@ -26,6 +26,7 @@ struct aic32x4_pdata {
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
+ int rstn_gpio;
};
#endif
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 4f67c762cd74..f634f8f85db5 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -27,12 +27,6 @@
#include <sound/hwdep.h>
#include <linux/interrupt.h>
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_VXLOADER) && !defined(CONFIG_SND_VX_LIB) /* built-in kernel */
-#define SND_VX_FW_LOADER /* use the standard firmware loader */
-#endif
-#endif
-
struct firmware;
struct device;
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index b1bea03274d5..2d32d073a6f9 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -43,6 +43,7 @@
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 19e765fbfef7..4e67194fd2c3 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -258,6 +258,7 @@ header-y += neighbour.h
header-y += net.h
header-y += net_dropmon.h
header-y += net_tstamp.h
+header-y += netconf.h
header-y += netdevice.h
header-y += netfilter.h
header-y += netfilter_arp.h
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index d3eaaaf1009e..be8c41e2dc15 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -500,13 +500,15 @@ union ethtool_flow_union {
struct ethtool_ah_espip4_spec esp_ip4_spec;
struct ethtool_usrip4_spec usr_ip4_spec;
struct ethhdr ether_spec;
- __u8 hdata[60];
+ __u8 hdata[52];
};
struct ethtool_flow_ext {
- __be16 vlan_etype;
- __be16 vlan_tci;
- __be32 data[2];
+ __u8 padding[2];
+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
+ __be16 vlan_etype;
+ __be16 vlan_tci;
+ __be32 data[2];
};
/**
@@ -1027,6 +1029,7 @@ enum ethtool_sfeatures_retval_bits {
#define ETHER_FLOW 0x12 /* spec only (ether_spec) */
/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
#define FLOW_EXT 0x80000000
+#define FLOW_MAC_EXT 0x40000000
/* L3-L4 network traffic flow hash options */
#define RXH_L2DA (1 << 1)
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h
index 3d7922433aba..9cfde6941099 100644
--- a/include/uapi/linux/filter.h
+++ b/include/uapi/linux/filter.h
@@ -127,7 +127,9 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
#define SKF_AD_RXHASH 32
#define SKF_AD_CPU 36
#define SKF_AD_ALU_XOR_X 40
-#define SKF_AD_MAX 44
+#define SKF_AD_VLAN_TAG 44
+#define SKF_AD_VLAN_TAG_PRESENT 48
+#define SKF_AD_MAX 52
#define SKF_NET_OFF (-0x100000)
#define SKF_LL_OFF (-0x200000)
diff --git a/include/uapi/linux/hdlc/Kbuild b/include/uapi/linux/hdlc/Kbuild
index aafaa5aa54d4..8c1d2cb75e33 100644
--- a/include/uapi/linux/hdlc/Kbuild
+++ b/include/uapi/linux/hdlc/Kbuild
@@ -1 +1,2 @@
# UAPI Header export list
+header-y += ioctl.h
diff --git a/include/linux/hdlc/ioctl.h b/include/uapi/linux/hdlc/ioctl.h
index 583972364357..04bc0274a189 100644
--- a/include/linux/hdlc/ioctl.h
+++ b/include/uapi/linux/hdlc/ioctl.h
@@ -34,13 +34,15 @@
#define LMI_CCITT 3 /* ITU-T Annex A */
#define LMI_CISCO 4 /* The "original" LMI, aka Gang of Four */
-typedef struct {
+#ifndef __ASSEMBLY__
+
+typedef struct {
unsigned int clock_rate; /* bits per second */
unsigned int clock_type; /* internal, external, TX-internal etc. */
unsigned short loopback;
} sync_serial_settings; /* V.35, V.24, X.21 */
-typedef struct {
+typedef struct {
unsigned int clock_rate; /* bits per second */
unsigned int clock_type; /* internal, external, TX-internal etc. */
unsigned short loopback;
@@ -78,4 +80,5 @@ typedef struct {
/* PPP doesn't need any info now - supply length = 0 to ioctl */
+#endif /* __ASSEMBLY__ */
#endif /* __HDLC_IOCTL_H__ */
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index a8fe9549ddbc..afbb18a0227c 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -97,5 +97,86 @@ struct __fdb_entry {
__u16 unused;
};
+/* Bridge Flags */
+#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */
+#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */
+
+#define BRIDGE_MODE_VEB 0 /* Default loopback mode */
+#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */
+
+/* Bridge management nested attributes
+ * [IFLA_AF_SPEC] = {
+ * [IFLA_BRIDGE_FLAGS]
+ * [IFLA_BRIDGE_MODE]
+ * }
+ */
+enum {
+ IFLA_BRIDGE_FLAGS,
+ IFLA_BRIDGE_MODE,
+ __IFLA_BRIDGE_MAX,
+};
+#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
+
+/* Bridge multicast database attributes
+ * [MDBA_MDB] = {
+ * [MDBA_MDB_ENTRY] = {
+ * [MDBA_MDB_ENTRY_INFO]
+ * }
+ * }
+ * [MDBA_ROUTER] = {
+ * [MDBA_ROUTER_PORT]
+ * }
+ */
+enum {
+ MDBA_UNSPEC,
+ MDBA_MDB,
+ MDBA_ROUTER,
+ __MDBA_MAX,
+};
+#define MDBA_MAX (__MDBA_MAX - 1)
+
+enum {
+ MDBA_MDB_UNSPEC,
+ MDBA_MDB_ENTRY,
+ __MDBA_MDB_MAX,
+};
+#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1)
+
+enum {
+ MDBA_MDB_ENTRY_UNSPEC,
+ MDBA_MDB_ENTRY_INFO,
+ __MDBA_MDB_ENTRY_MAX,
+};
+#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1)
+
+enum {
+ MDBA_ROUTER_UNSPEC,
+ MDBA_ROUTER_PORT,
+ __MDBA_ROUTER_MAX,
+};
+#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1)
+
+struct br_port_msg {
+ __u8 family;
+ __u32 ifindex;
+};
+
+struct br_mdb_entry {
+ __u32 ifindex;
+ struct {
+ union {
+ __be32 ip4;
+ struct in6_addr ip6;
+ } u;
+ __be16 proto;
+ } addr;
+};
+
+enum {
+ MDBA_SET_ENTRY_UNSPEC,
+ MDBA_SET_ENTRY,
+ __MDBA_SET_ENTRY_MAX,
+};
+#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1)
#endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 0343e1f0582c..67fb87ca1094 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -48,6 +48,7 @@
#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */
#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_BATMAN 0x4305 /* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 5c80cb11518b..60f3b6b90602 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -205,6 +205,24 @@ enum {
#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
+enum {
+ BRIDGE_MODE_UNSPEC,
+ BRIDGE_MODE_HAIRPIN,
+};
+
+enum {
+ IFLA_BRPORT_UNSPEC,
+ IFLA_BRPORT_STATE, /* Spanning tree state */
+ IFLA_BRPORT_PRIORITY, /* " priority */
+ IFLA_BRPORT_COST, /* " cost */
+ IFLA_BRPORT_MODE, /* mode (hairpin) */
+ IFLA_BRPORT_GUARD, /* bpdu guard */
+ IFLA_BRPORT_PROTECT, /* root port protection */
+ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */
+ __IFLA_BRPORT_MAX
+};
+#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
+
struct ifla_cacheinfo {
__u32 max_reasm_len;
__u32 tstamp; /* ipv6InterfaceTable updated timestamp */
@@ -285,6 +303,10 @@ enum {
IFLA_VXLAN_AGEING,
IFLA_VXLAN_LIMIT,
IFLA_VXLAN_PORT_RANGE,
+ IFLA_VXLAN_PROXY,
+ IFLA_VXLAN_RSC,
+ IFLA_VXLAN_L2MISS,
+ IFLA_VXLAN_L3MISS,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index f3799295d231..f9a60375f0d0 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -50,6 +50,7 @@ struct sockaddr_ll {
#define PACKET_TX_TIMESTAMP 16
#define PACKET_TIMESTAMP 17
#define PACKET_FANOUT 18
+#define PACKET_TX_HAS_OFF 19
#define PACKET_FANOUT_HASH 0
#define PACKET_FANOUT_LB 1
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 25a585ce23e6..2835b85fd46d 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -31,9 +31,11 @@
#define TUN_FASYNC 0x0010
#define TUN_NOCHECKSUM 0x0020
#define TUN_NO_PI 0x0040
+/* This flag has no real effect */
#define TUN_ONE_QUEUE 0x0080
#define TUN_PERSIST 0x0100
#define TUN_VNET_HDR 0x0200
+#define TUN_TAP_MQ 0x0400
/* Ioctl defines */
#define TUNSETNOCSUM _IOW('T', 200, int)
@@ -53,14 +55,19 @@
#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
#define TUNGETVNETHDRSZ _IOR('T', 215, int)
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
+#define TUNSETQUEUE _IOW('T', 217, int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
#define IFF_TAP 0x0002
#define IFF_NO_PI 0x1000
+/* This flag has no real effect */
#define IFF_ONE_QUEUE 0x2000
#define IFF_VNET_HDR 0x4000
#define IFF_TUN_EXCL 0x8000
+#define IFF_MULTI_QUEUE 0x0100
+#define IFF_ATTACH_QUEUE 0x0200
+#define IFF_DETACH_QUEUE 0x0400
/* Features for GSO (TUNSETOFFLOAD). */
#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 5db5942575fe..aee73d0611fb 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -37,6 +37,26 @@ struct ip_tunnel_parm {
struct iphdr iph;
};
+enum {
+ IFLA_IPTUN_UNSPEC,
+ IFLA_IPTUN_LINK,
+ IFLA_IPTUN_LOCAL,
+ IFLA_IPTUN_REMOTE,
+ IFLA_IPTUN_TTL,
+ IFLA_IPTUN_TOS,
+ IFLA_IPTUN_ENCAP_LIMIT,
+ IFLA_IPTUN_FLOWINFO,
+ IFLA_IPTUN_FLAGS,
+ IFLA_IPTUN_PROTO,
+ IFLA_IPTUN_PMTUDISC,
+ IFLA_IPTUN_6RD_PREFIX,
+ IFLA_IPTUN_6RD_RELAY_PREFIX,
+ IFLA_IPTUN_6RD_PREFIXLEN,
+ IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+ __IFLA_IPTUN_MAX,
+};
+#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+
/* SIT-mode i_flags */
#define SIT_ISATAP 0x0001
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index 1e3159989958..f79c3721da6e 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -240,6 +240,7 @@ struct in6_flowlabel_req {
*
* IP6T_SO_GET_REVISION_MATCH 68
* IP6T_SO_GET_REVISION_TARGET 69
+ * IP6T_SO_ORIGINAL_DST 80
*/
/* RFC5014: Source address selection */
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 8c469af939aa..bbde90fa5838 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -109,9 +109,10 @@ enum {
INET_DIAG_TOS,
INET_DIAG_TCLASS,
INET_DIAG_SKMEMINFO,
+ INET_DIAG_SHUTDOWN,
};
-#define INET_DIAG_MAX INET_DIAG_SKMEMINFO
+#define INET_DIAG_MAX INET_DIAG_SHUTDOWN
/* INET_DIAG_MEM */
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 558828590a69..935119c698ac 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -851,6 +851,7 @@ struct input_keymap_entry {
#define MSC_GESTURE 0x02
#define MSC_RAW 0x03
#define MSC_SCAN 0x04
+#define MSC_TIMESTAMP 0x05
#define MSC_MAX 0x07
#define MSC_CNT (MSC_MAX+1)
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index a6d7d1c536c3..5a2991cf0251 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -157,6 +157,7 @@ enum {
DEVCONF_DISABLE_IPV6,
DEVCONF_ACCEPT_DAD,
DEVCONF_FORCE_TLLAO,
+ DEVCONF_NDISC_NOTIFY,
DEVCONF_MAX
};
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index 0459664c2636..2be7bd174751 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -55,4 +55,7 @@ struct in6_rtmsg {
#define RTMSG_NEWROUTE 0x21
#define RTMSG_DELROUTE 0x22
+#define IP6_RT_PRIO_USER 1024
+#define IP6_RT_PRIO_ADDRCONF 256
+
#endif /* _UAPI_LINUX_IPV6_ROUTE_H */
diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h
new file mode 100644
index 000000000000..64804a798b0c
--- /dev/null
+++ b/include/uapi/linux/netconf.h
@@ -0,0 +1,24 @@
+#ifndef _UAPI_LINUX_NETCONF_H_
+#define _UAPI_LINUX_NETCONF_H_
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct netconfmsg {
+ __u8 ncm_family;
+};
+
+enum {
+ NETCONFA_UNSPEC,
+ NETCONFA_IFINDEX,
+ NETCONFA_FORWARDING,
+ NETCONFA_RP_FILTER,
+ NETCONFA_MC_FORWARDING,
+ __NETCONFA_MAX
+};
+#define NETCONFA_MAX (__NETCONFA_MAX - 1)
+
+#define NETCONFA_IFINDEX_ALL -1
+#define NETCONFA_IFINDEX_DEFAULT -2
+
+#endif /* _UAPI_LINUX_NETCONF_H_ */
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
index 43bfe3e1685b..86e930cf3dfb 100644
--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -9,6 +9,8 @@ enum cntl_msg_types {
IPCTNL_MSG_CT_GET_CTRZERO,
IPCTNL_MSG_CT_GET_STATS_CPU,
IPCTNL_MSG_CT_GET_STATS,
+ IPCTNL_MSG_CT_GET_DYING,
+ IPCTNL_MSG_CT_GET_UNCONFIRMED,
IPCTNL_MSG_MAX
};
diff --git a/include/uapi/linux/netfilter_ipv6/ip6_tables.h b/include/uapi/linux/netfilter_ipv6/ip6_tables.h
index bf1ef65cc582..649c68062dca 100644
--- a/include/uapi/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/uapi/linux/netfilter_ipv6/ip6_tables.h
@@ -178,6 +178,9 @@ struct ip6t_error {
#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5)
#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET
+/* obtain original address if REDIRECT'd connection */
+#define IP6T_SO_ORIGINAL_DST 80
+
/* ICMP matching stuff */
struct ip6t_icmp {
__u8 type; /* type to match */
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index d908d17da56d..0e63cee8d810 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -60,6 +60,13 @@
* target mode.
* @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
* from target mode.
+ * @NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device
+ * @NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for
+ * a device. LTO must be set before the link is up otherwise -EINPROGRESS
+ * is returned. RW and MIUX can be set at anytime and will be passed in
+ * subsequent CONNECT and CC messages.
+ * If one of the passed parameters is wrong none is set and -EINVAL is
+ * returned.
*/
enum nfc_commands {
NFC_CMD_UNSPEC,
@@ -77,6 +84,8 @@ enum nfc_commands {
NFC_EVENT_TARGET_LOST,
NFC_EVENT_TM_ACTIVATED,
NFC_EVENT_TM_DEACTIVATED,
+ NFC_CMD_LLC_GET_PARAMS,
+ NFC_CMD_LLC_SET_PARAMS,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
@@ -102,6 +111,9 @@ enum nfc_commands {
* @NFC_ATTR_RF_MODE: Initiator or target
* @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for
* @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for
+ * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter
+ * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter
+ * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter
*/
enum nfc_attrs {
NFC_ATTR_UNSPEC,
@@ -119,6 +131,9 @@ enum nfc_attrs {
NFC_ATTR_DEVICE_POWERED,
NFC_ATTR_IM_PROTOCOLS,
NFC_ATTR_TM_PROTOCOLS,
+ NFC_ATTR_LLC_PARAM_LTO,
+ NFC_ATTR_LLC_PARAM_RW,
+ NFC_ATTR_LLC_PARAM_MIUX,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7df9b500c804..e3e19f8b16f2 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -118,8 +118,9 @@
* to get a list of all present wiphys.
* @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
* %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
- * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
- * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
+ * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the
+ * attributes determining the channel width; this is used for setting
+ * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT,
* %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
* and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
* However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
@@ -171,7 +172,7 @@
* %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
* %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
* The channel to use can be set on the interface or be given using the
- * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_CHANNEL_TYPE attrs.
+ * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width.
* @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
* @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
* @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -401,8 +402,7 @@
* a response while being associated to an AP on another channel.
* %NL80211_ATTR_IFINDEX is used to specify which interface (and thus
* radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
- * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
- * optionally used to specify additional channel parameters.
+ * frequency for the operation.
* %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
* to remain on the channel. This command is also used as an event to
* notify when the requested duration starts (it may take a while for the
@@ -440,12 +440,11 @@
* as an event indicating reception of a frame that was not processed in
* kernel code, but is for us (i.e., which may need to be processed in a
* user space application). %NL80211_ATTR_FRAME is used to specify the
- * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
- * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
- * which channel the frame is to be transmitted or was received. If this
- * channel is not the current channel (remain-on-channel or the
- * operational channel) the device will switch to the given channel and
- * transmit the frame, optionally waiting for a response for the time
+ * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used
+ * to indicate on which channel the frame is to be transmitted or was
+ * received. If this channel is not the current channel (remain-on-channel
+ * or the operational channel) the device will switch to the given channel
+ * and transmit the frame, optionally waiting for a response for the time
* specified using %NL80211_ATTR_DURATION. When called, this operation
* returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
* TX status event pertaining to the TX request.
@@ -473,8 +472,8 @@
* command is used as an event to indicate the that a trigger level was
* reached.
* @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
- * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
- * by %NL80211_ATTR_IFINDEX) shall operate on.
+ * and the attributes determining channel width) the given interface
+ * (identifed by %NL80211_ATTR_IFINDEX) shall operate on.
* In case multiple channels are supported by the device, the mechanism
* with which it switches channels is implementation-defined.
* When a monitor interface is given, it can only switch channel while
@@ -526,6 +525,12 @@
* of PMKSA caching dandidates.
*
* @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * In addition, this can be used as an event to request userspace to take
+ * actions on TDLS links (set up a new link or tear down an existing one).
+ * In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested
+ * 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_UNEXPECTED_FRAME: Used by an application controlling an AP
@@ -562,8 +567,8 @@
*
* @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
* independently of the userspace SME, send this event indicating
- * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
- * %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
+ * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
+ * attributes determining channel width.
*
* @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
* its %NL80211_ATTR_WDEV identifier. It must have been created with
@@ -578,6 +583,9 @@
* station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON
* is used for this.
*
+ * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames
+ * for IBSS or MESH vif.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -726,6 +734,8 @@ enum nl80211_commands {
NL80211_CMD_CONN_FAILED,
+ NL80211_CMD_SET_MCAST_RATE,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -762,14 +772,26 @@ enum nl80211_commands {
* /sys/class/ieee80211/<phyname>/index
* @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
* @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
- * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
+ * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz,
+ * defines the channel together with the (deprecated)
+ * %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes
+ * %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1
+ * and %NL80211_ATTR_CENTER_FREQ2
+ * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values
+ * of &enum nl80211_chan_width, describing the channel width. See the
+ * documentation of the enum for more information.
+ * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the
+ * channel, used for anything but 20 MHz bandwidth
+ * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the
+ * channel, used only for 80+80 MHz bandwidth
* @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
- * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
+ * if HT20 or HT40 are to be used (i.e., HT disabled if not included):
* NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
* this attribute)
* NL80211_CHAN_HT20 = HT20 only
* NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
* NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
+ * This attribute is now deprecated.
* @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
* less than or equal to the RTS threshold; allowed range: 1..255;
* dot11ShortRetryLimit; u8
@@ -1273,6 +1295,21 @@ enum nl80211_commands {
* the connection request from a station. nl80211_connect_failed_reason
* enum has different reasons of connection failure.
*
+ * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
+ * with the Authentication transaction sequence number field.
+ *
+ * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
+ *
+ * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with
+ * the START_AP and SET_BSS commands
+ * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the
+ * START_AP and SET_BSS commands. This can have the values 0 or 1;
+ * if not given in START_AP 0 is assumed, if not given in SET_BSS
+ * no change is made.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1530,6 +1567,19 @@ enum nl80211_attrs {
NL80211_ATTR_CONN_FAILED_REASON,
+ NL80211_ATTR_SAE_DATA,
+
+ NL80211_ATTR_VHT_CAPABILITY,
+
+ NL80211_ATTR_SCAN_FLAGS,
+
+ NL80211_ATTR_CHANNEL_WIDTH,
+ NL80211_ATTR_CENTER_FREQ1,
+ NL80211_ATTR_CENTER_FREQ2,
+
+ NL80211_ATTR_P2P_CTWINDOW,
+ NL80211_ATTR_P2P_OPPPS,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1573,6 +1623,7 @@ enum nl80211_attrs {
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
#define NL80211_HT_CAPABILITY_LEN 26
+#define NL80211_VHT_CAPABILITY_LEN 12
#define NL80211_MAX_NR_CIPHER_SUITES 5
#define NL80211_MAX_NR_AKM_SUITES 2
@@ -1693,10 +1744,15 @@ struct nl80211_sta_flag_update {
* @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
* @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
* @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
- * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate
* @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
* @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
* @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8)
+ * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8)
+ * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate
+ * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate
+ * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate
* @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/
enum nl80211_rate_info {
@@ -1706,6 +1762,11 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_40_MHZ_WIDTH,
NL80211_RATE_INFO_SHORT_GI,
NL80211_RATE_INFO_BITRATE32,
+ NL80211_RATE_INFO_VHT_MCS,
+ NL80211_RATE_INFO_VHT_NSS,
+ NL80211_RATE_INFO_80_MHZ_WIDTH,
+ NL80211_RATE_INFO_80P80_MHZ_WIDTH,
+ NL80211_RATE_INFO_160_MHZ_WIDTH,
/* keep last */
__NL80211_RATE_INFO_AFTER_LAST,
@@ -2414,6 +2475,15 @@ enum nl80211_ac {
#define NL80211_TXQ_Q_BE NL80211_AC_BE
#define NL80211_TXQ_Q_BK NL80211_AC_BK
+/**
+ * enum nl80211_channel_type - channel type
+ * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel
+ * @NL80211_CHAN_HT20: 20 MHz HT channel
+ * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel
+ * below the control channel
+ * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel
+ * above the control channel
+ */
enum nl80211_channel_type {
NL80211_CHAN_NO_HT,
NL80211_CHAN_HT20,
@@ -2422,6 +2492,32 @@ enum nl80211_channel_type {
};
/**
+ * enum nl80211_chan_width - channel width definitions
+ *
+ * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH
+ * attribute.
+ *
+ * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel
+ * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel
+ * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ * attribute must be provided as well
+ * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ * attribute must be provided as well
+ * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
+ * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ * attribute must be provided as well
+ */
+enum nl80211_chan_width {
+ NL80211_CHAN_WIDTH_20_NOHT,
+ NL80211_CHAN_WIDTH_20,
+ NL80211_CHAN_WIDTH_40,
+ NL80211_CHAN_WIDTH_80,
+ NL80211_CHAN_WIDTH_80P80,
+ NL80211_CHAN_WIDTH_160,
+};
+
+/**
* enum nl80211_bss - netlink attributes for a BSS
*
* @__NL80211_BSS_INVALID: invalid
@@ -2489,6 +2585,7 @@ enum nl80211_bss_status {
* @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
* @__NL80211_AUTHTYPE_NUM: internal
* @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
* @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -2500,6 +2597,7 @@ enum nl80211_auth_type {
NL80211_AUTHTYPE_SHARED_KEY,
NL80211_AUTHTYPE_FT,
NL80211_AUTHTYPE_NETWORK_EAP,
+ NL80211_AUTHTYPE_SAE,
/* keep last */
__NL80211_AUTHTYPE_NUM,
@@ -3028,6 +3126,20 @@ enum nl80211_ap_sme_features {
* in the interface combinations, even when it's only used for scan
* and remain-on-channel. This could be due to, for example, the
* remain-on-channel implementation requiring a channel context.
+ * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
+ * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
+ * mode
+ * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan
+ * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported
+ * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif
+ * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting
+ * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform
+ * OBSS scans and generate 20/40 BSS coex reports. This flag is used only
+ * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied.
+ * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window
+ * setting
+ * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic
+ * powersave
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3035,6 +3147,14 @@ enum nl80211_feature_flags {
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
+ NL80211_FEATURE_SAE = 1 << 5,
+ NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6,
+ NL80211_FEATURE_SCAN_FLUSH = 1 << 7,
+ NL80211_FEATURE_AP_SCAN = 1 << 8,
+ NL80211_FEATURE_VIF_TXPOWER = 1 << 9,
+ NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10,
+ NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
+ NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
};
/**
@@ -3069,4 +3189,25 @@ enum nl80211_connect_failed_reason {
NL80211_CONN_FAIL_BLOCKED_CLIENT,
};
+/**
+ * enum nl80211_scan_flags - scan request control flags
+ *
+ * Scan request control flags are used to control the handling
+ * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN
+ * requests.
+ *
+ * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority
+ * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning
+ * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured
+ * as AP and the beaconing has already been configured. This attribute is
+ * dangerous because will destroy stations performance as a lot of frames
+ * will be lost while scanning off-channel, therefore it must be used only
+ * when really needed
+ */
+enum nl80211_scan_flags {
+ NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
+ NL80211_SCAN_FLAG_FLUSH = 1<<1,
+ NL80211_SCAN_FLAG_AP = 1<<2,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 20ae747ddf34..6b7b6f1e2fd6 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -349,7 +349,7 @@
#define PCI_AF_STATUS_TP 0x01
#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */
-/* PCI-X registers */
+/* PCI-X registers (Type 0 (non-bridge) devices) */
#define PCI_X_CMD 2 /* Modes & Features */
#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
@@ -389,6 +389,19 @@
#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */
#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */
+/* PCI-X registers (Type 1 (bridge) devices) */
+
+#define PCI_X_BRIDGE_SSTATUS 2 /* Secondary Status */
+#define PCI_X_SSTATUS_64BIT 0x0001 /* Secondary AD interface is 64 bits */
+#define PCI_X_SSTATUS_133MHZ 0x0002 /* 133 MHz capable */
+#define PCI_X_SSTATUS_FREQ 0x03c0 /* Secondary Bus Mode and Frequency */
+#define PCI_X_SSTATUS_VERS 0x3000 /* PCI-X Capability Version */
+#define PCI_X_SSTATUS_V1 0x1000 /* Mode 2, not Mode 1 */
+#define PCI_X_SSTATUS_V2 0x2000 /* Mode 1 or Modes 1 and 2 */
+#define PCI_X_SSTATUS_266MHZ 0x4000 /* 266 MHz capable */
+#define PCI_X_SSTATUS_533MHZ 0x8000 /* 533 MHz capable */
+#define PCI_X_BRIDGE_STATUS 4 /* Bridge Status */
+
/* PCI Bridge Subsystem ID registers */
#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */
@@ -456,6 +469,8 @@
#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
#define PCI_EXP_LNKCTL 16 /* Link Control */
#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */
+#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */
+#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */
#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
@@ -544,9 +559,9 @@
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */
-#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
-#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
-#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */
+#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */
+#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */
+#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */
#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 94e981f810a2..b65c834f83e9 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -67,12 +67,26 @@ struct ptp_perout_request {
unsigned int rsv[4]; /* Reserved for future use. */
};
+#define PTP_MAX_SAMPLES 25 /* Maximum allowed offset measurement samples. */
+
+struct ptp_sys_offset {
+ unsigned int n_samples; /* Desired number of measurements. */
+ unsigned int rsv[3]; /* Reserved for future use. */
+ /*
+ * Array of interleaved system/phc time stamps. The kernel
+ * will provide 2*n_samples + 1 time stamps, with the last
+ * one as a system time stamp.
+ */
+ struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
+};
+
#define PTP_CLK_MAGIC '='
#define PTP_CLOCK_GETCAPS _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
#define PTP_EXTTS_REQUEST _IOW(PTP_CLK_MAGIC, 2, struct ptp_extts_request)
#define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
#define PTP_ENABLE_PPS _IOW(PTP_CLK_MAGIC, 4, int)
+#define PTP_SYS_OFFSET _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
struct ptp_extts_event {
struct ptp_clock_time t; /* Time event occured. */
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index fcd768b09f6e..7a5eb196ade9 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -120,6 +120,18 @@ enum {
RTM_SETDCB,
#define RTM_SETDCB RTM_SETDCB
+ RTM_NEWNETCONF = 80,
+#define RTM_NEWNETCONF RTM_NEWNETCONF
+ RTM_GETNETCONF = 82,
+#define RTM_GETNETCONF RTM_GETNETCONF
+
+ RTM_NEWMDB = 84,
+#define RTM_NEWMDB RTM_NEWMDB
+ RTM_DELMDB = 85,
+#define RTM_DELMDB RTM_DELMDB
+ RTM_GETMDB = 86,
+#define RTM_GETMDB RTM_GETMDB
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -222,6 +234,7 @@ enum {
#define RTPROT_XORP 14 /* XORP */
#define RTPROT_NTK 15 /* Netsukuku */
#define RTPROT_DHCP 16 /* DHCP client */
+#define RTPROT_MROUTED 17 /* Multicast daemon */
/* rtm_scope
@@ -283,6 +296,7 @@ enum rtattr_type_t {
RTA_MP_ALGO, /* no longer used */
RTA_TABLE,
RTA_MARK,
+ RTA_MFC_STATS,
__RTA_MAX
};
@@ -403,6 +417,12 @@ struct rta_session {
} u;
};
+struct rta_mfc_stats {
+ __u64 mfcs_packets;
+ __u64 mfcs_bytes;
+ __u64 mfcs_wrong_if;
+};
+
/****
* General form of address family dependent message.
****/
@@ -587,6 +607,12 @@ enum rtnetlink_groups {
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
RTNLGRP_DCB,
#define RTNLGRP_DCB RTNLGRP_DCB
+ RTNLGRP_IPV4_NETCONF,
+#define RTNLGRP_IPV4_NETCONF RTNLGRP_IPV4_NETCONF
+ RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF
+ RTNLGRP_MDB,
+#define RTNLGRP_MDB RTNLGRP_MDB
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
diff --git a/include/uapi/linux/unix_diag.h b/include/uapi/linux/unix_diag.h
index b1d2bf16b33c..b8a24941db21 100644
--- a/include/uapi/linux/unix_diag.h
+++ b/include/uapi/linux/unix_diag.h
@@ -37,6 +37,7 @@ enum {
UNIX_DIAG_ICONS,
UNIX_DIAG_RQLEN,
UNIX_DIAG_MEMINFO,
+ UNIX_DIAG_SHUTDOWN,
UNIX_DIAG_MAX,
};
diff --git a/include/uapi/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h
index 81a927930bfd..f35aa0a338c7 100644
--- a/include/uapi/linux/usb/cdc.h
+++ b/include/uapi/linux/usb/cdc.h
@@ -19,6 +19,7 @@
#define USB_CDC_SUBCLASS_OBEX 0x0b
#define USB_CDC_SUBCLASS_EEM 0x0c
#define USB_CDC_SUBCLASS_NCM 0x0d
+#define USB_CDC_SUBCLASS_MBIM 0x0e
#define USB_CDC_PROTO_NONE 0
@@ -33,6 +34,7 @@
#define USB_CDC_PROTO_EEM 7
#define USB_CDC_NCM_PROTO_NTB 1
+#define USB_CDC_MBIM_PROTO_NTB 2
/*-------------------------------------------------------------------------*/
@@ -53,6 +55,7 @@
#define USB_CDC_DMM_TYPE 0x14
#define USB_CDC_OBEX_TYPE 0x15
#define USB_CDC_NCM_TYPE 0x1a
+#define USB_CDC_MBIM_TYPE 0x1b
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct usb_cdc_header_desc {
@@ -187,6 +190,21 @@ struct usb_cdc_ncm_desc {
__le16 bcdNcmVersion;
__u8 bmNetworkCapabilities;
} __attribute__ ((packed));
+
+/* "MBIM Control Model Functional Descriptor" */
+struct usb_cdc_mbim_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdMBIMVersion;
+ __le16 wMaxControlMessage;
+ __u8 bNumberFilters;
+ __u8 bMaxFilterSize;
+ __le16 wMaxSegmentSize;
+ __u8 bmNetworkCapabilities;
+} __attribute__ ((packed));
+
/*-------------------------------------------------------------------------*/
/*
@@ -332,6 +350,11 @@ struct usb_cdc_ncm_nth32 {
#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */
#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */
+#define USB_CDC_MBIM_NDP16_IPS_SIGN 0x00535049 /* IPS<sessionID> : IPS0 for now */
+#define USB_CDC_MBIM_NDP32_IPS_SIGN 0x00737069 /* ips<sessionID> : ips0 for now */
+#define USB_CDC_MBIM_NDP16_DSS_SIGN 0x00535344 /* DSS<sessionID> */
+#define USB_CDC_MBIM_NDP32_DSS_SIGN 0x00737364 /* dss<sessionID> */
+
/* 16-bit NCM Datagram Pointer Entry */
struct usb_cdc_ncm_dpe16 {
__le16 wDatagramIndex;
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 2470f541af50..848e3584d7c8 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -51,6 +51,8 @@
#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */
#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the
* network */
+#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow
+ * Steering */
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
@@ -60,6 +62,11 @@ struct virtio_net_config {
__u8 mac[6];
/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
__u16 status;
+ /* Maximum number of each of transmit and receive queues;
+ * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
+ * Legal values are between 1 and 0x8000
+ */
+ __u16 max_virtqueue_pairs;
} __attribute__((packed));
/* This is the first element of the scatter-gather list. If you don't
@@ -166,4 +173,24 @@ struct virtio_net_ctrl_mac {
#define VIRTIO_NET_CTRL_ANNOUNCE 3
#define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0
+/*
+ * Control Receive Flow Steering
+ *
+ * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
+ * enables Receive Flow Steering, specifying the number of the transmit and
+ * receive queues that will be used. After the command is consumed and acked by
+ * the device, the device will not steer new packets on receive virtqueues
+ * other than specified nor read from transmit virtqueues other than specified.
+ * Accordingly, driver should not transmit new packets on virtqueues other than
+ * specified.
+ */
+struct virtio_net_ctrl_mq {
+ u16 virtqueue_pairs;
+};
+
+#define VIRTIO_NET_CTRL_MQ 4
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
+
#endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild
index aafaa5aa54d4..0f7d279ebde3 100644
--- a/include/uapi/sound/Kbuild
+++ b/include/uapi/sound/Kbuild
@@ -1 +1,11 @@
# UAPI Header export list
+header-y += asequencer.h
+header-y += asound.h
+header-y += asound_fm.h
+header-y += compress_offload.h
+header-y += compress_params.h
+header-y += emu10k1.h
+header-y += hdsp.h
+header-y += hdspm.h
+header-y += sb16_csp.h
+header-y += sfnt_info.h
diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
new file mode 100644
index 000000000000..09c8a00ea503
--- /dev/null
+++ b/include/uapi/sound/asequencer.h
@@ -0,0 +1,614 @@
+/*
+ * Main header file for the ALSA sequencer
+ * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+ * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_ASEQUENCER_H
+#define _UAPI__SOUND_ASEQUENCER_H
+
+
+/** version of the sequencer */
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
+
+/**
+ * definition of sequencer event types
+ */
+
+/** system messages
+ * event data type = #snd_seq_result
+ */
+#define SNDRV_SEQ_EVENT_SYSTEM 0
+#define SNDRV_SEQ_EVENT_RESULT 1
+
+/** note messages (channel specific)
+ * event data type = #snd_seq_ev_note
+ */
+#define SNDRV_SEQ_EVENT_NOTE 5
+#define SNDRV_SEQ_EVENT_NOTEON 6
+#define SNDRV_SEQ_EVENT_NOTEOFF 7
+#define SNDRV_SEQ_EVENT_KEYPRESS 8
+
+/** control messages (channel specific)
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_CONTROLLER 10
+#define SNDRV_SEQ_EVENT_PGMCHANGE 11
+#define SNDRV_SEQ_EVENT_CHANPRESS 12
+#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */
+#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */
+#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
+
+/** synchronisation messages
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */
+#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */
+#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */
+#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */
+#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */
+
+/** timer messages
+ * event data type = snd_seq_ev_queue_control
+ */
+#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */
+#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */
+#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */
+#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */
+#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */
+#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */
+#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */
+#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */
+#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */
+
+/** others
+ * event data type = none
+ */
+#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */
+#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */
+#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */
+
+/** echo back, kernel private messages
+ * event data type = any type
+ */
+#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */
+#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */
+
+/** system status messages (broadcast for subscribers)
+ * event data type = snd_seq_addr
+ */
+#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */
+#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */
+#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */
+#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */
+#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */
+#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */
+
+/** port connection changes
+ * event data type = snd_seq_connect
+ */
+#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
+#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
+
+/* 70-89: synthesizer events - obsoleted */
+
+/** user-defined events with fixed length
+ * event data type = any
+ */
+#define SNDRV_SEQ_EVENT_USR0 90
+#define SNDRV_SEQ_EVENT_USR1 91
+#define SNDRV_SEQ_EVENT_USR2 92
+#define SNDRV_SEQ_EVENT_USR3 93
+#define SNDRV_SEQ_EVENT_USR4 94
+#define SNDRV_SEQ_EVENT_USR5 95
+#define SNDRV_SEQ_EVENT_USR6 96
+#define SNDRV_SEQ_EVENT_USR7 97
+#define SNDRV_SEQ_EVENT_USR8 98
+#define SNDRV_SEQ_EVENT_USR9 99
+
+/* 100-118: instrument layer - obsoleted */
+/* 119-129: reserved */
+
+/* 130-139: variable length events
+ * event data type = snd_seq_ev_ext
+ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
+ */
+#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */
+#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */
+/* 132-134: reserved */
+#define SNDRV_SEQ_EVENT_USR_VAR0 135
+#define SNDRV_SEQ_EVENT_USR_VAR1 136
+#define SNDRV_SEQ_EVENT_USR_VAR2 137
+#define SNDRV_SEQ_EVENT_USR_VAR3 138
+#define SNDRV_SEQ_EVENT_USR_VAR4 139
+
+/* 150-151: kernel events with quote - DO NOT use in user clients */
+#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */
+
+/* 152-191: reserved */
+
+/* 192-254: hardware specific events */
+
+/* 255: special event */
+#define SNDRV_SEQ_EVENT_NONE 255
+
+
+typedef unsigned char snd_seq_event_type_t;
+
+/** event address */
+struct snd_seq_addr {
+ unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */
+ unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */
+};
+
+/** port connection */
+struct snd_seq_connect {
+ struct snd_seq_addr sender;
+ struct snd_seq_addr dest;
+};
+
+
+#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */
+#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */
+#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */
+#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */
+
+ /* event mode flag - NOTE: only 8 bits available! */
+#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */
+#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */
+#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0)
+
+#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */
+#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */
+#define SNDRV_SEQ_TIME_MODE_MASK (1<<1)
+
+#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */
+#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2)
+
+#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */
+#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */
+#define SNDRV_SEQ_PRIORITY_MASK (1<<4)
+
+
+ /* note event */
+struct snd_seq_ev_note {
+ unsigned char channel;
+ unsigned char note;
+ unsigned char velocity;
+ unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */
+ unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */
+};
+
+ /* controller event */
+struct snd_seq_ev_ctrl {
+ unsigned char channel;
+ unsigned char unused1, unused2, unused3; /* pad */
+ unsigned int param;
+ signed int value;
+};
+
+ /* generic set of bytes (12x8 bit) */
+struct snd_seq_ev_raw8 {
+ unsigned char d[12]; /* 8 bit value */
+};
+
+ /* generic set of integers (3x32 bit) */
+struct snd_seq_ev_raw32 {
+ unsigned int d[3]; /* 32 bit value */
+};
+
+ /* external stored data */
+struct snd_seq_ev_ext {
+ unsigned int len; /* length of data */
+ void *ptr; /* pointer to data (note: maybe 64-bit) */
+} __attribute__((packed));
+
+struct snd_seq_result {
+ int event; /* processed event type */
+ int result;
+};
+
+
+struct snd_seq_real_time {
+ unsigned int tv_sec; /* seconds */
+ unsigned int tv_nsec; /* nanoseconds */
+};
+
+typedef unsigned int snd_seq_tick_time_t; /* midi ticks */
+
+union snd_seq_timestamp {
+ snd_seq_tick_time_t tick;
+ struct snd_seq_real_time time;
+};
+
+struct snd_seq_queue_skew {
+ unsigned int value;
+ unsigned int base;
+};
+
+ /* queue timer control */
+struct snd_seq_ev_queue_control {
+ unsigned char queue; /* affected queue */
+ unsigned char pad[3]; /* reserved */
+ union {
+ signed int value; /* affected value (e.g. tempo) */
+ union snd_seq_timestamp time; /* time */
+ unsigned int position; /* sync position */
+ struct snd_seq_queue_skew skew;
+ unsigned int d32[2];
+ unsigned char d8[8];
+ } param;
+};
+
+ /* quoted event - inside the kernel only */
+struct snd_seq_ev_quote {
+ struct snd_seq_addr origin; /* original sender */
+ unsigned short value; /* optional data */
+ struct snd_seq_event *event; /* quoted event */
+} __attribute__((packed));
+
+
+ /* sequencer event */
+struct snd_seq_event {
+ snd_seq_event_type_t type; /* event type */
+ unsigned char flags; /* event flags */
+ char tag;
+
+ unsigned char queue; /* schedule queue */
+ union snd_seq_timestamp time; /* schedule time */
+
+
+ struct snd_seq_addr source; /* source address */
+ struct snd_seq_addr dest; /* destination address */
+
+ union { /* event data... */
+ struct snd_seq_ev_note note;
+ struct snd_seq_ev_ctrl control;
+ struct snd_seq_ev_raw8 raw8;
+ struct snd_seq_ev_raw32 raw32;
+ struct snd_seq_ev_ext ext;
+ struct snd_seq_ev_queue_control queue;
+ union snd_seq_timestamp time;
+ struct snd_seq_addr addr;
+ struct snd_seq_connect connect;
+ struct snd_seq_result result;
+ struct snd_seq_ev_quote quote;
+ } data;
+};
+
+
+/*
+ * bounce event - stored as variable size data
+ */
+struct snd_seq_event_bounce {
+ int err;
+ struct snd_seq_event event;
+ /* external data follows here. */
+};
+
+
+ /* system information */
+struct snd_seq_system_info {
+ int queues; /* maximum queues count */
+ int clients; /* maximum clients count */
+ int ports; /* maximum ports per client */
+ int channels; /* maximum channels per port */
+ int cur_clients; /* current clients */
+ int cur_queues; /* current queues */
+ char reserved[24];
+};
+
+
+ /* system running information */
+struct snd_seq_running_info {
+ unsigned char client; /* client id */
+ unsigned char big_endian; /* 1 = big-endian */
+ unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */
+ unsigned char pad; /* reserved */
+ unsigned char reserved[12];
+};
+
+
+ /* known client numbers */
+#define SNDRV_SEQ_CLIENT_SYSTEM 0
+ /* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */
+#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */
+
+
+ /* client types */
+typedef int __bitwise snd_seq_client_type_t;
+#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
+#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
+#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
+
+ /* event filter flags */
+#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */
+#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */
+#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */
+#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */
+
+struct snd_seq_client_info {
+ int client; /* client number to inquire */
+ snd_seq_client_type_t type; /* client type */
+ char name[64]; /* client name */
+ unsigned int filter; /* filter flags */
+ unsigned char multicast_filter[8]; /* multicast filter bitmap */
+ unsigned char event_filter[32]; /* event filter bitmap */
+ int num_ports; /* RO: number of ports */
+ int event_lost; /* number of lost events */
+ char reserved[64]; /* for future use */
+};
+
+
+/* client pool size */
+struct snd_seq_client_pool {
+ int client; /* client number to inquire */
+ int output_pool; /* outgoing (write) pool size */
+ int input_pool; /* incoming (read) pool size */
+ int output_room; /* minimum free pool size for select/blocking mode */
+ int output_free; /* unused size */
+ int input_free; /* unused size */
+ char reserved[64];
+};
+
+
+/* Remove events by specified criteria */
+
+#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */
+#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */
+#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */
+#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */
+#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */
+#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */
+#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */
+#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */
+#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */
+#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */
+
+struct snd_seq_remove_events {
+ unsigned int remove_mode; /* Flags that determine what gets removed */
+
+ union snd_seq_timestamp time;
+
+ unsigned char queue; /* Queue for REMOVE_DEST */
+ struct snd_seq_addr dest; /* Address for REMOVE_DEST */
+ unsigned char channel; /* Channel for REMOVE_DEST */
+
+ int type; /* For REMOVE_EVENT_TYPE */
+ char tag; /* Tag for REMOVE_TAG */
+
+ int reserved[10]; /* To allow for future binary compatibility */
+
+};
+
+
+ /* known port numbers */
+#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0
+#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
+
+ /* port capabilities (32 bits) */
+#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */
+#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */
+
+#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2)
+#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3)
+
+#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4)
+
+#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */
+#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */
+#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */
+
+ /* port type */
+#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */
+
+/* other standards...*/
+#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
+#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */
+#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */
+/*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */
+#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */
+
+/* misc. conditioning flags */
+#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
+
+struct snd_seq_port_info {
+ struct snd_seq_addr addr; /* client/port numbers */
+ char name[64]; /* port name */
+
+ unsigned int capability; /* port capability bits */
+ unsigned int type; /* port type bits */
+ int midi_channels; /* channels per MIDI port */
+ int midi_voices; /* voices per MIDI port */
+ int synth_voices; /* voices per SYNTH port */
+
+ int read_use; /* R/O: subscribers for output (from this port) */
+ int write_use; /* R/O: subscribers for input (to this port) */
+
+ void *kernel; /* reserved for kernel use (must be NULL) */
+ unsigned int flags; /* misc. conditioning */
+ unsigned char time_queue; /* queue # for timestamping */
+ char reserved[59]; /* for future use */
+};
+
+
+/* queue flags */
+#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */
+
+/* queue information */
+struct snd_seq_queue_info {
+ int queue; /* queue id */
+
+ /*
+ * security settings, only owner of this queue can start/stop timer
+ * etc. if the queue is locked for other clients
+ */
+ int owner; /* client id for owner of the queue */
+ unsigned locked:1; /* timing queue locked for other queues */
+ char name[64]; /* name of this queue */
+ unsigned int flags; /* flags */
+ char reserved[60]; /* for future use */
+
+};
+
+/* queue info/status */
+struct snd_seq_queue_status {
+ int queue; /* queue id */
+ int events; /* read-only - queue size */
+ snd_seq_tick_time_t tick; /* current tick */
+ struct snd_seq_real_time time; /* current time */
+ int running; /* running state of queue */
+ int flags; /* various flags */
+ char reserved[64]; /* for the future */
+};
+
+
+/* queue tempo */
+struct snd_seq_queue_tempo {
+ int queue; /* sequencer queue */
+ unsigned int tempo; /* current tempo, us/tick */
+ int ppq; /* time resolution, ticks/quarter */
+ unsigned int skew_value; /* queue skew */
+ unsigned int skew_base; /* queue skew base */
+ char reserved[24]; /* for the future */
+};
+
+
+/* sequencer timer sources */
+#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */
+#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */
+#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */
+
+/* queue timer info */
+struct snd_seq_queue_timer {
+ int queue; /* sequencer queue */
+ int type; /* source timer type */
+ union {
+ struct {
+ struct snd_timer_id id; /* ALSA's timer ID */
+ unsigned int resolution; /* resolution in Hz */
+ } alsa;
+ } u;
+ char reserved[64]; /* for the future use */
+};
+
+
+struct snd_seq_queue_client {
+ int queue; /* sequencer queue */
+ int client; /* sequencer client */
+ int used; /* queue is used with this client
+ (must be set for accepting events) */
+ /* per client watermarks */
+ char reserved[64]; /* for future use */
+};
+
+
+#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */
+#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1)
+#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2)
+
+struct snd_seq_port_subscribe {
+ struct snd_seq_addr sender; /* sender address */
+ struct snd_seq_addr dest; /* destination address */
+ unsigned int voices; /* number of voices to be allocated (0 = don't care) */
+ unsigned int flags; /* modes */
+ unsigned char queue; /* input time-stamp queue (optional) */
+ unsigned char pad[3]; /* reserved */
+ char reserved[64];
+};
+
+/* type of query subscription */
+#define SNDRV_SEQ_QUERY_SUBS_READ 0
+#define SNDRV_SEQ_QUERY_SUBS_WRITE 1
+
+struct snd_seq_query_subs {
+ struct snd_seq_addr root; /* client/port id to be searched */
+ int type; /* READ or WRITE */
+ int index; /* 0..N-1 */
+ int num_subs; /* R/O: number of subscriptions on this port */
+ struct snd_seq_addr addr; /* R/O: result */
+ unsigned char queue; /* R/O: result */
+ unsigned int flags; /* R/O: result */
+ char reserved[64]; /* for future use */
+};
+
+
+/*
+ * IOCTL commands
+ */
+
+#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
+#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer)
+/* XXX
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
+*/
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info)
+
+#endif /* _UAPI__SOUND_ASEQUENCER_H */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
new file mode 100644
index 000000000000..1774a5c3ef10
--- /dev/null
+++ b/include/uapi/sound/asound.h
@@ -0,0 +1,971 @@
+/*
+ * Advanced Linux Sound Architecture - ALSA - Driver
+ * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
+ * Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _UAPI__SOUND_ASOUND_H
+#define _UAPI__SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+
+/*
+ * protocol version
+ */
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
+ (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
+ (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
+ SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+/****************************************************************************
+ * *
+ * Digital audio interface *
+ * *
+ ****************************************************************************/
+
+struct snd_aes_iec958 {
+ unsigned char status[24]; /* AES/IEC958 channel status bits */
+ unsigned char subcode[147]; /* AES/IEC958 subcode bits */
+ unsigned char pad; /* nothing */
+ unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
+};
+
+/****************************************************************************
+ * *
+ * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
+ * *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+ unsigned char db1_ct_cc; /* coding type and channel count */
+ unsigned char db2_sf_ss; /* sample frequency and size */
+ unsigned char db3; /* not used, all zeros */
+ unsigned char db4_ca; /* channel allocation code */
+ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ * *
+ * Section for driver hardware dependent interface - /dev/snd/hw? *
+ * *
+ ****************************************************************************/
+
+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+ SNDRV_HWDEP_IFACE_OPL2 = 0,
+ SNDRV_HWDEP_IFACE_OPL3,
+ SNDRV_HWDEP_IFACE_OPL4,
+ SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
+ SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
+ SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
+ SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
+ SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
+ SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
+ SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
+ SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
+ SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
+ SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
+ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
+ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
+ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
+ SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
+
+ /* Don't forget to change the following: */
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+ unsigned int device; /* WR: device number */
+ int card; /* R: card number */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* hwdep name */
+ int iface; /* hwdep interface */
+ unsigned char reserved[64]; /* reserved for future */
+};
+
+/* generic DSP loader */
+struct snd_hwdep_dsp_status {
+ unsigned int version; /* R: driver-specific version */
+ unsigned char id[32]; /* R: driver-specific ID string */
+ unsigned int num_dsps; /* R: number of DSP images to transfer */
+ unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
+ unsigned int chip_ready; /* R: 1 = initialization finished */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+struct snd_hwdep_dsp_image {
+ unsigned int index; /* W: DSP index */
+ unsigned char name[64]; /* W: ID (e.g. file name) */
+ unsigned char __user *image; /* W: binary image */
+ size_t length; /* W: size of image in bytes */
+ unsigned long driver_data; /* W: driver-specific data */
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+/*****************************************************************************
+ * *
+ * Digital Audio (PCM) interface - /dev/snd/pcm?? *
+ * *
+ *****************************************************************************/
+
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+ SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
+ SNDRV_PCM_CLASS_MULTI, /* multichannel device */
+ SNDRV_PCM_CLASS_MODEM, /* software modem class */
+ SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
+ /* Don't forget to change the following: */
+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
+ SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
+ /* Don't forget to change the following: */
+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+ SNDRV_PCM_STREAM_PLAYBACK = 0,
+ SNDRV_PCM_STREAM_CAPTURE,
+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
+#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
+#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
+#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
+#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
+#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
+#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
+#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
+
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+ unsigned char id[16];
+ unsigned short id16[8];
+ unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+ unsigned int device; /* RO/WR (control): device number */
+ unsigned int subdevice; /* RO/WR (control): subdevice number */
+ int stream; /* RO/WR (control): stream direction */
+ int card; /* R: card number */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* name of this device */
+ unsigned char subname[32]; /* subdevice name */
+ int dev_class; /* SNDRV_PCM_CLASS_* */
+ int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ union snd_pcm_sync_id sync; /* hardware synchronization ID */
+ unsigned char reserved[64]; /* reserved for future... */
+};
+
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
+#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
+#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
+ * interrupts in us
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
+ * buffer
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
+ * in us
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
+
+struct snd_interval {
+ unsigned int min, max;
+ unsigned int openmin:1,
+ openmax:1,
+ integer:1,
+ empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+ unsigned int flags;
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+ struct snd_mask mres[5]; /* reserved masks */
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9]; /* reserved intervals */
+ unsigned int rmask; /* W: requested masks */
+ unsigned int cmask; /* R: changed masks */
+ unsigned int info; /* R: Info flags for returned setup */
+ unsigned int msbits; /* R: used most significant bits */
+ unsigned int rate_num; /* R: rate numerator */
+ unsigned int rate_den; /* R: rate denominator */
+ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
+ unsigned char reserved[64]; /* reserved for future */
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_NONE = 0,
+ SNDRV_PCM_TSTAMP_ENABLE,
+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+ int tstamp_mode; /* timestamp mode */
+ unsigned int period_step;
+ unsigned int sleep_min; /* min ticks to sleep */
+ snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
+ snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
+ snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
+ snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
+ snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
+ snd_pcm_uframes_t silence_size; /* silence block size */
+ snd_pcm_uframes_t boundary; /* pointers wrap point */
+ unsigned char reserved[64]; /* reserved for future */
+};
+
+struct snd_pcm_channel_info {
+ unsigned int channel;
+ __kernel_off_t offset; /* mmap offset */
+ unsigned int first; /* offset to first sample in bits */
+ unsigned int step; /* samples distance in bits */
+};
+
+struct snd_pcm_status {
+ snd_pcm_state_t state; /* stream state */
+ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
+ struct timespec tstamp; /* reference timestamp */
+ snd_pcm_uframes_t appl_ptr; /* appl ptr */
+ snd_pcm_uframes_t hw_ptr; /* hw ptr */
+ snd_pcm_sframes_t delay; /* current delay in frames */
+ snd_pcm_uframes_t avail; /* number of frames available */
+ snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
+ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
+ snd_pcm_state_t suspended_state; /* suspended stream state */
+ __u32 reserved_alignment; /* must be filled with zero */
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
+ unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
+};
+
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
+ int pad1; /* Needed for 64 bit alignment */
+ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
+ struct timespec tstamp; /* Timestamp */
+ snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
+};
+
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
+ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
+
+struct snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+ struct snd_pcm_mmap_status status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control control;
+ unsigned char reserved[64];
+ } c;
+};
+
+struct snd_xferi {
+ snd_pcm_sframes_t result;
+ void __user *buf;
+ snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+ snd_pcm_sframes_t result;
+ void __user * __user *bufs;
+ snd_pcm_uframes_t frames;
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+/* channel positions */
+enum {
+ SNDRV_CHMAP_UNKNOWN = 0,
+ SNDRV_CHMAP_NA, /* N/A, silent */
+ SNDRV_CHMAP_MONO, /* mono stream */
+ /* this follows the alsa-lib mixer channel value + 3 */
+ SNDRV_CHMAP_FL, /* front left */
+ SNDRV_CHMAP_FR, /* front right */
+ SNDRV_CHMAP_RL, /* rear left */
+ SNDRV_CHMAP_RR, /* rear right */
+ SNDRV_CHMAP_FC, /* front center */
+ SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_SL, /* side left */
+ SNDRV_CHMAP_SR, /* side right */
+ SNDRV_CHMAP_RC, /* rear center */
+ /* new definitions */
+ SNDRV_CHMAP_FLC, /* front left center */
+ SNDRV_CHMAP_FRC, /* front right center */
+ SNDRV_CHMAP_RLC, /* rear left center */
+ SNDRV_CHMAP_RRC, /* rear right center */
+ SNDRV_CHMAP_FLW, /* front left wide */
+ SNDRV_CHMAP_FRW, /* front right wide */
+ SNDRV_CHMAP_FLH, /* front left high */
+ SNDRV_CHMAP_FCH, /* front center high */
+ SNDRV_CHMAP_FRH, /* front right high */
+ SNDRV_CHMAP_TC, /* top center */
+ SNDRV_CHMAP_TFL, /* top front left */
+ SNDRV_CHMAP_TFR, /* top front right */
+ SNDRV_CHMAP_TFC, /* top front center */
+ SNDRV_CHMAP_TRL, /* top rear left */
+ SNDRV_CHMAP_TRR, /* top rear right */
+ SNDRV_CHMAP_TRC, /* top rear center */
+ /* new definitions for UAC2 */
+ SNDRV_CHMAP_TFLC, /* top front left center */
+ SNDRV_CHMAP_TFRC, /* top front right center */
+ SNDRV_CHMAP_TSL, /* top side left */
+ SNDRV_CHMAP_TSR, /* top side right */
+ SNDRV_CHMAP_LLFE, /* left LFE */
+ SNDRV_CHMAP_RLFE, /* right LFE */
+ SNDRV_CHMAP_BC, /* bottom center */
+ SNDRV_CHMAP_BLC, /* bottom left center */
+ SNDRV_CHMAP_BRC, /* bottom right center */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
+};
+
+#define SNDRV_CHMAP_POSITION_MASK 0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
+
+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
+
+/*****************************************************************************
+ * *
+ * MIDI v1.0 interface *
+ * *
+ *****************************************************************************/
+
+/*
+ * Raw MIDI section - /dev/snd/midi??
+ */
+
+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
+
+struct snd_rawmidi_info {
+ unsigned int device; /* RO/WR (control): device number */
+ unsigned int subdevice; /* RO/WR (control): subdevice number */
+ int stream; /* WR: stream */
+ int card; /* R: card number */
+ unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* name of device */
+ unsigned char subname[32]; /* name of active or selected subdevice */
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ unsigned char reserved[64]; /* reserved for future use */
+};
+
+struct snd_rawmidi_params {
+ int stream;
+ size_t buffer_size; /* queue size in bytes */
+ size_t avail_min; /* minimum avail bytes for wakeup */
+ unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+struct snd_rawmidi_status {
+ int stream;
+ struct timespec tstamp; /* Timestamp */
+ size_t avail; /* available bytes */
+ size_t xruns; /* count of overruns since last status (in bytes) */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
+
+/*
+ * Timer section - /dev/snd/timer
+ */
+
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+ SNDRV_TIMER_CLASS_NONE = -1,
+ SNDRV_TIMER_CLASS_SLAVE = 0,
+ SNDRV_TIMER_CLASS_GLOBAL,
+ SNDRV_TIMER_CLASS_CARD,
+ SNDRV_TIMER_CLASS_PCM,
+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+/* slave timer classes */
+enum {
+ SNDRV_TIMER_SCLASS_NONE = 0,
+ SNDRV_TIMER_SCLASS_APPLICATION,
+ SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+/* global timers (device member) */
+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
+#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
+
+/* info flags */
+#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
+
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
+ int card;
+ int device;
+ int subdevice;
+};
+
+struct snd_timer_ginfo {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
+ int card; /* card number */
+ unsigned char id[64]; /* timer identification */
+ unsigned char name[80]; /* timer name */
+ unsigned long reserved0; /* reserved for future use */
+ unsigned long resolution; /* average period resolution in ns */
+ unsigned long resolution_min; /* minimal period resolution in ns */
+ unsigned long resolution_max; /* maximal period resolution in ns */
+ unsigned int clients; /* active timer clients */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
+ unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned long resolution; /* current period resolution in ns */
+ unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
+ unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+ struct snd_timer_id id; /* bind to timer ID */
+ unsigned char reserved[32]; /* reserved */
+};
+
+struct snd_timer_info {
+ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
+ int card; /* card number */
+ unsigned char id[64]; /* timer identificator */
+ unsigned char name[80]; /* timer name */
+ unsigned long reserved0; /* reserved for future use */
+ unsigned long resolution; /* average period resolution in ns */
+ unsigned char reserved[64]; /* reserved */
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
+
+struct snd_timer_params {
+ unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */
+ unsigned int ticks; /* requested resolution in ticks */
+ unsigned int queue_size; /* total size of queue (32-1024) */
+ unsigned int reserved0; /* reserved, was: failure locations */
+ unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
+ unsigned char reserved[60]; /* reserved */
+};
+
+struct snd_timer_status {
+ struct timespec tstamp; /* Timestamp - last update */
+ unsigned int resolution; /* current period resolution in ns */
+ unsigned int lost; /* counter of master tick lost */
+ unsigned int overrun; /* count of read queue overruns */
+ unsigned int queue; /* used queue size */
+ unsigned char reserved[64]; /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
+
+struct snd_timer_read {
+ unsigned int resolution;
+ unsigned int ticks;
+};
+
+enum {
+ SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_TICK, /* val = ticks */
+ SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_STOP, /* val = 0 */
+ SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
+ SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
+ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
+ SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
+ /* master timer events for slave timer instances */
+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+ int event;
+ struct timespec tstamp;
+ unsigned int val;
+};
+
+/****************************************************************************
+ * *
+ * Section for driver control interface - /dev/snd/control? *
+ * *
+ ****************************************************************************/
+
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
+
+struct snd_ctl_card_info {
+ int card; /* card number */
+ int pad; /* reserved for future (was type) */
+ unsigned char id[16]; /* ID of card (user selectable) */
+ unsigned char driver[16]; /* Driver name */
+ unsigned char name[32]; /* Short name of soundcard */
+ unsigned char longname[80]; /* name + info text about soundcard */
+ unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
+ unsigned char mixername[80]; /* visual mixer identification */
+ unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
+/* bits 30 and 31 are obsoleted (for indirect access) */
+
+/* for further details see the ACPI and PCI power management specification */
+#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
+#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
+#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
+#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
+
+struct snd_ctl_elem_id {
+ unsigned int numid; /* numeric identifier, zero = invalid */
+ snd_ctl_elem_iface_t iface; /* interface identifier */
+ unsigned int device; /* device/client number */
+ unsigned int subdevice; /* subdevice (substream) number */
+ unsigned char name[44]; /* ASCII name of item */
+ unsigned int index; /* index of item */
+};
+
+struct snd_ctl_elem_list {
+ unsigned int offset; /* W: first element ID to get */
+ unsigned int space; /* W: count of element IDs to get */
+ unsigned int used; /* R: count of element IDs set */
+ unsigned int count; /* R: count of all elements */
+ struct snd_ctl_elem_id __user *pids; /* R: IDs */
+ unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id; /* W: element ID */
+ snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+ unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
+ unsigned int count; /* count of values */
+ __kernel_pid_t owner; /* owner's PID of this control */
+ union {
+ struct {
+ long min; /* R: minimum value */
+ long max; /* R: maximum value */
+ long step; /* R: step (0 variable) */
+ } integer;
+ struct {
+ long long min; /* R: minimum value */
+ long long max; /* R: maximum value */
+ long long step; /* R: step (0 variable) */
+ } integer64;
+ struct {
+ unsigned int items; /* R: number of items */
+ unsigned int item; /* W: item number */
+ char name[64]; /* R: value name */
+ __u64 names_ptr; /* W: names list (ELEM_ADD only) */
+ unsigned int names_length;
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ union {
+ unsigned short d[4]; /* dimensions */
+ unsigned short *d_ptr; /* indirect - obsoleted */
+ } dimen;
+ unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id; /* W: element ID */
+ unsigned int indirect: 1; /* W: indirect access - obsoleted */
+ union {
+ union {
+ long value[128];
+ long *value_ptr; /* obsoleted */
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr; /* obsoleted */
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr; /* obsoleted */
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr; /* obsoleted */
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value; /* RO */
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+ unsigned int numid; /* control element numeric identification */
+ unsigned int length; /* in bytes aligned to 4 */
+ unsigned int tlv[0]; /* first TLV */
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
+
+/*
+ * Read interface.
+ */
+
+enum sndrv_ctl_event_type {
+ SNDRV_CTL_EVENT_ELEM = 0,
+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
+
+struct snd_ctl_event {
+ int type; /* event type - SNDRV_CTL_EVENT_* */
+ union {
+ struct {
+ unsigned int mask;
+ struct snd_ctl_elem_id id;
+ } elem;
+ unsigned char data8[60];
+ } data;
+};
+
+/*
+ * Control names
+ */
+
+#define SNDRV_CTL_NAME_NONE ""
+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
+#define SNDRV_CTL_NAME_CAPTURE "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/include/sound/asound_fm.h b/include/uapi/sound/asound_fm.h
index c2a4b967d5be..c2a4b967d5be 100644
--- a/include/sound/asound_fm.h
+++ b/include/uapi/sound/asound_fm.h
diff --git a/include/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
index 05341a43fedf..05341a43fedf 100644
--- a/include/sound/compress_offload.h
+++ b/include/uapi/sound/compress_offload.h
diff --git a/include/sound/compress_params.h b/include/uapi/sound/compress_params.h
index 602dc6c45d1a..602dc6c45d1a 100644
--- a/include/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h
new file mode 100644
index 000000000000..d1bbaf78457a
--- /dev/null
+++ b/include/uapi/sound/emu10k1.h
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
+ * Creative Labs, Inc.
+ * Definitions for EMU10K1 (SB Live!) chips
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_EMU10K1_H
+#define _UAPI__SOUND_EMU10K1_H
+
+#include <linux/types.h>
+
+
+
+/*
+ * ---- FX8010 ----
+ */
+
+#define EMU10K1_CARD_CREATIVE 0x00000000
+#define EMU10K1_CARD_EMUAPS 0x00000001
+
+#define EMU10K1_FX8010_PCM_COUNT 8
+
+/* instruction set */
+#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */
+#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */
+#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */
+#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */
+#define iMACINT0 0x04 /* R = A + X * Y ; saturation */
+#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */
+#define iACC3 0x06 /* R = A + X + Y ; saturation */
+#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */
+#define iANDXOR 0x08 /* R = (A & X) ^ Y */
+#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */
+#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */
+#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */
+#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */
+#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* GPRs */
+#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
+#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
+#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+ /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
+#define C_00000000 0x40
+#define C_00000001 0x41
+#define C_00000002 0x42
+#define C_00000003 0x43
+#define C_00000004 0x44
+#define C_00000008 0x45
+#define C_00000010 0x46
+#define C_00000020 0x47
+#define C_00000100 0x48
+#define C_00010000 0x49
+#define C_00080000 0x4a
+#define C_10000000 0x4b
+#define C_20000000 0x4c
+#define C_40000000 0x4d
+#define C_80000000 0x4e
+#define C_7fffffff 0x4f
+#define C_ffffffff 0x50
+#define C_fffffffe 0x51
+#define C_c0000000 0x52
+#define C_4f1bbcdc 0x53
+#define C_5a7ef9db 0x54
+#define C_00100000 0x55 /* ?? */
+#define GPR_ACCU 0x56 /* ACCUM, accumulator */
+#define GPR_COND 0x57 /* CCR, condition register */
+#define GPR_NOISE0 0x58 /* noise source */
+#define GPR_NOISE1 0x59 /* noise source */
+#define GPR_IRQ 0x5a /* IRQ register */
+#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */
+#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
+#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
+#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
+#define A_GPR(x) (A_FXGPREGBASE + (x))
+
+/* cc_reg constants */
+#define CC_REG_NORMALIZED C_00000001
+#define CC_REG_BORROW C_00000002
+#define CC_REG_MINUS C_00000004
+#define CC_REG_ZERO C_00000008
+#define CC_REG_SATURATE C_00000010
+#define CC_REG_NONZERO C_00000100
+
+/* FX buses */
+#define FXBUS_PCM_LEFT 0x00
+#define FXBUS_PCM_RIGHT 0x01
+#define FXBUS_PCM_LEFT_REAR 0x02
+#define FXBUS_PCM_RIGHT_REAR 0x03
+#define FXBUS_MIDI_LEFT 0x04
+#define FXBUS_MIDI_RIGHT 0x05
+#define FXBUS_PCM_CENTER 0x06
+#define FXBUS_PCM_LFE 0x07
+#define FXBUS_PCM_LEFT_FRONT 0x08
+#define FXBUS_PCM_RIGHT_FRONT 0x09
+#define FXBUS_MIDI_REVERB 0x0c
+#define FXBUS_MIDI_CHORUS 0x0d
+#define FXBUS_PCM_LEFT_SIDE 0x0e
+#define FXBUS_PCM_RIGHT_SIDE 0x0f
+#define FXBUS_PT_LEFT 0x14
+#define FXBUS_PT_RIGHT 0x15
+
+/* Inputs */
+#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
+#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */
+
+/* Outputs */
+#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */
+#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */
+#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L 0x08 /* Rear channel - left */
+#define EXTOUT_REAR_R 0x09 /* Rear channel - right */
+#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */
+#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */
+#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */
+#define EXTOUT_ACENTER 0x11 /* Analog Center */
+#define EXTOUT_ALFE 0x12 /* Analog LFE */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */
+#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */
+#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R 0x09 /* right */
+#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */
+#define A_EXTIN_ADC_R 0x0b /* right */
+#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R 0x0d /* - right */
+
+/* Audigiy Outputs */
+#define A_EXTOUT_FRONT_L 0x00 /* digital front left */
+#define A_EXTOUT_FRONT_R 0x01 /* right */
+#define A_EXTOUT_CENTER 0x02 /* digital front center */
+#define A_EXTOUT_LFE 0x03 /* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R 0x05 /* right */
+#define A_EXTOUT_REAR_L 0x06 /* digital rear left */
+#define A_EXTOUT_REAR_R 0x07 /* right */
+#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */
+#define A_EXTOUT_AFRONT_R 0x09 /* right */
+#define A_EXTOUT_ACENTER 0x0a /* analog center */
+#define A_EXTOUT_ALFE 0x0b /* analog LFE */
+#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */
+#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */
+#define A_EXTOUT_AREAR_R 0x0f /* right */
+#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */
+#define A_EXTOUT_AC97_R 0x11 /* right */
+#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R 0x17 /* right */
+#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */
+
+/* Audigy constants */
+#define A_C_00000000 0xc0
+#define A_C_00000001 0xc1
+#define A_C_00000002 0xc2
+#define A_C_00000003 0xc3
+#define A_C_00000004 0xc4
+#define A_C_00000008 0xc5
+#define A_C_00000010 0xc6
+#define A_C_00000020 0xc7
+#define A_C_00000100 0xc8
+#define A_C_00010000 0xc9
+#define A_C_00000800 0xca
+#define A_C_10000000 0xcb
+#define A_C_20000000 0xcc
+#define A_C_40000000 0xcd
+#define A_C_80000000 0xce
+#define A_C_7fffffff 0xcf
+#define A_C_ffffffff 0xd0
+#define A_C_fffffffe 0xd1
+#define A_C_c0000000 0xd2
+#define A_C_4f1bbcdc 0xd3
+#define A_C_5a7ef9db 0xd4
+#define A_C_00100000 0xd5
+#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */
+#define A_GPR_COND 0xd7 /* CCR, condition register */
+#define A_GPR_NOISE0 0xd8 /* noise source */
+#define A_GPR_NOISE1 0xd9 /* noise source */
+#define A_GPR_IRQ 0xda /* IRQ register */
+#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */
+
+/* definitions for debug register */
+#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */
+#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */
+#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */
+#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */
+#define EMU10K1_DBG_STEP 0x00004000 /* start single step */
+#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */
+#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */
+
+/* tank memory address line */
+#ifndef __KERNEL__
+#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */
+#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */
+#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */
+#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */
+#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
+#endif
+
+struct snd_emu10k1_fx8010_info {
+ unsigned int internal_tram_size; /* in samples */
+ unsigned int external_tram_size; /* in samples */
+ char fxbus_names[16][32]; /* names of FXBUSes */
+ char extin_names[16][32]; /* names of external inputs */
+ char extout_names[32][32]; /* names of external outputs */
+ unsigned int gpr_controls; /* count of GPR controls */
+};
+
+#define EMU10K1_GPR_TRANSLATION_NONE 0
+#define EMU10K1_GPR_TRANSLATION_TABLE100 1
+#define EMU10K1_GPR_TRANSLATION_BASS 2
+#define EMU10K1_GPR_TRANSLATION_TREBLE 3
+#define EMU10K1_GPR_TRANSLATION_ONOFF 4
+
+struct snd_emu10k1_fx8010_control_gpr {
+ struct snd_ctl_elem_id id; /* full control ID definition */
+ unsigned int vcount; /* visible count */
+ unsigned int count; /* count of GPR (1..16) */
+ unsigned short gpr[32]; /* GPR number(s) */
+ unsigned int value[32]; /* initial values */
+ unsigned int min; /* minimum range */
+ unsigned int max; /* maximum range */
+ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
+ const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+ struct snd_ctl_elem_id id;
+ unsigned int vcount;
+ unsigned int count;
+ unsigned short gpr[32];
+ unsigned int value[32];
+ unsigned int min;
+ unsigned int max;
+ unsigned int translation;
+};
+
+struct snd_emu10k1_fx8010_code {
+ char name[128];
+
+ DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+ __u32 __user *gpr_map; /* initializers */
+
+ unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
+ struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
+
+ unsigned int gpr_del_control_count; /* count of GPR controls to remove */
+ struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
+
+ unsigned int gpr_list_control_count; /* count of GPR controls to list */
+ unsigned int gpr_list_control_total; /* total count of GPR controls */
+ struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
+
+ DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+ __u32 __user *tram_data_map; /* data initializers */
+ __u32 __user *tram_addr_map; /* map initializers */
+
+ DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+ __u32 __user *code; /* one instruction - 64 bits */
+};
+
+struct snd_emu10k1_fx8010_tram {
+ unsigned int address; /* 31.bit == 1 -> external TRAM */
+ unsigned int size; /* size in samples (4 bytes) */
+ unsigned int *samples; /* pointer to samples (20-bit) */
+ /* NULL->clear memory */
+};
+
+struct snd_emu10k1_fx8010_pcm_rec {
+ unsigned int substream; /* substream number */
+ unsigned int res1; /* reserved */
+ unsigned int channels; /* 16-bit channels count, zero = remove this substream */
+ unsigned int tram_start; /* ring buffer position in TRAM (in samples) */
+ unsigned int buffer_size; /* count of buffered samples */
+ unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */
+ unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+ unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */
+ unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */
+ unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */
+ unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */
+ unsigned char pad; /* reserved */
+ unsigned char etram[32]; /* external TRAM address & data (one per channel) */
+ unsigned int res2; /* reserved */
+};
+
+#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
+#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
+#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
+#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
+#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
+#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
+
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+
+#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/sound/hdsp.h b/include/uapi/sound/hdsp.h
index 0909a3843479..0909a3843479 100644
--- a/include/sound/hdsp.h
+++ b/include/uapi/sound/hdsp.h
diff --git a/include/sound/hdspm.h b/include/uapi/sound/hdspm.h
index 1f59ea2a4a76..1f59ea2a4a76 100644
--- a/include/sound/hdspm.h
+++ b/include/uapi/sound/hdspm.h
diff --git a/include/uapi/sound/sb16_csp.h b/include/uapi/sound/sb16_csp.h
new file mode 100644
index 000000000000..3b96907e2afb
--- /dev/null
+++ b/include/uapi/sound/sb16_csp.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
+ * Takashi Iwai <tiwai@suse.de>
+ *
+ * SB16ASP/AWE32 CSP control
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_SB16_CSP_H
+#define _UAPI__SOUND_SB16_CSP_H
+
+
+/* CSP modes */
+#define SNDRV_SB_CSP_MODE_NONE 0x00
+#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */
+#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */
+#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */
+
+/* CSP load flags */
+#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01
+#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02
+
+/* CSP sample width */
+#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01
+#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02
+
+/* CSP channels */
+#define SNDRV_SB_CSP_MONO 0x01
+#define SNDRV_SB_CSP_STEREO 0x02
+
+/* CSP rates */
+#define SNDRV_SB_CSP_RATE_8000 0x01
+#define SNDRV_SB_CSP_RATE_11025 0x02
+#define SNDRV_SB_CSP_RATE_22050 0x04
+#define SNDRV_SB_CSP_RATE_44100 0x08
+#define SNDRV_SB_CSP_RATE_ALL 0x0f
+
+/* CSP running state */
+#define SNDRV_SB_CSP_ST_IDLE 0x00
+#define SNDRV_SB_CSP_ST_LOADED 0x01
+#define SNDRV_SB_CSP_ST_RUNNING 0x02
+#define SNDRV_SB_CSP_ST_PAUSED 0x04
+#define SNDRV_SB_CSP_ST_AUTO 0x08
+#define SNDRV_SB_CSP_ST_QSOUND 0x10
+
+/* maximum QSound value (180 degrees right) */
+#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20
+
+/* maximum microcode RIFF file size */
+#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000
+
+/* microcode header */
+struct snd_sb_csp_mc_header {
+ char codec_name[16]; /* id name of codec */
+ unsigned short func_req; /* requested function */
+};
+
+/* microcode to be loaded */
+struct snd_sb_csp_microcode {
+ struct snd_sb_csp_mc_header info;
+ unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
+};
+
+/* start CSP with sample_width in mono/stereo */
+struct snd_sb_csp_start {
+ int sample_width; /* sample width, look above */
+ int channels; /* channels, look above */
+};
+
+/* CSP information */
+struct snd_sb_csp_info {
+ char codec_name[16]; /* id name of codec */
+ unsigned short func_nr; /* function number */
+ unsigned int acc_format; /* accepted PCM formats */
+ unsigned short acc_channels; /* accepted channels */
+ unsigned short acc_width; /* accepted sample width */
+ unsigned short acc_rates; /* accepted sample rates */
+ unsigned short csp_mode; /* CSP mode, see above */
+ unsigned short run_channels; /* current channels */
+ unsigned short run_width; /* current sample width */
+ unsigned short version; /* version id: 0x10 - 0x1f */
+ unsigned short state; /* state bits */
+};
+
+/* HWDEP controls */
+/* get CSP information */
+#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info)
+/* load microcode to CSP */
+/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
+ * defined for some architectures like MIPS, and it leads to build errors.
+ * (x86 and co have 14-bit size, thus it's valid, though.)
+ * As a workaround for skipping the size-limit check, here we don't use the
+ * normal _IOW() macro but _IOC() with the manual argument.
+ */
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \
+ _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
+/* unload microcode from CSP */
+#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
+/* start CSP */
+#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start)
+/* stop CSP */
+#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
+/* pause CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15)
+/* restart CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16)
+
+
+#endif /* _UAPI__SOUND_SB16_CSP_H */
diff --git a/include/sound/sfnt_info.h b/include/uapi/sound/sfnt_info.h
index 1bce7fd1725f..1bce7fd1725f 100644
--- a/include/sound/sfnt_info.h
+++ b/include/uapi/sound/sfnt_info.h
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index b576f7f14bc6..7e1c3de1ce45 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
goto out_pid;
}
- new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns);
+ new_nsp->net_ns = copy_net_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->net_ns);
if (IS_ERR(new_nsp->net_ns)) {
err = PTR_ERR(new_nsp->net_ns);
goto out_net;
diff --git a/kernel/pid.c b/kernel/pid.c
index aebd4f5aaf41..fd996c1ed9f8 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -1,8 +1,8 @@
/*
* Generic pidhash and scalable, time-bounded PID allocator
*
- * (C) 2002-2003 William Irwin, IBM
- * (C) 2004 William Irwin, Oracle
+ * (C) 2002-2003 Nadia Yvette Chambers, IBM
+ * (C) 2004 Nadia Yvette Chambers, Oracle
* (C) 2002-2004 Ingo Molnar, Red Hat
*
* pid-structures are backing objects for tasks sharing a given ID to chain
diff --git a/kernel/profile.c b/kernel/profile.c
index 76b8e77773ee..1f391819c42f 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -8,9 +8,10 @@
* Scheduler profiling support, Arjan van de Ven and Ingo Molnar,
* Red Hat, July 2004
* Consolidation of architecture support code for profiling,
- * William Irwin, Oracle, July 2004
+ * Nadia Yvette Chambers, Oracle, July 2004
* Amortized hit count accounting via per-cpu open-addressed hashtables
- * to resolve timer interrupt livelocks, William Irwin, Oracle, 2004
+ * to resolve timer interrupt livelocks, Nadia Yvette Chambers,
+ * Oracle, 2004
*/
#include <linux/export.h>
@@ -256,7 +257,7 @@ EXPORT_SYMBOL_GPL(unregister_timer_hook);
* pagetable hash functions, but uses a full hashtable full of finite
* collision chains, not just pairs of them.
*
- * -- wli
+ * -- nyc
*/
static void __profile_flip_buffers(void *unused)
{
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index e2fd74b8e8c2..ff7d9d2ab504 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,4 +1,4 @@
-obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
+obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
obj-y += timeconv.o posix-clock.o alarmtimer.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o
diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
deleted file mode 100644
index a9ae369925ce..000000000000
--- a/kernel/time/timecompare.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/timecompare.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/math64.h>
-#include <linux/kernel.h>
-
-/*
- * fixed point arithmetic scale factor for skew
- *
- * Usually one would measure skew in ppb (parts per billion, 1e9), but
- * using a factor of 2 simplifies the math.
- */
-#define TIMECOMPARE_SKEW_RESOLUTION (((s64)1)<<30)
-
-ktime_t timecompare_transform(struct timecompare *sync,
- u64 source_tstamp)
-{
- u64 nsec;
-
- nsec = source_tstamp + sync->offset;
- nsec += (s64)(source_tstamp - sync->last_update) * sync->skew /
- TIMECOMPARE_SKEW_RESOLUTION;
-
- return ns_to_ktime(nsec);
-}
-EXPORT_SYMBOL_GPL(timecompare_transform);
-
-int timecompare_offset(struct timecompare *sync,
- s64 *offset,
- u64 *source_tstamp)
-{
- u64 start_source = 0, end_source = 0;
- struct {
- s64 offset;
- s64 duration_target;
- } buffer[10], sample, *samples;
- int counter = 0, i;
- int used;
- int index;
- int num_samples = sync->num_samples;
-
- if (num_samples > ARRAY_SIZE(buffer)) {
- samples = kmalloc(sizeof(*samples) * num_samples, GFP_ATOMIC);
- if (!samples) {
- samples = buffer;
- num_samples = ARRAY_SIZE(buffer);
- }
- } else {
- samples = buffer;
- }
-
- /* run until we have enough valid samples, but do not try forever */
- i = 0;
- counter = 0;
- while (1) {
- u64 ts;
- ktime_t start, end;
-
- start = sync->target();
- ts = timecounter_read(sync->source);
- end = sync->target();
-
- if (!i)
- start_source = ts;
-
- /* ignore negative durations */
- sample.duration_target = ktime_to_ns(ktime_sub(end, start));
- if (sample.duration_target >= 0) {
- /*
- * assume symetric delay to and from source:
- * average target time corresponds to measured
- * source time
- */
- sample.offset =
- (ktime_to_ns(end) + ktime_to_ns(start)) / 2 -
- ts;
-
- /* simple insertion sort based on duration */
- index = counter - 1;
- while (index >= 0) {
- if (samples[index].duration_target <
- sample.duration_target)
- break;
- samples[index + 1] = samples[index];
- index--;
- }
- samples[index + 1] = sample;
- counter++;
- }
-
- i++;
- if (counter >= num_samples || i >= 100000) {
- end_source = ts;
- break;
- }
- }
-
- *source_tstamp = (end_source + start_source) / 2;
-
- /* remove outliers by only using 75% of the samples */
- used = counter * 3 / 4;
- if (!used)
- used = counter;
- if (used) {
- /* calculate average */
- s64 off = 0;
- for (index = 0; index < used; index++)
- off += samples[index].offset;
- *offset = div_s64(off, used);
- }
-
- if (samples && samples != buffer)
- kfree(samples);
-
- return used;
-}
-EXPORT_SYMBOL_GPL(timecompare_offset);
-
-void __timecompare_update(struct timecompare *sync,
- u64 source_tstamp)
-{
- s64 offset;
- u64 average_time;
-
- if (!timecompare_offset(sync, &offset, &average_time))
- return;
-
- if (!sync->last_update) {
- sync->last_update = average_time;
- sync->offset = offset;
- sync->skew = 0;
- } else {
- s64 delta_nsec = average_time - sync->last_update;
-
- /* avoid division by negative or small deltas */
- if (delta_nsec >= 10000) {
- s64 delta_offset_nsec = offset - sync->offset;
- s64 skew; /* delta_offset_nsec *
- TIMECOMPARE_SKEW_RESOLUTION /
- delta_nsec */
- u64 divisor;
-
- /* div_s64() is limited to 32 bit divisor */
- skew = delta_offset_nsec * TIMECOMPARE_SKEW_RESOLUTION;
- divisor = delta_nsec;
- while (unlikely(divisor >= ((s64)1) << 32)) {
- /* divide both by 2; beware, right shift
- of negative value has undefined
- behavior and can only be used for
- the positive divisor */
- skew = div_s64(skew, 2);
- divisor >>= 1;
- }
- skew = div_s64(skew, divisor);
-
- /*
- * Calculate new overall skew as 4/16 the
- * old value and 12/16 the new one. This is
- * a rather arbitrary tradeoff between
- * only using the latest measurement (0/16 and
- * 16/16) and even more weight on past measurements.
- */
-#define TIMECOMPARE_NEW_SKEW_PER_16 12
- sync->skew =
- div_s64((16 - TIMECOMPARE_NEW_SKEW_PER_16) *
- sync->skew +
- TIMECOMPARE_NEW_SKEW_PER_16 * skew,
- 16);
- sync->last_update = average_time;
- sync->offset = offset;
- }
- }
-}
-EXPORT_SYMBOL_GPL(__timecompare_update);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 7693aaf324c6..afd092de45b7 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -10,7 +10,7 @@
* Based on code in the latency_tracer, that is:
*
* Copyright (C) 2004-2006 Ingo Molnar
- * Copyright (C) 2004 William Lee Irwin III
+ * Copyright (C) 2004 Nadia Yvette Chambers
*/
#include <linux/stop_machine.h>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b69cc380322d..61e081b4ba11 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9,7 +9,7 @@
*
* Based on code from the latency_tracer, that is:
* Copyright (C) 2004-2006 Ingo Molnar
- * Copyright (C) 2004 William Lee Irwin III
+ * Copyright (C) 2004 Nadia Yvette Chambers
*/
#include <linux/ring_buffer.h>
#include <generated/utsrelease.h>
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index bb227e380cb5..8e3ad8082ab7 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -7,7 +7,7 @@
* Based on code from the latency_tracer, that is:
*
* Copyright (C) 2004-2006 Ingo Molnar
- * Copyright (C) 2004 William Lee Irwin III
+ * Copyright (C) 2004 Nadia Yvette Chambers
*/
#include <linux/ring_buffer.h>
#include <linux/debugfs.h>
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 5ffce7b0f33c..713a2cac4881 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -7,7 +7,7 @@
* From code in the latency_tracer, that is:
*
* Copyright (C) 2004-2006 Ingo Molnar
- * Copyright (C) 2004 William Lee Irwin III
+ * Copyright (C) 2004 Nadia Yvette Chambers
*/
#include <linux/kallsyms.h>
#include <linux/debugfs.h>
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index bc64fc137554..9fe45fcefca0 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -7,7 +7,7 @@
* Based on code from the latency_tracer, that is:
*
* Copyright (C) 2004-2006 Ingo Molnar
- * Copyright (C) 2004 William Lee Irwin III
+ * Copyright (C) 2004 Nadia Yvette Chambers
*/
#include <linux/module.h>
#include <linux/fs.h>
diff --git a/kernel/wait.c b/kernel/wait.c
index 7fdd9eaca2c3..6698e0c04ead 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -1,7 +1,7 @@
/*
* Generic waiting primitives.
*
- * (C) 2004 William Irwin, Oracle
+ * (C) 2004 Nadia Yvette Chambers, Oracle
*/
#include <linux/init.h>
#include <linux/export.h>
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 41faf0b8df1d..e458782f3c52 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1115,7 +1115,7 @@ config NOTIFIER_ERROR_INJECTION
depends on DEBUG_KERNEL
select DEBUG_FS
help
- This option provides the ability to inject artifical errors to
+ This option provides the ability to inject artificial errors to
specified notifier chain callbacks. It is useful to test the error
handling of notifier call chain failures.
@@ -1126,7 +1126,7 @@ config CPU_NOTIFIER_ERROR_INJECT
depends on HOTPLUG_CPU && NOTIFIER_ERROR_INJECTION
help
This option provides a kernel module that can be used to test
- the error handling of the cpu notifiers by injecting artifical
+ the error handling of the cpu notifiers by injecting artificial
errors to CPU notifier chain callbacks. It is controlled through
debugfs interface under /sys/kernel/debug/notifier-error-inject/cpu
@@ -1150,7 +1150,7 @@ config PM_NOTIFIER_ERROR_INJECT
depends on PM && NOTIFIER_ERROR_INJECTION
default m if PM_DEBUG
help
- This option provides the ability to inject artifical errors to
+ This option provides the ability to inject artificial errors to
PM notifier chain callbacks. It is controlled through debugfs
interface /sys/kernel/debug/notifier-error-inject/pm
@@ -1173,7 +1173,7 @@ config MEMORY_NOTIFIER_ERROR_INJECT
tristate "Memory hotplug notifier error injection module"
depends on MEMORY_HOTPLUG_SPARSE && NOTIFIER_ERROR_INJECTION
help
- This option provides the ability to inject artifical errors to
+ This option provides the ability to inject artificial errors to
memory hotplug notifier chain callbacks. It is controlled through
debugfs interface under /sys/kernel/debug/notifier-error-inject/memory
@@ -1196,7 +1196,7 @@ config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT
tristate "pSeries reconfig notifier error injection module"
depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION
help
- This option provides the ability to inject artifical errors to
+ This option provides the ability to inject artificial errors to
pSeries reconfig notifier chain callbacks. It is controlled
through debugfs interface under
/sys/kernel/debug/notifier-error-inject/pSeries-reconfig/
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 06fdfa1aeba7..06f7e4fe8d2d 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -353,7 +353,7 @@ again:
EXPORT_SYMBOL(bitmap_find_next_zero_area);
/*
- * Bitmap printing & parsing functions: first version by Bill Irwin,
+ * Bitmap printing & parsing functions: first version by Nadia Yvette Chambers,
* second version by Paul Jackson, third by Joe Korty.
*/
diff --git a/mm/Kconfig b/mm/Kconfig
index 1680a0123a13..71259e052ce8 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -149,7 +149,7 @@ config MOVABLE_NODE
depends on NO_BOOTMEM
depends on X86_64
depends on NUMA
- default y
+ depends on BROKEN
# eventually, we can have this option just 'select SPARSEMEM'
config MEMORY_HOTPLUG
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 22508ef943e6..88e7293b96bd 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1,6 +1,6 @@
/*
* Generic hugetlb support.
- * (C) William Irwin, April 2004
+ * (C) Nadia Yvette Chambers, April 2004
*/
#include <linux/list.h>
#include <linux/init.h>
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index b7c93ca896d6..518baa896e83 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1312,10 +1312,10 @@ repeat:
goto repeat;
}
}
- /* drain all zone's lru pagevec, this is asyncronous... */
+ /* drain all zone's lru pagevec, this is asynchronous... */
lru_add_drain_all();
yield();
- /* drain pcp pages , this is synchrouns. */
+ /* drain pcp pages, this is synchronous. */
drain_all_pages();
/* check again */
offlined_pages = check_pages_isolated(start_pfn, end_pfn);
@@ -1324,7 +1324,7 @@ repeat:
goto failed_removal;
}
printk(KERN_INFO "Offlined Pages %ld\n", offlined_pages);
- /* Ok, all of our target is islaoted.
+ /* Ok, all of our target is isolated.
We cannot do rollback at this point. */
offline_isolated_pages(start_pfn, end_pfn);
/* reset pagetype flags and makes migrate type to be MOVABLE */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d187988e2b56..83637dfba110 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -526,7 +526,7 @@ static inline int page_is_buddy(struct page *page, struct page *buddy,
* If a block is freed, and its buddy is also free, then this
* triggers coalescing into a block of larger size.
*
- * -- wli
+ * -- nyc
*/
static inline void __free_one_page(struct page *page,
@@ -793,7 +793,7 @@ void __init init_cma_reserved_pageblock(struct page *page)
* large block of memory acted on by a series of small allocations.
* This behavior is a critical factor in sglist merging's success.
*
- * -- wli
+ * -- nyc
*/
static inline void expand(struct zone *zone, struct page *page,
int low, int high, struct free_area *area,
diff --git a/mm/util.c b/mm/util.c
index dc3036cdcc6a..c55e26b17d93 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(__krealloc);
*
* The contents of the object pointed to are preserved up to the
* lesser of the new and old sizes. If @p is %NULL, krealloc()
- * behaves exactly like kmalloc(). If @size is 0 and @p is not a
+ * behaves exactly like kmalloc(). If @new_size is 0 and @p is not a
* %NULL pointer, the object pointed to is freed.
*/
void *krealloc(const void *p, size_t new_size, gfp_t flags)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index ee070722a3a3..a292e8050ef2 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -242,6 +242,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
* hope the underlying device can handle it.
*/
new_dev->mtu = real_dev->mtu;
+ new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT);
vlan_dev_priv(new_dev)->vlan_id = vlan_id;
vlan_dev_priv(new_dev)->real_dev = real_dev;
@@ -294,7 +295,7 @@ static void vlan_transfer_features(struct net_device *dev,
else
vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
#endif
@@ -529,7 +530,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
switch (args.cmd) {
case SET_VLAN_INGRESS_PRIORITY_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
vlan_dev_set_ingress_priority(dev,
args.u.skb_priority,
@@ -539,7 +540,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
case SET_VLAN_EGRESS_PRIORITY_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
err = vlan_dev_set_egress_priority(dev,
args.u.skb_priority,
@@ -548,7 +549,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
case SET_VLAN_FLAG_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
err = vlan_dev_change_flags(dev,
args.vlan_qos ? args.u.flag : 0,
@@ -557,7 +558,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
case SET_VLAN_NAME_TYPE_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
if ((args.u.name_type >= 0) &&
(args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
@@ -573,14 +574,14 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
case ADD_VLAN_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
err = register_vlan_device(dev, args.u.VID);
break;
case DEL_VLAN_CMD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
unregister_vlan_dev(dev, NULL);
err = 0;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 402442402af7..4a6d31a082b9 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -409,7 +409,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
return err;
}
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid,
struct scatterlist *sgl, unsigned int sgc)
{
@@ -531,6 +531,10 @@ static const struct header_ops vlan_header_ops = {
.parse = eth_header_parse,
};
+static struct device_type vlan_type = {
+ .name = "vlan",
+};
+
static const struct net_device_ops vlan_netdev_ops;
static int vlan_dev_init(struct net_device *dev)
@@ -564,7 +568,7 @@ static int vlan_dev_init(struct net_device *dev)
if (is_zero_ether_addr(dev->broadcast))
memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
#endif
@@ -579,6 +583,8 @@ static int vlan_dev_init(struct net_device *dev)
dev->netdev_ops = &vlan_netdev_ops;
+ SET_NETDEV_DEVTYPE(dev, &vlan_type);
+
if (is_vlan_dev(real_dev))
subclass = 1;
@@ -741,7 +747,7 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
.ndo_get_stats64 = vlan_dev_get_stats64,
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
.ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
.ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
.ndo_fcoe_enable = vlan_dev_fcoe_enable,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 4819d31533e0..403e71fa88fe 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -68,12 +68,15 @@ struct br2684_vcc {
/* keep old push, pop functions for chaining */
void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+ void (*old_release_cb)(struct atm_vcc *vcc);
+ struct module *old_owner;
enum br2684_encaps encaps;
struct list_head brvccs;
#ifdef CONFIG_ATM_BR2684_IPFILTER
struct br2684_filter filter;
#endif /* CONFIG_ATM_BR2684_IPFILTER */
unsigned int copies_needed, copies_failed;
+ atomic_t qspace;
};
struct br2684_dev {
@@ -181,18 +184,15 @@ static struct notifier_block atm_dev_notifier = {
static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct br2684_vcc *brvcc = BR2684_VCC(vcc);
- struct net_device *net_dev = skb->dev;
- pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+ pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
brvcc->old_pop(vcc, skb);
- if (!net_dev)
- return;
-
- if (atm_may_send(vcc, 0))
- netif_wake_queue(net_dev);
-
+ /* If the queue space just went up from zero, wake */
+ if (atomic_inc_return(&brvcc->qspace) == 1)
+ netif_wake_queue(brvcc->device);
}
+
/*
* Send a packet out a particular vcc. Not to useful right now, but paves
* the way for multiple vcc's per itf. Returns true if we can send,
@@ -256,16 +256,30 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
ATM_SKB(skb)->atm_options = atmvcc->atm_options;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- atmvcc->send(atmvcc, skb);
- if (!atm_may_send(atmvcc, 0)) {
+ if (atomic_dec_return(&brvcc->qspace) < 1) {
+ /* No more please! */
netif_stop_queue(brvcc->device);
- /*check for race with br2684_pop*/
- if (atm_may_send(atmvcc, 0))
- netif_start_queue(brvcc->device);
+ /* We might have raced with br2684_pop() */
+ if (unlikely(atomic_read(&brvcc->qspace) > 0))
+ netif_wake_queue(brvcc->device);
}
- return 1;
+ /* If this fails immediately, the skb will be freed and br2684_pop()
+ will wake the queue if appropriate. Just return an error so that
+ the stats are updated correctly */
+ return !atmvcc->send(atmvcc, skb);
+}
+
+static void br2684_release_cb(struct atm_vcc *atmvcc)
+{
+ struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+
+ if (atomic_read(&brvcc->qspace) > 0)
+ netif_wake_queue(brvcc->device);
+
+ if (brvcc->old_release_cb)
+ brvcc->old_release_cb(atmvcc);
}
static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
@@ -279,6 +293,8 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
{
struct br2684_dev *brdev = BRPRIV(dev);
struct br2684_vcc *brvcc;
+ struct atm_vcc *atmvcc;
+ netdev_tx_t ret = NETDEV_TX_OK;
pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
read_lock(&devs_lock);
@@ -289,9 +305,26 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
dev->stats.tx_carrier_errors++;
/* netif_stop_queue(dev); */
dev_kfree_skb(skb);
- read_unlock(&devs_lock);
- return NETDEV_TX_OK;
+ goto out_devs;
}
+ atmvcc = brvcc->atmvcc;
+
+ bh_lock_sock(sk_atm(atmvcc));
+
+ if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
+ test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
+ !test_bit(ATM_VF_READY, &atmvcc->flags)) {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ goto out;
+ }
+
+ if (sock_owned_by_user(sk_atm(atmvcc))) {
+ netif_stop_queue(brvcc->device);
+ ret = NETDEV_TX_BUSY;
+ goto out;
+ }
+
if (!br2684_xmit_vcc(skb, dev, brvcc)) {
/*
* We should probably use netif_*_queue() here, but that
@@ -303,8 +336,11 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
dev->stats.tx_errors++;
dev->stats.tx_fifo_errors++;
}
+ out:
+ bh_unlock_sock(sk_atm(atmvcc));
+ out_devs:
read_unlock(&devs_lock);
- return NETDEV_TX_OK;
+ return ret;
}
/*
@@ -377,9 +413,10 @@ static void br2684_close_vcc(struct br2684_vcc *brvcc)
list_del(&brvcc->brvccs);
write_unlock_irq(&devs_lock);
brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
+ brvcc->atmvcc->release_cb = brvcc->old_release_cb;
brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
+ module_put(brvcc->old_owner);
kfree(brvcc);
- module_put(THIS_MODULE);
}
/* when AAL5 PDU comes in: */
@@ -504,6 +541,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
if (!brvcc)
return -ENOMEM;
+ /*
+ * Allow two packets in the ATM queue. One actually being sent, and one
+ * for the ATM 'TX done' handler to send. It shouldn't take long to get
+ * the next one from the netdev queue, when we need it. More than that
+ * would be bufferbloat.
+ */
+ atomic_set(&brvcc->qspace, 2);
write_lock_irq(&devs_lock);
net_dev = br2684_find_dev(&be.ifspec);
if (net_dev == NULL) {
@@ -546,9 +590,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
brvcc->encaps = (enum br2684_encaps)be.encaps;
brvcc->old_push = atmvcc->push;
brvcc->old_pop = atmvcc->pop;
+ brvcc->old_release_cb = atmvcc->release_cb;
+ brvcc->old_owner = atmvcc->owner;
barrier();
atmvcc->push = br2684_push;
atmvcc->pop = br2684_pop;
+ atmvcc->release_cb = br2684_release_cb;
+ atmvcc->owner = THIS_MODULE;
/* initialize netdev carrier state */
if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
@@ -687,10 +735,13 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
return -ENOIOCTLCMD;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (cmd == ATM_SETBACKEND)
+ if (cmd == ATM_SETBACKEND) {
+ if (sock->state != SS_CONNECTED)
+ return -EINVAL;
return br2684_regvcc(atmvcc, argp);
- else
+ } else {
return br2684_create(argp);
+ }
#ifdef CONFIG_ATM_BR2684_IPFILTER
case BR2684_SETFILT:
if (atmvcc->push != br2684_push)
diff --git a/net/atm/common.c b/net/atm/common.c
index 0c0ad930a632..806fc0a40051 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -126,10 +126,19 @@ static void vcc_write_space(struct sock *sk)
rcu_read_unlock();
}
+static void vcc_release_cb(struct sock *sk)
+{
+ struct atm_vcc *vcc = atm_sk(sk);
+
+ if (vcc->release_cb)
+ vcc->release_cb(vcc);
+}
+
static struct proto vcc_proto = {
.name = "VCC",
.owner = THIS_MODULE,
.obj_size = sizeof(struct atm_vcc),
+ .release_cb = vcc_release_cb,
};
int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
@@ -156,7 +165,9 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
atomic_set(&sk->sk_rmem_alloc, 0);
vcc->push = NULL;
vcc->pop = NULL;
+ vcc->owner = NULL;
vcc->push_oam = NULL;
+ vcc->release_cb = NULL;
vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
vcc->atm_options = vcc->aal_options = 0;
sk->sk_destruct = vcc_sock_destruct;
@@ -175,6 +186,7 @@ static void vcc_destroy_socket(struct sock *sk)
vcc->dev->ops->close(vcc);
if (vcc->push)
vcc->push(vcc, NULL); /* atmarpd has no push */
+ module_put(vcc->owner);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
atm_return(vcc, skb->truesize);
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 226dca989448..8c93267ce969 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -60,6 +60,8 @@ struct pppoatm_vcc {
struct atm_vcc *atmvcc; /* VCC descriptor */
void (*old_push)(struct atm_vcc *, struct sk_buff *);
void (*old_pop)(struct atm_vcc *, struct sk_buff *);
+ void (*old_release_cb)(struct atm_vcc *);
+ struct module *old_owner;
/* keep old push/pop for detaching */
enum pppoatm_encaps encaps;
atomic_t inflight;
@@ -107,6 +109,24 @@ static void pppoatm_wakeup_sender(unsigned long arg)
ppp_output_wakeup((struct ppp_channel *) arg);
}
+static void pppoatm_release_cb(struct atm_vcc *atmvcc)
+{
+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+
+ /*
+ * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
+ * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
+ * channel's ->downl lock. And the potential race with *setting* it,
+ * which leads to the double-check dance in pppoatm_may_send(), doesn't
+ * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
+ * set the BLOCKED bit while the socket is still locked. We know that
+ * ->release_cb() can't be called until that's done.
+ */
+ if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
+ tasklet_schedule(&pvcc->wakeup_tasklet);
+ if (pvcc->old_release_cb)
+ pvcc->old_release_cb(atmvcc);
+}
/*
* This gets called every time the ATM card has finished sending our
* skb. The ->old_pop will take care up normal atm flow control,
@@ -151,12 +171,11 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
pvcc = atmvcc_to_pvcc(atmvcc);
atmvcc->push = pvcc->old_push;
atmvcc->pop = pvcc->old_pop;
+ atmvcc->release_cb = pvcc->old_release_cb;
tasklet_kill(&pvcc->wakeup_tasklet);
ppp_unregister_channel(&pvcc->chan);
atmvcc->user_back = NULL;
kfree(pvcc);
- /* Gee, I hope we have the big kernel lock here... */
- module_put(THIS_MODULE);
}
/* Called when an AAL5 PDU comes in */
@@ -165,9 +184,13 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
pr_debug("\n");
if (skb == NULL) { /* VCC was closed */
+ struct module *module;
+
pr_debug("removing ATMPPP VCC %p\n", pvcc);
+ module = pvcc->old_owner;
pppoatm_unassign_vcc(atmvcc);
atmvcc->push(atmvcc, NULL); /* Pass along bad news */
+ module_put(module);
return;
}
atm_return(atmvcc, skb->truesize);
@@ -211,7 +234,7 @@ error:
ppp_input_error(&pvcc->chan, 0);
}
-static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
+static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
{
/*
* It's not clear that we need to bother with using atm_may_send()
@@ -269,10 +292,33 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
{
struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+ struct atm_vcc *vcc;
+ int ret;
+
ATM_SKB(skb)->vcc = pvcc->atmvcc;
pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
(void) skb_pull(skb, 1);
+
+ vcc = ATM_SKB(skb)->vcc;
+ bh_lock_sock(sk_atm(vcc));
+ if (sock_owned_by_user(sk_atm(vcc))) {
+ /*
+ * Needs to happen (and be flushed, hence test_and_) before we unlock
+ * the socket. It needs to be seen by the time our ->release_cb gets
+ * called.
+ */
+ test_and_set_bit(BLOCKED, &pvcc->blocked);
+ goto nospace;
+ }
+ if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
+ test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+ !test_bit(ATM_VF_READY, &vcc->flags)) {
+ bh_unlock_sock(sk_atm(vcc));
+ kfree_skb(skb);
+ return DROP_PACKET;
+ }
+
switch (pvcc->encaps) { /* LLC encapsulation needed */
case e_llc:
if (skb_headroom(skb) < LLC_LEN) {
@@ -285,8 +331,10 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
}
consume_skb(skb);
skb = n;
- if (skb == NULL)
+ if (skb == NULL) {
+ bh_unlock_sock(sk_atm(vcc));
return DROP_PACKET;
+ }
} else if (!pppoatm_may_send(pvcc, skb->truesize))
goto nospace;
memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
@@ -296,6 +344,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
goto nospace;
break;
case e_autodetect:
+ bh_unlock_sock(sk_atm(vcc));
pr_debug("Trying to send without setting encaps!\n");
kfree_skb(skb);
return 1;
@@ -305,9 +354,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
- return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+ ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
? DROP_PACKET : 1;
+ bh_unlock_sock(sk_atm(vcc));
+ return ret;
nospace:
+ bh_unlock_sock(sk_atm(vcc));
/*
* We don't have space to send this SKB now, but we might have
* already applied SC_COMP_PROT compression, so may need to undo
@@ -362,6 +414,8 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
atomic_set(&pvcc->inflight, NONE_INFLIGHT);
pvcc->old_push = atmvcc->push;
pvcc->old_pop = atmvcc->pop;
+ pvcc->old_owner = atmvcc->owner;
+ pvcc->old_release_cb = atmvcc->release_cb;
pvcc->encaps = (enum pppoatm_encaps) be.encaps;
pvcc->chan.private = pvcc;
pvcc->chan.ops = &pppoatm_ops;
@@ -377,7 +431,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
atmvcc->user_back = pvcc;
atmvcc->push = pppoatm_push;
atmvcc->pop = pppoatm_pop;
+ atmvcc->release_cb = pppoatm_release_cb;
__module_get(THIS_MODULE);
+ atmvcc->owner = THIS_MODULE;
/* re-process everything received between connection setup and
backend setup */
@@ -406,6 +462,8 @@ static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
return -ENOIOCTLCMD;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (sock->state != SS_CONNECTED)
+ return -EINVAL;
return pppoatm_assign_vcc(atmvcc, argp);
}
case PPPIOCGCHAN:
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 53f5244e28f8..8d8afb134b3a 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -6,6 +6,7 @@ config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET
select CRC16
+ select LIBCRC32C
default n
help
B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
@@ -25,6 +26,16 @@ config BATMAN_ADV_BLA
more than one mesh node in the same LAN, you can safely remove
this feature and save some space.
+config BATMAN_ADV_DAT
+ bool "Distributed ARP Table"
+ depends on BATMAN_ADV && INET
+ default n
+ help
+ This option enables DAT (Distributed ARP Table), a DHT based
+ mechanism that increases ARP reliability on sparse wireless
+ mesh networks. If you think that your network does not need
+ this option you can safely remove it and save some space.
+
config BATMAN_ADV_DEBUG
bool "B.A.T.M.A.N. debugging"
depends on BATMAN_ADV
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 8676d2b1d574..e45e3b4e32e3 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -23,6 +23,7 @@ batman-adv-y += bat_iv_ogm.o
batman-adv-y += bitarray.o
batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
batman-adv-y += debugfs.o
+batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o
batman-adv-y += gateway_client.o
batman-adv-y += gateway_common.o
batman-adv-y += hard-interface.o
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index b02b75dae3a8..9f3925a85aab 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -57,20 +57,22 @@ out:
static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
+ unsigned char *ogm_buff;
uint32_t random_seqno;
int res = -ENOMEM;
/* randomize initial seqno to avoid collision */
get_random_bytes(&random_seqno, sizeof(random_seqno));
- atomic_set(&hard_iface->seqno, random_seqno);
+ atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
- hard_iface->packet_len = BATADV_OGM_HLEN;
- hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
-
- if (!hard_iface->packet_buff)
+ hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
+ ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
+ if (!ogm_buff)
goto out;
- batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+ hard_iface->bat_iv.ogm_buff = ogm_buff;
+
+ batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
batadv_ogm_packet->header.ttl = 2;
@@ -87,15 +89,16 @@ out:
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
{
- kfree(hard_iface->packet_buff);
- hard_iface->packet_buff = NULL;
+ kfree(hard_iface->bat_iv.ogm_buff);
+ hard_iface->bat_iv.ogm_buff = NULL;
}
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
+ unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
- batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+ batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
memcpy(batadv_ogm_packet->orig,
hard_iface->net_dev->dev_addr, ETH_ALEN);
memcpy(batadv_ogm_packet->prev_sender,
@@ -106,8 +109,9 @@ static void
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
+ unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
- batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+ batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
batadv_ogm_packet->header.ttl = BATADV_TTL;
}
@@ -407,9 +411,11 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
if ((atomic_read(&bat_priv->aggregated_ogms)) &&
(packet_len < BATADV_MAX_AGGREGATION_BYTES))
- skb_size = BATADV_MAX_AGGREGATION_BYTES + ETH_HLEN;
+ skb_size = BATADV_MAX_AGGREGATION_BYTES;
else
- skb_size = packet_len + ETH_HLEN;
+ skb_size = packet_len;
+
+ skb_size += ETH_HLEN + NET_IP_ALIGN;
forw_packet_aggr->skb = dev_alloc_skb(skb_size);
if (!forw_packet_aggr->skb) {
@@ -418,7 +424,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
kfree(forw_packet_aggr);
goto out;
}
- skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
+ skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
INIT_HLIST_NODE(&forw_packet_aggr->list);
@@ -590,8 +596,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
struct batadv_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *primary_if;
+ int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
int vis_server, tt_num_changes = 0;
uint32_t seqno;
uint8_t bandwidth;
@@ -600,17 +608,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
primary_if = batadv_primary_if_get_selected(bat_priv);
if (hard_iface == primary_if)
- tt_num_changes = batadv_tt_append_diff(bat_priv,
- &hard_iface->packet_buff,
- &hard_iface->packet_len,
+ tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff,
+ ogm_buff_len,
BATADV_OGM_HLEN);
- batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+ batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
/* change sequence number to network order */
- seqno = (uint32_t)atomic_read(&hard_iface->seqno);
+ seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
batadv_ogm_packet->seqno = htonl(seqno);
- atomic_inc(&hard_iface->seqno);
+ atomic_inc(&hard_iface->bat_iv.ogm_seqno);
batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
@@ -631,8 +638,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
}
batadv_slide_own_bcast_window(hard_iface);
- batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
- hard_iface->packet_len, hard_iface, 1,
+ batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
+ hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
batadv_iv_ogm_emit_send_time(bat_priv));
if (primary_if)
@@ -1015,7 +1022,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
return;
/* could be changed by schedule_own_packet() */
- if_incoming_seqno = atomic_read(&if_incoming->seqno);
+ if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
has_directlink_flag = 1;
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index aea174cdbfbd..5453b17d8df2 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
* or the old packet got delayed somewhere in the network. The
* packet should be dropped without calling this function if the
* seqno window is protected.
+ *
+ * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
+ * or
+ * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
*/
- if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
- seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+ "Other host probably restarted!\n");
- batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
- "Other host probably restarted!\n");
-
- bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
- if (set_mark)
- batadv_set_bit(seq_bits, 0);
-
- return 1;
- }
+ bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
+ if (set_mark)
+ batadv_set_bit(seq_bits, 0);
- /* never reached */
- return 0;
+ return 1;
}
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index fd8d5afec0dd..5aebe9327d68 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
/* return the index of the claim */
static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
{
- const unsigned char *key = data;
+ struct batadv_claim *claim = (struct batadv_claim *)data;
uint32_t hash = 0;
- size_t i;
- for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
- hash += key[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
+ hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+ hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
hash += (hash << 3);
hash ^= (hash >> 11);
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
static inline uint32_t batadv_choose_backbone_gw(const void *data,
uint32_t size)
{
- const unsigned char *key = data;
+ struct batadv_claim *claim = (struct batadv_claim *)data;
uint32_t hash = 0;
- size_t i;
- for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
- hash += key[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
+ hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+ hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
hash += (hash << 3);
hash ^= (hash >> 11);
@@ -85,8 +77,15 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
{
const void *data1 = container_of(node, struct batadv_backbone_gw,
hash_entry);
+ const struct batadv_backbone_gw *gw1 = data1, *gw2 = data2;
+
+ if (!batadv_compare_eth(gw1->orig, gw2->orig))
+ return 0;
+
+ if (gw1->vid != gw2->vid)
+ return 0;
- return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+ return 1;
}
/* compares address and vid of two claims */
@@ -95,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node,
{
const void *data1 = container_of(node, struct batadv_claim,
hash_entry);
+ const struct batadv_claim *cl1 = data1, *cl2 = data2;
+
+ if (!batadv_compare_eth(cl1->addr, cl2->addr))
+ return 0;
+
+ if (cl1->vid != cl2->vid)
+ return 0;
- return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+ return 1;
}
/* free a backbone gw */
@@ -362,7 +368,7 @@ out:
*/
static struct batadv_backbone_gw *
batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
- short vid)
+ short vid, bool own_backbone)
{
struct batadv_backbone_gw *entry;
struct batadv_orig_node *orig_node;
@@ -386,6 +392,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
entry->crc = BATADV_BLA_CRC_INIT;
entry->bat_priv = bat_priv;
atomic_set(&entry->request_sent, 0);
+ atomic_set(&entry->wait_periods, 0);
memcpy(entry->orig, orig, ETH_ALEN);
/* one for the hash, one for returning */
@@ -409,6 +416,16 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
"became a backbone gateway");
batadv_orig_node_free_ref(orig_node);
}
+
+ if (own_backbone) {
+ batadv_bla_send_announce(bat_priv, entry);
+
+ /* this will be decreased in the worker thread */
+ atomic_inc(&entry->request_sent);
+ atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
+ atomic_inc(&bat_priv->bla.num_requests);
+ }
+
return entry;
}
@@ -424,7 +441,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
primary_if->net_dev->dev_addr,
- vid);
+ vid, true);
if (unlikely(!backbone_gw))
return;
@@ -632,7 +649,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
return 0;
- backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+ backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+ false);
if (unlikely(!backbone_gw))
return 1;
@@ -730,7 +748,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
/* register the gateway if not yet available, and add the claim. */
- backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+ backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+ false);
if (unlikely(!backbone_gw))
return 1;
@@ -1140,6 +1159,24 @@ static void batadv_bla_periodic_work(struct work_struct *work)
backbone_gw->lasttime = jiffies;
batadv_bla_send_announce(bat_priv, backbone_gw);
+
+ /* request_sent is only set after creation to avoid
+ * problems when we are not yet known as backbone gw
+ * in the backbone.
+ *
+ * We can reset this now after we waited some periods
+ * to give bridge forward delays and bla group forming
+ * some grace time.
+ */
+
+ if (atomic_read(&backbone_gw->request_sent) == 0)
+ continue;
+
+ if (!atomic_dec_and_test(&backbone_gw->wait_periods))
+ continue;
+
+ atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
+ atomic_set(&backbone_gw->request_sent, 0);
}
rcu_read_unlock();
}
@@ -1212,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
/**
* batadv_bla_check_bcast_duplist
* @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: encapsulated broadcast frame plus batman header
- * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
+ * @skb: contains the bcast_packet to be checked
*
* check if it is on our broadcast list. Another gateway might
* have sent the same packet because it is connected to the same backbone,
@@ -1225,20 +1261,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
* the same host however as this might be intended.
*/
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
- struct batadv_bcast_packet *bcast_packet,
- int bcast_packet_len)
+ struct sk_buff *skb)
{
- int i, length, curr, ret = 0;
- uint8_t *content;
- uint16_t crc;
+ int i, curr, ret = 0;
+ __be32 crc;
+ struct batadv_bcast_packet *bcast_packet;
struct batadv_bcast_duplist_entry *entry;
- length = bcast_packet_len - sizeof(*bcast_packet);
- content = (uint8_t *)bcast_packet;
- content += sizeof(*bcast_packet);
+ bcast_packet = (struct batadv_bcast_packet *)skb->data;
/* calculate the crc ... */
- crc = crc16(0, content, length);
+ crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
@@ -1585,23 +1618,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_head *head;
uint32_t i;
bool is_own;
- int ret = 0;
uint8_t *primary_addr;
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
- goto out;
- }
-
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
primary_addr = primary_if->net_dev->dev_addr;
seq_printf(seq,
@@ -1628,7 +1649,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
@@ -1643,23 +1664,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
int secs, msecs;
uint32_t i;
bool is_own;
- int ret = 0;
uint8_t *primary_addr;
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
- goto out;
- }
-
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
primary_addr = primary_if->net_dev->dev_addr;
seq_printf(seq,
@@ -1693,5 +1702,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 789cb73bde67..196d9a0254bc 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -31,8 +31,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
void *offset);
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
- struct batadv_bcast_packet *bcast_packet,
- int hdr_size);
+ struct sk_buff *skb);
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if,
struct batadv_hard_iface *oldif);
@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
static inline int
batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
- struct batadv_bcast_packet *bcast_packet,
- int hdr_size)
+ struct sk_buff *skb)
{
return 0;
}
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 391d4fb2026f..6f58ddd53bff 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -31,6 +31,7 @@
#include "vis.h"
#include "icmp_socket.h"
#include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
static struct dentry *batadv_debugfs;
@@ -99,15 +100,17 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
static int batadv_log_open(struct inode *inode, struct file *file)
{
+ if (!try_module_get(THIS_MODULE))
+ return -EBUSY;
+
nonseekable_open(inode, file);
file->private_data = inode->i_private;
- batadv_inc_module_count();
return 0;
}
static int batadv_log_release(struct inode *inode, struct file *file)
{
- batadv_dec_module_count();
+ module_put(THIS_MODULE);
return 0;
}
@@ -278,6 +281,19 @@ static int batadv_bla_backbone_table_open(struct inode *inode,
#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+/**
+ * batadv_dat_cache_open - Prepare file handler for reads from dat_chache
+ * @inode: inode which was opened
+ * @file: file handle to be initialized
+ */
+static int batadv_dat_cache_open(struct inode *inode, struct file *file)
+{
+ struct net_device *net_dev = (struct net_device *)inode->i_private;
+ return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
+}
+#endif
+
static int batadv_transtable_local_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
@@ -307,7 +323,17 @@ struct batadv_debuginfo batadv_debuginfo_##_name = { \
} \
};
+/* the following attributes are general and therefore they will be directly
+ * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
+ */
static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+
+static struct batadv_debuginfo *batadv_general_debuginfos[] = {
+ &batadv_debuginfo_routing_algos,
+ NULL,
+};
+
+/* The following attributes are per soft interface */
static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
@@ -317,6 +343,9 @@ static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
batadv_bla_backbone_table_open);
#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
+#endif
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
batadv_transtable_local_open);
static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
@@ -329,6 +358,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_bla_claim_table,
&batadv_debuginfo_bla_backbone_table,
#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+ &batadv_debuginfo_dat_cache,
+#endif
&batadv_debuginfo_transtable_local,
&batadv_debuginfo_vis_data,
NULL,
@@ -336,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
void batadv_debugfs_init(void)
{
- struct batadv_debuginfo *bat_debug;
+ struct batadv_debuginfo **bat_debug;
struct dentry *file;
batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
@@ -344,17 +376,23 @@ void batadv_debugfs_init(void)
batadv_debugfs = NULL;
if (!batadv_debugfs)
- goto out;
+ goto err;
- bat_debug = &batadv_debuginfo_routing_algos;
- file = debugfs_create_file(bat_debug->attr.name,
- S_IFREG | bat_debug->attr.mode,
- batadv_debugfs, NULL, &bat_debug->fops);
- if (!file)
- pr_err("Can't add debugfs file: %s\n", bat_debug->attr.name);
+ for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
+ file = debugfs_create_file(((*bat_debug)->attr).name,
+ S_IFREG | ((*bat_debug)->attr).mode,
+ batadv_debugfs, NULL,
+ &(*bat_debug)->fops);
+ if (!file) {
+ pr_err("Can't add general debugfs file: %s\n",
+ ((*bat_debug)->attr).name);
+ goto err;
+ }
+ }
-out:
return;
+err:
+ debugfs_remove_recursive(batadv_debugfs);
}
void batadv_debugfs_destroy(void)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
new file mode 100644
index 000000000000..8e1d89d2b1c1
--- /dev/null
+++ b/net/batman-adv/distributed-arp-table.c
@@ -0,0 +1,1066 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * 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-1301, USA
+ */
+
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include "main.h"
+#include "hash.h"
+#include "distributed-arp-table.h"
+#include "hard-interface.h"
+#include "originator.h"
+#include "send.h"
+#include "types.h"
+#include "translation-table.h"
+#include "unicast.h"
+
+static void batadv_dat_purge(struct work_struct *work);
+
+/**
+ * batadv_dat_start_timer - initialise the DAT periodic worker
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
+{
+ INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
+ queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work,
+ msecs_to_jiffies(10000));
+}
+
+/**
+ * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly
+ * free it
+ * @dat_entry: the oentry to free
+ */
+static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
+{
+ if (atomic_dec_and_test(&dat_entry->refcount))
+ kfree_rcu(dat_entry, rcu);
+}
+
+/**
+ * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not
+ * @dat_entry: the entry to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
+{
+ return batadv_has_timed_out(dat_entry->last_update,
+ BATADV_DAT_ENTRY_TIMEOUT);
+}
+
+/**
+ * __batadv_dat_purge - delete entries from the DAT local storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ * not. This function takes the dat_entry as argument and has to
+ * returns a boolean value: true is the entry has to be deleted,
+ * false otherwise
+ *
+ * Loops over each entry in the DAT local storage and delete it if and only if
+ * the to_purge function passed as argument returns true
+ */
+static void __batadv_dat_purge(struct batadv_priv *bat_priv,
+ bool (*to_purge)(struct batadv_dat_entry *))
+{
+ spinlock_t *list_lock; /* protects write access to the hash lists */
+ struct batadv_dat_entry *dat_entry;
+ struct hlist_node *node, *node_tmp;
+ struct hlist_head *head;
+ uint32_t i;
+
+ if (!bat_priv->dat.hash)
+ return;
+
+ for (i = 0; i < bat_priv->dat.hash->size; i++) {
+ head = &bat_priv->dat.hash->table[i];
+ list_lock = &bat_priv->dat.hash->list_locks[i];
+
+ spin_lock_bh(list_lock);
+ hlist_for_each_entry_safe(dat_entry, node, node_tmp, head,
+ hash_entry) {
+ /* if an helper function has been passed as parameter,
+ * ask it if the entry has to be purged or not
+ */
+ if (to_purge && !to_purge(dat_entry))
+ continue;
+
+ hlist_del_rcu(node);
+ batadv_dat_entry_free_ref(dat_entry);
+ }
+ spin_unlock_bh(list_lock);
+ }
+}
+
+/**
+ * batadv_dat_purge - periodic task that deletes old entries from the local DAT
+ * hash table
+ * @work: kernel work struct
+ */
+static void batadv_dat_purge(struct work_struct *work)
+{
+ struct delayed_work *delayed_work;
+ struct batadv_priv_dat *priv_dat;
+ struct batadv_priv *bat_priv;
+
+ delayed_work = container_of(work, struct delayed_work, work);
+ priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
+ bat_priv = container_of(priv_dat, struct batadv_priv, dat);
+
+ __batadv_dat_purge(bat_priv, batadv_dat_to_purge);
+ batadv_dat_start_timer(bat_priv);
+}
+
+/**
+ * batadv_compare_dat - comparing function used in the local DAT hash table
+ * @node: node in the local table
+ * @data2: second object to compare the node to
+ *
+ * Returns 1 if the two entry are the same, 0 otherwise
+ */
+static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
+{
+ const void *data1 = container_of(node, struct batadv_dat_entry,
+ hash_entry);
+
+ return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+}
+
+/**
+ * batadv_arp_hw_src - extract the hw_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_src field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
+{
+ uint8_t *addr;
+
+ addr = (uint8_t *)(skb->data + hdr_size);
+ addr += ETH_HLEN + sizeof(struct arphdr);
+
+ return addr;
+}
+
+/**
+ * batadv_arp_ip_src - extract the ip_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_src field in the ARP packet
+ */
+static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
+{
+ return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
+}
+
+/**
+ * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_dst field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
+{
+ return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4;
+}
+
+/**
+ * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_dst field in the ARP packet
+ */
+static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
+{
+ return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4);
+}
+
+/**
+ * batadv_hash_dat - compute the hash value for an IP address
+ * @data: data to hash
+ * @size: size of the hash table
+ *
+ * Returns the selected index in the hash table for the given data
+ */
+static uint32_t batadv_hash_dat(const void *data, uint32_t size)
+{
+ const unsigned char *key = data;
+ uint32_t hash = 0;
+ size_t i;
+
+ for (i = 0; i < 4; i++) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash % size;
+}
+
+/**
+ * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash
+ * table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: search key
+ *
+ * Returns the dat_entry if found, NULL otherwise
+ */
+static struct batadv_dat_entry *
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
+ struct batadv_hashtable *hash = bat_priv->dat.hash;
+ uint32_t index;
+
+ if (!hash)
+ return NULL;
+
+ index = batadv_hash_dat(&ip, hash->size);
+ head = &hash->table[index];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+ if (dat_entry->ip != ip)
+ continue;
+
+ if (!atomic_inc_not_zero(&dat_entry->refcount))
+ continue;
+
+ dat_entry_tmp = dat_entry;
+ break;
+ }
+ rcu_read_unlock();
+
+ return dat_entry_tmp;
+}
+
+/**
+ * batadv_dat_entry_add - add a new dat entry or update it if already exists
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ */
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+ uint8_t *mac_addr)
+{
+ struct batadv_dat_entry *dat_entry;
+ int hash_added;
+
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
+ /* if this entry is already known, just update it */
+ if (dat_entry) {
+ if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
+ memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+ dat_entry->last_update = jiffies;
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "Entry updated: %pI4 %pM\n", &dat_entry->ip,
+ dat_entry->mac_addr);
+ goto out;
+ }
+
+ dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC);
+ if (!dat_entry)
+ goto out;
+
+ dat_entry->ip = ip;
+ memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+ dat_entry->last_update = jiffies;
+ atomic_set(&dat_entry->refcount, 2);
+
+ hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
+ batadv_hash_dat, &dat_entry->ip,
+ &dat_entry->hash_entry);
+
+ if (unlikely(hash_added != 0)) {
+ /* remove the reference for the hash */
+ batadv_dat_entry_free_ref(dat_entry);
+ goto out;
+ }
+
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
+ &dat_entry->ip, dat_entry->mac_addr);
+
+out:
+ if (dat_entry)
+ batadv_dat_entry_free_ref(dat_entry);
+}
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+
+/**
+ * batadv_dbg_arp - print a debug message containing all the ARP packet details
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: ARP packet
+ * @type: ARP type
+ * @hdr_size: size of the possible header before the ARP packet
+ * @msg: message to print together with the debugging information
+ */
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+ uint16_t type, int hdr_size, char *msg)
+{
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+ struct batadv_bcast_packet *bcast_pkt;
+ uint8_t *orig_addr;
+ __be32 ip_src, ip_dst;
+
+ if (msg)
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
+
+ ip_src = batadv_arp_ip_src(skb, hdr_size);
+ ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n",
+ batadv_arp_hw_src(skb, hdr_size), &ip_src,
+ batadv_arp_hw_dst(skb, hdr_size), &ip_dst);
+
+ if (hdr_size == 0)
+ return;
+
+ /* if the ARP packet is encapsulated in a batman packet, let's print
+ * some debug messages
+ */
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+ switch (unicast_4addr_packet->u.header.packet_type) {
+ case BATADV_UNICAST:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "* encapsulated within a UNICAST packet\n");
+ break;
+ case BATADV_UNICAST_4ADDR:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n",
+ unicast_4addr_packet->src);
+ switch (unicast_4addr_packet->subtype) {
+ case BATADV_P_DAT_DHT_PUT:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n");
+ break;
+ case BATADV_P_DAT_DHT_GET:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n");
+ break;
+ case BATADV_P_DAT_CACHE_REPLY:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "* type: DAT_CACHE_REPLY\n");
+ break;
+ case BATADV_P_DATA:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n");
+ break;
+ default:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
+ unicast_4addr_packet->u.header.packet_type);
+ }
+ break;
+ case BATADV_BCAST:
+ bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet;
+ orig_addr = bcast_pkt->orig;
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "* encapsulated within a BCAST packet (src: %pM)\n",
+ orig_addr);
+ break;
+ default:
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "* encapsulated within an unknown packet type (0x%x)\n",
+ unicast_4addr_packet->u.header.packet_type);
+ }
+}
+
+#else
+
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+ uint16_t type, int hdr_size, char *msg)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DEBUG */
+
+/**
+ * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate
+ * @res: the array with the already selected candidates
+ * @select: number of already selected candidates
+ * @tmp_max: address of the currently evaluated node
+ * @max: current round max address
+ * @last_max: address of the last selected candidate
+ * @candidate: orig_node under evaluation
+ * @max_orig_node: last selected candidate
+ *
+ * Returns true if the node has been elected as next candidate or false othrwise
+ */
+static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
+ int select, batadv_dat_addr_t tmp_max,
+ batadv_dat_addr_t max,
+ batadv_dat_addr_t last_max,
+ struct batadv_orig_node *candidate,
+ struct batadv_orig_node *max_orig_node)
+{
+ bool ret = false;
+ int j;
+
+ /* Check if this node has already been selected... */
+ for (j = 0; j < select; j++)
+ if (res[j].orig_node == candidate)
+ break;
+ /* ..and possibly skip it */
+ if (j < select)
+ goto out;
+ /* sanity check: has it already been selected? This should not happen */
+ if (tmp_max > last_max)
+ goto out;
+ /* check if during this iteration an originator with a closer dht
+ * address has already been found
+ */
+ if (tmp_max < max)
+ goto out;
+ /* this is an hash collision with the temporary selected node. Choose
+ * the one with the lowest address
+ */
+ if ((tmp_max == max) &&
+ (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0))
+ goto out;
+
+ ret = true;
+out:
+ return ret;
+}
+
+/**
+ * batadv_choose_next_candidate - select the next DHT candidate
+ * @bat_priv: the bat priv with all the soft interface information
+ * @cands: candidates array
+ * @select: number of candidates already present in the array
+ * @ip_key: key to look up in the DHT
+ * @last_max: pointer where the address of the selected candidate will be saved
+ */
+static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
+ struct batadv_dat_candidate *cands,
+ int select, batadv_dat_addr_t ip_key,
+ batadv_dat_addr_t *last_max)
+{
+ batadv_dat_addr_t max = 0, tmp_max = 0;
+ struct batadv_orig_node *orig_node, *max_orig_node = NULL;
+ struct batadv_hashtable *hash = bat_priv->orig_hash;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ int i;
+
+ /* if no node is eligible as candidate, leave the candidate type as
+ * NOT_FOUND
+ */
+ cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND;
+
+ /* iterate over the originator list and find the node with closest
+ * dat_address which has not been selected yet
+ */
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+ /* the dht space is a ring and addresses are unsigned */
+ tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr +
+ ip_key;
+
+ if (!batadv_is_orig_node_eligible(cands, select,
+ tmp_max, max,
+ *last_max, orig_node,
+ max_orig_node))
+ continue;
+
+ if (!atomic_inc_not_zero(&orig_node->refcount))
+ continue;
+
+ max = tmp_max;
+ if (max_orig_node)
+ batadv_orig_node_free_ref(max_orig_node);
+ max_orig_node = orig_node;
+ }
+ rcu_read_unlock();
+ }
+ if (max_orig_node) {
+ cands[select].type = BATADV_DAT_CANDIDATE_ORIG;
+ cands[select].orig_node = max_orig_node;
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n",
+ select, max_orig_node->orig, max_orig_node->dat_addr,
+ max);
+ }
+ *last_max = max;
+}
+
+/**
+ * batadv_dat_select_candidates - selects the nodes which the DHT message has to
+ * be sent to
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip_dst: ipv4 to look up in the DHT
+ *
+ * An originator O is selected if and only if its DHT_ID value is one of three
+ * closest values (from the LEFT, with wrap around if needed) then the hash
+ * value of the key. ip_dst is the key.
+ *
+ * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM
+ */
+static struct batadv_dat_candidate *
+batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+{
+ int select;
+ batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
+ struct batadv_dat_candidate *res;
+
+ if (!bat_priv->orig_hash)
+ return NULL;
+
+ res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC);
+ if (!res)
+ return NULL;
+
+ ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
+ BATADV_DAT_ADDR_MAX);
+
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
+ ip_key);
+
+ for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
+ batadv_choose_next_candidate(bat_priv, res, select, ip_key,
+ &last_max);
+
+ return res;
+}
+
+/**
+ * batadv_dat_send_data - send a payload to the selected candidates
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @ip: the DHT key
+ * @packet_subtype: unicast4addr packet subtype to use
+ *
+ * In this function the skb is copied by means of pskb_copy() and is sent as
+ * unicast packet to each of the selected candidates
+ *
+ * Returns true if the packet is sent to at least one candidate, false otherwise
+ */
+static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, __be32 ip,
+ int packet_subtype)
+{
+ int i;
+ bool ret = false;
+ int send_status;
+ struct batadv_neigh_node *neigh_node = NULL;
+ struct sk_buff *tmp_skb;
+ struct batadv_dat_candidate *cand;
+
+ cand = batadv_dat_select_candidates(bat_priv, ip);
+ if (!cand)
+ goto out;
+
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+
+ for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
+ if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
+ continue;
+
+ neigh_node = batadv_orig_node_get_router(cand[i].orig_node);
+ if (!neigh_node)
+ goto free_orig;
+
+ tmp_skb = pskb_copy(skb, GFP_ATOMIC);
+ if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb,
+ cand[i].orig_node,
+ packet_subtype)) {
+ kfree_skb(tmp_skb);
+ goto free_neigh;
+ }
+
+ send_status = batadv_send_skb_packet(tmp_skb,
+ neigh_node->if_incoming,
+ neigh_node->addr);
+ if (send_status == NET_XMIT_SUCCESS) {
+ /* count the sent packet */
+ switch (packet_subtype) {
+ case BATADV_P_DAT_DHT_GET:
+ batadv_inc_counter(bat_priv,
+ BATADV_CNT_DAT_GET_TX);
+ break;
+ case BATADV_P_DAT_DHT_PUT:
+ batadv_inc_counter(bat_priv,
+ BATADV_CNT_DAT_PUT_TX);
+ break;
+ }
+
+ /* packet sent to a candidate: return true */
+ ret = true;
+ }
+free_neigh:
+ batadv_neigh_node_free_ref(neigh_node);
+free_orig:
+ batadv_orig_node_free_ref(cand[i].orig_node);
+ }
+
+out:
+ kfree(cand);
+ return ret;
+}
+
+/**
+ * batadv_dat_hash_free - free the local DAT hash table
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
+{
+ if (!bat_priv->dat.hash)
+ return;
+
+ __batadv_dat_purge(bat_priv, NULL);
+
+ batadv_hash_destroy(bat_priv->dat.hash);
+
+ bat_priv->dat.hash = NULL;
+}
+
+/**
+ * batadv_dat_init - initialise the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+ if (bat_priv->dat.hash)
+ return 0;
+
+ bat_priv->dat.hash = batadv_hash_new(1024);
+
+ if (!bat_priv->dat.hash)
+ return -ENOMEM;
+
+ batadv_dat_start_timer(bat_priv);
+
+ return 0;
+}
+
+/**
+ * batadv_dat_free - free the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+ cancel_delayed_work_sync(&bat_priv->dat.work);
+
+ batadv_dat_hash_free(bat_priv);
+}
+
+/**
+ * batadv_dat_cache_seq_print_text - print the local DAT hash table
+ * @seq: seq file to print on
+ * @offset: not used
+ */
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
+{
+ struct net_device *net_dev = (struct net_device *)seq->private;
+ struct batadv_priv *bat_priv = netdev_priv(net_dev);
+ struct batadv_hashtable *hash = bat_priv->dat.hash;
+ struct batadv_dat_entry *dat_entry;
+ struct batadv_hard_iface *primary_if;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ unsigned long last_seen_jiffies;
+ int last_seen_msecs, last_seen_secs, last_seen_mins;
+ uint32_t i;
+
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
+ goto out;
+
+ seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
+ seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
+ "last-seen");
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+ last_seen_jiffies = jiffies - dat_entry->last_update;
+ last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
+ last_seen_mins = last_seen_msecs / 60000;
+ last_seen_msecs = last_seen_msecs % 60000;
+ last_seen_secs = last_seen_msecs / 1000;
+
+ seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
+ &dat_entry->ip, dat_entry->mac_addr,
+ last_seen_mins, last_seen_secs);
+ }
+ rcu_read_unlock();
+ }
+
+out:
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ return 0;
+}
+
+/**
+ * batadv_arp_get_type - parse an ARP packet and gets the type
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to analyse
+ * @hdr_size: size of the possible header before the ARP packet in the skb
+ *
+ * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise
+ */
+static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ struct arphdr *arphdr;
+ struct ethhdr *ethhdr;
+ __be32 ip_src, ip_dst;
+ uint16_t type = 0;
+
+ /* pull the ethernet header */
+ if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
+ goto out;
+
+ ethhdr = (struct ethhdr *)(skb->data + hdr_size);
+
+ if (ethhdr->h_proto != htons(ETH_P_ARP))
+ goto out;
+
+ /* pull the ARP payload */
+ if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN +
+ arp_hdr_len(skb->dev))))
+ goto out;
+
+ arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN);
+
+ /* Check whether the ARP packet carries a valid
+ * IP information
+ */
+ if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
+ goto out;
+
+ if (arphdr->ar_pro != htons(ETH_P_IP))
+ goto out;
+
+ if (arphdr->ar_hln != ETH_ALEN)
+ goto out;
+
+ if (arphdr->ar_pln != 4)
+ goto out;
+
+ /* Check for bad reply/request. If the ARP message is not sane, DAT
+ * will simply ignore it
+ */
+ ip_src = batadv_arp_ip_src(skb, hdr_size);
+ ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+ if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
+ ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
+ goto out;
+
+ type = ntohs(arphdr->ar_op);
+out:
+ return type;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
+ * answer using DAT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ *
+ * Returns true if the message has been sent to the dht candidates, false
+ * otherwise. In case of true the message has to be enqueued to permit the
+ * fallback
+ */
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ uint16_t type = 0;
+ __be32 ip_dst, ip_src;
+ uint8_t *hw_src;
+ bool ret = false;
+ struct batadv_dat_entry *dat_entry = NULL;
+ struct sk_buff *skb_new;
+ struct batadv_hard_iface *primary_if = NULL;
+
+ if (!atomic_read(&bat_priv->distributed_arp_table))
+ goto out;
+
+ type = batadv_arp_get_type(bat_priv, skb, 0);
+ /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
+ * message to the selected DHT candidates
+ */
+ if (type != ARPOP_REQUEST)
+ goto out;
+
+ batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST");
+
+ ip_src = batadv_arp_ip_src(skb, 0);
+ hw_src = batadv_arp_hw_src(skb, 0);
+ ip_dst = batadv_arp_ip_dst(skb, 0);
+
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ if (dat_entry) {
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+ primary_if->soft_iface, ip_dst, hw_src,
+ dat_entry->mac_addr, hw_src);
+ if (!skb_new)
+ goto out;
+
+ skb_reset_mac_header(skb_new);
+ skb_new->protocol = eth_type_trans(skb_new,
+ primary_if->soft_iface);
+ bat_priv->stats.rx_packets++;
+ bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
+ primary_if->soft_iface->last_rx = jiffies;
+
+ netif_rx(skb_new);
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
+ ret = true;
+ } else {
+ /* Send the request on the DHT */
+ ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
+ BATADV_P_DAT_DHT_GET);
+ }
+out:
+ if (dat_entry)
+ batadv_dat_entry_free_ref(dat_entry);
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ return ret;
+}
+
+/**
+ * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to
+ * answer using the local DAT storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: size of the encapsulation header
+ *
+ * Returns true if the request has been answered, false otherwise
+ */
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ uint16_t type;
+ __be32 ip_src, ip_dst;
+ uint8_t *hw_src;
+ struct sk_buff *skb_new;
+ struct batadv_hard_iface *primary_if = NULL;
+ struct batadv_dat_entry *dat_entry = NULL;
+ bool ret = false;
+ int err;
+
+ if (!atomic_read(&bat_priv->distributed_arp_table))
+ goto out;
+
+ type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+ if (type != ARPOP_REQUEST)
+ goto out;
+
+ hw_src = batadv_arp_hw_src(skb, hdr_size);
+ ip_src = batadv_arp_ip_src(skb, hdr_size);
+ ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+ batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+ "Parsing incoming ARP REQUEST");
+
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ if (!dat_entry)
+ goto out;
+
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+ primary_if->soft_iface, ip_dst, hw_src,
+ dat_entry->mac_addr, hw_src);
+
+ if (!skb_new)
+ goto out;
+
+ /* to preserve backwards compatibility, here the node has to answer
+ * using the same packet type it received for the request. This is due
+ * to that if a node is not using the 4addr packet format it may not
+ * support it.
+ */
+ if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
+ err = batadv_unicast_4addr_send_skb(bat_priv, skb_new,
+ BATADV_P_DAT_CACHE_REPLY);
+ else
+ err = batadv_unicast_send_skb(bat_priv, skb_new);
+
+ if (!err) {
+ batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
+ ret = true;
+ }
+out:
+ if (dat_entry)
+ batadv_dat_entry_free_ref(dat_entry);
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ if (ret)
+ kfree_skb(skb);
+ return ret;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ */
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ uint16_t type;
+ __be32 ip_src, ip_dst;
+ uint8_t *hw_src, *hw_dst;
+
+ if (!atomic_read(&bat_priv->distributed_arp_table))
+ return;
+
+ type = batadv_arp_get_type(bat_priv, skb, 0);
+ if (type != ARPOP_REPLY)
+ return;
+
+ batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY");
+
+ hw_src = batadv_arp_hw_src(skb, 0);
+ ip_src = batadv_arp_ip_src(skb, 0);
+ hw_dst = batadv_arp_hw_dst(skb, 0);
+ ip_dst = batadv_arp_ip_dst(skb, 0);
+
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+ /* Send the ARP reply to the candidates for both the IP addresses that
+ * the node got within the ARP reply
+ */
+ batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+}
+/**
+ * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
+ * DAT storage only
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: siaze of the encapsulation header
+ */
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ uint16_t type;
+ __be32 ip_src, ip_dst;
+ uint8_t *hw_src, *hw_dst;
+ bool ret = false;
+
+ if (!atomic_read(&bat_priv->distributed_arp_table))
+ goto out;
+
+ type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+ if (type != ARPOP_REPLY)
+ goto out;
+
+ batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+ "Parsing incoming ARP REPLY");
+
+ hw_src = batadv_arp_hw_src(skb, hdr_size);
+ ip_src = batadv_arp_ip_src(skb, hdr_size);
+ hw_dst = batadv_arp_hw_dst(skb, hdr_size);
+ ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+ /* Update our internal cache with both the IP addresses the node got
+ * within the ARP reply
+ */
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+ /* if this REPLY is directed to a client of mine, let's deliver the
+ * packet to the interface
+ */
+ ret = !batadv_is_my_client(bat_priv, hw_dst);
+out:
+ /* if ret == false -> packet has to be delivered to the interface */
+ return ret;
+}
+
+/**
+ * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped
+ * (because the node has already got the reply via DAT) or not
+ * @bat_priv: the bat priv with all the soft interface information
+ * @forw_packet: the broadcast packet
+ *
+ * Returns true if the node can drop the packet, false otherwise
+ */
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet)
+{
+ uint16_t type;
+ __be32 ip_dst;
+ struct batadv_dat_entry *dat_entry = NULL;
+ bool ret = false;
+ const size_t bcast_len = sizeof(struct batadv_bcast_packet);
+
+ if (!atomic_read(&bat_priv->distributed_arp_table))
+ goto out;
+
+ /* If this packet is an ARP_REQUEST and the node already has the
+ * information that it is going to ask, then the packet can be dropped
+ */
+ if (forw_packet->num_packets)
+ goto out;
+
+ type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len);
+ if (type != ARPOP_REQUEST)
+ goto out;
+
+ ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ /* check if the node already got this entry */
+ if (!dat_entry) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "ARP Request for %pI4: fallback\n", &ip_dst);
+ goto out;
+ }
+
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "ARP Request for %pI4: fallback prevented\n", &ip_dst);
+ ret = true;
+
+out:
+ if (dat_entry)
+ batadv_dat_entry_free_ref(dat_entry);
+ return ret;
+}
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
new file mode 100644
index 000000000000..d060c033e7de
--- /dev/null
+++ b/net/batman-adv/distributed-arp-table.h
@@ -0,0 +1,167 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * 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-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_ARP_H_
+#define _NET_BATMAN_ADV_ARP_H_
+
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+#include "types.h"
+#include "originator.h"
+
+#include <linux/if_arp.h>
+
+#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
+
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size);
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size);
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet);
+
+/**
+ * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node
+ * @orig_node: the node to assign the DAT address to
+ */
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+ uint32_t addr;
+
+ addr = batadv_choose_orig(orig_node->orig, BATADV_DAT_ADDR_MAX);
+ orig_node->dat_addr = (batadv_dat_addr_t)addr;
+}
+
+/**
+ * batadv_dat_init_own_addr - assign a DAT address to the node itself
+ * @bat_priv: the bat priv with all the soft interface information
+ * @primary_if: a pointer to the primary interface
+ */
+static inline void
+batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+ struct batadv_hard_iface *primary_if)
+{
+ uint32_t addr;
+
+ addr = batadv_choose_orig(primary_if->net_dev->dev_addr,
+ BATADV_DAT_ADDR_MAX);
+
+ bat_priv->dat.addr = (batadv_dat_addr_t)addr;
+}
+
+int batadv_dat_init(struct batadv_priv *bat_priv);
+void batadv_dat_free(struct batadv_priv *bat_priv);
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset);
+
+/**
+ * batadv_dat_inc_counter - increment the correct DAT packet counter
+ * @bat_priv: the bat priv with all the soft interface information
+ * @subtype: the 4addr subtype of the packet to be counted
+ *
+ * Updates the ethtool statistics for the received packet if it is a DAT subtype
+ */
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+ uint8_t subtype)
+{
+ switch (subtype) {
+ case BATADV_P_DAT_DHT_GET:
+ batadv_inc_counter(bat_priv,
+ BATADV_CNT_DAT_GET_RX);
+ break;
+ case BATADV_P_DAT_DHT_PUT:
+ batadv_inc_counter(bat_priv,
+ BATADV_CNT_DAT_PUT_RX);
+ break;
+ }
+}
+
+#else
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ return false;
+}
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ return false;
+}
+
+static inline bool
+batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+ struct batadv_forw_packet *forw_packet)
+{
+ return false;
+}
+
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+}
+
+static inline void batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+ struct batadv_hard_iface *iface)
+{
+}
+
+static inline void batadv_arp_change_timeout(struct net_device *soft_iface,
+ const char *name)
+{
+}
+
+static inline int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+ return 0;
+}
+
+static inline void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+}
+
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+ uint8_t subtype)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+#endif /* _NET_BATMAN_ADV_ARP_H_ */
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 15d67abc10a4..dd07c7e3654f 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
struct batadv_hard_iface *primary_if;
struct batadv_gw_node *gw_node;
struct hlist_node *node;
- int gw_count = 0, ret = 0;
+ int gw_count = 0;
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
-
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
- goto out;
- }
seq_printf(seq,
" %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
@@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index d112fd6750b0..f1d37cd81815 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -18,6 +18,7 @@
*/
#include "main.h"
+#include "distributed-arp-table.h"
#include "hard-interface.h"
#include "soft-interface.h"
#include "send.h"
@@ -29,6 +30,7 @@
#include "bridge_loop_avoidance.h"
#include <linux/if_arp.h>
+#include <linux/if_ether.h>
void batadv_hardif_free_rcu(struct rcu_head *rcu)
{
@@ -58,6 +60,45 @@ out:
return hard_iface;
}
+/**
+ * batadv_is_on_batman_iface - check if a device is a batman iface descendant
+ * @net_dev: the device to check
+ *
+ * If the user creates any virtual device on top of a batman-adv interface, it
+ * is important to prevent this new interface to be used to create a new mesh
+ * network (this behaviour would lead to a batman-over-batman configuration).
+ * This function recursively checks all the fathers of the device passed as
+ * argument looking for a batman-adv soft interface.
+ *
+ * Returns true if the device is descendant of a batman-adv mesh interface (or
+ * if it is a batman-adv interface itself), false otherwise
+ */
+static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
+{
+ struct net_device *parent_dev;
+ bool ret;
+
+ /* check if this is a batman-adv mesh interface */
+ if (batadv_softif_is_valid(net_dev))
+ return true;
+
+ /* no more parents..stop recursion */
+ if (net_dev->iflink == net_dev->ifindex)
+ return false;
+
+ /* recurse over the parent device */
+ parent_dev = dev_get_by_index(&init_net, net_dev->iflink);
+ /* if we got a NULL parent_dev there is something broken.. */
+ if (WARN(!parent_dev, "Cannot find parent device"))
+ return false;
+
+ ret = batadv_is_on_batman_iface(parent_dev);
+
+ if (parent_dev)
+ dev_put(parent_dev);
+ return ret;
+}
+
static int batadv_is_valid_iface(const struct net_device *net_dev)
{
if (net_dev->flags & IFF_LOOPBACK)
@@ -70,7 +111,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)
return 0;
/* no batman over batman */
- if (batadv_softif_is_valid(net_dev))
+ if (batadv_is_on_batman_iface(net_dev))
return 0;
return 1;
@@ -109,6 +150,8 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
if (!primary_if)
goto out;
+ batadv_dat_init_own_addr(bat_priv, primary_if);
+
skb = bat_priv->vis.my_info->skb_packet;
vis_packet = (struct batadv_vis_packet *)skb->data;
memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
@@ -269,7 +312,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
{
struct batadv_priv *bat_priv;
struct net_device *soft_iface;
- __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
+ __be16 ethertype = __constant_htons(ETH_P_BATMAN);
int ret;
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
@@ -450,8 +493,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
/* This can't be called via a bat_priv callback because
* we have no bat_priv yet.
*/
- atomic_set(&hard_iface->seqno, 1);
- hard_iface->packet_buff = NULL;
+ atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
+ hard_iface->bat_iv.ogm_buff = NULL;
return hard_iface;
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 977de9c75fc2..e05333905afd 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -82,6 +82,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash,
}
/**
+ * batadv_hash_bytes - hash some bytes and add them to the previous hash
+ * @hash: previous hash value
+ * @data: data to be hashed
+ * @size: number of bytes to be hashed
+ *
+ * Returns the new hash value.
+ */
+static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data,
+ uint32_t size)
+{
+ const unsigned char *key = data;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ return hash;
+}
+
+/**
* batadv_hash_add - adds data to the hashtable
* @hash: storage hash table
* @compare: callback to determine if 2 hash elements are identical
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index bde3cf747507..87ca8095b011 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
unsigned int i;
struct batadv_socket_client *socket_client;
+ if (!try_module_get(THIS_MODULE))
+ return -EBUSY;
+
nonseekable_open(inode, file);
socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
-
- if (!socket_client)
+ if (!socket_client) {
+ module_put(THIS_MODULE);
return -ENOMEM;
+ }
for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
if (!batadv_socket_client_hash[i]) {
@@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
pr_err("Error - can't add another packet client: maximum number of clients reached\n");
kfree(socket_client);
+ module_put(THIS_MODULE);
return -EXFULL;
}
@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
file->private_data = socket_client;
- batadv_inc_module_count();
return 0;
}
@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file)
spin_unlock_bh(&socket_client->lock);
kfree(socket_client);
- batadv_dec_module_count();
+ module_put(THIS_MODULE);
return 0;
}
@@ -173,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
if (len >= sizeof(struct batadv_icmp_packet_rr))
packet_len = sizeof(struct batadv_icmp_packet_rr);
- skb = dev_alloc_skb(packet_len + ETH_HLEN);
+ skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
if (!skb) {
len = -ENOMEM;
goto out;
}
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
if (copy_from_user(icmp_packet, buff, packet_len)) {
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b4aa470bc4a6..f65a222b7b83 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -17,6 +17,8 @@
* 02110-1301, USA
*/
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
#include "main.h"
#include "sysfs.h"
#include "debugfs.h"
@@ -29,6 +31,7 @@
#include "hard-interface.h"
#include "gateway_client.h"
#include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
#include "vis.h"
#include "hash.h"
#include "bat_algo.h"
@@ -128,6 +131,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
if (ret < 0)
goto err;
+ ret = batadv_dat_init(bat_priv);
+ if (ret < 0)
+ goto err;
+
atomic_set(&bat_priv->gw.reselect, 0);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
@@ -155,21 +162,13 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_bla_free(bat_priv);
+ batadv_dat_free(bat_priv);
+
free_percpu(bat_priv->bat_counters);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
}
-void batadv_inc_module_count(void)
-{
- try_module_get(THIS_MODULE);
-}
-
-void batadv_dec_module_count(void)
-{
- module_put(THIS_MODULE);
-}
-
int batadv_is_my_mac(const uint8_t *addr)
{
const struct batadv_hard_iface *hard_iface;
@@ -188,6 +187,42 @@ int batadv_is_my_mac(const uint8_t *addr)
return 0;
}
+/**
+ * batadv_seq_print_text_primary_if_get - called from debugfs table printing
+ * function that requires the primary interface
+ * @seq: debugfs table seq_file struct
+ *
+ * Returns primary interface if found or NULL otherwise.
+ */
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq)
+{
+ struct net_device *net_dev = (struct net_device *)seq->private;
+ struct batadv_priv *bat_priv = netdev_priv(net_dev);
+ struct batadv_hard_iface *primary_if;
+
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+
+ if (!primary_if) {
+ seq_printf(seq,
+ "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
+ net_dev->name);
+ goto out;
+ }
+
+ if (primary_if->if_status == BATADV_IF_ACTIVE)
+ goto out;
+
+ seq_printf(seq,
+ "BATMAN mesh %s disabled - primary interface not active\n",
+ net_dev->name);
+ batadv_hardif_free_ref(primary_if);
+ primary_if = NULL;
+
+out:
+ return primary_if;
+}
+
static int batadv_recv_unhandled_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
@@ -274,6 +309,8 @@ static void batadv_recv_handler_init(void)
/* batman icmp packet */
batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
+ /* unicast with 4 addresses packet */
+ batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
/* unicast packet */
batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
/* fragmented unicast packet */
@@ -385,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
return 0;
}
+/**
+ * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
+ * the header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ * marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to an address in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
+{
+ u32 crc = 0;
+ unsigned int from;
+ unsigned int to = skb->len;
+ struct skb_seq_state st;
+ const u8 *data;
+ unsigned int len;
+ unsigned int consumed = 0;
+
+ from = (unsigned int)(payload_ptr - skb->data);
+
+ skb_prepare_seq_read(skb, from, to, &st);
+ while ((len = skb_seq_read(consumed, &data, &st)) != 0) {
+ crc = crc32c(crc, data, len);
+ consumed += len;
+ }
+ skb_abort_seq_read(&st);
+
+ return htonl(crc);
+}
+
static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
{
struct batadv_algo_ops *bat_algo_ops;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index d57b746219de..2f85577086a7 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -26,7 +26,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2012.4.0"
+#define BATADV_SOURCE_VERSION "2012.5.0"
#endif
/* B.A.T.M.A.N. parameters */
@@ -44,6 +44,7 @@
#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
+#define BATADV_DAT_ENTRY_TIMEOUT (5*60000) /* 5 mins in milliseconds */
/* sliding packet range of received originator messages in sequence numbers
* (should be a multiple of our word size)
*/
@@ -73,6 +74,11 @@
#define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */
+/* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
+#define ARP_REQ_DELAY 250
+/* numbers of originator to contact for any PUT/GET DHT operation */
+#define BATADV_DAT_CANDIDATES_NUM 3
+
#define BATADV_VIS_INTERVAL 5000 /* 5 seconds */
/* how much worse secondary interfaces may be to be considered as bonding
@@ -89,6 +95,7 @@
#define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */
#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3)
#define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10)
+#define BATADV_BLA_WAIT_PERIODS 3
#define BATADV_DUPLIST_SIZE 16
#define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */
@@ -117,6 +124,9 @@ enum batadv_uev_type {
#define BATADV_GW_THRESHOLD 50
+#define BATADV_DAT_CANDIDATE_NOT_FOUND 0
+#define BATADV_DAT_CANDIDATE_ORIG 1
+
/* Debug Messages */
#ifdef pr_fmt
#undef pr_fmt
@@ -150,9 +160,9 @@ extern struct workqueue_struct *batadv_event_workqueue;
int batadv_mesh_init(struct net_device *soft_iface);
void batadv_mesh_free(struct net_device *soft_iface);
-void batadv_inc_module_count(void);
-void batadv_dec_module_count(void);
int batadv_is_my_mac(const uint8_t *addr);
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq);
int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
struct net_device *orig_dev);
@@ -164,14 +174,24 @@ void batadv_recv_handler_unregister(uint8_t packet_type);
int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
-/* all messages related to routing / flooding / broadcasting / etc */
+/**
+ * enum batadv_dbg_level - available log levels
+ * @BATADV_DBG_BATMAN: OGM and TQ computations related messages
+ * @BATADV_DBG_ROUTES: route added / changed / deleted
+ * @BATADV_DBG_TT: translation table messages
+ * @BATADV_DBG_BLA: bridge loop avoidance messages
+ * @BATADV_DBG_DAT: ARP snooping and DAT related messages
+ * @BATADV_DBG_ALL: the union of all the above log levels
+ */
enum batadv_dbg_level {
BATADV_DBG_BATMAN = BIT(0),
- BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */
- BATADV_DBG_TT = BIT(2), /* translation table operations */
- BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */
- BATADV_DBG_ALL = 15,
+ BATADV_DBG_ROUTES = BIT(1),
+ BATADV_DBG_TT = BIT(2),
+ BATADV_DBG_BLA = BIT(3),
+ BATADV_DBG_DAT = BIT(4),
+ BATADV_DBG_ALL = 31,
};
#ifdef CONFIG_BATMAN_ADV_DEBUG
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ac9bdf8f80a6..8c32cf1c2dec 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -18,6 +18,7 @@
*/
#include "main.h"
+#include "distributed-arp-table.h"
#include "originator.h"
#include "hash.h"
#include "translation-table.h"
@@ -220,9 +221,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
atomic_set(&orig_node->refcount, 2);
orig_node->tt_initialised = false;
- orig_node->tt_poss_change = false;
orig_node->bat_priv = bat_priv;
memcpy(orig_node->orig, addr, ETH_ALEN);
+ batadv_dat_init_orig_node_addr(orig_node);
orig_node->router = NULL;
orig_node->tt_crc = 0;
atomic_set(&orig_node->last_ttvn, 0);
@@ -415,23 +416,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
int last_seen_msecs;
unsigned long last_seen_jiffies;
uint32_t i;
- int ret = 0;
- primary_if = batadv_primary_if_get_selected(bat_priv);
-
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
- goto out;
- }
-
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
BATADV_SOURCE_VERSION, primary_if->net_dev->name,
@@ -485,7 +473,7 @@ next:
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 2d23a14c220e..cb6405bf755c 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -20,17 +20,30 @@
#ifndef _NET_BATMAN_ADV_PACKET_H_
#define _NET_BATMAN_ADV_PACKET_H_
-#define BATADV_ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
-
enum batadv_packettype {
- BATADV_IV_OGM = 0x01,
- BATADV_ICMP = 0x02,
- BATADV_UNICAST = 0x03,
- BATADV_BCAST = 0x04,
- BATADV_VIS = 0x05,
- BATADV_UNICAST_FRAG = 0x06,
- BATADV_TT_QUERY = 0x07,
- BATADV_ROAM_ADV = 0x08,
+ BATADV_IV_OGM = 0x01,
+ BATADV_ICMP = 0x02,
+ BATADV_UNICAST = 0x03,
+ BATADV_BCAST = 0x04,
+ BATADV_VIS = 0x05,
+ BATADV_UNICAST_FRAG = 0x06,
+ BATADV_TT_QUERY = 0x07,
+ BATADV_ROAM_ADV = 0x08,
+ BATADV_UNICAST_4ADDR = 0x09,
+};
+
+/**
+ * enum batadv_subtype - packet subtype for unicast4addr
+ * @BATADV_P_DATA: user payload
+ * @BATADV_P_DAT_DHT_GET: DHT request message
+ * @BATADV_P_DAT_DHT_PUT: DHT store message
+ * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT
+ */
+enum batadv_subtype {
+ BATADV_P_DATA = 0x01,
+ BATADV_P_DAT_DHT_GET = 0x02,
+ BATADV_P_DAT_DHT_PUT = 0x03,
+ BATADV_P_DAT_CACHE_REPLY = 0x04,
};
/* this file is included by batctl which needs these defines */
@@ -106,13 +119,16 @@ struct batadv_bla_claim_dst {
uint8_t magic[3]; /* FF:43:05 */
uint8_t type; /* bla_claimframe */
__be16 group; /* group id */
-} __packed;
+};
struct batadv_header {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t ttl;
-} __packed;
+ /* the parent struct has to add a byte after the header to make
+ * everything 4 bytes aligned again
+ */
+};
struct batadv_ogm_packet {
struct batadv_header header;
@@ -137,7 +153,7 @@ struct batadv_icmp_packet {
__be16 seqno;
uint8_t uid;
uint8_t reserved;
-} __packed;
+};
#define BATADV_RR_LEN 16
@@ -153,13 +169,44 @@ struct batadv_icmp_packet_rr {
uint8_t uid;
uint8_t rr_cur;
uint8_t rr[BATADV_RR_LEN][ETH_ALEN];
-} __packed;
+};
+
+/* All packet headers in front of an ethernet header have to be completely
+ * divisible by 2 but not by 4 to make the payload after the ethernet
+ * header again 4 bytes boundary aligned.
+ *
+ * A packing of 2 is necessary to avoid extra padding at the end of the struct
+ * caused by a structure member which is larger than two bytes. Otherwise
+ * the structure would not fulfill the previously mentioned rule to avoid the
+ * misalignment of the payload after the ethernet header. It may also lead to
+ * leakage of information when the padding it not initialized before sending.
+ */
+#pragma pack(2)
struct batadv_unicast_packet {
struct batadv_header header;
uint8_t ttvn; /* destination translation table version number */
uint8_t dest[ETH_ALEN];
-} __packed;
+ /* "4 bytes boundary + 2 bytes" long to make the payload after the
+ * following ethernet header again 4 bytes boundary aligned
+ */
+};
+
+/**
+ * struct batadv_unicast_4addr_packet - extended unicast packet
+ * @u: common unicast packet header
+ * @src: address of the source
+ * @subtype: packet subtype
+ */
+struct batadv_unicast_4addr_packet {
+ struct batadv_unicast_packet u;
+ uint8_t src[ETH_ALEN];
+ uint8_t subtype;
+ uint8_t reserved;
+ /* "4 bytes boundary + 2 bytes" long to make the payload after the
+ * following ethernet header again 4 bytes boundary aligned
+ */
+};
struct batadv_unicast_frag_packet {
struct batadv_header header;
@@ -176,7 +223,12 @@ struct batadv_bcast_packet {
uint8_t reserved;
__be32 seqno;
uint8_t orig[ETH_ALEN];
-} __packed;
+ /* "4 bytes boundary + 2 bytes" long to make the payload after the
+ * following ethernet header again 4 bytes boundary aligned
+ */
+};
+
+#pragma pack()
struct batadv_vis_packet {
struct batadv_header header;
@@ -187,7 +239,7 @@ struct batadv_vis_packet {
uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */
uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */
uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
-} __packed;
+};
struct batadv_tt_query_packet {
struct batadv_header header;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 376b4cc6ca82..1aa1722d0187 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -28,6 +28,7 @@
#include "vis.h"
#include "unicast.h"
#include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
@@ -284,7 +285,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
{
struct batadv_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *router = NULL;
struct batadv_icmp_packet_rr *icmp_packet;
int ret = NET_RX_DROP;
@@ -306,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
if (!orig_node)
goto out;
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- goto out;
-
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
goto out;
@@ -321,14 +317,12 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_ECHO_REPLY;
icmp_packet->header.ttl = BATADV_TTL;
- batadv_send_skb_packet(skb, router->if_incoming, router->addr);
- ret = NET_RX_SUCCESS;
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+ ret = NET_RX_SUCCESS;
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- if (router)
- batadv_neigh_node_free_ref(router);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
return ret;
@@ -339,7 +333,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
{
struct batadv_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *router = NULL;
struct batadv_icmp_packet *icmp_packet;
int ret = NET_RX_DROP;
@@ -361,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
if (!orig_node)
goto out;
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- goto out;
-
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
goto out;
@@ -376,14 +365,12 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
icmp_packet->header.ttl = BATADV_TTL;
- batadv_send_skb_packet(skb, router->if_incoming, router->addr);
- ret = NET_RX_SUCCESS;
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+ ret = NET_RX_SUCCESS;
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- if (router)
- batadv_neigh_node_free_ref(router);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
return ret;
@@ -397,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct batadv_icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr;
struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *router = NULL;
int hdr_size = sizeof(struct batadv_icmp_packet);
int ret = NET_RX_DROP;
@@ -446,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
if (!orig_node)
goto out;
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- goto out;
-
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
goto out;
@@ -460,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet->header.ttl--;
/* route it */
- batadv_send_skb_packet(skb, router->if_incoming, router->addr);
- ret = NET_RX_SUCCESS;
+ if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+ ret = NET_RX_SUCCESS;
out:
- if (router)
- batadv_neigh_node_free_ref(router);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
return ret;
@@ -549,25 +529,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
if (tmp_neigh_node->if_incoming == recv_if)
continue;
- if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+ if (router && tmp_neigh_node->tq_avg <= router->tq_avg)
continue;
- /* if we don't have a router yet
- * or this one is better, choose it.
- */
- if ((!router) ||
- (tmp_neigh_node->tq_avg > router->tq_avg)) {
- /* decrement refcount of
- * previously selected router
- */
- if (router)
- batadv_neigh_node_free_ref(router);
+ if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+ continue;
- router = tmp_neigh_node;
- atomic_inc_not_zero(&router->refcount);
- }
+ /* decrement refcount of previously selected router */
+ if (router)
+ batadv_neigh_node_free_ref(router);
- batadv_neigh_node_free_ref(tmp_neigh_node);
+ /* we found a better router (or at least one valid router) */
+ router = tmp_neigh_node;
}
/* use the first candidate if nothing was found. */
@@ -687,21 +660,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_roam_adv_packet *roam_adv_packet;
struct batadv_orig_node *orig_node;
- struct ethhdr *ethhdr;
-
- /* drop packet if it has not necessary minimum size */
- if (unlikely(!pskb_may_pull(skb,
- sizeof(struct batadv_roam_adv_packet))))
- goto out;
-
- ethhdr = (struct ethhdr *)skb_mac_header(skb);
-
- /* packet with unicast indication but broadcast recipient */
- if (is_broadcast_ether_addr(ethhdr->h_dest))
- goto out;
- /* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
goto out;
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
@@ -730,12 +690,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
BATADV_TT_CLIENT_ROAM,
atomic_read(&orig_node->last_ttvn) + 1);
- /* Roaming phase starts: I have new information but the ttvn has not
- * been incremented yet. This flag will make me check all the incoming
- * packets for the correct destination.
- */
- bat_priv->tt.poss_change = true;
-
batadv_orig_node_free_ref(orig_node);
out:
/* returning NET_RX_DROP will make the caller function kfree the skb */
@@ -907,8 +861,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
skb->len + ETH_HLEN);
/* route it */
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = NET_RX_SUCCESS;
+ if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+ ret = NET_RX_SUCCESS;
out:
if (neigh_node)
@@ -918,80 +872,161 @@ out:
return ret;
}
+/**
+ * batadv_reroute_unicast_packet - update the unicast header for re-routing
+ * @bat_priv: the bat priv with all the soft interface information
+ * @unicast_packet: the unicast header to be updated
+ * @dst_addr: the payload destination
+ *
+ * Search the translation table for dst_addr and update the unicast header with
+ * the new corresponding information (originator address where the destination
+ * client currently is and its known TTVN)
+ *
+ * Returns true if the packet header has been updated, false otherwise
+ */
+static bool
+batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
+ struct batadv_unicast_packet *unicast_packet,
+ uint8_t *dst_addr)
+{
+ struct batadv_orig_node *orig_node = NULL;
+ struct batadv_hard_iface *primary_if = NULL;
+ bool ret = false;
+ uint8_t *orig_addr, orig_ttvn;
+
+ if (batadv_is_my_client(bat_priv, dst_addr)) {
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+ orig_addr = primary_if->net_dev->dev_addr;
+ orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+ } else {
+ orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr);
+ if (!orig_node)
+ goto out;
+
+ if (batadv_compare_eth(orig_node->orig, unicast_packet->dest))
+ goto out;
+
+ orig_addr = orig_node->orig;
+ orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+ }
+
+ /* update the packet header */
+ memcpy(unicast_packet->dest, orig_addr, ETH_ALEN);
+ unicast_packet->ttvn = orig_ttvn;
+
+ ret = true;
+out:
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ if (orig_node)
+ batadv_orig_node_free_ref(orig_node);
+
+ return ret;
+}
+
static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
struct sk_buff *skb) {
- uint8_t curr_ttvn;
+ uint8_t curr_ttvn, old_ttvn;
struct batadv_orig_node *orig_node;
struct ethhdr *ethhdr;
struct batadv_hard_iface *primary_if;
struct batadv_unicast_packet *unicast_packet;
- bool tt_poss_change;
int is_old_ttvn;
- /* I could need to modify it */
- if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0)
+ /* check if there is enough data before accessing it */
+ if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
+ return 0;
+
+ /* create a copy of the skb (in case of for re-routing) to modify it. */
+ if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
return 0;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
+ ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
- if (batadv_is_my_mac(unicast_packet->dest)) {
- tt_poss_change = bat_priv->tt.poss_change;
- curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
- } else {
+ /* check if the destination client was served by this node and it is now
+ * roaming. In this case, it means that the node has got a ROAM_ADV
+ * message and that it knows the new destination in the mesh to re-route
+ * the packet to
+ */
+ if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) {
+ if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+ ethhdr->h_dest))
+ net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
+ bat_priv,
+ "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n",
+ unicast_packet->dest,
+ ethhdr->h_dest);
+ /* at this point the mesh destination should have been
+ * substituted with the originator address found in the global
+ * table. If not, let the packet go untouched anyway because
+ * there is nothing the node can do
+ */
+ return 1;
+ }
+
+ /* retrieve the TTVN known by this node for the packet destination. This
+ * value is used later to check if the node which sent (or re-routed
+ * last time) the packet had an updated information or not
+ */
+ curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+ if (!batadv_is_my_mac(unicast_packet->dest)) {
orig_node = batadv_orig_hash_find(bat_priv,
unicast_packet->dest);
-
+ /* if it is not possible to find the orig_node representing the
+ * destination, the packet can immediately be dropped as it will
+ * not be possible to deliver it
+ */
if (!orig_node)
return 0;
curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
- tt_poss_change = orig_node->tt_poss_change;
batadv_orig_node_free_ref(orig_node);
}
- /* Check whether I have to reroute the packet */
+ /* check if the TTVN contained in the packet is fresher than what the
+ * node knows
+ */
is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
- if (is_old_ttvn || tt_poss_change) {
- /* check if there is enough data before accessing it */
- if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) +
- ETH_HLEN) < 0)
- return 0;
+ if (!is_old_ttvn)
+ return 1;
- ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
+ old_ttvn = unicast_packet->ttvn;
+ /* the packet was forged based on outdated network information. Its
+ * destination can possibly be updated and forwarded towards the new
+ * target host
+ */
+ if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+ ethhdr->h_dest)) {
+ net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
+ "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
+ unicast_packet->dest, ethhdr->h_dest,
+ old_ttvn, curr_ttvn);
+ return 1;
+ }
- /* we don't have an updated route for this client, so we should
- * not try to reroute the packet!!
- */
- if (batadv_tt_global_client_is_roaming(bat_priv,
- ethhdr->h_dest))
- return 1;
+ /* the packet has not been re-routed: either the destination is
+ * currently served by this node or there is no destination at all and
+ * it is possible to drop the packet
+ */
+ if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
+ return 0;
- orig_node = batadv_transtable_search(bat_priv, NULL,
- ethhdr->h_dest);
-
- if (!orig_node) {
- if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
- return 0;
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- return 0;
- memcpy(unicast_packet->dest,
- primary_if->net_dev->dev_addr, ETH_ALEN);
- batadv_hardif_free_ref(primary_if);
- } else {
- memcpy(unicast_packet->dest, orig_node->orig,
- ETH_ALEN);
- curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
- batadv_orig_node_free_ref(orig_node);
- }
+ /* update the header in order to let the packet be delivered to this
+ * node's soft interface
+ */
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ return 0;
- batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
- "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n",
- unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest,
- unicast_packet->dest);
+ memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN);
+
+ batadv_hardif_free_ref(primary_if);
+
+ unicast_packet->ttvn = curr_ttvn;
- unicast_packet->ttvn = curr_ttvn;
- }
return 1;
}
@@ -1000,7 +1035,19 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_unicast_packet *unicast_packet;
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+ uint8_t *orig_addr;
+ struct batadv_orig_node *orig_node = NULL;
int hdr_size = sizeof(*unicast_packet);
+ bool is4addr;
+
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+ is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+ /* the caller function should have already pulled 2 bytes */
+ if (is4addr)
+ hdr_size = sizeof(*unicast_4addr_packet);
if (batadv_check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;
@@ -1008,12 +1055,28 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
if (!batadv_check_unicast_ttvn(bat_priv, skb))
return NET_RX_DROP;
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
-
/* packet for me */
if (batadv_is_my_mac(unicast_packet->dest)) {
+ if (is4addr) {
+ batadv_dat_inc_counter(bat_priv,
+ unicast_4addr_packet->subtype);
+ orig_addr = unicast_4addr_packet->src;
+ orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+ }
+
+ if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
+ hdr_size))
+ goto rx_success;
+ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
+ hdr_size))
+ goto rx_success;
+
batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
- NULL);
+ orig_node);
+
+rx_success:
+ if (orig_node)
+ batadv_orig_node_free_ref(orig_node);
return NET_RX_SUCCESS;
}
@@ -1050,8 +1113,17 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
if (!new_skb)
return NET_RX_SUCCESS;
+ if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
+ hdr_size))
+ goto rx_success;
+ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
+ hdr_size))
+ goto rx_success;
+
batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
sizeof(struct batadv_unicast_packet), NULL);
+
+rx_success:
return NET_RX_SUCCESS;
}
@@ -1124,14 +1196,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
spin_unlock_bh(&orig_node->bcast_seqno_lock);
- /* keep skb linear for crc calculation */
- if (skb_linearize(skb) < 0)
- goto out;
-
- bcast_packet = (struct batadv_bcast_packet *)skb->data;
-
/* check whether this has been sent by another originator before */
- if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
+ if (batadv_bla_check_bcast_duplist(bat_priv, skb))
goto out;
/* rebroadcast packet */
@@ -1143,9 +1209,16 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
goto out;
+ if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
+ goto rx_success;
+ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
+ goto rx_success;
+
/* broadcast for me */
batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
orig_node);
+
+rx_success:
ret = NET_RX_SUCCESS;
goto out;
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 570a8bce0364..4425af9dad40 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -18,6 +18,7 @@
*/
#include "main.h"
+#include "distributed-arp-table.h"
#include "send.h"
#include "routing.h"
#include "translation-table.h"
@@ -27,6 +28,8 @@
#include "gateway_common.h"
#include "originator.h"
+#include <linux/if_ether.h>
+
static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
/* send out an already prepared packet to the given address via the
@@ -59,11 +62,11 @@ int batadv_send_skb_packet(struct sk_buff *skb,
ethhdr = (struct ethhdr *)skb_mac_header(skb);
memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
- ethhdr->h_proto = __constant_htons(BATADV_ETH_P_BATMAN);
+ ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
skb_set_network_header(skb, ETH_HLEN);
skb->priority = TC_PRIO_CONTROL;
- skb->protocol = __constant_htons(BATADV_ETH_P_BATMAN);
+ skb->protocol = __constant_htons(ETH_P_BATMAN);
skb->dev = hard_iface->net_dev;
@@ -77,6 +80,39 @@ send_skb_err:
return NET_XMIT_DROP;
}
+/**
+ * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
+ * @skb: Packet to be transmitted.
+ * @orig_node: Final destination of the packet.
+ * @recv_if: Interface used when receiving the packet (can be NULL).
+ *
+ * Looks up the best next-hop towards the passed originator and passes the
+ * skb on for preparation of MAC header. If the packet originated from this
+ * host, NULL can be passed as recv_if and no interface alternating is
+ * attempted.
+ *
+ * Returns TRUE on success; FALSE otherwise.
+ */
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ struct batadv_hard_iface *recv_if)
+{
+ struct batadv_priv *bat_priv = orig_node->bat_priv;
+ struct batadv_neigh_node *neigh_node;
+
+ /* batadv_find_router() increases neigh_nodes refcount if found. */
+ neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
+ if (!neigh_node)
+ return false;
+
+ /* route it */
+ batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+
+ batadv_neigh_node_free_ref(neigh_node);
+
+ return true;
+}
+
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -209,6 +245,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
+ if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
+ goto out;
+
/* rebroadcast packet */
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 643329b787ed..0078dece1abc 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -23,6 +23,9 @@
int batadv_send_skb_packet(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface,
const uint8_t *dst_addr);
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ struct batadv_hard_iface *recv_if);
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index ce0684a1fc83..6b548fde8e04 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -20,6 +20,7 @@
#include "main.h"
#include "soft-interface.h"
#include "hard-interface.h"
+#include "distributed-arp-table.h"
#include "routing.h"
#include "send.h"
#include "debugfs.h"
@@ -33,6 +34,7 @@
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
#include "unicast.h"
#include "bridge_loop_avoidance.h"
@@ -145,14 +147,17 @@ static int batadv_interface_tx(struct sk_buff *skb,
struct batadv_hard_iface *primary_if = NULL;
struct batadv_bcast_packet *bcast_packet;
struct vlan_ethhdr *vhdr;
- __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
- static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00,
- 0x00};
+ __be16 ethertype = __constant_htons(ETH_P_BATMAN);
+ static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
+ 0x00, 0x00};
+ static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
+ 0x00, 0x00};
unsigned int header_len = 0;
int data_len = skb->len, ret;
short vid __maybe_unused = -1;
bool do_bcast = false;
uint32_t seqno;
+ unsigned long brd_delay = 1;
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto dropped;
@@ -168,7 +173,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
break;
/* fall through */
- case BATADV_ETH_P_BATMAN:
+ case ETH_P_BATMAN:
goto dropped;
}
@@ -180,10 +185,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
/* don't accept stp packets. STP does not help in meshes.
* better use the bridge loop avoidance ...
+ *
+ * The same goes for ECTP sent at least by some Cisco Switches,
+ * it might confuse the mesh when used with bridge loop avoidance.
*/
if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
goto dropped;
+ if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
+ goto dropped;
+
if (is_multicast_ether_addr(ethhdr->h_dest)) {
do_bcast = true;
@@ -216,6 +227,13 @@ static int batadv_interface_tx(struct sk_buff *skb,
if (!primary_if)
goto dropped;
+ /* in case of ARP request, we do not immediately broadcasti the
+ * packet, instead we first wait for DAT to try to retrieve the
+ * correct ARP entry
+ */
+ if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+ brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
+
if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
goto dropped;
@@ -237,7 +255,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
seqno = atomic_inc_return(&bat_priv->bcast_seqno);
bcast_packet->seqno = htonl(seqno);
- batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
+ batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
/* a copy is stored in the bcast list, therefore removing
* the original skb.
@@ -252,7 +270,12 @@ static int batadv_interface_tx(struct sk_buff *skb,
goto dropped;
}
- ret = batadv_unicast_send_skb(skb, bat_priv);
+ if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+ goto dropped;
+
+ batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
+
+ ret = batadv_unicast_send_skb(bat_priv, skb);
if (ret != 0)
goto dropped_freed;
}
@@ -280,7 +303,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
struct vlan_ethhdr *vhdr;
struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
short vid __maybe_unused = -1;
- __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
+ __be16 ethertype = __constant_htons(ETH_P_BATMAN);
bool is_bcast;
is_bcast = (batadv_header->packet_type == BATADV_BCAST);
@@ -303,7 +326,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
break;
/* fall through */
- case BATADV_ETH_P_BATMAN:
+ case ETH_P_BATMAN:
goto dropped;
}
@@ -347,7 +370,51 @@ out:
return;
}
+/* batman-adv network devices have devices nesting below it and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key batadv_netdev_xmit_lock_key;
+static struct lock_class_key batadv_netdev_addr_lock_key;
+
+/**
+ * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue
+ * @dev: device which owns the tx queue
+ * @txq: tx queue to modify
+ * @_unused: always NULL
+ */
+static void batadv_set_lockdep_class_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
+}
+
+/**
+ * batadv_set_lockdep_class - Set txq and addr_list lockdep class
+ * @dev: network device to modify
+ */
+static void batadv_set_lockdep_class(struct net_device *dev)
+{
+ lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
+ netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
+}
+
+/**
+ * batadv_softif_init - Late stage initialization of soft interface
+ * @dev: registered network device to modify
+ *
+ * Returns error code on failures
+ */
+static int batadv_softif_init(struct net_device *dev)
+{
+ batadv_set_lockdep_class(dev);
+
+ return 0;
+}
+
static const struct net_device_ops batadv_netdev_ops = {
+ .ndo_init = batadv_softif_init,
.ndo_open = batadv_interface_open,
.ndo_stop = batadv_interface_release,
.ndo_get_stats = batadv_interface_stats,
@@ -414,6 +481,9 @@ struct net_device *batadv_softif_create(const char *name)
atomic_set(&bat_priv->aggregated_ogms, 1);
atomic_set(&bat_priv->bonding, 0);
atomic_set(&bat_priv->bridge_loop_avoidance, 0);
+#ifdef CONFIG_BATMAN_ADV_DAT
+ atomic_set(&bat_priv->distributed_arp_table, 1);
+#endif
atomic_set(&bat_priv->ap_isolation, 0);
atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
@@ -436,7 +506,6 @@ struct net_device *batadv_softif_create(const char *name)
#endif
bat_priv->tt.last_changeset = NULL;
bat_priv->tt.last_changeset_len = 0;
- bat_priv->tt.poss_change = false;
bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0;
@@ -556,6 +625,13 @@ static const struct {
{ "tt_response_rx" },
{ "tt_roam_adv_tx" },
{ "tt_roam_adv_rx" },
+#ifdef CONFIG_BATMAN_ADV_DAT
+ { "dat_get_tx" },
+ { "dat_get_rx" },
+ { "dat_put_tx" },
+ { "dat_put_rx" },
+ { "dat_cached_reply_tx" },
+#endif
};
static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 66518c75c217..84a55cb19b0b 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -20,6 +20,7 @@
#include "main.h"
#include "sysfs.h"
#include "translation-table.h"
+#include "distributed-arp-table.h"
#include "originator.h"
#include "hard-interface.h"
#include "gateway_common.h"
@@ -122,55 +123,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \
batadv_store_##_name)
-#define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
-ssize_t batadv_store_##_name(struct kobject *kobj, \
- struct attribute *attr, char *buff, \
- size_t count) \
-{ \
- struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
- struct batadv_hard_iface *hard_iface; \
- ssize_t length; \
- \
- hard_iface = batadv_hardif_get_by_netdev(net_dev); \
- if (!hard_iface) \
- return 0; \
- \
- length = __batadv_store_uint_attr(buff, count, _min, _max, \
- _post_func, attr, \
- &hard_iface->_name, net_dev); \
- \
- batadv_hardif_free_ref(hard_iface); \
- return length; \
-}
-
-#define BATADV_ATTR_HIF_SHOW_UINT(_name) \
-ssize_t batadv_show_##_name(struct kobject *kobj, \
- struct attribute *attr, char *buff) \
-{ \
- struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
- struct batadv_hard_iface *hard_iface; \
- ssize_t length; \
- \
- hard_iface = batadv_hardif_get_by_netdev(net_dev); \
- if (!hard_iface) \
- return 0; \
- \
- length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
- \
- batadv_hardif_free_ref(hard_iface); \
- return length; \
-}
-
-/* Use this, if you are going to set [name] in hard_iface to an
- * unsigned integer value
- */
-#define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \
- static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\
- static BATADV_ATTR_HIF_SHOW_UINT(_name) \
- static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
- batadv_store_##_name)
-
-
static int batadv_store_bool_attr(char *buff, size_t count,
struct net_device *net_dev,
const char *attr_name, atomic_t *attr)
@@ -469,6 +421,9 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
#ifdef CONFIG_BATMAN_ADV_BLA
BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL);
+#endif
BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
@@ -494,6 +449,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
#ifdef CONFIG_BATMAN_ADV_BLA
&batadv_attr_bridge_loop_avoidance,
#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+ &batadv_attr_distributed_arp_table,
+#endif
&batadv_attr_fragmentation,
&batadv_attr_ap_isolation,
&batadv_attr_vis_mode,
@@ -730,7 +688,7 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
enum batadv_uev_action action, const char *data)
{
int ret = -ENOMEM;
- struct batadv_hard_iface *primary_if = NULL;
+ struct batadv_hard_iface *primary_if;
struct kobject *bat_kobj;
char *uevent_env[4] = { NULL, NULL, NULL, NULL };
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index baae71585804..22457a7952ba 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -238,92 +238,134 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
return 0;
}
+static void batadv_tt_global_free(struct batadv_priv *bat_priv,
+ struct batadv_tt_global_entry *tt_global,
+ const char *message)
+{
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Deleting global tt entry %pM: %s\n",
+ tt_global->common.addr, message);
+
+ batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
+ batadv_choose_orig, tt_global->common.addr);
+ batadv_tt_global_entry_free_ref(tt_global);
+
+}
+
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex)
{
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
- struct batadv_tt_local_entry *tt_local_entry = NULL;
- struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_local_entry *tt_local;
+ struct batadv_tt_global_entry *tt_global;
struct hlist_head *head;
struct hlist_node *node;
struct batadv_tt_orig_list_entry *orig_entry;
int hash_added;
+ bool roamed_back = false;
- tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+ tt_local = batadv_tt_local_hash_find(bat_priv, addr);
+ tt_global = batadv_tt_global_hash_find(bat_priv, addr);
- if (tt_local_entry) {
- tt_local_entry->last_seen = jiffies;
- /* possibly unset the BATADV_TT_CLIENT_PENDING flag */
- tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING;
- goto out;
+ if (tt_local) {
+ tt_local->last_seen = jiffies;
+ if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Re-adding pending client %pM\n", addr);
+ /* whatever the reason why the PENDING flag was set,
+ * this is a client which was enqueued to be removed in
+ * this orig_interval. Since it popped up again, the
+ * flag can be reset like it was never enqueued
+ */
+ tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
+ goto add_event;
+ }
+
+ if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Roaming client %pM came back to its original location\n",
+ addr);
+ /* the ROAM flag is set because this client roamed away
+ * and the node got a roaming_advertisement message. Now
+ * that the client popped up again at its original
+ * location such flag can be unset
+ */
+ tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+ roamed_back = true;
+ }
+ goto check_roaming;
}
- tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
- if (!tt_local_entry)
+ tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
+ if (!tt_local)
goto out;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new local tt entry: %pM (ttvn: %d)\n", addr,
(uint8_t)atomic_read(&bat_priv->tt.vn));
- memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
- tt_local_entry->common.flags = BATADV_NO_FLAGS;
+ memcpy(tt_local->common.addr, addr, ETH_ALEN);
+ tt_local->common.flags = BATADV_NO_FLAGS;
if (batadv_is_wifi_iface(ifindex))
- tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
- atomic_set(&tt_local_entry->common.refcount, 2);
- tt_local_entry->last_seen = jiffies;
- tt_local_entry->common.added_at = tt_local_entry->last_seen;
+ tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
+ atomic_set(&tt_local->common.refcount, 2);
+ tt_local->last_seen = jiffies;
+ tt_local->common.added_at = tt_local->last_seen;
/* the batman interface mac address should never be purged */
if (batadv_compare_eth(addr, soft_iface->dev_addr))
- tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE;
+ tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
/* The local entry has to be marked as NEW to avoid to send it in
* a full table response going out before the next ttvn increment
* (consistency check)
*/
- tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
+ tt_local->common.flags |= BATADV_TT_CLIENT_NEW;
hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
- batadv_choose_orig,
- &tt_local_entry->common,
- &tt_local_entry->common.hash_entry);
+ batadv_choose_orig, &tt_local->common,
+ &tt_local->common.hash_entry);
if (unlikely(hash_added != 0)) {
/* remove the reference for the hash */
- batadv_tt_local_entry_free_ref(tt_local_entry);
+ batadv_tt_local_entry_free_ref(tt_local);
goto out;
}
- batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
+add_event:
+ batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
- /* remove address from global hash if present */
- tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
-
- /* Check whether it is a roaming! */
- if (tt_global_entry) {
+check_roaming:
+ /* Check whether it is a roaming, but don't do anything if the roaming
+ * process has already been handled
+ */
+ if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
/* These node are probably going to update their tt table */
- head = &tt_global_entry->orig_list;
+ head = &tt_global->orig_list;
rcu_read_lock();
hlist_for_each_entry_rcu(orig_entry, node, head, list) {
- orig_entry->orig_node->tt_poss_change = true;
-
- batadv_send_roam_adv(bat_priv,
- tt_global_entry->common.addr,
+ batadv_send_roam_adv(bat_priv, tt_global->common.addr,
orig_entry->orig_node);
}
rcu_read_unlock();
- /* The global entry has to be marked as ROAMING and
- * has to be kept for consistency purpose
- */
- tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
- tt_global_entry->roam_at = jiffies;
+ if (roamed_back) {
+ batadv_tt_global_free(bat_priv, tt_global,
+ "Roaming canceled");
+ tt_global = NULL;
+ } else {
+ /* The global entry has to be marked as ROAMING and
+ * has to be kept for consistency purpose
+ */
+ tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
+ tt_global->roam_at = jiffies;
+ }
}
+
out:
- if (tt_local_entry)
- batadv_tt_local_entry_free_ref(tt_local_entry);
- if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ if (tt_local)
+ batadv_tt_local_entry_free_ref(tt_local);
+ if (tt_global)
+ batadv_tt_global_entry_free_ref(tt_global);
}
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
@@ -434,22 +476,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_node *node;
struct hlist_head *head;
uint32_t i;
- int ret = 0;
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
- goto out;
- }
-
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
seq_printf(seq,
"Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
@@ -479,7 +509,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
static void
@@ -501,24 +531,57 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
tt_local_entry->common.addr, message);
}
-void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr,
- const char *message, bool roaming)
+/**
+ * batadv_tt_local_remove - logically remove an entry from the local table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the client to remove
+ * @message: message to append to the log on deletion
+ * @roaming: true if the deletion is due to a roaming event
+ *
+ * Returns the flags assigned to the local entry before being deleted
+ */
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+ const uint8_t *addr, const char *message,
+ bool roaming)
{
- struct batadv_tt_local_entry *tt_local_entry = NULL;
- uint16_t flags;
+ struct batadv_tt_local_entry *tt_local_entry;
+ uint16_t flags, curr_flags = BATADV_NO_FLAGS;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
if (!tt_local_entry)
goto out;
+ curr_flags = tt_local_entry->common.flags;
+
flags = BATADV_TT_CLIENT_DEL;
- if (roaming)
+ /* if this global entry addition is due to a roaming, the node has to
+ * mark the local entry as "roamed" in order to correctly reroute
+ * packets later
+ */
+ if (roaming) {
flags |= BATADV_TT_CLIENT_ROAM;
+ /* mark the local client as ROAMed */
+ tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
+ }
+
+ if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
+ batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
+ message);
+ goto out;
+ }
+ /* if this client has been added right now, it is possible to
+ * immediately purge it
+ */
+ batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
+ curr_flags | BATADV_TT_CLIENT_DEL);
+ hlist_del_rcu(&tt_local_entry->common.hash_entry);
+ batadv_tt_local_entry_free_ref(tt_local_entry);
- batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
out:
if (tt_local_entry)
batadv_tt_local_entry_free_ref(tt_local_entry);
+
+ return curr_flags;
}
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
@@ -721,12 +784,23 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
const unsigned char *tt_addr, uint8_t flags,
uint8_t ttvn)
{
- struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_global_entry *tt_global_entry;
+ struct batadv_tt_local_entry *tt_local_entry;
int ret = 0;
int hash_added;
struct batadv_tt_common_entry *common;
+ uint16_t local_flags;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
+ tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
+
+ /* if the node already has a local client for this entry, it has to wait
+ * for a roaming advertisement instead of manually messing up the global
+ * table
+ */
+ if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
+ !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
+ goto out;
if (!tt_global_entry) {
tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
@@ -738,6 +812,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
common->flags = flags;
tt_global_entry->roam_at = 0;
+ /* node must store current time in case of roaming. This is
+ * needed to purge this entry out on timeout (if nobody claims
+ * it)
+ */
+ if (flags & BATADV_TT_CLIENT_ROAM)
+ tt_global_entry->roam_at = jiffies;
atomic_set(&common->refcount, 2);
common->added_at = jiffies;
@@ -755,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
goto out_remove;
}
} else {
+ common = &tt_global_entry->common;
/* If there is already a global entry, we can use this one for
* our processing.
- * But if we are trying to add a temporary client we can exit
- * directly because the temporary information should never
- * override any already known client state (whatever it is)
+ * But if we are trying to add a temporary client then here are
+ * two options at this point:
+ * 1) the global client is not a temporary client: the global
+ * client has to be left as it is, temporary information
+ * should never override any already known client state
+ * 2) the global client is a temporary client: purge the
+ * originator list and add the new one orig_entry
*/
- if (flags & BATADV_TT_CLIENT_TEMP)
- goto out;
+ if (flags & BATADV_TT_CLIENT_TEMP) {
+ if (!(common->flags & BATADV_TT_CLIENT_TEMP))
+ goto out;
+ if (batadv_tt_global_entry_has_orig(tt_global_entry,
+ orig_node))
+ goto out_remove;
+ batadv_tt_global_del_orig_list(tt_global_entry);
+ goto add_orig_entry;
+ }
/* if the client was temporary added before receiving the first
* OGM announcing it, we have to clear the TEMP flag
*/
- tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
+ common->flags &= ~BATADV_TT_CLIENT_TEMP;
/* the change can carry possible "attribute" flags like the
* TT_CLIENT_WIFI, therefore they have to be copied in the
@@ -782,33 +874,81 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
* We should first delete the old originator before adding the
* new one.
*/
- if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) {
+ if (common->flags & BATADV_TT_CLIENT_ROAM) {
batadv_tt_global_del_orig_list(tt_global_entry);
- tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+ common->flags &= ~BATADV_TT_CLIENT_ROAM;
tt_global_entry->roam_at = 0;
}
}
+add_orig_entry:
/* add the new orig_entry (if needed) or update it */
batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new global tt entry: %pM (via %pM)\n",
- tt_global_entry->common.addr, orig_node->orig);
+ common->addr, orig_node->orig);
+ ret = 1;
out_remove:
+
/* remove address from local hash if present */
- batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr,
- "global tt received",
- flags & BATADV_TT_CLIENT_ROAM);
- ret = 1;
+ local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
+ "global tt received",
+ !!(flags & BATADV_TT_CLIENT_ROAM));
+ tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
+
+ if (!(flags & BATADV_TT_CLIENT_ROAM))
+ /* this is a normal global add. Therefore the client is not in a
+ * roaming state anymore.
+ */
+ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+
out:
if (tt_global_entry)
batadv_tt_global_entry_free_ref(tt_global_entry);
+ if (tt_local_entry)
+ batadv_tt_local_entry_free_ref(tt_local_entry);
return ret;
}
-/* print all orig nodes who announce the address for this global entry.
- * it is assumed that the caller holds rcu_read_lock();
+/* batadv_transtable_best_orig - Get best originator list entry from tt entry
+ * @tt_global_entry: global translation table entry to be analyzed
+ *
+ * This functon assumes the caller holds rcu_read_lock().
+ * Returns best originator list entry or NULL on errors.
+ */
+static struct batadv_tt_orig_list_entry *
+batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
+{
+ struct batadv_neigh_node *router = NULL;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
+ int best_tq = 0;
+
+ head = &tt_global_entry->orig_list;
+ hlist_for_each_entry_rcu(orig_entry, node, head, list) {
+ router = batadv_orig_node_get_router(orig_entry->orig_node);
+ if (!router)
+ continue;
+
+ if (router->tq_avg > best_tq) {
+ best_entry = orig_entry;
+ best_tq = router->tq_avg;
+ }
+
+ batadv_neigh_node_free_ref(router);
+ }
+
+ return best_entry;
+}
+
+/* batadv_tt_global_print_entry - print all orig nodes who announce the address
+ * for this global entry
+ * @tt_global_entry: global translation table entry to be printed
+ * @seq: debugfs table seq_file struct
+ *
+ * This functon assumes the caller holds rcu_read_lock().
*/
static void
batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
@@ -816,21 +956,37 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
{
struct hlist_head *head;
struct hlist_node *node;
- struct batadv_tt_orig_list_entry *orig_entry;
+ struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
struct batadv_tt_common_entry *tt_common_entry;
uint16_t flags;
uint8_t last_ttvn;
tt_common_entry = &tt_global_entry->common;
+ flags = tt_common_entry->flags;
+
+ best_entry = batadv_transtable_best_orig(tt_global_entry);
+ if (best_entry) {
+ last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
+ seq_printf(seq, " %c %pM (%3u) via %pM (%3u) [%c%c%c]\n",
+ '*', tt_global_entry->common.addr,
+ best_entry->ttvn, best_entry->orig_node->orig,
+ last_ttvn,
+ (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
+ (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+ (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
+ }
head = &tt_global_entry->orig_list;
hlist_for_each_entry_rcu(orig_entry, node, head, list) {
- flags = tt_common_entry->flags;
+ if (best_entry == orig_entry)
+ continue;
+
last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
- seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n",
- tt_global_entry->common.addr, orig_entry->ttvn,
- orig_entry->orig_node->orig, last_ttvn,
+ seq_printf(seq, " %c %pM (%3u) via %pM (%3u) [%c%c%c]\n",
+ '+', tt_global_entry->common.addr,
+ orig_entry->ttvn, orig_entry->orig_node->orig,
+ last_ttvn,
(flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
(flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
(flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
@@ -848,22 +1004,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_node *node;
struct hlist_head *head;
uint32_t i;
- int ret = 0;
-
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
- net_dev->name);
- goto out;
- }
- if (primary_if->if_status != BATADV_IF_ACTIVE) {
- ret = seq_printf(seq,
- "BATMAN mesh %s disabled - primary interface not active\n",
- net_dev->name);
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
goto out;
- }
seq_printf(seq,
"Globally announced TT entries received via the mesh %s\n",
@@ -887,7 +1031,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
out:
if (primary_if)
batadv_hardif_free_ref(primary_if);
- return ret;
+ return 0;
}
/* deletes the orig list of a tt_global_entry */
@@ -933,21 +1077,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
spin_unlock_bh(&tt_global_entry->list_lock);
}
-static void
-batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
- struct batadv_tt_global_entry *tt_global_entry,
- const char *message)
-{
- batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Deleting global tt entry %pM: %s\n",
- tt_global_entry->common.addr, message);
-
- batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
- batadv_choose_orig, tt_global_entry->common.addr);
- batadv_tt_global_entry_free_ref(tt_global_entry);
-
-}
-
/* If the client is to be deleted, we check if it is the last origantor entry
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
* timer, otherwise we simply remove the originator scheduled for deletion.
@@ -996,7 +1125,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
const unsigned char *addr,
const char *message, bool roaming)
{
- struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_global_entry *tt_global_entry;
struct batadv_tt_local_entry *local_entry = NULL;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
@@ -1008,8 +1137,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
orig_node, message);
if (hlist_empty(&tt_global_entry->orig_list))
- batadv_tt_global_del_struct(bat_priv, tt_global_entry,
- message);
+ batadv_tt_global_free(bat_priv, tt_global_entry,
+ message);
goto out;
}
@@ -1032,7 +1161,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
if (local_entry) {
/* local entry exists, case 2: client roamed to us. */
batadv_tt_global_del_orig_list(tt_global_entry);
- batadv_tt_global_del_struct(bat_priv, tt_global_entry, message);
+ batadv_tt_global_free(bat_priv, tt_global_entry, message);
} else
/* no local entry exists, case 1: check for roaming */
batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
@@ -1203,15 +1332,12 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry = NULL;
struct batadv_tt_global_entry *tt_global_entry = NULL;
struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *router = NULL;
- struct hlist_head *head;
- struct hlist_node *node;
- struct batadv_tt_orig_list_entry *orig_entry;
- int best_tq;
+ struct batadv_tt_orig_list_entry *best_entry;
if (src && atomic_read(&bat_priv->ap_isolation)) {
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
- if (!tt_local_entry)
+ if (!tt_local_entry ||
+ (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
goto out;
}
@@ -1226,25 +1352,15 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
goto out;
- best_tq = 0;
-
rcu_read_lock();
- head = &tt_global_entry->orig_list;
- hlist_for_each_entry_rcu(orig_entry, node, head, list) {
- router = batadv_orig_node_get_router(orig_entry->orig_node);
- if (!router)
- continue;
-
- if (router->tq_avg > best_tq) {
- orig_node = orig_entry->orig_node;
- best_tq = router->tq_avg;
- }
- batadv_neigh_node_free_ref(router);
- }
+ best_entry = batadv_transtable_best_orig(tt_global_entry);
/* found anything? */
+ if (best_entry)
+ orig_node = best_entry->orig_node;
if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
orig_node = NULL;
rcu_read_unlock();
+
out:
if (tt_global_entry)
batadv_tt_global_entry_free_ref(tt_global_entry);
@@ -1477,11 +1593,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = tt_query_size + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN);
+ skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
tt_response->ttvn = ttvn;
@@ -1526,7 +1642,6 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
{
struct sk_buff *skb = NULL;
struct batadv_tt_query_packet *tt_request;
- struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *primary_if;
struct batadv_tt_req_node *tt_req_node = NULL;
int ret = 1;
@@ -1543,11 +1658,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (!tt_req_node)
goto out;
- skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN);
+ skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
tt_req_len = sizeof(*tt_request);
tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
@@ -1564,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (full_table)
tt_request->flags |= BATADV_TT_FULL_TABLE;
- neigh_node = batadv_orig_node_get_router(dst_orig_node);
- if (!neigh_node)
- goto out;
-
- batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending TT_REQUEST to %pM via %pM [%c]\n",
- dst_orig_node->orig, neigh_node->addr,
- (full_table ? 'F' : '.'));
+ batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
+ dst_orig_node->orig, (full_table ? 'F' : '.'));
batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = 0;
+ if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
+ ret = 0;
out:
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
if (primary_if)
batadv_hardif_free_ref(primary_if);
if (ret)
@@ -1598,9 +1705,8 @@ static bool
batadv_send_other_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_request)
{
- struct batadv_orig_node *req_dst_orig_node = NULL;
+ struct batadv_orig_node *req_dst_orig_node;
struct batadv_orig_node *res_dst_orig_node = NULL;
- struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *primary_if = NULL;
uint8_t orig_ttvn, req_ttvn, ttvn;
int ret = false;
@@ -1626,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
if (!res_dst_orig_node)
goto out;
- neigh_node = batadv_orig_node_get_router(res_dst_orig_node);
- if (!neigh_node)
- goto out;
-
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
goto out;
@@ -1658,11 +1760,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN);
+ skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
if (!skb)
goto unlock;
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
@@ -1701,14 +1803,13 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
tt_response->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
- res_dst_orig_node->orig, neigh_node->addr,
- req_dst_orig_node->orig, req_ttvn);
+ "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
+ res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = true;
+ if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
+ ret = true;
goto out;
unlock:
@@ -1719,8 +1820,6 @@ out:
batadv_orig_node_free_ref(res_dst_orig_node);
if (req_dst_orig_node)
batadv_orig_node_free_ref(req_dst_orig_node);
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
if (primary_if)
batadv_hardif_free_ref(primary_if);
if (!ret)
@@ -1733,8 +1832,7 @@ static bool
batadv_send_my_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_request)
{
- struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *neigh_node = NULL;
+ struct batadv_orig_node *orig_node;
struct batadv_hard_iface *primary_if = NULL;
uint8_t my_ttvn, req_ttvn, ttvn;
int ret = false;
@@ -1759,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
if (!orig_node)
goto out;
- neigh_node = batadv_orig_node_get_router(orig_node);
- if (!neigh_node)
- goto out;
-
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
goto out;
@@ -1785,11 +1879,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN);
+ skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
if (!skb)
goto unlock;
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
@@ -1826,14 +1920,14 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
tt_response->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending TT_RESPONSE to %pM via %pM [%c]\n",
- orig_node->orig, neigh_node->addr,
+ "Sending TT_RESPONSE to %pM [%c]\n",
+ orig_node->orig,
(tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = true;
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+ ret = true;
goto out;
unlock:
@@ -1841,8 +1935,6 @@ unlock:
out:
if (orig_node)
batadv_orig_node_free_ref(orig_node);
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
if (primary_if)
batadv_hardif_free_ref(primary_if);
if (!ret)
@@ -1899,7 +1991,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_response)
{
- struct batadv_orig_node *orig_node = NULL;
+ struct batadv_orig_node *orig_node;
orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
if (!orig_node)
@@ -1941,7 +2033,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
{
- struct batadv_tt_local_entry *tt_local_entry = NULL;
+ struct batadv_tt_local_entry *tt_local_entry;
bool ret = false;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
@@ -1950,7 +2042,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
/* Check if the client has been logically deleted (but is kept for
* consistency purpose)
*/
- if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
+ if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
+ (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
goto out;
ret = true;
out:
@@ -2001,10 +2094,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
/* Recalculate the CRC for this orig_node and store it */
orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
- /* Roaming phase is over: tables are in sync again. I can
- * unset the flag
- */
- orig_node->tt_poss_change = false;
out:
if (orig_node)
batadv_orig_node_free_ref(orig_node);
@@ -2110,7 +2199,6 @@ unlock:
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
struct batadv_orig_node *orig_node)
{
- struct batadv_neigh_node *neigh_node = NULL;
struct sk_buff *skb = NULL;
struct batadv_roam_adv_packet *roam_adv_packet;
int ret = 1;
@@ -2123,11 +2211,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
if (!batadv_tt_check_roam_count(bat_priv, client))
goto out;
- skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN);
+ skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN);
+ skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
@@ -2143,23 +2231,17 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
memcpy(roam_adv_packet->client, client, ETH_ALEN);
- neigh_node = batadv_orig_node_get_router(orig_node);
- if (!neigh_node)
- goto out;
-
batadv_dbg(BATADV_DBG_TT, bat_priv,
- "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
- orig_node->orig, client, neigh_node->addr);
+ "Sending ROAMING_ADV to %pM (client %pM)\n",
+ orig_node->orig, client);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = 0;
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+ ret = 0;
out:
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
- if (ret)
+ if (ret && skb)
kfree_skb(skb);
return;
}
@@ -2295,7 +2377,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Local changes committed, updating to ttvn %u\n",
(uint8_t)atomic_read(&bat_priv->tt.vn));
- bat_priv->tt.poss_change = false;
/* reset the sending counter */
atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
@@ -2407,11 +2488,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
*/
if (orig_node->tt_crc != tt_crc)
goto request_table;
-
- /* Roaming phase is over: tables are in sync again. I can
- * unset the flag
- */
- orig_node->tt_poss_change = false;
} else {
/* if we missed more than one change or our tables are not
* in sync anymore -> request fresh tt data
@@ -2444,12 +2520,38 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
if (!tt_global_entry)
goto out;
- ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+ ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
batadv_tt_global_entry_free_ref(tt_global_entry);
out:
return ret;
}
+/**
+ * batadv_tt_local_client_is_roaming - tells whether the client is roaming
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the local client to query
+ *
+ * Returns true if the local client is known to be roaming (it is not served by
+ * this node anymore) or not. If yes, the client is still present in the table
+ * to keep the latter consistent with the node TTVN
+ */
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+ uint8_t *addr)
+{
+ struct batadv_tt_local_entry *tt_local_entry;
+ bool ret = false;
+
+ tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+ if (!tt_local_entry)
+ goto out;
+
+ ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+ batadv_tt_local_entry_free_ref(tt_local_entry);
+out:
+ return ret;
+
+}
+
bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *addr)
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 811fffd4760c..46d4451a59ee 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
int batadv_tt_init(struct batadv_priv *bat_priv);
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex);
-void batadv_tt_local_remove(struct batadv_priv *bat_priv,
- const uint8_t *addr, const char *message,
- bool roaming);
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+ const uint8_t *addr, const char *message,
+ bool roaming);
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
int packet_min_len);
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
uint8_t *addr);
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+ uint8_t *addr);
bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *addr);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index ac1e07a80454..ae9ac9aca8c5 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -28,20 +28,41 @@
(ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
sizeof(struct batadv_bcast_packet)))
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed,
+ * BATADV_DAT_ADDR_MAX is changed as well.
+ *
+ * *Please be careful: batadv_dat_addr_t must be UNSIGNED*
+ */
+#define batadv_dat_addr_t uint16_t
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+/**
+ * struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data
+ * @ogm_buff: buffer holding the OGM packet
+ * @ogm_buff_len: length of the OGM packet buffer
+ * @ogm_seqno: OGM sequence number - used to identify each OGM
+ */
+struct batadv_hard_iface_bat_iv {
+ unsigned char *ogm_buff;
+ int ogm_buff_len;
+ atomic_t ogm_seqno;
+};
+
struct batadv_hard_iface {
struct list_head list;
int16_t if_num;
char if_status;
struct net_device *net_dev;
- atomic_t seqno;
atomic_t frag_seqno;
- unsigned char *packet_buff;
- int packet_len;
struct kobject *hardif_obj;
atomic_t refcount;
struct packet_type batman_adv_ptype;
struct net_device *soft_iface;
struct rcu_head rcu;
+ struct batadv_hard_iface_bat_iv bat_iv;
};
/**
@@ -63,6 +84,9 @@ struct batadv_orig_node {
uint8_t orig[ETH_ALEN];
uint8_t primary_addr[ETH_ALEN];
struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
+#ifdef CONFIG_BATMAN_ADV_DAT
+ batadv_dat_addr_t dat_addr;
+#endif
unsigned long *bcast_own;
uint8_t *bcast_own_sum;
unsigned long last_seen;
@@ -77,13 +101,6 @@ struct batadv_orig_node {
spinlock_t tt_buff_lock; /* protects tt_buff */
atomic_t tt_size;
bool tt_initialised;
- /* The tt_poss_change flag is used to detect an ongoing roaming phase.
- * If true, then I sent a Roaming_adv to this orig_node and I have to
- * inspect every packet directed to it to check whether it is still
- * the true destination or not. This flag will be reset to false as
- * soon as I receive a new TTVN from this orig_node
- */
- bool tt_poss_change;
uint32_t last_real_seqno;
uint8_t last_ttl;
DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
@@ -139,7 +156,7 @@ struct batadv_neigh_node {
#ifdef CONFIG_BATMAN_ADV_BLA
struct batadv_bcast_duplist_entry {
uint8_t orig[ETH_ALEN];
- uint16_t crc;
+ __be32 crc;
unsigned long entrytime;
};
#endif
@@ -162,6 +179,13 @@ enum batadv_counters {
BATADV_CNT_TT_RESPONSE_RX,
BATADV_CNT_TT_ROAM_ADV_TX,
BATADV_CNT_TT_ROAM_ADV_RX,
+#ifdef CONFIG_BATMAN_ADV_DAT
+ BATADV_CNT_DAT_GET_TX,
+ BATADV_CNT_DAT_GET_RX,
+ BATADV_CNT_DAT_PUT_TX,
+ BATADV_CNT_DAT_PUT_RX,
+ BATADV_CNT_DAT_CACHED_REPLY_TX,
+#endif
BATADV_CNT_NUM,
};
@@ -181,7 +205,6 @@ struct batadv_priv_tt {
atomic_t vn;
atomic_t ogm_append_cnt;
atomic_t local_changes;
- bool poss_change;
struct list_head changes_list;
struct batadv_hashtable *local_hash;
struct batadv_hashtable *global_hash;
@@ -228,6 +251,20 @@ struct batadv_priv_vis {
struct batadv_vis_info *my_info;
};
+/**
+ * struct batadv_priv_dat - per mesh interface DAT private data
+ * @addr: node DAT address
+ * @hash: hashtable representing the local ARP cache
+ * @work: work queue callback item for cache purging
+ */
+#ifdef CONFIG_BATMAN_ADV_DAT
+struct batadv_priv_dat {
+ batadv_dat_addr_t addr;
+ struct batadv_hashtable *hash;
+ struct delayed_work work;
+};
+#endif
+
struct batadv_priv {
atomic_t mesh_state;
struct net_device_stats stats;
@@ -237,6 +274,9 @@ struct batadv_priv {
atomic_t fragmentation; /* boolean */
atomic_t ap_isolation; /* boolean */
atomic_t bridge_loop_avoidance; /* boolean */
+#ifdef CONFIG_BATMAN_ADV_DAT
+ atomic_t distributed_arp_table; /* boolean */
+#endif
atomic_t vis_mode; /* VIS_TYPE_* */
atomic_t gw_mode; /* GW_MODE_* */
atomic_t gw_sel_class; /* uint */
@@ -255,7 +295,7 @@ struct batadv_priv {
struct hlist_head forw_bcast_list;
struct batadv_hashtable *orig_hash;
spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
- spinlock_t forw_bcast_list_lock; /* protects */
+ spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */
struct delayed_work orig_work;
struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */
struct batadv_algo_ops *bat_algo_ops;
@@ -265,6 +305,9 @@ struct batadv_priv {
struct batadv_priv_gw gw;
struct batadv_priv_tt tt;
struct batadv_priv_vis vis;
+#ifdef CONFIG_BATMAN_ADV_DAT
+ struct batadv_priv_dat dat;
+#endif
};
struct batadv_socket_client {
@@ -318,6 +361,7 @@ struct batadv_backbone_gw {
struct hlist_node hash_entry;
struct batadv_priv *bat_priv;
unsigned long lasttime; /* last time we heard of this backbone gw */
+ atomic_t wait_periods;
atomic_t request_sent;
atomic_t refcount;
struct rcu_head rcu;
@@ -437,4 +481,36 @@ struct batadv_algo_ops {
void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
};
+/**
+ * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
+ * is used to stored ARP entries needed for the global DAT cache
+ * @ip: the IPv4 corresponding to this DAT/ARP entry
+ * @mac_addr: the MAC address associated to the stored IPv4
+ * @last_update: time in jiffies when this entry was refreshed last time
+ * @hash_entry: hlist node for batadv_priv_dat::hash
+ * @refcount: number of contexts the object is used
+ * @rcu: struct used for freeing in an RCU-safe manner
+ */
+struct batadv_dat_entry {
+ __be32 ip;
+ uint8_t mac_addr[ETH_ALEN];
+ unsigned long last_update;
+ struct hlist_node hash_entry;
+ atomic_t refcount;
+ struct rcu_head rcu;
+};
+
+/**
+ * struct batadv_dat_candidate - candidate destination for DAT operations
+ * @type: the type of the selected candidate. It can one of the following:
+ * - BATADV_DAT_CANDIDATE_NOT_FOUND
+ * - BATADV_DAT_CANDIDATE_ORIG
+ * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the
+ * corresponding originator node structure
+ */
+struct batadv_dat_candidate {
+ int type;
+ struct batadv_orig_node *orig_node;
+};
+
#endif /* _NET_BATMAN_ADV_TYPES_H_ */
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index f39723281ca1..10aff49fcf25 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -291,14 +291,118 @@ out:
return ret;
}
-int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv)
+/**
+ * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
+ * common fields for unicast packets
+ * @skb: packet
+ * @hdr_size: amount of bytes to push at the beginning of the skb
+ * @orig_node: the destination node
+ *
+ * Returns false if the buffer extension was not possible or true otherwise
+ */
+static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
+ struct batadv_orig_node *orig_node)
+{
+ struct batadv_unicast_packet *unicast_packet;
+ uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+
+ if (batadv_skb_head_push(skb, hdr_size) < 0)
+ return false;
+
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
+ unicast_packet->header.version = BATADV_COMPAT_VERSION;
+ /* batman packet type: unicast */
+ unicast_packet->header.packet_type = BATADV_UNICAST;
+ /* set unicast ttl */
+ unicast_packet->header.ttl = BATADV_TTL;
+ /* copy the destination for faster routing */
+ memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+ /* set the destination tt version number */
+ unicast_packet->ttvn = ttvn;
+
+ return true;
+}
+
+/**
+ * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node)
+{
+ size_t uni_size = sizeof(struct batadv_unicast_packet);
+ return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
+}
+
+/**
+ * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
+ * header
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ * @packet_subtype: the batman 4addr packet subtype to use
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ struct batadv_orig_node *orig,
+ int packet_subtype)
+{
+ struct batadv_hard_iface *primary_if;
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+ bool ret = false;
+
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ /* pull the header space and fill the unicast_packet substructure.
+ * We can do that because the first member of the unicast_4addr_packet
+ * is of type struct unicast_packet
+ */
+ if (!batadv_unicast_push_and_fill_skb(skb,
+ sizeof(*unicast_4addr_packet),
+ orig))
+ goto out;
+
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+ unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+ memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
+ ETH_ALEN);
+ unicast_4addr_packet->subtype = packet_subtype;
+ unicast_4addr_packet->reserved = 0;
+
+ ret = true;
+out:
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ return ret;
+}
+
+/**
+ * batadv_unicast_generic_send_skb - send an skb as unicast
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @packet_type: the batman unicast packet type to use
+ * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
+ * not BATADV_UNICAT_4ADDR
+ *
+ * Returns 1 in case of error or 0 otherwise
+ */
+int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int packet_type,
+ int packet_subtype)
{
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct batadv_unicast_packet *unicast_packet;
struct batadv_orig_node *orig_node;
struct batadv_neigh_node *neigh_node;
int data_len = skb->len;
- int ret = 1;
+ int ret = NET_RX_DROP;
unsigned int dev_mtu;
/* get routing information */
@@ -324,21 +428,23 @@ find_router:
if (!neigh_node)
goto out;
- if (batadv_skb_head_push(skb, sizeof(*unicast_packet)) < 0)
+ switch (packet_type) {
+ case BATADV_UNICAST:
+ batadv_unicast_prepare_skb(skb, orig_node);
+ break;
+ case BATADV_UNICAST_4ADDR:
+ batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
+ packet_subtype);
+ break;
+ default:
+ /* this function supports UNICAST and UNICAST_4ADDR only. It
+ * should never be invoked with any other packet type
+ */
goto out;
+ }
unicast_packet = (struct batadv_unicast_packet *)skb->data;
- unicast_packet->header.version = BATADV_COMPAT_VERSION;
- /* batman packet type: unicast */
- unicast_packet->header.packet_type = BATADV_UNICAST;
- /* set unicast ttl */
- unicast_packet->header.ttl = BATADV_TTL;
- /* copy the destination for faster routing */
- memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
- /* set the destination tt version number */
- unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-
/* inform the destination node that we are still missing a correct route
* for this client. The destination will receive this packet and will
* try to reroute it because the ttvn contained in the header is less
@@ -348,7 +454,9 @@ find_router:
unicast_packet->ttvn = unicast_packet->ttvn - 1;
dev_mtu = neigh_node->if_incoming->net_dev->mtu;
- if (atomic_read(&bat_priv->fragmentation) &&
+ /* fragmentation mechanism only works for UNICAST (now) */
+ if (packet_type == BATADV_UNICAST &&
+ atomic_read(&bat_priv->fragmentation) &&
data_len + sizeof(*unicast_packet) > dev_mtu) {
/* send frag skb decreases ttl */
unicast_packet->header.ttl++;
@@ -358,16 +466,15 @@ find_router:
goto out;
}
- batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = 0;
- goto out;
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+ ret = 0;
out:
if (neigh_node)
batadv_neigh_node_free_ref(neigh_node);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
- if (ret == 1)
+ if (ret == NET_RX_DROP)
kfree_skb(skb);
return ret;
}
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index 1c46e2eb1ef9..61abba58bd8f 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -29,10 +29,44 @@ int batadv_frag_reassemble_skb(struct sk_buff *skb,
struct batadv_priv *bat_priv,
struct sk_buff **new_skb);
void batadv_frag_list_free(struct list_head *head);
-int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv);
int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
struct batadv_hard_iface *hard_iface,
const uint8_t dstaddr[]);
+bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ int packet_subtype);
+int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int packet_type,
+ int packet_subtype);
+
+
+/**
+ * batadv_unicast_send_skb - send the skb encapsulated in a unicast packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ */
+static inline int batadv_unicast_send_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ return batadv_unicast_generic_send_skb(bat_priv, skb, BATADV_UNICAST,
+ 0);
+}
+
+/**
+ * batadv_unicast_send_skb - send the skb encapsulated in a unicast4addr packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ * @packet_subtype: the batman 4addr packet subtype to use
+ */
+static inline int batadv_unicast_4addr_send_skb(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ int packet_subtype)
+{
+ return batadv_unicast_generic_send_skb(bat_priv, skb,
+ BATADV_UNICAST_4ADDR,
+ packet_subtype);
+}
static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu)
{
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 5abd1454fb07..0f65a9de5f74 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -396,12 +396,12 @@ batadv_add_packet(struct batadv_priv *bat_priv,
return NULL;
len = sizeof(*packet) + vis_info_len;
- info->skb_packet = dev_alloc_skb(len + ETH_HLEN);
+ info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
if (!info->skb_packet) {
kfree(info);
return NULL;
}
- skb_reserve(info->skb_packet, ETH_HLEN);
+ skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
kref_init(&info->refcount);
@@ -698,15 +698,12 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
struct batadv_vis_info *info)
{
- struct batadv_neigh_node *router;
struct batadv_hashtable *hash = bat_priv->orig_hash;
struct hlist_node *node;
struct hlist_head *head;
struct batadv_orig_node *orig_node;
struct batadv_vis_packet *packet;
struct sk_buff *skb;
- struct batadv_hard_iface *hard_iface;
- uint8_t dstaddr[ETH_ALEN];
uint32_t i;
@@ -722,30 +719,20 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
if (!(orig_node->flags & BATADV_VIS_SERVER))
continue;
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
- continue;
-
/* don't send it if we already received the packet from
* this node.
*/
if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
- orig_node->orig)) {
- batadv_neigh_node_free_ref(router);
+ orig_node->orig))
continue;
- }
memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
- hard_iface = router->if_incoming;
- memcpy(dstaddr, router->addr, ETH_ALEN);
-
- batadv_neigh_node_free_ref(router);
-
skb = skb_clone(info->skb_packet, GFP_ATOMIC);
- if (skb)
- batadv_send_skb_packet(skb, hard_iface,
- dstaddr);
+ if (!skb)
+ continue;
+ if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+ kfree_skb(skb);
}
rcu_read_unlock();
}
@@ -755,7 +742,6 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
struct batadv_vis_info *info)
{
struct batadv_orig_node *orig_node;
- struct batadv_neigh_node *router = NULL;
struct sk_buff *skb;
struct batadv_vis_packet *packet;
@@ -765,17 +751,14 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
if (!orig_node)
goto out;
- router = batadv_orig_node_get_router(orig_node);
- if (!router)
+ skb = skb_clone(info->skb_packet, GFP_ATOMIC);
+ if (!skb)
goto out;
- skb = skb_clone(info->skb_packet, GFP_ATOMIC);
- if (skb)
- batadv_send_skb_packet(skb, router->if_incoming, router->addr);
+ if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+ kfree_skb(skb);
out:
- if (router)
- batadv_neigh_node_free_ref(router);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
}
@@ -873,12 +856,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
if (!bat_priv->vis.my_info)
goto err;
- len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
+ len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
+ len += ETH_HLEN + NET_IP_ALIGN;
bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
if (!bat_priv->vis.my_info->skb_packet)
goto free_info;
- skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
+ skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
tmp_skb = bat_priv->vis.my_info->skb_packet;
packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 3537d385035e..d3f3f7b1d32c 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,6 +11,7 @@ menuconfig BT
select CRYPTO_BLKCIPHER
select CRYPTO_AES
select CRYPTO_ECB
+ select CRYPTO_SHA256
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
@@ -47,4 +48,3 @@ source "net/bluetooth/cmtp/Kconfig"
source "net/bluetooth/hidp/Kconfig"
source "drivers/bluetooth/Kconfig"
-
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index fa6d94a4602a..dea6a287daca 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -10,4 +10,4 @@ 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
+ a2mp.o amp.o
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0760d1fed6f0..2f67d5ecc907 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -16,6 +16,11 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+
+/* Global AMP Manager list */
+LIST_HEAD(amp_mgr_list);
+DEFINE_MUTEX(amp_mgr_list_lock);
/* A2MP build & send command helper functions */
static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
@@ -37,8 +42,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
return cmd;
}
-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
- void *data)
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
{
struct l2cap_chan *chan = mgr->a2mp_chan;
struct a2mp_cmd *cmd;
@@ -63,6 +67,14 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
kfree(cmd);
}
+u8 __next_ident(struct amp_mgr *mgr)
+{
+ if (++mgr->ident == 0)
+ mgr->ident = 1;
+
+ return mgr->ident;
+}
+
static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
{
cl->id = 0;
@@ -161,6 +173,83 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
return 0;
}
+static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_discov_rsp *rsp = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+ struct a2mp_cl *cl;
+ u16 ext_feat;
+ bool found = false;
+
+ if (len < sizeof(*rsp))
+ return -EINVAL;
+
+ len -= sizeof(*rsp);
+ skb_pull(skb, sizeof(*rsp));
+
+ ext_feat = le16_to_cpu(rsp->ext_feat);
+
+ BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
+
+ /* check that packet is not broken for now */
+ while (ext_feat & A2MP_FEAT_EXT) {
+ if (len < sizeof(ext_feat))
+ return -EINVAL;
+
+ ext_feat = get_unaligned_le16(skb->data);
+ BT_DBG("efm 0x%4.4x", ext_feat);
+ len -= sizeof(ext_feat);
+ skb_pull(skb, sizeof(ext_feat));
+ }
+
+ cl = (void *) skb->data;
+ while (len >= sizeof(*cl)) {
+ BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
+ cl->status);
+
+ if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
+ struct a2mp_info_req req;
+
+ found = true;
+ req.id = cl->id;
+ a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
+ sizeof(req), &req);
+ }
+
+ len -= sizeof(*cl);
+ cl = (void *) skb_pull(skb, sizeof(*cl));
+ }
+
+ /* Fall back to L2CAP init sequence */
+ if (!found) {
+ struct l2cap_conn *conn = mgr->l2cap_conn;
+ struct l2cap_chan *chan;
+
+ mutex_lock(&conn->chan_lock);
+
+ list_for_each_entry(chan, &conn->chan_l, list) {
+
+ BT_DBG("chan %p state %s", chan,
+ state_to_string(chan->state));
+
+ if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+ continue;
+
+ l2cap_chan_lock(chan);
+
+ if (chan->state == BT_CONNECT)
+ l2cap_send_conn_req(chan);
+
+ l2cap_chan_unlock(chan);
+ }
+
+ mutex_unlock(&conn->chan_lock);
+ }
+
+ return 0;
+}
+
static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
@@ -181,7 +270,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
struct a2mp_info_req *req = (void *) skb->data;
- struct a2mp_info_rsp rsp;
struct hci_dev *hdev;
if (le16_to_cpu(hdr->len) < sizeof(*req))
@@ -189,53 +277,93 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("id %d", req->id);
- rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
-
hdev = hci_dev_get(req->id);
- if (hdev && hdev->amp_type != HCI_BREDR) {
- rsp.status = 0;
- rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
- rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
- rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
- rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
- rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ if (!hdev || hdev->dev_type != HCI_AMP) {
+ struct a2mp_info_rsp rsp;
+
+ rsp.id = req->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+ &rsp);
+
+ goto done;
}
+ mgr->state = READ_LOC_AMP_INFO;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+
+done:
if (hdev)
hci_dev_put(hdev);
- a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
-
skb_pull(skb, sizeof(*req));
return 0;
}
+static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data;
+ struct a2mp_amp_assoc_req req;
+ struct amp_ctrl *ctrl;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*rsp))
+ return -EINVAL;
+
+ BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status);
+
+ if (rsp->status)
+ return -EINVAL;
+
+ ctrl = amp_ctrl_add(mgr, rsp->id);
+ if (!ctrl)
+ return -ENOMEM;
+
+ req.id = rsp->id;
+ a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
+ &req);
+
+ skb_pull(skb, sizeof(*rsp));
+ return 0;
+}
+
static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
struct a2mp_amp_assoc_req *req = (void *) skb->data;
struct hci_dev *hdev;
+ struct amp_mgr *tmp;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
BT_DBG("id %d", req->id);
+ /* Make sure that other request is not processed */
+ tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+
hdev = hci_dev_get(req->id);
- if (!hdev || hdev->amp_type == HCI_BREDR) {
+ if (!hdev || hdev->amp_type == HCI_BREDR || tmp) {
struct a2mp_amp_assoc_rsp rsp;
rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (tmp) {
+ rsp.status = A2MP_STATUS_COLLISION_OCCURED;
+ amp_mgr_put(tmp);
+ } else {
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+ }
a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
&rsp);
- goto clean;
+
+ goto done;
}
- /* Placeholder for HCI Read AMP Assoc */
+ amp_read_loc_assoc(hdev, mgr);
-clean:
+done:
if (hdev)
hci_dev_put(hdev);
@@ -243,6 +371,68 @@ clean:
return 0;
}
+static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+ struct hci_dev *hdev;
+ struct amp_ctrl *ctrl;
+ struct hci_conn *hcon;
+ size_t assoc_len;
+
+ if (len < sizeof(*rsp))
+ return -EINVAL;
+
+ assoc_len = len - sizeof(*rsp);
+
+ BT_DBG("id %d status 0x%2.2x assoc len %zu", rsp->id, rsp->status,
+ assoc_len);
+
+ if (rsp->status)
+ return -EINVAL;
+
+ /* Save remote ASSOC data */
+ ctrl = amp_ctrl_lookup(mgr, rsp->id);
+ if (ctrl) {
+ u8 *assoc;
+
+ assoc = kzalloc(assoc_len, GFP_KERNEL);
+ if (!assoc) {
+ amp_ctrl_put(ctrl);
+ return -ENOMEM;
+ }
+
+ memcpy(assoc, rsp->amp_assoc, assoc_len);
+ ctrl->assoc = assoc;
+ ctrl->assoc_len = assoc_len;
+ ctrl->assoc_rem_len = assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ }
+
+ /* Create Phys Link */
+ hdev = hci_dev_get(rsp->id);
+ if (!hdev)
+ return -EINVAL;
+
+ hcon = phylink_add(hdev, mgr, rsp->id, true);
+ if (!hcon)
+ goto done;
+
+ BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
+
+ mgr->bredr_chan->remote_amp_id = rsp->id;
+
+ amp_create_phylink(hdev, mgr, hcon);
+
+done:
+ hci_dev_put(hdev);
+ skb_pull(skb, len);
+ return 0;
+}
+
static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
@@ -250,6 +440,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
+ struct hci_conn *hcon;
+ struct amp_ctrl *ctrl;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
@@ -265,9 +457,43 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
goto send_rsp;
}
- /* TODO process physlink create */
+ ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
+ if (!ctrl) {
+ ctrl = amp_ctrl_add(mgr, rsp.remote_id);
+ if (ctrl) {
+ amp_ctrl_get(ctrl);
+ } else {
+ rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+ goto send_rsp;
+ }
+ }
- rsp.status = A2MP_STATUS_SUCCESS;
+ if (ctrl) {
+ size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
+ u8 *assoc;
+
+ assoc = kzalloc(assoc_len, GFP_KERNEL);
+ if (!assoc) {
+ amp_ctrl_put(ctrl);
+ return -ENOMEM;
+ }
+
+ memcpy(assoc, req->amp_assoc, assoc_len);
+ ctrl->assoc = assoc;
+ ctrl->assoc_len = assoc_len;
+ ctrl->assoc_rem_len = assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ }
+
+ hcon = phylink_add(hdev, mgr, req->local_id, false);
+ if (hcon) {
+ amp_accept_phylink(hdev, mgr, hcon);
+ rsp.status = A2MP_STATUS_SUCCESS;
+ } else {
+ rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+ }
send_rsp:
if (hdev)
@@ -286,6 +512,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_physlink_req *req = (void *) skb->data;
struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
+ struct hci_conn *hcon;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
@@ -296,14 +523,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
rsp.remote_id = req->local_id;
rsp.status = A2MP_STATUS_SUCCESS;
- hdev = hci_dev_get(req->local_id);
+ hdev = hci_dev_get(req->remote_id);
if (!hdev) {
rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
goto send_rsp;
}
+ hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst);
+ if (!hcon) {
+ BT_ERR("No phys link exist");
+ rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
+ goto clean;
+ }
+
/* TODO Disconnect Phys Link here */
+clean:
hci_dev_put(hdev);
send_rsp:
@@ -377,10 +612,19 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
err = a2mp_discphyslink_req(mgr, skb, hdr);
break;
- case A2MP_CHANGE_RSP:
case A2MP_DISCOVER_RSP:
+ err = a2mp_discover_rsp(mgr, skb, hdr);
+ break;
+
case A2MP_GETINFO_RSP:
+ err = a2mp_getinfo_rsp(mgr, skb, hdr);
+ break;
+
case A2MP_GETAMPASSOC_RSP:
+ err = a2mp_getampassoc_rsp(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_RSP:
case A2MP_CREATEPHYSLINK_RSP:
case A2MP_DISCONNPHYSLINK_RSP:
err = a2mp_cmd_rsp(mgr, skb, hdr);
@@ -455,9 +699,10 @@ static struct l2cap_ops a2mp_chan_ops = {
.new_connection = l2cap_chan_no_new_connection,
.teardown = l2cap_chan_no_teardown,
.ready = l2cap_chan_no_ready,
+ .defer = l2cap_chan_no_defer,
};
-static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
+static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
{
struct l2cap_chan *chan;
int err;
@@ -492,7 +737,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
chan->conf_state = 0;
- l2cap_chan_add(conn, chan);
+ if (locked)
+ __l2cap_chan_add(conn, chan);
+ else
+ l2cap_chan_add(conn, chan);
chan->remote_mps = chan->omtu;
chan->mps = chan->omtu;
@@ -503,11 +751,13 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
}
/* AMP Manager functions */
-void amp_mgr_get(struct amp_mgr *mgr)
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
{
BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
kref_get(&mgr->kref);
+
+ return mgr;
}
static void amp_mgr_destroy(struct kref *kref)
@@ -516,6 +766,11 @@ static void amp_mgr_destroy(struct kref *kref)
BT_DBG("mgr %p", mgr);
+ mutex_lock(&amp_mgr_list_lock);
+ list_del(&mgr->list);
+ mutex_unlock(&amp_mgr_list_lock);
+
+ amp_ctrl_list_flush(mgr);
kfree(mgr);
}
@@ -526,7 +781,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
return kref_put(&mgr->kref, &amp_mgr_destroy);
}
-static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
{
struct amp_mgr *mgr;
struct l2cap_chan *chan;
@@ -539,7 +794,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
mgr->l2cap_conn = conn;
- chan = a2mp_chan_open(conn);
+ chan = a2mp_chan_open(conn, locked);
if (!chan) {
kfree(mgr);
return NULL;
@@ -552,6 +807,14 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
kref_init(&mgr->kref);
+ /* Remote AMP ctrl list initialization */
+ INIT_LIST_HEAD(&mgr->amp_ctrls);
+ mutex_init(&mgr->amp_ctrls_lock);
+
+ mutex_lock(&amp_mgr_list_lock);
+ list_add(&mgr->list, &amp_mgr_list);
+ mutex_unlock(&amp_mgr_list_lock);
+
return mgr;
}
@@ -560,7 +823,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
{
struct amp_mgr *mgr;
- mgr = amp_mgr_create(conn);
+ mgr = amp_mgr_create(conn, false);
if (!mgr) {
BT_ERR("Could not create AMP manager");
return NULL;
@@ -570,3 +833,139 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
return mgr->a2mp_chan;
}
+
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
+{
+ struct amp_mgr *mgr;
+
+ mutex_lock(&amp_mgr_list_lock);
+ list_for_each_entry(mgr, &amp_mgr_list, list) {
+ if (mgr->state == state) {
+ amp_mgr_get(mgr);
+ mutex_unlock(&amp_mgr_list_lock);
+ return mgr;
+ }
+ }
+ mutex_unlock(&amp_mgr_list_lock);
+
+ return NULL;
+}
+
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+{
+ struct amp_mgr *mgr;
+ struct a2mp_info_rsp rsp;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ rsp.id = hdev->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (hdev->amp_type != HCI_BREDR) {
+ rsp.status = 0;
+ rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+ rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+ rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+ rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+ rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ }
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+ amp_mgr_put(mgr);
+}
+
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
+{
+ struct amp_mgr *mgr;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+ struct a2mp_amp_assoc_rsp *rsp;
+ size_t len;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
+ rsp = kzalloc(len, GFP_KERNEL);
+ if (!rsp) {
+ amp_mgr_put(mgr);
+ return;
+ }
+
+ rsp->id = hdev->id;
+
+ if (status) {
+ rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
+ } else {
+ rsp->status = A2MP_STATUS_SUCCESS;
+ memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
+ }
+
+ a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
+ amp_mgr_put(mgr);
+ kfree(rsp);
+}
+
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
+{
+ struct amp_mgr *mgr;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+ struct a2mp_physlink_req *req;
+ struct l2cap_chan *bredr_chan;
+ size_t len;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
+ if (!mgr)
+ return;
+
+ len = sizeof(*req) + loc_assoc->len;
+
+ BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
+
+ req = kzalloc(len, GFP_KERNEL);
+ if (!req) {
+ amp_mgr_put(mgr);
+ return;
+ }
+
+ bredr_chan = mgr->bredr_chan;
+ if (!bredr_chan)
+ goto clean;
+
+ req->local_id = hdev->id;
+ req->remote_id = bredr_chan->remote_amp_id;
+ memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
+
+ a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
+
+clean:
+ amp_mgr_put(mgr);
+ kfree(req);
+}
+
+void a2mp_discover_amp(struct l2cap_chan *chan)
+{
+ struct l2cap_conn *conn = chan->conn;
+ struct amp_mgr *mgr = conn->hcon->amp_mgr;
+ struct a2mp_discov_req req;
+
+ BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
+
+ if (!mgr) {
+ mgr = amp_mgr_create(conn, true);
+ if (!mgr)
+ return;
+ }
+
+ mgr->bredr_chan = chan;
+
+ req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+ req.ext_feat = 0;
+ a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
+}
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index ba033f09196e..5355df63d39b 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -569,7 +569,6 @@ static int bt_seq_show(struct seq_file *seq, void *v)
{
struct bt_seq_state *s = seq->private;
struct bt_sock_list *l = s->l;
- bdaddr_t src_baswapped, dst_baswapped;
if (v == SEQ_START_TOKEN) {
seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
@@ -583,18 +582,17 @@ static int bt_seq_show(struct seq_file *seq, void *v)
} else {
struct sock *sk = sk_entry(v);
struct bt_sock *bt = bt_sk(sk);
- baswap(&src_baswapped, &bt->src);
- baswap(&dst_baswapped, &bt->dst);
- seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
+ seq_printf(seq,
+ "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
sk,
atomic_read(&sk->sk_refcnt),
sk_rmem_alloc_get(sk),
sk_wmem_alloc_get(sk),
from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
sock_i_ino(sk),
- &src_baswapped,
- &dst_baswapped,
+ &bt->src,
+ &bt->dst,
bt->parent? sock_i_ino(bt->parent): 0LU);
if (l->custom_seq_show) {
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
new file mode 100644
index 000000000000..1b0d92c0643a
--- /dev/null
+++ b/net/bluetooth/amp.c
@@ -0,0 +1,471 @@
+/*
+ Copyright (c) 2011,2012 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 <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+#include <crypto/hash.h>
+
+/* Remote AMP Controllers interface */
+void amp_ctrl_get(struct amp_ctrl *ctrl)
+{
+ BT_DBG("ctrl %p orig refcnt %d", ctrl,
+ atomic_read(&ctrl->kref.refcount));
+
+ kref_get(&ctrl->kref);
+}
+
+static void amp_ctrl_destroy(struct kref *kref)
+{
+ struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
+
+ BT_DBG("ctrl %p", ctrl);
+
+ kfree(ctrl->assoc);
+ kfree(ctrl);
+}
+
+int amp_ctrl_put(struct amp_ctrl *ctrl)
+{
+ BT_DBG("ctrl %p orig refcnt %d", ctrl,
+ atomic_read(&ctrl->kref.refcount));
+
+ return kref_put(&ctrl->kref, &amp_ctrl_destroy);
+}
+
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id)
+{
+ struct amp_ctrl *ctrl;
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return NULL;
+
+ kref_init(&ctrl->kref);
+ ctrl->id = id;
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_add(&ctrl->list, &mgr->amp_ctrls);
+ mutex_unlock(&mgr->amp_ctrls_lock);
+
+ BT_DBG("mgr %p ctrl %p", mgr, ctrl);
+
+ return ctrl;
+}
+
+void amp_ctrl_list_flush(struct amp_mgr *mgr)
+{
+ struct amp_ctrl *ctrl, *n;
+
+ BT_DBG("mgr %p", mgr);
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
+ list_del(&ctrl->list);
+ amp_ctrl_put(ctrl);
+ }
+ mutex_unlock(&mgr->amp_ctrls_lock);
+}
+
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
+{
+ struct amp_ctrl *ctrl;
+
+ BT_DBG("mgr %p id %d", mgr, id);
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
+ if (ctrl->id == id) {
+ amp_ctrl_get(ctrl);
+ mutex_unlock(&mgr->amp_ctrls_lock);
+ return ctrl;
+ }
+ }
+ mutex_unlock(&mgr->amp_ctrls_lock);
+
+ return NULL;
+}
+
+/* Physical Link interface */
+static u8 __next_handle(struct amp_mgr *mgr)
+{
+ if (++mgr->handle == 0)
+ mgr->handle = 1;
+
+ return mgr->handle;
+}
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+ u8 remote_id, bool out)
+{
+ bdaddr_t *dst = mgr->l2cap_conn->dst;
+ struct hci_conn *hcon;
+
+ hcon = hci_conn_add(hdev, AMP_LINK, dst);
+ if (!hcon)
+ return NULL;
+
+ BT_DBG("hcon %p dst %pMR", hcon, dst);
+
+ hcon->state = BT_CONNECT;
+ hcon->attempt++;
+ hcon->handle = __next_handle(mgr);
+ hcon->remote_id = remote_id;
+ hcon->amp_mgr = amp_mgr_get(mgr);
+ hcon->out = out;
+
+ return hcon;
+}
+
+/* AMP crypto key generation interface */
+static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
+{
+ int ret = 0;
+ struct crypto_shash *tfm;
+
+ if (!ksize)
+ return -EINVAL;
+
+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ if (IS_ERR(tfm)) {
+ BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ ret = crypto_shash_setkey(tfm, key, ksize);
+ if (ret) {
+ BT_DBG("crypto_ahash_setkey failed: err %d", ret);
+ } else {
+ struct {
+ struct shash_desc shash;
+ char ctx[crypto_shash_descsize(tfm)];
+ } desc;
+
+ desc.shash.tfm = tfm;
+ desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ret = crypto_shash_digest(&desc.shash, plaintext, psize,
+ output);
+ }
+
+ crypto_free_shash(tfm);
+ return ret;
+}
+
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct link_key *key;
+ u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+ u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+ int err;
+
+ if (!hci_conn_check_link_mode(conn))
+ return -EACCES;
+
+ BT_DBG("conn %p key_type %d", conn, conn->key_type);
+
+ /* Legacy key */
+ if (conn->key_type < 3) {
+ BT_ERR("Legacy key type %d", conn->key_type);
+ return -EACCES;
+ }
+
+ *type = conn->key_type;
+ *len = HCI_AMP_LINK_KEY_SIZE;
+
+ key = hci_find_link_key(hdev, &conn->dst);
+ if (!key) {
+ BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst);
+ return -EACCES;
+ }
+
+ /* BR/EDR Link Key concatenated together with itself */
+ memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+ memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+
+ /* Derive Generic AMP Link Key (gamp) */
+ err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+ if (err) {
+ BT_ERR("Could not derive Generic AMP Key: err %d", err);
+ return err;
+ }
+
+ if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+ BT_DBG("Use Generic AMP Key (gamp)");
+ memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+ return err;
+ }
+
+ /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+ return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+}
+
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+
+ BT_DBG("%s handle %d", hdev->name, phy_handle);
+
+ cp.phy_handle = phy_handle;
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+ cp.len_so_far = cpu_to_le16(loc_assoc->offset);
+
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+
+ memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
+ memset(&cp, 0, sizeof(cp));
+
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+ mgr->state = READ_LOC_AMP_ASSOC;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+ struct amp_mgr *mgr = hcon->amp_mgr;
+
+ cp.phy_handle = hcon->handle;
+ cp.len_so_far = cpu_to_le16(0);
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+ mgr->state = READ_LOC_AMP_ASSOC_FINAL;
+
+ /* Read Local AMP Assoc final link information data */
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+/* Write AMP Assoc data fragments, returns true with last fragment written*/
+static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_write_remote_amp_assoc *cp;
+ struct amp_mgr *mgr = hcon->amp_mgr;
+ struct amp_ctrl *ctrl;
+ u16 frag_len, len;
+
+ ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
+ if (!ctrl)
+ return false;
+
+ if (!ctrl->assoc_rem_len) {
+ BT_DBG("all fragments are written");
+ ctrl->assoc_rem_len = ctrl->assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ return true;
+ }
+
+ frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
+ len = frag_len + sizeof(*cp);
+
+ cp = kzalloc(len, GFP_KERNEL);
+ if (!cp) {
+ amp_ctrl_put(ctrl);
+ return false;
+ }
+
+ BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
+ hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
+
+ cp->phy_handle = hcon->handle;
+ cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
+ cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
+ memcpy(cp->frag, ctrl->assoc, frag_len);
+
+ ctrl->assoc_len_so_far += frag_len;
+ ctrl->assoc_rem_len -= frag_len;
+
+ amp_ctrl_put(ctrl);
+
+ hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
+
+ kfree(cp);
+
+ return false;
+}
+
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
+{
+ struct hci_conn *hcon;
+
+ BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, handle);
+ if (!hcon)
+ return;
+
+ amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
+{
+ struct hci_conn *hcon;
+
+ BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, handle);
+ if (!hcon)
+ return;
+
+ BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
+
+ amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_create_phy_link cp;
+
+ cp.phy_handle = hcon->handle;
+
+ BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+ hcon->handle);
+
+ if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+ &cp.key_type)) {
+ BT_DBG("Cannot create link key");
+ return;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
+}
+
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_accept_phy_link cp;
+
+ cp.phy_handle = hcon->handle;
+
+ BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+ hcon->handle);
+
+ if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+ &cp.key_type)) {
+ BT_DBG("Cannot create link key");
+ return;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
+}
+
+void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon)
+{
+ struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
+ struct amp_mgr *mgr = hs_hcon->amp_mgr;
+ struct l2cap_chan *bredr_chan;
+
+ BT_DBG("bredr_hcon %p hs_hcon %p mgr %p", bredr_hcon, hs_hcon, mgr);
+
+ if (!bredr_hdev || !mgr || !mgr->bredr_chan)
+ return;
+
+ bredr_chan = mgr->bredr_chan;
+
+ l2cap_chan_lock(bredr_chan);
+
+ set_bit(FLAG_EFS_ENABLE, &bredr_chan->flags);
+ bredr_chan->remote_amp_id = hs_hcon->remote_id;
+ bredr_chan->local_amp_id = hs_hcon->hdev->id;
+ bredr_chan->hs_hcon = hs_hcon;
+ bredr_chan->conn->mtu = hs_hcon->hdev->block_mtu;
+
+ __l2cap_physical_cfm(bredr_chan, 0);
+
+ l2cap_chan_unlock(bredr_chan);
+
+ hci_dev_put(bredr_hdev);
+}
+
+void amp_create_logical_link(struct l2cap_chan *chan)
+{
+ struct hci_cp_create_accept_logical_link cp;
+ struct hci_conn *hcon;
+ struct hci_dev *hdev;
+
+ BT_DBG("chan %p", chan);
+
+ if (!chan->hs_hcon)
+ return;
+
+ hdev = hci_dev_hold(chan->hs_hcon->hdev);
+ if (!hdev)
+ return;
+
+ BT_DBG("chan %p dst %pMR", chan, chan->conn->dst);
+
+ hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, chan->conn->dst);
+ if (!hcon)
+ goto done;
+
+ cp.phy_handle = hcon->handle;
+
+ cp.tx_flow_spec.id = chan->local_id;
+ cp.tx_flow_spec.stype = chan->local_stype;
+ cp.tx_flow_spec.msdu = cpu_to_le16(chan->local_msdu);
+ cp.tx_flow_spec.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
+ cp.tx_flow_spec.acc_lat = cpu_to_le32(chan->local_acc_lat);
+ cp.tx_flow_spec.flush_to = cpu_to_le32(chan->local_flush_to);
+
+ cp.rx_flow_spec.id = chan->remote_id;
+ cp.rx_flow_spec.stype = chan->remote_stype;
+ cp.rx_flow_spec.msdu = cpu_to_le16(chan->remote_msdu);
+ cp.rx_flow_spec.sdu_itime = cpu_to_le32(chan->remote_sdu_itime);
+ cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat);
+ cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to);
+
+ if (hcon->out)
+ hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp),
+ &cp);
+ else
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp),
+ &cp);
+
+done:
+ hci_dev_put(hdev);
+}
+
+void amp_disconnect_logical_link(struct hci_chan *hchan)
+{
+ struct hci_conn *hcon = hchan->conn;
+ struct hci_cp_disconn_logical_link cp;
+
+ if (hcon->state != BT_CONNECTED) {
+ BT_DBG("hchan %p not connected", hchan);
+ return;
+ }
+
+ cp.log_handle = cpu_to_le16(hchan->handle);
+ hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK, sizeof(cp), &cp);
+}
+
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason)
+{
+ BT_DBG("hchan %p", hchan);
+
+ hci_chan_del(hchan);
+}
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 4a6620bc1570..a5b639702637 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -182,8 +182,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
a2 = data;
data += ETH_ALEN;
- BT_DBG("mc filter %s -> %s",
- batostr((void *) a1), batostr((void *) a2));
+ BT_DBG("mc filter %pMR -> %pMR", a1, a2);
/* Iterate from a1 to a2 */
set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 98f86f91d47c..e58c8b32589c 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -25,7 +25,6 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/export.h>
#include <linux/etherdevice.h>
#include <net/bluetooth/bluetooth.h>
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 50f0d135eb8f..a4a9d4b6816c 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -20,7 +20,7 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/types.h>
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 6c9c1fd601ca..e0a6ebf2baa6 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -353,7 +353,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
BT_DBG("mtu %d", session->mtu);
- sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst));
+ sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst);
session->sock = sock;
session->state = BT_CONFIG;
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index aacb802d1ee4..1c57482112b6 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -20,7 +20,7 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/types.h>
#include <linux/capability.h>
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b9196a44f759..25bfce0666eb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
+static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
+{
+ struct hci_cp_disconn_phy_link cp;
+
+ BT_DBG("hcon %p", conn);
+
+ conn->state = BT_DISCONN;
+
+ cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
+ cp.reason = reason;
+ hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
+ sizeof(cp), &cp);
+}
+
static void hci_add_sco(struct hci_conn *conn, __u16 handle)
{
struct hci_dev *hdev = conn->hdev;
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
}
}
+static void hci_conn_disconnect(struct hci_conn *conn)
+{
+ __u8 reason = hci_proto_disconn_ind(conn);
+
+ switch (conn->type) {
+ case ACL_LINK:
+ hci_acl_disconn(conn, reason);
+ break;
+ case AMP_LINK:
+ hci_amp_disconn(conn, reason);
+ break;
+ }
+}
+
static void hci_conn_timeout(struct work_struct *work)
{
struct hci_conn *conn = container_of(work, struct hci_conn,
disc_work.work);
- __u8 reason;
BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work)
break;
case BT_CONFIG:
case BT_CONNECTED:
- reason = hci_proto_disconn_ind(conn);
- hci_acl_disconn(conn, reason);
+ hci_conn_disconnect(conn);
break;
default:
conn->state = BT_CLOSED;
@@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
{
struct hci_conn *conn;
- BT_DBG("%s dst %s", hdev->name, batostr(dst));
+ BT_DBG("%s dst %pMR", hdev->name, dst);
conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
if (!conn)
@@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
int use_src = bacmp(src, BDADDR_ANY);
struct hci_dev *hdev = NULL, *d;
- BT_DBG("%s -> %s", batostr(src), batostr(dst));
+ BT_DBG("%pMR -> %pMR", src, dst);
read_lock(&hci_dev_list_lock);
@@ -476,6 +502,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
{
struct hci_conn *le;
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags))
+ return ERR_PTR(-ENOTSUPP);
+
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (!le) {
le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
@@ -567,7 +596,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type)
{
- BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type);
+ BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
switch (type) {
case LE_LINK:
@@ -933,6 +962,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
chan->conn = conn;
skb_queue_head_init(&chan->data_q);
+ chan->state = BT_CONNECTED;
list_add_rcu(&chan->list, &conn->chan_list);
@@ -950,6 +980,8 @@ void hci_chan_del(struct hci_chan *chan)
synchronize_rcu();
+ hci_conn_put(conn);
+
skb_queue_purge(&chan->data_q);
kfree(chan);
}
@@ -963,3 +995,35 @@ void hci_chan_list_flush(struct hci_conn *conn)
list_for_each_entry_safe(chan, n, &conn->chan_list, list)
hci_chan_del(chan);
}
+
+static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon,
+ __u16 handle)
+{
+ struct hci_chan *hchan;
+
+ list_for_each_entry(hchan, &hcon->chan_list, list) {
+ if (hchan->handle == handle)
+ return hchan;
+ }
+
+ return NULL;
+}
+
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *hcon;
+ struct hci_chan *hchan = NULL;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(hcon, &h->list, list) {
+ hchan = __hci_chan_lookup_handle(hcon, handle);
+ if (hchan)
+ break;
+ }
+
+ rcu_read_unlock();
+
+ return hchan;
+}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a0a2f97b9c62..596660d37c5e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -178,48 +178,13 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
static void bredr_init(struct hci_dev *hdev)
{
- struct hci_cp_delete_stored_link_key cp;
- __le16 param;
- __u8 flt_type;
-
hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
- /* Mandatory initialization */
-
/* Read Local Supported Features */
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local Version */
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
-
- /* Read Buffer Size (ACL mtu, max pkt, etc.) */
- hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
-
- /* Read BD Address */
- hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
-
- /* Read Class of Device */
- hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
-
- /* Read Local Name */
- hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
-
- /* Read Voice Setting */
- hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
-
- /* Optional initialization */
-
- /* Clear Event Filters */
- flt_type = HCI_FLT_CLEAR_ALL;
- hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
-
- /* Connection accept timeout ~20 secs */
- param = __constant_cpu_to_le16(0x7d00);
- hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
-
- bacpy(&cp.bdaddr, BDADDR_ANY);
- cp.delete_all = 1;
- hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
}
static void amp_init(struct hci_dev *hdev)
@@ -273,14 +238,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
}
}
-static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
-{
- BT_DBG("%s", hdev->name);
-
- /* Read LE buffer size */
- hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
-}
-
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
{
__u8 scan = opt;
@@ -405,7 +362,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
- BT_DBG("cache %p, %s", cache, batostr(bdaddr));
+ BT_DBG("cache %p, %pMR", cache, bdaddr);
list_for_each_entry(e, &cache->all, all) {
if (!bacmp(&e->data.bdaddr, bdaddr))
@@ -421,7 +378,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
- BT_DBG("cache %p, %s", cache, batostr(bdaddr));
+ BT_DBG("cache %p, %pMR", cache, bdaddr);
list_for_each_entry(e, &cache->unknown, list) {
if (!bacmp(&e->data.bdaddr, bdaddr))
@@ -438,7 +395,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
- BT_DBG("cache %p bdaddr %s state %d", cache, batostr(bdaddr), state);
+ BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
list_for_each_entry(e, &cache->resolve, list) {
if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
@@ -475,7 +432,9 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *ie;
- BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
+ BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
+
+ hci_remove_remote_oob_data(hdev, &data->bdaddr);
if (ssp)
*ssp = data->ssp_mode;
@@ -637,6 +596,99 @@ done:
return err;
}
+static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
+{
+ u8 ad_len = 0, flags = 0;
+ size_t name_len;
+
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
+ flags |= LE_AD_GENERAL;
+
+ if (!lmp_bredr_capable(hdev))
+ flags |= LE_AD_NO_BREDR;
+
+ if (lmp_le_br_capable(hdev))
+ flags |= LE_AD_SIM_LE_BREDR_CTRL;
+
+ if (lmp_host_le_br_capable(hdev))
+ flags |= LE_AD_SIM_LE_BREDR_HOST;
+
+ if (flags) {
+ BT_DBG("adv flags 0x%02x", flags);
+
+ ptr[0] = 2;
+ ptr[1] = EIR_FLAGS;
+ ptr[2] = flags;
+
+ ad_len += 3;
+ ptr += 3;
+ }
+
+ if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
+ ptr[0] = 2;
+ ptr[1] = EIR_TX_POWER;
+ ptr[2] = (u8) hdev->adv_tx_power;
+
+ ad_len += 3;
+ ptr += 3;
+ }
+
+ name_len = strlen(hdev->dev_name);
+ if (name_len > 0) {
+ size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
+
+ if (name_len > max_len) {
+ name_len = max_len;
+ ptr[1] = EIR_NAME_SHORT;
+ } else
+ ptr[1] = EIR_NAME_COMPLETE;
+
+ ptr[0] = name_len + 1;
+
+ memcpy(ptr + 2, hdev->dev_name, name_len);
+
+ ad_len += (name_len + 2);
+ ptr += (name_len + 2);
+ }
+
+ return ad_len;
+}
+
+int hci_update_ad(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_adv_data cp;
+ u8 len;
+ int err;
+
+ hci_dev_lock(hdev);
+
+ if (!lmp_le_capable(hdev)) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+
+ len = create_ad(hdev, cp.data);
+
+ if (hdev->adv_data_len == len &&
+ memcmp(cp.data, hdev->adv_data, len) == 0) {
+ err = 0;
+ goto unlock;
+ }
+
+ memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
+ hdev->adv_data_len = len;
+
+ cp.length = len;
+ err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
+
+unlock:
+ hci_dev_unlock(hdev);
+
+ return err;
+}
+
/* ---- HCI ioctl helpers ---- */
int hci_dev_open(__u16 dev)
@@ -687,10 +739,6 @@ int hci_dev_open(__u16 dev)
ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
- if (lmp_host_le_capable(hdev))
- ret = __hci_request(hdev, hci_le_init_req, 0,
- HCI_INIT_TIMEOUT);
-
clear_bit(HCI_INIT, &hdev->flags);
}
@@ -698,6 +746,7 @@ int hci_dev_open(__u16 dev)
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
+ hci_update_ad(hdev);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev);
@@ -812,6 +861,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Clear flags */
hdev->flags = 0;
+ /* Controller radio is available but is currently powered down */
+ hdev->amp_status = 0;
+
memset(hdev->eir, 0, sizeof(hdev->eir));
memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
@@ -1039,10 +1091,17 @@ int hci_get_dev_info(void __user *arg)
di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4);
di.flags = hdev->flags;
di.pkt_type = hdev->pkt_type;
- di.acl_mtu = hdev->acl_mtu;
- di.acl_pkts = hdev->acl_pkts;
- di.sco_mtu = hdev->sco_mtu;
- di.sco_pkts = hdev->sco_pkts;
+ if (lmp_bredr_capable(hdev)) {
+ di.acl_mtu = hdev->acl_mtu;
+ di.acl_pkts = hdev->acl_pkts;
+ di.sco_mtu = hdev->sco_mtu;
+ di.sco_pkts = hdev->sco_pkts;
+ } else {
+ di.acl_mtu = hdev->le_mtu;
+ di.acl_pkts = hdev->le_pkts;
+ di.sco_mtu = 0;
+ di.sco_pkts = 0;
+ }
di.link_policy = hdev->link_policy;
di.link_mode = hdev->link_mode;
@@ -1259,7 +1318,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
list_add(&key->list, &hdev->link_keys);
}
- BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
+ BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
/* Some buggy controller combinations generate a changed
* combination key for legacy pairing even when there's no
@@ -1338,7 +1397,7 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
if (!key)
return -ENOENT;
- BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+ BT_DBG("%s removing %pMR", hdev->name, bdaddr);
list_del(&key->list);
kfree(key);
@@ -1354,7 +1413,7 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr)
if (bacmp(bdaddr, &k->bdaddr))
continue;
- BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+ BT_DBG("%s removing %pMR", hdev->name, bdaddr);
list_del(&k->list);
kfree(k);
@@ -1401,7 +1460,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
if (!data)
return -ENOENT;
- BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+ BT_DBG("%s removing %pMR", hdev->name, bdaddr);
list_del(&data->list);
kfree(data);
@@ -1440,7 +1499,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
memcpy(data->hash, hash, sizeof(data->hash));
memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
- BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
+ BT_DBG("%s for %pMR", hdev->name, bdaddr);
return 0;
}
@@ -1617,6 +1676,9 @@ int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
BT_DBG("%s", hdev->name);
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
+ return -ENOTSUPP;
+
if (work_busy(&hdev->le_scan))
return -EINPROGRESS;
@@ -1643,6 +1705,8 @@ struct hci_dev *hci_alloc_dev(void)
hdev->esco_type = (ESCO_HV1);
hdev->link_mode = (HCI_LM_ACCEPT);
hdev->io_capability = 0x03; /* No Input No Output */
+ hdev->inq_tx_power = HCI_TX_POWER_INVALID;
+ hdev->adv_tx_power = HCI_TX_POWER_INVALID;
hdev->sniff_max_interval = 800;
hdev->sniff_min_interval = 80;
@@ -1793,6 +1857,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
for (i = 0; i < NUM_REASSEMBLY; i++)
kfree_skb(hdev->reassembly[i]);
+ cancel_work_sync(&hdev->power_on);
+
if (!test_bit(HCI_INIT, &hdev->flags) &&
!test_bit(HCI_SETUP, &hdev->dev_flags)) {
hci_dev_lock(hdev);
@@ -2153,9 +2219,10 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
hdr->dlen = cpu_to_le16(len);
}
-static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
+static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
struct sk_buff *skb, __u16 flags)
{
+ struct hci_conn *conn = chan->conn;
struct hci_dev *hdev = conn->hdev;
struct sk_buff *list;
@@ -2163,7 +2230,18 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
skb->data_len = 0;
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
- hci_add_acl_hdr(skb, conn->handle, flags);
+
+ switch (hdev->dev_type) {
+ case HCI_BREDR:
+ hci_add_acl_hdr(skb, conn->handle, flags);
+ break;
+ case HCI_AMP:
+ hci_add_acl_hdr(skb, chan->handle, flags);
+ break;
+ default:
+ BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
+ return;
+ }
list = skb_shinfo(skb)->frag_list;
if (!list) {
@@ -2202,14 +2280,13 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
{
- struct hci_conn *conn = chan->conn;
- struct hci_dev *hdev = conn->hdev;
+ struct hci_dev *hdev = chan->conn->hdev;
BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);
skb->dev = (void *) hdev;
- hci_queue_acl(conn, &chan->data_q, skb, flags);
+ hci_queue_acl(chan, &chan->data_q, skb, flags);
queue_work(hdev->workqueue, &hdev->tx_work);
}
@@ -2311,8 +2388,8 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
/* Kill stalled connections */
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == type && c->sent) {
- BT_ERR("%s killing stalled connection %s",
- hdev->name, batostr(&c->dst));
+ BT_ERR("%s killing stalled connection %pMR",
+ hdev->name, &c->dst);
hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM);
}
}
@@ -2381,6 +2458,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
case ACL_LINK:
cnt = hdev->acl_cnt;
break;
+ case AMP_LINK:
+ cnt = hdev->block_cnt;
+ break;
case SCO_LINK:
case ESCO_LINK:
cnt = hdev->sco_cnt;
@@ -2510,11 +2590,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
struct hci_chan *chan;
struct sk_buff *skb;
int quote;
+ u8 type;
__check_timeout(hdev, cnt);
+ BT_DBG("%s", hdev->name);
+
+ if (hdev->dev_type == HCI_AMP)
+ type = AMP_LINK;
+ else
+ type = ACL_LINK;
+
while (hdev->block_cnt > 0 &&
- (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
+ (chan = hci_chan_sent(hdev, type, &quote))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
int blocks;
@@ -2547,14 +2635,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
}
if (cnt != hdev->block_cnt)
- hci_prio_recalculate(hdev, ACL_LINK);
+ hci_prio_recalculate(hdev, type);
}
static void hci_sched_acl(struct hci_dev *hdev)
{
BT_DBG("%s", hdev->name);
- if (!hci_conn_num(hdev, ACL_LINK))
+ /* No ACL link over BR/EDR controller */
+ if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR)
+ return;
+
+ /* No AMP link over AMP controller */
+ if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
return;
switch (hdev->flow_ctl_mode) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2022b43c7353..705078a0cc39 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -24,12 +24,13 @@
/* Bluetooth HCI event handling. */
-#include <linux/export.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
/* Handle HCI Event packets */
@@ -201,6 +202,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
BIT(HCI_PERIODIC_INQ));
hdev->discovery.state = DISCOVERY_STOPPED;
+ hdev->inq_tx_power = HCI_TX_POWER_INVALID;
+ hdev->adv_tx_power = HCI_TX_POWER_INVALID;
+
+ memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
+ hdev->adv_data_len = 0;
}
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -223,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev);
+ if (!status && !test_bit(HCI_INIT, &hdev->flags))
+ hci_update_ad(hdev);
+
hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
}
@@ -438,7 +447,7 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
- void *sent;
+ struct hci_cp_write_ssp_mode *sent;
BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -446,10 +455,17 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
if (!sent)
return;
+ if (!status) {
+ if (sent->mode)
+ hdev->host_features[0] |= LMP_HOST_SSP;
+ else
+ hdev->host_features[0] &= ~LMP_HOST_SSP;
+ }
+
if (test_bit(HCI_MGMT, &hdev->dev_flags))
- mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
+ mgmt_ssp_enable_complete(hdev, sent->mode, status);
else if (!status) {
- if (*((u8 *) sent))
+ if (sent->mode)
set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
else
clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
@@ -458,10 +474,10 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
{
- if (hdev->features[6] & LMP_EXT_INQ)
+ if (lmp_ext_inq_capable(hdev))
return 2;
- if (hdev->features[3] & LMP_RSSI_INQ)
+ if (lmp_inq_rssi_capable(hdev))
return 1;
if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
@@ -505,28 +521,30 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
return;
- events[4] |= 0x01; /* Flow Specification Complete */
- events[4] |= 0x02; /* Inquiry Result with RSSI */
- events[4] |= 0x04; /* Read Remote Extended Features Complete */
- events[5] |= 0x08; /* Synchronous Connection Complete */
- events[5] |= 0x10; /* Synchronous Connection Changed */
+ if (lmp_bredr_capable(hdev)) {
+ events[4] |= 0x01; /* Flow Specification Complete */
+ events[4] |= 0x02; /* Inquiry Result with RSSI */
+ events[4] |= 0x04; /* Read Remote Extended Features Complete */
+ events[5] |= 0x08; /* Synchronous Connection Complete */
+ events[5] |= 0x10; /* Synchronous Connection Changed */
+ }
- if (hdev->features[3] & LMP_RSSI_INQ)
+ if (lmp_inq_rssi_capable(hdev))
events[4] |= 0x02; /* Inquiry Result with RSSI */
if (lmp_sniffsubr_capable(hdev))
events[5] |= 0x20; /* Sniff Subrating */
- if (hdev->features[5] & LMP_PAUSE_ENC)
+ if (lmp_pause_enc_capable(hdev))
events[5] |= 0x80; /* Encryption Key Refresh Complete */
- if (hdev->features[6] & LMP_EXT_INQ)
+ if (lmp_ext_inq_capable(hdev))
events[5] |= 0x40; /* Extended Inquiry Result */
if (lmp_no_flush_capable(hdev))
events[7] |= 0x01; /* Enhanced Flush Complete */
- if (hdev->features[7] & LMP_LSTO)
+ if (lmp_lsto_capable(hdev))
events[6] |= 0x80; /* Link Supervision Timeout Changed */
if (lmp_ssp_capable(hdev)) {
@@ -546,6 +564,53 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
events[7] |= 0x20; /* LE Meta-Event */
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+
+ if (lmp_le_capable(hdev)) {
+ memset(events, 0, sizeof(events));
+ events[0] = 0x1f;
+ hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
+ sizeof(events), events);
+ }
+}
+
+static void bredr_setup(struct hci_dev *hdev)
+{
+ struct hci_cp_delete_stored_link_key cp;
+ __le16 param;
+ __u8 flt_type;
+
+ /* Read Buffer Size (ACL mtu, max pkt, etc.) */
+ hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
+
+ /* Read Class of Device */
+ hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+ /* Read Local Name */
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
+
+ /* Read Voice Setting */
+ hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
+
+ /* Clear Event Filters */
+ flt_type = HCI_FLT_CLEAR_ALL;
+ hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
+
+ /* Connection accept timeout ~20 secs */
+ param = __constant_cpu_to_le16(0x7d00);
+ hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+ bacpy(&cp.bdaddr, BDADDR_ANY);
+ cp.delete_all = 1;
+ hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+}
+
+static void le_setup(struct hci_dev *hdev)
+{
+ /* Read LE Buffer Size */
+ hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+ /* Read LE Advertising Channel TX Power */
+ hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
}
static void hci_setup(struct hci_dev *hdev)
@@ -553,6 +618,15 @@ static void hci_setup(struct hci_dev *hdev)
if (hdev->dev_type != HCI_BREDR)
return;
+ /* Read BD Address */
+ hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
+
+ if (lmp_bredr_capable(hdev))
+ bredr_setup(hdev);
+
+ if (lmp_le_capable(hdev))
+ le_setup(hdev);
+
hci_setup_event_mask(hdev);
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
@@ -573,13 +647,13 @@ static void hci_setup(struct hci_dev *hdev)
}
}
- if (hdev->features[3] & LMP_RSSI_INQ)
+ if (lmp_inq_rssi_capable(hdev))
hci_setup_inquiry_mode(hdev);
- if (hdev->features[7] & LMP_INQ_TX_PWR)
+ if (lmp_inq_tx_pwr_capable(hdev))
hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
- if (hdev->features[7] & LMP_EXTFEATURES) {
+ if (lmp_ext_feat_capable(hdev)) {
struct hci_cp_read_local_ext_features cp;
cp.page = 0x01;
@@ -626,11 +700,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
if (lmp_rswitch_capable(hdev))
link_policy |= HCI_LP_RSWITCH;
- if (hdev->features[0] & LMP_HOLD)
+ if (lmp_hold_capable(hdev))
link_policy |= HCI_LP_HOLD;
if (lmp_sniff_capable(hdev))
link_policy |= HCI_LP_SNIFF;
- if (hdev->features[1] & LMP_PARK)
+ if (lmp_park_capable(hdev))
link_policy |= HCI_LP_PARK;
cp.policy = cpu_to_le16(link_policy);
@@ -720,10 +794,10 @@ static void hci_set_le_support(struct hci_dev *hdev)
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
cp.le = 1;
- cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+ cp.simul = lmp_le_br_capable(hdev);
}
- if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
+ if (cp.le != lmp_host_le_capable(hdev))
hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
&cp);
}
@@ -846,7 +920,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
- return;
+ goto a2mp_rsp;
hdev->amp_status = rp->amp_status;
hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +934,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+a2mp_rsp:
+ a2mp_send_getinfo_rsp(hdev);
+}
+
+static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
+ struct amp_assoc *assoc = &hdev->loc_assoc;
+ size_t rem_len, frag_len;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
+ goto a2mp_rsp;
+
+ frag_len = skb->len - sizeof(*rp);
+ rem_len = __le16_to_cpu(rp->rem_len);
+
+ if (rem_len > frag_len) {
+ BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
+
+ memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
+ assoc->offset += frag_len;
+
+ /* Read other fragments */
+ amp_read_loc_assoc_frag(hdev, rp->phy_handle);
+
+ return;
+ }
+
+ memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
+ assoc->len = assoc->offset + rem_len;
+ assoc->offset = 0;
+
+a2mp_rsp:
+ /* Send A2MP Rsp when all fragments are received */
+ a2mp_send_getampassoc_rsp(hdev, rp->status);
+ a2mp_send_create_phy_link_req(hdev, rp->status);
}
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
@@ -976,6 +1090,31 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
}
+static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (!rp->status) {
+ hdev->adv_tx_power = rp->tx_power;
+ if (!test_bit(HCI_INIT, &hdev->flags))
+ hci_update_ad(hdev);
+ }
+
+ hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
+}
+
+static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
+}
+
static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1051,6 +1190,33 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
+static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 *sent, status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
+ if (!sent)
+ return;
+
+ hci_dev_lock(hdev);
+
+ if (!status) {
+ if (*sent)
+ set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ else
+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ }
+
+ hci_dev_unlock(hdev);
+
+ if (!test_bit(HCI_INIT, &hdev->flags))
+ hci_update_ad(hdev);
+
+ hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
+}
+
static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1165,6 +1331,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
hdev->host_features[0] |= LMP_HOST_LE;
else
hdev->host_features[0] &= ~LMP_HOST_LE;
+
+ if (sent->simul)
+ hdev->host_features[0] |= LMP_HOST_LE_BREDR;
+ else
+ hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -1174,6 +1345,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
}
+static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
+ hdev->name, rp->status, rp->phy_handle);
+
+ if (rp->status)
+ return;
+
+ amp_write_rem_assoc_continue(hdev, rp->phy_handle);
+}
+
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -1210,7 +1395,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
- BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
+ BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
@@ -1639,8 +1824,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
return;
}
- BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
- conn);
+ BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
conn->state = BT_CLOSED;
mgmt_connect_failed(hdev, &conn->dst, conn->type,
@@ -1657,6 +1841,52 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
BT_DBG("%s status 0x%2.2x", hdev->name, status);
}
+static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
+{
+ struct hci_cp_create_phy_link *cp;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
+ if (!cp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ if (status) {
+ struct hci_conn *hcon;
+
+ hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
+ if (hcon)
+ hci_conn_del(hcon);
+ } else {
+ amp_write_remote_assoc(hdev, cp->phy_handle);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
+static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
+{
+ struct hci_cp_accept_phy_link *cp;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
+ if (!cp)
+ return;
+
+ amp_write_remote_assoc(hdev, cp->phy_handle);
+}
+
+static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+}
+
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1817,15 +2047,53 @@ unlock:
hci_conn_check_pending(hdev);
}
+void hci_conn_accept(struct hci_conn *conn, int mask)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("conn %p", conn);
+
+ conn->state = BT_CONFIG;
+
+ if (!lmp_esco_capable(hdev)) {
+ struct hci_cp_accept_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+ cp.role = 0x00; /* Become master */
+ else
+ cp.role = 0x01; /* Remain slave */
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+ } else /* lmp_esco_capable(hdev)) */ {
+ struct hci_cp_accept_sync_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+ cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.max_latency = __constant_cpu_to_le16(0xffff);
+ cp.content_format = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+ sizeof(cp), &cp);
+ }
+}
+
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = (void *) skb->data;
int mask = hdev->link_mode;
+ __u8 flags = 0;
- BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
+ BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
ev->link_type);
- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
+ mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
+ &flags);
if ((mask & HCI_LM_ACCEPT) &&
!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
@@ -1851,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
memcpy(conn->dev_class, ev->dev_class, 3);
- conn->state = BT_CONNECT;
hci_dev_unlock(hdev);
- if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
+ if (ev->link_type == ACL_LINK ||
+ (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
struct hci_cp_accept_conn_req cp;
+ conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -1867,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
&cp);
- } else {
+ } else if (!(flags & HCI_PROTO_DEFER)) {
struct hci_cp_accept_sync_conn_req cp;
+ conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
@@ -1881,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
sizeof(cp), &cp);
+ } else {
+ conn->state = BT_CONNECT2;
+ hci_proto_connect_cfm(conn, 0);
+ hci_conn_put(conn);
}
} else {
/* Connection rejected */
@@ -2314,6 +2588,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_read_local_amp_info(hdev, skb);
break;
+ case HCI_OP_READ_LOCAL_AMP_ASSOC:
+ hci_cc_read_local_amp_assoc(hdev, skb);
+ break;
+
case HCI_OP_DELETE_STORED_LINK_KEY:
hci_cc_delete_stored_link_key(hdev, skb);
break;
@@ -2350,6 +2628,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_le_read_buffer_size(hdev, skb);
break;
+ case HCI_OP_LE_READ_ADV_TX_POWER:
+ hci_cc_le_read_adv_tx_power(hdev, skb);
+ break;
+
+ case HCI_OP_LE_SET_EVENT_MASK:
+ hci_cc_le_set_event_mask(hdev, skb);
+ break;
+
case HCI_OP_USER_CONFIRM_REPLY:
hci_cc_user_confirm_reply(hdev, skb);
break;
@@ -2370,6 +2656,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_le_set_scan_param(hdev, skb);
break;
+ case HCI_OP_LE_SET_ADV_ENABLE:
+ hci_cc_le_set_adv_enable(hdev, skb);
+ break;
+
case HCI_OP_LE_SET_SCAN_ENABLE:
hci_cc_le_set_scan_enable(hdev, skb);
break;
@@ -2386,6 +2676,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_write_le_host_supported(hdev, skb);
break;
+ case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
+ hci_cc_write_remote_amp_assoc(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
break;
@@ -2467,6 +2761,18 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_le_start_enc(hdev, ev->status);
break;
+ case HCI_OP_CREATE_PHY_LINK:
+ hci_cs_create_phylink(hdev, ev->status);
+ break;
+
+ case HCI_OP_ACCEPT_PHY_LINK:
+ hci_cs_accept_phylink(hdev, ev->status);
+ break;
+
+ case HCI_OP_CREATE_LOGICAL_LINK:
+ hci_cs_create_logical_link(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
break;
@@ -2574,6 +2880,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
queue_work(hdev->workqueue, &hdev->tx_work);
}
+static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
+ __u16 handle)
+{
+ struct hci_chan *chan;
+
+ switch (hdev->dev_type) {
+ case HCI_BREDR:
+ return hci_conn_hash_lookup_handle(hdev, handle);
+ case HCI_AMP:
+ chan = hci_chan_lookup_handle(hdev, handle);
+ if (chan)
+ return chan->conn;
+ break;
+ default:
+ BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
+ break;
+ }
+
+ return NULL;
+}
+
static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
@@ -2595,13 +2922,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
for (i = 0; i < ev->num_hndl; i++) {
struct hci_comp_blocks_info *info = &ev->handles[i];
- struct hci_conn *conn;
+ struct hci_conn *conn = NULL;
__u16 handle, block_count;
handle = __le16_to_cpu(info->handle);
block_count = __le16_to_cpu(info->blocks);
- conn = hci_conn_hash_lookup_handle(hdev, handle);
+ conn = __hci_conn_lookup_handle(hdev, handle);
if (!conn)
continue;
@@ -2609,6 +2936,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
switch (conn->type) {
case ACL_LINK:
+ case AMP_LINK:
hdev->block_cnt += block_count;
if (hdev->block_cnt > hdev->num_blocks)
hdev->block_cnt = hdev->num_blocks;
@@ -2705,13 +3033,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
key = hci_find_link_key(hdev, &ev->bdaddr);
if (!key) {
- BT_DBG("%s link key not found for %s", hdev->name,
- batostr(&ev->bdaddr));
+ BT_DBG("%s link key not found for %pMR", hdev->name,
+ &ev->bdaddr);
goto not_found;
}
- BT_DBG("%s found key type %u for %s", hdev->name, key->type,
- batostr(&ev->bdaddr));
+ BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
+ &ev->bdaddr);
if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
key->type == HCI_LK_DEBUG_COMBINATION) {
@@ -3419,6 +3747,130 @@ unlock:
hci_dev_unlock(hdev);
}
+static void hci_phy_link_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_phy_link_complete *ev = (void *) skb->data;
+ struct hci_conn *hcon, *bredr_hcon;
+
+ BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
+ ev->status);
+
+ hci_dev_lock(hdev);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+ if (!hcon) {
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ if (ev->status) {
+ hci_conn_del(hcon);
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
+
+ hcon->state = BT_CONNECTED;
+ bacpy(&hcon->dst, &bredr_hcon->dst);
+
+ hci_conn_hold(hcon);
+ hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
+ hci_conn_put(hcon);
+
+ hci_conn_hold_device(hcon);
+ hci_conn_add_sysfs(hcon);
+
+ amp_physical_cfm(bredr_hcon, hcon);
+
+ hci_dev_unlock(hdev);
+}
+
+static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_logical_link_complete *ev = (void *) skb->data;
+ struct hci_conn *hcon;
+ struct hci_chan *hchan;
+ struct amp_mgr *mgr;
+
+ BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
+ hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
+ ev->status);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+ if (!hcon)
+ return;
+
+ /* Create AMP hchan */
+ hchan = hci_chan_create(hcon);
+ if (!hchan)
+ return;
+
+ hchan->handle = le16_to_cpu(ev->handle);
+
+ BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
+
+ mgr = hcon->amp_mgr;
+ if (mgr && mgr->bredr_chan) {
+ struct l2cap_chan *bredr_chan = mgr->bredr_chan;
+
+ l2cap_chan_lock(bredr_chan);
+
+ bredr_chan->conn->mtu = hdev->block_mtu;
+ l2cap_logical_cfm(bredr_chan, hchan, 0);
+ hci_conn_hold(hcon);
+
+ l2cap_chan_unlock(bredr_chan);
+ }
+}
+
+static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
+ struct hci_chan *hchan;
+
+ BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
+ le16_to_cpu(ev->handle), ev->status);
+
+ if (ev->status)
+ return;
+
+ hci_dev_lock(hdev);
+
+ hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
+ if (!hchan)
+ goto unlock;
+
+ amp_destroy_logical_link(hchan, ev->reason);
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
+static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
+ struct hci_conn *hcon;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+
+ if (ev->status)
+ return;
+
+ hci_dev_lock(hdev);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+ if (hcon) {
+ hcon->state = BT_CLOSED;
+ hci_conn_del(hcon);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_conn_complete *ev = (void *) skb->data;
@@ -3558,6 +4010,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
}
+static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_channel_selected *ev = (void *) skb->data;
+ struct hci_conn *hcon;
+
+ BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+
+ skb_pull(skb, sizeof(*ev));
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+ if (!hcon)
+ return;
+
+ amp_read_loc_assoc_final_data(hdev, hcon);
+}
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3722,10 +4190,30 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_meta_evt(hdev, skb);
break;
+ case HCI_EV_CHANNEL_SELECTED:
+ hci_chan_selected_evt(hdev, skb);
+ break;
+
case HCI_EV_REMOTE_OOB_DATA_REQUEST:
hci_remote_oob_data_request_evt(hdev, skb);
break;
+ case HCI_EV_PHY_LINK_COMPLETE:
+ hci_phy_link_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_LOGICAL_LINK_COMPLETE:
+ hci_loglink_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
+ hci_disconn_loglink_complete_evt(hdev, skb);
+ break;
+
+ case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
+ hci_disconn_phylink_complete_evt(hdev, skb);
+ break;
+
case HCI_EV_NUM_COMP_BLOCKS:
hci_num_comp_blocks_evt(hdev, skb);
break;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index a20e61c3653d..55cceee02a84 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -38,7 +38,7 @@ static ssize_t show_link_address(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_conn *conn = to_hci_conn(dev);
- return sprintf(buf, "%s\n", batostr(&conn->dst));
+ return sprintf(buf, "%pMR\n", &conn->dst);
}
static ssize_t show_link_features(struct device *dev,
@@ -224,7 +224,7 @@ static ssize_t show_address(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
- return sprintf(buf, "%s\n", batostr(&hdev->bdaddr));
+ return sprintf(buf, "%pMR\n", &hdev->bdaddr);
}
static ssize_t show_features(struct device *dev,
@@ -406,8 +406,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
list_for_each_entry(e, &cache->all, all) {
struct inquiry_data *data = &e->data;
- seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
- batostr(&data->bdaddr),
+ seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
+ &data->bdaddr,
data->pscan_rep_mode, data->pscan_period_mode,
data->pscan_mode, data->dev_class[2],
data->dev_class[1], data->dev_class[0],
@@ -440,7 +440,7 @@ static int blacklist_show(struct seq_file *f, void *p)
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->blacklist, list)
- seq_printf(f, "%s\n", batostr(&b->bdaddr));
+ seq_printf(f, "%pMR\n", &b->bdaddr);
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index ccd985da6518..b2bcbe2dc328 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -932,8 +932,12 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->country = req->country;
strncpy(hid->name, req->name, 128);
- strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
- strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
+
+ snprintf(hid->phys, sizeof(hid->phys), "%pMR",
+ &bt_sk(session->ctrl_sock->sk)->src);
+
+ snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
+ &bt_sk(session->ctrl_sock->sk)->dst);
hid->dev.parent = &session->conn->dev;
hid->ll_driver = &hidp_hid_driver;
@@ -941,6 +945,13 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->hid_get_raw_report = hidp_get_raw_report;
hid->hid_output_raw_report = hidp_output_raw_report;
+ /* True if device is blacklisted in drivers/hid/hid-core.c */
+ if (hid_ignore(hid)) {
+ hid_destroy_device(session->hid);
+ session->hid = NULL;
+ return -ENODEV;
+ }
+
return 0;
fault:
@@ -1013,7 +1024,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (req->rd_size > 0) {
err = hidp_setup_hid(session, req);
- if (err)
+ if (err && err != -ENODEV)
goto purge;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a91239dcda41..2c78208d793e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -38,6 +38,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/smp.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
bool disable_ertm;
@@ -48,19 +49,19 @@ static LIST_HEAD(chan_list);
static DEFINE_RWLOCK(chan_list_lock);
static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
- u8 code, u8 ident, u16 dlen, void *data);
+ u8 code, u8 ident, u16 dlen, void *data);
static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
- void *data);
+ void *data);
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
-static void l2cap_send_disconn_req(struct l2cap_conn *conn,
- struct l2cap_chan *chan, int err);
+static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
- struct sk_buff_head *skbs, u8 event);
+ struct sk_buff_head *skbs, u8 event);
/* ---- L2CAP channels ---- */
-static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
+ u16 cid)
{
struct l2cap_chan *c;
@@ -71,7 +72,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
return NULL;
}
-static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
+ u16 cid)
{
struct l2cap_chan *c;
@@ -84,7 +86,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16
/* Find channel with given SCID.
* Returns locked channel. */
-static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
+static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
+ u16 cid)
{
struct l2cap_chan *c;
@@ -97,7 +100,25 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci
return c;
}
-static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
+/* Find channel with given DCID.
+ * Returns locked channel.
+ */
+static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
+ u16 cid)
+{
+ struct l2cap_chan *c;
+
+ mutex_lock(&conn->chan_lock);
+ c = __l2cap_get_chan_by_dcid(conn, cid);
+ if (c)
+ l2cap_chan_lock(c);
+ mutex_unlock(&conn->chan_lock);
+
+ return c;
+}
+
+static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+ u8 ident)
{
struct l2cap_chan *c;
@@ -108,6 +129,20 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8
return NULL;
}
+static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+ u8 ident)
+{
+ struct l2cap_chan *c;
+
+ mutex_lock(&conn->chan_lock);
+ c = __l2cap_get_chan_by_ident(conn, ident);
+ if (c)
+ l2cap_chan_lock(c);
+ mutex_unlock(&conn->chan_lock);
+
+ return c;
+}
+
static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
{
struct l2cap_chan *c;
@@ -178,7 +213,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
static void __l2cap_state_change(struct l2cap_chan *chan, int state)
{
BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
- state_to_string(state));
+ state_to_string(state));
chan->state = state;
chan->ops->state_change(chan, state);
@@ -361,7 +396,7 @@ static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
static void l2cap_chan_timeout(struct work_struct *work)
{
struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
- chan_timer.work);
+ chan_timer.work);
struct l2cap_conn *conn = chan->conn;
int reason;
@@ -373,7 +408,7 @@ static void l2cap_chan_timeout(struct work_struct *work)
if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
reason = ECONNREFUSED;
else if (chan->state == BT_CONNECT &&
- chan->sec_level != BT_SECURITY_SDP)
+ chan->sec_level != BT_SECURITY_SDP)
reason = ECONNREFUSED;
else
reason = ETIMEDOUT;
@@ -455,7 +490,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
}
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+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,
__le16_to_cpu(chan->psm), chan->dcid);
@@ -504,7 +539,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
- chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO;
l2cap_chan_hold(chan);
@@ -527,6 +562,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
if (conn) {
+ struct amp_mgr *mgr = conn->hcon->amp_mgr;
/* Delete from channel list */
list_del(&chan->list);
@@ -536,10 +572,19 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
hci_conn_put(conn->hcon);
+
+ if (mgr && mgr->bredr_chan == chan)
+ mgr->bredr_chan = NULL;
}
- if (chan->ops->teardown)
- chan->ops->teardown(chan, err);
+ if (chan->hs_hchan) {
+ struct hci_chan *hs_hchan = chan->hs_hchan;
+
+ BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
+ amp_disconnect_logical_link(hs_hchan);
+ }
+
+ chan->ops->teardown(chan, err);
if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
return;
@@ -573,28 +618,27 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
struct l2cap_conn *conn = chan->conn;
struct sock *sk = chan->sk;
- BT_DBG("chan %p state %s sk %p", chan,
- state_to_string(chan->state), sk);
+ BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state),
+ sk);
switch (chan->state) {
case BT_LISTEN:
- if (chan->ops->teardown)
- chan->ops->teardown(chan, 0);
+ chan->ops->teardown(chan, 0);
break;
case BT_CONNECTED:
case BT_CONFIG:
if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
- conn->hcon->type == ACL_LINK) {
+ conn->hcon->type == ACL_LINK) {
__set_chan_timer(chan, sk->sk_sndtimeo);
- l2cap_send_disconn_req(conn, chan, reason);
+ l2cap_send_disconn_req(chan, reason);
} else
l2cap_chan_del(chan, reason);
break;
case BT_CONNECT2:
if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
- conn->hcon->type == ACL_LINK) {
+ conn->hcon->type == ACL_LINK) {
struct l2cap_conn_rsp rsp;
__u16 result;
@@ -609,7 +653,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
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);
+ sizeof(rsp), &rsp);
}
l2cap_chan_del(chan, reason);
@@ -621,8 +665,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
break;
default:
- if (chan->ops->teardown)
- chan->ops->teardown(chan, 0);
+ chan->ops->teardown(chan, 0);
break;
}
}
@@ -691,7 +734,8 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
return id;
}
-static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+ void *data)
{
struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
u8 flags;
@@ -712,16 +756,31 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
hci_send_acl(conn->hchan, skb, flags);
}
+static bool __chan_is_moving(struct l2cap_chan *chan)
+{
+ return chan->move_state != L2CAP_MOVE_STABLE &&
+ chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
+}
+
static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
{
struct hci_conn *hcon = chan->conn->hcon;
u16 flags;
BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
- skb->priority);
+ skb->priority);
+
+ if (chan->hs_hcon && !__chan_is_moving(chan)) {
+ if (chan->hs_hchan)
+ hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
+ else
+ kfree_skb(skb);
+
+ return;
+ }
if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
- lmp_no_flush_capable(hcon->hdev))
+ lmp_no_flush_capable(hcon->hdev))
flags = ACL_START_NO_FLUSH;
else
flags = ACL_START;
@@ -895,6 +954,9 @@ static void l2cap_send_sframe(struct l2cap_chan *chan,
if (!control->sframe)
return;
+ if (__chan_is_moving(chan))
+ return;
+
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
!control->poll)
control->final = 1;
@@ -946,7 +1008,26 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
}
-static void l2cap_send_conn_req(struct l2cap_chan *chan)
+static bool __amp_capable(struct l2cap_chan *chan)
+{
+ struct l2cap_conn *conn = chan->conn;
+
+ if (enable_hs &&
+ hci_amp_capable() &&
+ chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
+ conn->fixed_chan_mask & L2CAP_FC_A2MP)
+ return true;
+ else
+ return false;
+}
+
+static bool l2cap_check_efs(struct l2cap_chan *chan)
+{
+ /* Check EFS parameters */
+ return true;
+}
+
+void l2cap_send_conn_req(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
struct l2cap_conn_req req;
@@ -961,6 +1042,76 @@ static void l2cap_send_conn_req(struct l2cap_chan *chan)
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
}
+static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
+{
+ struct l2cap_create_chan_req req;
+ req.scid = cpu_to_le16(chan->scid);
+ req.psm = chan->psm;
+ req.amp_id = amp_id;
+
+ chan->ident = l2cap_get_ident(chan->conn);
+
+ l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
+ sizeof(req), &req);
+}
+
+static void l2cap_move_setup(struct l2cap_chan *chan)
+{
+ struct sk_buff *skb;
+
+ BT_DBG("chan %p", chan);
+
+ if (chan->mode != L2CAP_MODE_ERTM)
+ return;
+
+ __clear_retrans_timer(chan);
+ __clear_monitor_timer(chan);
+ __clear_ack_timer(chan);
+
+ chan->retry_count = 0;
+ skb_queue_walk(&chan->tx_q, skb) {
+ if (bt_cb(skb)->control.retries)
+ bt_cb(skb)->control.retries = 1;
+ else
+ break;
+ }
+
+ chan->expected_tx_seq = chan->buffer_seq;
+
+ clear_bit(CONN_REJ_ACT, &chan->conn_state);
+ clear_bit(CONN_SREJ_ACT, &chan->conn_state);
+ l2cap_seq_list_clear(&chan->retrans_list);
+ l2cap_seq_list_clear(&chan->srej_list);
+ skb_queue_purge(&chan->srej_q);
+
+ chan->tx_state = L2CAP_TX_STATE_XMIT;
+ chan->rx_state = L2CAP_RX_STATE_MOVE;
+
+ set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+}
+
+static void l2cap_move_done(struct l2cap_chan *chan)
+{
+ u8 move_role = chan->move_role;
+ BT_DBG("chan %p", chan);
+
+ chan->move_state = L2CAP_MOVE_STABLE;
+ chan->move_role = L2CAP_MOVE_ROLE_NONE;
+
+ if (chan->mode != L2CAP_MODE_ERTM)
+ return;
+
+ switch (move_role) {
+ case L2CAP_MOVE_ROLE_INITIATOR:
+ l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
+ chan->rx_state = L2CAP_RX_STATE_WAIT_F;
+ break;
+ case L2CAP_MOVE_ROLE_RESPONDER:
+ chan->rx_state = L2CAP_RX_STATE_WAIT_P;
+ break;
+ }
+}
+
static void l2cap_chan_ready(struct l2cap_chan *chan)
{
/* This clears all conf flags, including CONF_NOT_COMPLETE */
@@ -972,6 +1123,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
chan->ops->ready(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 {
+ l2cap_send_conn_req(chan);
+ }
+}
+
static void l2cap_do_start(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
@@ -986,8 +1147,9 @@ static void l2cap_do_start(struct l2cap_chan *chan)
return;
if (l2cap_chan_check_security(chan) &&
- __l2cap_no_conn_pending(chan))
- l2cap_send_conn_req(chan);
+ __l2cap_no_conn_pending(chan)) {
+ l2cap_start_connection(chan);
+ }
} else {
struct l2cap_info_req req;
req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -997,8 +1159,8 @@ static void l2cap_do_start(struct l2cap_chan *chan)
schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
- l2cap_send_cmd(conn, conn->info_ident,
- L2CAP_INFO_REQ, sizeof(req), &req);
+ l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
+ sizeof(req), &req);
}
}
@@ -1018,9 +1180,10 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
}
}
-static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
+static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
{
struct sock *sk = chan->sk;
+ struct l2cap_conn *conn = chan->conn;
struct l2cap_disconn_req req;
if (!conn)
@@ -1033,14 +1196,14 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
}
if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
- __l2cap_state_change(chan, BT_DISCONN);
+ l2cap_state_change(chan, BT_DISCONN);
return;
}
req.dcid = cpu_to_le16(chan->dcid);
req.scid = cpu_to_le16(chan->scid);
- l2cap_send_cmd(conn, l2cap_get_ident(conn),
- L2CAP_DISCONN_REQ, sizeof(req), &req);
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
+ sizeof(req), &req);
lock_sock(sk);
__l2cap_state_change(chan, BT_DISCONN);
@@ -1069,20 +1232,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if (chan->state == BT_CONNECT) {
if (!l2cap_chan_check_security(chan) ||
- !__l2cap_no_conn_pending(chan)) {
+ !__l2cap_no_conn_pending(chan)) {
l2cap_chan_unlock(chan);
continue;
}
if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
- && test_bit(CONF_STATE2_DEVICE,
+ && test_bit(CONF_STATE2_DEVICE,
&chan->conf_state)) {
l2cap_chan_close(chan, ECONNRESET);
l2cap_chan_unlock(chan);
continue;
}
- l2cap_send_conn_req(chan);
+ l2cap_start_connection(chan);
} else if (chan->state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
@@ -1094,11 +1257,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
lock_sock(sk);
if (test_bit(BT_SK_DEFER_SETUP,
&bt_sk(sk)->flags)) {
- struct sock *parent = bt_sk(sk)->parent;
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
- if (parent)
- parent->sk_data_ready(parent, 0);
+ chan->ops->defer(chan);
} else {
__l2cap_state_change(chan, BT_CONFIG);
@@ -1112,17 +1273,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
- sizeof(rsp), &rsp);
+ sizeof(rsp), &rsp);
if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
- rsp.result != L2CAP_CR_SUCCESS) {
+ rsp.result != L2CAP_CR_SUCCESS) {
l2cap_chan_unlock(chan);
continue;
}
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
}
@@ -1204,8 +1365,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
- bt_accept_enqueue(parent, sk);
-
l2cap_chan_add(conn, chan);
l2cap_chan_ready(chan);
@@ -1270,7 +1429,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
list_for_each_entry(chan, &conn->chan_l, list) {
if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
- __l2cap_chan_set_err(chan, err);
+ l2cap_chan_set_err(chan, err);
}
mutex_unlock(&conn->chan_lock);
@@ -1279,7 +1438,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
static void l2cap_info_timeout(struct work_struct *work)
{
struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
- info_timer.work);
+ info_timer.work);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
conn->info_ident = 0;
@@ -1333,7 +1492,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
static void security_timeout(struct work_struct *work)
{
struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
- security_timer.work);
+ security_timer.work);
BT_DBG("conn %p", conn);
@@ -1355,7 +1514,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
if (!hchan)
return NULL;
- conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
+ conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
if (!conn) {
hci_chan_del(hchan);
return NULL;
@@ -1367,10 +1526,22 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
- if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
- conn->mtu = hcon->hdev->le_mtu;
- else
+ switch (hcon->type) {
+ case AMP_LINK:
+ conn->mtu = hcon->hdev->block_mtu;
+ break;
+
+ case LE_LINK:
+ if (hcon->hdev->le_mtu) {
+ conn->mtu = hcon->hdev->le_mtu;
+ break;
+ }
+ /* fall through */
+
+ default:
conn->mtu = hcon->hdev->acl_mtu;
+ break;
+ }
conn->src = &hcon->hdev->bdaddr;
conn->dst = &hcon->dst;
@@ -1448,7 +1619,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
__u8 auth_type;
int err;
- BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
+ BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst,
dst_type, __le16_to_cpu(psm));
hdev = hci_get_route(dst, src);
@@ -1461,7 +1632,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
/* PSM must be odd and lsb of upper byte must be 0 */
if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
- chan->chan_type != L2CAP_CHAN_RAW) {
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
goto done;
}
@@ -1657,6 +1828,9 @@ static void l2cap_streaming_send(struct l2cap_chan *chan,
BT_DBG("chan %p, skbs %p", chan, skbs);
+ if (__chan_is_moving(chan))
+ return;
+
skb_queue_splice_tail_init(skbs, &chan->tx_q);
while (!skb_queue_empty(&chan->tx_q)) {
@@ -1699,6 +1873,9 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
return 0;
+ if (__chan_is_moving(chan))
+ return 0;
+
while (chan->tx_send_head &&
chan->unacked_frames < chan->remote_tx_win &&
chan->tx_state == L2CAP_TX_STATE_XMIT) {
@@ -1764,13 +1941,16 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
return;
+ if (__chan_is_moving(chan))
+ return;
+
while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
seq = l2cap_seq_list_pop(&chan->retrans_list);
skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
if (!skb) {
BT_DBG("Error: Can't retransmit seq %d, frame missing",
- seq);
+ seq);
continue;
}
@@ -1780,7 +1960,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
if (chan->max_tx != 0 &&
bt_cb(skb)->control.retries > chan->max_tx) {
BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
l2cap_seq_list_clear(&chan->retrans_list);
break;
}
@@ -1795,9 +1975,9 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
/* Cloned sk_buffs are read-only, so we need a
* writeable copy
*/
- tx_skb = skb_copy(skb, GFP_ATOMIC);
+ tx_skb = skb_copy(skb, GFP_KERNEL);
} else {
- tx_skb = skb_clone(skb, GFP_ATOMIC);
+ tx_skb = skb_clone(skb, GFP_KERNEL);
}
if (!tx_skb) {
@@ -1855,7 +2035,7 @@ static void l2cap_retransmit_all(struct l2cap_chan *chan,
if (chan->unacked_frames) {
skb_queue_walk(&chan->tx_q, skb) {
if (bt_cb(skb)->control.txseq == control->reqseq ||
- skb == chan->tx_send_head)
+ skb == chan->tx_send_head)
break;
}
@@ -2106,7 +2286,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
/* PDU size is derived from the HCI MTU */
pdu_len = chan->conn->mtu;
- pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
+ /* Constrain PDU size for BR/EDR connections */
+ if (!chan->hs_hcon)
+ pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
/* Adjust for largest possible L2CAP overhead. */
if (chan->fcs)
@@ -2156,7 +2338,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
}
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
- u32 priority)
+ u32 priority)
{
struct sk_buff *skb;
int err;
@@ -2484,7 +2666,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
__set_monitor_timer(chan);
chan->retry_count++;
} else {
- l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
+ l2cap_send_disconn_req(chan, ECONNABORTED);
}
break;
default:
@@ -2543,7 +2725,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
/* Don't send frame to the socket it came from */
if (skb->sk == sk)
continue;
- nskb = skb_clone(skb, GFP_ATOMIC);
+ nskb = skb_clone(skb, GFP_KERNEL);
if (!nskb)
continue;
@@ -2569,7 +2751,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
count = min_t(unsigned int, conn->mtu, len);
- skb = bt_skb_alloc(count, GFP_ATOMIC);
+ skb = bt_skb_alloc(count, GFP_KERNEL);
if (!skb)
return NULL;
@@ -2599,7 +2781,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
while (len) {
count = min_t(unsigned int, conn->mtu, len);
- *frag = bt_skb_alloc(count, GFP_ATOMIC);
+ *frag = bt_skb_alloc(count, GFP_KERNEL);
if (!*frag)
goto fail;
@@ -2618,7 +2800,8 @@ fail:
return NULL;
}
-static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
+static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
+ unsigned long *val)
{
struct l2cap_conf_opt *opt = *ptr;
int len;
@@ -2692,7 +2875,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
efs.msdu = cpu_to_le16(chan->local_msdu);
efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
- efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
+ efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
break;
case L2CAP_MODE_STREAMING:
@@ -2709,7 +2892,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
}
l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs);
}
static void l2cap_ack_timeout(struct work_struct *work)
@@ -2749,6 +2932,11 @@ int l2cap_ertm_init(struct l2cap_chan *chan)
skb_queue_head_init(&chan->tx_q);
+ chan->local_amp_id = 0;
+ chan->move_id = 0;
+ chan->move_state = L2CAP_MOVE_STABLE;
+ chan->move_role = L2CAP_MOVE_ROLE_NONE;
+
if (chan->mode != L2CAP_MODE_ERTM)
return 0;
@@ -2795,16 +2983,54 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
}
+static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
+ struct l2cap_conf_rfc *rfc)
+{
+ if (chan->local_amp_id && chan->hs_hcon) {
+ u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
+
+ /* Class 1 devices have must have ERTM timeouts
+ * exceeding the Link Supervision Timeout. The
+ * default Link Supervision Timeout for AMP
+ * controllers is 10 seconds.
+ *
+ * Class 1 devices use 0xffffffff for their
+ * best-effort flush timeout, so the clamping logic
+ * will result in a timeout that meets the above
+ * requirement. ERTM timeouts are 16-bit values, so
+ * the maximum timeout is 65.535 seconds.
+ */
+
+ /* Convert timeout to milliseconds and round */
+ ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
+
+ /* This is the recommended formula for class 2 devices
+ * that start ERTM timers when packets are sent to the
+ * controller.
+ */
+ ertm_to = 3 * ertm_to + 500;
+
+ if (ertm_to > 0xffff)
+ ertm_to = 0xffff;
+
+ rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
+ rfc->monitor_timeout = rfc->retrans_timeout;
+ } else {
+ rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ }
+}
+
static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
{
if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
- __l2cap_ews_supported(chan)) {
+ __l2cap_ews_supported(chan)) {
/* use extended control field */
set_bit(FLAG_EXT_CTRL, &chan->flags);
chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
} else {
chan->tx_win = min_t(u16, chan->tx_win,
- L2CAP_DEFAULT_TX_WINDOW);
+ L2CAP_DEFAULT_TX_WINDOW);
chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
}
chan->ack_win = chan->tx_win;
@@ -2844,7 +3070,7 @@ done:
switch (chan->mode) {
case L2CAP_MODE_BASIC:
if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
- !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
+ !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
break;
rfc.mode = L2CAP_MODE_BASIC;
@@ -2855,44 +3081,42 @@ done:
rfc.max_pdu_size = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc);
break;
case L2CAP_MODE_ERTM:
rfc.mode = L2CAP_MODE_ERTM;
rfc.max_transmit = chan->max_tx;
- rfc.retrans_timeout = 0;
- rfc.monitor_timeout = 0;
+
+ __l2cap_set_ertm_timeouts(chan, &rfc);
size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
- L2CAP_EXT_HDR_SIZE -
- L2CAP_SDULEN_SIZE -
- L2CAP_FCS_SIZE);
+ L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
+ L2CAP_FCS_SIZE);
rfc.max_pdu_size = cpu_to_le16(size);
l2cap_txwin_setup(chan);
rfc.txwin_size = min_t(u16, chan->tx_win,
- L2CAP_DEFAULT_TX_WINDOW);
+ L2CAP_DEFAULT_TX_WINDOW);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
l2cap_add_opt_efs(&ptr, chan);
- if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
- break;
-
- if (chan->fcs == L2CAP_FCS_NONE ||
- test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
- chan->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
- }
-
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
- chan->tx_win);
+ chan->tx_win);
+
+ if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
+ if (chan->fcs == L2CAP_FCS_NONE ||
+ test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
+ chan->fcs = L2CAP_FCS_NONE;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
+ chan->fcs);
+ }
break;
case L2CAP_MODE_STREAMING:
@@ -2904,25 +3128,23 @@ done:
rfc.monitor_timeout = 0;
size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
- L2CAP_EXT_HDR_SIZE -
- L2CAP_SDULEN_SIZE -
- L2CAP_FCS_SIZE);
+ L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
+ L2CAP_FCS_SIZE);
rfc.max_pdu_size = cpu_to_le16(size);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
l2cap_add_opt_efs(&ptr, chan);
- if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
- break;
-
- if (chan->fcs == L2CAP_FCS_NONE ||
- test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
- chan->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
- }
+ if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
+ if (chan->fcs == L2CAP_FCS_NONE ||
+ test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
+ chan->fcs = L2CAP_FCS_NONE;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
+ chan->fcs);
+ }
break;
}
@@ -2974,7 +3196,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
case L2CAP_CONF_FCS:
if (val == L2CAP_FCS_NONE)
- set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
+ set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
break;
case L2CAP_CONF_EFS:
@@ -3011,7 +3233,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
case L2CAP_MODE_ERTM:
if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
chan->mode = l2cap_select_mode(rfc.mode,
- chan->conn->feat_mask);
+ chan->conn->feat_mask);
break;
}
@@ -3036,8 +3258,8 @@ done:
if (chan->num_conf_rsp == 1)
return -ECONNREFUSED;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+ (unsigned long) &rfc);
}
if (result == L2CAP_CONF_SUCCESS) {
@@ -3054,8 +3276,8 @@ done:
if (remote_efs) {
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
- efs.stype != L2CAP_SERV_NOTRAFIC &&
- efs.stype != chan->local_stype) {
+ efs.stype != L2CAP_SERV_NOTRAFIC &&
+ efs.stype != chan->local_stype) {
result = L2CAP_CONF_UNACCEPT;
@@ -3063,8 +3285,8 @@ done:
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
- sizeof(efs),
- (unsigned long) &efs);
+ sizeof(efs),
+ (unsigned long) &efs);
} else {
/* Send PENDING Conf Rsp */
result = L2CAP_CONF_PENDING;
@@ -3087,51 +3309,45 @@ done:
chan->remote_max_tx = rfc.max_transmit;
size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
- chan->conn->mtu -
- L2CAP_EXT_HDR_SIZE -
- L2CAP_SDULEN_SIZE -
- L2CAP_FCS_SIZE);
+ chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
+ L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
rfc.max_pdu_size = cpu_to_le16(size);
chan->remote_mps = size;
- rfc.retrans_timeout =
- __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout =
- __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ __l2cap_set_ertm_timeouts(chan, &rfc);
set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
chan->remote_id = efs.id;
chan->remote_stype = efs.stype;
chan->remote_msdu = le16_to_cpu(efs.msdu);
chan->remote_flush_to =
- le32_to_cpu(efs.flush_to);
+ le32_to_cpu(efs.flush_to);
chan->remote_acc_lat =
- le32_to_cpu(efs.acc_lat);
+ le32_to_cpu(efs.acc_lat);
chan->remote_sdu_itime =
le32_to_cpu(efs.sdu_itime);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
- sizeof(efs), (unsigned long) &efs);
+ sizeof(efs),
+ (unsigned long) &efs);
}
break;
case L2CAP_MODE_STREAMING:
size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
- chan->conn->mtu -
- L2CAP_EXT_HDR_SIZE -
- L2CAP_SDULEN_SIZE -
- L2CAP_FCS_SIZE);
+ chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
+ L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
rfc.max_pdu_size = cpu_to_le16(size);
chan->remote_mps = size;
set_bit(CONF_MODE_DONE, &chan->conf_state);
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+ (unsigned long) &rfc);
break;
@@ -3152,7 +3368,8 @@ done:
return ptr - data;
}
-static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
+static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
+ void *data, u16 *result)
{
struct l2cap_conf_req *req = data;
void *ptr = req->data;
@@ -3179,7 +3396,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
case L2CAP_CONF_FLUSH_TO:
chan->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, chan->flush_to);
+ 2, chan->flush_to);
break;
case L2CAP_CONF_RFC:
@@ -3187,13 +3404,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
memcpy(&rfc, (void *)val, olen);
if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
- rfc.mode != chan->mode)
+ rfc.mode != chan->mode)
return -ECONNREFUSED;
chan->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc);
break;
case L2CAP_CONF_EWS:
@@ -3207,12 +3424,19 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
memcpy(&efs, (void *)val, olen);
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
- efs.stype != L2CAP_SERV_NOTRAFIC &&
- efs.stype != chan->local_stype)
+ efs.stype != L2CAP_SERV_NOTRAFIC &&
+ efs.stype != chan->local_stype)
return -ECONNREFUSED;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
- sizeof(efs), (unsigned long) &efs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
+ (unsigned long) &efs);
+ break;
+
+ case L2CAP_CONF_FCS:
+ if (*result == L2CAP_CONF_PENDING)
+ if (val == L2CAP_FCS_NONE)
+ set_bit(CONF_RECV_NO_FCS,
+ &chan->conf_state);
break;
}
}
@@ -3235,10 +3459,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
chan->local_msdu = le16_to_cpu(efs.msdu);
chan->local_sdu_itime =
- le32_to_cpu(efs.sdu_itime);
+ le32_to_cpu(efs.sdu_itime);
chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
chan->local_flush_to =
- le32_to_cpu(efs.flush_to);
+ le32_to_cpu(efs.flush_to);
}
break;
@@ -3253,7 +3477,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
return ptr - data;
}
-static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
+static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
+ u16 result, u16 flags)
{
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
@@ -3272,19 +3497,27 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
struct l2cap_conn_rsp rsp;
struct l2cap_conn *conn = chan->conn;
u8 buf[128];
+ u8 rsp_code;
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
- l2cap_send_cmd(conn, chan->ident,
- L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+ if (chan->hs_hcon)
+ rsp_code = L2CAP_CREATE_CHAN_RSP;
+ else
+ rsp_code = L2CAP_CONN_RSP;
+
+ BT_DBG("chan %p rsp_code %u", chan, rsp_code);
+
+ l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
return;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
}
@@ -3339,7 +3572,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
}
}
-static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_command_rej(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
@@ -3347,7 +3581,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
return 0;
if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
- cmd->ident == conn->info_ident) {
+ cmd->ident == conn->info_ident) {
cancel_delayed_work(&conn->info_timer);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
@@ -3359,7 +3593,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
return 0;
}
-static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd,
+ u8 *data, u8 rsp_code, u8 amp_id)
{
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
struct l2cap_conn_rsp rsp;
@@ -3386,7 +3622,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
/* Check if the ACL is secure enough (if not SDP) */
if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
- !hci_conn_check_link_mode(conn->hcon)) {
+ !hci_conn_check_link_mode(conn->hcon)) {
conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
result = L2CAP_CR_SEC_BLOCK;
goto response;
@@ -3410,8 +3646,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
bacpy(&bt_sk(sk)->dst, conn->dst);
chan->psm = psm;
chan->dcid = scid;
-
- bt_accept_enqueue(parent, sk);
+ chan->local_amp_id = amp_id;
__l2cap_chan_add(conn, chan);
@@ -3427,10 +3662,19 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
__l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHOR_PEND;
- parent->sk_data_ready(parent, 0);
+ chan->ops->defer(chan);
} else {
- __l2cap_state_change(chan, BT_CONFIG);
- result = L2CAP_CR_SUCCESS;
+ /* Force pending result for AMP controllers.
+ * The connection will succeed after the
+ * physical link is up.
+ */
+ if (amp_id) {
+ __l2cap_state_change(chan, BT_CONNECT2);
+ result = L2CAP_CR_PEND;
+ } else {
+ __l2cap_state_change(chan, BT_CONFIG);
+ result = L2CAP_CR_SUCCESS;
+ }
status = L2CAP_CS_NO_INFO;
}
} else {
@@ -3453,7 +3697,7 @@ sendresp:
rsp.dcid = cpu_to_le16(dcid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(status);
- l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+ l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
struct l2cap_info_req info;
@@ -3464,23 +3708,31 @@ sendresp:
schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
- l2cap_send_cmd(conn, conn->info_ident,
- L2CAP_INFO_REQ, sizeof(info), &info);
+ l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
+ sizeof(info), &info);
}
if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
- result == L2CAP_CR_SUCCESS) {
+ result == L2CAP_CR_SUCCESS) {
u8 buf[128];
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
}
+ return chan;
+}
+
+static int l2cap_connect_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+ l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
return 0;
}
-static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
u16 scid, dcid, result, status;
@@ -3494,7 +3746,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
status = __le16_to_cpu(rsp->status);
BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
- dcid, scid, result, status);
+ dcid, scid, result, status);
mutex_lock(&conn->chan_lock);
@@ -3527,7 +3779,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
break;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, req), req);
+ l2cap_build_conf_req(chan, req), req);
chan->num_conf_req++;
break;
@@ -3555,11 +3807,29 @@ static inline void set_default_fcs(struct l2cap_chan *chan)
*/
if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
chan->fcs = L2CAP_FCS_NONE;
- else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
+ else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
chan->fcs = L2CAP_FCS_CRC16;
}
-static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
+ u8 ident, u16 flags)
+{
+ struct l2cap_conn *conn = chan->conn;
+
+ BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
+ flags);
+
+ clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
+ set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
+
+ l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
+ l2cap_build_conf_rsp(chan, data,
+ L2CAP_CONF_SUCCESS, flags), data);
+}
+
+static inline int l2cap_config_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
u16 dcid, flags;
@@ -3584,7 +3854,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
rej.dcid = cpu_to_le16(chan->dcid);
l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
- sizeof(rej), &rej);
+ sizeof(rej), &rej);
goto unlock;
}
@@ -3592,8 +3862,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
len = cmd_len - sizeof(*req);
if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(chan, rsp,
- L2CAP_CONF_REJECT, flags), rsp);
+ l2cap_build_conf_rsp(chan, rsp,
+ L2CAP_CONF_REJECT, flags), rsp);
goto unlock;
}
@@ -3604,18 +3874,19 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
/* Incomplete config. Send empty response. */
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(chan, rsp,
- L2CAP_CONF_SUCCESS, flags), rsp);
+ l2cap_build_conf_rsp(chan, rsp,
+ L2CAP_CONF_SUCCESS, flags), rsp);
goto unlock;
}
/* Complete config. */
len = l2cap_parse_conf_req(chan, rsp);
if (len < 0) {
- l2cap_send_disconn_req(conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto unlock;
}
+ chan->ident = cmd->ident;
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
chan->num_conf_rsp++;
@@ -3633,7 +3904,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
err = l2cap_ertm_init(chan);
if (err < 0)
- l2cap_send_disconn_req(chan->conn, chan, -err);
+ l2cap_send_disconn_req(chan, -err);
else
l2cap_chan_ready(chan);
@@ -3643,23 +3914,22 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
u8 buf[64];
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
}
/* Got Conf Rsp PENDING from remote side and asume we sent
Conf Rsp PENDING in the code above */
if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
- test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
+ test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
/* check compatibility */
- clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
- set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
-
- l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(chan, rsp,
- L2CAP_CONF_SUCCESS, flags), rsp);
+ /* Send rsp for BR/EDR channel */
+ if (!chan->hs_hcon)
+ l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
+ else
+ chan->ident = cmd->ident;
}
unlock:
@@ -3667,7 +3937,8 @@ unlock:
return err;
}
-static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_config_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
u16 scid, flags, result;
@@ -3699,20 +3970,21 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
char buf[64];
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- buf, &result);
+ buf, &result);
if (len < 0) {
- l2cap_send_disconn_req(conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
}
- /* check compatibility */
-
- clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
- set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
-
- l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(chan, buf,
- L2CAP_CONF_SUCCESS, 0x0000), buf);
+ if (!chan->hs_hcon) {
+ l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
+ 0);
+ } else {
+ if (l2cap_check_efs(chan)) {
+ amp_create_logical_link(chan);
+ chan->ident = cmd->ident;
+ }
+ }
}
goto done;
@@ -3721,21 +3993,21 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
char req[64];
if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
- l2cap_send_disconn_req(conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
}
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- req, &result);
+ req, &result);
if (len < 0) {
- l2cap_send_disconn_req(conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
}
l2cap_send_cmd(conn, l2cap_get_ident(conn),
- L2CAP_CONF_REQ, len, req);
+ L2CAP_CONF_REQ, len, req);
chan->num_conf_req++;
if (result != L2CAP_CONF_SUCCESS)
goto done;
@@ -3746,7 +4018,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
l2cap_chan_set_err(chan, ECONNRESET);
__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
- l2cap_send_disconn_req(conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
}
@@ -3763,7 +4035,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
err = l2cap_ertm_init(chan);
if (err < 0)
- l2cap_send_disconn_req(chan->conn, chan, -err);
+ l2cap_send_disconn_req(chan, -err);
else
l2cap_chan_ready(chan);
}
@@ -3773,7 +4045,8 @@ done:
return err;
}
-static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
struct l2cap_disconn_rsp rsp;
@@ -3819,7 +4092,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
return 0;
}
-static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
u16 dcid, scid;
@@ -3853,7 +4127,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
return 0;
}
-static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_info_req *req = (struct l2cap_info_req *) data;
u16 type;
@@ -3870,14 +4145,14 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
if (!disable_ertm)
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
- | L2CAP_FEAT_FCS;
+ | L2CAP_FEAT_FCS;
if (enable_hs)
feat_mask |= L2CAP_FEAT_EXT_FLOW
- | L2CAP_FEAT_EXT_WINDOW;
+ | L2CAP_FEAT_EXT_WINDOW;
put_unaligned_le32(feat_mask, rsp->data);
- l2cap_send_cmd(conn, cmd->ident,
- L2CAP_INFO_RSP, sizeof(buf), buf);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
+ buf);
} else if (type == L2CAP_IT_FIXED_CHAN) {
u8 buf[12];
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
@@ -3890,20 +4165,21 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
- l2cap_send_cmd(conn, cmd->ident,
- L2CAP_INFO_RSP, sizeof(buf), buf);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
+ buf);
} else {
struct l2cap_info_rsp rsp;
rsp.type = cpu_to_le16(type);
rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
- l2cap_send_cmd(conn, cmd->ident,
- L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
+ &rsp);
}
return 0;
}
-static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
u16 type, result;
@@ -3915,7 +4191,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
/* L2CAP Info req/rsp are unbound to channels, add extra checks */
if (cmd->ident != conn->info_ident ||
- conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
+ conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
return 0;
cancel_delayed_work(&conn->info_timer);
@@ -3940,7 +4216,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
conn->info_ident = l2cap_get_ident(conn);
l2cap_send_cmd(conn, conn->info_ident,
- L2CAP_INFO_REQ, sizeof(req), &req);
+ L2CAP_INFO_REQ, sizeof(req), &req);
} else {
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
conn->info_ident = 0;
@@ -3961,12 +4237,14 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
return 0;
}
-static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u16 cmd_len,
- void *data)
+static int l2cap_create_channel_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd,
+ u16 cmd_len, void *data)
{
struct l2cap_create_chan_req *req = data;
struct l2cap_create_chan_rsp rsp;
+ struct l2cap_chan *chan;
+ struct hci_dev *hdev;
u16 psm, scid;
if (cmd_len != sizeof(*req))
@@ -3980,56 +4258,119 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
- /* Placeholder: Always reject */
+ /* For controller id 0 make BR/EDR connection */
+ if (req->amp_id == HCI_BREDR_ID) {
+ l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
+ req->amp_id);
+ return 0;
+ }
+
+ /* Validate AMP controller id */
+ hdev = hci_dev_get(req->amp_id);
+ if (!hdev)
+ goto error;
+
+ if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
+ hci_dev_put(hdev);
+ goto error;
+ }
+
+ chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
+ req->amp_id);
+ if (chan) {
+ struct amp_mgr *mgr = conn->hcon->amp_mgr;
+ struct hci_conn *hs_hcon;
+
+ hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst);
+ if (!hs_hcon) {
+ hci_dev_put(hdev);
+ return -EFAULT;
+ }
+
+ BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
+
+ mgr->bredr_chan = chan;
+ chan->hs_hcon = hs_hcon;
+ chan->fcs = L2CAP_FCS_NONE;
+ conn->mtu = hdev->block_mtu;
+ }
+
+ hci_dev_put(hdev);
+
+ return 0;
+
+error:
rsp.dcid = 0;
rsp.scid = cpu_to_le16(scid);
- rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
sizeof(rsp), &rsp);
- return 0;
+ return -EFAULT;
}
-static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, void *data)
+static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
{
- BT_DBG("conn %p", conn);
+ struct l2cap_move_chan_req req;
+ u8 ident;
+
+ BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
+
+ ident = l2cap_get_ident(chan->conn);
+ chan->ident = ident;
+
+ req.icid = cpu_to_le16(chan->scid);
+ req.dest_amp_id = dest_amp_id;
+
+ l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
+ &req);
- return l2cap_connect_rsp(conn, cmd, data);
+ __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
}
-static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
- u16 icid, u16 result)
+static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
{
struct l2cap_move_chan_rsp rsp;
- BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+ BT_DBG("chan %p, result 0x%4.4x", chan, result);
- rsp.icid = cpu_to_le16(icid);
+ rsp.icid = cpu_to_le16(chan->dcid);
rsp.result = cpu_to_le16(result);
- l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
+ l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
+ sizeof(rsp), &rsp);
}
-static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
- struct l2cap_chan *chan,
- u16 icid, u16 result)
+static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
{
struct l2cap_move_chan_cfm cfm;
- u8 ident;
- BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+ BT_DBG("chan %p, result 0x%4.4x", chan, result);
- ident = l2cap_get_ident(conn);
- if (chan)
- chan->ident = ident;
+ chan->ident = l2cap_get_ident(chan->conn);
- cfm.icid = cpu_to_le16(icid);
+ cfm.icid = cpu_to_le16(chan->scid);
cfm.result = cpu_to_le16(result);
- l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
+ l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
+ sizeof(cfm), &cfm);
+
+ __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+}
+
+static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
+{
+ struct l2cap_move_chan_cfm cfm;
+
+ BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
+
+ cfm.icid = cpu_to_le16(icid);
+ cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
+
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
+ sizeof(cfm), &cfm);
}
static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
@@ -4043,11 +4384,289 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
}
+static void __release_logical_link(struct l2cap_chan *chan)
+{
+ chan->hs_hchan = NULL;
+ chan->hs_hcon = NULL;
+
+ /* Placeholder - release the logical link */
+}
+
+static void l2cap_logical_fail(struct l2cap_chan *chan)
+{
+ /* Logical link setup failed */
+ if (chan->state != BT_CONNECTED) {
+ /* Create channel failure, disconnect */
+ l2cap_send_disconn_req(chan, ECONNRESET);
+ return;
+ }
+
+ switch (chan->move_role) {
+ case L2CAP_MOVE_ROLE_RESPONDER:
+ l2cap_move_done(chan);
+ l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
+ break;
+ case L2CAP_MOVE_ROLE_INITIATOR:
+ if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
+ chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
+ /* Remote has only sent pending or
+ * success responses, clean up
+ */
+ l2cap_move_done(chan);
+ }
+
+ /* Other amp move states imply that the move
+ * has already aborted
+ */
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+ break;
+ }
+}
+
+static void l2cap_logical_finish_create(struct l2cap_chan *chan,
+ struct hci_chan *hchan)
+{
+ struct l2cap_conf_rsp rsp;
+
+ chan->hs_hchan = hchan;
+ chan->hs_hcon->l2cap_data = chan->conn;
+
+ l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
+
+ if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
+ int err;
+
+ set_default_fcs(chan);
+
+ err = l2cap_ertm_init(chan);
+ if (err < 0)
+ l2cap_send_disconn_req(chan, -err);
+ else
+ l2cap_chan_ready(chan);
+ }
+}
+
+static void l2cap_logical_finish_move(struct l2cap_chan *chan,
+ struct hci_chan *hchan)
+{
+ chan->hs_hcon = hchan->conn;
+ chan->hs_hcon->l2cap_data = chan->conn;
+
+ BT_DBG("move_state %d", chan->move_state);
+
+ switch (chan->move_state) {
+ case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+ /* Move confirm will be sent after a success
+ * response is received
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+ break;
+ case L2CAP_MOVE_WAIT_LOGICAL_CFM:
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+ chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+ } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+ chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+ } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+ chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+ l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+ }
+ break;
+ default:
+ /* Move was not in expected state, free the channel */
+ __release_logical_link(chan);
+
+ chan->move_state = L2CAP_MOVE_STABLE;
+ }
+}
+
+/* Call with chan locked */
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+ u8 status)
+{
+ BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
+
+ if (status) {
+ l2cap_logical_fail(chan);
+ __release_logical_link(chan);
+ return;
+ }
+
+ if (chan->state != BT_CONNECTED) {
+ /* Ignore logical link if channel is on BR/EDR */
+ if (chan->local_amp_id)
+ l2cap_logical_finish_create(chan, hchan);
+ } else {
+ l2cap_logical_finish_move(chan, hchan);
+ }
+}
+
+void l2cap_move_start(struct l2cap_chan *chan)
+{
+ BT_DBG("chan %p", chan);
+
+ if (chan->local_amp_id == HCI_BREDR_ID) {
+ if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
+ return;
+ chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+ chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+ /* Placeholder - start physical link setup */
+ } else {
+ chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+ chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+ chan->move_id = 0;
+ l2cap_move_setup(chan);
+ l2cap_send_move_chan_req(chan, 0);
+ }
+}
+
+static void l2cap_do_create(struct l2cap_chan *chan, int result,
+ u8 local_amp_id, u8 remote_amp_id)
+{
+ BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
+ local_amp_id, remote_amp_id);
+
+ chan->fcs = L2CAP_FCS_NONE;
+
+ /* Outgoing channel on AMP */
+ if (chan->state == BT_CONNECT) {
+ if (result == L2CAP_CR_SUCCESS) {
+ chan->local_amp_id = local_amp_id;
+ l2cap_send_create_chan_req(chan, remote_amp_id);
+ } else {
+ /* Revert to BR/EDR connect */
+ l2cap_send_conn_req(chan);
+ }
+
+ return;
+ }
+
+ /* Incoming channel on AMP */
+ if (__l2cap_no_conn_pending(chan)) {
+ struct l2cap_conn_rsp rsp;
+ char buf[128];
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
+
+ if (result == L2CAP_CR_SUCCESS) {
+ /* Send successful response */
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ } else {
+ /* Send negative response */
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+ }
+
+ l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
+ sizeof(rsp), &rsp);
+
+ if (result == L2CAP_CR_SUCCESS) {
+ __l2cap_state_change(chan, BT_CONFIG);
+ set_bit(CONF_REQ_SENT, &chan->conf_state);
+ l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
+ L2CAP_CONF_REQ,
+ l2cap_build_conf_req(chan, buf), buf);
+ chan->num_conf_req++;
+ }
+ }
+}
+
+static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
+ u8 remote_amp_id)
+{
+ l2cap_move_setup(chan);
+ chan->move_id = local_amp_id;
+ chan->move_state = L2CAP_MOVE_WAIT_RSP;
+
+ l2cap_send_move_chan_req(chan, remote_amp_id);
+}
+
+static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
+{
+ struct hci_chan *hchan = NULL;
+
+ /* Placeholder - get hci_chan for logical link */
+
+ if (hchan) {
+ if (hchan->state == BT_CONNECTED) {
+ /* Logical link is ready to go */
+ chan->hs_hcon = hchan->conn;
+ chan->hs_hcon->l2cap_data = chan->conn;
+ chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+ l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+
+ l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+ } else {
+ /* Wait for logical link to be ready */
+ chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+ }
+ } else {
+ /* Logical link not available */
+ l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
+ }
+}
+
+static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
+{
+ if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+ u8 rsp_result;
+ if (result == -EINVAL)
+ rsp_result = L2CAP_MR_BAD_ID;
+ else
+ rsp_result = L2CAP_MR_NOT_ALLOWED;
+
+ l2cap_send_move_chan_rsp(chan, rsp_result);
+ }
+
+ chan->move_role = L2CAP_MOVE_ROLE_NONE;
+ chan->move_state = L2CAP_MOVE_STABLE;
+
+ /* Restart data transmission */
+ l2cap_ertm_send(chan);
+}
+
+/* Invoke with locked chan */
+void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
+{
+ u8 local_amp_id = chan->local_amp_id;
+ u8 remote_amp_id = chan->remote_amp_id;
+
+ BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
+ chan, result, local_amp_id, remote_amp_id);
+
+ if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
+ l2cap_chan_unlock(chan);
+ return;
+ }
+
+ if (chan->state != BT_CONNECTED) {
+ l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
+ } else if (result != L2CAP_MR_SUCCESS) {
+ l2cap_do_move_cancel(chan, result);
+ } else {
+ switch (chan->move_role) {
+ case L2CAP_MOVE_ROLE_INITIATOR:
+ l2cap_do_move_initiate(chan, local_amp_id,
+ remote_amp_id);
+ break;
+ case L2CAP_MOVE_ROLE_RESPONDER:
+ l2cap_do_move_respond(chan, result);
+ break;
+ default:
+ l2cap_do_move_cancel(chan, result);
+ break;
+ }
+ }
+}
+
static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
struct l2cap_cmd_hdr *cmd,
u16 cmd_len, void *data)
{
struct l2cap_move_chan_req *req = data;
+ struct l2cap_move_chan_rsp rsp;
+ struct l2cap_chan *chan;
u16 icid = 0;
u16 result = L2CAP_MR_NOT_ALLOWED;
@@ -4061,15 +4680,206 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
if (!enable_hs)
return -EINVAL;
- /* Placeholder: Always refuse */
- l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
+ chan = l2cap_get_chan_by_dcid(conn, icid);
+ if (!chan) {
+ rsp.icid = cpu_to_le16(icid);
+ rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
+ sizeof(rsp), &rsp);
+ return 0;
+ }
+
+ chan->ident = cmd->ident;
+
+ if (chan->scid < L2CAP_CID_DYN_START ||
+ chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
+ (chan->mode != L2CAP_MODE_ERTM &&
+ chan->mode != L2CAP_MODE_STREAMING)) {
+ result = L2CAP_MR_NOT_ALLOWED;
+ goto send_move_response;
+ }
+
+ if (chan->local_amp_id == req->dest_amp_id) {
+ result = L2CAP_MR_SAME_ID;
+ goto send_move_response;
+ }
+
+ if (req->dest_amp_id) {
+ struct hci_dev *hdev;
+ hdev = hci_dev_get(req->dest_amp_id);
+ if (!hdev || hdev->dev_type != HCI_AMP ||
+ !test_bit(HCI_UP, &hdev->flags)) {
+ if (hdev)
+ hci_dev_put(hdev);
+
+ result = L2CAP_MR_BAD_ID;
+ goto send_move_response;
+ }
+ hci_dev_put(hdev);
+ }
+
+ /* Detect a move collision. Only send a collision response
+ * if this side has "lost", otherwise proceed with the move.
+ * The winner has the larger bd_addr.
+ */
+ if ((__chan_is_moving(chan) ||
+ chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
+ bacmp(conn->src, conn->dst) > 0) {
+ result = L2CAP_MR_COLLISION;
+ goto send_move_response;
+ }
+
+ chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+ l2cap_move_setup(chan);
+ chan->move_id = req->dest_amp_id;
+ icid = chan->dcid;
+
+ if (!req->dest_amp_id) {
+ /* Moving to BR/EDR */
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+ chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+ result = L2CAP_MR_PEND;
+ } else {
+ chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+ result = L2CAP_MR_SUCCESS;
+ }
+ } else {
+ chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+ /* Placeholder - uncomment when amp functions are available */
+ /*amp_accept_physical(chan, req->dest_amp_id);*/
+ result = L2CAP_MR_PEND;
+ }
+
+send_move_response:
+ l2cap_send_move_chan_rsp(chan, result);
+
+ l2cap_chan_unlock(chan);
return 0;
}
-static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd,
- u16 cmd_len, void *data)
+static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
+{
+ struct l2cap_chan *chan;
+ struct hci_chan *hchan = NULL;
+
+ chan = l2cap_get_chan_by_scid(conn, icid);
+ if (!chan) {
+ l2cap_send_move_chan_cfm_icid(conn, icid);
+ return;
+ }
+
+ __clear_chan_timer(chan);
+ if (result == L2CAP_MR_PEND)
+ __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
+
+ switch (chan->move_state) {
+ case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+ /* Move confirm will be sent when logical link
+ * is complete.
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+ break;
+ case L2CAP_MOVE_WAIT_RSP_SUCCESS:
+ if (result == L2CAP_MR_PEND) {
+ break;
+ } else if (test_bit(CONN_LOCAL_BUSY,
+ &chan->conn_state)) {
+ chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+ } else {
+ /* Logical link is up or moving to BR/EDR,
+ * proceed with move
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+ }
+ break;
+ case L2CAP_MOVE_WAIT_RSP:
+ /* Moving to AMP */
+ if (result == L2CAP_MR_SUCCESS) {
+ /* Remote is ready, send confirm immediately
+ * after logical link is ready
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+ } else {
+ /* Both logical link and move success
+ * are required to confirm
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
+ }
+
+ /* Placeholder - get hci_chan for logical link */
+ if (!hchan) {
+ /* Logical link not available */
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+ break;
+ }
+
+ /* If the logical link is not yet connected, do not
+ * send confirmation.
+ */
+ if (hchan->state != BT_CONNECTED)
+ break;
+
+ /* Logical link is already ready to go */
+
+ chan->hs_hcon = hchan->conn;
+ chan->hs_hcon->l2cap_data = chan->conn;
+
+ if (result == L2CAP_MR_SUCCESS) {
+ /* Can confirm now */
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+ } else {
+ /* Now only need move success
+ * to confirm
+ */
+ chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+ }
+
+ l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+ break;
+ default:
+ /* Any other amp move state means the move failed. */
+ chan->move_id = chan->local_amp_id;
+ l2cap_move_done(chan);
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+ }
+
+ l2cap_chan_unlock(chan);
+}
+
+static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
+ u16 result)
+{
+ struct l2cap_chan *chan;
+
+ chan = l2cap_get_chan_by_ident(conn, ident);
+ if (!chan) {
+ /* Could not locate channel, icid is best guess */
+ l2cap_send_move_chan_cfm_icid(conn, icid);
+ return;
+ }
+
+ __clear_chan_timer(chan);
+
+ if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+ if (result == L2CAP_MR_COLLISION) {
+ chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+ } else {
+ /* Cleanup - cancel move */
+ chan->move_id = chan->local_amp_id;
+ l2cap_move_done(chan);
+ }
+ }
+
+ l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+
+ l2cap_chan_unlock(chan);
+}
+
+static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd,
+ u16 cmd_len, void *data)
{
struct l2cap_move_chan_rsp *rsp = data;
u16 icid, result;
@@ -4082,17 +4892,20 @@ static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
- /* Placeholder: Always unconfirmed */
- l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
+ if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
+ l2cap_move_continue(conn, icid, result);
+ else
+ l2cap_move_fail(conn, cmd->ident, icid, result);
return 0;
}
-static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd,
- u16 cmd_len, void *data)
+static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd,
+ u16 cmd_len, void *data)
{
struct l2cap_move_chan_cfm *cfm = data;
+ struct l2cap_chan *chan;
u16 icid, result;
if (cmd_len != sizeof(*cfm))
@@ -4103,8 +4916,29 @@ static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+ chan = l2cap_get_chan_by_dcid(conn, icid);
+ if (!chan) {
+ /* Spec requires a response even if the icid was not found */
+ l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+ return 0;
+ }
+
+ if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
+ if (result == L2CAP_MC_CONFIRMED) {
+ chan->local_amp_id = chan->move_id;
+ if (!chan->local_amp_id)
+ __release_logical_link(chan);
+ } else {
+ chan->move_id = chan->local_amp_id;
+ }
+
+ l2cap_move_done(chan);
+ }
+
l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+ l2cap_chan_unlock(chan);
+
return 0;
}
@@ -4113,6 +4947,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
u16 cmd_len, void *data)
{
struct l2cap_move_chan_cfm_rsp *rsp = data;
+ struct l2cap_chan *chan;
u16 icid;
if (cmd_len != sizeof(*rsp))
@@ -4122,11 +4957,28 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
BT_DBG("icid 0x%4.4x", icid);
+ chan = l2cap_get_chan_by_scid(conn, icid);
+ if (!chan)
+ return 0;
+
+ __clear_chan_timer(chan);
+
+ if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
+ chan->local_amp_id = chan->move_id;
+
+ if (!chan->local_amp_id && chan->hs_hchan)
+ __release_logical_link(chan);
+
+ l2cap_move_done(chan);
+ }
+
+ l2cap_chan_unlock(chan);
+
return 0;
}
static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
- u16 to_multiplier)
+ u16 to_multiplier)
{
u16 max_latency;
@@ -4147,7 +4999,8 @@ 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)
+ struct l2cap_cmd_hdr *cmd,
+ u8 *data)
{
struct hci_conn *hcon = conn->hcon;
struct l2cap_conn_param_update_req *req;
@@ -4169,7 +5022,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
to_multiplier = __le16_to_cpu(req->to_multiplier);
BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
- min, max, latency, to_multiplier);
+ min, max, latency, to_multiplier);
memset(&rsp, 0, sizeof(rsp));
@@ -4180,7 +5033,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
- sizeof(rsp), &rsp);
+ sizeof(rsp), &rsp);
if (!err)
hci_le_conn_update(hcon, min, max, latency, to_multiplier);
@@ -4189,7 +5042,8 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
}
static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
int err = 0;
@@ -4203,7 +5057,8 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_CONN_RSP:
- err = l2cap_connect_rsp(conn, cmd, data);
+ case L2CAP_CREATE_CHAN_RSP:
+ err = l2cap_connect_create_rsp(conn, cmd, data);
break;
case L2CAP_CONF_REQ:
@@ -4241,10 +5096,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
break;
- case L2CAP_CREATE_CHAN_RSP:
- err = l2cap_create_channel_rsp(conn, cmd, data);
- break;
-
case L2CAP_MOVE_CHAN_REQ:
err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
break;
@@ -4271,7 +5122,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
}
static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u8 *data)
{
switch (cmd->code) {
case L2CAP_COMMAND_REJ:
@@ -4290,7 +5141,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
}
static inline void l2cap_sig_channel(struct l2cap_conn *conn,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
u8 *data = skb->data;
int len = skb->len;
@@ -4307,7 +5158,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
cmd_len = le16_to_cpu(cmd.len);
- BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
+ BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
+ cmd.ident);
if (cmd_len > len || !cmd.ident) {
BT_DBG("corrupted command");
@@ -4326,7 +5178,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
/* FIXME: Map err to a valid reason */
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
- l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
+ l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
+ sizeof(rej), &rej);
}
data += cmd_len;
@@ -4391,8 +5244,8 @@ static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
}
}
-static void append_skb_frag(struct sk_buff *skb,
- struct sk_buff *new_frag, struct sk_buff **last_frag)
+static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
+ struct sk_buff **last_frag)
{
/* skb->len reflects data in skb as well as all fragments
* skb->data_len reflects only data in fragments
@@ -4492,6 +5345,12 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
return err;
}
+static int l2cap_resegment(struct l2cap_chan *chan)
+{
+ /* Placeholder */
+ return 0;
+}
+
void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
{
u8 event;
@@ -4546,7 +5405,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan,
if (control->reqseq == chan->next_tx_seq) {
BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
return;
}
@@ -4560,7 +5419,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan,
if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
return;
}
@@ -4604,7 +5463,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan,
if (control->reqseq == chan->next_tx_seq) {
BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
return;
}
@@ -4613,7 +5472,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan,
if (chan->max_tx && skb &&
bt_cb(skb)->control.retries >= chan->max_tx) {
BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
return;
}
@@ -4641,7 +5500,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
- chan->tx_win) {
+ chan->tx_win) {
/* See notes below regarding "double poll" and
* invalid packets.
*/
@@ -4682,8 +5541,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
}
if (__seq_offset(chan, txseq, chan->last_acked_seq) <
- __seq_offset(chan, chan->expected_tx_seq,
- chan->last_acked_seq)){
+ __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
BT_DBG("Duplicate - expected_tx_seq later than txseq");
return L2CAP_TXSEQ_DUPLICATE;
}
@@ -4798,8 +5656,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
break;
case L2CAP_TXSEQ_INVALID:
default:
- l2cap_send_disconn_req(chan->conn, chan,
- ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
break;
}
break;
@@ -4808,8 +5665,8 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
if (control->final) {
clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- if (!test_and_clear_bit(CONN_REJ_ACT,
- &chan->conn_state)) {
+ if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
+ !__chan_is_moving(chan)) {
control->final = 0;
l2cap_retransmit_all(chan, control);
}
@@ -4932,8 +5789,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
break;
case L2CAP_TXSEQ_INVALID:
default:
- l2cap_send_disconn_req(chan->conn, chan,
- ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
break;
}
break;
@@ -4998,6 +5854,96 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
return err;
}
+static int l2cap_finish_move(struct l2cap_chan *chan)
+{
+ BT_DBG("chan %p", chan);
+
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+
+ if (chan->hs_hcon)
+ chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+ else
+ chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+ return l2cap_resegment(chan);
+}
+
+static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+{
+ int err;
+
+ BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
+ event);
+
+ if (!control->poll)
+ return -EPROTO;
+
+ l2cap_process_reqseq(chan, control->reqseq);
+
+ if (!skb_queue_empty(&chan->tx_q))
+ chan->tx_send_head = skb_peek(&chan->tx_q);
+ else
+ chan->tx_send_head = NULL;
+
+ /* Rewind next_tx_seq to the point expected
+ * by the receiver.
+ */
+ chan->next_tx_seq = control->reqseq;
+ chan->unacked_frames = 0;
+
+ err = l2cap_finish_move(chan);
+ if (err)
+ return err;
+
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ l2cap_send_i_or_rr_or_rnr(chan);
+
+ if (event == L2CAP_EV_RECV_IFRAME)
+ return -EPROTO;
+
+ return l2cap_rx_state_recv(chan, control, NULL, event);
+}
+
+static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+{
+ int err;
+
+ if (!control->final)
+ return -EPROTO;
+
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+ l2cap_process_reqseq(chan, control->reqseq);
+
+ if (!skb_queue_empty(&chan->tx_q))
+ chan->tx_send_head = skb_peek(&chan->tx_q);
+ else
+ chan->tx_send_head = NULL;
+
+ /* Rewind next_tx_seq to the point expected
+ * by the receiver.
+ */
+ chan->next_tx_seq = control->reqseq;
+ chan->unacked_frames = 0;
+
+ if (chan->hs_hcon)
+ chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+ else
+ chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+ err = l2cap_resegment(chan);
+
+ if (!err)
+ err = l2cap_rx_state_recv(chan, control, skb, event);
+
+ return err;
+}
+
static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
{
/* Make sure reqseq is for a packet that has been sent but not acked */
@@ -5024,6 +5970,12 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
err = l2cap_rx_state_srej_sent(chan, control, skb,
event);
break;
+ case L2CAP_RX_STATE_WAIT_P:
+ err = l2cap_rx_state_wait_p(chan, control, skb, event);
+ break;
+ case L2CAP_RX_STATE_WAIT_F:
+ err = l2cap_rx_state_wait_f(chan, control, skb, event);
+ break;
default:
/* shut it down */
break;
@@ -5032,7 +5984,7 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
control->reqseq, chan->next_tx_seq,
chan->expected_ack_seq);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
}
return err;
@@ -5101,7 +6053,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
len -= L2CAP_FCS_SIZE;
if (len > chan->mps) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto drop;
}
@@ -5126,8 +6078,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
}
if (err)
- l2cap_send_disconn_req(chan->conn, chan,
- ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
} else {
const u8 rx_func_to_event[4] = {
L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
@@ -5143,8 +6094,8 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
control->super);
if (len != 0) {
- BT_ERR("%d", len);
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ BT_ERR("Trailing bytes: %d in sframe", len);
+ l2cap_send_disconn_req(chan, ECONNRESET);
goto drop;
}
@@ -5155,7 +6106,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
event = rx_func_to_event[control->super];
if (l2cap_rx(chan, control, skb, event))
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan, ECONNRESET);
}
return 0;
@@ -5323,7 +6274,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
int exact = 0, lm1 = 0, lm2 = 0;
struct l2cap_chan *c;
- BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
+ BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
/* Find listening sockets and check their link_mode */
read_lock(&chan_list_lock);
@@ -5353,15 +6304,15 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn;
- BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
+ BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) {
conn = l2cap_conn_add(hcon, status);
if (conn)
l2cap_conn_ready(conn);
- } else
+ } else {
l2cap_conn_del(hcon, bt_to_errno(status));
-
+ }
}
int l2cap_disconn_ind(struct hci_conn *hcon)
@@ -5437,13 +6388,13 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
continue;
}
- if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
+ if (!__l2cap_no_conn_pending(chan)) {
l2cap_chan_unlock(chan);
continue;
}
if (!status && (chan->state == BT_CONNECTED ||
- chan->state == BT_CONFIG)) {
+ chan->state == BT_CONFIG)) {
struct sock *sk = chan->sk;
clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
@@ -5456,7 +6407,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (chan->state == BT_CONNECT) {
if (!status) {
- l2cap_send_conn_req(chan);
+ l2cap_start_connection(chan);
} else {
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
}
@@ -5470,11 +6421,9 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status) {
if (test_bit(BT_SK_DEFER_SETUP,
&bt_sk(sk)->flags)) {
- struct sock *parent = bt_sk(sk)->parent;
res = L2CAP_CR_PEND;
stat = L2CAP_CS_AUTHOR_PEND;
- if (parent)
- parent->sk_data_ready(parent, 0);
+ chan->ops->defer(chan);
} else {
__l2cap_state_change(chan, BT_CONFIG);
res = L2CAP_CR_SUCCESS;
@@ -5494,7 +6443,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
rsp.result = cpu_to_le16(res);
rsp.status = cpu_to_le16(stat);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
- sizeof(rsp), &rsp);
+ sizeof(rsp), &rsp);
if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
res == L2CAP_CR_SUCCESS) {
@@ -5519,6 +6468,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
{
struct l2cap_conn *conn = hcon->l2cap_data;
+ struct l2cap_hdr *hdr;
+ int len;
+
+ /* For AMP controller do not create l2cap conn */
+ if (!conn && hcon->hdev->dev_type != HCI_BREDR)
+ goto drop;
if (!conn)
conn = l2cap_conn_add(hcon, 0);
@@ -5528,10 +6483,10 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
- if (!(flags & ACL_CONT)) {
- struct l2cap_hdr *hdr;
- int len;
-
+ switch (flags) {
+ case ACL_START:
+ case ACL_START_NO_FLUSH:
+ case ACL_COMPLETE:
if (conn->rx_len) {
BT_ERR("Unexpected start frame (len %d)", skb->len);
kfree_skb(conn->rx_skb);
@@ -5560,20 +6515,22 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (skb->len > len) {
BT_ERR("Frame is too long (len %d, expected len %d)",
- skb->len, len);
+ skb->len, len);
l2cap_conn_unreliable(conn, ECOMM);
goto drop;
}
/* Allocate skb for the complete frame (with header) */
- conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
+ conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
if (!conn->rx_skb)
goto drop;
skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
- skb->len);
+ skb->len);
conn->rx_len = len - skb->len;
- } else {
+ break;
+
+ case ACL_CONT:
BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
if (!conn->rx_len) {
@@ -5584,7 +6541,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (skb->len > conn->rx_len) {
BT_ERR("Fragment is too long (len %d, expected %d)",
- skb->len, conn->rx_len);
+ skb->len, conn->rx_len);
kfree_skb(conn->rx_skb);
conn->rx_skb = NULL;
conn->rx_len = 0;
@@ -5593,7 +6550,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
}
skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
- skb->len);
+ skb->len);
conn->rx_len -= skb->len;
if (!conn->rx_len) {
@@ -5601,6 +6558,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
l2cap_recv_frame(conn, conn->rx_skb);
conn->rx_skb = NULL;
}
+ break;
}
drop:
@@ -5617,12 +6575,11 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
list_for_each_entry(c, &chan_list, global_l) {
struct sock *sk = c->sk;
- seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
- batostr(&bt_sk(sk)->src),
- batostr(&bt_sk(sk)->dst),
- c->state, __le16_to_cpu(c->psm),
- c->scid, c->dcid, c->imtu, c->omtu,
- c->sec_level, c->mode);
+ seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
+ &bt_sk(sk)->src, &bt_sk(sk)->dst,
+ c->state, __le16_to_cpu(c->psm),
+ c->scid, c->dcid, c->imtu, c->omtu,
+ c->sec_level, c->mode);
}
read_unlock(&chan_list_lock);
@@ -5653,8 +6610,8 @@ int __init l2cap_init(void)
return err;
if (bt_debugfs) {
- l2cap_debugfs = debugfs_create_file("l2cap", 0444,
- bt_debugfs, NULL, &l2cap_debugfs_fops);
+ l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
+ NULL, &l2cap_debugfs_fops);
if (!l2cap_debugfs)
BT_ERR("Failed to create L2CAP debug file");
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 083f2bf065d4..1bcfb8422fdc 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = {
static const struct proto_ops l2cap_sock_ops;
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+ int proto, gfp_t prio);
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
@@ -106,7 +107,8 @@ done:
return err;
}
-static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
+static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
+ int alen, int flags)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CONNECTED,
- sock_sndtimeo(sk, flags & O_NONBLOCK));
+ sock_sndtimeo(sk, flags & O_NONBLOCK));
release_sock(sk);
@@ -185,7 +187,8 @@ done:
return err;
}
-static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
+ int flags)
{
DECLARE_WAITQUEUE(wait, current);
struct sock *sk = sock->sk, *nsk;
@@ -241,7 +244,8 @@ done:
return err;
}
-static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
+ int *len, int peer)
{
struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
struct sock *sk = sock->sk;
@@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
return 0;
}
-static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
+ char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break;
case BT_SECURITY_HIGH:
opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
- L2CAP_LM_SECURE;
+ L2CAP_LM_SECURE;
break;
default:
opt = 0;
@@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
return err;
}
-static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
switch (optname) {
case BT_SECURITY:
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
- chan->chan_type != L2CAP_CHAN_RAW) {
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
break;
}
memset(&sec, 0, sizeof(sec));
- if (chan->conn)
+ if (chan->conn) {
sec.level = chan->conn->hcon->sec_level;
- else
- sec.level = chan->sec_level;
- if (sk->sk_state == BT_CONNECTED)
- sec.key_size = chan->conn->hcon->enc_key_size;
+ if (sk->sk_state == BT_CONNECTED)
+ sec.key_size = chan->conn->hcon->enc_key_size;
+ } else {
+ sec.level = chan->sec_level;
+ }
len = min_t(unsigned int, len, sizeof(sec));
if (copy_to_user(optval, (char *) &sec, len))
@@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
case BT_FLUSHABLE:
if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
- (u32 __user *) optval))
+ (u32 __user *) optval))
err = -EFAULT;
break;
case BT_POWER:
if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
- && sk->sk_type != SOCK_RAW) {
+ && sk->sk_type != SOCK_RAW) {
err = -EINVAL;
break;
}
@@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
return true;
}
-static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
+static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
chan->fcs = opts.fcs;
chan->max_tx = opts.max_tx;
chan->tx_win = opts.txwin_size;
+ chan->flush_to = opts.flush_to;
break;
case L2CAP_LM:
@@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
return err;
}
-static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
switch (optname) {
case BT_SECURITY:
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
- chan->chan_type != L2CAP_CHAN_RAW) {
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
break;
}
@@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if (sec.level < BT_SECURITY_LOW ||
- sec.level > BT_SECURITY_HIGH) {
+ sec.level > BT_SECURITY_HIGH) {
err = -EINVAL;
break;
}
@@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
/* or for ACL link */
} else if ((sk->sk_state == BT_CONNECT2 &&
- test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
+ test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
sk->sk_state == BT_CONNECTED) {
if (!l2cap_chan_check_security(chan))
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
@@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
case BT_POWER:
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
- chan->chan_type != L2CAP_CHAN_RAW) {
+ chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL;
break;
}
@@ -720,12 +730,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if (chan->mode != L2CAP_MODE_ERTM &&
- chan->mode != L2CAP_MODE_STREAMING) {
+ chan->mode != L2CAP_MODE_STREAMING) {
err = -EOPNOTSUPP;
break;
}
chan->chan_policy = (u8) opt;
+
+ if (sk->sk_state == BT_CONNECTED &&
+ chan->move_role == L2CAP_MOVE_ROLE_NONE)
+ l2cap_move_start(chan);
+
break;
default:
@@ -737,7 +752,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
return err;
}
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
+static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -762,7 +778,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
return err;
}
-static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
+static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags)
{
struct sock *sk = sock->sk;
struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -866,7 +883,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED,
- sk->sk_lingertime);
+ sk->sk_lingertime);
}
if (!err && sk->sk_err)
@@ -930,7 +947,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
}
sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
- GFP_ATOMIC);
+ GFP_ATOMIC);
if (!sk)
return NULL;
@@ -938,6 +955,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
l2cap_sock_init(sk, parent);
+ bt_accept_enqueue(parent, sk);
+
return l2cap_pi(sk)->chan;
}
@@ -1068,6 +1087,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
release_sock(sk);
}
+static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
+{
+ struct sock *sk = chan->data;
+ struct sock *parent = bt_sk(sk)->parent;
+
+ if (parent)
+ parent->sk_data_ready(parent, 0);
+}
+
static struct l2cap_ops l2cap_chan_ops = {
.name = "L2CAP Socket Interface",
.new_connection = l2cap_sock_new_connection_cb,
@@ -1076,6 +1104,7 @@ static struct l2cap_ops l2cap_chan_ops = {
.teardown = l2cap_sock_teardown_cb,
.state_change = l2cap_sock_state_change_cb,
.ready = l2cap_sock_ready_cb,
+ .defer = l2cap_sock_defer_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb,
};
@@ -1083,7 +1112,8 @@ static void l2cap_sock_destruct(struct sock *sk)
{
BT_DBG("sk %p", sk);
- l2cap_chan_put(l2cap_pi(sk)->chan);
+ if (l2cap_pi(sk)->chan)
+ l2cap_chan_put(l2cap_pi(sk)->chan);
if (l2cap_pi(sk)->rx_busy_skb) {
kfree_skb(l2cap_pi(sk)->rx_busy_skb);
l2cap_pi(sk)->rx_busy_skb = NULL;
@@ -1159,7 +1189,8 @@ static struct proto l2cap_proto = {
.obj_size = sizeof(struct l2cap_pinfo)
};
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+ int proto, gfp_t prio)
{
struct sock *sk;
struct l2cap_chan *chan;
@@ -1204,7 +1235,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
sock->state = SS_UNCONNECTED;
if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
- sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
+ sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
@@ -1261,7 +1292,8 @@ int __init l2cap_init_sockets(void)
goto error;
}
- err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL);
+ err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list,
+ NULL);
if (err < 0) {
BT_ERR("Failed to create L2CAP proc file");
bt_sock_unregister(BTPROTO_L2CAP);
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index e1c97527e16c..b3fbc73516c4 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -41,20 +41,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src)
}
EXPORT_SYMBOL(baswap);
-char *batostr(bdaddr_t *ba)
-{
- static char str[2][18];
- static int i = 1;
-
- i ^= 1;
- sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
- ba->b[5], ba->b[4], ba->b[3],
- ba->b[2], ba->b[1], ba->b[0]);
-
- return str[i];
-}
-EXPORT_SYMBOL(batostr);
-
/* Bluetooth error codes to Unix errno mapping */
int bt_to_errno(__u16 code)
{
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 91de4239da66..f559b966279c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -222,7 +222,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
hdr = (void *) skb_put(skb, sizeof(*hdr));
- hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
+ hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS);
hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev));
@@ -253,7 +253,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
hdr = (void *) skb_put(skb, sizeof(*hdr));
- hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE);
hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
@@ -377,15 +377,15 @@ static u32 get_supported_settings(struct hci_dev *hdev)
u32 settings = 0;
settings |= MGMT_SETTING_POWERED;
- settings |= MGMT_SETTING_CONNECTABLE;
- settings |= MGMT_SETTING_FAST_CONNECTABLE;
- settings |= MGMT_SETTING_DISCOVERABLE;
settings |= MGMT_SETTING_PAIRABLE;
if (lmp_ssp_capable(hdev))
settings |= MGMT_SETTING_SSP;
if (lmp_bredr_capable(hdev)) {
+ settings |= MGMT_SETTING_CONNECTABLE;
+ settings |= MGMT_SETTING_FAST_CONNECTABLE;
+ settings |= MGMT_SETTING_DISCOVERABLE;
settings |= MGMT_SETTING_BREDR;
settings |= MGMT_SETTING_LINK_SECURITY;
}
@@ -485,7 +485,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr += (name_len + 2);
}
- if (hdev->inq_tx_power) {
+ if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
ptr[0] = 2;
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->inq_tx_power;
@@ -566,7 +566,7 @@ static int update_eir(struct hci_dev *hdev)
if (!hdev_is_powered(hdev))
return 0;
- if (!(hdev->features[6] & LMP_EXT_INQ))
+ if (!lmp_ext_inq_capable(hdev))
return 0;
if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
@@ -833,7 +833,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
if (hdev)
hdr->index = cpu_to_le16(hdev->id);
else
- hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
+ hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
hdr->len = cpu_to_le16(data_len);
if (data)
@@ -868,6 +868,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
+ if (!lmp_bredr_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
+ MGMT_STATUS_NOT_SUPPORTED);
+
timeout = __le16_to_cpu(cp->timeout);
if (!cp->val && timeout > 0)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
@@ -963,6 +967,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
+ if (!lmp_bredr_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
+ MGMT_STATUS_NOT_SUPPORTED);
+
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
@@ -1061,6 +1069,10 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
+ if (!lmp_bredr_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
+ MGMT_STATUS_NOT_SUPPORTED);
+
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
@@ -1214,7 +1226,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
}
val = !!cp->val;
- enabled = !!(hdev->host_features[0] & LMP_HOST_LE);
+ enabled = lmp_host_le_capable(hdev);
if (!hdev_is_powered(hdev) || val == enabled) {
bool changed = false;
@@ -1250,7 +1262,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (val) {
hci_cp.le = val;
- hci_cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+ hci_cp.simul = lmp_le_br_capable(hdev);
}
err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
@@ -2596,6 +2608,10 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name);
+ if (!lmp_bredr_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+ MGMT_STATUS_NOT_SUPPORTED);
+
if (!hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_NOT_POWERED);
@@ -2873,6 +2889,21 @@ static void settings_rsp(struct pending_cmd *cmd, void *data)
mgmt_pending_free(cmd);
}
+static int set_bredr_scan(struct hci_dev *hdev)
+{
+ u8 scan = 0;
+
+ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
+ scan |= SCAN_PAGE;
+ if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
+ scan |= SCAN_INQUIRY;
+
+ if (!scan)
+ return 0;
+
+ return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+}
+
int mgmt_powered(struct hci_dev *hdev, u8 powered)
{
struct cmd_lookup match = { NULL, hdev };
@@ -2884,17 +2915,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
if (powered) {
- u8 scan = 0;
-
- if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
- scan |= SCAN_PAGE;
- if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
- scan |= SCAN_INQUIRY;
-
- if (scan)
- hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-
- if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+ if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+ !lmp_host_ssp_capable(hdev)) {
u8 ssp = 1;
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
@@ -2904,15 +2926,24 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
struct hci_cp_write_le_host_supported cp;
cp.le = 1;
- cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
-
- hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
- sizeof(cp), &cp);
+ cp.simul = lmp_le_br_capable(hdev);
+
+ /* Check first if we already have the right
+ * host state (host features set)
+ */
+ if (cp.le != lmp_host_le_capable(hdev) ||
+ cp.simul != lmp_host_le_br_capable(hdev))
+ hci_send_cmd(hdev,
+ HCI_OP_WRITE_LE_HOST_SUPPORTED,
+ sizeof(cp), &cp);
}
- update_class(hdev);
- update_name(hdev, hdev->dev_name);
- update_eir(hdev);
+ if (lmp_bredr_capable(hdev)) {
+ set_bredr_scan(hdev);
+ update_class(hdev);
+ update_name(hdev, hdev->dev_name);
+ update_eir(hdev);
+ }
} else {
u8 status = MGMT_STATUS_NOT_POWERED;
mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
@@ -3127,6 +3158,9 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
struct pending_cmd *cmd;
int err;
+ mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
+ hdev);
+
cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
if (!cmd)
return -ENOENT;
@@ -3139,8 +3173,6 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
mgmt_pending_remove(cmd);
- mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
- hdev);
return err;
}
@@ -3360,7 +3392,7 @@ static int clear_eir(struct hci_dev *hdev)
{
struct hci_cp_write_eir cp;
- if (!(hdev->features[6] & LMP_EXT_INQ))
+ if (!lmp_ext_inq_capable(hdev))
return 0;
memset(hdev->eir, 0, sizeof(hdev->eir));
@@ -3492,7 +3524,12 @@ send_event:
err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev,
sizeof(ev), cmd ? cmd->sk : NULL);
- update_eir(hdev);
+ /* EIR is taken care of separately when powering on the
+ * adapter so only update them here if this is a name change
+ * unrelated to power on.
+ */
+ if (!test_bit(HCI_INIT, &hdev->flags))
+ update_eir(hdev);
failed:
if (cmd)
@@ -3587,9 +3624,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
ev->addr.type = link_to_bdaddr(link_type, addr_type);
ev->rssi = rssi;
if (cfm_name)
- ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
+ ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
if (!ssp)
- ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
+ ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
if (eir_len > 0)
memcpy(ev->eir, eir, eir_len);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index c75107ef8920..201fdf737209 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -377,8 +377,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
int err = 0;
u8 dlci;
- BT_DBG("dlc %p state %ld %s %s channel %d",
- d, d->state, batostr(src), batostr(dst), channel);
+ BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d",
+ d, d->state, src, dst, channel);
if (channel < 1 || channel > 30)
return -EINVAL;
@@ -676,7 +676,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
struct socket *sock;
struct sock *sk;
- BT_DBG("%s %s", batostr(src), batostr(dst));
+ BT_DBG("%pMR -> %pMR", src, dst);
*err = rfcomm_l2sock_create(&sock);
if (*err < 0)
@@ -709,7 +709,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
bacpy(&addr.l2_bdaddr, dst);
addr.l2_family = AF_BLUETOOTH;
- addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
+ addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
*err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
if (*err == 0 || *err == -EINPROGRESS)
@@ -1987,7 +1987,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Bind socket */
bacpy(&addr.l2_bdaddr, ba);
addr.l2_family = AF_BLUETOOTH;
- addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
+ addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0) {
@@ -2125,11 +2125,10 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
list_for_each_entry(d, &s->dlcs, list) {
struct sock *sk = s->sock->sk;
- seq_printf(f, "%s %s %ld %d %d %d %d\n",
- batostr(&bt_sk(sk)->src),
- batostr(&bt_sk(sk)->dst),
- d->state, d->dlci, d->mtu,
- d->rx_credits, d->tx_credits);
+ seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n",
+ &bt_sk(sk)->src, &bt_sk(sk)->dst,
+ d->state, d->dlci, d->mtu,
+ d->rx_credits, d->tx_credits);
}
}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index b3226f3658cf..ce3f6658f4b2 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -334,7 +334,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
struct sock *sk = sock->sk;
int err = 0;
- BT_DBG("sk %p %s", sk, batostr(&sa->rc_bdaddr));
+ BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr);
if (!addr || addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
@@ -467,7 +467,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
long timeo;
int err = 0;
- lock_sock(sk);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
if (sk->sk_type != SOCK_STREAM) {
err = -EINVAL;
@@ -504,7 +504,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
release_sock(sk);
timeo = schedule_timeout(timeo);
- lock_sock(sk);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
@@ -975,10 +975,9 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
read_lock(&rfcomm_sk_list.lock);
sk_for_each(sk, node, &rfcomm_sk_list.head) {
- seq_printf(f, "%s %s %d %d\n",
- batostr(&bt_sk(sk)->src),
- batostr(&bt_sk(sk)->dst),
- sk->sk_state, rfcomm_pi(sk)->channel);
+ seq_printf(f, "%pMR %pMR %d %d\n",
+ &bt_sk(sk)->src, &bt_sk(sk)->dst,
+ sk->sk_state, rfcomm_pi(sk)->channel);
}
read_unlock(&rfcomm_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index ccc248791d50..bd6fd0f43d2b 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -166,7 +166,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
{
struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
- return sprintf(buf, "%s\n", batostr(&dev->dst));
+ return sprintf(buf, "%pMR\n", &dev->dst);
}
static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
@@ -663,8 +663,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if (!dev)
return -ENODEV;
- BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
- dev->channel, dev->port.count);
+ BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
+ dev->channel, dev->port.count);
spin_lock_irqsave(&dev->port.lock, flags);
if (++dev->port.count > 1) {
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index dc42b917aaaf..531a93d613d4 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -131,15 +131,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
sco_sock_clear_timer(sk);
sco_chan_del(sk, err);
bh_unlock_sock(sk);
-
- sco_conn_lock(conn);
- conn->sk = NULL;
- sco_pi(sk)->conn = NULL;
- sco_conn_unlock(conn);
-
- if (conn->hcon)
- hci_conn_put(conn->hcon);
-
sco_sock_kill(sk);
}
@@ -172,7 +163,7 @@ static int sco_connect(struct sock *sk)
struct hci_dev *hdev;
int err, type;
- BT_DBG("%s -> %s", batostr(src), batostr(dst));
+ BT_DBG("%pMR -> %pMR", src, dst);
hdev = hci_get_route(dst, src);
if (!hdev)
@@ -397,6 +388,7 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
if (parent) {
sk->sk_type = parent->sk_type;
+ bt_sk(sk)->flags = bt_sk(parent)->flags;
security_sk_clone(parent, sk);
}
}
@@ -460,7 +452,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
struct sock *sk = sock->sk;
int err = 0;
- BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr));
+ BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
if (!addr || addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
@@ -662,16 +654,57 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return err;
}
+static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sco_pinfo *pi = sco_pi(sk);
+
+ lock_sock(sk);
+
+ if (sk->sk_state == BT_CONNECT2 &&
+ test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+ hci_conn_accept(pi->conn->hcon, 0);
+ sk->sk_state = BT_CONFIG;
+
+ release_sock(sk);
+ return 0;
+ }
+
+ release_sock(sk);
+
+ return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+}
+
static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int err = 0;
+ u32 opt;
BT_DBG("sk %p", sk);
lock_sock(sk);
switch (optname) {
+
+ case BT_DEFER_SETUP:
+ if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ else
+ clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -753,6 +786,19 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
lock_sock(sk);
switch (optname) {
+
+ case BT_DEFER_SETUP:
+ if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
+ (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -830,6 +876,16 @@ static void sco_chan_del(struct sock *sk, int err)
BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
+ if (conn) {
+ sco_conn_lock(conn);
+ conn->sk = NULL;
+ sco_pi(sk)->conn = NULL;
+ sco_conn_unlock(conn);
+
+ if (conn->hcon)
+ hci_conn_put(conn->hcon);
+ }
+
sk->sk_state = BT_CLOSED;
sk->sk_err = err;
sk->sk_state_change(sk);
@@ -874,7 +930,10 @@ static void sco_conn_ready(struct sco_conn *conn)
hci_conn_hold(conn->hcon);
__sco_chan_add(conn, sk, parent);
- sk->sk_state = BT_CONNECTED;
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
+ sk->sk_state = BT_CONNECT2;
+ else
+ sk->sk_state = BT_CONNECTED;
/* Wake up parent */
parent->sk_data_ready(parent, 1);
@@ -887,13 +946,13 @@ done:
}
/* ----- SCO interface with lower layer (HCI) ----- */
-int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
{
struct sock *sk;
struct hlist_node *node;
int lm = 0;
- BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
+ BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
/* Find listening sockets */
read_lock(&sco_sk_list.lock);
@@ -904,6 +963,9 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
lm |= HCI_LM_ACCEPT;
+
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+ *flags |= HCI_PROTO_DEFER;
break;
}
}
@@ -914,7 +976,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{
- BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
+ BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) {
struct sco_conn *conn;
@@ -959,8 +1021,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p)
read_lock(&sco_sk_list.lock);
sk_for_each(sk, node, &sco_sk_list.head) {
- seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
- batostr(&bt_sk(sk)->dst), sk->sk_state);
+ seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src,
+ &bt_sk(sk)->dst, sk->sk_state);
}
read_unlock(&sco_sk_list.lock);
@@ -992,7 +1054,7 @@ static const struct proto_ops sco_sock_ops = {
.accept = sco_sock_accept,
.getname = sco_sock_getname,
.sendmsg = sco_sock_sendmsg,
- .recvmsg = bt_sock_recvmsg,
+ .recvmsg = sco_sock_recvmsg,
.poll = bt_sock_poll,
.ioctl = bt_sock_ioctl,
.mmap = sock_no_mmap,
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a5923378bdf0..68a9587c9694 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -167,7 +167,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(sizeof(code) + dlen);
- lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+ lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index d0359ea8ee79..e859098f5ee9 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -12,6 +12,6 @@ bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
-bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o
+bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 070e8a68cfc6..7c78e2640190 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -313,6 +313,8 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_fdb_add = br_fdb_add,
.ndo_fdb_del = br_fdb_delete,
.ndo_fdb_dump = br_fdb_dump,
+ .ndo_bridge_getlink = br_getlink,
+ .ndo_bridge_setlink = br_setlink,
};
static void br_dev_free(struct net_device *dev)
@@ -356,7 +358,7 @@ void br_dev_setup(struct net_device *dev)
br->bridge_id.prio[0] = 0x80;
br->bridge_id.prio[1] = 0x00;
- memcpy(br->group_addr, br_group_address, ETH_ALEN);
+ memcpy(br->group_addr, eth_reserved_addr_base, ETH_ALEN);
br->stp_enabled = BR_NO_STP;
br->group_fwd_mask = BR_GROUPFWD_DEFAULT;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 76f15fda0212..4b34207419b1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -19,9 +19,6 @@
#include <linux/export.h>
#include "br_private.h"
-/* Bridge group multicast address 802.1d (pg 51). */
-const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
-
/* Hook for brouter */
br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
EXPORT_SYMBOL(br_should_route_hook);
@@ -127,18 +124,6 @@ static int br_handle_local_finish(struct sk_buff *skb)
return 0; /* process further */
}
-/* Does address match the link local multicast address.
- * 01:80:c2:00:00:0X
- */
-static inline int is_link_local(const unsigned char *dest)
-{
- __be16 *a = (__be16 *)dest;
- static const __be16 *b = (const __be16 *)br_group_address;
- static const __be16 m = cpu_to_be16(0xfff0);
-
- return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
-}
-
/*
* Return NULL if skb is handled
* note: already called with rcu_read_lock
@@ -162,7 +147,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
p = br_port_get_rcu(skb->dev);
- if (unlikely(is_link_local(dest))) {
+ if (unlikely(is_link_local_ether_addr(dest))) {
/*
* See IEEE 802.1D Table 7-10 Reserved addresses
*
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 7222fe1d5460..cd8c3a44ab7d 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -85,13 +85,14 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
/* called with RTNL */
static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
{
+ struct net *net = dev_net(br->dev);
struct net_device *dev;
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
- dev = __dev_get_by_index(dev_net(br->dev), ifindex);
+ dev = __dev_get_by_index(net, ifindex);
if (dev == NULL)
return -EINVAL;
@@ -178,25 +179,25 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
case BRCTL_SET_BRIDGE_FORWARD_DELAY:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
return br_set_forward_delay(br, args[1]);
case BRCTL_SET_BRIDGE_HELLO_TIME:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
return br_set_hello_time(br, args[1]);
case BRCTL_SET_BRIDGE_MAX_AGE:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
return br_set_max_age(br, args[1]);
case BRCTL_SET_AGEING_TIME:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
br->ageing_time = clock_t_to_jiffies(args[1]);
@@ -236,14 +237,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
case BRCTL_SET_BRIDGE_STP_STATE:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
br_stp_set_enabled(br, args[1]);
return 0;
case BRCTL_SET_BRIDGE_PRIORITY:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock);
@@ -256,7 +257,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct net_bridge_port *p;
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock);
@@ -273,7 +274,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct net_bridge_port *p;
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock);
@@ -330,7 +331,7 @@ static int old_deviceless(struct net *net, void __user *uarg)
{
char buf[IFNAMSIZ];
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
@@ -360,7 +361,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar
{
char buf[IFNAMSIZ];
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(buf, uarg, IFNAMSIZ))
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
new file mode 100644
index 000000000000..6f0a2eebcb27
--- /dev/null
+++ b/net/bridge/br_mdb.c
@@ -0,0 +1,481 @@
+#include <linux/err.h>
+#include <linux/igmp.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/rculist.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <net/ip.h>
+#include <net/netlink.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+#endif
+
+#include "br_private.h"
+
+static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev)
+{
+ struct net_bridge *br = netdev_priv(dev);
+ struct net_bridge_port *p;
+ struct hlist_node *n;
+ struct nlattr *nest;
+
+ if (!br->multicast_router || hlist_empty(&br->router_list))
+ return 0;
+
+ nest = nla_nest_start(skb, MDBA_ROUTER);
+ if (nest == NULL)
+ return -EMSGSIZE;
+
+ hlist_for_each_entry_rcu(p, n, &br->router_list, rlist) {
+ if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex))
+ goto fail;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+fail:
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+}
+
+static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev)
+{
+ struct net_bridge *br = netdev_priv(dev);
+ struct net_bridge_mdb_htable *mdb;
+ struct nlattr *nest, *nest2;
+ int i, err = 0;
+ int idx = 0, s_idx = cb->args[1];
+
+ if (br->multicast_disabled)
+ return 0;
+
+ mdb = rcu_dereference(br->mdb);
+ if (!mdb)
+ return 0;
+
+ nest = nla_nest_start(skb, MDBA_MDB);
+ if (nest == NULL)
+ return -EMSGSIZE;
+
+ for (i = 0; i < mdb->max; i++) {
+ struct hlist_node *h;
+ struct net_bridge_mdb_entry *mp;
+ struct net_bridge_port_group *p, **pp;
+ struct net_bridge_port *port;
+
+ hlist_for_each_entry_rcu(mp, h, &mdb->mhash[i], hlist[mdb->ver]) {
+ if (idx < s_idx)
+ goto skip;
+
+ nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY);
+ if (nest2 == NULL) {
+ err = -EMSGSIZE;
+ goto out;
+ }
+
+ for (pp = &mp->ports;
+ (p = rcu_dereference(*pp)) != NULL;
+ pp = &p->next) {
+ port = p->port;
+ if (port) {
+ struct br_mdb_entry e;
+ e.ifindex = port->dev->ifindex;
+ e.addr.u.ip4 = p->addr.u.ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+ e.addr.u.ip6 = p->addr.u.ip6;
+#endif
+ e.addr.proto = p->addr.proto;
+ if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) {
+ nla_nest_cancel(skb, nest2);
+ err = -EMSGSIZE;
+ goto out;
+ }
+ }
+ }
+ nla_nest_end(skb, nest2);
+ skip:
+ idx++;
+ }
+ }
+
+out:
+ cb->args[1] = idx;
+ nla_nest_end(skb, nest);
+ return err;
+}
+
+static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct net_device *dev;
+ struct net *net = sock_net(skb->sk);
+ struct nlmsghdr *nlh = NULL;
+ int idx = 0, s_idx;
+
+ s_idx = cb->args[0];
+
+ rcu_read_lock();
+
+ /* In theory this could be wrapped to 0... */
+ cb->seq = net->dev_base_seq + br_mdb_rehash_seq;
+
+ for_each_netdev_rcu(net, dev) {
+ if (dev->priv_flags & IFF_EBRIDGE) {
+ struct br_port_msg *bpm;
+
+ if (idx < s_idx)
+ goto skip;
+
+ nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, RTM_GETMDB,
+ sizeof(*bpm), NLM_F_MULTI);
+ if (nlh == NULL)
+ break;
+
+ bpm = nlmsg_data(nlh);
+ bpm->ifindex = dev->ifindex;
+ if (br_mdb_fill_info(skb, cb, dev) < 0)
+ goto out;
+ if (br_rports_fill_info(skb, cb, dev) < 0)
+ goto out;
+
+ cb->args[1] = 0;
+ nlmsg_end(skb, nlh);
+ skip:
+ idx++;
+ }
+ }
+
+out:
+ if (nlh)
+ nlmsg_end(skb, nlh);
+ rcu_read_unlock();
+ cb->args[0] = idx;
+ return skb->len;
+}
+
+static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
+ struct net_device *dev,
+ struct br_mdb_entry *entry, u32 pid,
+ u32 seq, int type, unsigned int flags)
+{
+ struct nlmsghdr *nlh;
+ struct br_port_msg *bpm;
+ struct nlattr *nest, *nest2;
+
+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
+ if (!nlh)
+ return -EMSGSIZE;
+
+ bpm = nlmsg_data(nlh);
+ bpm->family = AF_BRIDGE;
+ bpm->ifindex = dev->ifindex;
+ nest = nla_nest_start(skb, MDBA_MDB);
+ if (nest == NULL)
+ goto cancel;
+ nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY);
+ if (nest2 == NULL)
+ goto end;
+
+ if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(*entry), entry))
+ goto end;
+
+ nla_nest_end(skb, nest2);
+ nla_nest_end(skb, nest);
+ return nlmsg_end(skb, nlh);
+
+end:
+ nla_nest_end(skb, nest);
+cancel:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
+static inline size_t rtnl_mdb_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct br_port_msg))
+ + nla_total_size(sizeof(struct br_mdb_entry));
+}
+
+static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
+ int type)
+{
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC);
+ if (!skb)
+ goto errout;
+
+ err = nlmsg_populate_mdb_fill(skb, dev, entry, 0, 0, type, NTF_SELF);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto errout;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_MDB, NULL, GFP_ATOMIC);
+ return;
+errout:
+ rtnl_set_sk_err(net, RTNLGRP_MDB, err);
+}
+
+void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
+ struct br_ip *group, int type)
+{
+ struct br_mdb_entry entry;
+
+ entry.ifindex = port->dev->ifindex;
+ entry.addr.proto = group->proto;
+ entry.addr.u.ip4 = group->u.ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+ entry.addr.u.ip6 = group->u.ip6;
+#endif
+ __br_mdb_notify(dev, &entry, type);
+}
+
+static bool is_valid_mdb_entry(struct br_mdb_entry *entry)
+{
+ if (entry->ifindex == 0)
+ return false;
+
+ if (entry->addr.proto == htons(ETH_P_IP)) {
+ if (!ipv4_is_multicast(entry->addr.u.ip4))
+ return false;
+ if (ipv4_is_local_multicast(entry->addr.u.ip4))
+ return false;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (entry->addr.proto == htons(ETH_P_IPV6)) {
+ if (!ipv6_is_transient_multicast(&entry->addr.u.ip6))
+ return false;
+#endif
+ } else
+ return false;
+
+ return true;
+}
+
+static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct net_device **pdev, struct br_mdb_entry **pentry)
+{
+ struct net *net = sock_net(skb->sk);
+ struct br_mdb_entry *entry;
+ struct br_port_msg *bpm;
+ struct nlattr *tb[MDBA_SET_ENTRY_MAX+1];
+ struct net_device *dev;
+ int err;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ err = nlmsg_parse(nlh, sizeof(*bpm), tb, MDBA_SET_ENTRY, NULL);
+ if (err < 0)
+ return err;
+
+ bpm = nlmsg_data(nlh);
+ if (bpm->ifindex == 0) {
+ pr_info("PF_BRIDGE: br_mdb_parse() with invalid ifindex\n");
+ return -EINVAL;
+ }
+
+ dev = __dev_get_by_index(net, bpm->ifindex);
+ if (dev == NULL) {
+ pr_info("PF_BRIDGE: br_mdb_parse() with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ if (!(dev->priv_flags & IFF_EBRIDGE)) {
+ pr_info("PF_BRIDGE: br_mdb_parse() with non-bridge\n");
+ return -EOPNOTSUPP;
+ }
+
+ *pdev = dev;
+
+ if (!tb[MDBA_SET_ENTRY] ||
+ nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) {
+ pr_info("PF_BRIDGE: br_mdb_parse() with invalid attr\n");
+ return -EINVAL;
+ }
+
+ entry = nla_data(tb[MDBA_SET_ENTRY]);
+ if (!is_valid_mdb_entry(entry)) {
+ pr_info("PF_BRIDGE: br_mdb_parse() with invalid entry\n");
+ return -EINVAL;
+ }
+
+ *pentry = entry;
+ return 0;
+}
+
+static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
+ struct br_ip *group)
+{
+ struct net_bridge_mdb_entry *mp;
+ struct net_bridge_port_group *p;
+ struct net_bridge_port_group __rcu **pp;
+ struct net_bridge_mdb_htable *mdb;
+ int err;
+
+ mdb = mlock_dereference(br->mdb, br);
+ mp = br_mdb_ip_get(mdb, group);
+ if (!mp) {
+ mp = br_multicast_new_group(br, port, group);
+ err = PTR_ERR(mp);
+ if (IS_ERR(mp))
+ return err;
+ }
+
+ for (pp = &mp->ports;
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->port == port)
+ return -EEXIST;
+ if ((unsigned long)p->port < (unsigned long)port)
+ break;
+ }
+
+ p = br_multicast_new_port_group(port, group, *pp);
+ if (unlikely(!p))
+ return -ENOMEM;
+ rcu_assign_pointer(*pp, p);
+
+ br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
+ return 0;
+}
+
+static int __br_mdb_add(struct net *net, struct net_bridge *br,
+ struct br_mdb_entry *entry)
+{
+ struct br_ip ip;
+ struct net_device *dev;
+ struct net_bridge_port *p;
+ int ret;
+
+ if (!netif_running(br->dev) || br->multicast_disabled)
+ return -EINVAL;
+
+ dev = __dev_get_by_index(net, entry->ifindex);
+ if (!dev)
+ return -ENODEV;
+
+ p = br_port_get_rtnl(dev);
+ if (!p || p->br != br || p->state == BR_STATE_DISABLED)
+ return -EINVAL;
+
+ ip.proto = entry->addr.proto;
+ if (ip.proto == htons(ETH_P_IP))
+ ip.u.ip4 = entry->addr.u.ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+ else
+ ip.u.ip6 = entry->addr.u.ip6;
+#endif
+
+ spin_lock_bh(&br->multicast_lock);
+ ret = br_mdb_add_group(br, p, &ip);
+ spin_unlock_bh(&br->multicast_lock);
+ return ret;
+}
+
+static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct br_mdb_entry *entry;
+ struct net_device *dev;
+ struct net_bridge *br;
+ int err;
+
+ err = br_mdb_parse(skb, nlh, &dev, &entry);
+ if (err < 0)
+ return err;
+
+ br = netdev_priv(dev);
+
+ err = __br_mdb_add(net, br, entry);
+ if (!err)
+ __br_mdb_notify(dev, entry, RTM_NEWMDB);
+ return err;
+}
+
+static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
+{
+ struct net_bridge_mdb_htable *mdb;
+ struct net_bridge_mdb_entry *mp;
+ struct net_bridge_port_group *p;
+ struct net_bridge_port_group __rcu **pp;
+ struct br_ip ip;
+ int err = -EINVAL;
+
+ if (!netif_running(br->dev) || br->multicast_disabled)
+ return -EINVAL;
+
+ if (timer_pending(&br->multicast_querier_timer))
+ return -EBUSY;
+
+ ip.proto = entry->addr.proto;
+ if (ip.proto == htons(ETH_P_IP))
+ ip.u.ip4 = entry->addr.u.ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+ else
+ ip.u.ip6 = entry->addr.u.ip6;
+#endif
+
+ spin_lock_bh(&br->multicast_lock);
+ mdb = mlock_dereference(br->mdb, br);
+
+ mp = br_mdb_ip_get(mdb, &ip);
+ if (!mp)
+ goto unlock;
+
+ for (pp = &mp->ports;
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (!p->port || p->port->dev->ifindex != entry->ifindex)
+ continue;
+
+ if (p->port->state == BR_STATE_DISABLED)
+ goto unlock;
+
+ rcu_assign_pointer(*pp, p->next);
+ hlist_del_init(&p->mglist);
+ del_timer(&p->timer);
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+ err = 0;
+
+ if (!mp->ports && !mp->mglist &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+ break;
+ }
+
+unlock:
+ spin_unlock_bh(&br->multicast_lock);
+ return err;
+}
+
+static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net_device *dev;
+ struct br_mdb_entry *entry;
+ struct net_bridge *br;
+ int err;
+
+ err = br_mdb_parse(skb, nlh, &dev, &entry);
+ if (err < 0)
+ return err;
+
+ br = netdev_priv(dev);
+
+ err = __br_mdb_del(br, entry);
+ if (!err)
+ __br_mdb_notify(dev, entry, RTM_DELMDB);
+ return err;
+}
+
+void br_mdb_init(void)
+{
+ rtnl_register(PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, NULL);
+ rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL);
+ rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL);
+}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 241743417f49..977c3ee02e65 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -27,25 +27,13 @@
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
#include <net/mld.h>
-#include <net/addrconf.h>
#include <net/ip6_checksum.h>
#endif
#include "br_private.h"
-#define mlock_dereference(X, br) \
- rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
-
static void br_multicast_start_querier(struct net_bridge *br);
-
-#if IS_ENABLED(CONFIG_IPV6)
-static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
-{
- if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr))
- return 1;
- return 0;
-}
-#endif
+unsigned int br_mdb_rehash_seq;
static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
{
@@ -103,8 +91,8 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(
return NULL;
}
-static struct net_bridge_mdb_entry *br_mdb_ip_get(
- struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
+struct net_bridge_mdb_entry *br_mdb_ip_get(struct net_bridge_mdb_htable *mdb,
+ struct br_ip *dst)
{
if (!mdb)
return NULL;
@@ -207,7 +195,7 @@ static int br_mdb_copy(struct net_bridge_mdb_htable *new,
return maxlen > elasticity ? -EINVAL : 0;
}
-static void br_multicast_free_pg(struct rcu_head *head)
+void br_multicast_free_pg(struct rcu_head *head)
{
struct net_bridge_port_group *p =
container_of(head, struct net_bridge_port_group, rcu);
@@ -338,6 +326,7 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
return err;
}
+ br_mdb_rehash_seq++;
call_rcu_bh(&mdb->rcu, br_mdb_free);
out:
@@ -582,9 +571,8 @@ err:
return mp;
}
-static struct net_bridge_mdb_entry *br_multicast_new_group(
- struct net_bridge *br, struct net_bridge_port *port,
- struct br_ip *group)
+struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
+ struct net_bridge_port *port, struct br_ip *group)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -631,6 +619,26 @@ out:
return mp;
}
+struct net_bridge_port_group *br_multicast_new_port_group(
+ struct net_bridge_port *port,
+ struct br_ip *group,
+ struct net_bridge_port_group *next)
+{
+ struct net_bridge_port_group *p;
+
+ p = kzalloc(sizeof(*p), GFP_ATOMIC);
+ if (unlikely(!p))
+ return NULL;
+
+ p->addr = *group;
+ p->port = port;
+ p->next = next;
+ hlist_add_head(&p->mglist, &port->mglist);
+ setup_timer(&p->timer, br_multicast_port_group_expired,
+ (unsigned long)p);
+ return p;
+}
+
static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *group)
@@ -666,19 +674,11 @@ static int br_multicast_add_group(struct net_bridge *br,
break;
}
- p = kzalloc(sizeof(*p), GFP_ATOMIC);
- err = -ENOMEM;
+ p = br_multicast_new_port_group(port, group, *pp);
if (unlikely(!p))
goto err;
-
- p->addr = *group;
- p->port = port;
- p->next = *pp;
- hlist_add_head(&p->mglist, &port->mglist);
- setup_timer(&p->timer, br_multicast_port_group_expired,
- (unsigned long)p);
-
rcu_assign_pointer(*pp, p);
+ br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
found:
mod_timer(&p->timer, now + br->multicast_membership_interval);
@@ -1225,6 +1225,28 @@ static void br_multicast_leave_group(struct net_bridge *br,
if (!mp)
goto out;
+ if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
+ struct net_bridge_port_group __rcu **pp;
+
+ for (pp = &mp->ports;
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->port != port)
+ continue;
+
+ rcu_assign_pointer(*pp, p->next);
+ hlist_del_init(&p->mglist);
+ del_timer(&p->timer);
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+ br_mdb_notify(br->dev, port, group, RTM_DELMDB);
+
+ if (!mp->ports && !mp->mglist &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+ }
+ goto out;
+ }
+
now = jiffies;
time = now + br->multicast_last_member_count *
br->multicast_last_member_interval;
@@ -1584,6 +1606,7 @@ void br_multicast_init(struct net_bridge *br)
br_multicast_querier_expired, (unsigned long)br);
setup_timer(&br->multicast_query_timer, br_multicast_query_expired,
(unsigned long)br);
+ br_mdb_init();
}
void br_multicast_open(struct net_bridge *br)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 093f527276a3..dead9dfe865b 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -20,16 +20,44 @@
#include "br_private.h"
#include "br_private_stp.h"
+static inline size_t br_port_info_size(void)
+{
+ return nla_total_size(1) /* IFLA_BRPORT_STATE */
+ + nla_total_size(2) /* IFLA_BRPORT_PRIORITY */
+ + nla_total_size(4) /* IFLA_BRPORT_COST */
+ + nla_total_size(1) /* IFLA_BRPORT_MODE */
+ + nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ + nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ + 0;
+}
+
static inline size_t br_nlmsg_size(void)
{
return NLMSG_ALIGN(sizeof(struct ifinfomsg))
- + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
- + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
- + nla_total_size(4) /* IFLA_MASTER */
- + nla_total_size(4) /* IFLA_MTU */
- + nla_total_size(4) /* IFLA_LINK */
- + nla_total_size(1) /* IFLA_OPERSTATE */
- + nla_total_size(1); /* IFLA_PROTINFO */
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(4) /* IFLA_MASTER */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size(1) /* IFLA_OPERSTATE */
+ + nla_total_size(br_port_info_size()); /* IFLA_PROTINFO */
+}
+
+static int br_port_fill_attrs(struct sk_buff *skb,
+ const struct net_bridge_port *p)
+{
+ u8 mode = !!(p->flags & BR_HAIRPIN_MODE);
+
+ if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
+ nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
+ nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) ||
+ nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
+ nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
+ nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) ||
+ nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)))
+ return -EMSGSIZE;
+
+ return 0;
}
/*
@@ -67,10 +95,18 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
(dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink &&
- nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
- (event == RTM_NEWLINK &&
- nla_put_u8(skb, IFLA_PROTINFO, port->state)))
+ nla_put_u32(skb, IFLA_LINK, dev->iflink)))
goto nla_put_failure;
+
+ if (event == RTM_NEWLINK) {
+ struct nlattr *nest
+ = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
+
+ if (nest == NULL || br_port_fill_attrs(skb, port) < 0)
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
+ }
+
return nlmsg_end(skb, nlh);
nla_put_failure:
@@ -111,89 +147,134 @@ errout:
/*
* Dump information about all ports, in response to GETLINK
*/
-static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev)
{
- struct net *net = sock_net(skb->sk);
- struct net_device *dev;
- int idx;
-
- idx = 0;
- rcu_read_lock();
- for_each_netdev_rcu(net, dev) {
- struct net_bridge_port *port = br_port_get_rcu(dev);
-
- /* not a bridge port */
- if (!port || idx < cb->args[0])
- goto skip;
-
- if (br_fill_ifinfo(skb, port,
- NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, RTM_NEWLINK,
- NLM_F_MULTI) < 0)
- break;
-skip:
- ++idx;
+ int err = 0;
+ struct net_bridge_port *port = br_port_get_rcu(dev);
+
+ /* not a bridge port */
+ if (!port)
+ goto out;
+
+ err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI);
+out:
+ return err;
+}
+
+static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
+ [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
+ [IFLA_BRPORT_COST] = { .type = NLA_U32 },
+ [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
+ [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
+ [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
+ [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
+};
+
+/* Change the state of the port and notify spanning tree */
+static int br_set_port_state(struct net_bridge_port *p, u8 state)
+{
+ if (state > BR_STATE_BLOCKING)
+ return -EINVAL;
+
+ /* if kernel STP is running, don't allow changes */
+ if (p->br->stp_enabled == BR_KERNEL_STP)
+ return -EBUSY;
+
+ if (!netif_running(p->dev) ||
+ (!netif_carrier_ok(p->dev) && state != BR_STATE_DISABLED))
+ return -ENETDOWN;
+
+ p->state = state;
+ br_log_state(p);
+ br_port_state_selection(p->br);
+ return 0;
+}
+
+/* Set/clear or port flags based on attribute */
+static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
+ int attrtype, unsigned long mask)
+{
+ if (tb[attrtype]) {
+ u8 flag = nla_get_u8(tb[attrtype]);
+ if (flag)
+ p->flags |= mask;
+ else
+ p->flags &= ~mask;
}
- rcu_read_unlock();
- cb->args[0] = idx;
+}
+
+/* Process bridge protocol info on port */
+static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
+{
+ int err;
- return skb->len;
+ br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
+ br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
+ br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
+
+ if (tb[IFLA_BRPORT_COST]) {
+ err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_PRIORITY]) {
+ err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY]));
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_STATE]) {
+ err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE]));
+ if (err)
+ return err;
+ }
+ return 0;
}
-/*
- * Change state of port (ie from forwarding to blocking etc)
- * Used by spanning tree in user space.
- */
-static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+/* Change state and parameters on port. */
+int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
{
- struct net *net = sock_net(skb->sk);
struct ifinfomsg *ifm;
struct nlattr *protinfo;
- struct net_device *dev;
struct net_bridge_port *p;
- u8 new_state;
-
- if (nlmsg_len(nlh) < sizeof(*ifm))
- return -EINVAL;
+ struct nlattr *tb[IFLA_BRPORT_MAX + 1];
+ int err;
ifm = nlmsg_data(nlh);
- if (ifm->ifi_family != AF_BRIDGE)
- return -EPFNOSUPPORT;
protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
- if (!protinfo || nla_len(protinfo) < sizeof(u8))
- return -EINVAL;
-
- new_state = nla_get_u8(protinfo);
- if (new_state > BR_STATE_BLOCKING)
- return -EINVAL;
-
- dev = __dev_get_by_index(net, ifm->ifi_index);
- if (!dev)
- return -ENODEV;
+ if (!protinfo)
+ return 0;
p = br_port_get_rtnl(dev);
if (!p)
return -EINVAL;
- /* if kernel STP is running, don't allow changes */
- if (p->br->stp_enabled == BR_KERNEL_STP)
- return -EBUSY;
-
- if (!netif_running(dev) ||
- (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
- return -ENETDOWN;
-
- p->state = new_state;
- br_log_state(p);
+ if (protinfo->nla_type & NLA_F_NESTED) {
+ err = nla_parse_nested(tb, IFLA_BRPORT_MAX,
+ protinfo, ifla_brport_policy);
+ if (err)
+ return err;
+
+ spin_lock_bh(&p->br->lock);
+ err = br_setport(p, tb);
+ spin_unlock_bh(&p->br->lock);
+ } else {
+ /* Binary compatability with old RSTP */
+ if (nla_len(protinfo) < sizeof(u8))
+ return -EINVAL;
- spin_lock_bh(&p->br->lock);
- br_port_state_selection(p->br);
- spin_unlock_bh(&p->br->lock);
+ spin_lock_bh(&p->br->lock);
+ err = br_set_port_state(p, nla_get_u8(protinfo));
+ spin_unlock_bh(&p->br->lock);
+ }
- br_ifinfo_notify(RTM_NEWLINK, p);
+ if (err == 0)
+ br_ifinfo_notify(RTM_NEWLINK, p);
- return 0;
+ return err;
}
static int br_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -218,29 +299,7 @@ struct rtnl_link_ops br_link_ops __read_mostly = {
int __init br_netlink_init(void)
{
- int err;
-
- err = rtnl_link_register(&br_link_ops);
- if (err < 0)
- goto err1;
-
- err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
- br_dump_ifinfo, NULL);
- if (err)
- goto err2;
- err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
- br_rtm_setlink, NULL, NULL);
- if (err)
- goto err3;
-
- return 0;
-
-err3:
- rtnl_unregister_all(PF_BRIDGE);
-err2:
- rtnl_link_unregister(&br_link_ops);
-err1:
- return err;
+ return rtnl_link_register(&br_link_ops);
}
void __exit br_netlink_fini(void)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 9b278c4ebee1..f21a739a6186 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -135,6 +135,9 @@ struct net_bridge_port
unsigned long flags;
#define BR_HAIRPIN_MODE 0x00000001
+#define BR_BPDU_GUARD 0x00000002
+#define BR_ROOT_BLOCK 0x00000004
+#define BR_MULTICAST_FAST_LEAVE 0x00000008
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
u32 multicast_startup_queries_sent;
@@ -158,7 +161,9 @@ struct net_bridge_port
static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
{
- struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
+ struct net_bridge_port *port =
+ rcu_dereference_rtnl(dev->rx_handler_data);
+
return br_port_exists(dev) ? port : NULL;
}
@@ -288,7 +293,6 @@ struct br_input_skb_cb {
pr_debug("%s: " format, (br)->dev->name, ##args)
extern struct notifier_block br_device_notifier;
-extern const u8 br_group_address[ETH_ALEN];
/* called under bridge lock */
static inline int br_is_root_bridge(const struct net_bridge *br)
@@ -407,6 +411,7 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us
/* br_multicast.c */
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+extern unsigned int br_mdb_rehash_seq;
extern int br_multicast_rcv(struct net_bridge *br,
struct net_bridge_port *port,
struct sk_buff *skb);
@@ -429,6 +434,32 @@ extern int br_multicast_set_port_router(struct net_bridge_port *p,
extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
+extern struct net_bridge_mdb_entry *br_mdb_ip_get(
+ struct net_bridge_mdb_htable *mdb,
+ struct br_ip *dst);
+extern struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
+ struct net_bridge_port *port, struct br_ip *group);
+extern void br_multicast_free_pg(struct rcu_head *head);
+extern struct net_bridge_port_group *br_multicast_new_port_group(
+ struct net_bridge_port *port,
+ struct br_ip *group,
+ struct net_bridge_port_group *next);
+extern void br_mdb_init(void);
+extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
+ struct br_ip *group, int type);
+
+#define mlock_dereference(X, br) \
+ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/addrconf.h>
+static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
+{
+ if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr))
+ return 1;
+ return 0;
+}
+#endif
static inline bool br_multicast_is_router(struct net_bridge *br)
{
@@ -553,6 +584,9 @@ extern struct rtnl_link_ops br_link_ops;
extern int br_netlink_init(void);
extern void br_netlink_fini(void);
extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
+extern int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg);
+extern int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev);
#ifdef CONFIG_SYSFS
/* br_sysfs_if.c */
@@ -566,10 +600,10 @@ extern void br_sysfs_delbr(struct net_device *dev);
#else
-#define br_sysfs_addif(p) (0)
-#define br_sysfs_renameif(p) (0)
-#define br_sysfs_addbr(dev) (0)
-#define br_sysfs_delbr(dev) do { } while(0)
+static inline int br_sysfs_addif(struct net_bridge_port *p) { return 0; }
+static inline int br_sysfs_renameif(struct net_bridge_port *p) { return 0; }
+static inline int br_sysfs_addbr(struct net_device *dev) { return 0; }
+static inline void br_sysfs_delbr(struct net_device *dev) { return; }
#endif /* CONFIG_SYSFS */
#endif
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index af9a12099ba4..b01849a74310 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -100,6 +100,21 @@ static int br_should_become_root_port(const struct net_bridge_port *p,
return 0;
}
+static void br_root_port_block(const struct net_bridge *br,
+ struct net_bridge_port *p)
+{
+
+ br_notice(br, "port %u(%s) tried to become root port (blocked)",
+ (unsigned int) p->port_no, p->dev->name);
+
+ p->state = BR_STATE_LISTENING;
+ br_log_state(p);
+ br_ifinfo_notify(RTM_NEWLINK, p);
+
+ if (br->forward_delay > 0)
+ mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
+}
+
/* called under bridge lock */
static void br_root_selection(struct net_bridge *br)
{
@@ -107,7 +122,12 @@ static void br_root_selection(struct net_bridge *br)
u16 root_port = 0;
list_for_each_entry(p, &br->port_list, list) {
- if (br_should_become_root_port(p, root_port))
+ if (!br_should_become_root_port(p, root_port))
+ continue;
+
+ if (p->flags & BR_ROOT_BLOCK)
+ br_root_port_block(br, p);
+ else
root_port = p->port_no;
}
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index fd30a6022dea..7f884e3fb955 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -170,6 +170,13 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
if (!ether_addr_equal(dest, br->group_addr))
goto out;
+ if (p->flags & BR_BPDU_GUARD) {
+ br_notice(br, "BPDU received on blocked port %u(%s)\n",
+ (unsigned int) p->port_no, p->dev->name);
+ br_stp_disable_port(p);
+ goto out;
+ }
+
buf = skb_pull(skb, 3);
if (buf[0] == BPDU_TYPE_CONFIG) {
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index c5c059333eab..5913a3a0047b 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -14,6 +14,7 @@
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
@@ -36,7 +37,7 @@ static ssize_t store_bridge_parm(struct device *d,
unsigned long val;
int err;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
@@ -132,7 +133,7 @@ static ssize_t store_stp_state(struct device *d,
char *endp;
unsigned long val;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
@@ -165,7 +166,7 @@ static ssize_t store_group_fwd_mask(struct device *d,
char *endp;
unsigned long val;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
@@ -297,23 +298,18 @@ static ssize_t store_group_addr(struct device *d,
const char *buf, size_t len)
{
struct net_bridge *br = to_bridge(d);
- unsigned int new_addr[6];
+ u8 new_addr[6];
int i;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
- if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
+ if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&new_addr[0], &new_addr[1], &new_addr[2],
&new_addr[3], &new_addr[4], &new_addr[5]) != 6)
return -EINVAL;
- /* Must be 01:80:c2:00:00:0X */
- for (i = 0; i < 5; i++)
- if (new_addr[i] != br_group_address[i])
- return -EINVAL;
-
- if (new_addr[5] & ~0xf)
+ if (!is_link_local_ether_addr(new_addr))
return -EINVAL;
if (new_addr[5] == 1 || /* 802.3x Pause address */
@@ -337,7 +333,7 @@ static ssize_t store_flush(struct device *d,
{
struct net_bridge *br = to_bridge(d);
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
br_fdb_flush(br);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 13b36bdc76a7..a1ef1b6e14dc 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -34,6 +34,28 @@ const struct brport_attribute brport_attr_##_name = { \
.store = _store, \
};
+#define BRPORT_ATTR_FLAG(_name, _mask) \
+static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \
+{ \
+ return sprintf(buf, "%d\n", !!(p->flags & _mask)); \
+} \
+static int store_##_name(struct net_bridge_port *p, unsigned long v) \
+{ \
+ unsigned long flags = p->flags; \
+ if (v) \
+ flags |= _mask; \
+ else \
+ flags &= ~_mask; \
+ if (flags != p->flags) { \
+ p->flags = flags; \
+ br_ifinfo_notify(RTM_NEWLINK, p); \
+ } \
+ return 0; \
+} \
+static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR, \
+ show_##_name, store_##_name)
+
+
static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
{
return sprintf(buf, "%d\n", p->path_cost);
@@ -133,21 +155,9 @@ static int store_flush(struct net_bridge_port *p, unsigned long v)
}
static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
-static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
-{
- int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
- return sprintf(buf, "%d\n", hairpin_mode);
-}
-static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
-{
- if (v)
- p->flags |= BR_HAIRPIN_MODE;
- else
- p->flags &= ~BR_HAIRPIN_MODE;
- return 0;
-}
-static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
- show_hairpin_mode, store_hairpin_mode);
+BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE);
+BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);
+BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@@ -162,6 +172,8 @@ static int store_multicast_router(struct net_bridge_port *p,
}
static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
store_multicast_router);
+
+BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
#endif
static const struct brport_attribute *brport_attrs[] = {
@@ -181,8 +193,11 @@ static const struct brport_attribute *brport_attrs[] = {
&brport_attr_hold_timer,
&brport_attr_flush,
&brport_attr_hairpin_mode,
+ &brport_attr_bpdu_guard,
+ &brport_attr_root_block,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&brport_attr_multicast_router,
+ &brport_attr_multicast_fast_leave,
#endif
NULL
};
@@ -209,7 +224,7 @@ static ssize_t brport_store(struct kobject * kobj,
char *endp;
unsigned long val;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c
index fd7cbf5aa895..3ebc8cbc91ff 100644
--- a/net/caif/caif_usb.c
+++ b/net/caif/caif_usb.c
@@ -126,20 +126,16 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
struct net_device *dev = arg;
struct caif_dev_common common;
struct cflayer *layer, *link_support;
- struct usbnet *usbnet = netdev_priv(dev);
- struct usb_device *usbdev = usbnet->udev;
- struct ethtool_drvinfo drvinfo;
+ struct usbnet *usbnet;
+ struct usb_device *usbdev;
- /*
- * Quirks: High-jack ethtool to find if we have a NCM device,
- * and find it's VID/PID.
- */
- if (dev->ethtool_ops == NULL || dev->ethtool_ops->get_drvinfo == NULL)
+ /* Check whether we have a NCM device, and find its VID/PID. */
+ if (!(dev->dev.parent && dev->dev.parent->driver &&
+ strcmp(dev->dev.parent->driver->name, "cdc_ncm") == 0))
return 0;
- dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
- if (strncmp(drvinfo.driver, "cdc_ncm", 7) != 0)
- return 0;
+ usbnet = netdev_priv(dev);
+ usbdev = usbnet->udev;
pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n",
le16_to_cpu(usbdev->descriptor.idVendor),
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 44f270fc2d06..a376ec1ac0a7 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -515,8 +515,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
client_layer : NULL);
}
- if (req != NULL)
- kfree(req);
+ kfree(req);
spin_unlock_bh(&cfctrl->info_list_lock);
}
diff --git a/net/can/gw.c b/net/can/gw.c
index 1f5c9785a262..574dda78eb0f 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -751,6 +751,9 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
struct cgw_job *gwj;
int err = 0;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (nlmsg_len(nlh) < sizeof(*r))
return -EINVAL;
@@ -839,6 +842,9 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct can_can_gw ccgw;
int err = 0;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (nlmsg_len(nlh) < sizeof(*r))
return -EINVAL;
diff --git a/net/can/proc.c b/net/can/proc.c
index 3b6dd3180492..ae566902d2bf 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -397,7 +397,7 @@ static inline void can_rcvlist_sff_proc_show_one(struct seq_file *m,
int i;
int all_empty = 1;
- /* check wether at least one list is non-empty */
+ /* check whether at least one list is non-empty */
for (i = 0; i < 0x800; i++)
if (!hlist_empty(&d->rx_sff[i])) {
all_empty = 0;
diff --git a/net/core/dev.c b/net/core/dev.c
index e5942bf45a6d..d0cbc93fcf32 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -176,8 +176,10 @@
#define PTYPE_HASH_MASK (PTYPE_HASH_SIZE - 1)
static DEFINE_SPINLOCK(ptype_lock);
+static DEFINE_SPINLOCK(offload_lock);
static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
static struct list_head ptype_all __read_mostly; /* Taps */
+static struct list_head offload_base __read_mostly;
/*
* The @dev_base_head list is protected by @dev_base_lock and the rtnl
@@ -201,6 +203,8 @@ static struct list_head ptype_all __read_mostly; /* Taps */
DEFINE_RWLOCK(dev_base_lock);
EXPORT_SYMBOL(dev_base_lock);
+DEFINE_SEQLOCK(devnet_rename_seq);
+
static inline void dev_base_seq_inc(struct net *net)
{
while (++net->dev_base_seq == 0);
@@ -470,6 +474,82 @@ void dev_remove_pack(struct packet_type *pt)
}
EXPORT_SYMBOL(dev_remove_pack);
+
+/**
+ * dev_add_offload - register offload handlers
+ * @po: protocol offload declaration
+ *
+ * Add protocol offload handlers to the networking stack. The passed
+ * &proto_offload is linked into kernel lists and may not be freed until
+ * it has been removed from the kernel lists.
+ *
+ * This call does not sleep therefore it can not
+ * guarantee all CPU's that are in middle of receiving packets
+ * will see the new offload handlers (until the next received packet).
+ */
+void dev_add_offload(struct packet_offload *po)
+{
+ struct list_head *head = &offload_base;
+
+ spin_lock(&offload_lock);
+ list_add_rcu(&po->list, head);
+ spin_unlock(&offload_lock);
+}
+EXPORT_SYMBOL(dev_add_offload);
+
+/**
+ * __dev_remove_offload - remove offload handler
+ * @po: packet offload declaration
+ *
+ * Remove a protocol offload handler that was previously added to the
+ * kernel offload handlers by dev_add_offload(). The passed &offload_type
+ * is removed from the kernel lists and can be freed or reused once this
+ * function returns.
+ *
+ * The packet type might still be in use by receivers
+ * and must not be freed until after all the CPU's have gone
+ * through a quiescent state.
+ */
+void __dev_remove_offload(struct packet_offload *po)
+{
+ struct list_head *head = &offload_base;
+ struct packet_offload *po1;
+
+ spin_lock(&offload_lock);
+
+ list_for_each_entry(po1, head, list) {
+ if (po == po1) {
+ list_del_rcu(&po->list);
+ goto out;
+ }
+ }
+
+ pr_warn("dev_remove_offload: %p not found\n", po);
+out:
+ spin_unlock(&offload_lock);
+}
+EXPORT_SYMBOL(__dev_remove_offload);
+
+/**
+ * dev_remove_offload - remove packet offload handler
+ * @po: packet offload declaration
+ *
+ * Remove a packet offload handler that was previously added to the kernel
+ * offload handlers by dev_add_offload(). The passed &offload_type is
+ * removed from the kernel lists and can be freed or reused once this
+ * function returns.
+ *
+ * This call sleeps to guarantee that no CPU is looking at the packet
+ * type after return.
+ */
+void dev_remove_offload(struct packet_offload *po)
+{
+ __dev_remove_offload(po);
+
+ synchronize_net();
+}
+EXPORT_SYMBOL(dev_remove_offload);
+
/******************************************************************************
Device Boot-time Settings Routines
@@ -1013,22 +1093,31 @@ int dev_change_name(struct net_device *dev, const char *newname)
if (dev->flags & IFF_UP)
return -EBUSY;
- if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+ write_seqlock(&devnet_rename_seq);
+
+ if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
+ write_sequnlock(&devnet_rename_seq);
return 0;
+ }
memcpy(oldname, dev->name, IFNAMSIZ);
err = dev_get_valid_name(net, dev, newname);
- if (err < 0)
+ if (err < 0) {
+ write_sequnlock(&devnet_rename_seq);
return err;
+ }
rollback:
ret = device_rename(&dev->dev, dev->name);
if (ret) {
memcpy(dev->name, oldname, IFNAMSIZ);
+ write_sequnlock(&devnet_rename_seq);
return ret;
}
+ write_sequnlock(&devnet_rename_seq);
+
write_lock_bh(&dev_base_lock);
hlist_del_rcu(&dev->name_hlist);
write_unlock_bh(&dev_base_lock);
@@ -1046,6 +1135,7 @@ rollback:
/* err >= 0 after dev_alloc_name() or stores the first errno */
if (err >= 0) {
err = ret;
+ write_seqlock(&devnet_rename_seq);
memcpy(dev->name, oldname, IFNAMSIZ);
goto rollback;
} else {
@@ -1075,10 +1165,8 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
return -EINVAL;
if (!len) {
- if (dev->ifalias) {
- kfree(dev->ifalias);
- dev->ifalias = NULL;
- }
+ kfree(dev->ifalias);
+ dev->ifalias = NULL;
return 0;
}
@@ -1994,7 +2082,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
- struct packet_type *ptype;
+ struct packet_offload *ptype;
__be16 type = skb->protocol;
int vlan_depth = ETH_HLEN;
int err;
@@ -2023,18 +2111,17 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
}
rcu_read_lock();
- list_for_each_entry_rcu(ptype,
- &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
- if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+ list_for_each_entry_rcu(ptype, &offload_base, list) {
+ if (ptype->type == type && ptype->callbacks.gso_segment) {
if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
- err = ptype->gso_send_check(skb);
+ err = ptype->callbacks.gso_send_check(skb);
segs = ERR_PTR(err);
if (err || skb_gso_ok(skb, features))
break;
__skb_push(skb, (skb->data -
skb_network_header(skb)));
}
- segs = ptype->gso_segment(skb, features);
+ segs = ptype->callbacks.gso_segment(skb, features);
break;
}
}
@@ -2237,6 +2324,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
skb->vlan_tci = 0;
}
+ /* If encapsulation offload request, verify we are testing
+ * hardware encapsulation features instead of standard
+ * features for the netdev
+ */
+ if (skb->encapsulation)
+ features &= dev->hw_enc_features;
+
if (netif_needs_gso(skb, features)) {
if (unlikely(dev_gso_segment(skb, features)))
goto out_kfree_skb;
@@ -2252,8 +2346,12 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
* checksumming here.
*/
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- skb_set_transport_header(skb,
- skb_checksum_start_offset(skb));
+ if (skb->encapsulation)
+ skb_set_inner_transport_header(skb,
+ skb_checksum_start_offset(skb));
+ else
+ skb_set_transport_header(skb,
+ skb_checksum_start_offset(skb));
if (!(features & NETIF_F_ALL_CSUM) &&
skb_checksum_help(skb))
goto out_kfree_skb;
@@ -3446,9 +3544,9 @@ static void flush_backlog(void *arg)
static int napi_gro_complete(struct sk_buff *skb)
{
- struct packet_type *ptype;
+ struct packet_offload *ptype;
__be16 type = skb->protocol;
- struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+ struct list_head *head = &offload_base;
int err = -ENOENT;
BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));
@@ -3460,10 +3558,10 @@ static int napi_gro_complete(struct sk_buff *skb)
rcu_read_lock();
list_for_each_entry_rcu(ptype, head, list) {
- if (ptype->type != type || ptype->dev || !ptype->gro_complete)
+ if (ptype->type != type || !ptype->callbacks.gro_complete)
continue;
- err = ptype->gro_complete(skb);
+ err = ptype->callbacks.gro_complete(skb);
break;
}
rcu_read_unlock();
@@ -3507,12 +3605,34 @@ void napi_gro_flush(struct napi_struct *napi, bool flush_old)
}
EXPORT_SYMBOL(napi_gro_flush);
-enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
+{
+ struct sk_buff *p;
+ unsigned int maclen = skb->dev->hard_header_len;
+
+ for (p = napi->gro_list; p; p = p->next) {
+ unsigned long diffs;
+
+ diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
+ diffs |= p->vlan_tci ^ skb->vlan_tci;
+ if (maclen == ETH_HLEN)
+ diffs |= compare_ether_header(skb_mac_header(p),
+ skb_gro_mac_header(skb));
+ else if (!diffs)
+ diffs = memcmp(skb_mac_header(p),
+ skb_gro_mac_header(skb),
+ maclen);
+ NAPI_GRO_CB(p)->same_flow = !diffs;
+ NAPI_GRO_CB(p)->flush = 0;
+ }
+}
+
+static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
struct sk_buff **pp = NULL;
- struct packet_type *ptype;
+ struct packet_offload *ptype;
__be16 type = skb->protocol;
- struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+ struct list_head *head = &offload_base;
int same_flow;
int mac_len;
enum gro_result ret;
@@ -3523,9 +3643,11 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
if (skb_is_gso(skb) || skb_has_frag_list(skb))
goto normal;
+ gro_list_prepare(napi, skb);
+
rcu_read_lock();
list_for_each_entry_rcu(ptype, head, list) {
- if (ptype->type != type || ptype->dev || !ptype->gro_receive)
+ if (ptype->type != type || !ptype->callbacks.gro_receive)
continue;
skb_set_network_header(skb, skb_gro_offset(skb));
@@ -3535,7 +3657,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
NAPI_GRO_CB(skb)->flush = 0;
NAPI_GRO_CB(skb)->free = 0;
- pp = ptype->gro_receive(&napi->gro_list, skb);
+ pp = ptype->callbacks.gro_receive(&napi->gro_list, skb);
break;
}
rcu_read_unlock();
@@ -3598,34 +3720,9 @@ normal:
ret = GRO_NORMAL;
goto pull;
}
-EXPORT_SYMBOL(dev_gro_receive);
-
-static inline gro_result_t
-__napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
-{
- struct sk_buff *p;
- unsigned int maclen = skb->dev->hard_header_len;
-
- for (p = napi->gro_list; p; p = p->next) {
- unsigned long diffs;
-
- diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
- diffs |= p->vlan_tci ^ skb->vlan_tci;
- if (maclen == ETH_HLEN)
- diffs |= compare_ether_header(skb_mac_header(p),
- skb_gro_mac_header(skb));
- else if (!diffs)
- diffs = memcmp(skb_mac_header(p),
- skb_gro_mac_header(skb),
- maclen);
- NAPI_GRO_CB(p)->same_flow = !diffs;
- NAPI_GRO_CB(p)->flush = 0;
- }
- return dev_gro_receive(napi, skb);
-}
-gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
+static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
{
switch (ret) {
case GRO_NORMAL:
@@ -3651,7 +3748,6 @@ gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
return ret;
}
-EXPORT_SYMBOL(napi_skb_finish);
static void skb_gro_reset_offset(struct sk_buff *skb)
{
@@ -3674,7 +3770,7 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
skb_gro_reset_offset(skb);
- return napi_skb_finish(__napi_gro_receive(napi, skb), skb);
+ return napi_skb_finish(dev_gro_receive(napi, skb), skb);
}
EXPORT_SYMBOL(napi_gro_receive);
@@ -3703,7 +3799,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi)
}
EXPORT_SYMBOL(napi_get_frags);
-gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
+static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
gro_result_t ret)
{
switch (ret) {
@@ -3728,7 +3824,6 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
return ret;
}
-EXPORT_SYMBOL(napi_frags_finish);
static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
{
@@ -3773,7 +3868,7 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
if (!skb)
return GRO_DROP;
- return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb));
+ return napi_frags_finish(napi, skb, dev_gro_receive(napi, skb));
}
EXPORT_SYMBOL(napi_gro_frags);
@@ -4075,6 +4170,7 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
{
struct net_device *dev;
struct ifreq ifr;
+ unsigned seq;
/*
* Fetch the caller's info block.
@@ -4083,6 +4179,8 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
+retry:
+ seq = read_seqbegin(&devnet_rename_seq);
rcu_read_lock();
dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex);
if (!dev) {
@@ -4092,6 +4190,8 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
strcpy(ifr.ifr_name, dev->name);
rcu_read_unlock();
+ if (read_seqretry(&devnet_rename_seq, seq))
+ goto retry;
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
return -EFAULT;
@@ -4884,7 +4984,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
else
dev->mtu = new_mtu;
- if (!err && dev->flags & IFF_UP)
+ if (!err)
call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
return err;
}
@@ -5204,7 +5304,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSIFNAME:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
dev_load(net, ifr.ifr_name);
rtnl_lock();
@@ -5225,16 +5325,25 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
* - require strict serialization.
* - do not return a value
*/
+ case SIOCSIFMAP:
+ case SIOCSIFTXQLEN:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ /* fall through */
+ /*
+ * These ioctl calls:
+ * - require local superuser power.
+ * - require strict serialization.
+ * - do not return a value
+ */
case SIOCSIFFLAGS:
case SIOCSIFMETRIC:
case SIOCSIFMTU:
- case SIOCSIFMAP:
case SIOCSIFHWADDR:
case SIOCSIFSLAVE:
case SIOCADDMULTI:
case SIOCDELMULTI:
case SIOCSIFHWBROADCAST:
- case SIOCSIFTXQLEN:
case SIOCSMIIREG:
case SIOCBONDENSLAVE:
case SIOCBONDRELEASE:
@@ -5243,7 +5352,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCBRADDIF:
case SIOCBRDELIF:
case SIOCSHWTSTAMP:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
/* fall through */
case SIOCBONDSLAVEINFOQUERY:
@@ -6268,7 +6377,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
goto out;
/* Ensure the device has been registrered */
- err = -EINVAL;
if (dev->reg_state != NETREG_REGISTERED)
goto out;
@@ -6323,6 +6431,9 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev_uc_flush(dev);
dev_mc_flush(dev);
+ /* Send a netdev-removed uevent to the old namespace */
+ kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE);
+
/* Actually switch the network namespace */
dev_net_set(dev, net);
@@ -6334,6 +6445,9 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev->iflink = dev->ifindex;
}
+ /* Send a netdev-add uevent to the new namespace */
+ kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
+
/* Fixup kobjects */
err = device_rename(&dev->dev, dev->name);
WARN_ON(err);
@@ -6666,6 +6780,8 @@ static int __init net_dev_init(void)
for (i = 0; i < PTYPE_HASH_SIZE; i++)
INIT_LIST_HEAD(&ptype_base[i]);
+ INIT_LIST_HEAD(&offload_base);
+
if (register_pernet_subsys(&netdev_net_ops))
goto out;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4d64cc2e3fa9..a8705432e4b1 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1460,7 +1460,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_GEEE:
break;
default:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 3d92ebb7fbcf..c23543cba132 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -39,6 +39,7 @@
#include <linux/reciprocal_div.h>
#include <linux/ratelimit.h>
#include <linux/seccomp.h>
+#include <linux/if_vlan.h>
/* No hurry in this branch
*
@@ -341,6 +342,12 @@ load_b:
case BPF_S_ANC_CPU:
A = raw_smp_processor_id();
continue;
+ case BPF_S_ANC_VLAN_TAG:
+ A = vlan_tx_tag_get(skb);
+ continue;
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ A = !!vlan_tx_tag_present(skb);
+ continue;
case BPF_S_ANC_NLATTR: {
struct nlattr *nla;
@@ -600,6 +607,8 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
ANCILLARY(RXHASH);
ANCILLARY(CPU);
ANCILLARY(ALU_XOR_X);
+ ANCILLARY(VLAN_TAG);
+ ANCILLARY(VLAN_TAG_PRESENT);
}
}
ftest->code = code;
@@ -751,3 +760,133 @@ int sk_detach_filter(struct sock *sk)
return ret;
}
EXPORT_SYMBOL_GPL(sk_detach_filter);
+
+static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
+{
+ static const u16 decodes[] = {
+ [BPF_S_ALU_ADD_K] = BPF_ALU|BPF_ADD|BPF_K,
+ [BPF_S_ALU_ADD_X] = BPF_ALU|BPF_ADD|BPF_X,
+ [BPF_S_ALU_SUB_K] = BPF_ALU|BPF_SUB|BPF_K,
+ [BPF_S_ALU_SUB_X] = BPF_ALU|BPF_SUB|BPF_X,
+ [BPF_S_ALU_MUL_K] = BPF_ALU|BPF_MUL|BPF_K,
+ [BPF_S_ALU_MUL_X] = BPF_ALU|BPF_MUL|BPF_X,
+ [BPF_S_ALU_DIV_X] = BPF_ALU|BPF_DIV|BPF_X,
+ [BPF_S_ALU_MOD_K] = BPF_ALU|BPF_MOD|BPF_K,
+ [BPF_S_ALU_MOD_X] = BPF_ALU|BPF_MOD|BPF_X,
+ [BPF_S_ALU_AND_K] = BPF_ALU|BPF_AND|BPF_K,
+ [BPF_S_ALU_AND_X] = BPF_ALU|BPF_AND|BPF_X,
+ [BPF_S_ALU_OR_K] = BPF_ALU|BPF_OR|BPF_K,
+ [BPF_S_ALU_OR_X] = BPF_ALU|BPF_OR|BPF_X,
+ [BPF_S_ALU_XOR_K] = BPF_ALU|BPF_XOR|BPF_K,
+ [BPF_S_ALU_XOR_X] = BPF_ALU|BPF_XOR|BPF_X,
+ [BPF_S_ALU_LSH_K] = BPF_ALU|BPF_LSH|BPF_K,
+ [BPF_S_ALU_LSH_X] = BPF_ALU|BPF_LSH|BPF_X,
+ [BPF_S_ALU_RSH_K] = BPF_ALU|BPF_RSH|BPF_K,
+ [BPF_S_ALU_RSH_X] = BPF_ALU|BPF_RSH|BPF_X,
+ [BPF_S_ALU_NEG] = BPF_ALU|BPF_NEG,
+ [BPF_S_LD_W_ABS] = BPF_LD|BPF_W|BPF_ABS,
+ [BPF_S_LD_H_ABS] = BPF_LD|BPF_H|BPF_ABS,
+ [BPF_S_LD_B_ABS] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_PROTOCOL] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_PKTTYPE] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_IFINDEX] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_NLATTR] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_NLATTR_NEST] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_MARK] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_QUEUE] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_HATYPE] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_RXHASH] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_CPU] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_ALU_XOR_X] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
+ [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN,
+ [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND,
+ [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND,
+ [BPF_S_LD_B_IND] = BPF_LD|BPF_B|BPF_IND,
+ [BPF_S_LD_IMM] = BPF_LD|BPF_IMM,
+ [BPF_S_LDX_W_LEN] = BPF_LDX|BPF_W|BPF_LEN,
+ [BPF_S_LDX_B_MSH] = BPF_LDX|BPF_B|BPF_MSH,
+ [BPF_S_LDX_IMM] = BPF_LDX|BPF_IMM,
+ [BPF_S_MISC_TAX] = BPF_MISC|BPF_TAX,
+ [BPF_S_MISC_TXA] = BPF_MISC|BPF_TXA,
+ [BPF_S_RET_K] = BPF_RET|BPF_K,
+ [BPF_S_RET_A] = BPF_RET|BPF_A,
+ [BPF_S_ALU_DIV_K] = BPF_ALU|BPF_DIV|BPF_K,
+ [BPF_S_LD_MEM] = BPF_LD|BPF_MEM,
+ [BPF_S_LDX_MEM] = BPF_LDX|BPF_MEM,
+ [BPF_S_ST] = BPF_ST,
+ [BPF_S_STX] = BPF_STX,
+ [BPF_S_JMP_JA] = BPF_JMP|BPF_JA,
+ [BPF_S_JMP_JEQ_K] = BPF_JMP|BPF_JEQ|BPF_K,
+ [BPF_S_JMP_JEQ_X] = BPF_JMP|BPF_JEQ|BPF_X,
+ [BPF_S_JMP_JGE_K] = BPF_JMP|BPF_JGE|BPF_K,
+ [BPF_S_JMP_JGE_X] = BPF_JMP|BPF_JGE|BPF_X,
+ [BPF_S_JMP_JGT_K] = BPF_JMP|BPF_JGT|BPF_K,
+ [BPF_S_JMP_JGT_X] = BPF_JMP|BPF_JGT|BPF_X,
+ [BPF_S_JMP_JSET_K] = BPF_JMP|BPF_JSET|BPF_K,
+ [BPF_S_JMP_JSET_X] = BPF_JMP|BPF_JSET|BPF_X,
+ };
+ u16 code;
+
+ code = filt->code;
+
+ to->code = decodes[code];
+ to->jt = filt->jt;
+ to->jf = filt->jf;
+
+ if (code == BPF_S_ALU_DIV_K) {
+ /*
+ * When loaded this rule user gave us X, which was
+ * translated into R = r(X). Now we calculate the
+ * RR = r(R) and report it back. If next time this
+ * value is loaded and RRR = r(RR) is calculated
+ * then the R == RRR will be true.
+ *
+ * One exception. X == 1 translates into R == 0 and
+ * we can't calculate RR out of it with r().
+ */
+
+ if (filt->k == 0)
+ to->k = 1;
+ else
+ to->k = reciprocal_value(filt->k);
+
+ BUG_ON(reciprocal_value(to->k) != filt->k);
+ } else
+ to->k = filt->k;
+}
+
+int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
+{
+ struct sk_filter *filter;
+ int i, ret;
+
+ lock_sock(sk);
+ filter = rcu_dereference_protected(sk->sk_filter,
+ sock_owned_by_user(sk));
+ ret = 0;
+ if (!filter)
+ goto out;
+ ret = filter->len;
+ if (!len)
+ goto out;
+ ret = -EINVAL;
+ if (len < filter->len)
+ goto out;
+
+ ret = -EFAULT;
+ for (i = 0; i < filter->len; i++) {
+ struct sock_filter fb;
+
+ sk_decode_filter(&filter->insns[i], &fb);
+ if (copy_to_user(&ubuf[i], &fb, sizeof(fb)))
+ goto out;
+ }
+
+ ret = filter->len;
+out:
+ release_sock(sk);
+ return ret;
+}
diff --git a/net/core/flow.c b/net/core/flow.c
index e318c7e98042..b0901ee5a002 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -327,11 +327,9 @@ static void flow_cache_flush_tasklet(unsigned long data)
static void flow_cache_flush_per_cpu(void *data)
{
struct flow_flush_info *info = data;
- int cpu;
struct tasklet_struct *tasklet;
- cpu = smp_processor_id();
- tasklet = &per_cpu_ptr(info->cache->percpu, cpu)->flush_tasklet;
+ tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
tasklet->data = (unsigned long)info;
tasklet_schedule(tasklet);
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 22571488730a..c815f285e5ab 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1787,8 +1787,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
/* approximative value for deprecated QUEUE_LEN (in packets) */
nla_put_u32(skb, NDTPA_QUEUE_LEN,
- DIV_ROUND_UP(parms->queue_len_bytes,
- SKB_TRUESIZE(ETH_FRAME_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) ||
@@ -2770,6 +2769,8 @@ EXPORT_SYMBOL(neigh_app_ns);
#endif /* CONFIG_ARPD */
#ifdef CONFIG_SYSCTL
+static int zero;
+static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
size_t *lenp, loff_t *ppos)
@@ -2777,9 +2778,13 @@ static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
int size, ret;
ctl_table tmp = *ctl;
+ tmp.extra1 = &zero;
+ tmp.extra2 = &unres_qlen_max;
tmp.data = &size;
- size = DIV_ROUND_UP(*(int *)ctl->data, SKB_TRUESIZE(ETH_FRAME_LEN));
- ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
+
+ size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+
if (write && !ret)
*(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
return ret;
@@ -2865,7 +2870,8 @@ static struct neigh_sysctl_table {
.procname = "unres_qlen_bytes",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .extra1 = &zero,
+ .proc_handler = proc_dointvec_minmax,
},
[NEIGH_VAR_PROXY_QLEN] = {
.procname = "proxy_qlen",
@@ -2987,6 +2993,10 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
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;
+
snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
p_name, dev_name_source);
t->sysctl_header =
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 017a8bacfb27..334efd5d67a9 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -18,11 +18,9 @@
#include <net/sock.h>
#include <net/net_namespace.h>
#include <linux/rtnetlink.h>
-#include <linux/wireless.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/jiffies.h>
-#include <net/wext.h>
#include "net-sysfs.h"
@@ -73,11 +71,12 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len,
int (*set)(struct net_device *, unsigned long))
{
- struct net_device *net = to_net_dev(dev);
+ struct net_device *netdev = to_net_dev(dev);
+ struct net *net = dev_net(netdev);
unsigned long new;
int ret = -EINVAL;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
ret = kstrtoul(buf, 0, &new);
@@ -87,8 +86,8 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
if (!rtnl_trylock())
return restart_syscall();
- if (dev_isalive(net)) {
- if ((ret = (*set)(net, new)) == 0)
+ if (dev_isalive(netdev)) {
+ if ((ret = (*set)(netdev, new)) == 0)
ret = len;
}
rtnl_unlock();
@@ -264,6 +263,9 @@ static ssize_t store_tx_queue_len(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
return netdev_store(dev, attr, buf, len, change_tx_queue_len);
}
@@ -271,10 +273,11 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
{
struct net_device *netdev = to_net_dev(dev);
+ struct net *net = dev_net(netdev);
size_t count = len;
ssize_t ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
/* ignore trailing newline */
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 42f1e1c7514f..6456439cbbd9 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -13,6 +13,7 @@
#include <linux/proc_fs.h>
#include <linux/file.h>
#include <linux/export.h>
+#include <linux/user_namespace.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops,
/*
* setup_net runs the initializers for the network namespace object.
*/
-static __net_init int setup_net(struct net *net)
+static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
{
/* Must be called with net_mutex held */
const struct pernet_operations *ops, *saved_ops;
@@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net)
atomic_set(&net->count, 1);
atomic_set(&net->passive, 1);
net->dev_base_seq = 1;
+ net->user_ns = user_ns;
#ifdef NETNS_REFCNT_DEBUG
atomic_set(&net->use_count, 0);
@@ -232,7 +234,8 @@ void net_drop_ns(void *p)
net_free(ns);
}
-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+struct net *copy_net_ns(unsigned long flags,
+ struct user_namespace *user_ns, struct net *old_net)
{
struct net *net;
int rv;
@@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
net = net_alloc();
if (!net)
return ERR_PTR(-ENOMEM);
+
+ get_user_ns(user_ns);
+
mutex_lock(&net_mutex);
- rv = setup_net(net);
+ rv = setup_net(net, user_ns);
if (rv == 0) {
rtnl_lock();
list_add_tail_rcu(&net->list, &net_namespace_list);
@@ -252,6 +258,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
}
mutex_unlock(&net_mutex);
if (rv < 0) {
+ put_user_ns(user_ns);
net_drop_ns(net);
return ERR_PTR(rv);
}
@@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work)
/* Finally it is safe to free my network namespace structure */
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
list_del_init(&net->exit_list);
+ put_user_ns(net->user_ns);
net_drop_ns(net);
}
}
@@ -347,13 +355,6 @@ struct net *get_net_ns_by_fd(int fd)
}
#else
-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
-{
- if (flags & CLONE_NEWNET)
- return ERR_PTR(-EINVAL);
- return old_net;
-}
-
struct net *get_net_ns_by_fd(int fd)
{
return ERR_PTR(-EINVAL);
@@ -402,7 +403,7 @@ static int __init net_ns_init(void)
rcu_assign_pointer(init_net.gen, ng);
mutex_lock(&net_mutex);
- if (setup_net(&init_net))
+ if (setup_net(&init_net, &init_user_ns))
panic("Could not setup the initial network namespace");
rtnl_lock();
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 77a0388fc3be..3151acf5ec13 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -674,7 +674,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
if ((delim = strchr(cur, '@')) == NULL)
goto parse_failed;
*delim = 0;
- np->local_port = simple_strtol(cur, NULL, 10);
+ if (kstrtou16(cur, 10, &np->local_port))
+ goto parse_failed;
cur = delim;
}
cur++;
@@ -705,7 +706,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
*delim = 0;
if (*cur == ' ' || *cur == '\t')
np_info(np, "warning: whitespace is not allowed\n");
- np->remote_port = simple_strtol(cur, NULL, 10);
+ if (kstrtou16(cur, 10, &np->remote_port))
+ goto parse_failed;
cur = delim;
}
cur++;
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index bde53da9cd86..5e67defe2cb0 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -223,7 +223,7 @@ static int update_netprio(const void *v, struct file *file, unsigned n)
return 0;
}
-void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+static void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
{
struct task_struct *p;
void *v;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index d1dc14c2aac4..b29dacf900f9 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -419,20 +419,6 @@ struct pktgen_thread {
#define REMOVE 1
#define FIND 0
-static inline ktime_t ktime_now(void)
-{
- struct timespec ts;
- ktime_get_ts(&ts);
-
- return timespec_to_ktime(ts);
-}
-
-/* This works even if 32 bit because of careful byte order choice */
-static inline int ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
-{
- return cmp1.tv64 < cmp2.tv64;
-}
-
static const char version[] =
"Packet Generator for packet performance testing. "
"Version: " VERSION "\n";
@@ -675,7 +661,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
seq_puts(seq, "\n");
/* not really stopped, more like last-running-at */
- stopped = pkt_dev->running ? ktime_now() : pkt_dev->stopped_at;
+ stopped = pkt_dev->running ? ktime_get() : pkt_dev->stopped_at;
idle = pkt_dev->idle_acc;
do_div(idle, NSEC_PER_USEC);
@@ -2141,12 +2127,12 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
return;
}
- start_time = ktime_now();
+ start_time = ktime_get();
if (remaining < 100000) {
/* for small delays (<100us), just loop until limit is reached */
do {
- end_time = ktime_now();
- } while (ktime_lt(end_time, spin_until));
+ end_time = ktime_get();
+ } while (ktime_compare(end_time, spin_until) < 0);
} else {
/* see do_nanosleep */
hrtimer_init_sleeper(&t, current);
@@ -2162,7 +2148,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
hrtimer_cancel(&t.timer);
} while (t.task && pkt_dev->running && !signal_pending(current));
__set_current_state(TASK_RUNNING);
- end_time = ktime_now();
+ end_time = ktime_get();
}
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
@@ -2427,11 +2413,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
}
} else { /* IPV6 * */
- if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
- pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
- pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
- pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ;
- else {
+ if (!ipv6_addr_any(&pkt_dev->min_in6_daddr)) {
int i;
/* Only random destinations yet */
@@ -2916,8 +2898,7 @@ static void pktgen_run(struct pktgen_thread *t)
pktgen_clear_counters(pkt_dev);
pkt_dev->running = 1; /* Cranke yeself! */
pkt_dev->skb = NULL;
- pkt_dev->started_at =
- pkt_dev->next_tx = ktime_now();
+ pkt_dev->started_at = pkt_dev->next_tx = ktime_get();
set_pkt_overhead(pkt_dev);
@@ -3076,7 +3057,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
kfree_skb(pkt_dev->skb);
pkt_dev->skb = NULL;
- pkt_dev->stopped_at = ktime_now();
+ pkt_dev->stopped_at = ktime_get();
pkt_dev->running = 0;
show_results(pkt_dev, nr_frags);
@@ -3095,7 +3076,7 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t)
continue;
if (best == NULL)
best = pkt_dev;
- else if (ktime_lt(pkt_dev->next_tx, best->next_tx))
+ else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0)
best = pkt_dev;
}
if_unlock(t);
@@ -3180,14 +3161,14 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
static void pktgen_resched(struct pktgen_dev *pkt_dev)
{
- ktime_t idle_start = ktime_now();
+ ktime_t idle_start = ktime_get();
schedule();
- pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
+ pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
}
static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
{
- ktime_t idle_start = ktime_now();
+ ktime_t idle_start = ktime_get();
while (atomic_read(&(pkt_dev->skb->users)) != 1) {
if (signal_pending(current))
@@ -3198,7 +3179,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
else
cpu_relax();
}
- pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
+ pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
}
static void pktgen_xmit(struct pktgen_dev *pkt_dev)
@@ -3220,7 +3201,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
* "never transmit"
*/
if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
- pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
+ pkt_dev->next_tx = ktime_add_ns(ktime_get(), ULONG_MAX);
return;
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fad649ae4dec..1868625af25e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -128,7 +128,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
if (tab == NULL || tab[msgindex].doit == NULL)
tab = rtnl_msg_handlers[PF_UNSPEC];
- return tab ? tab[msgindex].doit : NULL;
+ return tab[msgindex].doit;
}
static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
@@ -143,7 +143,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
if (tab == NULL || tab[msgindex].dumpit == NULL)
tab = rtnl_msg_handlers[PF_UNSPEC];
- return tab ? tab[msgindex].dumpit : NULL;
+ return tab[msgindex].dumpit;
}
static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
@@ -158,7 +158,7 @@ static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
if (tab == NULL || tab[msgindex].calcit == NULL)
tab = rtnl_msg_handlers[PF_UNSPEC];
- return tab ? tab[msgindex].calcit : NULL;
+ return tab[msgindex].calcit;
}
/**
@@ -1316,6 +1316,10 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
err = PTR_ERR(net);
goto errout;
}
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+ err = -EPERM;
+ goto errout;
+ }
err = dev_change_net_namespace(dev, net, ifname);
put_net(net);
if (err)
@@ -1638,7 +1642,7 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
}
EXPORT_SYMBOL(rtnl_configure_link);
-struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+struct net_device *rtnl_create_link(struct net *net,
char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[])
{
int err;
@@ -1836,7 +1840,7 @@ replay:
if (IS_ERR(dest_net))
return PTR_ERR(dest_net);
- dev = rtnl_create_link(net, dest_net, ifname, ops, tb);
+ dev = rtnl_create_link(dest_net, ifname, ops, tb);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out;
@@ -2057,6 +2061,9 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
u8 *addr;
int err;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
if (err < 0)
return err;
@@ -2123,6 +2130,9 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
int err = -EINVAL;
__u8 *addr;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (nlmsg_len(nlh) < sizeof(*ndm))
return -EINVAL;
@@ -2253,6 +2263,211 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
+int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ struct net_device *dev, u16 mode)
+{
+ struct nlmsghdr *nlh;
+ struct ifinfomsg *ifm;
+ struct nlattr *br_afspec;
+ u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+
+ nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ ifm = nlmsg_data(nlh);
+ ifm->ifi_family = AF_BRIDGE;
+ ifm->__ifi_pad = 0;
+ ifm->ifi_type = dev->type;
+ ifm->ifi_index = dev->ifindex;
+ ifm->ifi_flags = dev_get_flags(dev);
+ ifm->ifi_change = 0;
+
+
+ if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
+ nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
+ nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
+ (dev->master &&
+ nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+ (dev->addr_len &&
+ nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
+ (dev->ifindex != dev->iflink &&
+ nla_put_u32(skb, IFLA_LINK, dev->iflink)))
+ goto nla_put_failure;
+
+ br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
+ if (!br_afspec)
+ goto nla_put_failure;
+
+ if (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF) ||
+ nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) {
+ nla_nest_cancel(skb, br_afspec);
+ goto nla_put_failure;
+ }
+ nla_nest_end(skb, br_afspec);
+
+ return nlmsg_end(skb, nlh);
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+EXPORT_SYMBOL(ndo_dflt_bridge_getlink);
+
+static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+ int idx = 0;
+ u32 portid = NETLINK_CB(cb->skb).portid;
+ u32 seq = cb->nlh->nlmsg_seq;
+
+ rcu_read_lock();
+ for_each_netdev_rcu(net, dev) {
+ const struct net_device_ops *ops = dev->netdev_ops;
+ struct net_device *master = dev->master;
+
+ if (master && master->netdev_ops->ndo_bridge_getlink) {
+ if (idx >= cb->args[0] &&
+ master->netdev_ops->ndo_bridge_getlink(
+ skb, portid, seq, dev) < 0)
+ break;
+ idx++;
+ }
+
+ if (ops->ndo_bridge_getlink) {
+ if (idx >= cb->args[0] &&
+ ops->ndo_bridge_getlink(skb, portid, seq, dev) < 0)
+ break;
+ idx++;
+ }
+ }
+ rcu_read_unlock();
+ cb->args[0] = idx;
+
+ return skb->len;
+}
+
+static inline size_t bridge_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(sizeof(u32)) /* IFLA_MASTER */
+ + nla_total_size(sizeof(u32)) /* IFLA_MTU */
+ + nla_total_size(sizeof(u32)) /* IFLA_LINK */
+ + nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */
+ + nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */
+ + nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */
+ + nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */
+ + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
+}
+
+static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
+{
+ struct net *net = dev_net(dev);
+ struct net_device *master = dev->master;
+ struct sk_buff *skb;
+ int err = -EOPNOTSUPP;
+
+ skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC);
+ if (!skb) {
+ err = -ENOMEM;
+ goto errout;
+ }
+
+ if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
+ master && master->netdev_ops->ndo_bridge_getlink) {
+ err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+ if (err < 0)
+ goto errout;
+ }
+
+ if ((flags & BRIDGE_FLAGS_SELF) &&
+ dev->netdev_ops->ndo_bridge_getlink) {
+ err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+ if (err < 0)
+ goto errout;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+ return 0;
+errout:
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ rtnl_set_sk_err(net, RTNLGRP_LINK, err);
+ return err;
+}
+
+static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
+ void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct ifinfomsg *ifm;
+ struct net_device *dev;
+ struct nlattr *br_spec, *attr = NULL;
+ int rem, err = -EOPNOTSUPP;
+ u16 oflags, flags = 0;
+ bool have_flags = false;
+
+ if (nlmsg_len(nlh) < sizeof(*ifm))
+ return -EINVAL;
+
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifi_family != AF_BRIDGE)
+ return -EPFNOSUPPORT;
+
+ dev = __dev_get_by_index(net, ifm->ifi_index);
+ if (!dev) {
+ pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+ if (br_spec) {
+ nla_for_each_nested(attr, br_spec, rem) {
+ if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+ have_flags = true;
+ flags = nla_get_u16(attr);
+ break;
+ }
+ }
+ }
+
+ oflags = flags;
+
+ if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
+ if (!dev->master ||
+ !dev->master->netdev_ops->ndo_bridge_setlink) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
+ if (err)
+ goto out;
+
+ flags &= ~BRIDGE_FLAGS_MASTER;
+ }
+
+ if ((flags & BRIDGE_FLAGS_SELF)) {
+ if (!dev->netdev_ops->ndo_bridge_setlink)
+ err = -EOPNOTSUPP;
+ else
+ err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
+
+ if (!err)
+ flags &= ~BRIDGE_FLAGS_SELF;
+ }
+
+ if (have_flags)
+ memcpy(nla_data(attr), &flags, sizeof(flags));
+ /* Generate event to notify upper layer of bridge change */
+ if (!err)
+ err = rtnl_bridge_notify(dev, oflags);
+out:
+ return err;
+}
+
/* Protected by RTNL sempahore. */
static struct rtattr **rta_buf;
static int rtattr_max;
@@ -2283,7 +2498,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
sz_idx = type>>2;
kind = type&3;
- if (kind != 2 && !capable(CAP_NET_ADMIN))
+ if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
@@ -2434,5 +2649,8 @@ void __init rtnetlink_init(void)
rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL);
rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL);
rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL);
+
+ rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL);
+ rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL);
}
diff --git a/net/core/scm.c b/net/core/scm.c
index ab570841a532..57fb1ee6649f 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -51,11 +51,11 @@ static __inline__ int scm_check_creds(struct ucred *creds)
if (!uid_valid(uid) || !gid_valid(gid))
return -EINVAL;
- if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
+ if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) &&
((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||
- uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) &&
+ uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||
- gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) {
+ gid_eq(gid, cred->sgid)) || nsown_capable(CAP_SETGID))) {
return 0;
}
return -EPERM;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3f0636cd76cd..3ab989b0de42 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -519,7 +519,7 @@ static void skb_release_data(struct sk_buff *skb)
uarg = skb_shinfo(skb)->destructor_arg;
if (uarg->callback)
- uarg->callback(uarg);
+ uarg->callback(uarg, true);
}
if (skb_has_frag_list(skb))
@@ -635,6 +635,26 @@ void kfree_skb(struct sk_buff *skb)
EXPORT_SYMBOL(kfree_skb);
/**
+ * skb_tx_error - report an sk_buff xmit error
+ * @skb: buffer that triggered an error
+ *
+ * Report xmit error if a device callback is tracking this skb.
+ * skb must be freed afterwards.
+ */
+void skb_tx_error(struct sk_buff *skb)
+{
+ if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+ struct ubuf_info *uarg;
+
+ uarg = skb_shinfo(skb)->destructor_arg;
+ if (uarg->callback)
+ uarg->callback(uarg, false);
+ skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
+ }
+}
+EXPORT_SYMBOL(skb_tx_error);
+
+/**
* consume_skb - free an skbuff
* @skb: buffer to free
*
@@ -662,11 +682,14 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->transport_header = old->transport_header;
new->network_header = old->network_header;
new->mac_header = old->mac_header;
+ new->inner_transport_header = old->inner_transport_header;
+ new->inner_network_header = old->inner_transport_header;
skb_dst_copy(new, old);
new->rxhash = old->rxhash;
new->ooo_okay = old->ooo_okay;
new->l4_rxhash = old->l4_rxhash;
new->no_fcs = old->no_fcs;
+ new->encapsulation = old->encapsulation;
#ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp);
#endif
@@ -797,7 +820,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
for (i = 0; i < num_frags; i++)
skb_frag_unref(skb, i);
- uarg->callback(uarg);
+ uarg->callback(uarg, false);
/* skb frags point to kernel buffers */
for (i = num_frags - 1; i >= 0; i--) {
@@ -872,6 +895,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->network_header += offset;
if (skb_mac_header_was_set(new))
new->mac_header += offset;
+ new->inner_transport_header += offset;
+ new->inner_network_header += offset;
#endif
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
@@ -1069,6 +1094,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
skb->network_header += off;
if (skb_mac_header_was_set(skb))
skb->mac_header += off;
+ skb->inner_transport_header += off;
+ skb->inner_network_header += off;
/* Only adjust this if it actually is csum_start rather than csum */
if (skb->ip_summed == CHECKSUM_PARTIAL)
skb->csum_start += nhead;
@@ -1168,6 +1195,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
n->network_header += off;
if (skb_mac_header_was_set(skb))
n->mac_header += off;
+ n->inner_transport_header += off;
+ n->inner_network_header += off;
#endif
return n;
@@ -2999,7 +3028,6 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
memcpy(skb_mac_header(nskb), skb_mac_header(p),
p->data - skb_mac_header(p));
- *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
skb_shinfo(nskb)->frag_list = p;
skb_shinfo(nskb)->gso_size = pinfo->gso_size;
pinfo->gso_size = 0;
diff --git a/net/core/sock.c b/net/core/sock.c
index 8a146cfcc366..a692ef49c9bb 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -505,7 +505,8 @@ struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
}
EXPORT_SYMBOL(sk_dst_check);
-static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
+static int sock_setbindtodevice(struct sock *sk, char __user *optval,
+ int optlen)
{
int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES
@@ -515,7 +516,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
/* Sorry... */
ret = -EPERM;
- if (!capable(CAP_NET_RAW))
+ if (!ns_capable(net->user_ns, CAP_NET_RAW))
goto out;
ret = -EINVAL;
@@ -562,6 +563,59 @@ out:
return ret;
}
+static int sock_getbindtodevice(struct sock *sk, char __user *optval,
+ int __user *optlen, int len)
+{
+ int ret = -ENOPROTOOPT;
+#ifdef CONFIG_NETDEVICES
+ struct net *net = sock_net(sk);
+ struct net_device *dev;
+ char devname[IFNAMSIZ];
+ unsigned seq;
+
+ if (sk->sk_bound_dev_if == 0) {
+ len = 0;
+ goto zero;
+ }
+
+ ret = -EINVAL;
+ if (len < IFNAMSIZ)
+ goto out;
+
+retry:
+ seq = read_seqbegin(&devnet_rename_seq);
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+ ret = -ENODEV;
+ if (!dev) {
+ rcu_read_unlock();
+ goto out;
+ }
+
+ strcpy(devname, dev->name);
+ rcu_read_unlock();
+ if (read_seqretry(&devnet_rename_seq, seq))
+ goto retry;
+
+ len = strlen(devname) + 1;
+
+ ret = -EFAULT;
+ if (copy_to_user(optval, devname, len))
+ goto out;
+
+zero:
+ ret = -EFAULT;
+ if (put_user(len, optlen))
+ goto out;
+
+ ret = 0;
+
+out:
+#endif
+
+ return ret;
+}
+
static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
{
if (valbool)
@@ -589,7 +643,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
*/
if (optname == SO_BINDTODEVICE)
- return sock_bindtodevice(sk, optval, optlen);
+ return sock_setbindtodevice(sk, optval, optlen);
if (optlen < sizeof(int))
return -EINVAL;
@@ -696,7 +750,8 @@ set_rcvbuf:
break;
case SO_PRIORITY:
- if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN))
+ if ((val >= 0 && val <= 6) ||
+ ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
sk->sk_priority = val;
else
ret = -EPERM;
@@ -813,7 +868,7 @@ set_rcvbuf:
clear_bit(SOCK_PASSSEC, &sock->flags);
break;
case SO_MARK:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
ret = -EPERM;
else
sk->sk_mark = val;
@@ -1074,6 +1129,17 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
case SO_NOFCS:
v.val = sock_flag(sk, SOCK_NOFCS);
break;
+
+ case SO_BINDTODEVICE:
+ return sock_getbindtodevice(sk, optval, optlen, len);
+
+ case SO_GET_FILTER:
+ len = sk_get_filter(sk, (struct sock_filter __user *)optval, len);
+ if (len < 0)
+ return len;
+
+ goto lenout;
+
default:
return -ENOPROTOOPT;
}
@@ -1214,13 +1280,11 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
#ifdef CONFIG_CGROUPS
#if IS_ENABLED(CONFIG_NET_CLS_CGROUP)
-void sock_update_classid(struct sock *sk)
+void sock_update_classid(struct sock *sk, struct task_struct *task)
{
u32 classid;
- rcu_read_lock(); /* doing current task, which cannot vanish. */
- classid = task_cls_classid(current);
- rcu_read_unlock();
+ classid = task_cls_classid(task);
if (classid != sk->sk_classid)
sk->sk_classid = classid;
}
@@ -1263,7 +1327,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
sock_net_set(sk, get_net(net));
atomic_set(&sk->sk_wmem_alloc, 1);
- sock_update_classid(sk);
+ sock_update_classid(sk, current);
sock_update_netprioidx(sk, current);
}
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index a7c36845b123..d1b08045a9df 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -216,6 +216,11 @@ static __net_init int sysctl_core_net_init(struct net *net)
goto err_dup;
tbl[0].data = &net->core.sysctl_somaxconn;
+
+ /* Don't export any sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns) {
+ tbl[0].procname = NULL;
+ }
}
net->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 70989e672304..1b588e23cf80 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1662,8 +1662,8 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct nlmsghdr *reply_nlh = NULL;
const struct reply_func *fn;
- if (!net_eq(net, &init_net))
- return -EINVAL;
+ if ((nlh->nlmsg_type == RTM_SETDCB) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
dcbnl_rtnl_policy);
@@ -1681,7 +1681,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!tb[DCB_ATTR_IFNAME])
return -EINVAL;
- netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
+ netdev = dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME]));
if (!netdev)
return -ENODEV;
@@ -1705,7 +1705,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
nlmsg_end(reply_skb, reply_nlh);
- ret = rtnl_unicast(reply_skb, &init_net, portid);
+ ret = rtnl_unicast(reply_skb, net, portid);
out:
dev_put(netdev);
return ret;
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index ea850ce35d4a..662071b249cc 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -174,8 +174,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
* To protect against Request floods, increment retrans
* counter (backoff, monitored by dccp_response_timer).
*/
- req->retrans++;
- req->rsk_ops->rtx_syn_ack(sk, req, NULL);
+ inet_rtx_syn_ack(sk, req);
}
/* Network Duplicate, discard packet */
return NULL;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 7b7e561412d3..e47ba9fc4a0e 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -573,6 +573,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct dn_ifaddr __rcu **ifap;
int err = -EINVAL;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!net_eq(net, &init_net))
goto errout;
@@ -614,6 +617,9 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct dn_ifaddr *ifa;
int err;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!net_eq(net, &init_net))
return -EINVAL;
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 102d6106a942..e36614eccc04 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -520,6 +520,9 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
struct rtattr **rta = arg;
struct rtmsg *r = NLMSG_DATA(nlh);
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!net_eq(net, &init_net))
return -EINVAL;
@@ -540,6 +543,9 @@ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
struct rtattr **rta = arg;
struct rtmsg *r = NLMSG_DATA(nlh);
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!net_eq(net, &init_net))
return -EINVAL;
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 274791cd7a35..f5eede1d6cb8 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -1,26 +1,24 @@
+config HAVE_NET_DSA
+ def_bool y
+ depends on NETDEVICES && !S390
+
+# Drivers must select NET_DSA and the appropriate tagging format
+
config NET_DSA
- tristate "Distributed Switch Architecture support"
- default n
- depends on EXPERIMENTAL && NETDEVICES && !S390
+ tristate
+ depends on HAVE_NET_DSA
select PHYLIB
- ---help---
- This allows you to use hardware switch chips that use
- the Distributed Switch Architecture.
-
if NET_DSA
# tagging formats
config NET_DSA_TAG_DSA
bool
- default n
config NET_DSA_TAG_EDSA
bool
- default n
config NET_DSA_TAG_TRAILER
bool
- default n
endif
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 6d42c17af96b..f651da60f161 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1047,7 +1047,8 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
goto error;
}
- if (skb->len <= IEEE802154_MTU) {
+ /* Send directly if less than the MTU minus the 2 checksum bytes. */
+ if (skb->len <= IEEE802154_MTU - IEEE802154_MFR_SIZE) {
err = dev_queue_xmit(skb);
goto out;
}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 766c59658563..24b384b7903e 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -346,7 +346,8 @@ lookup_protocol:
}
err = -EPERM;
- if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+ if (sock->type == SOCK_RAW && !kern &&
+ !ns_capable(net->user_ns, CAP_NET_RAW))
goto out_rcu_unlock;
err = -EAFNOSUPPORT;
@@ -473,6 +474,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
struct sock *sk = sock->sk;
struct inet_sock *inet = inet_sk(sk);
+ struct net *net = sock_net(sk);
unsigned short snum;
int chk_addr_ret;
int err;
@@ -496,7 +498,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out;
}
- chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+ chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
/* Not specified by any standard per-se, however it breaks too
* many applications when removed. It is unfortunate since
@@ -516,7 +518,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
snum = ntohs(addr->sin_port);
err = -EACCES;
- if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ if (snum && snum < PROT_SOCK &&
+ !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
goto out;
/* We keep a pair of addresses. rcv_saddr is the one
@@ -1251,7 +1254,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);
static int inet_gso_send_check(struct sk_buff *skb)
{
- const struct net_protocol *ops;
+ const struct net_offload *ops;
const struct iphdr *iph;
int proto;
int ihl;
@@ -1275,9 +1278,9 @@ static int inet_gso_send_check(struct sk_buff *skb)
err = -EPROTONOSUPPORT;
rcu_read_lock();
- ops = rcu_dereference(inet_protos[proto]);
- if (likely(ops && ops->gso_send_check))
- err = ops->gso_send_check(skb);
+ ops = rcu_dereference(inet_offloads[proto]);
+ if (likely(ops && ops->callbacks.gso_send_check))
+ err = ops->callbacks.gso_send_check(skb);
rcu_read_unlock();
out:
@@ -1288,7 +1291,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
- const struct net_protocol *ops;
+ const struct net_offload *ops;
struct iphdr *iph;
int proto;
int ihl;
@@ -1325,9 +1328,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
segs = ERR_PTR(-EPROTONOSUPPORT);
rcu_read_lock();
- ops = rcu_dereference(inet_protos[proto]);
- if (likely(ops && ops->gso_segment))
- segs = ops->gso_segment(skb, features);
+ ops = rcu_dereference(inet_offloads[proto]);
+ if (likely(ops && ops->callbacks.gso_segment))
+ segs = ops->callbacks.gso_segment(skb, features);
rcu_read_unlock();
if (!segs || IS_ERR(segs))
@@ -1356,7 +1359,7 @@ out:
static struct sk_buff **inet_gro_receive(struct sk_buff **head,
struct sk_buff *skb)
{
- const struct net_protocol *ops;
+ const struct net_offload *ops;
struct sk_buff **pp = NULL;
struct sk_buff *p;
const struct iphdr *iph;
@@ -1378,8 +1381,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
proto = iph->protocol;
rcu_read_lock();
- ops = rcu_dereference(inet_protos[proto]);
- if (!ops || !ops->gro_receive)
+ ops = rcu_dereference(inet_offloads[proto]);
+ if (!ops || !ops->callbacks.gro_receive)
goto out_unlock;
if (*(u8 *)iph != 0x45)
@@ -1420,7 +1423,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
skb_gro_pull(skb, sizeof(*iph));
skb_set_transport_header(skb, skb_gro_offset(skb));
- pp = ops->gro_receive(head, skb);
+ pp = ops->callbacks.gro_receive(head, skb);
out_unlock:
rcu_read_unlock();
@@ -1435,7 +1438,7 @@ static int inet_gro_complete(struct sk_buff *skb)
{
__be16 newlen = htons(skb->len - skb_network_offset(skb));
struct iphdr *iph = ip_hdr(skb);
- const struct net_protocol *ops;
+ const struct net_offload *ops;
int proto = iph->protocol;
int err = -ENOSYS;
@@ -1443,11 +1446,11 @@ static int inet_gro_complete(struct sk_buff *skb)
iph->tot_len = newlen;
rcu_read_lock();
- ops = rcu_dereference(inet_protos[proto]);
- if (WARN_ON(!ops || !ops->gro_complete))
+ ops = rcu_dereference(inet_offloads[proto]);
+ if (WARN_ON(!ops || !ops->callbacks.gro_complete))
goto out_unlock;
- err = ops->gro_complete(skb);
+ err = ops->callbacks.gro_complete(skb);
out_unlock:
rcu_read_unlock();
@@ -1558,23 +1561,33 @@ static const struct net_protocol tcp_protocol = {
.early_demux = tcp_v4_early_demux,
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
- .gso_send_check = tcp_v4_gso_send_check,
- .gso_segment = tcp_tso_segment,
- .gro_receive = tcp4_gro_receive,
- .gro_complete = tcp4_gro_complete,
.no_policy = 1,
.netns_ok = 1,
};
+static const struct net_offload tcp_offload = {
+ .callbacks = {
+ .gso_send_check = tcp_v4_gso_send_check,
+ .gso_segment = tcp_tso_segment,
+ .gro_receive = tcp4_gro_receive,
+ .gro_complete = tcp4_gro_complete,
+ },
+};
+
static const struct net_protocol udp_protocol = {
.handler = udp_rcv,
.err_handler = udp_err,
- .gso_send_check = udp4_ufo_send_check,
- .gso_segment = udp4_ufo_fragment,
.no_policy = 1,
.netns_ok = 1,
};
+static const struct net_offload udp_offload = {
+ .callbacks = {
+ .gso_send_check = udp4_ufo_send_check,
+ .gso_segment = udp4_ufo_fragment,
+ },
+};
+
static const struct net_protocol icmp_protocol = {
.handler = icmp_rcv,
.err_handler = ping_err,
@@ -1659,13 +1672,35 @@ static int ipv4_proc_init(void);
* IP protocol layer initialiser
*/
+static struct packet_offload ip_packet_offload __read_mostly = {
+ .type = cpu_to_be16(ETH_P_IP),
+ .callbacks = {
+ .gso_send_check = inet_gso_send_check,
+ .gso_segment = inet_gso_segment,
+ .gro_receive = inet_gro_receive,
+ .gro_complete = inet_gro_complete,
+ },
+};
+
+static int __init ipv4_offload_init(void)
+{
+ /*
+ * Add offloads
+ */
+ if (inet_add_offload(&udp_offload, IPPROTO_UDP) < 0)
+ pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
+ if (inet_add_offload(&tcp_offload, IPPROTO_TCP) < 0)
+ pr_crit("%s: Cannot add TCP protocol offlaod\n", __func__);
+
+ dev_add_offload(&ip_packet_offload);
+ return 0;
+}
+
+fs_initcall(ipv4_offload_init);
+
static struct packet_type ip_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_IP),
.func = ip_rcv,
- .gso_send_check = inet_gso_send_check,
- .gso_segment = inet_gso_segment,
- .gro_receive = inet_gro_receive,
- .gro_complete = inet_gro_complete,
};
static int __init inet_init(void)
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 47800459e4cb..ce6fbdfd40b8 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1161,7 +1161,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
switch (cmd) {
case SIOCDARP:
case SIOCSARP:
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
case SIOCGARP:
err = copy_from_user(&r, arg, sizeof(struct arpreq));
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 2a6abc163ed2..cc06a47f1216 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -55,6 +55,7 @@
#include <linux/sysctl.h>
#endif
#include <linux/kmod.h>
+#include <linux/netconf.h>
#include <net/arp.h>
#include <net/ip.h>
@@ -723,7 +724,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCSIFFLAGS:
ret = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto out;
break;
case SIOCSIFADDR: /* Set interface address (and family) */
@@ -731,7 +732,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
ret = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto out;
ret = -EINVAL;
if (sin->sin_family != AF_INET)
@@ -1442,6 +1443,155 @@ static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla)
return 0;
}
+static int inet_netconf_msgsize_devconf(int type)
+{
+ int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
+ + nla_total_size(4); /* NETCONFA_IFINDEX */
+
+ /* type -1 is used for ALL */
+ if (type == -1 || type == NETCONFA_FORWARDING)
+ size += nla_total_size(4);
+ if (type == -1 || type == NETCONFA_RP_FILTER)
+ size += nla_total_size(4);
+ if (type == -1 || type == NETCONFA_MC_FORWARDING)
+ size += nla_total_size(4);
+
+ return size;
+}
+
+static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+ struct ipv4_devconf *devconf, u32 portid,
+ u32 seq, int event, unsigned int flags,
+ int type)
+{
+ struct nlmsghdr *nlh;
+ struct netconfmsg *ncm;
+
+ nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
+ flags);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ ncm = nlmsg_data(nlh);
+ ncm->ncm_family = AF_INET;
+
+ if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
+ goto nla_put_failure;
+
+ /* type -1 is used for ALL */
+ if ((type == -1 || type == NETCONFA_FORWARDING) &&
+ nla_put_s32(skb, NETCONFA_FORWARDING,
+ IPV4_DEVCONF(*devconf, FORWARDING)) < 0)
+ goto nla_put_failure;
+ if ((type == -1 || type == NETCONFA_RP_FILTER) &&
+ nla_put_s32(skb, NETCONFA_RP_FILTER,
+ IPV4_DEVCONF(*devconf, RP_FILTER)) < 0)
+ goto nla_put_failure;
+ if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+ nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+ IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
+ goto nla_put_failure;
+
+ return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
+void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+ struct ipv4_devconf *devconf)
+{
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(inet_netconf_msgsize_devconf(type), GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
+ RTM_NEWNETCONF, 0, type);
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV4_NETCONF, NULL, GFP_ATOMIC);
+ return;
+errout:
+ if (err < 0)
+ rtnl_set_sk_err(net, RTNLGRP_IPV4_NETCONF, err);
+}
+
+static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
+ [NETCONFA_IFINDEX] = { .len = sizeof(int) },
+ [NETCONFA_FORWARDING] = { .len = sizeof(int) },
+ [NETCONFA_RP_FILTER] = { .len = sizeof(int) },
+};
+
+static int inet_netconf_get_devconf(struct sk_buff *in_skb,
+ struct nlmsghdr *nlh,
+ void *arg)
+{
+ struct net *net = sock_net(in_skb->sk);
+ struct nlattr *tb[NETCONFA_MAX+1];
+ struct netconfmsg *ncm;
+ struct sk_buff *skb;
+ struct ipv4_devconf *devconf;
+ struct in_device *in_dev;
+ struct net_device *dev;
+ int ifindex;
+ int err;
+
+ err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
+ devconf_ipv4_policy);
+ if (err < 0)
+ goto errout;
+
+ err = EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+ ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+ switch (ifindex) {
+ case NETCONFA_IFINDEX_ALL:
+ devconf = net->ipv4.devconf_all;
+ break;
+ case NETCONFA_IFINDEX_DEFAULT:
+ devconf = net->ipv4.devconf_dflt;
+ break;
+ default:
+ dev = __dev_get_by_index(net, ifindex);
+ if (dev == NULL)
+ goto errout;
+ in_dev = __in_dev_get_rtnl(dev);
+ if (in_dev == NULL)
+ goto errout;
+ devconf = &in_dev->cnf;
+ break;
+ }
+
+ err = -ENOBUFS;
+ skb = nlmsg_new(inet_netconf_msgsize_devconf(-1), GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = inet_netconf_fill_devconf(skb, ifindex, devconf,
+ NETLINK_CB(in_skb).portid,
+ nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
+ -1);
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+ err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
+errout:
+ return err;
+}
+
#ifdef CONFIG_SYSCTL
static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -1467,6 +1617,12 @@ static void inet_forward_change(struct net *net)
IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
+ inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv4.devconf_all);
+ inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ NETCONFA_IFINDEX_DEFAULT,
+ net->ipv4.devconf_dflt);
for_each_netdev(net, dev) {
struct in_device *in_dev;
@@ -1474,8 +1630,11 @@ static void inet_forward_change(struct net *net)
dev_disable_lro(dev);
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
- if (in_dev)
+ if (in_dev) {
IN_DEV_CONF_SET(in_dev, FORWARDING, on);
+ inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ dev->ifindex, &in_dev->cnf);
+ }
rcu_read_unlock();
}
}
@@ -1501,6 +1660,23 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
if ((new_value == 0) && (old_value != 0))
rt_cache_flush(net);
+ if (i == IPV4_DEVCONF_RP_FILTER - 1 &&
+ new_value != old_value) {
+ int ifindex;
+
+ if (cnf == net->ipv4.devconf_dflt)
+ ifindex = NETCONFA_IFINDEX_DEFAULT;
+ else if (cnf == net->ipv4.devconf_all)
+ ifindex = NETCONFA_IFINDEX_ALL;
+ else {
+ struct in_device *idev =
+ container_of(cnf, struct in_device,
+ cnf);
+ ifindex = idev->dev->ifindex;
+ }
+ inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER,
+ ifindex, cnf);
+ }
}
return ret;
@@ -1527,15 +1703,23 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
}
if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
inet_forward_change(net);
- } else if (*valp) {
+ } else {
struct ipv4_devconf *cnf = ctl->extra1;
struct in_device *idev =
container_of(cnf, struct in_device, cnf);
- dev_disable_lro(idev->dev);
+ if (*valp)
+ dev_disable_lro(idev->dev);
+ inet_netconf_notify_devconf(net,
+ NETCONFA_FORWARDING,
+ idev->dev->ifindex,
+ cnf);
}
rtnl_unlock();
rt_cache_flush(net);
- }
+ } else
+ inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ NETCONFA_IFINDEX_DEFAULT,
+ net->ipv4.devconf_dflt);
}
return ret;
@@ -1809,5 +1993,7 @@ void __init devinet_init(void)
rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, NULL);
rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
+ rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
+ NULL, NULL);
}
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 825c608826de..5cd75e2dab2c 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -488,7 +488,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
switch (cmd) {
case SIOCADDRT: /* Add a route */
case SIOCDELRT: /* Delete a route */
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&rt, arg, sizeof(rt)))
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 71b125cd5db1..4797a800faf8 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -803,7 +803,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
unsigned int bytes;
if (!new_size)
- new_size = 1;
+ new_size = 16;
bytes = new_size * sizeof(struct hlist_head *);
new_info_hash = fib_info_hash_alloc(bytes);
new_laddrhash = fib_info_hash_alloc(bytes);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d34ce2972c8f..2026542d6836 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -521,21 +521,31 @@ static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
int *expire, int *resend)
{
if (!rskq_defer_accept) {
- *expire = req->retrans >= thresh;
+ *expire = req->num_timeout >= thresh;
*resend = 1;
return;
}
- *expire = req->retrans >= thresh &&
- (!inet_rsk(req)->acked || req->retrans >= max_retries);
+ *expire = req->num_timeout >= thresh &&
+ (!inet_rsk(req)->acked || req->num_timeout >= max_retries);
/*
* Do not resend while waiting for data after ACK,
* start to resend on end of deferring period to give
* last chance for data or ACK to create established socket.
*/
*resend = !inet_rsk(req)->acked ||
- req->retrans >= rskq_defer_accept - 1;
+ req->num_timeout >= rskq_defer_accept - 1;
}
+int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
+{
+ int err = req->rsk_ops->rtx_syn_ack(parent, req, NULL);
+
+ if (!err)
+ req->num_retrans++;
+ return err;
+}
+EXPORT_SYMBOL(inet_rtx_syn_ack);
+
void inet_csk_reqsk_queue_prune(struct sock *parent,
const unsigned long interval,
const unsigned long timeout,
@@ -599,13 +609,14 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
req->rsk_ops->syn_ack_timeout(parent, req);
if (!expire &&
(!resend ||
- !req->rsk_ops->rtx_syn_ack(parent, req, NULL) ||
+ !inet_rtx_syn_ack(parent, req) ||
inet_rsk(req)->acked)) {
unsigned long timeo;
- if (req->retrans++ == 0)
+ if (req->num_timeout++ == 0)
lopt->qlen_young--;
- timeo = min((timeout << req->retrans), max_rto);
+ timeo = min(timeout << req->num_timeout,
+ max_rto);
req->expires = now + timeo;
reqp = &req->dl_next;
continue;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index e23e16dc501d..7afa2c3c788f 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -109,6 +109,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
r->id.idiag_src[0] = inet->inet_rcv_saddr;
r->id.idiag_dst[0] = inet->inet_daddr;
+ if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
+ goto errout;
+
/* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
* hence this needs to be included regardless of socket family.
*/
@@ -716,7 +719,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
r->idiag_family = sk->sk_family;
r->idiag_state = TCP_SYN_RECV;
r->idiag_timer = 1;
- r->idiag_retrans = req->retrans;
+ r->idiag_retrans = req->num_retrans;
r->id.idiag_if = sk->sk_bound_dev_if;
sock_diag_save_cookie(req, r->id.idiag_cookie);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7880af970208..fa3ae8148710 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -237,12 +237,14 @@ struct sock *__inet_lookup_established(struct net *net,
rcu_read_lock();
begin:
sk_nulls_for_each_rcu(sk, node, &head->chain) {
- if (INET_MATCH(sk, net, hash, acookie,
- saddr, daddr, ports, dif)) {
+ if (sk->sk_hash != hash)
+ continue;
+ if (likely(INET_MATCH(sk, net, acookie,
+ saddr, daddr, ports, dif))) {
if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
goto begintw;
- if (unlikely(!INET_MATCH(sk, net, hash, acookie,
- saddr, daddr, ports, dif))) {
+ if (unlikely(!INET_MATCH(sk, net, acookie,
+ saddr, daddr, ports, dif))) {
sock_put(sk);
goto begin;
}
@@ -260,14 +262,18 @@ begin:
begintw:
/* Must check for a TIME_WAIT'er before going to listener hash. */
sk_nulls_for_each_rcu(sk, node, &head->twchain) {
- if (INET_TW_MATCH(sk, net, hash, acookie,
- saddr, daddr, ports, dif)) {
+ if (sk->sk_hash != hash)
+ continue;
+ if (likely(INET_TW_MATCH(sk, net, acookie,
+ saddr, daddr, ports,
+ dif))) {
if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
sk = NULL;
goto out;
}
- if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie,
- saddr, daddr, ports, dif))) {
+ if (unlikely(!INET_TW_MATCH(sk, net, acookie,
+ saddr, daddr, ports,
+ dif))) {
sock_put(sk);
goto begintw;
}
@@ -314,10 +320,12 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
/* Check TIME-WAIT sockets first. */
sk_nulls_for_each(sk2, node, &head->twchain) {
- tw = inet_twsk(sk2);
+ if (sk2->sk_hash != hash)
+ continue;
- if (INET_TW_MATCH(sk2, net, hash, acookie,
- saddr, daddr, ports, dif)) {
+ if (likely(INET_TW_MATCH(sk2, net, acookie,
+ saddr, daddr, ports, dif))) {
+ tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
goto unique;
else
@@ -328,8 +336,10 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
/* And established part... */
sk_nulls_for_each(sk2, node, &head->chain) {
- if (INET_MATCH(sk2, net, hash, acookie,
- saddr, daddr, ports, dif))
+ if (sk2->sk_hash != hash)
+ continue;
+ if (likely(INET_MATCH(sk2, net, acookie,
+ saddr, daddr, ports, dif)))
goto not_unique;
}
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 8d5cc75dac88..eb9d63a570cd 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -801,6 +801,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net)
table[0].data = &net->ipv4.frags.high_thresh;
table[1].data = &net->ipv4.frags.low_thresh;
table[2].data = &net->ipv4.frags.timeout;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
}
hdr = register_net_sysctl(net, "net/ipv4", table);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 7240f8e2dd45..a85ae2f7a21c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -164,21 +164,6 @@ struct ipgre_net {
#define tunnels_r tunnels[2]
#define tunnels_l tunnels[1]
#define tunnels_wc tunnels[0]
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
- for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- struct u64_stats_sync syncp;
-};
static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot)
@@ -250,7 +235,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
ARPHRD_ETHER : ARPHRD_IPGRE;
int score, cand_score = 4;
- for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
if (local != t->parms.iph.saddr ||
remote != t->parms.iph.daddr ||
!(t->dev->flags & IFF_UP))
@@ -277,7 +262,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) {
if (remote != t->parms.iph.daddr ||
!(t->dev->flags & IFF_UP))
continue;
@@ -303,7 +288,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) {
if ((local != t->parms.iph.saddr &&
(local != t->parms.iph.daddr ||
!ipv4_is_multicast(local))) ||
@@ -331,7 +316,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) {
if (t->parms.i_key != key ||
!(t->dev->flags & IFF_UP))
continue;
@@ -753,7 +738,6 @@ drop:
static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct pcpu_tstats *tstats;
const struct iphdr *old_iph = ip_hdr(skb);
const struct iphdr *tiph;
struct flowi4 fl4;
@@ -977,9 +961,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
}
}
- nf_reset(skb);
- tstats = this_cpu_ptr(dev->tstats);
- __IPTUNNEL_XMIT(tstats, &dev->stats);
+ iptunnel_xmit(skb, dev);
return NETDEV_TX_OK;
#if IS_ENABLED(CONFIG_IPV6)
@@ -1082,7 +1064,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -1157,7 +1139,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
if (dev == ign->fb_tunnel_dev) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 1dc01f9793d5..f6289bf6f332 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -409,7 +409,7 @@ int ip_options_compile(struct net *net,
optptr[2] += 8;
break;
default:
- if (!skb && !capable(CAP_NET_RAW)) {
+ if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
pp_ptr = optptr + 3;
goto error;
}
@@ -445,7 +445,7 @@ int ip_options_compile(struct net *net,
opt->router_alert = optptr - iph;
break;
case IPOPT_CIPSO:
- if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
+ if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
pp_ptr = optptr;
goto error;
}
@@ -458,7 +458,7 @@ int ip_options_compile(struct net *net,
case IPOPT_SEC:
case IPOPT_SID:
default:
- if (!skb && !capable(CAP_NET_RAW)) {
+ if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
pp_ptr = optptr;
goto error;
}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 6537a408a4fb..3e98ed2bff55 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -595,6 +595,10 @@ slow_path_clean:
}
slow_path:
+ /* for offloaded checksums cleanup checksum before fragmentation */
+ if ((skb->ip_summed == CHECKSUM_PARTIAL) && skb_checksum_help(skb))
+ goto fail;
+
left = skb->len - hlen; /* Space per frame */
ptr = hlen; /* Where to start from */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 14bbfcf717ac..3c9d20880283 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -989,13 +989,14 @@ mc_msf_out:
case IP_IPSEC_POLICY:
case IP_XFRM_POLICY:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
break;
err = xfrm_user_policy(sk, optname, optval, optlen);
break;
case IP_TRANSPARENT:
- if (!!val && !capable(CAP_NET_RAW) && !capable(CAP_NET_ADMIN)) {
+ if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
+ !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
err = -EPERM;
break;
}
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 858fddf6482a..c3a4233c0ac2 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -66,20 +66,6 @@ static void vti_tunnel_setup(struct net_device *dev);
static void vti_dev_free(struct net_device *dev);
static int vti_tunnel_bind_dev(struct net_device *dev);
-/* Locking : hash tables are protected by RCU and RTNL */
-
-#define for_each_ip_tunnel_rcu(start) \
- for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- struct u64_stats_sync syncp;
-};
-
#define VTI_XMIT(stats1, stats2) do { \
int err; \
int pkt_len = skb->len; \
@@ -142,19 +128,19 @@ static struct ip_tunnel *vti_tunnel_lookup(struct net *net,
struct ip_tunnel *t;
struct vti_net *ipn = net_generic(net, vti_net_id);
- for_each_ip_tunnel_rcu(ipn->tunnels_r_l[h0 ^ h1])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
if (local == t->parms.iph.saddr &&
remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
return t;
- for_each_ip_tunnel_rcu(ipn->tunnels_r[h0])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
return t;
- for_each_ip_tunnel_rcu(ipn->tunnels_l[h1])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
return t;
- for_each_ip_tunnel_rcu(ipn->tunnels_wc[0])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_wc[0])
if (t && (t->dev->flags&IFF_UP))
return t;
return NULL;
@@ -502,7 +488,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -567,7 +553,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
if (dev == ipn->fb_tunnel_dev) {
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 798358b10717..d763701cff1b 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1500,8 +1500,10 @@ static int __init ip_auto_config(void)
* Clue in the operator.
*/
pr_info("IP-Config: Complete:\n");
- pr_info(" device=%s, addr=%pI4, mask=%pI4, gw=%pI4\n",
- ic_dev->name, &ic_myaddr, &ic_netmask, &ic_gateway);
+
+ pr_info(" device=%s, hwaddr=%*phC, ipaddr=%pI4, mask=%pI4, gw=%pI4\n",
+ ic_dev->name, ic_dev->addr_len, ic_dev->dev_addr,
+ &ic_myaddr, &ic_netmask, &ic_gateway);
pr_info(" host=%s, domain=%s, nis-domain=%s\n",
utsname()->nodename, ic_domain, utsname()->domainname);
pr_info(" bootserver=%pI4, rootserver=%pI4, rootpath=%s",
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index e15b45297c09..191fc24a745a 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -138,22 +138,7 @@ struct ipip_net {
static int ipip_tunnel_init(struct net_device *dev);
static void ipip_tunnel_setup(struct net_device *dev);
static void ipip_dev_free(struct net_device *dev);
-
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
- for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- struct u64_stats_sync syncp;
-};
+static struct rtnl_link_ops ipip_link_ops __read_mostly;
static struct rtnl_link_stats64 *ipip_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot)
@@ -197,16 +182,16 @@ static struct ip_tunnel *ipip_tunnel_lookup(struct net *net,
struct ip_tunnel *t;
struct ipip_net *ipn = net_generic(net, ipip_net_id);
- for_each_ip_tunnel_rcu(ipn->tunnels_r_l[h0 ^ h1])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
if (local == t->parms.iph.saddr &&
remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
return t;
- for_each_ip_tunnel_rcu(ipn->tunnels_r[h0])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
return t;
- for_each_ip_tunnel_rcu(ipn->tunnels_l[h1])
+ for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
return t;
@@ -264,6 +249,32 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
rcu_assign_pointer(*tp, t);
}
+static int ipip_tunnel_create(struct net_device *dev)
+{
+ struct ip_tunnel *t = netdev_priv(dev);
+ struct net *net = dev_net(dev);
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ int err;
+
+ err = ipip_tunnel_init(dev);
+ if (err < 0)
+ goto out;
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out;
+
+ strcpy(t->parms.name, dev->name);
+ dev->rtnl_link_ops = &ipip_link_ops;
+
+ dev_hold(dev);
+ ipip_tunnel_link(ipn, t);
+ return 0;
+
+out:
+ return err;
+}
+
static struct ip_tunnel *ipip_tunnel_locate(struct net *net,
struct ip_tunnel_parm *parms, int create)
{
@@ -298,16 +309,9 @@ static struct ip_tunnel *ipip_tunnel_locate(struct net *net,
nt = netdev_priv(dev);
nt->parms = *parms;
- if (ipip_tunnel_init(dev) < 0)
+ if (ipip_tunnel_create(dev) < 0)
goto failed_free;
- if (register_netdevice(dev) < 0)
- goto failed_free;
-
- strcpy(nt->parms.name, dev->name);
-
- dev_hold(dev);
- ipip_tunnel_link(ipn, nt);
return nt;
failed_free:
@@ -463,7 +467,6 @@ drop:
static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct pcpu_tstats *tstats;
const struct iphdr *tiph = &tunnel->parms.iph;
u8 tos = tunnel->parms.iph.tos;
__be16 df = tiph->frag_off;
@@ -479,6 +482,10 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->protocol != htons(ETH_P_IP))
goto tx_error;
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ skb_checksum_help(skb))
+ goto tx_error;
+
if (tos & 1)
tos = old_iph->tos;
@@ -586,9 +593,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
if ((iph->ttl = tiph->ttl) == 0)
iph->ttl = old_iph->ttl;
- nf_reset(skb);
- tstats = this_cpu_ptr(dev->tstats);
- __IPTUNNEL_XMIT(tstats, &dev->stats);
+ iptunnel_xmit(skb, dev);
return NETDEV_TX_OK;
tx_error_icmp:
@@ -635,6 +640,28 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
dev->iflink = tunnel->parms.link;
}
+static void ipip_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
+{
+ struct net *net = dev_net(t->dev);
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+ ipip_tunnel_unlink(ipn, t);
+ synchronize_net();
+ t->parms.iph.saddr = p->iph.saddr;
+ t->parms.iph.daddr = p->iph.daddr;
+ memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
+ memcpy(t->dev->broadcast, &p->iph.daddr, 4);
+ ipip_tunnel_link(ipn, t);
+ t->parms.iph.ttl = p->iph.ttl;
+ t->parms.iph.tos = p->iph.tos;
+ t->parms.iph.frag_off = p->iph.frag_off;
+ if (t->parms.link != p->link) {
+ t->parms.link = p->link;
+ ipip_tunnel_bind_dev(t->dev);
+ }
+ netdev_state_change(t->dev);
+}
+
static int
ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -664,7 +691,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -693,29 +720,13 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
break;
}
t = netdev_priv(dev);
- ipip_tunnel_unlink(ipn, t);
- synchronize_net();
- t->parms.iph.saddr = p.iph.saddr;
- t->parms.iph.daddr = p.iph.daddr;
- memcpy(dev->dev_addr, &p.iph.saddr, 4);
- memcpy(dev->broadcast, &p.iph.daddr, 4);
- ipip_tunnel_link(ipn, t);
- netdev_state_change(dev);
}
+
+ ipip_tunnel_update(t, &p);
}
if (t) {
err = 0;
- if (cmd == SIOCCHGTUNNEL) {
- t->parms.iph.ttl = p.iph.ttl;
- t->parms.iph.tos = p.iph.tos;
- t->parms.iph.frag_off = p.iph.frag_off;
- if (t->parms.link != p.link) {
- t->parms.link = p.link;
- ipip_tunnel_bind_dev(dev);
- netdev_state_change(dev);
- }
- }
if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
err = -EFAULT;
} else
@@ -724,7 +735,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
if (dev == ipn->fb_tunnel_dev) {
@@ -773,6 +784,11 @@ static void ipip_dev_free(struct net_device *dev)
free_netdev(dev);
}
+#define IPIP_FEATURES (NETIF_F_SG | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_HIGHDMA | \
+ NETIF_F_HW_CSUM)
+
static void ipip_tunnel_setup(struct net_device *dev)
{
dev->netdev_ops = &ipip_netdev_ops;
@@ -787,6 +803,9 @@ static void ipip_tunnel_setup(struct net_device *dev)
dev->features |= NETIF_F_NETNS_LOCAL;
dev->features |= NETIF_F_LLTX;
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+
+ dev->features |= IPIP_FEATURES;
+ dev->hw_features |= IPIP_FEATURES;
}
static int ipip_tunnel_init(struct net_device *dev)
@@ -829,6 +848,142 @@ static int __net_init ipip_fb_tunnel_init(struct net_device *dev)
return 0;
}
+static void ipip_netlink_parms(struct nlattr *data[],
+ struct ip_tunnel_parm *parms)
+{
+ memset(parms, 0, sizeof(*parms));
+
+ parms->iph.version = 4;
+ parms->iph.protocol = IPPROTO_IPIP;
+ parms->iph.ihl = 5;
+
+ if (!data)
+ return;
+
+ if (data[IFLA_IPTUN_LINK])
+ parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+ if (data[IFLA_IPTUN_LOCAL])
+ parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
+
+ if (data[IFLA_IPTUN_REMOTE])
+ parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
+
+ if (data[IFLA_IPTUN_TTL]) {
+ parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
+ if (parms->iph.ttl)
+ parms->iph.frag_off = htons(IP_DF);
+ }
+
+ if (data[IFLA_IPTUN_TOS])
+ parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
+
+ if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
+ parms->iph.frag_off = htons(IP_DF);
+}
+
+static int ipip_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct net *net = dev_net(dev);
+ struct ip_tunnel *nt;
+
+ nt = netdev_priv(dev);
+ ipip_netlink_parms(data, &nt->parms);
+
+ if (ipip_tunnel_locate(net, &nt->parms, 0))
+ return -EEXIST;
+
+ return ipip_tunnel_create(dev);
+}
+
+static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[])
+{
+ struct ip_tunnel *t;
+ struct ip_tunnel_parm p;
+ struct net *net = dev_net(dev);
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+ if (dev == ipn->fb_tunnel_dev)
+ return -EINVAL;
+
+ ipip_netlink_parms(data, &p);
+
+ if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
+ (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
+ return -EINVAL;
+
+ t = ipip_tunnel_locate(net, &p, 0);
+
+ if (t) {
+ if (t->dev != dev)
+ return -EEXIST;
+ } else
+ t = netdev_priv(dev);
+
+ ipip_tunnel_update(t, &p);
+ return 0;
+}
+
+static size_t ipip_get_size(const struct net_device *dev)
+{
+ return
+ /* IFLA_IPTUN_LINK */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_LOCAL */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_REMOTE */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_TTL */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_TOS */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_PMTUDISC */
+ nla_total_size(1) +
+ 0;
+}
+
+static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct ip_tunnel_parm *parm = &tunnel->parms;
+
+ if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+ nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
+ nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
+ nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
+ nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+ nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
+ !!(parm->iph.frag_off & htons(IP_DF))))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
+ [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
+ [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
+ [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
+ [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
+ [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
+ [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
+};
+
+static struct rtnl_link_ops ipip_link_ops __read_mostly = {
+ .kind = "ipip",
+ .maxtype = IFLA_IPTUN_MAX,
+ .policy = ipip_policy,
+ .priv_size = sizeof(struct ip_tunnel),
+ .setup = ipip_tunnel_setup,
+ .newlink = ipip_newlink,
+ .changelink = ipip_changelink,
+ .get_size = ipip_get_size,
+ .fill_info = ipip_fill_info,
+};
+
static struct xfrm_tunnel ipip_handler __read_mostly = {
.handler = ipip_rcv,
.err_handler = ipip_err,
@@ -925,14 +1080,26 @@ static int __init ipip_init(void)
return err;
err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
if (err < 0) {
- unregister_pernet_device(&ipip_net_ops);
pr_info("%s: can't register tunnel\n", __func__);
+ goto xfrm_tunnel_failed;
}
+ err = rtnl_link_register(&ipip_link_ops);
+ if (err < 0)
+ goto rtnl_link_failed;
+
+out:
return err;
+
+rtnl_link_failed:
+ xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+xfrm_tunnel_failed:
+ unregister_pernet_device(&ipip_net_ops);
+ goto out;
}
static void __exit ipip_fini(void)
{
+ rtnl_link_unregister(&ipip_link_ops);
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
pr_info("%s: can't deregister tunnel\n", __func__);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 3eab2b2ffd34..a9454cbd953c 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -65,6 +65,7 @@
#include <net/checksum.h>
#include <net/netlink.h>
#include <net/fib_rules.h>
+#include <linux/netconf.h>
#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
#define CONFIG_IP_PIMSM 1
@@ -83,8 +84,8 @@ struct mr_table {
struct vif_device vif_table[MAXVIFS];
int maxvif;
atomic_t cache_resolve_queue_len;
- int mroute_do_assert;
- int mroute_do_pim;
+ bool mroute_do_assert;
+ bool mroute_do_pim;
#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
int mroute_reg_vif_num;
#endif
@@ -133,6 +134,8 @@ static int ipmr_cache_report(struct mr_table *mrt,
struct sk_buff *pkt, vifi_t vifi, int assert);
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm);
+static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
+ int cmd);
static void mroute_clean_tables(struct mr_table *mrt);
static void ipmr_expire_process(unsigned long arg);
@@ -582,6 +585,9 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
in_dev = __in_dev_get_rtnl(dev);
if (in_dev) {
IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
+ inet_netconf_notify_devconf(dev_net(dev),
+ NETCONFA_MC_FORWARDING,
+ dev->ifindex, &in_dev->cnf);
ip_rt_multicast_event(in_dev);
}
@@ -665,6 +671,7 @@ static void ipmr_expire_process(unsigned long arg)
}
list_del(&c->list);
+ mroute_netlink_event(mrt, c, RTM_DELROUTE);
ipmr_destroy_unres(mrt, c);
}
@@ -772,6 +779,8 @@ static int vif_add(struct net *net, struct mr_table *mrt,
return -EADDRNOTAVAIL;
}
IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
+ inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, dev->ifindex,
+ &in_dev->cnf);
ip_rt_multicast_event(in_dev);
/* Fill in the VIF structures */
@@ -1020,6 +1029,7 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
atomic_inc(&mrt->cache_resolve_queue_len);
list_add(&c->list, &mrt->mfc_unres_queue);
+ mroute_netlink_event(mrt, c, RTM_NEWROUTE);
if (atomic_read(&mrt->cache_resolve_queue_len) == 1)
mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
@@ -1054,7 +1064,7 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
list_del_rcu(&c->list);
-
+ mroute_netlink_event(mrt, c, RTM_DELROUTE);
ipmr_cache_free(c);
return 0;
}
@@ -1089,6 +1099,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
if (!mrtsock)
c->mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock);
+ mroute_netlink_event(mrt, c, RTM_NEWROUTE);
return 0;
}
@@ -1131,6 +1142,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
ipmr_cache_resolve(net, mrt, uc, c);
ipmr_cache_free(uc);
}
+ mroute_netlink_event(mrt, c, RTM_NEWROUTE);
return 0;
}
@@ -1159,6 +1171,7 @@ static void mroute_clean_tables(struct mr_table *mrt)
if (c->mfc_flags & MFC_STATIC)
continue;
list_del_rcu(&c->list);
+ mroute_netlink_event(mrt, c, RTM_DELROUTE);
ipmr_cache_free(c);
}
}
@@ -1167,6 +1180,7 @@ static void mroute_clean_tables(struct mr_table *mrt)
spin_lock_bh(&mfc_unres_lock);
list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
list_del(&c->list);
+ mroute_netlink_event(mrt, c, RTM_DELROUTE);
ipmr_destroy_unres(mrt, c);
}
spin_unlock_bh(&mfc_unres_lock);
@@ -1185,6 +1199,9 @@ static void mrtsock_destruct(struct sock *sk)
ipmr_for_each_table(mrt, net) {
if (sk == rtnl_dereference(mrt->mroute_sk)) {
IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
+ inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv4.devconf_all);
RCU_INIT_POINTER(mrt->mroute_sk, NULL);
mroute_clean_tables(mrt);
}
@@ -1207,23 +1224,24 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
struct net *net = sock_net(sk);
struct mr_table *mrt;
+ if (sk->sk_type != SOCK_RAW ||
+ inet_sk(sk)->inet_num != IPPROTO_IGMP)
+ return -EOPNOTSUPP;
+
mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
if (mrt == NULL)
return -ENOENT;
if (optname != MRT_INIT) {
if (sk != rcu_access_pointer(mrt->mroute_sk) &&
- !capable(CAP_NET_ADMIN))
+ !ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EACCES;
}
switch (optname) {
case MRT_INIT:
- if (sk->sk_type != SOCK_RAW ||
- inet_sk(sk)->inet_num != IPPROTO_IGMP)
- return -EOPNOTSUPP;
if (optlen != sizeof(int))
- return -ENOPROTOOPT;
+ return -EINVAL;
rtnl_lock();
if (rtnl_dereference(mrt->mroute_sk)) {
@@ -1235,6 +1253,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
if (ret == 0) {
rcu_assign_pointer(mrt->mroute_sk, sk);
IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
+ inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv4.devconf_all);
}
rtnl_unlock();
return ret;
@@ -1284,9 +1305,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
case MRT_ASSERT:
{
int v;
+ if (optlen != sizeof(v))
+ return -EINVAL;
if (get_user(v, (int __user *)optval))
return -EFAULT;
- mrt->mroute_do_assert = (v) ? 1 : 0;
+ mrt->mroute_do_assert = v;
return 0;
}
#ifdef CONFIG_IP_PIMSM
@@ -1294,9 +1317,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
{
int v;
+ if (optlen != sizeof(v))
+ return -EINVAL;
if (get_user(v, (int __user *)optval))
return -EFAULT;
- v = (v) ? 1 : 0;
+ v = !!v;
rtnl_lock();
ret = 0;
@@ -1329,7 +1354,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
} else {
if (!ipmr_new_table(net, v))
ret = -ENOMEM;
- raw_sk(sk)->ipmr_table = v;
+ else
+ raw_sk(sk)->ipmr_table = v;
}
rtnl_unlock();
return ret;
@@ -1355,6 +1381,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
struct net *net = sock_net(sk);
struct mr_table *mrt;
+ if (sk->sk_type != SOCK_RAW ||
+ inet_sk(sk)->inet_num != IPPROTO_IGMP)
+ return -EOPNOTSUPP;
+
mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
if (mrt == NULL)
return -ENOENT;
@@ -2024,6 +2054,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
int ct;
struct rtnexthop *nhp;
struct nlattr *mp_attr;
+ struct rta_mfc_stats mfcs;
/* If cache is unresolved, don't try to parse IIF and OIF */
if (c->mfc_parent >= MAXVIFS)
@@ -2052,6 +2083,12 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
nla_nest_end(skb, mp_attr);
+ mfcs.mfcs_packets = c->mfc_un.res.pkt;
+ mfcs.mfcs_bytes = c->mfc_un.res.bytes;
+ mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
+ if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0)
+ return -EMSGSIZE;
+
rtm->rtm_type = RTN_MULTICAST;
return 1;
}
@@ -2121,12 +2158,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
}
static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
- u32 portid, u32 seq, struct mfc_cache *c)
+ u32 portid, u32 seq, struct mfc_cache *c, int cmd)
{
struct nlmsghdr *nlh;
struct rtmsg *rtm;
+ int err;
- nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
+ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
if (nlh == NULL)
return -EMSGSIZE;
@@ -2140,13 +2178,18 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
goto nla_put_failure;
rtm->rtm_type = RTN_MULTICAST;
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
- rtm->rtm_protocol = RTPROT_UNSPEC;
+ if (c->mfc_flags & MFC_STATIC)
+ rtm->rtm_protocol = RTPROT_STATIC;
+ else
+ rtm->rtm_protocol = RTPROT_MROUTED;
rtm->rtm_flags = 0;
if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) ||
nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp))
goto nla_put_failure;
- if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0)
+ err = __ipmr_fill_mroute(mrt, skb, c, rtm);
+ /* do not break the dump if cache is unresolved */
+ if (err < 0 && err != -ENOENT)
goto nla_put_failure;
return nlmsg_end(skb, nlh);
@@ -2156,6 +2199,52 @@ nla_put_failure:
return -EMSGSIZE;
}
+static size_t mroute_msgsize(bool unresolved, int maxvif)
+{
+ size_t len =
+ NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(4) /* RTA_SRC */
+ + nla_total_size(4) /* RTA_DST */
+ ;
+
+ if (!unresolved)
+ len = len
+ + nla_total_size(4) /* RTA_IIF */
+ + nla_total_size(0) /* RTA_MULTIPATH */
+ + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
+ /* RTA_MFC_STATS */
+ + nla_total_size(sizeof(struct rta_mfc_stats))
+ ;
+
+ return len;
+}
+
+static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
+ int cmd)
+{
+ struct net *net = read_pnet(&mrt->net);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(mroute_msgsize(mfc->mfc_parent >= MAXVIFS, mrt->maxvif),
+ GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+ if (err < 0)
+ goto errout;
+
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MROUTE, NULL, GFP_ATOMIC);
+ return;
+
+errout:
+ kfree_skb(skb);
+ if (err < 0)
+ rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE, err);
+}
+
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
@@ -2182,13 +2271,29 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ipmr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
- mfc) < 0)
+ mfc, RTM_NEWROUTE) < 0)
goto done;
next_entry:
e++;
}
e = s_e = 0;
}
+ spin_lock_bh(&mfc_unres_lock);
+ list_for_each_entry(mfc, &mrt->mfc_unres_queue, list) {
+ if (e < s_e)
+ goto next_entry2;
+ if (ipmr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ mfc, RTM_NEWROUTE) < 0) {
+ spin_unlock_bh(&mfc_unres_lock);
+ goto done;
+ }
+next_entry2:
+ e++;
+ }
+ spin_unlock_bh(&mfc_unres_lock);
+ e = s_e = 0;
s_h = 0;
next_table:
t++;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 97e61eadf580..3ea4127404d6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1533,7 +1533,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1677,7 +1677,7 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1698,7 +1698,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1722,7 +1722,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 170b1fdd6b72..17c5e06da662 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1846,7 +1846,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1961,7 +1961,7 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1983,7 +1983,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -2008,7 +2008,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index fe5daea5214d..75e33a7048f8 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -661,6 +661,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
#define PROC_WRITELEN 10
char buffer[PROC_WRITELEN+1];
unsigned long nodenum;
+ int rc;
if (size > PROC_WRITELEN)
return -EIO;
@@ -669,11 +670,15 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
buffer[size] = 0;
if (*buffer == '+') {
- nodenum = simple_strtoul(buffer+1, NULL, 10);
+ rc = kstrtoul(buffer+1, 10, &nodenum);
+ if (rc)
+ return rc;
if (clusterip_add_node(c, nodenum))
return -ENOMEM;
} else if (*buffer == '-') {
- nodenum = simple_strtoul(buffer+1, NULL,10);
+ rc = kstrtoul(buffer+1, 10, &nodenum);
+ if (rc)
+ return rc;
if (clusterip_del_node(c, nodenum))
return -ENOENT;
} else
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index a82047282dbb..da2c8a368f68 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -134,6 +134,10 @@ nf_nat_ipv4_fn(unsigned int hooknum,
/* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == IP_CT_ESTABLISHED_REPLY);
+ if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
+ nf_ct_kill_acct(ct, ctinfo, skb);
+ return NF_DROP;
+ }
}
return nf_nat_packet(ct, ctinfo, hooknum, skb);
@@ -276,9 +280,7 @@ static int __net_init iptable_nat_net_init(struct net *net)
return -ENOMEM;
net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
kfree(repl);
- if (IS_ERR(net->ipv4.nat_table))
- return PTR_ERR(net->ipv4.nat_table);
- return 0;
+ return PTR_RET(net->ipv4.nat_table);
}
static void __net_exit iptable_nat_net_exit(struct net *net)
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index 8918eff1426d..0f9d09f54bd9 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -29,6 +29,7 @@
#include <net/protocol.h>
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
@@ -41,6 +42,13 @@ int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
}
EXPORT_SYMBOL(inet_add_protocol);
+int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
+{
+ return !cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+ NULL, prot) ? 0 : -1;
+}
+EXPORT_SYMBOL(inet_add_offload);
+
/*
* Remove a protocol from the hash tables.
*/
@@ -57,3 +65,16 @@ int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
return ret;
}
EXPORT_SYMBOL(inet_del_protocol);
+
+int inet_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+ int ret;
+
+ ret = (cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+ prot, NULL) == prot) ? 0 : -1;
+
+ synchronize_net();
+
+ return ret;
+}
+EXPORT_SYMBOL(inet_del_offload);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index df251424d816..844a9ef60dbd 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2232,8 +2232,27 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
error = rt->dst.error;
if (rt_is_input_route(rt)) {
- if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
- goto nla_put_failure;
+#ifdef CONFIG_IP_MROUTE
+ if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) &&
+ IPV4_DEVCONF_ALL(net, MC_FORWARDING)) {
+ int err = ipmr_get_route(net, skb,
+ fl4->saddr, fl4->daddr,
+ r, nowait);
+ if (err <= 0) {
+ if (!nowait) {
+ if (err == 0)
+ return 0;
+ goto nla_put_failure;
+ } else {
+ if (err == -EMSGSIZE)
+ goto nla_put_failure;
+ error = err;
+ }
+ }
+ } else
+#endif
+ if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
+ goto nla_put_failure;
}
if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, error) < 0)
@@ -2496,6 +2515,10 @@ static __net_init int sysctl_route_net_init(struct net *net)
tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL);
if (tbl == NULL)
goto err_dup;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ tbl[0].procname = NULL;
}
tbl[0].extra1 = net;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index ba48e799b031..b236ef04914f 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -340,7 +340,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
}
req->expires = 0UL;
- req->retrans = 0;
+ req->num_retrans = 0;
/*
* We need to lookup the route here to get at the correct
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 63d4eccc674d..d84400b65049 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -883,6 +883,9 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
table[6].data =
&net->ipv4.sysctl_ping_group_range;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
}
/*
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e457c7ab2e28..1ca253635f7a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -536,13 +536,14 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
struct tcp_sock *tp = tcp_sk(sk);
int answ;
+ bool slow;
switch (cmd) {
case SIOCINQ:
if (sk->sk_state == TCP_LISTEN)
return -EINVAL;
- lock_sock(sk);
+ slow = lock_sock_fast(sk);
if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
answ = 0;
else if (sock_flag(sk, SOCK_URGINLINE) ||
@@ -557,7 +558,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
answ--;
} else
answ = tp->urg_seq - tp->copied_seq;
- release_sock(sk);
+ unlock_sock_fast(sk, slow);
break;
case SIOCATMARK:
answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
@@ -1490,15 +1491,19 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
copied += used;
offset += used;
}
- /*
- * If recv_actor drops the lock (e.g. TCP splice
+ /* If recv_actor drops the lock (e.g. TCP splice
* receive) the skb pointer might be invalid when
* getting here: tcp_collapse might have deleted it
* while aggregating skbs from the socket queue.
*/
- skb = tcp_recv_skb(sk, seq-1, &offset);
- if (!skb || (offset+1 != skb->len))
+ skb = tcp_recv_skb(sk, seq - 1, &offset);
+ if (!skb)
break;
+ /* TCP coalescing might have appended data to the skb.
+ * Try to splice more frags
+ */
+ if (offset + 1 != skb->len)
+ continue;
}
if (tcp_hdr(skb)->fin) {
sk_eat_skb(sk, skb, false);
@@ -2300,7 +2305,7 @@ void tcp_sock_destruct(struct sock *sk)
static inline bool tcp_can_repair_sock(const struct sock *sk)
{
- return capable(CAP_NET_ADMIN) &&
+ return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
}
@@ -3586,8 +3591,7 @@ void __init tcp_init(void)
alloc_large_system_hash("TCP established",
sizeof(struct inet_ehash_bucket),
thash_entries,
- (totalram_pages >= 128 * 1024) ?
- 13 : 15,
+ 17, /* one slot per 128 KB of memory */
0,
NULL,
&tcp_hashinfo.ehash_mask,
@@ -3603,8 +3607,7 @@ void __init tcp_init(void)
alloc_large_system_hash("TCP bind",
sizeof(struct inet_bind_hashbucket),
tcp_hashinfo.ehash_mask + 1,
- (totalram_pages >= 128 * 1024) ?
- 13 : 15,
+ 17, /* one slot per 128 KB of memory */
0,
&tcp_hashinfo.bhash_size,
NULL,
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1432cdb0644c..291f2ed7cc31 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -1,7 +1,7 @@
/*
* Plugable TCP congestion control support and newReno
* congestion control.
- * Based on ideas from I/O scheduler suport and Web100.
+ * Based on ideas from I/O scheduler support and Web100.
*
* Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
*/
@@ -259,7 +259,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
if (!ca)
err = -ENOENT;
- else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || capable(CAP_NET_ADMIN)))
+ else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
+ ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)))
err = -EPERM;
else if (!try_module_get(ca->owner))
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 181fc8234a52..a13692560e63 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3552,6 +3552,24 @@ static bool tcp_process_frto(struct sock *sk, int flag)
return false;
}
+/* RFC 5961 7 [ACK Throttling] */
+static void tcp_send_challenge_ack(struct sock *sk)
+{
+ /* unprotected vars, we dont care of overwrites */
+ static u32 challenge_timestamp;
+ static unsigned int challenge_count;
+ u32 now = jiffies / HZ;
+
+ if (now != challenge_timestamp) {
+ challenge_timestamp = now;
+ challenge_count = 0;
+ }
+ if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
+ tcp_send_ack(sk);
+ }
+}
+
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
@@ -3571,8 +3589,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
/* If the ack is older than previous acks
* then we can probably ignore it.
*/
- if (before(ack, prior_snd_una))
+ if (before(ack, prior_snd_una)) {
+ /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
+ if (before(ack, prior_snd_una - tp->max_window)) {
+ tcp_send_challenge_ack(sk);
+ return -1;
+ }
goto old_ack;
+ }
/* If the ack includes data we haven't sent yet, discard
* this segment (RFC793 Section 3.9).
@@ -5244,23 +5268,6 @@ out:
}
#endif /* CONFIG_NET_DMA */
-static void tcp_send_challenge_ack(struct sock *sk)
-{
- /* unprotected vars, we dont care of overwrites */
- static u32 challenge_timestamp;
- static unsigned int challenge_count;
- u32 now = jiffies / HZ;
-
- if (now != challenge_timestamp) {
- challenge_timestamp = now;
- challenge_count = 0;
- }
- if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
- NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
- tcp_send_ack(sk);
- }
-}
-
/* Does PAWS and seqno based validation of an incoming segment, flags will
* play significant role here.
*/
@@ -5992,7 +5999,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
*/
if (req) {
tcp_synack_rtt_meas(sk, req);
- tp->total_retrans = req->retrans;
+ tp->total_retrans = req->num_retrans;
reqsk_fastopen_remove(sk, req, false);
} else {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0c4a64355603..1ed230716d51 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -138,14 +138,6 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
}
EXPORT_SYMBOL_GPL(tcp_twsk_unique);
-static int tcp_repair_connect(struct sock *sk)
-{
- tcp_connect_init(sk);
- tcp_finish_connect(sk, NULL);
-
- return 0;
-}
-
/* This will initiate an outgoing connection. */
int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
@@ -250,10 +242,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
inet->inet_id = tp->write_seq ^ jiffies;
- if (likely(!tp->repair))
- err = tcp_connect(sk);
- else
- err = tcp_repair_connect(sk);
+ err = tcp_connect(sk);
rt = NULL;
if (err)
@@ -877,10 +866,13 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
}
static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
- struct request_values *rvp)
+ struct request_values *rvp)
{
- TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
- return tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
+ int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
+
+ if (!res)
+ TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
+ return res;
}
/*
@@ -1070,7 +1062,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
}
EXPORT_SYMBOL(tcp_md5_do_del);
-void tcp_clear_md5_list(struct sock *sk)
+static void tcp_clear_md5_list(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_md5sig_key *key;
@@ -1386,7 +1378,8 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
struct sock *child;
int err;
- req->retrans = 0;
+ req->num_retrans = 0;
+ req->num_timeout = 0;
req->sk = NULL;
child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);
@@ -1741,7 +1734,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
tcp_initialize_rcv_mss(newsk);
tcp_synack_rtt_meas(newsk, req);
- newtp->total_retrans = req->retrans;
+ newtp->total_retrans = req->num_retrans;
#ifdef CONFIG_TCP_MD5SIG
/* Copy over the MD5 key from the original socket */
@@ -1919,7 +1912,6 @@ EXPORT_SYMBOL(tcp_v4_do_rcv);
void tcp_v4_early_demux(struct sk_buff *skb)
{
- struct net *net = dev_net(skb->dev);
const struct iphdr *iph;
const struct tcphdr *th;
struct sock *sk;
@@ -1927,16 +1919,16 @@ void tcp_v4_early_demux(struct sk_buff *skb)
if (skb->pkt_type != PACKET_HOST)
return;
- if (!pskb_may_pull(skb, ip_hdrlen(skb) + sizeof(struct tcphdr)))
+ if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
return;
iph = ip_hdr(skb);
- th = (struct tcphdr *) ((char *)iph + ip_hdrlen(skb));
+ th = tcp_hdr(skb);
if (th->doff < sizeof(struct tcphdr) / 4)
return;
- sk = __inet_lookup_established(net, &tcp_hashinfo,
+ sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
iph->saddr, th->source,
iph->daddr, ntohs(th->dest),
skb->skb_iif);
@@ -2640,7 +2632,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req,
0, 0, /* could print option size, but that is af dependent. */
1, /* timers active (only the expire timer) */
jiffies_delta_to_clock_t(delta),
- req->retrans,
+ req->num_timeout,
from_kuid_munged(seq_user_ns(f), uid),
0, /* non standard timer */
0, /* open_requests have no inode */
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index a7302d974f32..f35f2dfb6401 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -553,7 +553,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
* it can be estimated (approximately)
* from another data.
*/
- tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<<req->retrans);
+ tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<<req->num_timeout);
paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
}
}
@@ -582,7 +582,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
* Note that even if there is new data in the SYN packet
* they will be thrown away too.
*/
- req->rsk_ops->rtx_syn_ack(sk, req, NULL);
+ inet_rtx_syn_ack(sk, req);
return NULL;
}
@@ -696,7 +696,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
/* Got ACK for our SYNACK, so update baseline for SYNACK RTT sample. */
if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr)
tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr;
- else if (req->retrans) /* don't take RTT sample if retrans && ~TS */
+ else if (req->num_retrans) /* don't take RTT sample if retrans && ~TS */
tcp_rsk(req)->snt_synack = 0;
/* For Fast Open no more processing is needed (sk is the
@@ -706,7 +706,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
return sk;
/* While TCP_DEFER_ACCEPT is active, drop bare ACK. */
- if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+ if (req->num_timeout < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
inet_rsk(req)->acked = 1;
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 948ac275b9b5..5d451593ef16 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2992,6 +2992,11 @@ int tcp_connect(struct sock *sk)
tcp_connect_init(sk);
+ if (unlikely(tp->repair)) {
+ tcp_finish_connect(sk, NULL);
+ return 0;
+ }
+
buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
if (unlikely(buff == NULL))
return -ENOBUFS;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index d47c1b4421a3..b78aac30c498 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -318,7 +318,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk)
req = tcp_sk(sk)->fastopen_rsk;
req->rsk_ops->syn_ack_timeout(sk, req);
- if (req->retrans >= max_retries) {
+ if (req->num_timeout >= max_retries) {
tcp_write_err(sk);
return;
}
@@ -327,10 +327,10 @@ static void tcp_fastopen_synack_timer(struct sock *sk)
* regular retransmit because if the child socket has been accepted
* it's not good to give up too easily.
*/
- req->rsk_ops->rtx_syn_ack(sk, req, NULL);
- req->retrans++;
+ inet_rtx_syn_ack(sk, req);
+ req->num_timeout++;
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
- TCP_TIMEOUT_INIT << req->retrans, TCP_RTO_MAX);
+ TCP_TIMEOUT_INIT << req->num_timeout, TCP_RTO_MAX);
}
/*
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index b6d3f79151e2..2068ac4fbdad 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -7,9 +7,11 @@ obj-$(CONFIG_IPV6) += ipv6.o
ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
addrlabel.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
- raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
+ raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
+ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
+
ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
@@ -39,5 +41,6 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
obj-y += addrconf_core.o exthdrs_core.o
+obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6_offload)
obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0424e4e27414..6fca01f136ad 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -81,6 +81,7 @@
#include <net/pkt_sched.h>
#include <linux/if_tunnel.h>
#include <linux/rtnetlink.h>
+#include <linux/netconf.h>
#ifdef CONFIG_IPV6_PRIVACY
#include <linux/random.h>
@@ -401,7 +402,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
ndev->cnf.accept_dad = -1;
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
pr_info("%s: Disabled Multicast RS\n", dev->name);
ndev->cnf.rtr_solicits = 0;
@@ -460,6 +461,150 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
return idev;
}
+static int inet6_netconf_msgsize_devconf(int type)
+{
+ int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
+ + nla_total_size(4); /* NETCONFA_IFINDEX */
+
+ /* type -1 is used for ALL */
+ if (type == -1 || type == NETCONFA_FORWARDING)
+ size += nla_total_size(4);
+#ifdef CONFIG_IPV6_MROUTE
+ if (type == -1 || type == NETCONFA_MC_FORWARDING)
+ size += nla_total_size(4);
+#endif
+
+ return size;
+}
+
+static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+ struct ipv6_devconf *devconf, u32 portid,
+ u32 seq, int event, unsigned int flags,
+ int type)
+{
+ struct nlmsghdr *nlh;
+ struct netconfmsg *ncm;
+
+ nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
+ flags);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ ncm = nlmsg_data(nlh);
+ ncm->ncm_family = AF_INET6;
+
+ if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
+ goto nla_put_failure;
+
+ /* type -1 is used for ALL */
+ if ((type == -1 || type == NETCONFA_FORWARDING) &&
+ nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
+ goto nla_put_failure;
+#ifdef CONFIG_IPV6_MROUTE
+ if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+ nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+ devconf->mc_forwarding) < 0)
+ goto nla_put_failure;
+#endif
+ return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
+void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+ struct ipv6_devconf *devconf)
+{
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
+ RTM_NEWNETCONF, 0, type);
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
+ return;
+errout:
+ if (err < 0)
+ rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
+}
+
+static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
+ [NETCONFA_IFINDEX] = { .len = sizeof(int) },
+ [NETCONFA_FORWARDING] = { .len = sizeof(int) },
+};
+
+static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
+ struct nlmsghdr *nlh,
+ void *arg)
+{
+ struct net *net = sock_net(in_skb->sk);
+ struct nlattr *tb[NETCONFA_MAX+1];
+ struct netconfmsg *ncm;
+ struct sk_buff *skb;
+ struct ipv6_devconf *devconf;
+ struct inet6_dev *in6_dev;
+ struct net_device *dev;
+ int ifindex;
+ int err;
+
+ err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
+ devconf_ipv6_policy);
+ if (err < 0)
+ goto errout;
+
+ err = EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+ ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+ switch (ifindex) {
+ case NETCONFA_IFINDEX_ALL:
+ devconf = net->ipv6.devconf_all;
+ break;
+ case NETCONFA_IFINDEX_DEFAULT:
+ devconf = net->ipv6.devconf_dflt;
+ break;
+ default:
+ dev = __dev_get_by_index(net, ifindex);
+ if (dev == NULL)
+ goto errout;
+ in6_dev = __in6_dev_get(dev);
+ if (in6_dev == NULL)
+ goto errout;
+ devconf = &in6_dev->cnf;
+ break;
+ }
+
+ err = -ENOBUFS;
+ skb = nlmsg_new(inet6_netconf_msgsize_devconf(-1), GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = inet6_netconf_fill_devconf(skb, ifindex, devconf,
+ NETLINK_CB(in_skb).portid,
+ nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
+ -1);
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+ err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
+errout:
+ return err;
+}
+
#ifdef CONFIG_SYSCTL
static void dev_forward_change(struct inet6_dev *idev)
{
@@ -471,7 +616,7 @@ static void dev_forward_change(struct inet6_dev *idev)
dev = idev->dev;
if (idev->cnf.forwarding)
dev_disable_lro(dev);
- if (dev && (dev->flags & IFF_MULTICAST)) {
+ if (dev->flags & IFF_MULTICAST) {
if (idev->cnf.forwarding)
ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
else
@@ -486,6 +631,8 @@ static void dev_forward_change(struct inet6_dev *idev)
else
addrconf_leave_anycast(ifa);
}
+ inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING,
+ dev->ifindex, &idev->cnf);
}
@@ -518,6 +665,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
*p = newf;
if (p == &net->ipv6.devconf_dflt->forwarding) {
+ if ((!newf) ^ (!old))
+ inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ NETCONFA_IFINDEX_DEFAULT,
+ net->ipv6.devconf_dflt);
rtnl_unlock();
return 0;
}
@@ -525,6 +676,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
if (p == &net->ipv6.devconf_all->forwarding) {
net->ipv6.devconf_dflt->forwarding = newf;
addrconf_forward_change(net, newf);
+ if ((!newf) ^ (!old))
+ inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv6.devconf_all);
} else if ((!newf) ^ (!old))
dev_forward_change((struct inet6_dev *)table->extra1);
rtnl_unlock();
@@ -553,7 +708,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
pr_warn("Freeing alive inet6 address %p\n", ifp);
return;
}
- dst_release(&ifp->rt->dst);
+ ip6_rt_put(ifp->rt);
kfree_rcu(ifp, rcu);
}
@@ -805,7 +960,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
rt6_set_expires(rt, expires);
}
}
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
/* clean up prefsrc entries */
@@ -1692,7 +1847,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
This thing is done here expecting that the whole
class of non-broadcast devices need not cloning.
*/
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
cfg.fc_flags |= RTF_NONEXTHOP;
#endif
@@ -1752,7 +1907,7 @@ static void addrconf_add_mroute(struct net_device *dev)
ip6_route_add(&cfg);
}
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
static void sit_route_add(struct net_device *dev)
{
struct fib6_config cfg = {
@@ -1881,8 +2036,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
dev, expires, flags);
}
- if (rt)
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
/* Try to figure out our local address for this prefix */
@@ -2104,7 +2258,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg)
if (dev == NULL)
goto err_exit;
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
if (dev->type == ARPHRD_SIT) {
const struct net_device_ops *ops = dev->netdev_ops;
struct ifreq ifr;
@@ -2268,7 +2422,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
struct in6_ifreq ireq;
int err;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -2287,7 +2441,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
struct in6_ifreq ireq;
int err;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -2315,7 +2469,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
}
}
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
static void sit_add_v4_addrs(struct inet6_dev *idev)
{
struct in6_addr addr;
@@ -2434,7 +2588,7 @@ static void addrconf_dev_config(struct net_device *dev)
addrconf_add_linklocal(idev, &addr);
}
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
static void addrconf_sit_config(struct net_device *dev)
{
struct inet6_dev *idev;
@@ -2471,7 +2625,7 @@ static void addrconf_sit_config(struct net_device *dev)
}
#endif
-#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+#if IS_ENABLED(CONFIG_NET_IPGRE)
static void addrconf_gre_config(struct net_device *dev)
{
struct inet6_dev *idev;
@@ -2601,12 +2755,12 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
}
switch (dev->type) {
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
case ARPHRD_SIT:
addrconf_sit_config(dev);
break;
#endif
-#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+#if IS_ENABLED(CONFIG_NET_IPGRE)
case ARPHRD_IPGRE:
addrconf_gre_config(dev);
break;
@@ -2843,7 +2997,7 @@ static void addrconf_rs_timer(unsigned long data)
if (idev->dead || !(idev->if_flags & IF_READY))
goto out;
- if (idev->cnf.forwarding)
+ if (!ipv6_accept_ra(idev))
goto out;
/* Announcement received after solicitation was sent */
@@ -3005,8 +3159,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
router advertisements, start sending router solicitations.
*/
- if (((ifp->idev->cnf.accept_ra == 1 && !ifp->idev->cnf.forwarding) ||
- ifp->idev->cnf.accept_ra == 2) &&
+ if (ipv6_accept_ra(ifp->idev) &&
ifp->idev->cnf.rtr_solicits > 0 &&
(dev->flags&IFF_LOOPBACK) == 0 &&
(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
@@ -3194,7 +3347,7 @@ void if6_proc_exit(void)
}
#endif /* CONFIG_PROC_FS */
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
/* Check if address is a home address configured on any interface. */
int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
{
@@ -3892,6 +4045,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
+ array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
}
static inline size_t inet6_ifla6_size(void)
@@ -4560,6 +4714,13 @@ static struct addrconf_sysctl_table
.proc_handler = proc_dointvec
},
{
+ .procname = "ndisc_notify",
+ .data = &ipv6_devconf.ndisc_notify,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ {
/* sentinel */
}
},
@@ -4784,6 +4945,8 @@ int __init addrconf_init(void)
inet6_dump_ifmcaddr, NULL);
__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
inet6_dump_ifacaddr, NULL);
+ __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
+ NULL, NULL);
ipv6_addr_label_rtnl_register();
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index a974247a9ae4..b043c60429bd 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -160,7 +160,8 @@ lookup_protocol:
}
err = -EPERM;
- if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+ if (sock->type == SOCK_RAW && !kern &&
+ !ns_capable(net->user_ns, CAP_NET_RAW))
goto out_rcu_unlock;
sock->ops = answer->ops;
@@ -282,7 +283,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EINVAL;
snum = ntohs(addr->sin6_port);
- if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ if (snum && snum < PROT_SOCK && !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
return -EACCES;
lock_sock(sk);
@@ -699,249 +700,9 @@ bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
-static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
-{
- const struct inet6_protocol *ops = NULL;
-
- for (;;) {
- struct ipv6_opt_hdr *opth;
- int len;
-
- if (proto != NEXTHDR_HOP) {
- ops = rcu_dereference(inet6_protos[proto]);
-
- if (unlikely(!ops))
- break;
-
- if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
- break;
- }
-
- if (unlikely(!pskb_may_pull(skb, 8)))
- break;
-
- opth = (void *)skb->data;
- len = ipv6_optlen(opth);
-
- if (unlikely(!pskb_may_pull(skb, len)))
- break;
-
- proto = opth->nexthdr;
- __skb_pull(skb, len);
- }
-
- return proto;
-}
-
-static int ipv6_gso_send_check(struct sk_buff *skb)
-{
- const struct ipv6hdr *ipv6h;
- const struct inet6_protocol *ops;
- int err = -EINVAL;
-
- if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
- goto out;
-
- ipv6h = ipv6_hdr(skb);
- __skb_pull(skb, sizeof(*ipv6h));
- err = -EPROTONOSUPPORT;
-
- rcu_read_lock();
- ops = rcu_dereference(inet6_protos[
- ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
-
- if (likely(ops && ops->gso_send_check)) {
- skb_reset_transport_header(skb);
- err = ops->gso_send_check(skb);
- }
- rcu_read_unlock();
-
-out:
- return err;
-}
-
-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
- netdev_features_t features)
-{
- struct sk_buff *segs = ERR_PTR(-EINVAL);
- struct ipv6hdr *ipv6h;
- const struct inet6_protocol *ops;
- int proto;
- struct frag_hdr *fptr;
- unsigned int unfrag_ip6hlen;
- u8 *prevhdr;
- int offset = 0;
-
- if (!(features & NETIF_F_V6_CSUM))
- features &= ~NETIF_F_SG;
-
- if (unlikely(skb_shinfo(skb)->gso_type &
- ~(SKB_GSO_UDP |
- SKB_GSO_DODGY |
- SKB_GSO_TCP_ECN |
- SKB_GSO_TCPV6 |
- 0)))
- goto out;
-
- if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
- goto out;
-
- ipv6h = ipv6_hdr(skb);
- __skb_pull(skb, sizeof(*ipv6h));
- segs = ERR_PTR(-EPROTONOSUPPORT);
-
- proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
- rcu_read_lock();
- ops = rcu_dereference(inet6_protos[proto]);
- if (likely(ops && ops->gso_segment)) {
- skb_reset_transport_header(skb);
- segs = ops->gso_segment(skb, features);
- }
- rcu_read_unlock();
-
- if (IS_ERR(segs))
- goto out;
-
- for (skb = segs; skb; skb = skb->next) {
- ipv6h = ipv6_hdr(skb);
- ipv6h->payload_len = htons(skb->len - skb->mac_len -
- sizeof(*ipv6h));
- if (proto == IPPROTO_UDP) {
- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
- fptr = (struct frag_hdr *)(skb_network_header(skb) +
- unfrag_ip6hlen);
- fptr->frag_off = htons(offset);
- if (skb->next != NULL)
- fptr->frag_off |= htons(IP6_MF);
- offset += (ntohs(ipv6h->payload_len) -
- sizeof(struct frag_hdr));
- }
- }
-
-out:
- return segs;
-}
-
-static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
- struct sk_buff *skb)
-{
- const struct inet6_protocol *ops;
- struct sk_buff **pp = NULL;
- struct sk_buff *p;
- struct ipv6hdr *iph;
- unsigned int nlen;
- unsigned int hlen;
- unsigned int off;
- int flush = 1;
- int proto;
- __wsum csum;
-
- off = skb_gro_offset(skb);
- hlen = off + sizeof(*iph);
- iph = skb_gro_header_fast(skb, off);
- if (skb_gro_header_hard(skb, hlen)) {
- iph = skb_gro_header_slow(skb, hlen, off);
- if (unlikely(!iph))
- goto out;
- }
-
- skb_gro_pull(skb, sizeof(*iph));
- skb_set_transport_header(skb, skb_gro_offset(skb));
-
- flush += ntohs(iph->payload_len) != skb_gro_len(skb);
-
- rcu_read_lock();
- proto = iph->nexthdr;
- ops = rcu_dereference(inet6_protos[proto]);
- if (!ops || !ops->gro_receive) {
- __pskb_pull(skb, skb_gro_offset(skb));
- proto = ipv6_gso_pull_exthdrs(skb, proto);
- skb_gro_pull(skb, -skb_transport_offset(skb));
- skb_reset_transport_header(skb);
- __skb_push(skb, skb_gro_offset(skb));
-
- ops = rcu_dereference(inet6_protos[proto]);
- if (!ops || !ops->gro_receive)
- goto out_unlock;
-
- iph = ipv6_hdr(skb);
- }
-
- NAPI_GRO_CB(skb)->proto = proto;
-
- flush--;
- nlen = skb_network_header_len(skb);
-
- for (p = *head; p; p = p->next) {
- const struct ipv6hdr *iph2;
- __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
-
- if (!NAPI_GRO_CB(p)->same_flow)
- continue;
-
- iph2 = ipv6_hdr(p);
- first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
-
- /* All fields must match except length and Traffic Class. */
- if (nlen != skb_network_header_len(p) ||
- (first_word & htonl(0xF00FFFFF)) ||
- memcmp(&iph->nexthdr, &iph2->nexthdr,
- nlen - offsetof(struct ipv6hdr, nexthdr))) {
- NAPI_GRO_CB(p)->same_flow = 0;
- continue;
- }
- /* flush if Traffic Class fields are different */
- NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
- NAPI_GRO_CB(p)->flush |= flush;
- }
-
- NAPI_GRO_CB(skb)->flush |= flush;
-
- csum = skb->csum;
- skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
-
- pp = ops->gro_receive(head, skb);
-
- skb->csum = csum;
-
-out_unlock:
- rcu_read_unlock();
-
-out:
- NAPI_GRO_CB(skb)->flush |= flush;
-
- return pp;
-}
-
-static int ipv6_gro_complete(struct sk_buff *skb)
-{
- const struct inet6_protocol *ops;
- struct ipv6hdr *iph = ipv6_hdr(skb);
- int err = -ENOSYS;
-
- iph->payload_len = htons(skb->len - skb_network_offset(skb) -
- sizeof(*iph));
-
- rcu_read_lock();
- ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
- if (WARN_ON(!ops || !ops->gro_complete))
- goto out_unlock;
-
- err = ops->gro_complete(skb);
-
-out_unlock:
- rcu_read_unlock();
-
- return err;
-}
-
static struct packet_type ipv6_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_IPV6),
.func = ipv6_rcv,
- .gso_send_check = ipv6_gso_send_check,
- .gso_segment = ipv6_gso_segment,
- .gro_receive = ipv6_gro_receive,
- .gro_complete = ipv6_gro_complete,
};
static int __init ipv6_packet_init(void)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 7e6139508ee7..ecc35b93314b 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -44,7 +44,7 @@
#define IPV6HDR_BASELEN 8
struct tmp_ext {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
struct in6_addr saddr;
#endif
struct in6_addr daddr;
@@ -152,7 +152,7 @@ bad:
return false;
}
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
/**
* ipv6_rearrange_destopt - rearrange IPv6 destination options header
* @iph: IPv6 header
@@ -320,7 +320,7 @@ static void ah6_output_done(struct crypto_async_request *base, int err)
memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
memcpy(&top_iph->saddr, iph_ext, extlen);
#else
memcpy(&top_iph->daddr, iph_ext, extlen);
@@ -385,7 +385,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
memcpy(iph_ext, &top_iph->saddr, extlen);
#else
memcpy(iph_ext, &top_iph->daddr, extlen);
@@ -434,7 +434,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
memcpy(&top_iph->saddr, iph_ext, extlen);
#else
memcpy(&top_iph->daddr, iph_ext, extlen);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index cdf02be5f191..757a810d8f15 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -64,7 +64,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
int ishost = !net->ipv6.devconf_all->forwarding;
int err = 0;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (ipv6_addr_is_multicast(addr))
return -EINVAL;
@@ -84,7 +84,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
rt = rt6_lookup(net, addr, NULL, 0, 0);
if (rt) {
dev = rt->dst.dev;
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
} else if (ishost) {
err = -EADDRNOTAVAIL;
goto error;
@@ -189,6 +189,9 @@ void ipv6_sock_ac_close(struct sock *sk)
struct net *net = sock_net(sk);
int prev_index;
+ if (!np->ipv6_ac_list)
+ return;
+
write_lock_bh(&ipv6_sk_ac_lock);
pac = np->ipv6_ac_list;
np->ipv6_ac_list = NULL;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index be2b67d631e5..8edf2601065a 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -701,7 +701,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
err = -EINVAL;
goto exit_f;
}
- if (!capable(CAP_NET_RAW)) {
+ if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
err = -EPERM;
goto exit_f;
}
@@ -721,7 +721,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
err = -EINVAL;
goto exit_f;
}
- if (!capable(CAP_NET_RAW)) {
+ if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
err = -EPERM;
goto exit_f;
}
@@ -746,7 +746,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
err = -EINVAL;
goto exit_f;
}
- if (!capable(CAP_NET_RAW)) {
+ if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
err = -EPERM;
goto exit_f;
}
@@ -769,7 +769,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
switch (rthdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPV6_SRCRT_TYPE_2:
if (rthdr->hdrlen != 2 ||
rthdr->segments_left != 1) {
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index fa3d9c328092..473f628f9f20 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -43,56 +43,12 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/xfrm.h>
#endif
#include <asm/uaccess.h>
-int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
-{
- const unsigned char *nh = skb_network_header(skb);
- int packet_len = skb->tail - skb->network_header;
- struct ipv6_opt_hdr *hdr;
- int len;
-
- if (offset + 2 > packet_len)
- goto bad;
- hdr = (struct ipv6_opt_hdr *)(nh + offset);
- len = ((hdr->hdrlen + 1) << 3);
-
- if (offset + len > packet_len)
- goto bad;
-
- offset += 2;
- len -= 2;
-
- while (len > 0) {
- int opttype = nh[offset];
- int optlen;
-
- if (opttype == type)
- return offset;
-
- switch (opttype) {
- case IPV6_TLV_PAD1:
- optlen = 1;
- break;
- default:
- optlen = nh[offset + 1] + 2;
- if (optlen > len)
- goto bad;
- break;
- }
- offset += optlen;
- len -= optlen;
- }
- /* not_found */
- bad:
- return -1;
-}
-EXPORT_SYMBOL_GPL(ipv6_find_tlv);
-
/*
* Parsing tlv encoded headers.
*
@@ -224,7 +180,7 @@ bad:
Destination options header.
*****************************/
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
{
struct ipv6_destopt_hao *hao;
@@ -288,7 +244,7 @@ static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
#endif
static const struct tlvtype_proc tlvprocdestopt_lst[] = {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
{
.type = IPV6_TLV_HAO,
.func = ipv6_dest_hao,
@@ -300,7 +256,7 @@ static const struct tlvtype_proc tlvprocdestopt_lst[] = {
static int ipv6_destopt_rcv(struct sk_buff *skb)
{
struct inet6_skb_parm *opt = IP6CB(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
__u16 dstbuf;
#endif
struct dst_entry *dst = skb_dst(skb);
@@ -315,14 +271,14 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
}
opt->lastopt = opt->dst1 = skb_network_header_len(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
dstbuf = opt->dst1;
#endif
if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
opt = IP6CB(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
opt->nhoff = dstbuf;
#else
opt->nhoff = opt->dst1;
@@ -378,7 +334,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
looped_back:
if (hdr->segments_left == 0) {
switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPV6_SRCRT_TYPE_2:
/* Silently discard type 2 header unless it was
* processed by own
@@ -404,7 +360,7 @@ looped_back:
}
switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPV6_SRCRT_TYPE_2:
if (accept_source_route < 0)
goto unknown_rh;
@@ -461,7 +417,7 @@ looped_back:
addr += i - 1;
switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPV6_SRCRT_TYPE_2:
if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
(xfrm_address_t *)&ipv6_hdr(skb)->saddr,
@@ -528,12 +484,12 @@ unknown_rh:
static const struct inet6_protocol rthdr_protocol = {
.handler = ipv6_rthdr_rcv,
- .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
+ .flags = INET6_PROTO_NOPOLICY,
};
static const struct inet6_protocol destopt_protocol = {
.handler = ipv6_destopt_rcv,
- .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
+ .flags = INET6_PROTO_NOPOLICY,
};
static const struct inet6_protocol nodata_protocol = {
@@ -559,10 +515,10 @@ int __init ipv6_exthdrs_init(void)
out:
return ret;
-out_rthdr:
- inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
out_destopt:
inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+out_rthdr:
+ inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
goto out;
};
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index f73d59a14131..c5e83fae4df4 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -111,3 +111,171 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
return start;
}
EXPORT_SYMBOL(ipv6_skip_exthdr);
+
+int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
+{
+ const unsigned char *nh = skb_network_header(skb);
+ int packet_len = skb->tail - skb->network_header;
+ struct ipv6_opt_hdr *hdr;
+ int len;
+
+ if (offset + 2 > packet_len)
+ goto bad;
+ hdr = (struct ipv6_opt_hdr *)(nh + offset);
+ len = ((hdr->hdrlen + 1) << 3);
+
+ if (offset + len > packet_len)
+ goto bad;
+
+ offset += 2;
+ len -= 2;
+
+ while (len > 0) {
+ int opttype = nh[offset];
+ int optlen;
+
+ if (opttype == type)
+ return offset;
+
+ switch (opttype) {
+ case IPV6_TLV_PAD1:
+ optlen = 1;
+ break;
+ default:
+ optlen = nh[offset + 1] + 2;
+ if (optlen > len)
+ goto bad;
+ break;
+ }
+ offset += optlen;
+ len -= optlen;
+ }
+ /* not_found */
+ bad:
+ return -1;
+}
+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
+
+/*
+ * find the offset to specified header or the protocol number of last header
+ * if target < 0. "last header" is transport protocol header, ESP, or
+ * "No next header".
+ *
+ * Note that *offset is used as input/output parameter. an if it is not zero,
+ * then it must be a valid offset to an inner IPv6 header. This can be used
+ * to explore inner IPv6 header, eg. ICMPv6 error messages.
+ *
+ * If target header is found, its offset is set in *offset and return protocol
+ * number. Otherwise, return -1.
+ *
+ * If the first fragment doesn't contain the final protocol header or
+ * NEXTHDR_NONE it is considered invalid.
+ *
+ * Note that non-1st fragment is special case that "the protocol number
+ * of last header" is "next header" field in Fragment header. In this case,
+ * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
+ * isn't NULL.
+ *
+ * if flags is not NULL and it's a fragment, then the frag flag
+ * IP6_FH_F_FRAG will be set. If it's an AH header, the
+ * IP6_FH_F_AUTH flag is set and target < 0, then this function will
+ * stop at the AH header. If IP6_FH_F_SKIP_RH flag was passed, then this
+ * function will skip all those routing headers, where segements_left was 0.
+ */
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff, int *flags)
+{
+ unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+ u8 nexthdr = ipv6_hdr(skb)->nexthdr;
+ unsigned int len;
+ bool found;
+
+ if (fragoff)
+ *fragoff = 0;
+
+ if (*offset) {
+ struct ipv6hdr _ip6, *ip6;
+
+ ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
+ if (!ip6 || (ip6->version != 6)) {
+ printk(KERN_ERR "IPv6 header not found\n");
+ return -EBADMSG;
+ }
+ start = *offset + sizeof(struct ipv6hdr);
+ nexthdr = ip6->nexthdr;
+ }
+ len = skb->len - start;
+
+ do {
+ struct ipv6_opt_hdr _hdr, *hp;
+ unsigned int hdrlen;
+ found = (nexthdr == target);
+
+ if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
+ if (target < 0)
+ break;
+ return -ENOENT;
+ }
+
+ hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return -EBADMSG;
+
+ if (nexthdr == NEXTHDR_ROUTING) {
+ struct ipv6_rt_hdr _rh, *rh;
+
+ rh = skb_header_pointer(skb, start, sizeof(_rh),
+ &_rh);
+ if (rh == NULL)
+ return -EBADMSG;
+
+ if (flags && (*flags & IP6_FH_F_SKIP_RH) &&
+ rh->segments_left == 0)
+ found = false;
+ }
+
+ if (nexthdr == NEXTHDR_FRAGMENT) {
+ unsigned short _frag_off;
+ __be16 *fp;
+
+ if (flags) /* Indicate that this is a fragment */
+ *flags |= IP6_FH_F_FRAG;
+ fp = skb_header_pointer(skb,
+ start+offsetof(struct frag_hdr,
+ frag_off),
+ sizeof(_frag_off),
+ &_frag_off);
+ if (fp == NULL)
+ return -EBADMSG;
+
+ _frag_off = ntohs(*fp) & ~0x7;
+ if (_frag_off) {
+ if (target < 0 &&
+ ((!ipv6_ext_hdr(hp->nexthdr)) ||
+ hp->nexthdr == NEXTHDR_NONE)) {
+ if (fragoff)
+ *fragoff = _frag_off;
+ return hp->nexthdr;
+ }
+ return -ENOENT;
+ }
+ hdrlen = 8;
+ } else if (nexthdr == NEXTHDR_AUTH) {
+ if (flags && (*flags & IP6_FH_F_AUTH) && (target < 0))
+ break;
+ hdrlen = (hp->hdrlen + 2) << 2;
+ } else
+ hdrlen = ipv6_optlen(hp);
+
+ if (!found) {
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ start += hdrlen;
+ }
+ } while (!found);
+
+ *offset = start;
+ return nexthdr;
+}
+EXPORT_SYMBOL(ipv6_find_hdr);
+
diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c
new file mode 100644
index 000000000000..cf77f3abfd06
--- /dev/null
+++ b/net/ipv6/exthdrs_offload.c
@@ -0,0 +1,41 @@
+/*
+ * IPV6 GSO/GRO offload support
+ * Linux INET6 implementation
+ *
+ * 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.
+ *
+ * IPV6 Extension Header GSO/GRO support
+ */
+#include <net/protocol.h>
+#include "ip6_offload.h"
+
+static const struct net_offload rthdr_offload = {
+ .flags = INET6_PROTO_GSO_EXTHDR,
+};
+
+static const struct net_offload dstopt_offload = {
+ .flags = INET6_PROTO_GSO_EXTHDR,
+};
+
+int __init ipv6_exthdrs_offload_init(void)
+{
+ int ret;
+
+ ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
+ if (!ret)
+ goto out;
+
+ ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
+ if (!ret)
+ goto out_rt;
+
+out:
+ return ret;
+
+out_rt:
+ inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
+ goto out;
+}
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d9fb9110f607..2e1a432867c0 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -100,7 +100,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
goto out;
}
again:
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
rt = NULL;
goto out;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 24d69dbca4d6..b4a9fd51dae7 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -280,7 +280,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
return 0;
}
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
static void mip6_addr_swap(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 73f1a00a96af..dea17fd28e50 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -87,11 +87,13 @@ struct sock *__inet6_lookup_established(struct net *net,
rcu_read_lock();
begin:
sk_nulls_for_each_rcu(sk, node, &head->chain) {
- /* For IPV6 do the cheaper port and family tests first. */
- if (INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+ if (sk->sk_hash != hash)
+ continue;
+ if (likely(INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
goto begintw;
- if (!INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+ if (unlikely(!INET6_MATCH(sk, net, saddr, daddr,
+ ports, dif))) {
sock_put(sk);
goto begin;
}
@@ -104,12 +106,16 @@ begin:
begintw:
/* Must check for a TIME_WAIT'er before going to listener hash. */
sk_nulls_for_each_rcu(sk, node, &head->twchain) {
- if (INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+ if (sk->sk_hash != hash)
+ continue;
+ if (likely(INET6_TW_MATCH(sk, net, saddr, daddr,
+ ports, dif))) {
if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
sk = NULL;
goto out;
}
- if (!INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+ if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
+ ports, dif))) {
sock_put(sk);
goto begintw;
}
@@ -236,9 +242,12 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
/* Check TIME-WAIT sockets first. */
sk_nulls_for_each(sk2, node, &head->twchain) {
- tw = inet_twsk(sk2);
+ if (sk2->sk_hash != hash)
+ continue;
- if (INET6_TW_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) {
+ if (likely(INET6_TW_MATCH(sk2, net, saddr, daddr,
+ ports, dif))) {
+ tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
goto unique;
else
@@ -249,7 +258,9 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
/* And established part... */
sk_nulls_for_each(sk2, node, &head->chain) {
- if (INET6_MATCH(sk2, net, hash, saddr, daddr, ports, dif))
+ if (sk2->sk_hash != hash)
+ continue;
+ if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, dif)))
goto not_unique;
}
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 24995a93ef8c..710cafd2e1a9 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -672,6 +672,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
iter->rt6i_idev == rt->rt6i_idev &&
ipv6_addr_equal(&iter->rt6i_gateway,
&rt->rt6i_gateway)) {
+ if (rt->rt6i_nsiblings)
+ rt->rt6i_nsiblings = 0;
if (!(iter->rt6i_flags & RTF_EXPIRES))
return -EEXIST;
if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +682,21 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
rt6_set_expires(iter, rt->dst.expires);
return -EEXIST;
}
+ /* If we have the same destination and the same metric,
+ * but not the same gateway, then the route we try to
+ * add is sibling to this route, increment our counter
+ * of siblings, and later we will add our route to the
+ * list.
+ * Only static routes (which don't have flag
+ * RTF_EXPIRES) are used for ECMPv6.
+ *
+ * To avoid long list, we only had siblings if the
+ * route have a gateway.
+ */
+ if (rt->rt6i_flags & RTF_GATEWAY &&
+ !(rt->rt6i_flags & RTF_EXPIRES) &&
+ !(iter->rt6i_flags & RTF_EXPIRES))
+ rt->rt6i_nsiblings++;
}
if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +709,35 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
if (ins == &fn->leaf)
fn->rr_ptr = NULL;
+ /* Link this route to others same route. */
+ if (rt->rt6i_nsiblings) {
+ unsigned int rt6i_nsiblings;
+ struct rt6_info *sibling, *temp_sibling;
+
+ /* Find the first route that have the same metric */
+ sibling = fn->leaf;
+ while (sibling) {
+ if (sibling->rt6i_metric == rt->rt6i_metric) {
+ list_add_tail(&rt->rt6i_siblings,
+ &sibling->rt6i_siblings);
+ break;
+ }
+ sibling = sibling->dst.rt6_next;
+ }
+ /* For each sibling in the list, increment the counter of
+ * siblings. BUG() if counters does not match, list of siblings
+ * is broken!
+ */
+ rt6i_nsiblings = 0;
+ list_for_each_entry_safe(sibling, temp_sibling,
+ &rt->rt6i_siblings, rt6i_siblings) {
+ sibling->rt6i_nsiblings++;
+ BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
+ rt6i_nsiblings++;
+ }
+ BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
+ }
+
/*
* insert node
*/
@@ -1193,6 +1239,17 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
if (fn->rr_ptr == rt)
fn->rr_ptr = NULL;
+ /* Remove this entry from other siblings */
+ if (rt->rt6i_nsiblings) {
+ struct rt6_info *sibling, *next_sibling;
+
+ list_for_each_entry_safe(sibling, next_sibling,
+ &rt->rt6i_siblings, rt6i_siblings)
+ sibling->rt6i_nsiblings--;
+ rt->rt6i_nsiblings = 0;
+ list_del_init(&rt->rt6i_siblings);
+ }
+
/* Adjust walkers */
read_lock(&fib6_walker_lock);
FOR_WALKERS(w) {
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 90bbefb57943..29124b7a04c8 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -519,7 +519,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
}
read_unlock_bh(&ip6_sk_fl_lock);
- if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
+ if (freq.flr_share == IPV6_FL_S_NONE &&
+ ns_capable(net->user_ns, CAP_NET_ADMIN)) {
fl = fl_lookup(net, freq.flr_label);
if (fl) {
err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index d5cb3c4e66f8..867466c96aac 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -109,21 +109,6 @@ static u32 HASH_ADDR(const struct in6_addr *addr)
#define tunnels_r tunnels[2]
#define tunnels_l tunnels[1]
#define tunnels_wc tunnels[0]
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
- for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- struct u64_stats_sync syncp;
-};
static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot)
@@ -181,7 +166,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
ARPHRD_ETHER : ARPHRD_IP6GRE;
int score, cand_score = 4;
- for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
if (!ipv6_addr_equal(local, &t->parms.laddr) ||
!ipv6_addr_equal(remote, &t->parms.raddr) ||
key != t->parms.i_key ||
@@ -206,7 +191,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) {
if (!ipv6_addr_equal(remote, &t->parms.raddr) ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
@@ -230,7 +215,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) {
if ((!ipv6_addr_equal(local, &t->parms.laddr) &&
(!ipv6_addr_equal(local, &t->parms.raddr) ||
!ipv6_addr_is_multicast(local))) ||
@@ -256,7 +241,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
}
}
- for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
+ for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) {
if (t->parms.i_key != key ||
!(t->dev->flags & IFF_UP))
continue;
@@ -1069,7 +1054,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
dev->mtu = IPV6_MIN_MTU;
}
}
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
t->hlen = addend;
@@ -1161,7 +1146,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -1209,7 +1194,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
if (dev == ign->fb_tunnel_dev) {
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
new file mode 100644
index 000000000000..f26f0da7f095
--- /dev/null
+++ b/net/ipv6/ip6_offload.c
@@ -0,0 +1,282 @@
+/*
+ * IPV6 GSO/GRO offload support
+ * Linux INET6 implementation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/printk.h>
+
+#include <net/protocol.h>
+#include <net/ipv6.h>
+
+#include "ip6_offload.h"
+
+static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
+{
+ const struct net_offload *ops = NULL;
+
+ for (;;) {
+ struct ipv6_opt_hdr *opth;
+ int len;
+
+ if (proto != NEXTHDR_HOP) {
+ ops = rcu_dereference(inet6_offloads[proto]);
+
+ if (unlikely(!ops))
+ break;
+
+ if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
+ break;
+ }
+
+ if (unlikely(!pskb_may_pull(skb, 8)))
+ break;
+
+ opth = (void *)skb->data;
+ len = ipv6_optlen(opth);
+
+ if (unlikely(!pskb_may_pull(skb, len)))
+ break;
+
+ proto = opth->nexthdr;
+ __skb_pull(skb, len);
+ }
+
+ return proto;
+}
+
+static int ipv6_gso_send_check(struct sk_buff *skb)
+{
+ const struct ipv6hdr *ipv6h;
+ const struct net_offload *ops;
+ int err = -EINVAL;
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+ goto out;
+
+ ipv6h = ipv6_hdr(skb);
+ __skb_pull(skb, sizeof(*ipv6h));
+ err = -EPROTONOSUPPORT;
+
+ rcu_read_lock();
+ ops = rcu_dereference(inet6_offloads[
+ ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
+
+ if (likely(ops && ops->callbacks.gso_send_check)) {
+ skb_reset_transport_header(skb);
+ err = ops->callbacks.gso_send_check(skb);
+ }
+ rcu_read_unlock();
+
+out:
+ return err;
+}
+
+static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
+ netdev_features_t features)
+{
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ struct ipv6hdr *ipv6h;
+ const struct net_offload *ops;
+ int proto;
+ struct frag_hdr *fptr;
+ unsigned int unfrag_ip6hlen;
+ u8 *prevhdr;
+ int offset = 0;
+
+ if (!(features & NETIF_F_V6_CSUM))
+ features &= ~NETIF_F_SG;
+
+ if (unlikely(skb_shinfo(skb)->gso_type &
+ ~(SKB_GSO_UDP |
+ SKB_GSO_DODGY |
+ SKB_GSO_TCP_ECN |
+ SKB_GSO_TCPV6 |
+ 0)))
+ goto out;
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+ goto out;
+
+ ipv6h = ipv6_hdr(skb);
+ __skb_pull(skb, sizeof(*ipv6h));
+ segs = ERR_PTR(-EPROTONOSUPPORT);
+
+ proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+ rcu_read_lock();
+ ops = rcu_dereference(inet6_offloads[proto]);
+ if (likely(ops && ops->callbacks.gso_segment)) {
+ skb_reset_transport_header(skb);
+ segs = ops->callbacks.gso_segment(skb, features);
+ }
+ rcu_read_unlock();
+
+ if (IS_ERR(segs))
+ goto out;
+
+ for (skb = segs; skb; skb = skb->next) {
+ ipv6h = ipv6_hdr(skb);
+ ipv6h->payload_len = htons(skb->len - skb->mac_len -
+ sizeof(*ipv6h));
+ if (proto == IPPROTO_UDP) {
+ unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+ fptr = (struct frag_hdr *)(skb_network_header(skb) +
+ unfrag_ip6hlen);
+ fptr->frag_off = htons(offset);
+ if (skb->next != NULL)
+ fptr->frag_off |= htons(IP6_MF);
+ offset += (ntohs(ipv6h->payload_len) -
+ sizeof(struct frag_hdr));
+ }
+ }
+
+out:
+ return segs;
+}
+
+static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ const struct net_offload *ops;
+ struct sk_buff **pp = NULL;
+ struct sk_buff *p;
+ struct ipv6hdr *iph;
+ unsigned int nlen;
+ unsigned int hlen;
+ unsigned int off;
+ int flush = 1;
+ int proto;
+ __wsum csum;
+
+ off = skb_gro_offset(skb);
+ hlen = off + sizeof(*iph);
+ iph = skb_gro_header_fast(skb, off);
+ if (skb_gro_header_hard(skb, hlen)) {
+ iph = skb_gro_header_slow(skb, hlen, off);
+ if (unlikely(!iph))
+ goto out;
+ }
+
+ skb_gro_pull(skb, sizeof(*iph));
+ skb_set_transport_header(skb, skb_gro_offset(skb));
+
+ flush += ntohs(iph->payload_len) != skb_gro_len(skb);
+
+ rcu_read_lock();
+ proto = iph->nexthdr;
+ ops = rcu_dereference(inet6_offloads[proto]);
+ if (!ops || !ops->callbacks.gro_receive) {
+ __pskb_pull(skb, skb_gro_offset(skb));
+ proto = ipv6_gso_pull_exthdrs(skb, proto);
+ skb_gro_pull(skb, -skb_transport_offset(skb));
+ skb_reset_transport_header(skb);
+ __skb_push(skb, skb_gro_offset(skb));
+
+ ops = rcu_dereference(inet6_offloads[proto]);
+ if (!ops || !ops->callbacks.gro_receive)
+ goto out_unlock;
+
+ iph = ipv6_hdr(skb);
+ }
+
+ NAPI_GRO_CB(skb)->proto = proto;
+
+ flush--;
+ nlen = skb_network_header_len(skb);
+
+ for (p = *head; p; p = p->next) {
+ const struct ipv6hdr *iph2;
+ __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
+
+ if (!NAPI_GRO_CB(p)->same_flow)
+ continue;
+
+ iph2 = ipv6_hdr(p);
+ first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
+
+ /* All fields must match except length and Traffic Class. */
+ if (nlen != skb_network_header_len(p) ||
+ (first_word & htonl(0xF00FFFFF)) ||
+ memcmp(&iph->nexthdr, &iph2->nexthdr,
+ nlen - offsetof(struct ipv6hdr, nexthdr))) {
+ NAPI_GRO_CB(p)->same_flow = 0;
+ continue;
+ }
+ /* flush if Traffic Class fields are different */
+ NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
+ NAPI_GRO_CB(p)->flush |= flush;
+ }
+
+ NAPI_GRO_CB(skb)->flush |= flush;
+
+ csum = skb->csum;
+ skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
+
+ pp = ops->callbacks.gro_receive(head, skb);
+
+ skb->csum = csum;
+
+out_unlock:
+ rcu_read_unlock();
+
+out:
+ NAPI_GRO_CB(skb)->flush |= flush;
+
+ return pp;
+}
+
+static int ipv6_gro_complete(struct sk_buff *skb)
+{
+ const struct net_offload *ops;
+ struct ipv6hdr *iph = ipv6_hdr(skb);
+ int err = -ENOSYS;
+
+ iph->payload_len = htons(skb->len - skb_network_offset(skb) -
+ sizeof(*iph));
+
+ rcu_read_lock();
+ ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]);
+ if (WARN_ON(!ops || !ops->callbacks.gro_complete))
+ goto out_unlock;
+
+ err = ops->callbacks.gro_complete(skb);
+
+out_unlock:
+ rcu_read_unlock();
+
+ return err;
+}
+
+static struct packet_offload ipv6_packet_offload __read_mostly = {
+ .type = cpu_to_be16(ETH_P_IPV6),
+ .callbacks = {
+ .gso_send_check = ipv6_gso_send_check,
+ .gso_segment = ipv6_gso_segment,
+ .gro_receive = ipv6_gro_receive,
+ .gro_complete = ipv6_gro_complete,
+ },
+};
+
+static int __init ipv6_offload_init(void)
+{
+
+ if (tcpv6_offload_init() < 0)
+ pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
+ if (udp_offload_init() < 0)
+ pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
+ if (ipv6_exthdrs_offload_init() < 0)
+ pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);
+
+ dev_add_offload(&ipv6_packet_offload);
+ return 0;
+}
+
+fs_initcall(ipv6_offload_init);
diff --git a/net/ipv6/ip6_offload.h b/net/ipv6/ip6_offload.h
new file mode 100644
index 000000000000..2e155c651b35
--- /dev/null
+++ b/net/ipv6/ip6_offload.h
@@ -0,0 +1,18 @@
+/*
+ * IPV6 GSO/GRO offload support
+ * Linux INET6 implementation
+ *
+ * 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 __ip6_offload_h
+#define __ip6_offload_h
+
+int ipv6_exthdrs_offload_init(void);
+int udp_offload_init(void);
+int tcpv6_offload_init(void);
+
+#endif
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index aece3e792f84..5552d13ae92f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -538,78 +538,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->tc_index = from->tc_index;
#endif
nf_copy(to, from);
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
- defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
to->nf_trace = from->nf_trace;
#endif
skb_copy_secmark(to, from);
}
-int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
-{
- u16 offset = sizeof(struct ipv6hdr);
- struct ipv6_opt_hdr *exthdr =
- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
- unsigned int packet_len = skb->tail - skb->network_header;
- int found_rhdr = 0;
- *nexthdr = &ipv6_hdr(skb)->nexthdr;
-
- while (offset + 1 <= packet_len) {
-
- switch (**nexthdr) {
-
- case NEXTHDR_HOP:
- break;
- case NEXTHDR_ROUTING:
- found_rhdr = 1;
- break;
- case NEXTHDR_DEST:
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
- break;
-#endif
- if (found_rhdr)
- return offset;
- break;
- default :
- return offset;
- }
-
- offset += ipv6_optlen(exthdr);
- *nexthdr = &exthdr->nexthdr;
- exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
- offset);
- }
-
- return offset;
-}
-
-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
-{
- static atomic_t ipv6_fragmentation_id;
- int old, new;
-
- if (rt && !(rt->dst.flags & DST_NOPEER)) {
- struct inet_peer *peer;
- struct net *net;
-
- net = dev_net(rt->dst.dev);
- peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
- if (peer) {
- fhdr->identification = htonl(inet_getid(peer, 0));
- inet_putpeer(peer);
- return;
- }
- }
- do {
- old = atomic_read(&ipv6_fragmentation_id);
- new = old + 1;
- if (!new)
- new = 1;
- } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
- fhdr->identification = htonl(new);
-}
-
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
{
struct sk_buff *frag;
@@ -756,7 +690,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
if (err == 0) {
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
IPSTATS_MIB_FRAGOKS);
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return 0;
}
@@ -768,7 +702,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
IPSTATS_MIB_FRAGFAILS);
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return err;
slow_path_clean:
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index cb7e2ded6f08..a14f28b280f5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -74,6 +74,10 @@ MODULE_ALIAS_NETDEV("ip6tnl0");
#define HASH_SIZE_SHIFT 5
#define HASH_SIZE (1 << HASH_SIZE_SHIFT)
+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");
+
static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2)
{
u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2);
@@ -83,6 +87,7 @@ static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2)
static int ip6_tnl_dev_init(struct net_device *dev);
static void ip6_tnl_dev_setup(struct net_device *dev);
+static struct rtnl_link_ops ip6_link_ops __read_mostly;
static int ip6_tnl_net_id __read_mostly;
struct ip6_tnl_net {
@@ -94,14 +99,6 @@ struct ip6_tnl_net {
struct ip6_tnl __rcu **tnls[2];
};
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long tx_bytes;
-} __attribute__((aligned(4*sizeof(unsigned long))));
-
static struct net_device_stats *ip6_get_stats(struct net_device *dev)
{
struct pcpu_tstats sum = { 0 };
@@ -258,6 +255,33 @@ static void ip6_dev_free(struct net_device *dev)
free_netdev(dev);
}
+static int ip6_tnl_create2(struct net_device *dev)
+{
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct net *net = dev_net(dev);
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ int err;
+
+ t = netdev_priv(dev);
+ err = ip6_tnl_dev_init(dev);
+ if (err < 0)
+ goto out;
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out;
+
+ strcpy(t->parms.name, dev->name);
+ dev->rtnl_link_ops = &ip6_link_ops;
+
+ dev_hold(dev);
+ ip6_tnl_link(ip6n, t);
+ return 0;
+
+out:
+ return err;
+}
+
/**
* ip6_tnl_create - create a new tunnel
* @p: tunnel parameters
@@ -276,7 +300,6 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
struct ip6_tnl *t;
char name[IFNAMSIZ];
int err;
- struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
if (p->name[0])
strlcpy(name, p->name, IFNAMSIZ);
@@ -291,17 +314,10 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
t = netdev_priv(dev);
t->parms = *p;
- err = ip6_tnl_dev_init(dev);
+ err = ip6_tnl_create2(dev);
if (err < 0)
goto failed_free;
- if ((err = register_netdevice(dev)) < 0)
- goto failed_free;
-
- strcpy(t->parms.name, dev->name);
-
- dev_hold(dev);
- ip6_tnl_link(ip6n, t);
return t;
failed_free:
@@ -663,8 +679,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
icmpv6_send(skb2, rel_type, rel_code, rel_info);
- if (rt)
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
kfree_skb(skb2);
}
@@ -672,28 +687,26 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
}
-static void ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
- const struct ipv6hdr *ipv6h,
- struct sk_buff *skb)
+static int ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
+ const struct ipv6hdr *ipv6h,
+ struct sk_buff *skb)
{
__u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK;
if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield);
- if (INET_ECN_is_ce(dsfield))
- IP_ECN_set_ce(ip_hdr(skb));
+ return IP6_ECN_decapsulate(ipv6h, skb);
}
-static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
- const struct ipv6hdr *ipv6h,
- struct sk_buff *skb)
+static int ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
+ const struct ipv6hdr *ipv6h,
+ struct sk_buff *skb)
{
if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb));
- if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h)))
- IP6_ECN_set_ce(ipv6_hdr(skb));
+ return IP6_ECN_decapsulate(ipv6h, skb);
}
__u32 ip6_tnl_get_cap(struct ip6_tnl *t,
@@ -757,12 +770,13 @@ EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl);
static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
__u8 ipproto,
- void (*dscp_ecn_decapsulate)(const struct ip6_tnl *t,
- const struct ipv6hdr *ipv6h,
- struct sk_buff *skb))
+ int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t,
+ const struct ipv6hdr *ipv6h,
+ struct sk_buff *skb))
{
struct ip6_tnl *t;
const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ int err;
rcu_read_lock();
@@ -792,14 +806,26 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
skb->pkt_type = PACKET_HOST;
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+ __skb_tunnel_rx(skb, t->dev);
+
+ err = dscp_ecn_decapsulate(t, ipv6h, skb);
+ if (unlikely(err)) {
+ if (log_ecn_error)
+ net_info_ratelimited("non-ECT from %pI6 with dsfield=%#x\n",
+ &ipv6h->saddr,
+ ipv6_get_dsfield(ipv6h));
+ if (err > 1) {
+ ++t->dev->stats.rx_frame_errors;
+ ++t->dev->stats.rx_errors;
+ rcu_read_unlock();
+ goto discard;
+ }
+ }
+
tstats = this_cpu_ptr(t->dev->tstats);
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
- __skb_tunnel_rx(skb, t->dev);
-
- dscp_ecn_decapsulate(t, ipv6h, skb);
-
netif_rx(skb);
rcu_read_unlock();
@@ -1208,7 +1234,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
if (dev->mtu < IPV6_MIN_MTU)
dev->mtu = IPV6_MIN_MTU;
}
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
}
@@ -1237,6 +1263,20 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p)
return 0;
}
+static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
+{
+ struct net *net = dev_net(t->dev);
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ int err;
+
+ ip6_tnl_unlink(ip6n, t);
+ synchronize_net();
+ err = ip6_tnl_change(t, p);
+ ip6_tnl_link(ip6n, t);
+ netdev_state_change(t->dev);
+ return err;
+}
+
static void
ip6_tnl_parm_from_user(struct __ip6_tnl_parm *p, const struct ip6_tnl_parm *u)
{
@@ -1325,7 +1365,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
err = -EFAULT;
if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
@@ -1345,11 +1385,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
} else
t = netdev_priv(dev);
- ip6_tnl_unlink(ip6n, t);
- synchronize_net();
- err = ip6_tnl_change(t, &p1);
- ip6_tnl_link(ip6n, t);
- netdev_state_change(dev);
+ err = ip6_tnl_update(t, &p1);
}
if (t) {
err = 0;
@@ -1362,7 +1398,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
if (dev == ip6n->fb_tnl_dev) {
@@ -1505,6 +1541,164 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
return 0;
}
+static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ u8 proto;
+
+ if (!data)
+ return 0;
+
+ proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+ if (proto != IPPROTO_IPV6 &&
+ proto != IPPROTO_IPIP &&
+ proto != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void ip6_tnl_netlink_parms(struct nlattr *data[],
+ struct __ip6_tnl_parm *parms)
+{
+ memset(parms, 0, sizeof(*parms));
+
+ if (!data)
+ return;
+
+ if (data[IFLA_IPTUN_LINK])
+ parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+ if (data[IFLA_IPTUN_LOCAL])
+ nla_memcpy(&parms->laddr, data[IFLA_IPTUN_LOCAL],
+ sizeof(struct in6_addr));
+
+ if (data[IFLA_IPTUN_REMOTE])
+ nla_memcpy(&parms->raddr, data[IFLA_IPTUN_REMOTE],
+ sizeof(struct in6_addr));
+
+ if (data[IFLA_IPTUN_TTL])
+ parms->hop_limit = nla_get_u8(data[IFLA_IPTUN_TTL]);
+
+ if (data[IFLA_IPTUN_ENCAP_LIMIT])
+ parms->encap_limit = nla_get_u8(data[IFLA_IPTUN_ENCAP_LIMIT]);
+
+ if (data[IFLA_IPTUN_FLOWINFO])
+ parms->flowinfo = nla_get_be32(data[IFLA_IPTUN_FLOWINFO]);
+
+ if (data[IFLA_IPTUN_FLAGS])
+ parms->flags = nla_get_u32(data[IFLA_IPTUN_FLAGS]);
+
+ if (data[IFLA_IPTUN_PROTO])
+ parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+}
+
+static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct net *net = dev_net(dev);
+ struct ip6_tnl *nt;
+
+ nt = netdev_priv(dev);
+ ip6_tnl_netlink_parms(data, &nt->parms);
+
+ if (ip6_tnl_locate(net, &nt->parms, 0))
+ return -EEXIST;
+
+ return ip6_tnl_create2(dev);
+}
+
+static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[])
+{
+ struct ip6_tnl *t;
+ struct __ip6_tnl_parm p;
+ struct net *net = dev_net(dev);
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+ if (dev == ip6n->fb_tnl_dev)
+ return -EINVAL;
+
+ ip6_tnl_netlink_parms(data, &p);
+
+ t = ip6_tnl_locate(net, &p, 0);
+
+ if (t) {
+ if (t->dev != dev)
+ return -EEXIST;
+ } else
+ t = netdev_priv(dev);
+
+ return ip6_tnl_update(t, &p);
+}
+
+static size_t ip6_tnl_get_size(const struct net_device *dev)
+{
+ return
+ /* IFLA_IPTUN_LINK */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_LOCAL */
+ nla_total_size(sizeof(struct in6_addr)) +
+ /* IFLA_IPTUN_REMOTE */
+ nla_total_size(sizeof(struct in6_addr)) +
+ /* IFLA_IPTUN_TTL */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_ENCAP_LIMIT */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_FLOWINFO */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_FLAGS */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_PROTO */
+ nla_total_size(1) +
+ 0;
+}
+
+static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct ip6_tnl *tunnel = netdev_priv(dev);
+ struct __ip6_tnl_parm *parm = &tunnel->parms;
+
+ if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+ nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr),
+ &parm->raddr) ||
+ nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
+ &parm->laddr) ||
+ nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) ||
+ nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) ||
+ nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) ||
+ nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) ||
+ nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static const struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
+ [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
+ [IFLA_IPTUN_LOCAL] = { .len = sizeof(struct in6_addr) },
+ [IFLA_IPTUN_REMOTE] = { .len = sizeof(struct in6_addr) },
+ [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
+ [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
+ [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
+ [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
+ [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
+};
+
+static struct rtnl_link_ops ip6_link_ops __read_mostly = {
+ .kind = "ip6tnl",
+ .maxtype = IFLA_IPTUN_MAX,
+ .policy = ip6_tnl_policy,
+ .priv_size = sizeof(struct ip6_tnl),
+ .setup = ip6_tnl_dev_setup,
+ .validate = ip6_tnl_validate,
+ .newlink = ip6_tnl_newlink,
+ .changelink = ip6_tnl_changelink,
+ .get_size = ip6_tnl_get_size,
+ .fill_info = ip6_tnl_fill_info,
+};
+
static struct xfrm6_tunnel ip4ip6_handler __read_mostly = {
.handler = ip4ip6_rcv,
.err_handler = ip4ip6_err,
@@ -1613,9 +1807,14 @@ static int __init ip6_tunnel_init(void)
pr_err("%s: can't register ip6ip6\n", __func__);
goto out_ip6ip6;
}
+ err = rtnl_link_register(&ip6_link_ops);
+ if (err < 0)
+ goto rtnl_link_failed;
return 0;
+rtnl_link_failed:
+ xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
out_ip6ip6:
xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
out_ip4ip6:
@@ -1630,6 +1829,7 @@ out_pernet:
static void __exit ip6_tunnel_cleanup(void)
{
+ rtnl_link_unregister(&ip6_link_ops);
if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET))
pr_info("%s: can't deregister ip4ip6\n", __func__);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index f7c7c6319720..26dcdec9e3a5 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -52,6 +52,7 @@
#include <linux/netfilter_ipv6.h>
#include <linux/export.h>
#include <net/ip6_checksum.h>
+#include <linux/netconf.h>
struct mr6_table {
struct list_head list;
@@ -66,8 +67,8 @@ struct mr6_table {
struct mif_device vif6_table[MAXMIFS];
int maxvif;
atomic_t cache_resolve_queue_len;
- int mroute_do_assert;
- int mroute_do_pim;
+ bool mroute_do_assert;
+ bool mroute_do_pim;
#ifdef CONFIG_IPV6_PIMSM_V2
int mroute_reg_vif_num;
#endif
@@ -115,6 +116,8 @@ static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
mifi_t mifi, int assert);
static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
struct mfc6_cache *c, struct rtmsg *rtm);
+static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
+ int cmd);
static int ip6mr_rtm_dumproute(struct sk_buff *skb,
struct netlink_callback *cb);
static void mroute_clean_tables(struct mr6_table *mrt);
@@ -805,8 +808,12 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
dev_set_allmulti(dev, -1);
in6_dev = __in6_dev_get(dev);
- if (in6_dev)
+ if (in6_dev) {
in6_dev->cnf.mc_forwarding--;
+ inet6_netconf_notify_devconf(dev_net(dev),
+ NETCONFA_MC_FORWARDING,
+ dev->ifindex, &in6_dev->cnf);
+ }
if (v->flags & MIFF_REGISTER)
unregister_netdevice_queue(dev, head);
@@ -865,6 +872,7 @@ static void ipmr_do_expire_process(struct mr6_table *mrt)
}
list_del(&c->list);
+ mr6_netlink_event(mrt, c, RTM_DELROUTE);
ip6mr_destroy_unres(mrt, c);
}
@@ -958,8 +966,12 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
}
in6_dev = __in6_dev_get(dev);
- if (in6_dev)
+ if (in6_dev) {
in6_dev->cnf.mc_forwarding++;
+ inet6_netconf_notify_devconf(dev_net(dev),
+ NETCONFA_MC_FORWARDING,
+ dev->ifindex, &in6_dev->cnf);
+ }
/*
* Fill in the VIF structures
@@ -1211,6 +1223,7 @@ ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
atomic_inc(&mrt->cache_resolve_queue_len);
list_add(&c->list, &mrt->mfc6_unres_queue);
+ mr6_netlink_event(mrt, c, RTM_NEWROUTE);
ipmr_do_expire_process(mrt);
}
@@ -1248,6 +1261,7 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
list_del(&c->list);
write_unlock_bh(&mrt_lock);
+ mr6_netlink_event(mrt, c, RTM_DELROUTE);
ip6mr_cache_free(c);
return 0;
}
@@ -1412,6 +1426,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
if (!mrtsock)
c->mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock);
+ mr6_netlink_event(mrt, c, RTM_NEWROUTE);
return 0;
}
@@ -1456,6 +1471,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
ip6mr_cache_resolve(net, mrt, uc, c);
ip6mr_cache_free(uc);
}
+ mr6_netlink_event(mrt, c, RTM_NEWROUTE);
return 0;
}
@@ -1489,6 +1505,7 @@ static void mroute_clean_tables(struct mr6_table *mrt)
list_del(&c->list);
write_unlock_bh(&mrt_lock);
+ mr6_netlink_event(mrt, c, RTM_DELROUTE);
ip6mr_cache_free(c);
}
}
@@ -1497,6 +1514,7 @@ static void mroute_clean_tables(struct mr6_table *mrt)
spin_lock_bh(&mfc_unres_lock);
list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
list_del(&c->list);
+ mr6_netlink_event(mrt, c, RTM_DELROUTE);
ip6mr_destroy_unres(mrt, c);
}
spin_unlock_bh(&mfc_unres_lock);
@@ -1513,6 +1531,9 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
if (likely(mrt->mroute6_sk == NULL)) {
mrt->mroute6_sk = sk;
net->ipv6.devconf_all->mc_forwarding++;
+ inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv6.devconf_all);
}
else
err = -EADDRINUSE;
@@ -1535,6 +1556,10 @@ int ip6mr_sk_done(struct sock *sk)
write_lock_bh(&mrt_lock);
mrt->mroute6_sk = NULL;
net->ipv6.devconf_all->mc_forwarding--;
+ inet6_netconf_notify_devconf(net,
+ NETCONFA_MC_FORWARDING,
+ NETCONFA_IFINDEX_ALL,
+ net->ipv6.devconf_all);
write_unlock_bh(&mrt_lock);
mroute_clean_tables(mrt);
@@ -1583,7 +1608,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
return -ENOENT;
if (optname != MRT6_INIT) {
- if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN))
+ if (sk != mrt->mroute6_sk && !ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EACCES;
}
@@ -1646,9 +1671,12 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
case MRT6_ASSERT:
{
int v;
+
+ if (optlen != sizeof(v))
+ return -EINVAL;
if (get_user(v, (int __user *)optval))
return -EFAULT;
- mrt->mroute_do_assert = !!v;
+ mrt->mroute_do_assert = v;
return 0;
}
@@ -1656,6 +1684,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
case MRT6_PIM:
{
int v;
+
+ if (optlen != sizeof(v))
+ return -EINVAL;
if (get_user(v, (int __user *)optval))
return -EFAULT;
v = !!v;
@@ -2097,8 +2128,8 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
{
int ct;
struct rtnexthop *nhp;
- u8 *b = skb_tail_pointer(skb);
- struct rtattr *mp_head;
+ struct nlattr *mp_attr;
+ struct rta_mfc_stats mfcs;
/* If cache is unresolved, don't try to parse IIF and OIF */
if (c->mf6c_parent >= MAXMIFS)
@@ -2107,28 +2138,35 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
if (MIF_EXISTS(mrt, c->mf6c_parent) &&
nla_put_u32(skb, RTA_IIF, mrt->vif6_table[c->mf6c_parent].dev->ifindex) < 0)
return -EMSGSIZE;
-
- mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
+ mp_attr = nla_nest_start(skb, RTA_MULTIPATH);
+ if (mp_attr == NULL)
+ return -EMSGSIZE;
for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
- if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
- goto rtattr_failure;
- nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+ nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
+ if (nhp == NULL) {
+ nla_nest_cancel(skb, mp_attr);
+ return -EMSGSIZE;
+ }
+
nhp->rtnh_flags = 0;
nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
nhp->rtnh_len = sizeof(*nhp);
}
}
- mp_head->rta_type = RTA_MULTIPATH;
- mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
+
+ nla_nest_end(skb, mp_attr);
+
+ mfcs.mfcs_packets = c->mfc_un.res.pkt;
+ mfcs.mfcs_bytes = c->mfc_un.res.bytes;
+ mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
+ if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0)
+ return -EMSGSIZE;
+
rtm->rtm_type = RTN_MULTICAST;
return 1;
-
-rtattr_failure:
- nlmsg_trim(skb, b);
- return -EMSGSIZE;
}
int ip6mr_get_route(struct net *net,
@@ -2202,31 +2240,38 @@ int ip6mr_get_route(struct net *net,
}
static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
- u32 portid, u32 seq, struct mfc6_cache *c)
+ u32 portid, u32 seq, struct mfc6_cache *c, int cmd)
{
struct nlmsghdr *nlh;
struct rtmsg *rtm;
+ int err;
- nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
+ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
if (nlh == NULL)
return -EMSGSIZE;
rtm = nlmsg_data(nlh);
- rtm->rtm_family = RTNL_FAMILY_IPMR;
+ rtm->rtm_family = RTNL_FAMILY_IP6MR;
rtm->rtm_dst_len = 128;
rtm->rtm_src_len = 128;
rtm->rtm_tos = 0;
rtm->rtm_table = mrt->id;
if (nla_put_u32(skb, RTA_TABLE, mrt->id))
goto nla_put_failure;
+ rtm->rtm_type = RTN_MULTICAST;
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
- rtm->rtm_protocol = RTPROT_UNSPEC;
+ if (c->mfc_flags & MFC_STATIC)
+ rtm->rtm_protocol = RTPROT_STATIC;
+ else
+ rtm->rtm_protocol = RTPROT_MROUTED;
rtm->rtm_flags = 0;
if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) ||
nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp))
goto nla_put_failure;
- if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0)
+ err = __ip6mr_fill_mroute(mrt, skb, c, rtm);
+ /* do not break the dump if cache is unresolved */
+ if (err < 0 && err != -ENOENT)
goto nla_put_failure;
return nlmsg_end(skb, nlh);
@@ -2236,6 +2281,52 @@ nla_put_failure:
return -EMSGSIZE;
}
+static int mr6_msgsize(bool unresolved, int maxvif)
+{
+ size_t len =
+ NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
+ + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
+ ;
+
+ if (!unresolved)
+ len = len
+ + nla_total_size(4) /* RTA_IIF */
+ + nla_total_size(0) /* RTA_MULTIPATH */
+ + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
+ /* RTA_MFC_STATS */
+ + nla_total_size(sizeof(struct rta_mfc_stats))
+ ;
+
+ return len;
+}
+
+static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
+ int cmd)
+{
+ struct net *net = read_pnet(&mrt->net);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(mr6_msgsize(mfc->mf6c_parent >= MAXMIFS, mrt->maxvif),
+ GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+ if (err < 0)
+ goto errout;
+
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
+ return;
+
+errout:
+ kfree_skb(skb);
+ if (err < 0)
+ rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
+}
+
static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
@@ -2262,13 +2353,29 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
if (ip6mr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
- mfc) < 0)
+ mfc, RTM_NEWROUTE) < 0)
goto done;
next_entry:
e++;
}
e = s_e = 0;
}
+ spin_lock_bh(&mfc_unres_lock);
+ list_for_each_entry(mfc, &mrt->mfc6_unres_queue, list) {
+ if (e < s_e)
+ goto next_entry2;
+ if (ip6mr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ mfc, RTM_NEWROUTE) < 0) {
+ spin_unlock_bh(&mfc_unres_lock);
+ goto done;
+ }
+next_entry2:
+ e++;
+ }
+ spin_unlock_bh(&mfc_unres_lock);
+ e = s_e = 0;
s_h = 0;
next_table:
t++;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index e02faed6d17e..ee94d31c9d4d 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -343,7 +343,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
case IPV6_TRANSPARENT:
- if (valbool && !capable(CAP_NET_ADMIN) && !capable(CAP_NET_RAW)) {
+ if (valbool && !ns_capable(net->user_ns, CAP_NET_ADMIN) &&
+ !ns_capable(net->user_ns, CAP_NET_RAW)) {
retv = -EPERM;
break;
}
@@ -381,7 +382,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
/* hop-by-hop / destination options are privileged option */
retv = -EPERM;
- if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
+ if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
break;
opt = ipv6_renew_options(sk, np->opt, optname,
@@ -397,7 +398,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
if (optname == IPV6_RTHDR && opt && opt->srcrt) {
struct ipv6_rt_hdr *rthdr = opt->srcrt;
switch (rthdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPV6_SRCRT_TYPE_2:
if (rthdr->hdrlen != 2 ||
rthdr->segments_left != 1)
@@ -754,7 +755,7 @@ done:
case IPV6_IPSEC_POLICY:
case IPV6_XFRM_POLICY:
retv = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
break;
retv = xfrm_user_policy(sk, optname, optval, optlen);
break;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 92f8e48e4ba4..28dfa5f3801f 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -163,7 +163,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
rt = rt6_lookup(net, addr, NULL, 0, 0);
if (rt) {
dev = rt->dst.dev;
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
} else
dev = dev_get_by_index_rcu(net, ifindex);
@@ -260,7 +260,7 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
if (rt) {
dev = rt->dst.dev;
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
} else
dev = dev_get_by_index_rcu(net, ifindex);
@@ -284,6 +284,9 @@ void ipv6_sock_mc_close(struct sock *sk)
struct ipv6_mc_socklist *mc_lst;
struct net *net = sock_net(sk);
+ if (!rcu_access_pointer(np->ipv6_mc_list))
+ return;
+
spin_lock(&ipv6_sk_mc_lock);
while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 2edce30ef733..4c02e6ab96e7 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -370,12 +370,12 @@ static void pndisc_destructor(struct pneigh_entry *n)
ipv6_dev_mc_dec(dev, &maddr);
}
-struct sk_buff *ndisc_build_skb(struct net_device *dev,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h,
- const struct in6_addr *target,
- int llinfo)
+static struct sk_buff *ndisc_build_skb(struct net_device *dev,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h,
+ const struct in6_addr *target,
+ int llinfo)
{
struct net *net = dev_net(dev);
struct sock *sk = net->ipv6.ndisc_sk;
@@ -431,14 +431,11 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev,
return skb;
}
-EXPORT_SYMBOL(ndisc_build_skb);
-
-void ndisc_send_skb(struct sk_buff *skb,
- struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h)
+static void ndisc_send_skb(struct sk_buff *skb, struct net_device *dev,
+ struct neighbour *neigh,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h)
{
struct flowi6 fl6;
struct dst_entry *dst;
@@ -473,8 +470,6 @@ void ndisc_send_skb(struct sk_buff *skb,
rcu_read_unlock();
}
-EXPORT_SYMBOL(ndisc_send_skb);
-
/*
* Send a Neighbour Discover packet
*/
@@ -535,7 +530,6 @@ static void ndisc_send_unsol_na(struct net_device *dev)
{
struct inet6_dev *idev;
struct inet6_ifaddr *ifa;
- struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
idev = in6_dev_get(dev);
if (!idev)
@@ -543,7 +537,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)
read_lock_bh(&idev->lock);
list_for_each_entry(ifa, &idev->addr_list, if_list) {
- ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr,
+ ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &ifa->addr,
/*router=*/ !!idev->cnf.forwarding,
/*solicited=*/ false, /*override=*/ true,
/*inc_opt=*/ true);
@@ -905,7 +899,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
- /* XXX: idev->cnf.prixy_ndp */
+ /* XXX: idev->cnf.proxy_ndp */
goto out;
}
@@ -1033,18 +1027,6 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
}
-static inline int accept_ra(struct inet6_dev *in6_dev)
-{
- /*
- * If forwarding is enabled, RA are not accepted unless the special
- * hybrid mode (accept_ra=2) is enabled.
- */
- if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2)
- return 0;
-
- return in6_dev->cnf.accept_ra;
-}
-
static void ndisc_router_discovery(struct sk_buff *skb)
{
struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
@@ -1092,7 +1074,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return;
}
- if (!accept_ra(in6_dev))
+ if (!ipv6_accept_ra(in6_dev))
goto skip_linkparms;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
@@ -1144,7 +1126,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
ND_PRINTK(0, err,
"RA: %s got default router without neighbour\n",
__func__);
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return;
}
}
@@ -1169,7 +1151,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
ND_PRINTK(0, err,
"RA: %s got default router without neighbour\n",
__func__);
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return;
}
neigh->flags |= NTF_ROUTER;
@@ -1248,7 +1230,7 @@ skip_linkparms:
NEIGH_UPDATE_F_ISROUTER);
}
- if (!accept_ra(in6_dev))
+ if (!ipv6_accept_ra(in6_dev))
goto out;
#ifdef CONFIG_IPV6_ROUTE_INFO
@@ -1325,8 +1307,7 @@ skip_routeinfo:
ND_PRINTK(2, warn, "RA: invalid RA options\n");
}
out:
- if (rt)
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
if (neigh)
neigh_release(neigh);
}
@@ -1574,11 +1555,18 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = ptr;
struct net *net = dev_net(dev);
+ struct inet6_dev *idev;
switch (event) {
case NETDEV_CHANGEADDR:
neigh_changeaddr(&nd_tbl, dev);
fib6_run_gc(~0UL, net);
+ idev = in6_dev_get(dev);
+ if (!idev)
+ break;
+ if (idev->cnf.ndisc_notify)
+ ndisc_send_unsol_na(dev);
+ in6_dev_put(idev);
break;
case NETDEV_DOWN:
neigh_ifdown(&nd_tbl, dev);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index d7cb04506c3d..125a90d6a795 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -207,8 +207,7 @@ ip6t_get_target_c(const struct ip6t_entry *e)
return ip6t_get_target((struct ip6t_entry *)e);
}
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
- defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
/* This cries for unification! */
static const char *const hooknames[] = {
[NF_INET_PRE_ROUTING] = "PREROUTING",
@@ -381,8 +380,7 @@ ip6t_do_table(struct sk_buff *skb,
t = ip6t_get_target_c(e);
IP_NF_ASSERT(t->u.kernel.target);
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
- defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
/* The packet is traced: log it */
if (unlikely(skb->nf_trace))
trace_packet(skb, hook, in, out,
@@ -1856,7 +1854,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1971,7 +1969,7 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1993,7 +1991,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -2018,7 +2016,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -2273,112 +2271,9 @@ static void __exit ip6_tables_fini(void)
unregister_pernet_subsys(&ip6_tables_net_ops);
}
-/*
- * find the offset to specified header or the protocol number of last header
- * if target < 0. "last header" is transport protocol header, ESP, or
- * "No next header".
- *
- * Note that *offset is used as input/output parameter. an if it is not zero,
- * then it must be a valid offset to an inner IPv6 header. This can be used
- * to explore inner IPv6 header, eg. ICMPv6 error messages.
- *
- * If target header is found, its offset is set in *offset and return protocol
- * number. Otherwise, return -1.
- *
- * If the first fragment doesn't contain the final protocol header or
- * NEXTHDR_NONE it is considered invalid.
- *
- * Note that non-1st fragment is special case that "the protocol number
- * of last header" is "next header" field in Fragment header. In this case,
- * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
- * isn't NULL.
- *
- * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
- * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
- * target < 0, then this function will stop at the AH header.
- */
-int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
- int target, unsigned short *fragoff, int *flags)
-{
- unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
- u8 nexthdr = ipv6_hdr(skb)->nexthdr;
- unsigned int len;
-
- if (fragoff)
- *fragoff = 0;
-
- if (*offset) {
- struct ipv6hdr _ip6, *ip6;
-
- ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
- if (!ip6 || (ip6->version != 6)) {
- printk(KERN_ERR "IPv6 header not found\n");
- return -EBADMSG;
- }
- start = *offset + sizeof(struct ipv6hdr);
- nexthdr = ip6->nexthdr;
- }
- len = skb->len - start;
-
- while (nexthdr != target) {
- struct ipv6_opt_hdr _hdr, *hp;
- unsigned int hdrlen;
-
- if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
- if (target < 0)
- break;
- return -ENOENT;
- }
-
- hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
- if (hp == NULL)
- return -EBADMSG;
- if (nexthdr == NEXTHDR_FRAGMENT) {
- unsigned short _frag_off;
- __be16 *fp;
-
- if (flags) /* Indicate that this is a fragment */
- *flags |= IP6T_FH_F_FRAG;
- fp = skb_header_pointer(skb,
- start+offsetof(struct frag_hdr,
- frag_off),
- sizeof(_frag_off),
- &_frag_off);
- if (fp == NULL)
- return -EBADMSG;
-
- _frag_off = ntohs(*fp) & ~0x7;
- if (_frag_off) {
- if (target < 0 &&
- ((!ipv6_ext_hdr(hp->nexthdr)) ||
- hp->nexthdr == NEXTHDR_NONE)) {
- if (fragoff)
- *fragoff = _frag_off;
- return hp->nexthdr;
- }
- return -ENOENT;
- }
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH) {
- if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
- break;
- hdrlen = (hp->hdrlen + 2) << 2;
- } else
- hdrlen = ipv6_optlen(hp);
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- start += hdrlen;
- }
-
- *offset = start;
- return nexthdr;
-}
-
EXPORT_SYMBOL(ip6t_register_table);
EXPORT_SYMBOL(ip6t_unregister_table);
EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ipv6_find_hdr);
module_init(ip6_tables_init);
module_exit(ip6_tables_fini);
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
index 5d1d8b04d694..5060d54199ab 100644
--- a/net/ipv6/netfilter/ip6t_rpfilter.c
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -67,7 +67,7 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
ret = true;
out:
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return ret;
}
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index d57dab17a182..6c8ae24b85eb 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -137,6 +137,10 @@ nf_nat_ipv6_fn(unsigned int hooknum,
/* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == IP_CT_ESTABLISHED_REPLY);
+ if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
+ nf_ct_kill_acct(ct, ctinfo, skb);
+ return NF_DROP;
+ }
}
return nf_nat_packet(ct, ctinfo, hooknum, skb);
@@ -277,9 +281,7 @@ static int __net_init ip6table_nat_net_init(struct net *net)
return -ENOMEM;
net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
kfree(repl);
- if (IS_ERR(net->ipv6.ip6table_nat))
- return PTR_ERR(net->ipv6.ip6table_nat);
- return 0;
+ return PTR_RET(net->ipv6.ip6table_nat);
}
static void __net_exit ip6table_nat_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 8860d23e61cf..00ee17c3e893 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -21,6 +21,7 @@
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
@@ -295,7 +296,56 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
},
};
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+static int
+ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ const struct nf_conntrack_tuple_hash *h;
+ struct sockaddr_in6 sin6;
+ struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
+ struct nf_conn *ct;
+
+ tuple.src.u3.in6 = inet6->rcv_saddr;
+ tuple.src.u.tcp.port = inet->inet_sport;
+ tuple.dst.u3.in6 = inet6->daddr;
+ tuple.dst.u.tcp.port = inet->inet_dport;
+ tuple.dst.protonum = sk->sk_protocol;
+
+ if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP)
+ return -ENOPROTOOPT;
+
+ if (*len < 0 || (unsigned int) *len < sizeof(sin6))
+ return -EINVAL;
+
+ h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);
+ if (!h) {
+ pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n",
+ &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port),
+ &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port));
+ return -ENOENT;
+ }
+
+ ct = nf_ct_tuplehash_to_ctrack(h);
+
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
+ sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK;
+ memcpy(&sin6.sin6_addr,
+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
+ sizeof(sin6.sin6_addr));
+
+ nf_ct_put(ct);
+
+ if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
+ sin6.sin6_scope_id = sk->sk_bound_dev_if;
+ else
+ sin6.sin6_scope_id = 0;
+
+ return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
+}
+
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
@@ -346,7 +396,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
.invert_tuple = ipv6_invert_tuple,
.print_tuple = ipv6_print_tuple,
.get_l4proto = ipv6_get_l4proto,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = ipv6_tuple_to_nlattr,
.nlattr_tuple_size = ipv6_nlattr_tuple_size,
.nlattr_to_tuple = ipv6_nlattr_to_tuple,
@@ -359,6 +409,14 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+static struct nf_sockopt_ops so_getorigdst6 = {
+ .pf = NFPROTO_IPV6,
+ .get_optmin = IP6T_SO_ORIGINAL_DST,
+ .get_optmax = IP6T_SO_ORIGINAL_DST + 1,
+ .get = ipv6_getorigdst,
+ .owner = THIS_MODULE,
+};
+
static int ipv6_net_init(struct net *net)
{
int ret = 0;
@@ -425,6 +483,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
need_conntrack();
nf_defrag_ipv6_enable();
+ ret = nf_register_sockopt(&so_getorigdst6);
+ if (ret < 0) {
+ pr_err("Unable to register netfilter socket option\n");
+ return ret;
+ }
+
ret = register_pernet_subsys(&ipv6_net_ops);
if (ret < 0)
goto cleanup_pernet;
@@ -440,6 +504,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
cleanup_ipv6:
unregister_pernet_subsys(&ipv6_net_ops);
cleanup_pernet:
+ nf_unregister_sockopt(&so_getorigdst6);
return ret;
}
@@ -448,6 +513,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
synchronize_net();
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
unregister_pernet_subsys(&ipv6_net_ops);
+ nf_unregister_sockopt(&so_getorigdst6);
}
module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 2d54b2061d68..24df3dde0076 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -232,7 +232,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum);
}
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
@@ -375,7 +375,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
.get_timeouts = icmpv6_get_timeouts,
.new = icmpv6_new,
.error = icmpv6_error,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = icmpv6_tuple_to_nlattr,
.nlattr_tuple_size = icmpv6_nlattr_tuple_size,
.nlattr_to_tuple = icmpv6_nlattr_to_tuple,
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index cdd6d045e42e..aacd121fe8c5 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -19,7 +19,7 @@
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_bridge.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
@@ -35,7 +35,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
{
u16 zone = NF_CT_DEFAULT_ZONE;
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
#endif
@@ -60,7 +60,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
{
struct sk_buff *reasm;
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
/* Previously seen (loopback)? */
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
return NF_ACCEPT;
diff --git a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c
index 5d6da784305b..61aaf70f376e 100644
--- a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c
@@ -84,7 +84,7 @@ const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = {
.manip_pkt = icmpv6_manip_pkt,
.in_range = icmpv6_in_range,
.unique_tuple = icmpv6_unique_tuple,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
#endif
};
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
new file mode 100644
index 000000000000..c2e73e647e44
--- /dev/null
+++ b/net/ipv6/output_core.c
@@ -0,0 +1,76 @@
+/*
+ * IPv6 library code, needed by static components when full IPv6 support is
+ * not configured or static. These functions are needed by GSO/GRO implementation.
+ */
+#include <linux/export.h>
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+{
+ static atomic_t ipv6_fragmentation_id;
+ int old, new;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (rt && !(rt->dst.flags & DST_NOPEER)) {
+ struct inet_peer *peer;
+ struct net *net;
+
+ net = dev_net(rt->dst.dev);
+ peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
+ if (peer) {
+ fhdr->identification = htonl(inet_getid(peer, 0));
+ inet_putpeer(peer);
+ return;
+ }
+ }
+#endif
+ do {
+ old = atomic_read(&ipv6_fragmentation_id);
+ new = old + 1;
+ if (!new)
+ new = 1;
+ } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
+ fhdr->identification = htonl(new);
+}
+EXPORT_SYMBOL(ipv6_select_ident);
+
+int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+{
+ u16 offset = sizeof(struct ipv6hdr);
+ struct ipv6_opt_hdr *exthdr =
+ (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
+ unsigned int packet_len = skb->tail - skb->network_header;
+ int found_rhdr = 0;
+ *nexthdr = &ipv6_hdr(skb)->nexthdr;
+
+ while (offset + 1 <= packet_len) {
+
+ switch (**nexthdr) {
+
+ case NEXTHDR_HOP:
+ break;
+ case NEXTHDR_ROUTING:
+ found_rhdr = 1;
+ break;
+ case NEXTHDR_DEST:
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
+ if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
+ break;
+#endif
+ if (found_rhdr)
+ return offset;
+ break;
+ default :
+ return offset;
+ }
+
+ offset += ipv6_optlen(exthdr);
+ *nexthdr = &exthdr->nexthdr;
+ exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
+ offset);
+ }
+
+ return offset;
+}
+EXPORT_SYMBOL(ip6_find_1stfragopt);
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 053082dfc93e..22d1bd4670da 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -25,7 +25,9 @@
#include <linux/spinlock.h>
#include <net/protocol.h>
+#if IS_ENABLED(CONFIG_IPV6)
const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
+EXPORT_SYMBOL(inet6_protos);
int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
{
@@ -50,3 +52,26 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
return ret;
}
EXPORT_SYMBOL(inet6_del_protocol);
+#endif
+
+const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
+
+int inet6_add_offload(const struct net_offload *prot, unsigned char protocol)
+{
+ return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
+ NULL, prot) ? 0 : -1;
+}
+EXPORT_SYMBOL(inet6_add_offload);
+
+int inet6_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+ int ret;
+
+ ret = (cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
+ prot, NULL) == prot) ? 0 : -1;
+
+ synchronize_net();
+
+ return ret;
+}
+EXPORT_SYMBOL(inet6_del_offload);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d8e95c77db99..6cd29b1e8b92 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -50,7 +50,7 @@
#include <net/udp.h>
#include <net/inet_common.h>
#include <net/tcp_states.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/mip6.h>
#endif
#include <linux/mroute6.h>
@@ -123,7 +123,7 @@ static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
return 1;
}
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb);
static mh_filter_t __rcu *mh_filter __read_mostly;
@@ -184,7 +184,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
filtered = icmpv6_filter(sk, skb);
break;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_MH:
{
/* XXX: To validate MH only once for each packet,
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index da8a4e301b1b..e5253ec9e0fc 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -616,6 +616,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net)
table[0].data = &net->ipv6.frags.high_thresh;
table[1].data = &net->ipv6.frags.low_thresh;
table[2].data = &net->ipv6.frags.timeout;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
}
hdr = register_net_sysctl(net, "net/ipv6", table);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b1e6cf0b95fd..e229a3bc345d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -57,6 +57,7 @@
#include <net/xfrm.h>
#include <net/netevent.h>
#include <net/netlink.h>
+#include <net/nexthop.h>
#include <asm/uaccess.h>
@@ -289,6 +290,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
rt->rt6i_genid = rt_genid(net);
+ INIT_LIST_HEAD(&rt->rt6i_siblings);
+ rt->rt6i_nsiblings = 0;
}
return rt;
}
@@ -318,13 +321,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
}
}
-static atomic_t __rt6_peer_genid = ATOMIC_INIT(0);
-
-static u32 rt6_peer_genid(void)
-{
- return atomic_read(&__rt6_peer_genid);
-}
-
void rt6_bind_peer(struct rt6_info *rt, int create)
{
struct inet_peer_base *base;
@@ -338,8 +334,6 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
if (peer) {
if (!rt6_set_peer(rt, peer))
inet_putpeer(peer);
- else
- rt->rt6i_peer_genid = rt6_peer_genid();
}
}
@@ -385,6 +379,69 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}
+/* Multipath route selection:
+ * Hash based function using packet header and flowlabel.
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+ const struct flowi6 *fl6)
+{
+ unsigned int val = fl6->flowi6_proto;
+
+ val ^= (__force u32)fl6->daddr.s6_addr32[0];
+ val ^= (__force u32)fl6->daddr.s6_addr32[1];
+ val ^= (__force u32)fl6->daddr.s6_addr32[2];
+ val ^= (__force u32)fl6->daddr.s6_addr32[3];
+
+ val ^= (__force u32)fl6->saddr.s6_addr32[0];
+ val ^= (__force u32)fl6->saddr.s6_addr32[1];
+ val ^= (__force u32)fl6->saddr.s6_addr32[2];
+ val ^= (__force u32)fl6->saddr.s6_addr32[3];
+
+ /* Work only if this not encapsulated */
+ switch (fl6->flowi6_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ val ^= (__force u16)fl6->fl6_sport;
+ val ^= (__force u16)fl6->fl6_dport;
+ break;
+
+ case IPPROTO_ICMPV6:
+ val ^= (__force u16)fl6->fl6_icmp_type;
+ val ^= (__force u16)fl6->fl6_icmp_code;
+ break;
+ }
+ /* RFC6438 recommands to use flowlabel */
+ val ^= (__force u32)fl6->flowlabel;
+
+ /* Perhaps, we need to tune, this function? */
+ val = val ^ (val >> 7) ^ (val >> 12);
+ return val % candidate_count;
+}
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+ struct flowi6 *fl6)
+{
+ struct rt6_info *sibling, *next_sibling;
+ int route_choosen;
+
+ route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
+ /* Don't change the route, if route_choosen == 0
+ * (siblings does not include ourself)
+ */
+ if (route_choosen)
+ list_for_each_entry_safe(sibling, next_sibling,
+ &match->rt6i_siblings, rt6i_siblings) {
+ route_choosen--;
+ if (route_choosen == 0) {
+ match = sibling;
+ break;
+ }
+ }
+ return match;
+}
+
/*
* Route lookup. Any table->tb6_lock is implied.
*/
@@ -487,35 +544,32 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
return 0;
}
-static inline int rt6_check_neigh(struct rt6_info *rt)
+static inline bool rt6_check_neigh(struct rt6_info *rt)
{
struct neighbour *neigh;
- int m;
+ bool ret = false;
neigh = rt->n;
if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY))
- m = 1;
+ ret = true;
else if (neigh) {
read_lock_bh(&neigh->lock);
if (neigh->nud_state & NUD_VALID)
- m = 2;
+ ret = true;
#ifdef CONFIG_IPV6_ROUTER_PREF
- else if (neigh->nud_state & NUD_FAILED)
- m = 0;
+ else if (!(neigh->nud_state & NUD_FAILED))
+ ret = true;
#endif
- else
- m = 1;
read_unlock_bh(&neigh->lock);
- } else
- m = 0;
- return m;
+ }
+ return ret;
}
static int rt6_score_route(struct rt6_info *rt, int oif,
int strict)
{
- int m, n;
+ int m;
m = rt6_check_dev(rt, oif);
if (!m && (strict & RT6_LOOKUP_F_IFACE))
@@ -523,8 +577,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
#ifdef CONFIG_IPV6_ROUTER_PREF
m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
#endif
- n = rt6_check_neigh(rt);
- if (!n && (strict & RT6_LOOKUP_F_REACHABLE))
+ if (!rt6_check_neigh(rt) && (strict & RT6_LOOKUP_F_REACHABLE))
return -1;
return m;
}
@@ -666,7 +719,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
else
rt6_set_expires(rt, jiffies + HZ * lifetime);
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
}
return 0;
}
@@ -702,6 +755,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
restart:
rt = fn->leaf;
rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+ if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
BACKTRACK(net, &fl6->saddr);
out:
dst_use(&rt->dst, jiffies);
@@ -863,7 +918,8 @@ restart_2:
restart:
rt = rt6_select(fn, oif, strict | reachable);
-
+ if (rt->rt6i_nsiblings && oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
BACKTRACK(net, &fl6->saddr);
if (rt == net->ipv6.ip6_null_entry ||
rt->rt6i_flags & RTF_CACHE)
@@ -879,7 +935,7 @@ restart:
else
goto out2;
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
rt = nrt ? : net->ipv6.ip6_null_entry;
dst_hold(&rt->dst);
@@ -896,7 +952,7 @@ restart:
* Race condition! In the gap, when table->tb6_lock was
* released someone could insert this route. Relookup.
*/
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
goto relookup;
out:
@@ -1030,14 +1086,9 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
return NULL;
- if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
- if (rt->rt6i_peer_genid != rt6_peer_genid()) {
- if (!rt6_has_peer(rt))
- rt6_bind_peer(rt, 0);
- rt->rt6i_peer_genid = rt6_peer_genid();
- }
+ if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
return dst;
- }
+
return NULL;
}
@@ -1316,12 +1367,6 @@ out:
return entries > rt_max_size;
}
-/* Clean host part of a prefix. Not necessary in radix tree,
- but results in cleaner routing tables.
-
- Remove it only when all the things will work!
- */
-
int ip6_dst_hoplimit(struct dst_entry *dst)
{
int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
@@ -1507,7 +1552,7 @@ int ip6_route_add(struct fib6_config *cfg)
goto out;
if (dev) {
if (dev != grt->dst.dev) {
- dst_release(&grt->dst);
+ ip6_rt_put(grt);
goto out;
}
} else {
@@ -1518,7 +1563,7 @@ int ip6_route_add(struct fib6_config *cfg)
}
if (!(grt->rt6i_flags & RTF_GATEWAY))
err = 0;
- dst_release(&grt->dst);
+ ip6_rt_put(grt);
if (err)
goto out;
@@ -1604,7 +1649,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
write_unlock_bh(&table->tb6_lock);
out:
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
return err;
}
@@ -1987,7 +2032,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
switch(cmd) {
case SIOCADDRT: /* Add a route */
case SIOCDELRT: /* Delete a route */
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
err = copy_from_user(&rtmsg, arg,
sizeof(struct in6_rtmsg));
@@ -2249,6 +2294,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_IIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 },
[RTA_METRICS] = { .type = NLA_NESTED },
+ [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2326,11 +2372,71 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
if (tb[RTA_TABLE])
cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
+ if (tb[RTA_MULTIPATH]) {
+ cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+ cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+ }
+
err = 0;
errout:
return err;
}
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+ struct fib6_config r_cfg;
+ struct rtnexthop *rtnh;
+ int remaining;
+ int attrlen;
+ int err = 0, last_err = 0;
+
+beginning:
+ rtnh = (struct rtnexthop *)cfg->fc_mp;
+ remaining = cfg->fc_mp_len;
+
+ /* Parse a Multipath Entry */
+ while (rtnh_ok(rtnh, remaining)) {
+ memcpy(&r_cfg, cfg, sizeof(*cfg));
+ if (rtnh->rtnh_ifindex)
+ r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+ attrlen = rtnh_attrlen(rtnh);
+ if (attrlen > 0) {
+ struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+ nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+ if (nla) {
+ nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+ r_cfg.fc_flags |= RTF_GATEWAY;
+ }
+ }
+ err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+ if (err) {
+ last_err = err;
+ /* If we are trying to remove a route, do not stop the
+ * loop when ip6_route_del() fails (because next hop is
+ * already gone), we should try to remove all next hops.
+ */
+ if (add) {
+ /* If add fails, we should try to delete all
+ * next hops that have been already added.
+ */
+ add = 0;
+ goto beginning;
+ }
+ }
+ /* Because each route is added like a single route we remove
+ * this flag after the first nexthop (if there is a collision,
+ * we have already fail to add the first nexthop:
+ * fib6_add_rt2node() has reject it).
+ */
+ cfg->fc_nlinfo.nlh->nlmsg_flags &= ~NLM_F_EXCL;
+ rtnh = rtnh_next(rtnh, &remaining);
+ }
+
+ return last_err;
+}
+
static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib6_config cfg;
@@ -2340,7 +2446,10 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_del(&cfg);
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 0);
+ else
+ return ip6_route_del(&cfg);
}
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2352,7 +2461,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_add(&cfg);
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 1);
+ else
+ return ip6_route_add(&cfg);
}
static inline size_t rt6_nlmsg_size(void)
@@ -2596,7 +2708,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb) {
- dst_release(&rt->dst);
+ ip6_rt_put(rt);
err = -ENOBUFS;
goto errout;
}
@@ -2873,6 +2985,10 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
}
return table;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 3ed54ffd8d50..cfba99b2c2a4 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -65,9 +65,14 @@
#define HASH_SIZE 16
#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+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");
+
static int ipip6_tunnel_init(struct net_device *dev);
static void ipip6_tunnel_setup(struct net_device *dev);
static void ipip6_dev_free(struct net_device *dev);
+static struct rtnl_link_ops sit_link_ops __read_mostly;
static int sit_net_id __read_mostly;
struct sit_net {
@@ -80,22 +85,6 @@ struct sit_net {
struct net_device *fb_tunnel_dev;
};
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
- for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- struct u64_stats_sync syncp;
-};
-
static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot)
{
@@ -121,6 +110,7 @@ static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
}
tot->rx_errors = dev->stats.rx_errors;
+ tot->rx_frame_errors = dev->stats.rx_frame_errors;
tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
tot->tx_dropped = dev->stats.tx_dropped;
@@ -141,20 +131,20 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net,
struct ip_tunnel *t;
struct sit_net *sitn = net_generic(net, sit_net_id);
- for_each_ip_tunnel_rcu(sitn->tunnels_r_l[h0 ^ h1]) {
+ for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) {
if (local == t->parms.iph.saddr &&
remote == t->parms.iph.daddr &&
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
(t->dev->flags & IFF_UP))
return t;
}
- for_each_ip_tunnel_rcu(sitn->tunnels_r[h0]) {
+ for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) {
if (remote == t->parms.iph.daddr &&
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
(t->dev->flags & IFF_UP))
return t;
}
- for_each_ip_tunnel_rcu(sitn->tunnels_l[h1]) {
+ for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) {
if (local == t->parms.iph.saddr &&
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
(t->dev->flags & IFF_UP))
@@ -231,6 +221,37 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
#endif
}
+static int ipip6_tunnel_create(struct net_device *dev)
+{
+ struct ip_tunnel *t = netdev_priv(dev);
+ struct net *net = dev_net(dev);
+ struct sit_net *sitn = net_generic(net, sit_net_id);
+ int err;
+
+ err = ipip6_tunnel_init(dev);
+ if (err < 0)
+ goto out;
+ ipip6_tunnel_clone_6rd(dev, sitn);
+
+ if ((__force u16)t->parms.i_flags & SIT_ISATAP)
+ dev->priv_flags |= IFF_ISATAP;
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out;
+
+ strcpy(t->parms.name, dev->name);
+ dev->rtnl_link_ops = &sit_link_ops;
+
+ dev_hold(dev);
+
+ ipip6_tunnel_link(sitn, t);
+ return 0;
+
+out:
+ return err;
+}
+
static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
struct ip_tunnel_parm *parms, int create)
{
@@ -271,21 +292,9 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
nt = netdev_priv(dev);
nt->parms = *parms;
- if (ipip6_tunnel_init(dev) < 0)
+ if (ipip6_tunnel_create(dev) < 0)
goto failed_free;
- ipip6_tunnel_clone_6rd(dev, sitn);
- if (parms->i_flags & SIT_ISATAP)
- dev->priv_flags |= IFF_ISATAP;
-
- if (register_netdevice(dev) < 0)
- goto failed_free;
-
- strcpy(nt->parms.name, dev->name);
-
- dev_hold(dev);
-
- ipip6_tunnel_link(sitn, nt);
return nt;
failed_free:
@@ -581,16 +590,11 @@ out:
return err;
}
-static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb)
-{
- if (INET_ECN_is_ce(iph->tos))
- IP6_ECN_set_ce(ipv6_hdr(skb));
-}
-
static int ipip6_rcv(struct sk_buff *skb)
{
const struct iphdr *iph;
struct ip_tunnel *tunnel;
+ int err;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
goto out;
@@ -612,18 +616,27 @@ static int ipip6_rcv(struct sk_buff *skb)
if ((tunnel->dev->priv_flags & IFF_ISATAP) &&
!isatap_chksrc(skb, iph, tunnel)) {
tunnel->dev->stats.rx_errors++;
- kfree_skb(skb);
- return 0;
+ goto out;
+ }
+
+ __skb_tunnel_rx(skb, tunnel->dev);
+
+ err = IP_ECN_decapsulate(iph, skb);
+ if (unlikely(err)) {
+ if (log_ecn_error)
+ net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
+ &iph->saddr, iph->tos);
+ if (err > 1) {
+ ++tunnel->dev->stats.rx_frame_errors;
+ ++tunnel->dev->stats.rx_errors;
+ goto out;
+ }
}
tstats = this_cpu_ptr(tunnel->dev->tstats);
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
- __skb_tunnel_rx(skb, tunnel->dev);
-
- ipip6_ecn_decapsulate(iph, skb);
-
netif_rx(skb);
return 0;
@@ -683,7 +696,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct pcpu_tstats *tstats;
const struct iphdr *tiph = &tunnel->parms.iph;
const struct ipv6hdr *iph6 = ipv6_hdr(skb);
u8 tos = tunnel->parms.iph.tos;
@@ -864,9 +876,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
if ((iph->ttl = tiph->ttl) == 0)
iph->ttl = iph6->hop_limit;
- nf_reset(skb);
- tstats = this_cpu_ptr(dev->tstats);
- __IPTUNNEL_XMIT(tstats, &dev->stats);
+ iptunnel_xmit(skb, dev);
return NETDEV_TX_OK;
tx_error_icmp:
@@ -914,6 +924,59 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
dev->iflink = tunnel->parms.link;
}
+static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
+{
+ struct net *net = dev_net(t->dev);
+ struct sit_net *sitn = net_generic(net, sit_net_id);
+
+ ipip6_tunnel_unlink(sitn, t);
+ synchronize_net();
+ t->parms.iph.saddr = p->iph.saddr;
+ t->parms.iph.daddr = p->iph.daddr;
+ memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
+ memcpy(t->dev->broadcast, &p->iph.daddr, 4);
+ ipip6_tunnel_link(sitn, t);
+ t->parms.iph.ttl = p->iph.ttl;
+ t->parms.iph.tos = p->iph.tos;
+ if (t->parms.link != p->link) {
+ t->parms.link = p->link;
+ ipip6_tunnel_bind_dev(t->dev);
+ }
+ netdev_state_change(t->dev);
+}
+
+#ifdef CONFIG_IPV6_SIT_6RD
+static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
+ struct ip_tunnel_6rd *ip6rd)
+{
+ struct in6_addr prefix;
+ __be32 relay_prefix;
+
+ if (ip6rd->relay_prefixlen > 32 ||
+ ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
+ return -EINVAL;
+
+ ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
+ if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
+ return -EINVAL;
+ if (ip6rd->relay_prefixlen)
+ relay_prefix = ip6rd->relay_prefix &
+ htonl(0xffffffffUL <<
+ (32 - ip6rd->relay_prefixlen));
+ else
+ relay_prefix = 0;
+ if (relay_prefix != ip6rd->relay_prefix)
+ return -EINVAL;
+
+ t->ip6rd.prefix = prefix;
+ t->ip6rd.relay_prefix = relay_prefix;
+ t->ip6rd.prefixlen = ip6rd->prefixlen;
+ t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
+ netdev_state_change(t->dev);
+ return 0;
+}
+#endif
+
static int
ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -966,7 +1029,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCADDTUNNEL:
case SIOCCHGTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -995,28 +1058,13 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
break;
}
t = netdev_priv(dev);
- ipip6_tunnel_unlink(sitn, t);
- synchronize_net();
- t->parms.iph.saddr = p.iph.saddr;
- t->parms.iph.daddr = p.iph.daddr;
- memcpy(dev->dev_addr, &p.iph.saddr, 4);
- memcpy(dev->broadcast, &p.iph.daddr, 4);
- ipip6_tunnel_link(sitn, t);
- netdev_state_change(dev);
}
+
+ ipip6_tunnel_update(t, &p);
}
if (t) {
err = 0;
- if (cmd == SIOCCHGTUNNEL) {
- t->parms.iph.ttl = p.iph.ttl;
- t->parms.iph.tos = p.iph.tos;
- if (t->parms.link != p.link) {
- t->parms.link = p.link;
- ipip6_tunnel_bind_dev(dev);
- netdev_state_change(dev);
- }
- }
if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
err = -EFAULT;
} else
@@ -1025,7 +1073,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCDELTUNNEL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
if (dev == sitn->fb_tunnel_dev) {
@@ -1058,7 +1106,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCDELPRL:
case SIOCCHGPRL:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EINVAL;
if (dev == sitn->fb_tunnel_dev)
@@ -1087,7 +1135,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCCHG6RD:
case SIOCDEL6RD:
err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto done;
err = -EFAULT;
@@ -1098,31 +1146,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t = netdev_priv(dev);
if (cmd != SIOCDEL6RD) {
- struct in6_addr prefix;
- __be32 relay_prefix;
-
- err = -EINVAL;
- if (ip6rd.relay_prefixlen > 32 ||
- ip6rd.prefixlen + (32 - ip6rd.relay_prefixlen) > 64)
- goto done;
-
- ipv6_addr_prefix(&prefix, &ip6rd.prefix,
- ip6rd.prefixlen);
- if (!ipv6_addr_equal(&prefix, &ip6rd.prefix))
- goto done;
- if (ip6rd.relay_prefixlen)
- relay_prefix = ip6rd.relay_prefix &
- htonl(0xffffffffUL <<
- (32 - ip6rd.relay_prefixlen));
- else
- relay_prefix = 0;
- if (relay_prefix != ip6rd.relay_prefix)
+ err = ipip6_tunnel_update_6rd(t, &ip6rd);
+ if (err < 0)
goto done;
-
- t->ip6rd.prefix = prefix;
- t->ip6rd.relay_prefix = relay_prefix;
- t->ip6rd.prefixlen = ip6rd.prefixlen;
- t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen;
} else
ipip6_tunnel_clone_6rd(dev, sitn);
@@ -1216,6 +1242,239 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
return 0;
}
+static void ipip6_netlink_parms(struct nlattr *data[],
+ struct ip_tunnel_parm *parms)
+{
+ memset(parms, 0, sizeof(*parms));
+
+ parms->iph.version = 4;
+ parms->iph.protocol = IPPROTO_IPV6;
+ parms->iph.ihl = 5;
+ parms->iph.ttl = 64;
+
+ if (!data)
+ return;
+
+ if (data[IFLA_IPTUN_LINK])
+ parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+ if (data[IFLA_IPTUN_LOCAL])
+ parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
+
+ if (data[IFLA_IPTUN_REMOTE])
+ parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
+
+ if (data[IFLA_IPTUN_TTL]) {
+ parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
+ if (parms->iph.ttl)
+ parms->iph.frag_off = htons(IP_DF);
+ }
+
+ if (data[IFLA_IPTUN_TOS])
+ parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
+
+ if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
+ parms->iph.frag_off = htons(IP_DF);
+
+ if (data[IFLA_IPTUN_FLAGS])
+ parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
+}
+
+#ifdef CONFIG_IPV6_SIT_6RD
+/* This function returns true when 6RD attributes are present in the nl msg */
+static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
+ struct ip_tunnel_6rd *ip6rd)
+{
+ bool ret = false;
+ memset(ip6rd, 0, sizeof(*ip6rd));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_IPTUN_6RD_PREFIX]) {
+ ret = true;
+ nla_memcpy(&ip6rd->prefix, data[IFLA_IPTUN_6RD_PREFIX],
+ sizeof(struct in6_addr));
+ }
+
+ if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
+ ret = true;
+ ip6rd->relay_prefix =
+ nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+ }
+
+ if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
+ ret = true;
+ ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
+ }
+
+ if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
+ ret = true;
+ ip6rd->relay_prefixlen =
+ nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+ }
+
+ return ret;
+}
+#endif
+
+static int ipip6_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct net *net = dev_net(dev);
+ struct ip_tunnel *nt;
+#ifdef CONFIG_IPV6_SIT_6RD
+ struct ip_tunnel_6rd ip6rd;
+#endif
+ int err;
+
+ nt = netdev_priv(dev);
+ ipip6_netlink_parms(data, &nt->parms);
+
+ if (ipip6_tunnel_locate(net, &nt->parms, 0))
+ return -EEXIST;
+
+ err = ipip6_tunnel_create(dev);
+ if (err < 0)
+ return err;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (ipip6_netlink_6rd_parms(data, &ip6rd))
+ err = ipip6_tunnel_update_6rd(nt, &ip6rd);
+#endif
+
+ return err;
+}
+
+static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[])
+{
+ struct ip_tunnel *t;
+ struct ip_tunnel_parm p;
+ struct net *net = dev_net(dev);
+ struct sit_net *sitn = net_generic(net, sit_net_id);
+#ifdef CONFIG_IPV6_SIT_6RD
+ struct ip_tunnel_6rd ip6rd;
+#endif
+
+ if (dev == sitn->fb_tunnel_dev)
+ return -EINVAL;
+
+ ipip6_netlink_parms(data, &p);
+
+ if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
+ (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
+ return -EINVAL;
+
+ t = ipip6_tunnel_locate(net, &p, 0);
+
+ if (t) {
+ if (t->dev != dev)
+ return -EEXIST;
+ } else
+ t = netdev_priv(dev);
+
+ ipip6_tunnel_update(t, &p);
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (ipip6_netlink_6rd_parms(data, &ip6rd))
+ return ipip6_tunnel_update_6rd(t, &ip6rd);
+#endif
+
+ return 0;
+}
+
+static size_t ipip6_get_size(const struct net_device *dev)
+{
+ return
+ /* IFLA_IPTUN_LINK */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_LOCAL */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_REMOTE */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_TTL */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_TOS */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_PMTUDISC */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_FLAGS */
+ nla_total_size(2) +
+#ifdef CONFIG_IPV6_SIT_6RD
+ /* IFLA_IPTUN_6RD_PREFIX */
+ nla_total_size(sizeof(struct in6_addr)) +
+ /* IFLA_IPTUN_6RD_RELAY_PREFIX */
+ nla_total_size(4) +
+ /* IFLA_IPTUN_6RD_PREFIXLEN */
+ nla_total_size(2) +
+ /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
+ nla_total_size(2) +
+#endif
+ 0;
+}
+
+static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct ip_tunnel_parm *parm = &tunnel->parms;
+
+ if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+ nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
+ nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
+ nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
+ nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+ nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
+ !!(parm->iph.frag_off & htons(IP_DF))) ||
+ nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
+ goto nla_put_failure;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+ if (nla_put(skb, IFLA_IPTUN_6RD_PREFIX, sizeof(struct in6_addr),
+ &tunnel->ip6rd.prefix) ||
+ nla_put_be32(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
+ tunnel->ip6rd.relay_prefix) ||
+ nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
+ tunnel->ip6rd.prefixlen) ||
+ nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+ tunnel->ip6rd.relay_prefixlen))
+ goto nla_put_failure;
+#endif
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
+ [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
+ [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
+ [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
+ [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
+ [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
+ [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
+ [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
+#ifdef CONFIG_IPV6_SIT_6RD
+ [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) },
+ [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
+ [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
+ [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
+#endif
+};
+
+static struct rtnl_link_ops sit_link_ops __read_mostly = {
+ .kind = "sit",
+ .maxtype = IFLA_IPTUN_MAX,
+ .policy = ipip6_policy,
+ .priv_size = sizeof(struct ip_tunnel),
+ .setup = ipip6_tunnel_setup,
+ .newlink = ipip6_newlink,
+ .changelink = ipip6_changelink,
+ .get_size = ipip6_get_size,
+ .fill_info = ipip6_fill_info,
+};
+
static struct xfrm_tunnel sit_handler __read_mostly = {
.handler = ipip6_rcv,
.err_handler = ipip6_err,
@@ -1302,6 +1561,7 @@ static struct pernet_operations sit_net_ops = {
static void __exit sit_cleanup(void)
{
+ rtnl_link_unregister(&sit_link_ops);
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
unregister_pernet_device(&sit_net_ops);
@@ -1319,10 +1579,21 @@ static int __init sit_init(void)
return err;
err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
if (err < 0) {
- unregister_pernet_device(&sit_net_ops);
pr_info("%s: can't add protocol\n", __func__);
+ goto xfrm_tunnel_failed;
}
+ err = rtnl_link_register(&sit_link_ops);
+ if (err < 0)
+ goto rtnl_link_failed;
+
+out:
return err;
+
+rtnl_link_failed:
+ xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+xfrm_tunnel_failed:
+ unregister_pernet_device(&sit_net_ops);
+ goto out;
}
module_init(sit_init);
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 182ab9a85d6c..40161977f7cf 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -214,7 +214,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
ireq6->iif = inet6_iif(skb);
req->expires = 0UL;
- req->retrans = 0;
+ req->num_retrans = 0;
ireq->ecn_ok = ecn_ok;
ireq->snd_wscale = tcp_opt.snd_wscale;
ireq->sack_ok = tcp_opt.sack_ok;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 26175bffbaa0..6565cf55eb1e 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -77,9 +77,6 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
-static void __tcp_v6_send_check(struct sk_buff *skb,
- const struct in6_addr *saddr,
- const struct in6_addr *daddr);
static const struct inet_connection_sock_af_ops ipv6_mapped;
static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -119,14 +116,6 @@ static void tcp_v6_hash(struct sock *sk)
}
}
-static __inline__ __sum16 tcp_v6_check(int len,
- const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- __wsum base)
-{
- return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
-}
-
static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
{
return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
@@ -306,7 +295,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (err)
goto late_failure;
- if (!tp->write_seq)
+ if (!tp->write_seq && likely(!tp->repair))
tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
np->daddr.s6_addr32,
inet->inet_sport,
@@ -495,9 +484,12 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
struct request_values *rvp)
{
struct flowi6 fl6;
+ int res;
- TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
- return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
+ res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
+ if (!res)
+ TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
+ return res;
}
static void tcp_v6_reqsk_destructor(struct request_sock *req)
@@ -719,94 +711,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
};
#endif
-static void __tcp_v6_send_check(struct sk_buff *skb,
- const struct in6_addr *saddr, const struct in6_addr *daddr)
-{
- struct tcphdr *th = tcp_hdr(skb);
-
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
- skb->csum_start = skb_transport_header(skb) - skb->head;
- skb->csum_offset = offsetof(struct tcphdr, check);
- } else {
- th->check = tcp_v6_check(skb->len, saddr, daddr,
- csum_partial(th, th->doff << 2,
- skb->csum));
- }
-}
-
-static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
-}
-
-static int tcp_v6_gso_send_check(struct sk_buff *skb)
-{
- const struct ipv6hdr *ipv6h;
- struct tcphdr *th;
-
- if (!pskb_may_pull(skb, sizeof(*th)))
- return -EINVAL;
-
- ipv6h = ipv6_hdr(skb);
- th = tcp_hdr(skb);
-
- th->check = 0;
- skb->ip_summed = CHECKSUM_PARTIAL;
- __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
- return 0;
-}
-
-static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
- struct sk_buff *skb)
-{
- const struct ipv6hdr *iph = skb_gro_network_header(skb);
- __wsum wsum;
- __sum16 sum;
-
- switch (skb->ip_summed) {
- case CHECKSUM_COMPLETE:
- if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
- skb->csum)) {
- 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;
- }
-
- return tcp_gro_receive(head, skb);
-}
-
-static int tcp6_gro_complete(struct sk_buff *skb)
-{
- const struct ipv6hdr *iph = ipv6_hdr(skb);
- struct tcphdr *th = tcp_hdr(skb);
-
- th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
- &iph->saddr, &iph->daddr, 0);
- skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
-
- return tcp_gro_complete(skb);
-}
-
static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
{
@@ -1364,7 +1268,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
tcp_initialize_rcv_mss(newsk);
tcp_synack_rtt_meas(newsk, req);
- newtp->total_retrans = req->retrans;
+ newtp->total_retrans = req->num_retrans;
newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
@@ -1741,11 +1645,11 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
skb->destructor = sock_edemux;
if (sk->sk_state != TCP_TIME_WAIT) {
struct dst_entry *dst = sk->sk_rx_dst;
- struct inet_sock *icsk = inet_sk(sk);
+
if (dst)
dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
if (dst &&
- icsk->rx_dst_ifindex == skb->skb_iif)
+ inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
skb_dst_set_noref(skb, dst);
}
}
@@ -1866,7 +1770,7 @@ static void get_openreq6(struct seq_file *seq,
0,0, /* could print option size, but that is af dependent. */
1, /* timers active (only the expire timer) */
jiffies_to_clock_t(ttd),
- req->retrans,
+ req->num_timeout,
from_kuid_munged(seq_user_ns(seq), uid),
0, /* non standard timer */
0, /* open_requests have no inode */
@@ -2063,10 +1967,6 @@ static const struct inet6_protocol tcpv6_protocol = {
.early_demux = tcp_v6_early_demux,
.handler = tcp_v6_rcv,
.err_handler = tcp_v6_err,
- .gso_send_check = tcp_v6_gso_send_check,
- .gso_segment = tcp_tso_segment,
- .gro_receive = tcp6_gro_receive,
- .gro_complete = tcp6_gro_complete,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
@@ -2121,10 +2021,10 @@ int __init tcpv6_init(void)
out:
return ret;
-out_tcpv6_protocol:
- inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
out_tcpv6_protosw:
inet6_unregister_protosw(&tcpv6_protosw);
+out_tcpv6_protocol:
+ inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
goto out;
}
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
new file mode 100644
index 000000000000..2ec6bf6a0aa0
--- /dev/null
+++ b/net/ipv6/tcpv6_offload.c
@@ -0,0 +1,95 @@
+/*
+ * IPV6 GSO/GRO offload support
+ * Linux INET6 implementation
+ *
+ * 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.
+ *
+ * TCPv6 GSO/GRO support
+ */
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/ip6_checksum.h>
+#include "ip6_offload.h"
+
+static int tcp_v6_gso_send_check(struct sk_buff *skb)
+{
+ const struct ipv6hdr *ipv6h;
+ struct tcphdr *th;
+
+ if (!pskb_may_pull(skb, sizeof(*th)))
+ return -EINVAL;
+
+ ipv6h = ipv6_hdr(skb);
+ th = tcp_hdr(skb);
+
+ th->check = 0;
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
+ return 0;
+}
+
+static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ const struct ipv6hdr *iph = skb_gro_network_header(skb);
+ __wsum wsum;
+ __sum16 sum;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_COMPLETE:
+ if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
+ skb->csum)) {
+ 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;
+ }
+
+ return tcp_gro_receive(head, skb);
+}
+
+static int tcp6_gro_complete(struct sk_buff *skb)
+{
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct tcphdr *th = tcp_hdr(skb);
+
+ th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
+ &iph->saddr, &iph->daddr, 0);
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+
+ return tcp_gro_complete(skb);
+}
+
+static const struct net_offload tcpv6_offload = {
+ .callbacks = {
+ .gso_send_check = tcp_v6_gso_send_check,
+ .gso_segment = tcp_tso_segment,
+ .gro_receive = tcp6_gro_receive,
+ .gro_complete = tcp6_gro_complete,
+ },
+};
+
+int __init tcpv6_offload_init(void)
+{
+ return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
+}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index fc9997260a6b..dfaa29b8b293 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1343,103 +1343,9 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
}
#endif
-static int udp6_ufo_send_check(struct sk_buff *skb)
-{
- const struct ipv6hdr *ipv6h;
- struct udphdr *uh;
-
- if (!pskb_may_pull(skb, sizeof(*uh)))
- return -EINVAL;
-
- ipv6h = ipv6_hdr(skb);
- uh = udp_hdr(skb);
-
- uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
- IPPROTO_UDP, 0);
- skb->csum_start = skb_transport_header(skb) - skb->head;
- skb->csum_offset = offsetof(struct udphdr, check);
- skb->ip_summed = CHECKSUM_PARTIAL;
- return 0;
-}
-
-static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
- netdev_features_t features)
-{
- struct sk_buff *segs = ERR_PTR(-EINVAL);
- unsigned int mss;
- unsigned int unfrag_ip6hlen, unfrag_len;
- struct frag_hdr *fptr;
- u8 *mac_start, *prevhdr;
- u8 nexthdr;
- u8 frag_hdr_sz = sizeof(struct frag_hdr);
- int offset;
- __wsum csum;
-
- mss = skb_shinfo(skb)->gso_size;
- if (unlikely(skb->len <= mss))
- goto out;
-
- if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
- /* Packet is from an untrusted source, reset gso_segs. */
- int type = skb_shinfo(skb)->gso_type;
-
- if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
- !(type & (SKB_GSO_UDP))))
- goto out;
-
- skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
-
- segs = NULL;
- goto out;
- }
-
- /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
- * do checksum of UDP packets sent as multiple IP fragments.
- */
- offset = skb_checksum_start_offset(skb);
- csum = skb_checksum(skb, offset, skb->len - offset, 0);
- offset += skb->csum_offset;
- *(__sum16 *)(skb->data + offset) = csum_fold(csum);
- skb->ip_summed = CHECKSUM_NONE;
-
- /* Check if there is enough headroom to insert fragment header. */
- if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
- pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
- goto out;
-
- /* Find the unfragmentable header and shift it left by frag_hdr_sz
- * bytes to insert fragment header.
- */
- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
- nexthdr = *prevhdr;
- *prevhdr = NEXTHDR_FRAGMENT;
- unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
- unfrag_ip6hlen;
- mac_start = skb_mac_header(skb);
- memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
-
- skb->mac_header -= frag_hdr_sz;
- skb->network_header -= frag_hdr_sz;
-
- fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
- fptr->nexthdr = nexthdr;
- fptr->reserved = 0;
- ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
-
- /* Fragment the skb. ipv6 header and the remaining fields of the
- * fragment header are updated in ipv6_gso_segment()
- */
- segs = skb_segment(skb, features);
-
-out:
- return segs;
-}
-
static const struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv,
.err_handler = udpv6_err,
- .gso_send_check = udp6_ufo_send_check,
- .gso_segment = udp6_ufo_fragment,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
new file mode 100644
index 000000000000..0c8934a317c2
--- /dev/null
+++ b/net/ipv6/udp_offload.c
@@ -0,0 +1,120 @@
+/*
+ * IPV6 GSO/GRO offload support
+ * Linux INET6 implementation
+ *
+ * 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.
+ *
+ * UDPv6 GSO support
+ */
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/ipv6.h>
+#include <net/udp.h>
+#include <net/ip6_checksum.h>
+#include "ip6_offload.h"
+
+static int udp6_ufo_send_check(struct sk_buff *skb)
+{
+ const struct ipv6hdr *ipv6h;
+ struct udphdr *uh;
+
+ if (!pskb_may_pull(skb, sizeof(*uh)))
+ return -EINVAL;
+
+ ipv6h = ipv6_hdr(skb);
+ uh = udp_hdr(skb);
+
+ uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+ IPPROTO_UDP, 0);
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ return 0;
+}
+
+static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
+ netdev_features_t features)
+{
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ unsigned int mss;
+ unsigned int unfrag_ip6hlen, unfrag_len;
+ struct frag_hdr *fptr;
+ u8 *mac_start, *prevhdr;
+ u8 nexthdr;
+ u8 frag_hdr_sz = sizeof(struct frag_hdr);
+ int offset;
+ __wsum csum;
+
+ mss = skb_shinfo(skb)->gso_size;
+ if (unlikely(skb->len <= mss))
+ goto out;
+
+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ /* Packet is from an untrusted source, reset gso_segs. */
+ int type = skb_shinfo(skb)->gso_type;
+
+ if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
+ !(type & (SKB_GSO_UDP))))
+ goto out;
+
+ skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
+
+ segs = NULL;
+ goto out;
+ }
+
+ /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
+ * do checksum of UDP packets sent as multiple IP fragments.
+ */
+ offset = skb_checksum_start_offset(skb);
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
+ offset += skb->csum_offset;
+ *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Check if there is enough headroom to insert fragment header. */
+ if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
+ pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
+ goto out;
+
+ /* Find the unfragmentable header and shift it left by frag_hdr_sz
+ * bytes to insert fragment header.
+ */
+ unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+ nexthdr = *prevhdr;
+ *prevhdr = NEXTHDR_FRAGMENT;
+ unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
+ unfrag_ip6hlen;
+ mac_start = skb_mac_header(skb);
+ memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+
+ skb->mac_header -= frag_hdr_sz;
+ skb->network_header -= frag_hdr_sz;
+
+ fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
+ fptr->nexthdr = nexthdr;
+ fptr->reserved = 0;
+ ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+
+ /* Fragment the skb. ipv6 header and the remaining fields of the
+ * fragment header are updated in ipv6_gso_segment()
+ */
+ segs = skb_segment(skb, features);
+
+out:
+ return segs;
+}
+static const struct net_offload udpv6_offload = {
+ .callbacks = {
+ .gso_send_check = udp6_ufo_send_check,
+ .gso_segment = udp6_ufo_fragment,
+ },
+};
+
+int __init udp_offload_init(void)
+{
+ return inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
+}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index f8c4c08ffb60..c9844135c9ca 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -20,7 +20,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/mip6.h>
#endif
@@ -182,7 +182,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
fl6->flowi6_proto = nexthdr;
return;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_MH:
if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
struct ip6_mh *mh;
@@ -327,21 +327,7 @@ static struct ctl_table_header *sysctl_hdr;
int __init xfrm6_init(void)
{
int ret;
- unsigned int gc_thresh;
-
- /*
- * We need a good default value for the xfrm6 gc threshold.
- * In ipv4 we set it to the route hash table size * 8, which
- * is half the size of the maximaum route cache for ipv4. It
- * would be good to do the same thing for v6, except the table is
- * constructed differently here. Here each table for a net namespace
- * can have FIB_TABLE_HASHSZ entries, so lets go with the same
- * computation that we used for ipv4 here. Also, lets keep the initial
- * gc_thresh to a minimum of 1024, since, the ipv6 route cache defaults
- * to that as a minimum as well
- */
- gc_thresh = FIB6_TABLE_HASHSZ * 8;
- xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
+
dst_entries_init(&xfrm6_dst_ops);
ret = xfrm6_policy_init();
@@ -370,7 +356,6 @@ void xfrm6_fini(void)
if (sysctl_hdr)
unregister_net_sysctl_table(sysctl_hdr);
#endif
- //xfrm6_input_fini();
xfrm6_policy_fini();
xfrm6_state_fini();
dst_entries_destroy(&xfrm6_dst_ops);
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index 3f2f7c4ab721..d8c70b8efc24 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -101,7 +101,7 @@ static int __xfrm6_state_sort_cmp(void *p)
return 1;
else
return 3;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case XFRM_MODE_ROUTEOPTIMIZATION:
case XFRM_MODE_IN_TRIGGER:
return 2;
@@ -134,7 +134,7 @@ static int __xfrm6_tmpl_sort_cmp(void *p)
switch (v->mode) {
case XFRM_MODE_TRANSPORT:
return 1;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
case XFRM_MODE_ROUTEOPTIMIZATION:
case XFRM_MODE_IN_TRIGGER:
return 2;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 08897a3c7ec7..5b426a646544 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -141,7 +141,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol,
struct sock *sk;
int err;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 6c4cc12c7414..bbba3a19e944 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -632,7 +632,7 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
nla_put_u16(skb, L2TP_ATTR_MRU, session->mru)))
goto nla_put_failure;
- if ((session->ifname && session->ifname[0] &&
+ if ((session->ifname[0] &&
nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) ||
(session->cookie_len &&
nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len,
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index c2190005a114..88709882c464 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -160,7 +160,7 @@ static int llc_ui_create(struct net *net, struct socket *sock, int protocol,
struct sock *sk;
int rc = -ESOCKTNOSUPPORT;
- if (!capable(CAP_NET_RAW))
+ if (!ns_capable(net->user_ns, CAP_NET_RAW))
return -EPERM;
if (!net_eq(net, &init_net))
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 63af25458fda..b4ecf267a34b 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -248,7 +248,7 @@ config MAC80211_MHWMP_DEBUG
Do not select this option.
config MAC80211_MESH_SYNC_DEBUG
- bool "Verbose mesh mesh synchronization debugging"
+ bool "Verbose mesh synchronization debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
---help---
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index a7dd110faafa..4911202334d9 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -8,6 +8,7 @@ mac80211-y := \
wpa.o \
scan.o offchannel.o \
ht.o agg-tx.o agg-rx.o \
+ vht.o \
ibss.o \
iface.o \
rate.o \
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index a04752e91023..537488cbf941 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/crypto.h>
+#include <linux/export.h>
#include <linux/err.h>
#include <crypto/aes.h>
@@ -126,3 +127,20 @@ void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
{
crypto_free_cipher(tfm);
}
+
+void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
+ u8 *k1, u8 *k2)
+{
+ u8 l[AES_BLOCK_SIZE] = {};
+ struct ieee80211_key *key =
+ container_of(keyconf, struct ieee80211_key, conf);
+
+ crypto_cipher_encrypt_one(key->u.aes_cmac.tfm, l, l);
+
+ memcpy(k1, l, AES_BLOCK_SIZE);
+ gf_mulx(k1);
+
+ memcpy(k2, k1, AES_BLOCK_SIZE);
+ gf_mulx(k2);
+}
+EXPORT_SYMBOL(ieee80211_aes_cmac_calculate_k1_k2);
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 186d9919b043..808338a1bce5 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -118,7 +118,7 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
return;
}
- for (i = 0; i < STA_TID_NUM; i++)
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++)
if (ba_rx_bitmap & BIT(i))
set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 3195a6307f50..eb9df22418f0 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -445,10 +445,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
trace_api_start_tx_ba_session(pubsta, tid);
- if (WARN_ON(!local->ops->ampdu_action))
+ if (WARN_ON_ONCE(!local->ops->ampdu_action))
return -EINVAL;
- if ((tid >= STA_TID_NUM) ||
+ if ((tid >= IEEE80211_NUM_TIDS) ||
!(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) ||
(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW))
return -EINVAL;
@@ -605,9 +605,9 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
trace_api_start_tx_ba_cb(sdata, ra, tid);
- if (tid >= STA_TID_NUM) {
+ if (tid >= IEEE80211_NUM_TIDS) {
ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
- tid, STA_TID_NUM);
+ tid, IEEE80211_NUM_TIDS);
return;
}
@@ -687,7 +687,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
if (!local->ops->ampdu_action)
return -EINVAL;
- if (tid >= STA_TID_NUM)
+ if (tid >= IEEE80211_NUM_TIDS)
return -EINVAL;
spin_lock_bh(&sta->lock);
@@ -722,9 +722,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
trace_api_stop_tx_ba_cb(sdata, ra, tid);
- if (tid >= STA_TID_NUM) {
+ if (tid >= IEEE80211_NUM_TIDS) {
ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
- tid, STA_TID_NUM);
+ tid, IEEE80211_NUM_TIDS);
return;
}
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7371f676cf41..5c61677487cf 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -370,29 +370,64 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
return 0;
}
-static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
-{
- if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
- struct ieee80211_supported_band *sband;
- sband = sta->local->hw.wiphy->bands[
- sta->local->oper_channel->band];
- rate->legacy = sband->bitrates[idx].bitrate;
- } else
- rate->mcs = idx;
-}
-
void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo)
{
rinfo->flags = 0;
- if (rate->flags & IEEE80211_TX_RC_MCS)
+ if (rate->flags & IEEE80211_TX_RC_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_MCS;
+ rinfo->mcs = rate->idx;
+ } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+ rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
+ rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
+ rinfo->nss = ieee80211_rate_get_vht_nss(rate);
+ } else {
+ struct ieee80211_supported_band *sband;
+ sband = sta->local->hw.wiphy->bands[
+ ieee80211_get_sdata_band(sta->sdata)];
+ rinfo->legacy = sband->bitrates[rate->idx].bitrate;
+ }
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
+ if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
- rate_idx_to_bitrate(rinfo, sta, rate->idx);
+}
+
+void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
+{
+ rinfo->flags = 0;
+
+ if (sta->last_rx_rate_flag & RX_FLAG_HT) {
+ rinfo->flags |= RATE_INFO_FLAGS_MCS;
+ rinfo->mcs = sta->last_rx_rate_idx;
+ } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
+ rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
+ rinfo->nss = sta->last_rx_rate_vht_nss;
+ rinfo->mcs = sta->last_rx_rate_idx;
+ } else {
+ struct ieee80211_supported_band *sband;
+
+ sband = sta->local->hw.wiphy->bands[
+ ieee80211_get_sdata_band(sta->sdata)];
+ rinfo->legacy =
+ sband->bitrates[sta->last_rx_rate_idx].bitrate;
+ }
+
+ if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
+ rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
+ rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+ if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
+ rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
+ if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
+ rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
+ if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
+ rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
}
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
@@ -441,15 +476,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
}
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
-
- sinfo->rxrate.flags = 0;
- if (sta->last_rx_rate_flag & RX_FLAG_HT)
- sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
- if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
- sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
- if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
- sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx);
+ sta_set_rate_info_rx(sta, &sinfo->rxrate);
if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH
@@ -532,6 +559,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
u64 *data)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *channel;
struct sta_info *sta;
struct ieee80211_local *local = sdata->local;
struct station_info sinfo;
@@ -607,19 +636,26 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
do_survey:
i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
/* Get survey stats for current channel */
- q = 0;
- while (true) {
- survey.filled = 0;
- if (drv_get_survey(local, q, &survey) != 0) {
- survey.filled = 0;
- break;
- }
+ survey.filled = 0;
- if (survey.channel &&
- (local->oper_channel->center_freq ==
- survey.channel->center_freq))
- break;
- q++;
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (chanctx_conf)
+ channel = chanctx_conf->def.chan;
+ else
+ channel = NULL;
+ rcu_read_unlock();
+
+ if (channel) {
+ q = 0;
+ do {
+ survey.filled = 0;
+ if (drv_get_survey(local, q, &survey) != 0) {
+ survey.filled = 0;
+ break;
+ }
+ q++;
+ } while (channel != survey.channel);
}
if (survey.filled)
@@ -724,47 +760,37 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
-static int ieee80211_set_channel(struct wiphy *wiphy,
- struct net_device *netdev,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
+static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_sub_if_data *sdata = NULL;
-
- if (netdev)
- sdata = IEEE80211_DEV_TO_SUB_IF(netdev);
-
- switch (ieee80211_get_channel_mode(local, NULL)) {
- case CHAN_MODE_HOPPING:
- return -EBUSY;
- case CHAN_MODE_FIXED:
- if (local->oper_channel != chan ||
- (!sdata && local->_oper_channel_type != channel_type))
- return -EBUSY;
- if (!sdata && local->_oper_channel_type == channel_type)
- return 0;
- break;
- case CHAN_MODE_UNDEFINED:
- break;
- }
+ struct ieee80211_sub_if_data *sdata;
+ int ret = 0;
- if (!ieee80211_set_channel_type(local, sdata, channel_type))
- return -EBUSY;
+ if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
+ return 0;
- local->oper_channel = chan;
+ mutex_lock(&local->iflist_mtx);
+ if (local->use_chanctx) {
+ sdata = rcu_dereference_protected(
+ local->monitor_sdata,
+ lockdep_is_held(&local->iflist_mtx));
+ if (sdata) {
+ ieee80211_vif_release_channel(sdata);
+ ret = ieee80211_vif_use_channel(sdata, chandef,
+ IEEE80211_CHANCTX_EXCLUSIVE);
+ }
+ } else if (local->open_count == local->monitors) {
+ local->_oper_channel = chandef->chan;
+ local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ ieee80211_hw_config(local, 0);
+ }
- /* auto-detects changes */
- ieee80211_hw_config(local, 0);
+ if (ret == 0)
+ local->monitor_chandef = *chandef;
+ mutex_unlock(&local->iflist_mtx);
- return 0;
-}
-
-static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
-{
- return ieee80211_set_channel(wiphy, NULL, chan, channel_type);
+ return ret;
}
static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
@@ -872,15 +898,20 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
u32 changed = BSS_CHANGED_BEACON_INT |
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON |
- BSS_CHANGED_SSID;
+ BSS_CHANGED_SSID |
+ BSS_CHANGED_P2P_PS;
int err;
old = rtnl_dereference(sdata->u.ap.beacon);
if (old)
return -EALREADY;
- err = ieee80211_set_channel(wiphy, dev, params->channel,
- params->channel_type);
+ /* TODO: make hostapd tell us what it wants */
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
+ sdata->needed_rx_chains = sdata->local->rx_chains;
+
+ err = ieee80211_vif_use_channel(sdata, &params->chandef,
+ IEEE80211_CHANCTX_SHARED);
if (err)
return err;
@@ -907,11 +938,23 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.hidden_ssid =
(params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
+ sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
+ sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+
err = ieee80211_assign_beacon(sdata, &params->beacon);
if (err < 0)
return err;
changed |= err;
+ err = drv_start_ap(sdata->local, sdata);
+ if (err) {
+ old = rtnl_dereference(sdata->u.ap.beacon);
+ if (old)
+ kfree_rcu(old, rcu_head);
+ RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
+ return err;
+ }
+
ieee80211_bss_info_change_notify(sdata, changed);
netif_carrier_on(dev);
@@ -943,26 +986,40 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
{
- struct ieee80211_sub_if_data *sdata, *vlan;
- struct beacon_data *old;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *vlan;
+ struct ieee80211_local *local = sdata->local;
+ struct beacon_data *old_beacon;
+ struct probe_resp *old_probe_resp;
- old = rtnl_dereference(sdata->u.ap.beacon);
- if (!old)
+ old_beacon = rtnl_dereference(sdata->u.ap.beacon);
+ if (!old_beacon)
return -ENOENT;
+ old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
+ /* turn off carrier for this interface and dependent VLANs */
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
netif_carrier_off(vlan->dev);
netif_carrier_off(dev);
+ /* remove beacon and probe response */
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
+ RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
+ kfree_rcu(old_beacon, rcu_head);
+ if (old_probe_resp)
+ kfree_rcu(old_probe_resp, rcu_head);
- kfree_rcu(old, rcu_head);
-
- sta_info_flush(sdata->local, sdata);
+ sta_info_flush(local, sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+ drv_stop_ap(sdata->local, sdata);
+
+ /* free all potentially still buffered bcast frames */
+ local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
+ skb_queue_purge(&sdata->u.ap.ps.bc_buf);
+
+ ieee80211_vif_release_channel(sdata);
+
return 0;
}
@@ -1019,9 +1076,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
int i, j;
struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
u32 mask, set;
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ sband = local->hw.wiphy->bands[band];
mask = params->sta_flags_mask;
set = params->sta_flags_set;
@@ -1136,7 +1194,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
rates |= BIT(j);
}
}
- sta->sta.supp_rates[local->oper_channel->band] = rates;
+ sta->sta.supp_rates[band] = rates;
}
if (params->ht_capa)
@@ -1144,6 +1202,11 @@ static int sta_apply_parameters(struct ieee80211_local *local,
params->ht_capa,
&sta->sta.ht_cap);
+ if (params->vht_capa)
+ ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
+ params->vht_capa,
+ &sta->sta.vht_cap);
+
if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH
if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED)
@@ -1664,8 +1727,12 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
if (err)
return err;
- err = ieee80211_set_channel(wiphy, dev, setup->channel,
- setup->channel_type);
+ /* can mesh use other SMPS modes? */
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
+ sdata->needed_rx_chains = sdata->local->rx_chains;
+
+ err = ieee80211_vif_use_channel(sdata, &setup->chandef,
+ IEEE80211_CHANCTX_SHARED);
if (err)
return err;
@@ -1679,6 +1746,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_stop_mesh(sdata);
+ ieee80211_vif_release_channel(sdata);
return 0;
}
@@ -1688,10 +1756,14 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
struct net_device *dev,
struct bss_parameters *params)
{
- struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ enum ieee80211_band band;
u32 changed = 0;
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (!rtnl_dereference(sdata->u.ap.beacon))
+ return -ENOENT;
+
+ band = ieee80211_get_sdata_band(sdata);
if (params->use_cts_prot >= 0) {
sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
@@ -1704,7 +1776,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
}
if (!sdata->vif.bss_conf.use_short_slot &&
- sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) {
+ band == IEEE80211_BAND_5GHZ) {
sdata->vif.bss_conf.use_short_slot = true;
changed |= BSS_CHANGED_ERP_SLOT;
}
@@ -1718,9 +1790,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
if (params->basic_rates) {
int i, j;
u32 rates = 0;
- struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_supported_band *sband =
- wiphy->bands[local->oper_channel->band];
+ struct ieee80211_supported_band *sband = wiphy->bands[band];
for (i = 0; i < params->basic_rates_len; i++) {
int rate = (params->basic_rates[i] & 0x7f) * 5;
@@ -1746,6 +1816,16 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
changed |= BSS_CHANGED_HT;
}
+ if (params->p2p_ctwindow >= 0) {
+ sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
+ changed |= BSS_CHANGED_P2P_PS;
+ }
+
+ if (params->p2p_opp_ps >= 0) {
+ sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+ changed |= BSS_CHANGED_P2P_PS;
+ }
+
ieee80211_bss_info_change_notify(sdata, changed);
return 0;
@@ -1829,7 +1909,16 @@ static int ieee80211_scan(struct wiphy *wiphy,
* beaconing hasn't been configured yet
*/
case NL80211_IFTYPE_AP:
- if (sdata->u.ap.beacon)
+ /*
+ * If the scan has been forced (and the driver supports
+ * forcing), don't care about being beaconing already.
+ * This will create problems to the attached stations (e.g. all
+ * the frames sent while scanning on other channel will be
+ * lost)
+ */
+ if (sdata->u.ap.beacon &&
+ (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
+ !(req->flags & NL80211_SCAN_FLAG_AP)))
return -EOPNOTSUPP;
break;
default:
@@ -1872,20 +1961,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req)
{
- struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- switch (ieee80211_get_channel_mode(local, sdata)) {
- case CHAN_MODE_HOPPING:
- return -EBUSY;
- case CHAN_MODE_FIXED:
- if (local->oper_channel == req->bss->channel)
- break;
- return -EBUSY;
- case CHAN_MODE_UNDEFINED:
- break;
- }
-
return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
}
@@ -1904,30 +1979,22 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
- struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- switch (ieee80211_get_channel_mode(local, sdata)) {
- case CHAN_MODE_HOPPING:
- return -EBUSY;
- case CHAN_MODE_FIXED:
- if (!params->channel_fixed)
- return -EBUSY;
- if (local->oper_channel == params->channel)
- break;
- return -EBUSY;
- case CHAN_MODE_UNDEFINED:
- break;
- }
-
- return ieee80211_ibss_join(sdata, params);
+ return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params);
}
static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
{
+ return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
+}
+
+static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
+ int rate[IEEE80211_NUM_BANDS])
+{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- return ieee80211_ibss_leave(sdata);
+ memcpy(sdata->vif.bss_conf.mcast_rate, rate, sizeof(rate));
+
+ return 0;
}
static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
@@ -1956,10 +2023,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return err;
}
- if (changed & WIPHY_PARAM_RETRY_SHORT)
+ if (changed & WIPHY_PARAM_RETRY_SHORT) {
+ if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY)
+ return -EINVAL;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
- if (changed & WIPHY_PARAM_RETRY_LONG)
+ }
+ if (changed & WIPHY_PARAM_RETRY_LONG) {
+ if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY)
+ return -EINVAL;
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
+ }
if (changed &
(WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
@@ -1968,41 +2041,65 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
}
static int ieee80211_set_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_channel *chan = local->oper_channel;
- u32 changes = 0;
+ struct ieee80211_sub_if_data *sdata;
+
+ if (wdev) {
+ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+ break;
+ case NL80211_TX_POWER_LIMITED:
+ case NL80211_TX_POWER_FIXED:
+ if (mbm < 0 || (mbm % 100))
+ return -EOPNOTSUPP;
+ sdata->user_power_level = MBM_TO_DBM(mbm);
+ break;
+ }
+
+ ieee80211_recalc_txpower(sdata);
+
+ return 0;
+ }
switch (type) {
case NL80211_TX_POWER_AUTOMATIC:
- local->user_power_level = -1;
+ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
break;
case NL80211_TX_POWER_LIMITED:
- if (mbm < 0 || (mbm % 100))
- return -EOPNOTSUPP;
- local->user_power_level = MBM_TO_DBM(mbm);
- break;
case NL80211_TX_POWER_FIXED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
- /* TODO: move to cfg80211 when it knows the channel */
- if (MBM_TO_DBM(mbm) > chan->max_power)
- return -EINVAL;
local->user_power_level = MBM_TO_DBM(mbm);
break;
}
- ieee80211_hw_config(local, changes);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list)
+ sdata->user_power_level = local->user_power_level;
+ list_for_each_entry(sdata, &local->interfaces, list)
+ ieee80211_recalc_txpower(sdata);
+ mutex_unlock(&local->iflist_mtx);
return 0;
}
-static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
+static int ieee80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ int *dbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- *dbm = local->hw.conf.power_level;
+ if (!local->use_chanctx)
+ *dbm = local->hw.conf.power_level;
+ else
+ *dbm = sdata->vif.bss_conf.txpower;
return 0;
}
@@ -2067,13 +2164,12 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
/*
* If not associated, or current association is not an HT
- * association, there's no need to send an action frame.
+ * association, there's no need to do anything, just store
+ * the new value until we associate.
*/
if (!sdata->u.mgd.associated ||
- sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) {
- ieee80211_recalc_smps(sdata->local);
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0;
- }
ap = sdata->u.mgd.associated->bssid;
@@ -2179,7 +2275,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
static int ieee80211_start_roc_work(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel,
- enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie,
struct sk_buff *txskb)
{
@@ -2189,12 +2284,14 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
lockdep_assert_held(&local->mtx);
+ if (local->use_chanctx && !local->ops->remain_on_channel)
+ return -EOPNOTSUPP;
+
roc = kzalloc(sizeof(*roc), GFP_KERNEL);
if (!roc)
return -ENOMEM;
roc->chan = channel;
- roc->chan_type = channel_type;
roc->duration = duration;
roc->req_duration = duration;
roc->frame = txskb;
@@ -2227,7 +2324,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
if (!duration)
duration = 10;
- ret = drv_remain_on_channel(local, channel, channel_type, duration);
+ ret = drv_remain_on_channel(local, sdata, channel, duration);
if (ret) {
kfree(roc);
return ret;
@@ -2238,7 +2335,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
out_check_combine:
list_for_each_entry(tmp, &local->roc_list, list) {
- if (tmp->chan != channel || tmp->chan_type != channel_type)
+ if (tmp->chan != channel || tmp->sdata != sdata)
continue;
/*
@@ -2332,13 +2429,22 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
list_add_tail(&roc->list, &local->roc_list);
/*
- * cookie is either the roc (for normal roc)
+ * cookie is either the roc cookie (for normal roc)
* or the SKB (for mgmt TX)
*/
- if (txskb)
+ if (!txskb) {
+ /* local->mtx protects this */
+ local->roc_cookie_counter++;
+ roc->cookie = local->roc_cookie_counter;
+ /* wow, you wrapped 64 bits ... more likely a bug */
+ if (WARN_ON(roc->cookie == 0)) {
+ roc->cookie = 1;
+ local->roc_cookie_counter++;
+ }
+ *cookie = roc->cookie;
+ } else {
*cookie = (unsigned long)txskb;
- else
- *cookie = (unsigned long)roc;
+ }
return 0;
}
@@ -2346,7 +2452,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
static int ieee80211_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie)
{
@@ -2355,7 +2460,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
int ret;
mutex_lock(&local->mtx);
- ret = ieee80211_start_roc_work(local, sdata, chan, channel_type,
+ ret = ieee80211_start_roc_work(local, sdata, chan,
duration, cookie, NULL);
mutex_unlock(&local->mtx);
@@ -2373,7 +2478,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
struct ieee80211_roc_work *dep, *tmp2;
list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
- if (!mgmt_tx && (unsigned long)dep != cookie)
+ if (!mgmt_tx && dep->cookie != cookie)
continue;
else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
continue;
@@ -2385,7 +2490,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
return 0;
}
- if (!mgmt_tx && (unsigned long)roc != cookie)
+ if (!mgmt_tx && roc->cookie != cookie)
continue;
else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
continue;
@@ -2448,10 +2553,8 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie)
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = sdata->local;
@@ -2515,10 +2618,16 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
/* Check if the operating channel is the requested channel */
if (!need_offchan) {
- need_offchan = chan != local->oper_channel;
- if (channel_type_valid &&
- channel_type != local->_oper_channel_type)
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+ if (chanctx_conf)
+ need_offchan = chan != chanctx_conf->def.chan;
+ else
need_offchan = true;
+ rcu_read_unlock();
}
if (need_offchan && !offchan) {
@@ -2552,7 +2661,7 @@ 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, channel_type,
+ ret = ieee80211_start_roc_work(local, sdata, chan,
wait, cookie, skb);
if (ret)
kfree_skb(skb);
@@ -2670,7 +2779,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
u16 capab;
capab = 0;
- if (local->oper_channel->band != IEEE80211_BAND_2GHZ)
+ if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
return capab;
if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
@@ -2702,7 +2811,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
u16 status_code, struct sk_buff *skb)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_tdls_data *tf;
tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
@@ -2722,10 +2831,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_req.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(sdata, skb, false,
- local->oper_channel->band);
- ieee80211_add_ext_srates_ie(sdata, skb, false,
- local->oper_channel->band);
+ ieee80211_add_srates_ie(sdata, skb, false, band);
+ ieee80211_add_ext_srates_ie(sdata, skb, false, band);
ieee80211_tdls_add_ext_capab(skb);
break;
case WLAN_TDLS_SETUP_RESPONSE:
@@ -2738,10 +2845,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(sdata, skb, false,
- local->oper_channel->band);
- ieee80211_add_ext_srates_ie(sdata, skb, false,
- local->oper_channel->band);
+ ieee80211_add_srates_ie(sdata, skb, false, band);
+ ieee80211_add_ext_srates_ie(sdata, skb, false, band);
ieee80211_tdls_add_ext_capab(skb);
break;
case WLAN_TDLS_SETUP_CONFIRM:
@@ -2779,7 +2884,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
u16 status_code, struct sk_buff *skb)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_mgmt *mgmt;
mgmt = (void *)skb_put(skb, 24);
@@ -2802,10 +2907,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
mgmt->u.action.u.tdls_discover_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(sdata, skb, false,
- local->oper_channel->band);
- ieee80211_add_ext_srates_ie(sdata, skb, false,
- local->oper_channel->band);
+ ieee80211_add_srates_ie(sdata, skb, false, band);
+ ieee80211_add_ext_srates_ie(sdata, skb, false, band);
ieee80211_tdls_add_ext_capab(skb);
break;
default:
@@ -2822,7 +2925,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- struct ieee80211_tx_info *info;
struct sk_buff *skb = NULL;
bool send_direct;
int ret;
@@ -2848,7 +2950,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
if (!skb)
return -ENOMEM;
- info = IEEE80211_SKB_CB(skb);
skb_reserve(skb, local->hw.extra_tx_headroom);
switch (action_code) {
@@ -2985,12 +3086,19 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
bool qos;
struct ieee80211_tx_info *info;
struct sta_info *sta;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum ieee80211_band band;
rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ band = chanctx_conf->def.chan->band;
sta = sta_info_get(sdata, peer);
if (sta) {
qos = test_sta_flag(sta, WLAN_STA_WME);
- rcu_read_unlock();
} else {
rcu_read_unlock();
return -ENOLINK;
@@ -3008,8 +3116,10 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
}
skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
- if (!skb)
+ if (!skb) {
+ rcu_read_unlock();
return -ENOMEM;
+ }
skb->dev = dev;
@@ -3034,21 +3144,31 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
nullfunc->qos_ctrl = cpu_to_le16(7);
local_bh_disable();
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, band);
local_bh_enable();
+ rcu_read_unlock();
*cookie = (unsigned long) skb;
return 0;
}
-static struct ieee80211_channel *
-ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
- enum nl80211_channel_type *type)
+static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef)
{
- struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int ret = -ENODATA;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (chanctx_conf) {
+ *chandef = chanctx_conf->def;
+ ret = 0;
+ }
+ rcu_read_unlock();
- *type = local->_oper_channel_type;
- return local->oper_channel;
+ return ret;
}
#ifdef CONFIG_PM
@@ -3103,6 +3223,7 @@ struct cfg80211_ops mac80211_config_ops = {
.disassoc = ieee80211_disassoc,
.join_ibss = ieee80211_join_ibss,
.leave_ibss = ieee80211_leave_ibss,
+ .set_mcast_rate = ieee80211_set_mcast_rate,
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 0bfc914ddd15..53f03120db55 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -3,168 +3,347 @@
*/
#include <linux/nl80211.h>
+#include <linux/export.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
+#include "driver-ops.h"
-static enum ieee80211_chan_mode
-__ieee80211_get_channel_mode(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *ignore)
+static void ieee80211_change_chandef(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx,
+ const struct cfg80211_chan_def *chandef)
{
+ if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
+ return;
+
+ WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
+
+ ctx->conf.def = *chandef;
+ drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
+
+ if (!local->use_chanctx) {
+ local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ ieee80211_hw_config(local, 0);
+ }
+}
+
+static struct ieee80211_chanctx *
+ieee80211_find_chanctx(struct ieee80211_local *local,
+ const struct cfg80211_chan_def *chandef,
+ enum ieee80211_chanctx_mode mode)
+{
+ struct ieee80211_chanctx *ctx;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
+ return NULL;
+
+ list_for_each_entry(ctx, &local->chanctx_list, list) {
+ const struct cfg80211_chan_def *compat;
+
+ if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
+ continue;
+
+ compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
+ if (!compat)
+ continue;
+
+ ieee80211_change_chandef(local, ctx, compat);
+
+ return ctx;
+ }
+
+ return NULL;
+}
+
+static struct ieee80211_chanctx *
+ieee80211_new_chanctx(struct ieee80211_local *local,
+ const struct cfg80211_chan_def *chandef,
+ enum ieee80211_chanctx_mode mode)
+{
+ struct ieee80211_chanctx *ctx;
+ int err;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ ctx->conf.def = *chandef;
+ ctx->conf.rx_chains_static = 1;
+ ctx->conf.rx_chains_dynamic = 1;
+ ctx->mode = mode;
+
+ if (!local->use_chanctx) {
+ local->_oper_channel_type =
+ cfg80211_get_chandef_type(chandef);
+ local->_oper_channel = chandef->chan;
+ ieee80211_hw_config(local, 0);
+ } else {
+ err = drv_add_chanctx(local, ctx);
+ if (err) {
+ kfree(ctx);
+ return ERR_PTR(err);
+ }
+ }
+
+ list_add_rcu(&ctx->list, &local->chanctx_list);
+
+ return ctx;
+}
+
+static void ieee80211_free_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx)
+{
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ WARN_ON_ONCE(ctx->refcount != 0);
+
+ if (!local->use_chanctx) {
+ local->_oper_channel_type = NL80211_CHAN_NO_HT;
+ ieee80211_hw_config(local, 0);
+ } else {
+ drv_remove_chanctx(local, ctx);
+ }
+
+ list_del_rcu(&ctx->list);
+ kfree_rcu(ctx, rcu_head);
+}
+
+static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx)
+{
+ struct ieee80211_local *local = sdata->local;
+ int ret;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ ret = drv_assign_vif_chanctx(local, sdata, ctx);
+ if (ret)
+ return ret;
+
+ rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
+ ctx->refcount++;
+
+ ieee80211_recalc_txpower(sdata);
+
+ return 0;
+}
+
+static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx)
+{
+ struct ieee80211_chanctx_conf *conf = &ctx->conf;
struct ieee80211_sub_if_data *sdata;
+ const struct cfg80211_chan_def *compat = NULL;
- lockdep_assert_held(&local->iflist_mtx);
+ lockdep_assert_held(&local->chanctx_mtx);
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata == ignore)
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+ if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
continue;
+ if (!compat)
+ compat = &sdata->vif.bss_conf.chandef;
+
+ compat = cfg80211_chandef_compatible(
+ &sdata->vif.bss_conf.chandef, compat);
+ if (!compat)
+ break;
+ }
+ rcu_read_unlock();
+
+ if (WARN_ON_ONCE(!compat))
+ return;
+
+ ieee80211_change_chandef(local, ctx, compat);
+}
+
+static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx)
+{
+ struct ieee80211_local *local = sdata->local;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ ctx->refcount--;
+ rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
+
+ drv_unassign_vif_chanctx(local, sdata, ctx);
+
+ if (ctx->refcount > 0) {
+ ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
+ ieee80211_recalc_smps_chanctx(local, ctx);
+ }
+}
+
+static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *conf;
+ struct ieee80211_chanctx *ctx;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (!conf)
+ return;
+
+ ctx = container_of(conf, struct ieee80211_chanctx, conf);
+
+ ieee80211_unassign_vif_chanctx(sdata, ctx);
+ if (ctx->refcount == 0)
+ ieee80211_free_chanctx(local, ctx);
+}
+
+void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *chanctx)
+{
+ struct ieee80211_sub_if_data *sdata;
+ u8 rx_chains_static, rx_chains_dynamic;
+
+ lockdep_assert_held(&local->chanctx_mtx);
+
+ rx_chains_static = 1;
+ rx_chains_dynamic = 1;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ u8 needed_static, needed_dynamic;
+
if (!ieee80211_sdata_running(sdata))
continue;
+ if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
+ &chanctx->conf)
+ continue;
+
switch (sdata->vif.type) {
- case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_P2P_DEVICE:
continue;
case NL80211_IFTYPE_STATION:
if (!sdata->u.mgd.associated)
continue;
break;
- case NL80211_IFTYPE_ADHOC:
- if (!sdata->u.ibss.ssid_len)
- continue;
- if (!sdata->u.ibss.fixed_channel)
- return CHAN_MODE_HOPPING;
- break;
case NL80211_IFTYPE_AP_VLAN:
- /* will also have _AP interface */
continue;
case NL80211_IFTYPE_AP:
- if (!sdata->u.ap.beacon)
- continue;
- break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
- if (!sdata->wdev.mesh_id_len)
- continue;
break;
default:
+ WARN_ON_ONCE(1);
+ }
+
+ switch (sdata->smps_mode) {
+ default:
+ WARN_ONCE(1, "Invalid SMPS mode %d\n",
+ sdata->smps_mode);
+ /* fall through */
+ case IEEE80211_SMPS_OFF:
+ needed_static = sdata->needed_rx_chains;
+ needed_dynamic = sdata->needed_rx_chains;
+ break;
+ case IEEE80211_SMPS_DYNAMIC:
+ needed_static = 1;
+ needed_dynamic = sdata->needed_rx_chains;
+ break;
+ case IEEE80211_SMPS_STATIC:
+ needed_static = 1;
+ needed_dynamic = 1;
break;
}
- return CHAN_MODE_FIXED;
+ rx_chains_static = max(rx_chains_static, needed_static);
+ rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
}
+ rcu_read_unlock();
- return CHAN_MODE_UNDEFINED;
-}
-
-enum ieee80211_chan_mode
-ieee80211_get_channel_mode(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *ignore)
-{
- enum ieee80211_chan_mode mode;
+ if (!local->use_chanctx) {
+ if (rx_chains_static > 1)
+ local->smps_mode = IEEE80211_SMPS_OFF;
+ else if (rx_chains_dynamic > 1)
+ local->smps_mode = IEEE80211_SMPS_DYNAMIC;
+ else
+ local->smps_mode = IEEE80211_SMPS_STATIC;
+ ieee80211_hw_config(local, 0);
+ }
- mutex_lock(&local->iflist_mtx);
- mode = __ieee80211_get_channel_mode(local, ignore);
- mutex_unlock(&local->iflist_mtx);
+ if (rx_chains_static == chanctx->conf.rx_chains_static &&
+ rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
+ return;
- return mode;
+ chanctx->conf.rx_chains_static = rx_chains_static;
+ chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
+ drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
}
-static enum nl80211_channel_type
-ieee80211_get_superchan(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
+int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_chan_def *chandef,
+ enum ieee80211_chanctx_mode mode)
{
- enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT;
- struct ieee80211_sub_if_data *tmp;
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx *ctx;
+ int ret;
- mutex_lock(&local->iflist_mtx);
- list_for_each_entry(tmp, &local->interfaces, list) {
- if (tmp == sdata)
- continue;
-
- if (!ieee80211_sdata_running(tmp))
- continue;
+ WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
- switch (tmp->vif.bss_conf.channel_type) {
- case NL80211_CHAN_NO_HT:
- case NL80211_CHAN_HT20:
- if (superchan > tmp->vif.bss_conf.channel_type)
- break;
+ mutex_lock(&local->chanctx_mtx);
+ __ieee80211_vif_release_channel(sdata);
- superchan = tmp->vif.bss_conf.channel_type;
- break;
- case NL80211_CHAN_HT40PLUS:
- WARN_ON(superchan == NL80211_CHAN_HT40MINUS);
- superchan = NL80211_CHAN_HT40PLUS;
- break;
- case NL80211_CHAN_HT40MINUS:
- WARN_ON(superchan == NL80211_CHAN_HT40PLUS);
- superchan = NL80211_CHAN_HT40MINUS;
- break;
- }
+ ctx = ieee80211_find_chanctx(local, chandef, mode);
+ if (!ctx)
+ ctx = ieee80211_new_chanctx(local, chandef, mode);
+ if (IS_ERR(ctx)) {
+ ret = PTR_ERR(ctx);
+ goto out;
}
- mutex_unlock(&local->iflist_mtx);
- return superchan;
-}
+ sdata->vif.bss_conf.chandef = *chandef;
-static bool
-ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1,
- enum nl80211_channel_type chantype2,
- enum nl80211_channel_type *compat)
-{
- /*
- * start out with chantype1 being the result,
- * overwriting later if needed
- */
- if (compat)
- *compat = chantype1;
-
- switch (chantype1) {
- case NL80211_CHAN_NO_HT:
- if (compat)
- *compat = chantype2;
- break;
- case NL80211_CHAN_HT20:
- /*
- * allow any change that doesn't go to no-HT
- * (if it already is no-HT no change is needed)
- */
- if (chantype2 == NL80211_CHAN_NO_HT)
- break;
- if (compat)
- *compat = chantype2;
- break;
- case NL80211_CHAN_HT40PLUS:
- case NL80211_CHAN_HT40MINUS:
- /* allow smaller bandwidth and same */
- if (chantype2 == NL80211_CHAN_NO_HT)
- break;
- if (chantype2 == NL80211_CHAN_HT20)
- break;
- if (chantype2 == chantype1)
- break;
- return false;
+ ret = ieee80211_assign_vif_chanctx(sdata, ctx);
+ if (ret) {
+ /* if assign fails refcount stays the same */
+ if (ctx->refcount == 0)
+ ieee80211_free_chanctx(local, ctx);
+ goto out;
}
- return true;
+ ieee80211_recalc_smps_chanctx(local, ctx);
+ out:
+ mutex_unlock(&local->chanctx_mtx);
+ return ret;
}
-bool ieee80211_set_channel_type(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum nl80211_channel_type chantype)
+void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
{
- enum nl80211_channel_type superchan;
- enum nl80211_channel_type compatchan;
-
- superchan = ieee80211_get_superchan(local, sdata);
- if (!ieee80211_channel_types_are_compatible(superchan, chantype,
- &compatchan))
- return false;
+ WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
- local->_oper_channel_type = compatchan;
-
- if (sdata)
- sdata->vif.bss_conf.channel_type = chantype;
+ mutex_lock(&sdata->local->chanctx_mtx);
+ __ieee80211_vif_release_channel(sdata);
+ mutex_unlock(&sdata->local->chanctx_mtx);
+}
- return true;
+void ieee80211_iter_chan_contexts_atomic(
+ struct ieee80211_hw *hw,
+ void (*iter)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ void *data),
+ void *iter_data)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_chanctx *ctx;
+ rcu_read_lock();
+ list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
+ iter(hw, &ctx->conf, iter_data);
+ rcu_read_unlock();
}
+EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index 9be4e6d71d00..214ed4ecd739 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -2,9 +2,9 @@
#define __MAC80211_DEBUGFS_H
#ifdef CONFIG_MAC80211_DEBUGFS
-extern void debugfs_hw_add(struct ieee80211_local *local);
-extern int mac80211_format_buffer(char __user *userbuf, size_t count,
- loff_t *ppos, char *fmt, ...);
+void debugfs_hw_add(struct ieee80211_local *local);
+int __printf(4, 5) mac80211_format_buffer(char __user *userbuf, size_t count,
+ loff_t *ppos, char *fmt, ...);
#else
static inline void debugfs_hw_add(struct ieee80211_local *local)
{
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 090d08ff22c4..c3a3082b72e5 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -116,7 +116,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_key *key = file->private_data;
- char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
+ char buf[14*IEEE80211_NUM_TIDS+1], *p = buf;
int i, len;
const u8 *rpn;
@@ -126,7 +126,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
len = scnprintf(buf, sizeof(buf), "\n");
break;
case WLAN_CIPHER_SUITE_TKIP:
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++)
p += scnprintf(p, sizeof(buf)+buf-p,
"%08x %04x\n",
key->u.tkip.rx[i].iv32,
@@ -134,7 +134,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
len = p - buf;
break;
case WLAN_CIPHER_SUITE_CCMP:
- for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
rpn = key->u.ccmp.rx_pn[i];
p += scnprintf(p, sizeof(buf)+buf-p,
"%02x%02x%02x%02x%02x%02x\n",
@@ -199,6 +199,22 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
}
KEY_OPS(icverrors);
+static ssize_t key_mic_failures_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_key *key = file->private_data;
+ char buf[20];
+ int len;
+
+ if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP)
+ return -EINVAL;
+
+ len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(mic_failures);
+
static ssize_t key_key_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -260,6 +276,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
DEBUGFS_ADD(rx_spec);
DEBUGFS_ADD(replays);
DEBUGFS_ADD(icverrors);
+ DEBUGFS_ADD(mic_failures);
DEBUGFS_ADD(key);
DEBUGFS_ADD(ifindex);
};
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 6d5aec9418ee..cbde5cc49a40 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/if.h>
+#include <linux/if_ether.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
@@ -167,7 +168,29 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
IEEE80211_IF_FILE(flags, flags, HEX);
IEEE80211_IF_FILE(state, state, LHEX);
-IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
+IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
+IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
+IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
+
+static ssize_t
+ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
+ char *buf, int buflen)
+{
+ int len;
+
+ len = scnprintf(buf, buflen, "AC queues: VO:%d VI:%d BE:%d BK:%d\n",
+ sdata->vif.hw_queue[IEEE80211_AC_VO],
+ sdata->vif.hw_queue[IEEE80211_AC_VI],
+ sdata->vif.hw_queue[IEEE80211_AC_BE],
+ sdata->vif.hw_queue[IEEE80211_AC_BK]);
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ len += scnprintf(buf + len, buflen - len, "cab queue: %d\n",
+ sdata->vif.cab_queue);
+
+ return len;
+}
+__IEEE80211_IF_FILE(hw_queues, NULL);
/* STA attributes */
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
@@ -217,7 +240,7 @@ static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
return snprintf(buf, buflen, "request: %s\nused: %s\n",
smps_modes[sdata->u.mgd.req_smps],
- smps_modes[sdata->u.mgd.ap_smps]);
+ smps_modes[sdata->smps_mode]);
}
static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
@@ -245,27 +268,6 @@ static ssize_t ieee80211_if_fmt_tkip_mic_test(
return -EOPNOTSUPP;
}
-static int hwaddr_aton(const char *txt, u8 *addr)
-{
- int i;
-
- for (i = 0; i < ETH_ALEN; i++) {
- int a, b;
-
- a = hex_to_bin(*txt++);
- if (a < 0)
- return -1;
- b = hex_to_bin(*txt++);
- if (b < 0)
- return -1;
- *addr++ = (a << 4) | b;
- if (i < 5 && *txt++ != ':')
- return -1;
- }
-
- return 0;
-}
-
static ssize_t ieee80211_if_parse_tkip_mic_test(
struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
{
@@ -275,13 +277,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
struct ieee80211_hdr *hdr;
__le16 fc;
- /*
- * Assume colon-delimited MAC address with possible white space
- * following.
- */
- if (buflen < 3 * ETH_ALEN - 1)
- return -EINVAL;
- if (hwaddr_aton(buf, addr) < 0)
+ if (!mac_pton(buf, addr))
return -EINVAL;
if (!ieee80211_sdata_running(sdata))
@@ -307,13 +303,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
- if (sdata->vif.bss_conf.bssid == NULL) {
+ mutex_lock(&sdata->u.mgd.mtx);
+ if (!sdata->u.mgd.associated) {
+ mutex_unlock(&sdata->u.mgd.mtx);
dev_kfree_skb(skb);
return -ENOTCONN;
}
- memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN);
+ memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN);
+ mutex_unlock(&sdata->u.mgd.mtx);
break;
default:
dev_kfree_skb(skb);
@@ -395,14 +394,14 @@ __IEEE80211_IF_FILE_W(uapsd_max_sp_len);
/* AP attributes */
IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
-IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
-IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
+IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
+IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
return scnprintf(buf, buflen, "%u\n",
- skb_queue_len(&sdata->u.ap.ps_bc_buf));
+ skb_queue_len(&sdata->u.ap.ps.bc_buf));
}
__IEEE80211_IF_FILE(num_buffered_multicast, NULL);
@@ -443,7 +442,7 @@ static ssize_t ieee80211_if_parse_tsf(
}
ret = kstrtoull(buf, 10, &tsf);
if (ret < 0)
- return -EINVAL;
+ return ret;
if (tsf_is_delta)
tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf;
if (local->ops->set_tsf) {
@@ -471,7 +470,7 @@ IEEE80211_IF_FILE(dropped_frames_congestion,
u.mesh.mshstats.dropped_frames_congestion, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route,
u.mesh.mshstats.dropped_frames_no_route, DEC);
-IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
+IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
/* Mesh parameters */
IEEE80211_IF_FILE(dot11MeshMaxRetries,
@@ -531,6 +530,7 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+ DEBUGFS_ADD(hw_queues);
}
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
@@ -631,7 +631,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(flags);
DEBUGFS_ADD(state);
- DEBUGFS_ADD(channel_type);
+ DEBUGFS_ADD(txpower);
+ DEBUGFS_ADD(user_power_level);
+ DEBUGFS_ADD(ap_power_level);
if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
add_common_files(sdata);
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 5ccec2c1e9f6..6fb1168b9f16 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -14,6 +14,7 @@
#include "debugfs.h"
#include "debugfs_sta.h"
#include "sta_info.h"
+#include "driver-ops.h"
/* sta attributtes */
@@ -52,6 +53,7 @@ static const struct file_operations sta_ ##name## _ops = { \
STA_FILE(aid, sta.aid, D);
STA_FILE(dev, sdata->name, S);
STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_ack_signal, last_ack_signal, D);
static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
@@ -131,10 +133,10 @@ STA_OPS(connected_time);
static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+ char buf[15*IEEE80211_NUM_TIDS], *p = buf;
int i;
struct sta_info *sta = file->private_data;
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
le16_to_cpu(sta->last_seq_ctrl[i]));
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
@@ -145,7 +147,7 @@ STA_OPS(last_seq_ctrl);
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- char buf[71 + STA_TID_NUM * 40], *p = buf;
+ char buf[71 + IEEE80211_NUM_TIDS * 40], *p = buf;
int i;
struct sta_info *sta = file->private_data;
struct tid_ampdu_rx *tid_rx;
@@ -158,7 +160,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
p += scnprintf(p, sizeof(buf) + buf - p,
"TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
- for (i = 0; i < STA_TID_NUM; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
@@ -218,9 +220,11 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
} else
return -EINVAL;
- tid = simple_strtoul(buf, NULL, 0);
+ ret = kstrtoul(buf, 0, &tid);
+ if (ret)
+ return ret;
- if (tid >= STA_TID_NUM)
+ if (tid >= IEEE80211_NUM_TIDS)
return -EINVAL;
if (tx) {
@@ -320,6 +324,38 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
}
STA_OPS(ht_capa);
+static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct sta_info *sta = file->private_data;
+ struct rate_info rinfo;
+ u16 rate;
+ sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
+ rate = cfg80211_calculate_bitrate(&rinfo);
+
+ return mac80211_format_buffer(userbuf, count, ppos,
+ "%d.%d MBit/s\n",
+ rate/10, rate%10);
+}
+STA_OPS(current_tx_rate);
+
+static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct sta_info *sta = file->private_data;
+ struct rate_info rinfo;
+ u16 rate;
+
+ sta_set_rate_info_rx(sta, &rinfo);
+
+ rate = cfg80211_calculate_bitrate(&rinfo);
+
+ return mac80211_format_buffer(userbuf, count, ppos,
+ "%d.%d MBit/s\n",
+ rate/10, rate%10);
+}
+STA_OPS(last_rx_rate);
+
#define DEBUGFS_ADD(name) \
debugfs_create_file(#name, 0400, \
sta->debugfs.dir, sta, &sta_ ##name## _ops);
@@ -334,6 +370,8 @@ STA_OPS(ht_capa);
void ieee80211_sta_debugfs_add(struct sta_info *sta)
{
+ struct ieee80211_local *local = sta->local;
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations;
u8 mac[3*ETH_ALEN];
@@ -366,6 +404,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(dev);
DEBUGFS_ADD(last_signal);
DEBUGFS_ADD(ht_capa);
+ DEBUGFS_ADD(last_ack_signal);
+ DEBUGFS_ADD(current_tx_rate);
+ DEBUGFS_ADD(last_rx_rate);
DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
@@ -379,10 +420,16 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed);
DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count);
DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count);
+
+ drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir);
}
void ieee80211_sta_debugfs_remove(struct sta_info *sta)
{
+ struct ieee80211_local *local = sta->local;
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+
+ drv_sta_remove_debugfs(local, sdata, &sta->sta, sta->debugfs.dir);
debugfs_remove_recursive(sta->debugfs.dir);
sta->debugfs.dir = NULL;
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index da9003b20004..698dc7e6f309 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -490,6 +490,38 @@ static inline void drv_sta_remove(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+#ifdef CONFIG_MAC80211_DEBUGFS
+static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct dentry *dir)
+{
+ might_sleep();
+
+ sdata = get_bss_sdata(sdata);
+ check_sdata_in_driver(sdata);
+
+ if (local->ops->sta_add_debugfs)
+ local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
+ sta, dir);
+}
+
+static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct dentry *dir)
+{
+ might_sleep();
+
+ sdata = get_bss_sdata(sdata);
+ check_sdata_in_driver(sdata);
+
+ if (local->ops->sta_remove_debugfs)
+ local->ops->sta_remove_debugfs(&local->hw, &sdata->vif,
+ sta, dir);
+}
+#endif
+
static inline __must_check
int drv_sta_state(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
@@ -602,7 +634,7 @@ static inline void drv_reset_tsf(struct ieee80211_local *local,
static inline int drv_tx_last_beacon(struct ieee80211_local *local)
{
- int ret = 0; /* default unsuported op for less congestion */
+ int ret = 0; /* default unsupported op for less congestion */
might_sleep();
@@ -704,17 +736,17 @@ static inline int drv_get_antenna(struct ieee80211_local *local,
}
static inline int drv_remain_on_channel(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *chan,
- enum nl80211_channel_type chantype,
unsigned int duration)
{
int ret;
might_sleep();
- trace_drv_remain_on_channel(local, chan, chantype, duration);
- ret = local->ops->remain_on_channel(&local->hw, chan, chantype,
- duration);
+ trace_drv_remain_on_channel(local, sdata, chan, duration);
+ ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
+ chan, duration);
trace_drv_return_int(local, ret);
return ret;
@@ -871,4 +903,104 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
trace_drv_return_void(local);
}
+
+static inline int drv_add_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx)
+{
+ int ret = -EOPNOTSUPP;
+
+ trace_drv_add_chanctx(local, ctx);
+ if (local->ops->add_chanctx)
+ ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
+static inline void drv_remove_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx)
+{
+ trace_drv_remove_chanctx(local, ctx);
+ if (local->ops->remove_chanctx)
+ local->ops->remove_chanctx(&local->hw, &ctx->conf);
+ trace_drv_return_void(local);
+}
+
+static inline void drv_change_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx,
+ u32 changed)
+{
+ trace_drv_change_chanctx(local, ctx, changed);
+ if (local->ops->change_chanctx)
+ local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
+ trace_drv_return_void(local);
+}
+
+static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx)
+{
+ int ret = 0;
+
+ check_sdata_in_driver(sdata);
+
+ trace_drv_assign_vif_chanctx(local, sdata, ctx);
+ if (local->ops->assign_vif_chanctx)
+ ret = local->ops->assign_vif_chanctx(&local->hw,
+ &sdata->vif,
+ &ctx->conf);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
+static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx)
+{
+ check_sdata_in_driver(sdata);
+
+ trace_drv_unassign_vif_chanctx(local, sdata, ctx);
+ if (local->ops->unassign_vif_chanctx)
+ local->ops->unassign_vif_chanctx(&local->hw,
+ &sdata->vif,
+ &ctx->conf);
+ trace_drv_return_void(local);
+}
+
+static inline int drv_start_ap(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ int ret = 0;
+
+ check_sdata_in_driver(sdata);
+
+ trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
+ if (local->ops->start_ap)
+ ret = local->ops->start_ap(&local->hw, &sdata->vif);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
+static inline void drv_stop_ap(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ check_sdata_in_driver(sdata);
+
+ trace_drv_stop_ap(local, sdata);
+ if (local->ops->stop_ap)
+ local->ops->stop_ap(&local->hw, &sdata->vif);
+ trace_drv_return_void(local);
+}
+
+static inline void drv_restart_complete(struct ieee80211_local *local)
+{
+ might_sleep();
+
+ trace_drv_restart_complete(local);
+ if (local->ops->restart_complete)
+ local->ops->restart_complete(&local->hw);
+ trace_drv_return_void(local);
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 4b4538d63925..a71d891794a4 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -185,7 +185,7 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
cancel_work_sync(&sta->ampdu_mlme.work);
- for (i = 0; i < STA_TID_NUM; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
__ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx);
__ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
WLAN_REASON_QSTA_LEAVE_QBSS, tx);
@@ -209,7 +209,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
return;
mutex_lock(&sta->ampdu_mlme.mtx);
- for (tid = 0; tid < STA_TID_NUM; tid++) {
+ for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
___ieee80211_stop_rx_ba_session(
sta, tid, WLAN_BACK_RECIPIENT,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index c21e33d1abd0..8881fc77fb13 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -26,7 +26,6 @@
#include "rate.h"
#define IEEE80211_SCAN_INTERVAL (2 * HZ)
-#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
@@ -39,7 +38,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, const int beacon_int,
struct ieee80211_channel *chan,
const u32 basic_rates,
- const u16 capability, u64 tsf)
+ const u16 capability, u64 tsf,
+ bool creator)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
@@ -51,7 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct cfg80211_bss *bss;
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
lockdep_assert_held(&ifibss->mtx);
@@ -72,25 +72,29 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
/* if merging, indicate to driver that we leave the old IBSS */
if (sdata->vif.bss_conf.ibss_joined) {
sdata->vif.bss_conf.ibss_joined = false;
+ sdata->vif.bss_conf.ibss_creator = false;
netif_carrier_off(sdata->dev);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
}
- memcpy(ifibss->bssid, bssid, ETH_ALEN);
-
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
- local->oper_channel = chan;
- channel_type = ifibss->channel_type;
- if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
- channel_type = NL80211_CHAN_HT20;
- if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
- /* can only fail due to HT40+/- mismatch */
- channel_type = NL80211_CHAN_HT20;
- WARN_ON(!ieee80211_set_channel_type(local, sdata,
- NL80211_CHAN_HT20));
+ cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+ chandef.width = NL80211_CHAN_WIDTH_20;
+ chandef.center_freq1 = chan->center_freq;
+ }
+
+ ieee80211_vif_release_channel(sdata);
+ if (ieee80211_vif_use_channel(sdata, &chandef,
+ ifibss->fixed_channel ?
+ IEEE80211_CHANCTX_SHARED :
+ IEEE80211_CHANCTX_EXCLUSIVE)) {
+ sdata_info(sdata, "Failed to join IBSS, no channel context\n");
+ return;
}
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ memcpy(ifibss->bssid, bssid, ETH_ALEN);
sband = local->hw.wiphy->bands[chan->band];
@@ -156,7 +160,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
ifibss->ie, ifibss->ie_len);
/* add HT capability and information IEs */
- if (channel_type && sband->ht_cap.ht_supported) {
+ if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
+ sband->ht_cap.ht_supported) {
pos = skb_put(skb, 4 +
sizeof(struct ieee80211_ht_cap) +
sizeof(struct ieee80211_ht_operation));
@@ -168,7 +173,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
* keep them at 0
*/
pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
- chan, channel_type, 0);
+ &chandef, 0);
}
if (local->hw.queues >= IEEE80211_NUM_ACS) {
@@ -196,7 +201,22 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change |= BSS_CHANGED_BASIC_RATES;
bss_change |= BSS_CHANGED_HT;
bss_change |= BSS_CHANGED_IBSS;
+
+ /*
+ * In 5 GHz/802.11a, we can always use short slot time.
+ * (IEEE 802.11-2012 18.3.8.7)
+ *
+ * In 2.4GHz, we must always use long slots in IBSS for compatibility
+ * reasons.
+ * (IEEE 802.11-2012 19.4.5)
+ *
+ * HT follows these specifications (IEEE 802.11-2012 20.3.18)
+ */
+ sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ;
+ bss_change |= BSS_CHANGED_ERP_SLOT;
+
sdata->vif.bss_conf.ibss_joined = true;
+ sdata->vif.bss_conf.ibss_creator = creator;
ieee80211_bss_info_change_notify(sdata, bss_change);
ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
@@ -249,7 +269,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
cbss->channel,
basic_rates,
cbss->capability,
- cbss->tsf);
+ cbss->tsf,
+ false);
}
static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
@@ -279,7 +300,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
ibss_dbg(sdata,
"TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
sdata->vif.addr, addr, sdata->u.ibss.bssid);
- ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0,
+ ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0,
addr, sdata->u.ibss.bssid, NULL, 0, 0);
}
return sta;
@@ -294,7 +315,8 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
- int band = local->oper_channel->band;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int band;
/*
* XXX: Consider removing the least recently used entry and
@@ -317,6 +339,13 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
return NULL;
}
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON_ONCE(!chanctx_conf))
+ return NULL;
+ band = chanctx_conf->def.chan->band;
+ rcu_read_unlock();
+
sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
if (!sta) {
rcu_read_lock();
@@ -362,11 +391,13 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
- if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
- return;
ibss_dbg(sdata,
"RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction);
+
+ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
+ return;
+
sta_info_destroy_addr(sdata, mgmt->sa);
sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false);
rcu_read_unlock();
@@ -389,7 +420,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
* However, try to reply to authentication attempts if someone
* has actually implemented this.
*/
- ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
+ ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, 0, NULL, 0,
mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0);
}
@@ -461,9 +492,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
/* we both use HT */
struct ieee80211_sta_ht_cap sta_ht_cap_new;
- enum nl80211_channel_type channel_type =
- ieee80211_ht_oper_to_channel_type(
- elems->ht_operation);
+ struct cfg80211_chan_def chandef;
+
+ ieee80211_ht_oper_to_chandef(channel,
+ elems->ht_operation,
+ &chandef);
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems->ht_cap_elem,
@@ -473,9 +506,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
* fall back to HT20 if we don't use or use
* the other extension channel
*/
- if (!(channel_type == NL80211_CHAN_HT40MINUS ||
- channel_type == NL80211_CHAN_HT40PLUS) ||
- channel_type != sdata->u.ibss.channel_type)
+ if (chandef.width != NL80211_CHAN_WIDTH_40 ||
+ cfg80211_get_chandef_type(&chandef) !=
+ sdata->u.ibss.channel_type)
sta_ht_cap_new.cap &=
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
@@ -517,7 +550,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
goto put_bss;
/* different channel */
- if (cbss->channel != local->oper_channel)
+ if (sdata->u.ibss.fixed_channel &&
+ sdata->u.ibss.channel != cbss->channel)
goto put_bss;
/* different SSID */
@@ -530,30 +564,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid))
goto put_bss;
- if (rx_status->flag & RX_FLAG_MACTIME_MPDU) {
- /*
- * For correct IBSS merging we need mactime; since mactime is
- * defined as the time the first data symbol of the frame hits
- * the PHY, and the timestamp of the beacon is defined as "the
- * time that the data symbol containing the first bit of the
- * timestamp is transmitted to the PHY plus the transmitting
- * STA's delays through its local PHY from the MAC-PHY
- * interface to its interface with the WM" (802.11 11.1.2)
- * - equals the time this bit arrives at the receiver - we have
- * to take into account the offset between the two.
- *
- * E.g. at 1 MBit that means mactime is 192 usec earlier
- * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
- */
- int rate;
-
- if (rx_status->flag & RX_FLAG_HT)
- rate = 65; /* TODO: HT rates */
- else
- rate = local->hw.wiphy->bands[band]->
- bitrates[rx_status->rate_idx].bitrate;
-
- rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
+ if (ieee80211_have_rx_timestamp(rx_status)) {
+ /* time when timestamp field was received */
+ rx_timestamp =
+ ieee80211_calculate_rx_timestamp(local, rx_status,
+ len + FCS_LEN, 24);
} else {
/*
* second best option: get current TSF
@@ -592,7 +607,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
- int band = local->oper_channel->band;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int band;
/*
* XXX: Consider removing the least recently used entry and
@@ -610,6 +626,15 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
if (!ether_addr_equal(bssid, sdata->u.ibss.bssid))
return;
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON_ONCE(!chanctx_conf)) {
+ rcu_read_unlock();
+ return;
+ }
+ band = chanctx_conf->def.chan->band;
+ rcu_read_unlock();
+
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
if (!sta)
return;
@@ -715,7 +740,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
ifibss->channel, ifibss->basic_rates,
- capability, 0);
+ capability, 0, true);
}
/*
@@ -784,18 +809,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
int interval = IEEE80211_SCAN_INTERVAL;
if (time_after(jiffies, ifibss->ibss_join_req +
- IEEE80211_IBSS_JOIN_TIMEOUT)) {
- if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) {
- ieee80211_sta_create_ibss(sdata);
- return;
- }
- sdata_info(sdata, "IBSS not allowed on %d MHz\n",
- local->oper_channel->center_freq);
-
- /* No IBSS found - decrease scan interval and continue
- * scanning. */
- interval = IEEE80211_SCAN_INTERVAL_SLOW;
- }
+ IEEE80211_IBSS_JOIN_TIMEOUT))
+ ieee80211_sta_create_ibss(sdata);
mod_timer(&ifibss->timer,
round_jiffies(jiffies + interval));
@@ -1082,21 +1097,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
- sdata->u.ibss.channel = params->channel;
- sdata->u.ibss.channel_type = params->channel_type;
+ sdata->u.ibss.channel = params->chandef.chan;
+ sdata->u.ibss.channel_type =
+ cfg80211_get_chandef_type(&params->chandef);
sdata->u.ibss.fixed_channel = params->channel_fixed;
- /* fix ourselves to that channel now already */
- if (params->channel_fixed) {
- sdata->local->oper_channel = params->channel;
- if (!ieee80211_set_channel_type(sdata->local, sdata,
- params->channel_type)) {
- mutex_unlock(&sdata->u.ibss.mtx);
- kfree_skb(skb);
- return -EINVAL;
- }
- }
-
if (params->ie) {
sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
GFP_KERNEL);
@@ -1134,6 +1139,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_HT;
ieee80211_bss_info_change_notify(sdata, changed);
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
+ sdata->needed_rx_chains = sdata->local->rx_chains;
+
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
return 0;
@@ -1197,6 +1205,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
lockdep_is_held(&sdata->u.ibss.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
+ sdata->vif.bss_conf.ibss_creator = false;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_IBSS);
synchronize_rcu();
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 156e5835e37f..42d0d0267730 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -56,6 +56,9 @@ struct ieee80211_local;
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
+/* power level hasn't been configured (or set to automatic) */
+#define IEEE80211_UNSET_POWER_LEVEL INT_MIN
+
/*
* Some APs experience problems when working with U-APSD. Decrease the
* probability of that happening by using legacy mode for all ACs but VO.
@@ -280,23 +283,27 @@ struct probe_resp {
u8 data[0];
};
-struct ieee80211_if_ap {
- struct beacon_data __rcu *beacon;
- struct probe_resp __rcu *probe_resp;
-
- struct list_head vlans;
-
+struct ps_data {
/* yes, this looks ugly, but guarantees that we can later use
* bitmap_empty :)
* NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
- struct sk_buff_head ps_bc_buf;
+ struct sk_buff_head bc_buf;
atomic_t num_sta_ps; /* number of stations in PS mode */
- atomic_t num_mcast_sta; /* number of stations receiving multicast */
int dtim_count;
bool dtim_bc_mc;
};
+struct ieee80211_if_ap {
+ struct beacon_data __rcu *beacon;
+ struct probe_resp __rcu *probe_resp;
+
+ struct list_head vlans;
+
+ struct ps_data ps;
+ atomic_t num_mcast_sta; /* number of stations receiving multicast */
+};
+
struct ieee80211_if_wds {
struct sta_info *sta;
u8 remote_addr[ETH_ALEN];
@@ -316,7 +323,6 @@ struct mesh_stats {
__u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
__u32 dropped_frames_no_route; /* Not transmitted, no route found */
__u32 dropped_frames_congestion;/* Not forwarded due to congestion */
- atomic_t estab_plinks;
};
#define PREQ_Q_F_START 0x1
@@ -342,7 +348,6 @@ struct ieee80211_roc_work {
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *chan;
- enum nl80211_channel_type chan_type;
bool started, abort, hw_begun, notified;
@@ -350,7 +355,7 @@ struct ieee80211_roc_work {
u32 duration, req_duration;
struct sk_buff *frame;
- u64 mgmt_tx_cookie;
+ u64 cookie, mgmt_tx_cookie;
};
/* flags used in struct ieee80211_if_managed.flags */
@@ -358,7 +363,7 @@ enum ieee80211_sta_flags {
IEEE80211_STA_BEACON_POLL = BIT(0),
IEEE80211_STA_CONNECTION_POLL = BIT(1),
IEEE80211_STA_CONTROL_PORT = BIT(2),
- IEEE80211_STA_DISABLE_11N = BIT(4),
+ IEEE80211_STA_DISABLE_HT = BIT(4),
IEEE80211_STA_CSA_RECEIVED = BIT(5),
IEEE80211_STA_MFP_ENABLED = BIT(6),
IEEE80211_STA_UAPSD_ENABLED = BIT(7),
@@ -366,6 +371,8 @@ enum ieee80211_sta_flags {
IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9),
IEEE80211_STA_DISABLE_40MHZ = BIT(10),
IEEE80211_STA_DISABLE_VHT = BIT(11),
+ IEEE80211_STA_DISABLE_80P80MHZ = BIT(12),
+ IEEE80211_STA_DISABLE_160MHZ = BIT(13),
};
struct ieee80211_mgd_auth_data {
@@ -378,8 +385,9 @@ struct ieee80211_mgd_auth_data {
u8 key_len, key_idx;
bool done;
- size_t ie_len;
- u8 ie[];
+ u16 sae_trans, sae_status;
+ size_t data_len;
+ u8 data[];
};
struct ieee80211_mgd_assoc_data {
@@ -433,7 +441,6 @@ struct ieee80211_if_managed {
bool powersave; /* powersave requested for this iface */
bool broken_ap; /* AP is broken -- turn off powersave */
enum ieee80211_smps_mode req_smps, /* requested smps mode */
- ap_smps, /* smps mode AP thinks we're in */
driver_smps_mode; /* smps mode request */
struct work_struct request_smps_work;
@@ -467,6 +474,8 @@ struct ieee80211_if_managed {
u8 use_4addr;
+ u8 p2p_noa_index;
+
/* Signal strength from the last Beacon frame in the current BSS. */
int last_beacon_signal;
@@ -599,6 +608,7 @@ struct ieee80211_if_mesh {
int preq_queue_len;
struct mesh_stats mshstats;
struct mesh_config mshcfg;
+ atomic_t estab_plinks;
u32 mesh_seqnum;
bool accepting_plinks;
int num_gates;
@@ -610,7 +620,7 @@ struct ieee80211_if_mesh {
IEEE80211_MESH_SEC_SECURED = 0x2,
} security;
/* Extensible Synchronization Framework */
- struct ieee80211_mesh_sync_ops *sync_ops;
+ const struct ieee80211_mesh_sync_ops *sync_ops;
s64 sync_offset_clockdrift_max;
spinlock_t sync_offset_lock;
bool adjusting_tbtt;
@@ -658,6 +668,30 @@ enum ieee80211_sdata_state_bits {
SDATA_STATE_OFFCHANNEL,
};
+/**
+ * enum ieee80211_chanctx_mode - channel context configuration mode
+ *
+ * @IEEE80211_CHANCTX_SHARED: channel context may be used by
+ * multiple interfaces
+ * @IEEE80211_CHANCTX_EXCLUSIVE: channel context can be used
+ * only by a single interface. This can be used for example for
+ * non-fixed channel IBSS.
+ */
+enum ieee80211_chanctx_mode {
+ IEEE80211_CHANCTX_SHARED,
+ IEEE80211_CHANCTX_EXCLUSIVE
+};
+
+struct ieee80211_chanctx {
+ struct list_head list;
+ struct rcu_head rcu_head;
+
+ enum ieee80211_chanctx_mode mode;
+ int refcount;
+
+ struct ieee80211_chanctx_conf conf;
+};
+
struct ieee80211_sub_if_data {
struct list_head list;
@@ -704,11 +738,20 @@ struct ieee80211_sub_if_data {
struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
+ /* used to reconfigure hardware SM PS */
+ struct work_struct recalc_smps;
+
struct work_struct work;
struct sk_buff_head skb_queue;
bool arp_filter_state;
+ u8 needed_rx_chains;
+ enum ieee80211_smps_mode smps_mode;
+
+ int user_power_level; /* in dBm */
+ int ap_power_level; /* in dBm */
+
/*
* AP this belongs to: self in AP mode and
* corresponding AP in VLAN mode, NULL for
@@ -749,6 +792,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
return container_of(p, struct ieee80211_sub_if_data, vif);
}
+static inline enum ieee80211_band
+ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
+{
+ enum ieee80211_band band = IEEE80211_BAND_2GHZ;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!WARN_ON(!chanctx_conf))
+ band = chanctx_conf->def.chan->band;
+ rcu_read_unlock();
+
+ return band;
+}
+
enum sdata_queue_type {
IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
IEEE80211_SDATA_QUEUE_AGG_START = 1,
@@ -821,6 +879,7 @@ enum {
* @SCAN_SUSPEND: Suspend the scan and go back to operating channel to
* send out data
* @SCAN_RESUME: Resume the scan and scan the next channel
+ * @SCAN_ABORT: Abort the scan and go back to operating channel
*/
enum mac80211_scan_state {
SCAN_DECISION,
@@ -828,6 +887,7 @@ enum mac80211_scan_state {
SCAN_SEND_PROBE,
SCAN_SUSPEND,
SCAN_RESUME,
+ SCAN_ABORT,
};
struct ieee80211_local {
@@ -858,15 +918,14 @@ struct ieee80211_local {
bool wiphy_ciphers_allocated;
+ bool use_chanctx;
+
/* protects the aggregated multicast list and filter calls */
spinlock_t filter_lock;
/* used for uploading changed mc list */
struct work_struct reconfig_filter;
- /* used to reconfigure hardware SM PS */
- struct work_struct recalc_smps;
-
/* aggregated multicast list */
struct netdev_hw_addr_list mc_list;
@@ -903,6 +962,9 @@ struct ieee80211_local {
/* wowlan is enabled -- don't reconfig on resume */
bool wowlan;
+ /* number of RX chains the hardware has */
+ u8 rx_chains;
+
int tx_headroom; /* required headroom for hardware/radiotap */
/* Tasklet and skb queue to process calls from IRQ mode. All frames
@@ -972,6 +1034,7 @@ struct ieee80211_local {
enum ieee80211_band hw_scan_band;
int scan_channel_idx;
int scan_ies_len;
+ int hw_scan_ies_bufsize;
struct work_struct sched_scan_stopped_work;
struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
@@ -980,12 +1043,17 @@ struct ieee80211_local {
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data __rcu *scan_sdata;
+ struct ieee80211_channel *csa_channel;
+ /* For backward compatibility only -- do not use */
+ struct ieee80211_channel *_oper_channel;
enum nl80211_channel_type _oper_channel_type;
- struct ieee80211_channel *oper_channel, *csa_channel;
/* Temporary remain-on-channel for off-channel operations */
struct ieee80211_channel *tmp_channel;
- enum nl80211_channel_type tmp_channel_type;
+
+ /* channel contexts */
+ struct list_head chanctx_list;
+ struct mutex chanctx_mtx;
/* SNMP counters */
/* dot11CountersTable */
@@ -1058,8 +1126,7 @@ struct ieee80211_local {
int dynamic_ps_user_timeout;
bool disable_dynamic_ps;
- int user_power_level; /* in dBm */
- int ap_power_level; /* in dBm */
+ int user_power_level; /* in dBm, for all interfaces */
enum ieee80211_smps_mode smps_mode;
@@ -1078,6 +1145,7 @@ struct ieee80211_local {
struct list_head roc_list;
struct work_struct hw_roc_start, hw_roc_done;
unsigned long hw_roc_start_time;
+ u64 roc_cookie_counter;
struct idr ack_status_frames;
spinlock_t ack_status_lock;
@@ -1091,6 +1159,7 @@ struct ieee80211_local {
/* virtual monitor interface */
struct ieee80211_sub_if_data __rcu *monitor_sdata;
+ struct cfg80211_chan_def monitor_chandef;
};
static inline struct ieee80211_sub_if_data *
@@ -1133,6 +1202,8 @@ struct ieee802_11_elems {
u8 *wmm_param;
struct ieee80211_ht_cap *ht_cap_elem;
struct ieee80211_ht_operation *ht_operation;
+ struct ieee80211_vht_cap *vht_cap_elem;
+ struct ieee80211_vht_operation *vht_operation;
struct ieee80211_meshconf_ie *mesh_config;
u8 *mesh_id;
u8 *peering;
@@ -1188,7 +1259,18 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
is_broadcast_ether_addr(raddr);
}
+static inline bool
+ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
+{
+ WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START &&
+ status->flag & RX_FLAG_MACTIME_END);
+ return status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END);
+}
+u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status,
+ unsigned int mpdu_len,
+ unsigned int mpdu_offset);
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
@@ -1302,6 +1384,9 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up);
void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
+bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
+
static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
{
return test_bit(SDATA_STATE_RUNNING, &sdata->state);
@@ -1361,6 +1446,13 @@ void ieee80211_ba_session_work(struct work_struct *work);
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
+u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs);
+
+/* VHT */
+void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_vht_cap *vht_cap_ie,
+ struct ieee80211_sta_vht_cap *vht_cap);
/* Spectrum management */
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
@@ -1395,11 +1487,42 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
gfp_t gfp);
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify);
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+ enum ieee80211_band band);
+
+void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int tid,
+ enum ieee80211_band band);
-void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, int tid);
-static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
+static inline void
+ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int tid,
+ enum ieee80211_band band)
+{
+ rcu_read_lock();
+ __ieee80211_tx_skb_tid_band(sdata, skb, tid, band);
+ rcu_read_unlock();
+}
+
+static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int tid)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return;
+ }
+
+ __ieee80211_tx_skb_tid_band(sdata, skb, tid,
+ chanctx_conf->def.chan->band);
+ rcu_read_unlock();
+}
+
+static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
/* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
@@ -1446,14 +1569,14 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
}
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
- u16 transaction, u16 auth_alg,
+ u16 transaction, u16 auth_alg, u16 status,
u8 *extra, size_t extra_len, const u8 *bssid,
const u8 *da, const u8 *key, u8 key_len, u8 key_idx);
void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, u16 stype, u16 reason,
bool send_frame, u8 *frame_buf);
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
- const u8 *ie, size_t ie_len,
+ size_t buffer_len, const u8 *ie, size_t ie_len,
enum ieee80211_band band, u32 rate_mask,
u8 channel);
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -1466,7 +1589,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
u32 ratemask, bool directed, bool no_cck,
- struct ieee80211_channel *channel);
+ struct ieee80211_channel *channel, bool scan);
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
const size_t supp_rates_len,
@@ -1476,7 +1599,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
enum ieee80211_band band, u32 *basic_rates);
int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps_mode);
-void ieee80211_recalc_smps(struct ieee80211_local *local);
+void ieee80211_recalc_smps(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);
@@ -1484,8 +1607,7 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u16 cap);
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
- struct ieee80211_channel *channel,
- enum nl80211_channel_type channel_type,
+ const struct cfg80211_chan_def *chandef,
u16 prot_mode);
u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
u32 cap);
@@ -1497,20 +1619,18 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
enum ieee80211_band band);
/* channel management */
-enum ieee80211_chan_mode {
- CHAN_MODE_UNDEFINED,
- CHAN_MODE_HOPPING,
- CHAN_MODE_FIXED,
-};
-
-enum ieee80211_chan_mode
-ieee80211_get_channel_mode(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *ignore);
-bool ieee80211_set_channel_type(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum nl80211_channel_type chantype);
-enum nl80211_channel_type
-ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper);
+void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
+ struct ieee80211_ht_operation *ht_oper,
+ struct cfg80211_chan_def *chandef);
+
+int __must_check
+ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_chan_def *chandef,
+ enum ieee80211_chanctx_mode mode);
+void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
+
+void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
+ struct ieee80211_chanctx *chanctx);
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7de7717ad67d..09a80b55cf5a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -42,6 +42,41 @@
* by either the RTNL, the iflist_mtx or RCU.
*/
+bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int power;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf) {
+ rcu_read_unlock();
+ return false;
+ }
+
+ power = chanctx_conf->def.chan->max_power;
+ rcu_read_unlock();
+
+ if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
+ power = min(power, sdata->user_power_level);
+
+ if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
+ power = min(power, sdata->ap_power_level);
+
+ if (power != sdata->vif.bss_conf.txpower) {
+ sdata->vif.bss_conf.txpower = power;
+ ieee80211_hw_config(sdata->local, 0);
+ return true;
+ }
+
+ return false;
+}
+
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+{
+ if (__ieee80211_recalc_txpower(sdata))
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
+}
static u32 ieee80211_idle_off(struct ieee80211_local *local,
const char *reason)
@@ -188,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
+{
+ struct ieee80211_sub_if_data *sdata;
+ u64 new, mask, tmp;
+ u8 *m;
+ int ret = 0;
+
+ if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
+ return 0;
+
+ m = addr;
+ new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
+ ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
+ ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
+
+ m = local->hw.wiphy->addr_mask;
+ mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
+ ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
+ ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
+
+
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+
+ m = sdata->vif.addr;
+ tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
+ ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
+ ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
+
+ if ((new & ~mask) != (tmp & ~mask)) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ return ret;
+}
+
static int ieee80211_change_mac(struct net_device *dev, void *addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -197,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
if (ieee80211_sdata_running(sdata))
return -EBUSY;
+ ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
+ if (ret)
+ return ret;
+
ret = eth_mac_addr(dev, sa);
if (ret == 0)
@@ -380,6 +460,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
goto out_unlock;
}
+ ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
+ IEEE80211_CHANCTX_EXCLUSIVE);
+ if (ret) {
+ drv_remove_interface(local, sdata);
+ kfree(sdata);
+ goto out_unlock;
+ }
+
rcu_assign_pointer(local->monitor_sdata, sdata);
out_unlock:
mutex_unlock(&local->iflist_mtx);
@@ -403,6 +491,8 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
rcu_assign_pointer(local->monitor_sdata, NULL);
synchronize_net();
+ ieee80211_vif_release_channel(sdata);
+
drv_remove_interface(local, sdata);
kfree(sdata);
@@ -665,7 +755,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, *tmp;
u32 hw_reconf_flags = 0;
int i;
- enum nl80211_channel_type orig_ct;
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
@@ -729,34 +818,17 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work);
+ cancel_work_sync(&sdata->recalc_smps);
+
/* APs need special treatment */
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan, *tmpsdata;
- struct beacon_data *old_beacon =
- rtnl_dereference(sdata->u.ap.beacon);
- struct probe_resp *old_probe_resp =
- rtnl_dereference(sdata->u.ap.probe_resp);
-
- /* sdata_running will return false, so this will disable */
- ieee80211_bss_info_change_notify(sdata,
- BSS_CHANGED_BEACON_ENABLED);
-
- /* remove beacon and probe response */
- RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
- RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
- synchronize_rcu();
- kfree(old_beacon);
- kfree(old_probe_resp);
/* down all dependent devices, that is VLANs */
list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
u.vlan.list)
dev_close(vlan->dev);
WARN_ON(!list_empty(&sdata->u.ap.vlans));
-
- /* free all potentially still buffered bcast frames */
- local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
- skb_queue_purge(&sdata->u.ap.ps_bc_buf);
} else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
ieee80211_mgd_stop(sdata);
}
@@ -790,7 +862,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
rcu_assign_pointer(local->p2p_sdata, NULL);
/* fall through */
default:
- flush_work(&sdata->work);
+ cancel_work_sync(&sdata->work);
/*
* When we get here, the interface is marked down.
* Call rcu_barrier() to wait both for the RX path
@@ -837,14 +909,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
hw_reconf_flags = 0;
}
- /* Re-calculate channel-type, in case there are multiple vifs
- * on different channel types.
- */
- orig_ct = local->_oper_channel_type;
- ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT);
-
/* do after stop to avoid reconfiguring when we stop anyway */
- if (hw_reconf_flags || (orig_ct != local->_oper_channel_type))
+ if (hw_reconf_flags)
ieee80211_hw_config(local, hw_reconf_flags);
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
@@ -1121,6 +1187,13 @@ static void ieee80211_iface_work(struct work_struct *work)
}
}
+static void ieee80211_recalc_smps_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data, recalc_smps);
+
+ ieee80211_recalc_smps(sdata);
+}
/*
* Helper function to initialise an interface to a specific type.
@@ -1149,6 +1222,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
skb_queue_head_init(&sdata->skb_queue);
INIT_WORK(&sdata->work, ieee80211_iface_work);
+ INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
switch (type) {
case NL80211_IFTYPE_P2P_GO:
@@ -1157,7 +1231,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->vif.p2p = true;
/* fall through */
case NL80211_IFTYPE_AP:
- skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+ skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
INIT_LIST_HEAD(&sdata->u.ap.vlans);
break;
case NL80211_IFTYPE_P2P_CLIENT:
@@ -1282,11 +1356,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
if (type == ieee80211_vif_type_p2p(&sdata->vif))
return 0;
- /* Setting ad-hoc mode on non-IBSS channel is not supported. */
- if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS &&
- type == NL80211_IFTYPE_ADHOC)
- return -EOPNOTSUPP;
-
if (ieee80211_sdata_running(sdata)) {
ret = ieee80211_runtime_change_iftype(sdata, type);
if (ret)
@@ -1298,9 +1367,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
}
/* reset some values that shouldn't be kept across type changes */
- sdata->vif.bss_conf.basic_rates =
- ieee80211_mandatory_rates(sdata->local,
- sdata->local->oper_channel->band);
sdata->drop_unencrypted = 0;
if (type == NL80211_IFTYPE_STATION)
sdata->u.mgd.use_4addr = false;
@@ -1523,6 +1589,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
ieee80211_set_default_queues(sdata);
+ sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
+ sdata->user_power_level = local->user_power_level;
+
/* setup type-dependent data */
ieee80211_setup_sdata(sdata, type);
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index d27e61aaa71b..619c5d697999 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -339,7 +339,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
key->conf.iv_len = TKIP_IV_LEN;
key->conf.icv_len = TKIP_ICV_LEN;
if (seq) {
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
key->u.tkip.rx[i].iv32 =
get_unaligned_le32(&seq[2]);
key->u.tkip.rx[i].iv16 =
@@ -352,7 +352,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
key->conf.iv_len = CCMP_HDR_LEN;
key->conf.icv_len = CCMP_MIC_LEN;
if (seq) {
- for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++)
+ for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
for (j = 0; j < CCMP_PN_LEN; j++)
key->u.ccmp.rx_pn[i][j] =
seq[CCMP_PN_LEN - j - 1];
@@ -372,8 +372,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
key->conf.iv_len = 0;
key->conf.icv_len = sizeof(struct ieee80211_mmie);
if (seq)
- for (j = 0; j < 6; j++)
- key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
+ for (j = 0; j < CMAC_PN_LEN; j++)
+ key->u.aes_cmac.rx_pn[j] =
+ seq[CMAC_PN_LEN - j - 1];
/*
* Initialize AES key state here as an optimization so that
* it does not need to be initialized for every packet.
@@ -654,16 +655,16 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
switch (key->conf.cipher) {
case WLAN_CIPHER_SUITE_TKIP:
- if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES))
+ if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS))
return;
seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
break;
case WLAN_CIPHER_SUITE_CCMP:
- if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES))
+ if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
return;
if (tid < 0)
- pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES];
+ pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
else
pn = key->u.ccmp.rx_pn[tid];
memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 7d4e31f037d7..382dc44ed330 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -30,8 +30,6 @@
#define TKIP_ICV_LEN 4
#define CMAC_PN_LEN 6
-#define NUM_RX_DATA_QUEUES 16
-
struct ieee80211_local;
struct ieee80211_sub_if_data;
struct sta_info;
@@ -82,17 +80,20 @@ struct ieee80211_key {
struct tkip_ctx tx;
/* last received RSC */
- struct tkip_ctx rx[NUM_RX_DATA_QUEUES];
+ struct tkip_ctx rx[IEEE80211_NUM_TIDS];
+
+ /* number of mic failures */
+ u32 mic_failures;
} tkip;
struct {
atomic64_t tx_pn;
/*
* Last received packet number. The first
- * NUM_RX_DATA_QUEUES counters are used with Data
+ * IEEE80211_NUM_TIDS counters are used with Data
* frames and the last counter is used with Robust
* Management frames.
*/
- u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN];
+ u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN];
struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCCMPReplays */
} ccmp;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f57f597972f8..1b087fff93e7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -93,15 +93,15 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
ieee80211_configure_filter(local);
}
-int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
{
+ struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *chan;
- int ret = 0;
+ u32 changed = 0;
int power;
enum nl80211_channel_type channel_type;
u32 offchannel_flag;
-
- might_sleep();
+ bool scanning = false;
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
if (local->scan_channel) {
@@ -109,19 +109,19 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
/* If scanning on oper channel, use whatever channel-type
* is currently in use.
*/
- if (chan == local->oper_channel)
+ if (chan == local->_oper_channel)
channel_type = local->_oper_channel_type;
else
channel_type = NL80211_CHAN_NO_HT;
} else if (local->tmp_channel) {
chan = local->tmp_channel;
- channel_type = local->tmp_channel_type;
+ channel_type = NL80211_CHAN_NO_HT;
} else {
- chan = local->oper_channel;
+ chan = local->_oper_channel;
channel_type = local->_oper_channel_type;
}
- if (chan != local->oper_channel ||
+ if (chan != local->_oper_channel ||
channel_type != local->_oper_channel_type)
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
else
@@ -148,22 +148,39 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
changed |= IEEE80211_CONF_CHANGE_SMPS;
}
- if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
- test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- !local->ap_power_level)
- power = chan->max_power;
- else
- power = min(chan->max_power, local->ap_power_level);
+ scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
+ test_bit(SCAN_HW_SCANNING, &local->scanning);
+ power = chan->max_power;
- if (local->user_power_level >= 0)
- power = min(power, local->user_power_level);
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (!rcu_access_pointer(sdata->vif.chanctx_conf))
+ continue;
+ power = min(power, sdata->vif.bss_conf.txpower);
+ }
+ rcu_read_unlock();
if (local->hw.conf.power_level != power) {
changed |= IEEE80211_CONF_CHANGE_POWER;
local->hw.conf.power_level = power;
}
+ return changed;
+}
+
+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+{
+ int ret = 0;
+
+ might_sleep();
+
+ if (!local->use_chanctx)
+ changed |= ieee80211_hw_conf_chan(local);
+ else
+ changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
+ IEEE80211_CONF_CHANGE_POWER);
+
if (changed && local->open_count) {
ret = drv_config(local, changed);
/*
@@ -359,14 +376,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_restart_hw);
-static void ieee80211_recalc_smps_work(struct work_struct *work)
-{
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, recalc_smps);
-
- ieee80211_recalc_smps(local);
-}
-
#ifdef CONFIG_INET
static int ieee80211_ifa_changed(struct notifier_block *nb,
unsigned long data, void *arg)
@@ -465,7 +474,8 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_AUTH >> 4) |
- BIT(IEEE80211_STYPE_DEAUTH >> 4),
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
},
[NL80211_IFTYPE_STATION] = {
.tx = 0xffff,
@@ -540,6 +550,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
struct ieee80211_local *local;
int priv_size, i;
struct wiphy *wiphy;
+ bool use_chanctx;
if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
!ops->add_interface || !ops->remove_interface ||
@@ -549,6 +560,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
return NULL;
+ /* check all or no channel context operations exist */
+ i = !!ops->add_chanctx + !!ops->remove_chanctx +
+ !!ops->change_chanctx + !!ops->assign_vif_chanctx +
+ !!ops->unassign_vif_chanctx;
+ if (WARN_ON(i != 0 && i != 5))
+ return NULL;
+ use_chanctx = i == 5;
+
/* Ensure 32-byte alignment of our private data and hw private data.
* We use the wiphy priv data for both our ieee80211_local and for
* the driver's private data
@@ -584,8 +603,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
if (ops->remain_on_channel)
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
- NL80211_FEATURE_HT_IBSS;
+ wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
+ NL80211_FEATURE_SAE |
+ NL80211_FEATURE_HT_IBSS |
+ NL80211_FEATURE_VIF_TXPOWER;
+
+ if (!ops->hw_scan)
+ wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
+ NL80211_FEATURE_AP_SCAN;
+
if (!ops->set_key)
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -599,6 +625,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
local->ops = ops;
+ local->use_chanctx = use_chanctx;
/* set up some defaults */
local->hw.queues = 1;
@@ -612,7 +639,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI |
IEEE80211_RADIOTAP_MCS_HAVE_BW;
- local->user_power_level = -1;
+ local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
INIT_LIST_HEAD(&local->interfaces);
@@ -626,6 +655,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
spin_lock_init(&local->filter_lock);
spin_lock_init(&local->queue_stop_reason_lock);
+ INIT_LIST_HEAD(&local->chanctx_list);
+ mutex_init(&local->chanctx_mtx);
+
/*
* The rx_skb_queue is only accessed from tasklets,
* but other SKB queues are used from within IRQ
@@ -641,7 +673,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
INIT_WORK(&local->restart_work, ieee80211_restart_work);
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
- INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
local->smps_mode = IEEE80211_SMPS_OFF;
INIT_WORK(&local->dynamic_ps_enable_work,
@@ -719,6 +750,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
return -EINVAL;
+ if (!local->use_chanctx) {
+ for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
+ const struct ieee80211_iface_combination *comb;
+
+ comb = &local->hw.wiphy->iface_combinations[i];
+
+ if (comb->num_different_channels > 1)
+ return -EINVAL;
+ }
+ } else {
+ /*
+ * WDS is currently prohibited when channel contexts are used
+ * because there's no clear definition of which channel WDS
+ * type interfaces use
+ */
+ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
+ return -EINVAL;
+ }
+
/* Only HW csum features are currently compatible with mac80211 */
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_HW_CSUM;
@@ -728,6 +778,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (hw->max_report_rates == 0)
hw->max_report_rates = hw->max_rates;
+ local->rx_chains = 1;
+
/*
* generic code guarantees at least one band,
* set this very early because much code assumes
@@ -743,18 +795,28 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sband = local->hw.wiphy->bands[band];
if (!sband)
continue;
- if (!local->oper_channel) {
+ if (!local->use_chanctx && !local->_oper_channel) {
/* init channel we're on */
local->hw.conf.channel =
- local->oper_channel = &sband->channels[0];
+ local->_oper_channel = &sband->channels[0];
local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
}
+ cfg80211_chandef_create(&local->monitor_chandef,
+ &sband->channels[0],
+ NL80211_CHAN_NO_HT);
channels += sband->n_channels;
if (max_bitrates < sband->n_bitrates)
max_bitrates = sband->n_bitrates;
supp_ht = supp_ht || sband->ht_cap.ht_supported;
supp_vht = supp_vht || sband->vht_cap.vht_supported;
+
+ if (sband->ht_cap.ht_supported)
+ local->rx_chains =
+ max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+ local->rx_chains);
+
+ /* TODO: consider VHT for RX chains, hopefully it's the same */
}
local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -778,19 +840,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
- /*
- * mac80211 doesn't support more than 1 channel, and also not more
- * than one IBSS interface
- */
+ /* mac80211 doesn't support more than one IBSS interface right now */
for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
const struct ieee80211_iface_combination *c;
int j;
c = &hw->wiphy->iface_combinations[i];
- if (c->num_different_channels > 1)
- return -EINVAL;
-
for (j = 0; j < c->n_limits; j++)
if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
c->limits[j].max > 1)
@@ -830,9 +886,21 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
- if (supp_vht)
+ if (supp_vht) {
local->scan_ies_len +=
- 2 + sizeof(struct ieee80211_vht_capabilities);
+ 2 + sizeof(struct ieee80211_vht_cap);
+
+ /*
+ * (for now at least), drivers wanting to use VHT must
+ * support channel contexts, as they contain all the
+ * necessary VHT information and the global hw config
+ * doesn't (yet)
+ */
+ if (WARN_ON(!local->use_chanctx)) {
+ result = -EINVAL;
+ goto fail_wiphy_register;
+ }
+ }
if (!local->ops->hw_scan) {
/* For hw_scan, driver needs to set these up. */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index ff0296c7bab8..1bf03f9ff3ba 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
u32 basic_rates = 0;
- enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT;
+ struct cfg80211_chan_def sta_chan_def;
/*
* As support for each feature is added, check for matching
@@ -97,23 +97,17 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
(ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
goto mismatch;
- ieee80211_sta_get_rates(local, ie, local->oper_channel->band,
+ ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
&basic_rates);
if (sdata->vif.bss_conf.basic_rates != basic_rates)
goto mismatch;
- if (ie->ht_operation)
- sta_channel_type =
- ieee80211_ht_oper_to_channel_type(ie->ht_operation);
-
- /* Disallow HT40+/- mismatch */
- if (ie->ht_operation &&
- (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS ||
- sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) &&
- (sta_channel_type == NL80211_CHAN_HT40MINUS ||
- sta_channel_type == NL80211_CHAN_HT40PLUS) &&
- sdata->vif.bss_conf.channel_type != sta_channel_type)
+ ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
+ ie->ht_operation, &sta_chan_def);
+
+ if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
+ &sta_chan_def))
goto mismatch;
return true;
@@ -129,7 +123,7 @@ mismatch:
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
{
return (ie->mesh_config->meshconf_cap &
- MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
+ IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
}
/**
@@ -264,16 +258,16 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
/* Authentication Protocol identifier */
*pos++ = ifmsh->mesh_auth_id;
/* Mesh Formation Info - number of neighbors */
- neighbors = atomic_read(&ifmsh->mshstats.estab_plinks);
+ neighbors = atomic_read(&ifmsh->estab_plinks);
/* Number of neighbor mesh STAs or 15 whichever is smaller */
neighbors = (neighbors > 15) ? 15 : neighbors;
*pos++ = neighbors << 1;
/* Mesh capability */
- *pos = MESHCONF_CAPAB_FORWARDING;
+ *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
*pos |= ifmsh->accepting_plinks ?
- MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
+ IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ |= ifmsh->adjusting_tbtt ?
- MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
+ IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
*pos++ = 0x00;
return 0;
@@ -355,12 +349,22 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
- struct ieee80211_channel *chan = local->oper_channel;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *chan;
u8 *pos;
if (skb_tailroom(skb) < 3)
return -ENOMEM;
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ chan = chanctx_conf->def.chan;
+ rcu_read_unlock();
+
sband = local->hw.wiphy->bands[chan->band];
if (sband->band == IEEE80211_BAND_2GHZ) {
pos = skb_put(skb, 2 + 1);
@@ -376,12 +380,13 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_supported_band *sband;
u8 *pos;
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ sband = local->hw.wiphy->bands[band];
if (!sband->ht_cap.ht_supported ||
- sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT)
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0;
if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@@ -397,14 +402,26 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
- struct ieee80211_channel *channel = local->oper_channel;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *channel;
enum nl80211_channel_type channel_type =
- sdata->vif.bss_conf.channel_type;
- struct ieee80211_supported_band *sband =
- local->hw.wiphy->bands[channel->band];
- struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+ cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef);
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_sta_ht_cap *ht_cap;
u8 *pos;
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ channel = chanctx_conf->def.chan;
+ rcu_read_unlock();
+
+ sband = local->hw.wiphy->bands[channel->band];
+ ht_cap = &sband->ht_cap;
+
if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
return 0;
@@ -412,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
return -ENOMEM;
pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
- ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type,
+ ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
sdata->vif.bss_conf.ht_operation_mode);
return 0;
@@ -610,7 +627,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
sdata->vif.bss_conf.basic_rates =
ieee80211_mandatory_rates(sdata->local,
- sdata->local->oper_channel->band);
+ ieee80211_get_sdata_band(sdata));
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_HT |
@@ -680,8 +697,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
&elems);
- /* ignore beacons from secure mesh peers if our security is off */
- if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE)
+ /* ignore non-mesh or secure / unsecure mismatch */
+ if ((!elems.mesh_id || !elems.mesh_config) ||
+ (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
+ (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
return;
if (elems.ds_params && elems.ds_params_len == 1)
@@ -694,8 +713,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;
- if (elems.mesh_id && elems.mesh_config &&
- mesh_matches_local(sdata, &elems))
+ if (mesh_matches_local(sdata, &elems))
mesh_neighbour_update(sdata, mgmt->sa, &elems);
if (ifmsh->sync_ops)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 25d0f17dec71..7c9215fb2ac8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -19,20 +19,6 @@
/* Data structures */
/**
- * enum mesh_config_capab_flags - mesh config IE capability flags
- *
- * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
- * additional mesh peerings with other mesh STAs
- * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
- * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing
- */
-enum mesh_config_capab_flags {
- MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0),
- MESHCONF_CAPAB_FORWARDING = BIT(3),
- MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5),
-};
-
-/**
* enum mesh_path_flags - mac80211 mesh path flags
*
*
@@ -256,7 +242,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
-struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);
+const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);
/* Mesh paths */
int mesh_nexthop_lookup(struct sk_buff *skb,
@@ -324,7 +310,7 @@ extern int mesh_allocated;
static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
{
return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks -
- atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
+ atomic_read(&sdata->u.mesh.estab_plinks);
}
static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 3ab34d816897..4b274e9c91a5 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -19,12 +19,6 @@
#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
jiffies + HZ * t / 1000))
-#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
-#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
-#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
-#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
-#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
-
/* 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 ||\
@@ -50,14 +44,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
static inline
u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{
- atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
+ atomic_inc(&sdata->u.mesh.estab_plinks);
return mesh_accept_plinks_update(sdata);
}
static inline
u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{
- atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
+ atomic_dec(&sdata->u.mesh.estab_plinks);
return mesh_accept_plinks_update(sdata);
}
@@ -117,7 +111,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
u16 ht_opmode;
bool non_ht_sta = false, ht20_sta = false;
- if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT)
+ if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0;
rcu_read_lock();
@@ -126,14 +120,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
sta->plink_state != NL80211_PLINK_ESTAB)
continue;
- switch (sta->ch_type) {
- case NL80211_CHAN_NO_HT:
+ switch (sta->ch_width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
mpl_dbg(sdata,
"mesh_plink %pM: nonHT sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr);
non_ht_sta = true;
goto out;
- case NL80211_CHAN_HT20:
+ case NL80211_CHAN_WIDTH_20:
mpl_dbg(sdata,
"mesh_plink %pM: HT20 sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr);
@@ -148,7 +142,7 @@ out:
if (non_ht_sta)
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
else if (ht20_sta &&
- sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20)
+ sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
else
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
@@ -252,6 +246,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
mgmt->u.action.u.self_prot.action_code = action;
if (action != WLAN_SP_MESH_PEERING_CLOSE) {
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+
/* capability info */
pos = skb_put(skb, 2);
memset(pos, 0, 2);
@@ -260,10 +256,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
pos = skb_put(skb, 2);
memcpy(pos + 2, &plid, 2);
}
- if (ieee80211_add_srates_ie(sdata, skb, true,
- local->oper_channel->band) ||
- ieee80211_add_ext_srates_ie(sdata, skb, true,
- local->oper_channel->band) ||
+ if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
+ ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
mesh_add_rsn_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata))
@@ -343,7 +337,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems)
{
struct ieee80211_local *local = sdata->local;
- enum ieee80211_band band = local->oper_channel->band;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_supported_band *sband;
u32 rates, basic_rates = 0;
struct sta_info *sta;
@@ -378,7 +372,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
sta->sta.supp_rates[band] = rates;
if (elems->ht_cap_elem &&
- sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT)
+ sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems->ht_cap_elem,
&sta->sta.ht_cap);
@@ -386,15 +380,19 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
if (elems->ht_operation) {
+ struct cfg80211_chan_def chandef;
+
if (!(elems->ht_operation->ht_param &
IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
sta->sta.ht_cap.cap &=
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- sta->ch_type =
- ieee80211_ht_oper_to_channel_type(elems->ht_operation);
+ ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
+ elems->ht_operation, &chandef);
+ sta->ch_width = chandef.width;
}
- rate_control_rate_init(sta);
+ if (insert)
+ rate_control_rate_init(sta);
spin_unlock_bh(&sta->lock);
if (insert && sta_info_insert(sta))
@@ -430,6 +428,7 @@ static void mesh_plink_timer(unsigned long data)
struct sta_info *sta;
__le16 llid, plid, reason;
struct ieee80211_sub_if_data *sdata;
+ struct mesh_config *mshcfg;
/*
* This STA is valid because sta_info_destroy() will
@@ -456,12 +455,13 @@ static void mesh_plink_timer(unsigned long data)
llid = sta->llid;
plid = sta->plid;
sdata = sta->sdata;
+ mshcfg = &sdata->u.mesh.mshcfg;
switch (sta->plink_state) {
case NL80211_PLINK_OPN_RCVD:
case NL80211_PLINK_OPN_SNT:
/* retry timer */
- if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
+ if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) {
u32 rand;
mpl_dbg(sta->sdata,
"Mesh plink for %pM (retry, timeout): %d %d\n",
@@ -484,7 +484,7 @@ static void mesh_plink_timer(unsigned long data)
if (!reason)
reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
sta->plink_state = NL80211_PLINK_HOLDING;
- mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
+ 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);
@@ -543,7 +543,7 @@ int mesh_plink_open(struct sta_info *sta)
return -EBUSY;
}
sta->plink_state = NL80211_PLINK_OPN_SNT;
- mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
+ mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
spin_unlock_bh(&sta->lock);
mpl_dbg(sdata,
"Mesh plink: starting establishment with %pM\n",
@@ -570,6 +570,7 @@ void mesh_plink_block(struct sta_info *sta)
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 mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
struct ieee802_11_elems elems;
struct sta_info *sta;
enum plink_event event;
@@ -777,7 +778,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->plid = plid;
get_random_bytes(&llid, 2);
sta->llid = llid;
- mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
+ mesh_plink_timer_set(sta,
+ mshcfg->dot11MeshRetryTimeout);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata,
WLAN_SP_MESH_PEERING_OPEN,
@@ -803,7 +805,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta,
- dot11MeshHoldingTimeout(sdata)))
+ mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true;
llid = sta->llid;
@@ -825,7 +827,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CNF_ACPT:
sta->plink_state = NL80211_PLINK_CNF_RCVD;
if (!mod_plink_timer(sta,
- dot11MeshConfirmTimeout(sdata)))
+ mshcfg->dot11MeshConfirmTimeout))
sta->ignore_plink_timer = true;
spin_unlock_bh(&sta->lock);
@@ -847,7 +849,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta,
- dot11MeshHoldingTimeout(sdata)))
+ mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true;
llid = sta->llid;
@@ -888,7 +890,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta,
- dot11MeshHoldingTimeout(sdata)))
+ mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true;
llid = sta->llid;
@@ -923,7 +925,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
changed |= __mesh_plink_deactivate(sta);
sta->plink_state = NL80211_PLINK_HOLDING;
llid = sta->llid;
- mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
+ mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
spin_unlock_bh(&sta->lock);
changed |= mesh_set_ht_prot_mode(sdata);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c
index a16b7b4b1e02..aa8d1e437385 100644
--- a/net/mac80211/mesh_sync.c
+++ b/net/mac80211/mesh_sync.c
@@ -43,7 +43,7 @@ struct sync_method {
static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie)
{
return (ie->mesh_config->meshconf_cap &
- MESHCONF_CAPAB_TBTT_ADJUSTING) != 0;
+ IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0;
}
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
@@ -116,43 +116,13 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
goto no_sync;
}
- if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) {
- /*
- * The mactime is defined as the time the first data symbol
- * of the frame hits the PHY, and the timestamp of the beacon
- * is defined as "the time that the data symbol containing the
- * first bit of the timestamp is transmitted to the PHY plus
- * the transmitting STA's delays through its local PHY from the
- * MAC-PHY interface to its interface with the WM" (802.11
- * 11.1.2)
- *
- * T_r, in 13.13.2.2.2, is just defined as "the frame reception
- * time" but we unless we interpret that time to be the same
- * time of the beacon timestamp, the offset calculation will be
- * off. Below we adjust t_r to be "the time at which the first
- * symbol of the timestamp element in the beacon is received".
- * This correction depends on the rate.
- *
- * Based on similar code in ibss.c
- */
- int rate;
-
- if (rx_status->flag & RX_FLAG_HT) {
- /* TODO:
- * In principle there could be HT-beacons (Dual Beacon
- * HT Operation options), but for now ignore them and
- * just use the primary (i.e. non-HT) beacons for
- * synchronization.
- * */
- goto no_sync;
- } else
- rate = local->hw.wiphy->bands[rx_status->band]->
- bitrates[rx_status->rate_idx].bitrate;
-
- /* 24 bytes of header * 8 bits/byte *
- * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/
- t_r = rx_status->mactime + (24 * 8 * 10 / rate);
- }
+ 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);
@@ -225,58 +195,20 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
ifmsh->sync_offset_clockdrift_max);
set_bit(MESH_WORK_DRIFT_ADJUST,
&ifmsh->wrkq_flags);
+
+ ifmsh->adjusting_tbtt = true;
} else {
msync_dbg(sdata,
"TBTT : max clockdrift=%lld; too small to adjust\n",
(long long)ifmsh->sync_offset_clockdrift_max);
ifmsh->sync_offset_clockdrift_max = 0;
+
+ ifmsh->adjusting_tbtt = false;
}
spin_unlock_bh(&ifmsh->sync_offset_lock);
}
-static const u8 *mesh_get_vendor_oui(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- u8 offset;
-
- if (!ifmsh->ie || !ifmsh->ie_len)
- return NULL;
-
- offset = ieee80211_ie_split_vendor(ifmsh->ie,
- ifmsh->ie_len, 0);
-
- if (!offset)
- return NULL;
-
- return ifmsh->ie + offset + 2;
-}
-
-static void mesh_sync_vendor_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
- u16 stype,
- struct ieee80211_mgmt *mgmt,
- struct ieee802_11_elems *elems,
- struct ieee80211_rx_status *rx_status)
-{
- const u8 *oui;
-
- WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
- msync_dbg(sdata, "called mesh_sync_vendor_rx_bcn_presp\n");
- oui = mesh_get_vendor_oui(sdata);
- /* here you would implement the vendor offset tracking for this oui */
-}
-
-static void mesh_sync_vendor_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
-{
- const u8 *oui;
-
- WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
- msync_dbg(sdata, "called mesh_sync_vendor_adjust_tbtt\n");
- oui = mesh_get_vendor_oui(sdata);
- /* here you would implement the vendor tsf adjustment for this oui */
-}
-
-/* global variable */
-static struct sync_method sync_methods[] = {
+static const struct sync_method sync_methods[] = {
{
.method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
.ops = {
@@ -284,18 +216,11 @@ static struct sync_method sync_methods[] = {
.adjust_tbtt = &mesh_sync_offset_adjust_tbtt,
}
},
- {
- .method = IEEE80211_SYNC_METHOD_VENDOR,
- .ops = {
- .rx_bcn_presp = &mesh_sync_vendor_rx_bcn_presp,
- .adjust_tbtt = &mesh_sync_vendor_adjust_tbtt,
- }
- },
};
-struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method)
+const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method)
{
- struct ieee80211_mesh_sync_ops *ops = NULL;
+ const struct ieee80211_mesh_sync_ops *ops = NULL;
u8 i;
for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1b7eed252fe9..7753a9ca98a6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -178,20 +178,32 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *chan;
struct sta_info *sta;
u32 changed = 0;
u16 ht_opmode;
bool disable_40 = false;
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return 0;
+ }
+ chan = chanctx_conf->def.chan;
+ rcu_read_unlock();
+ sband = local->hw.wiphy->bands[chan->band];
- switch (sdata->vif.bss_conf.channel_type) {
- case NL80211_CHAN_HT40PLUS:
- if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+ switch (sdata->vif.bss_conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_40:
+ if (sdata->vif.bss_conf.chandef.chan->center_freq >
+ sdata->vif.bss_conf.chandef.center_freq1 &&
+ chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
disable_40 = true;
- break;
- case NL80211_CHAN_HT40MINUS:
- if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+ if (sdata->vif.bss_conf.chandef.chan->center_freq <
+ sdata->vif.bss_conf.chandef.center_freq1 &&
+ chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
disable_40 = true;
break;
default:
@@ -342,8 +354,18 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
/* determine capability flags */
cap = vht_cap.cap;
+ if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
+ cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ }
+
+ if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
+ cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
+ cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ }
+
/* reserve and fill IE */
- pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
}
@@ -359,11 +381,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
int i, count, rates_len, supp_rates_len;
u16 capab;
struct ieee80211_supported_band *sband;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *chan;
u32 rates = 0;
lockdep_assert_held(&ifmgd->mtx);
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return;
+ }
+ chan = chanctx_conf->def.chan;
+ rcu_read_unlock();
+ sband = local->hw.wiphy->bands[chan->band];
if (assoc_data->supp_rates_len) {
/*
@@ -392,7 +424,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
4 + /* power capability */
2 + 2 * sband->n_channels + /* supported channels */
2 + sizeof(struct ieee80211_ht_cap) + /* HT */
- 2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */
+ 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
assoc_data->ie_len + /* extra IEs */
9, /* WMM */
GFP_KERNEL);
@@ -485,7 +517,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
*pos++ = WLAN_EID_PWR_CAPABILITY;
*pos++ = 2;
*pos++ = 0; /* min tx power */
- *pos++ = local->oper_channel->max_power; /* max tx power */
+ *pos++ = chan->max_power; /* max tx power */
/* 2. supported channels */
/* TODO: get this in reg domain format */
@@ -521,9 +553,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
offset = noffset;
}
- if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
+ if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)))
+ ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
+
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
- sband, local->oper_channel, ifmgd->ap_smps);
+ sband, chan, sdata->smps_mode);
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
ieee80211_add_vht_ie(sdata, skb, sband);
@@ -657,18 +693,18 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ifmgd->associated)
goto out;
- sdata->local->oper_channel = sdata->local->csa_channel;
+ sdata->local->_oper_channel = sdata->local->csa_channel;
if (!sdata->local->ops->channel_switch) {
/* call "hw_config" only if doing sw channel switch */
ieee80211_hw_config(sdata->local,
IEEE80211_CONF_CHANGE_CHANNEL);
} else {
/* update the device channel directly */
- sdata->local->hw.conf.channel = sdata->local->oper_channel;
+ sdata->local->hw.conf.channel = sdata->local->_oper_channel;
}
/* XXX: shouldn't really modify cfg80211-owned data! */
- ifmgd->associated->channel = sdata->local->oper_channel;
+ ifmgd->associated->channel = sdata->local->_oper_channel;
/* XXX: wait for a beacon first? */
ieee80211_wake_queues_by_reason(&sdata->local->hw,
@@ -680,11 +716,8 @@ static void ieee80211_chswitch_work(struct work_struct *work)
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
{
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_managed *ifmgd;
-
- sdata = vif_to_sdata(vif);
- ifmgd = &sdata->u.mgd;
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
trace_api_chswitch_done(sdata, success);
if (!success) {
@@ -723,6 +756,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
cbss->channel->band);
+ struct ieee80211_chanctx *chanctx;
ASSERT_MGD_MTX(ifmgd);
@@ -748,10 +782,35 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return;
}
- sdata->local->csa_channel = new_ch;
-
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
+ if (sdata->local->use_chanctx) {
+ sdata_info(sdata,
+ "not handling channel switch with channel contexts\n");
+ ieee80211_queue_work(&sdata->local->hw,
+ &ifmgd->csa_connection_drop_work);
+ return;
+ }
+
+ mutex_lock(&sdata->local->chanctx_mtx);
+ if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
+ mutex_unlock(&sdata->local->chanctx_mtx);
+ return;
+ }
+ chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
+ struct ieee80211_chanctx, conf);
+ if (chanctx->refcount > 1) {
+ sdata_info(sdata,
+ "channel switch with multiple interfaces on the same channel, disconnecting\n");
+ ieee80211_queue_work(&sdata->local->hw,
+ &ifmgd->csa_connection_drop_work);
+ mutex_unlock(&sdata->local->chanctx_mtx);
+ return;
+ }
+ mutex_unlock(&sdata->local->chanctx_mtx);
+
+ sdata->local->csa_channel = new_ch;
+
if (sw_elem->mode)
ieee80211_stop_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -778,10 +837,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
cbss->beacon_interval));
}
-static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel *channel,
- const u8 *country_ie, u8 country_ie_len,
- const u8 *pwr_constr_elem)
+static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_channel *channel,
+ const u8 *country_ie, u8 country_ie_len,
+ const u8 *pwr_constr_elem)
{
struct ieee80211_country_ie_triplet *triplet;
int chan = ieee80211_frequency_to_channel(channel->center_freq);
@@ -790,7 +849,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
/* Invalid IE */
if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
- return;
+ return 0;
triplet = (void *)(country_ie + 3);
country_ie_len -= 3;
@@ -831,19 +890,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
}
if (!have_chan_pwr)
- return;
+ return 0;
new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
- if (sdata->local->ap_power_level == new_ap_level)
- return;
+ if (sdata->ap_power_level == new_ap_level)
+ return 0;
sdata_info(sdata,
"Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
new_ap_level, chan_pwr, *pwr_constr_elem,
sdata->u.mgd.bssid);
- sdata->local->ap_power_level = new_ap_level;
- ieee80211_hw_config(sdata->local, 0);
+ sdata->ap_power_level = new_ap_level;
+ if (__ieee80211_recalc_txpower(sdata))
+ return BSS_CHANGED_TXPOWER;
+ return 0;
}
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1280,7 +1341,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
}
use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
- if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ)
+ if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ)
use_short_slot = true;
if (use_protection != bss_conf->use_cts_prot) {
@@ -1321,6 +1382,29 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
+ if (sdata->vif.p2p) {
+ const struct cfg80211_bss_ies *ies;
+
+ rcu_read_lock();
+ ies = rcu_dereference(cbss->ies);
+ if (ies) {
+ u8 noa[2];
+ int ret;
+
+ ret = cfg80211_get_p2p_attr(
+ ies->data, ies->len,
+ IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+ noa, sizeof(noa));
+ if (ret >= 2) {
+ bss_conf->p2p_oppps = noa[1] & 0x80;
+ bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ bss_info_changed |= BSS_CHANGED_P2P_PS;
+ sdata->u.mgd.p2p_noa_index = noa[0];
+ }
+ }
+ rcu_read_unlock();
+ }
+
/* just to be sure */
ieee80211_stop_poll(sdata);
@@ -1350,7 +1434,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_ps(local, -1);
mutex_unlock(&local->iflist_mtx);
- ieee80211_recalc_smps(local);
+ ieee80211_recalc_smps(sdata);
ieee80211_recalc_ps_vif(sdata);
netif_tx_start_all_queues(sdata->dev);
@@ -1443,11 +1527,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
+ sdata->vif.bss_conf.p2p_ctwindow = 0;
+ sdata->vif.bss_conf.p2p_oppps = false;
+
/* on the next assoc, re-program HT parameters */
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
- local->ap_power_level = 0;
+ sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -1465,10 +1552,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
ieee80211_bss_info_change_notify(sdata, changed);
- /* channel(_type) changes are handled by ieee80211_hw_config */
- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
- ieee80211_hw_config(local, 0);
-
/* disassociated - set to defaults now */
ieee80211_set_wmm_default(sdata, false);
@@ -1478,6 +1561,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync(&sdata->u.mgd.chswitch_timer);
sdata->u.mgd.timers_running = 0;
+
+ ifmgd->flags = 0;
+ ieee80211_vif_release_channel(sdata);
}
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1581,6 +1667,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
} else {
int ssid_len;
+ rcu_read_lock();
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
if (WARN_ON_ONCE(ssid == NULL))
ssid_len = 0;
@@ -1589,7 +1676,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
0, (u32) -1, true, false,
- ifmgd->associated->channel);
+ ifmgd->associated->channel, false);
+ rcu_read_unlock();
}
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1685,6 +1773,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
else
return NULL;
+ rcu_read_lock();
ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
if (WARN_ON_ONCE(ssid == NULL))
ssid_len = 0;
@@ -1692,10 +1781,10 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
ssid_len = ssid[1];
skb = ieee80211_build_probe_req(sdata, cbss->bssid,
- (u32) -1,
- sdata->local->oper_channel,
+ (u32) -1, cbss->channel,
ssid + 2, ssid_len,
NULL, 0, true);
+ rcu_read_unlock();
return skb;
}
@@ -1804,6 +1893,8 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+ sdata->u.mgd.flags = 0;
+ ieee80211_vif_release_channel(sdata);
}
cfg80211_put_bss(auth_data->bss);
@@ -1824,7 +1915,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
return;
auth_data->expected_transaction = 4;
drv_mgd_prepare_tx(sdata->local, sdata);
- ieee80211_send_auth(sdata, 3, auth_data->algorithm,
+ ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
elems.challenge - 2, elems.challenge_len + 2,
auth_data->bss->bssid, auth_data->bss->bssid,
auth_data->key, auth_data->key_len,
@@ -1858,8 +1949,13 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
status_code = le16_to_cpu(mgmt->u.auth.status_code);
if (auth_alg != ifmgd->auth_data->algorithm ||
- auth_transaction != ifmgd->auth_data->expected_transaction)
+ auth_transaction != ifmgd->auth_data->expected_transaction) {
+ sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
+ mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
+ auth_transaction,
+ ifmgd->auth_data->expected_transaction);
return RX_MGMT_NONE;
+ }
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied authentication (status %d)\n",
@@ -1872,6 +1968,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
case WLAN_AUTH_OPEN:
case WLAN_AUTH_LEAP:
case WLAN_AUTH_FT:
+ case WLAN_AUTH_SAE:
break;
case WLAN_AUTH_SHARED_KEY:
if (ifmgd->auth_data->expected_transaction != 4) {
@@ -1891,6 +1988,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
run_again(ifmgd, ifmgd->auth_data->timeout);
+ if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
+ ifmgd->auth_data->expected_transaction != 2) {
+ /*
+ * Report auth frame to user space for processing since another
+ * round of Authentication frames is still needed.
+ */
+ return RX_MGMT_CFG80211_RX_AUTH;
+ }
+
/* move station state to auth */
mutex_lock(&sdata->local->sta_mtx);
sta = sta_info_get(sdata, bssid);
@@ -2030,6 +2136,8 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+ sdata->u.mgd.flags = 0;
+ ieee80211_vif_release_channel(sdata);
}
kfree(assoc_data);
@@ -2091,15 +2199,20 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
return false;
}
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
- if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
+ if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
sta->supports_40mhz =
sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ if (elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
+ ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
+ elems.vht_cap_elem,
+ &sta->sta.vht_cap);
+
rate_control_rate_init(sta);
if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
@@ -2140,7 +2253,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_QOS;
if (elems.ht_operation && elems.wmm_param &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
cbss->bssid, false);
@@ -2247,9 +2360,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_CFG80211_RX_ASSOC;
}
+
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len,
+ struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status,
struct ieee802_11_elems *elems,
bool beacon)
@@ -2369,8 +2482,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
size_t baselen;
struct ieee802_11_elems elems;
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *chan;
u32 changed = 0;
- bool erp_valid, directed_tim = false;
+ bool erp_valid;
u8 erp_value = 0;
u32 ncrc;
u8 *bssid;
@@ -2382,8 +2497,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (baselen > len)
return;
- if (rx_status->freq != local->oper_channel->center_freq)
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
+ rcu_read_unlock();
return;
+ }
+ chan = chanctx_conf->def.chan;
+ rcu_read_unlock();
if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
@@ -2490,11 +2616,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
len - baselen, &elems,
care_about_ies, ncrc);
- if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
- directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
- ifmgd->aid);
-
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
+ bool directed_tim = ieee80211_check_tim(elems.tim,
+ elems.tim_len,
+ ifmgd->aid);
if (directed_tim) {
if (local->hw.conf.dynamic_ps_timeout > 0) {
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
@@ -2519,6 +2644,27 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
}
+ if (sdata->vif.p2p) {
+ u8 noa[2];
+ int ret;
+
+ ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
+ len - baselen,
+ IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+ noa, sizeof(noa));
+ if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) {
+ bss_conf->p2p_oppps = noa[1] & 0x80;
+ bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ changed |= BSS_CHANGED_P2P_PS;
+ sdata->u.mgd.p2p_noa_index = noa[0];
+ /*
+ * make sure we update all information, the CRC
+ * mechanism doesn't look at P2P attributes.
+ */
+ ifmgd->beacon_crc_valid = false;
+ }
+ }
+
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
return;
ifmgd->beacon_crc = ncrc;
@@ -2543,22 +2689,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
- struct ieee80211_supported_band *sband;
-
- sband = local->hw.wiphy->bands[local->oper_channel->band];
-
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
bssid, true);
- }
if (elems.country_elem && elems.pwr_constr_elem &&
mgmt->u.probe_resp.capab_info &
cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
- ieee80211_handle_pwr_constr(sdata, local->oper_channel,
- elems.country_elem,
- elems.country_elem_len,
- elems.pwr_constr_elem);
+ changed |= ieee80211_handle_pwr_constr(sdata, chan,
+ elems.country_elem,
+ elems.country_elem_len,
+ elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed);
}
@@ -2703,13 +2844,23 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
drv_mgd_prepare_tx(local, sdata);
if (auth_data->bss->proberesp_ies) {
+ u16 trans = 1;
+ u16 status = 0;
+
sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
auth_data->bss->bssid, auth_data->tries,
IEEE80211_AUTH_MAX_TRIES);
auth_data->expected_transaction = 2;
- ieee80211_send_auth(sdata, 1, auth_data->algorithm,
- auth_data->ie, auth_data->ie_len,
+
+ if (auth_data->algorithm == WLAN_AUTH_SAE) {
+ trans = auth_data->sae_trans;
+ status = auth_data->sae_status;
+ auth_data->expected_transaction = trans;
+ }
+
+ ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
+ auth_data->data, auth_data->data_len,
auth_data->bss->bssid,
auth_data->bss->bssid, NULL, 0, 0);
} else {
@@ -2719,16 +2870,20 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
auth_data->bss->bssid, auth_data->tries,
IEEE80211_AUTH_MAX_TRIES);
+ rcu_read_lock();
ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
- if (!ssidie)
+ if (!ssidie) {
+ rcu_read_unlock();
return -EINVAL;
+ }
/*
* Direct probe is sent to broadcast address as some APs
* will not answer to direct packet in unassociated state.
*/
ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
NULL, 0, (u32) -1, true, false,
- auth_data->bss->channel);
+ auth_data->bss->channel, false);
+ rcu_read_unlock();
}
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3058,90 +3213,313 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
return 0;
}
+static u32 chandef_downgrade(struct cfg80211_chan_def *c)
+{
+ u32 ret;
+ int tmp;
+
+ switch (c->width) {
+ case NL80211_CHAN_WIDTH_20:
+ c->width = NL80211_CHAN_WIDTH_20_NOHT;
+ ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ c->width = NL80211_CHAN_WIDTH_20;
+ c->center_freq1 = c->chan->center_freq;
+ ret = IEEE80211_STA_DISABLE_40MHZ |
+ IEEE80211_STA_DISABLE_VHT;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
+ /* n_P40 */
+ tmp /= 2;
+ /* freq_P40 */
+ c->center_freq1 = c->center_freq1 - 20 + 40 * tmp;
+ c->width = NL80211_CHAN_WIDTH_40;
+ ret = IEEE80211_STA_DISABLE_VHT;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ c->center_freq2 = 0;
+ c->width = NL80211_CHAN_WIDTH_80;
+ ret = IEEE80211_STA_DISABLE_80P80MHZ |
+ IEEE80211_STA_DISABLE_160MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ /* n_P20 */
+ tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
+ /* n_P80 */
+ tmp /= 4;
+ c->center_freq1 = c->center_freq1 - 40 + 80 * tmp;
+ c->width = NL80211_CHAN_WIDTH_80;
+ ret = IEEE80211_STA_DISABLE_80P80MHZ |
+ IEEE80211_STA_DISABLE_160MHZ;
+ break;
+ default:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ WARN_ON_ONCE(1);
+ c->width = NL80211_CHAN_WIDTH_20_NOHT;
+ ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
+ break;
+ }
+
+ WARN_ON_ONCE(!cfg80211_chandef_valid(c));
+
+ return ret;
+}
+
+static u32
+ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_channel *channel,
+ const struct ieee80211_ht_operation *ht_oper,
+ const struct ieee80211_vht_operation *vht_oper,
+ struct cfg80211_chan_def *chandef)
+{
+ struct cfg80211_chan_def vht_chandef;
+ u32 ht_cfreq, ret;
+
+ chandef->chan = channel;
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = channel->center_freq;
+ chandef->center_freq2 = 0;
+
+ if (!ht_oper || !sband->ht_cap.ht_supported) {
+ ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ chandef->width = NL80211_CHAN_WIDTH_20;
+
+ ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
+ channel->band);
+ /* check that channel matches the right operating channel */
+ if (channel->center_freq != ht_cfreq) {
+ /*
+ * It's possible that some APs are confused here;
+ * Netgear WNDR3700 sometimes reports 4 higher than
+ * the actual channel in association responses, but
+ * since we look at probe response/beacon data here
+ * it should be OK.
+ */
+ sdata_info(sdata,
+ "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
+ channel->center_freq, ht_cfreq,
+ ht_oper->primary_chan, channel->band);
+ ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ /* check 40 MHz support, if we have it */
+ if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+ switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ chandef->width = NL80211_CHAN_WIDTH_40;
+ chandef->center_freq1 += 10;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ chandef->width = NL80211_CHAN_WIDTH_40;
+ chandef->center_freq1 -= 10;
+ break;
+ }
+ } else {
+ /* 40 MHz (and 80 MHz) must be supported for VHT */
+ ret = IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ if (!vht_oper || !sband->vht_cap.vht_supported) {
+ ret = IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ vht_chandef.chan = channel;
+ vht_chandef.center_freq1 =
+ ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
+ channel->band);
+ vht_chandef.center_freq2 = 0;
+
+ if (vht_oper->center_freq_seg2_idx)
+ vht_chandef.center_freq2 =
+ ieee80211_channel_to_frequency(
+ vht_oper->center_freq_seg2_idx,
+ channel->band);
+
+ switch (vht_oper->chan_width) {
+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ vht_chandef.width = chandef->width;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
+ vht_chandef.width = NL80211_CHAN_WIDTH_80;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ vht_chandef.width = NL80211_CHAN_WIDTH_160;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ break;
+ default:
+ sdata_info(sdata,
+ "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
+ vht_oper->chan_width);
+ ret = IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ if (!cfg80211_chandef_valid(&vht_chandef)) {
+ sdata_info(sdata,
+ "AP VHT information is invalid, disable VHT\n");
+ ret = IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ if (cfg80211_chandef_identical(chandef, &vht_chandef)) {
+ ret = 0;
+ goto out;
+ }
+
+ if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
+ sdata_info(sdata,
+ "AP VHT information doesn't match HT, disable VHT\n");
+ ret = IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ *chandef = vht_chandef;
+
+ ret = 0;
+
+ while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
+ IEEE80211_CHAN_DISABLED)) {
+ if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
+ ret = IEEE80211_STA_DISABLE_HT |
+ IEEE80211_STA_DISABLE_VHT;
+ goto out;
+ }
+
+ ret = chandef_downgrade(chandef);
+ }
+
+ if (chandef->width != vht_chandef.width)
+ sdata_info(sdata,
+ "local regulatory prevented using AP HT/VHT configuration, downgraded\n");
+
+out:
+ WARN_ON_ONCE(!cfg80211_chandef_valid(chandef));
+ return ret;
+}
+
+static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_bss *cbss)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ const u8 *ht_cap_ie, *vht_cap_ie;
+ const struct ieee80211_ht_cap *ht_cap;
+ const struct ieee80211_vht_cap *vht_cap;
+ u8 chains = 1;
+
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_HT)
+ return chains;
+
+ ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
+ if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
+ ht_cap = (void *)(ht_cap_ie + 2);
+ chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
+ /*
+ * TODO: use "Tx Maximum Number Spatial Streams Supported" and
+ * "Tx Unequal Modulation Supported" fields.
+ */
+ }
+
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
+ return chains;
+
+ vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
+ if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) {
+ u8 nss;
+ u16 tx_mcs_map;
+
+ vht_cap = (void *)(vht_cap_ie + 2);
+ tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
+ for (nss = 8; nss > 0; nss--) {
+ if (((tx_mcs_map >> (2 * (nss - 1))) & 3) !=
+ IEEE80211_VHT_MCS_NOT_SUPPORTED)
+ break;
+ }
+ /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */
+ chains = max(chains, nss);
+ }
+
+ return chains;
+}
+
static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
struct cfg80211_bss *cbss)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- int ht_cfreq;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- const u8 *ht_oper_ie;
const struct ieee80211_ht_operation *ht_oper = NULL;
+ const struct ieee80211_vht_operation *vht_oper = NULL;
struct ieee80211_supported_band *sband;
+ struct cfg80211_chan_def chandef;
+ int ret;
sband = local->hw.wiphy->bands[cbss->channel->band];
- ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ;
+ ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
+ IEEE80211_STA_DISABLE_80P80MHZ |
+ IEEE80211_STA_DISABLE_160MHZ);
+
+ rcu_read_lock();
+
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
+ sband->ht_cap.ht_supported) {
+ const u8 *ht_oper_ie;
- if (sband->ht_cap.ht_supported) {
- ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
- cbss->information_elements,
- cbss->len_information_elements);
+ ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
ht_oper = (void *)(ht_oper_ie + 2);
}
- if (ht_oper) {
- ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
- cbss->channel->band);
- /* check that channel matches the right operating channel */
- if (cbss->channel->center_freq != ht_cfreq) {
- /*
- * It's possible that some APs are confused here;
- * Netgear WNDR3700 sometimes reports 4 higher than
- * the actual channel in association responses, but
- * since we look at probe response/beacon data here
- * it should be OK.
- */
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
+ sband->vht_cap.vht_supported) {
+ const u8 *vht_oper_ie;
+
+ vht_oper_ie = ieee80211_bss_get_ie(cbss,
+ WLAN_EID_VHT_OPERATION);
+ if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
+ vht_oper = (void *)(vht_oper_ie + 2);
+ if (vht_oper && !ht_oper) {
+ vht_oper = NULL;
sdata_info(sdata,
- "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
- cbss->channel->center_freq,
- ht_cfreq, ht_oper->primary_chan,
- cbss->channel->band);
- ht_oper = NULL;
- } else {
- channel_type = NL80211_CHAN_HT20;
+ "AP advertised VHT without HT, disabling both\n");
+ sdata->flags |= IEEE80211_STA_DISABLE_HT;
+ sdata->flags |= IEEE80211_STA_DISABLE_VHT;
}
}
- if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
- /*
- * cfg80211 already verified that the channel itself can
- * be used, but it didn't check that we can do the right
- * HT type, so do that here as well. If HT40 isn't allowed
- * on this channel, disable 40 MHz operation.
- */
+ ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
+ cbss->channel,
+ ht_oper, vht_oper,
+ &chandef);
- switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
- ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
- else
- channel_type = NL80211_CHAN_HT40PLUS;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
- ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
- else
- channel_type = NL80211_CHAN_HT40MINUS;
- break;
- }
- }
+ sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
+ local->rx_chains);
- if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
- /* can only fail due to HT40+/- mismatch */
- channel_type = NL80211_CHAN_HT20;
- sdata_info(sdata,
- "disabling 40 MHz due to multi-vif mismatch\n");
- ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
- WARN_ON(!ieee80211_set_channel_type(local, sdata,
- channel_type));
- }
+ rcu_read_unlock();
- local->oper_channel = cbss->channel;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+ /* will change later if needed */
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
- return 0;
+ /*
+ * If this fails (possibly due to channel context sharing
+ * on incompatible channels, e.g. 80+80 and 160 sharing the
+ * same control channel) try to use a smaller bandwidth.
+ */
+ ret = ieee80211_vif_use_channel(sdata, &chandef,
+ IEEE80211_CHANCTX_SHARED);
+ while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
+ ifmgd->flags |= chandef_downgrade(&chandef);
+ return ret;
}
static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
@@ -3211,7 +3589,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.basic_rates = basic_rates;
/* cf. IEEE 802.11 9.2.12 */
- if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
+ if (cbss->channel->band == IEEE80211_BAND_2GHZ &&
have_higher_than_11mbit)
sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
else
@@ -3273,19 +3651,33 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
case NL80211_AUTHTYPE_NETWORK_EAP:
auth_alg = WLAN_AUTH_LEAP;
break;
+ case NL80211_AUTHTYPE_SAE:
+ auth_alg = WLAN_AUTH_SAE;
+ break;
default:
return -EOPNOTSUPP;
}
- auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL);
+ auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
+ req->ie_len, GFP_KERNEL);
if (!auth_data)
return -ENOMEM;
auth_data->bss = req->bss;
+ if (req->sae_data_len >= 4) {
+ __le16 *pos = (__le16 *) req->sae_data;
+ auth_data->sae_trans = le16_to_cpu(pos[0]);
+ auth_data->sae_status = le16_to_cpu(pos[1]);
+ memcpy(auth_data->data, req->sae_data + 4,
+ req->sae_data_len - 4);
+ auth_data->data_len += req->sae_data_len - 4;
+ }
+
if (req->ie && req->ie_len) {
- memcpy(auth_data->ie, req->ie, req->ie_len);
- auth_data->ie_len = req->ie_len;
+ memcpy(&auth_data->data[auth_data->data_len],
+ req->ie, req->ie_len);
+ auth_data->data_len += req->ie_len;
}
if (req->key && req->key_len) {
@@ -3355,14 +3747,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
const u8 *ssidie, *ht_ie;
int i, err;
- ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
- if (!ssidie)
- return -EINVAL;
-
assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
if (!assoc_data)
return -ENOMEM;
+ rcu_read_lock();
+ ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
+ if (!ssidie) {
+ rcu_read_unlock();
+ kfree(assoc_data);
+ return -EINVAL;
+ }
+ memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
+ assoc_data->ssid_len = ssidie[1];
+ rcu_read_unlock();
+
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated)
@@ -3388,13 +3787,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
/* prepare assoc data */
- /*
- * keep only the 40 MHz disable bit set as it might have
- * been set during authentication already, all other bits
- * should be reset for a new connection
- */
- ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ;
-
ifmgd->beacon_crc_valid = false;
/*
@@ -3408,7 +3800,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
- ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
netdev_info(sdata->dev,
"disabling HT/VHT due to WEP/TKIP use\n");
@@ -3416,7 +3808,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
if (req->flags & ASSOC_REQ_DISABLE_HT) {
- ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
}
@@ -3424,7 +3816,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[req->bss->channel->band];
if (!sband->ht_cap.ht_supported ||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
- ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
if (!bss->wmm_used)
netdev_info(sdata->dev,
"disabling HT as WMM/QoS is not supported by the AP\n");
@@ -3452,11 +3844,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
if (ifmgd->powersave)
- ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC;
+ sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
else
- ifmgd->ap_smps = IEEE80211_SMPS_OFF;
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
} else
- ifmgd->ap_smps = ifmgd->req_smps;
+ sdata->smps_mode = ifmgd->req_smps;
assoc_data->capability = req->bss->capability;
assoc_data->wmm = bss->wmm_used &&
@@ -3464,12 +3856,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->supp_rates = bss->supp_rates;
assoc_data->supp_rates_len = bss->supp_rates_len;
+ rcu_read_lock();
ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation))
assoc_data->ap_ht_param =
((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
else
- ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
+ rcu_read_unlock();
if (bss->wmm_used && bss->uapsd_supported &&
(sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
@@ -3480,9 +3874,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
}
- memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
- assoc_data->ssid_len = ssidie[1];
-
if (req->prev_bssid)
memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
@@ -3560,40 +3951,44 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
bool tx = !req->local_state_change;
+ bool sent_frame = false;
mutex_lock(&ifmgd->mtx);
- if (ifmgd->auth_data) {
- ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
- return 0;
- }
-
sdata_info(sdata,
"deauthenticating from %pM by local choice (reason=%d)\n",
req->bssid, req->reason_code);
- if (ifmgd->associated &&
- ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
- ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
- req->reason_code, tx, frame_buf);
- } else {
+ if (ifmgd->auth_data) {
drv_mgd_prepare_tx(sdata->local, sdata);
ieee80211_send_deauth_disassoc(sdata, req->bssid,
IEEE80211_STYPE_DEAUTH,
req->reason_code, tx,
frame_buf);
+ ieee80211_destroy_auth_data(sdata, false);
+ mutex_unlock(&ifmgd->mtx);
+
+ sent_frame = tx;
+ goto out;
}
+ if (ifmgd->associated &&
+ ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ req->reason_code, tx, frame_buf);
+ sent_frame = tx;
+ }
mutex_unlock(&ifmgd->mtx);
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
-
+ out:
mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);
+ if (sent_frame)
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
+
return 0;
}
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 2c84185dfdb0..a5379aea7d09 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -107,6 +107,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
{
struct ieee80211_sub_if_data *sdata;
+ if (WARN_ON(local->use_chanctx))
+ return;
+
/*
* notify the AP about us leaving the channel and stop all
* STA interfaces.
@@ -145,6 +148,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
{
struct ieee80211_sub_if_data *sdata;
+ if (WARN_ON(local->use_chanctx))
+ return;
+
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
@@ -193,13 +199,14 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
if (roc->mgmt_tx_cookie) {
if (!WARN_ON(!roc->frame)) {
- ieee80211_tx_skb(roc->sdata, roc->frame);
+ ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7,
+ roc->chan->band);
roc->frame = NULL;
}
} else {
- cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc,
- roc->chan, roc->chan_type,
- roc->req_duration, GFP_KERNEL);
+ cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie,
+ roc->chan, roc->req_duration,
+ GFP_KERNEL);
}
roc->notified = true;
@@ -276,8 +283,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
if (!duration)
duration = 10;
- ret = drv_remain_on_channel(local, roc->chan,
- roc->chan_type,
+ ret = drv_remain_on_channel(local, roc->sdata, roc->chan,
duration);
roc->started = true;
@@ -313,8 +319,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
if (!roc->mgmt_tx_cookie)
cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
- (unsigned long)roc,
- roc->chan, roc->chan_type,
+ roc->cookie, roc->chan,
GFP_KERNEL);
list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
@@ -353,7 +358,6 @@ void ieee80211_sw_roc_work(struct work_struct *work)
ieee80211_recalc_idle(local);
local->tmp_channel = roc->chan;
- local->tmp_channel_type = roc->chan_type;
ieee80211_hw_config(local, 0);
/* tell userspace or send frame */
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 5c572e7a1a71..79a48f37d409 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -33,6 +33,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
+ struct ieee80211_chanctx *ctx;
if (!local->open_count)
goto suspend;
@@ -135,12 +136,55 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_BEACON_ENABLED);
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ rcu_access_pointer(sdata->u.ap.beacon))
+ drv_stop_ap(local, sdata);
+
+ if (local->use_chanctx) {
+ struct ieee80211_chanctx_conf *conf;
+
+ mutex_lock(&local->chanctx_mtx);
+ conf = rcu_dereference_protected(
+ sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (conf) {
+ ctx = container_of(conf,
+ struct ieee80211_chanctx,
+ conf);
+ drv_unassign_vif_chanctx(local, sdata, ctx);
+ }
+
+ mutex_unlock(&local->chanctx_mtx);
+ }
drv_remove_interface(local, sdata);
}
sdata = rtnl_dereference(local->monitor_sdata);
- if (sdata)
+ if (sdata) {
+ if (local->use_chanctx) {
+ struct ieee80211_chanctx_conf *conf;
+
+ mutex_lock(&local->chanctx_mtx);
+ conf = rcu_dereference_protected(
+ sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (conf) {
+ ctx = container_of(conf,
+ struct ieee80211_chanctx,
+ conf);
+ drv_unassign_vif_chanctx(local, sdata, ctx);
+ }
+
+ mutex_unlock(&local->chanctx_mtx);
+ }
+
drv_remove_interface(local, sdata);
+ }
+
+ mutex_lock(&local->chanctx_mtx);
+ list_for_each_entry(ctx, &local->chanctx_list, list)
+ drv_remove_chanctx(local, ctx);
+ mutex_unlock(&local->chanctx_mtx);
/* stop hardware - this must stop RX */
if (local->open_count)
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 3313c117b322..dd88381c53b7 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
return;
/* if HT BSS, and we handle a data frame, also try HT rates */
- if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT)
+ if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return;
fc = hdr->frame_control;
@@ -408,8 +408,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
alt_rate.flags |= IEEE80211_TX_RC_MCS;
- if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) ||
- (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS))
+ if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40)
alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 10de668eb9f6..301386dabf88 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -52,11 +52,21 @@ static inline void rate_control_rate_init(struct sta_info *sta)
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
struct ieee80211_supported_band *sband;
+ struct ieee80211_chanctx_conf *chanctx_conf;
if (!ref)
return;
- sband = local->hw.wiphy->bands[local->oper_channel->band];
+ rcu_read_lock();
+
+ chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
+ rcu_read_unlock();
ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 79633ae06fd6..8c5acdc06226 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -154,6 +154,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
+ struct minstrel_priv *mp = priv;
struct minstrel_sta_info *mi = priv_sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
@@ -181,6 +182,10 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (mi->sample_deferred > 0)
mi->sample_deferred--;
+
+ if (time_after(jiffies, mi->stats_update +
+ (mp->update_interval * HZ) / 1000))
+ minstrel_update_stats(mp, mi);
}
@@ -235,10 +240,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
- if (time_after(jiffies, mi->stats_update + (mp->update_interval *
- HZ) / 1000))
- minstrel_update_stats(mp, mi);
-
ndx = mi->max_tp_rate;
if (mrr)
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index fb1d4aa65e8c..9f9c453bc45d 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -389,9 +389,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_tx_rate *ar = info->status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
- bool last = false;
+ bool last;
int group;
- int i = 0;
+ int i;
if (!msp->is_ht)
return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
@@ -419,13 +419,11 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
mi->sample_packets += info->status.ampdu_len;
+ last = !minstrel_ht_txstat_valid(&ar[0]);
for (i = 0; !last; i++) {
last = (i == IEEE80211_TX_MAX_RATES - 1) ||
!minstrel_ht_txstat_valid(&ar[i + 1]);
- if (!minstrel_ht_txstat_valid(&ar[i]))
- break;
-
group = minstrel_ht_get_group_idx(&ar[i]);
rate = &mi->groups[group].rates[ar[i].idx % 8];
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 00ade7feb2e3..580704eba8b8 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -40,6 +40,8 @@
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
struct sk_buff *skb)
{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
if (likely(skb->len > FCS_LEN))
__pskb_trim(skb, skb->len - FCS_LEN);
@@ -47,24 +49,29 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
/* driver bug */
WARN_ON(1);
dev_kfree_skb(skb);
- skb = NULL;
+ return NULL;
}
}
+ if (status->vendor_radiotap_len)
+ __pskb_pull(skb, status->vendor_radiotap_len);
+
return skb;
}
-static inline int should_drop_frame(struct sk_buff *skb,
- int present_fcs_len)
+static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr;
+
+ hdr = (void *)(skb->data + status->vendor_radiotap_len);
if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
RX_FLAG_FAILED_PLCP_CRC |
RX_FLAG_AMPDU_IS_ZEROLEN))
return 1;
- if (unlikely(skb->len < 16 + present_fcs_len))
+ if (unlikely(skb->len < 16 + present_fcs_len +
+ status->vendor_radiotap_len))
return 1;
if (ieee80211_is_ctl(hdr->frame_control) &&
!ieee80211_is_pspoll(hdr->frame_control) &&
@@ -74,32 +81,53 @@ static inline int should_drop_frame(struct sk_buff *skb,
}
static int
-ieee80211_rx_radiotap_len(struct ieee80211_local *local,
- struct ieee80211_rx_status *status)
+ieee80211_rx_radiotap_space(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status)
{
int len;
/* always present fields */
len = sizeof(struct ieee80211_radiotap_header) + 9;
- if (status->flag & RX_FLAG_MACTIME_MPDU)
+ /* allocate extra bitmap */
+ if (status->vendor_radiotap_len)
+ len += 4;
+
+ if (ieee80211_have_rx_timestamp(status)) {
+ len = ALIGN(len, 8);
len += 8;
+ }
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
len += 1;
- if (len & 1) /* padding for RX_FLAGS if necessary */
- len++;
+ /* padding for RX_FLAGS if necessary */
+ len = ALIGN(len, 2);
if (status->flag & RX_FLAG_HT) /* HT info */
len += 3;
if (status->flag & RX_FLAG_AMPDU_DETAILS) {
- /* padding */
- while (len & 3)
- len++;
+ len = ALIGN(len, 4);
len += 8;
}
+ if (status->flag & RX_FLAG_VHT) {
+ len = ALIGN(len, 2);
+ len += 12;
+ }
+
+ if (status->vendor_radiotap_len) {
+ if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
+ status->vendor_radiotap_align = 1;
+ /* align standard part of vendor namespace */
+ len = ALIGN(len, 2);
+ /* allocate standard part of vendor namespace */
+ len += 6;
+ /* align vendor-defined part */
+ len = ALIGN(len, status->vendor_radiotap_align);
+ /* vendor-defined part is already in skb */
+ }
+
return len;
}
@@ -118,6 +146,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_radiotap_header *rthdr;
unsigned char *pos;
u16 rx_flags = 0;
+ int mpdulen;
+
+ mpdulen = skb->len;
+ if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
+ mpdulen += FCS_LEN;
rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len);
@@ -128,17 +161,30 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
(1 << IEEE80211_RADIOTAP_CHANNEL) |
(1 << IEEE80211_RADIOTAP_ANTENNA) |
(1 << IEEE80211_RADIOTAP_RX_FLAGS));
- rthdr->it_len = cpu_to_le16(rtap_len);
+ rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len);
- pos = (unsigned char *)(rthdr+1);
+ pos = (unsigned char *)(rthdr + 1);
+
+ if (status->vendor_radiotap_len) {
+ rthdr->it_present |=
+ cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) |
+ cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT));
+ put_unaligned_le32(status->vendor_radiotap_bitmap, pos);
+ pos += 4;
+ }
/* the order of the following fields is important */
/* IEEE80211_RADIOTAP_TSFT */
- if (status->flag & RX_FLAG_MACTIME_MPDU) {
- put_unaligned_le64(status->mactime, pos);
- rthdr->it_present |=
- cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
+ if (ieee80211_have_rx_timestamp(status)) {
+ /* padding */
+ while ((pos - (u8 *)rthdr) & 7)
+ *pos++ = 0;
+ put_unaligned_le64(
+ ieee80211_calculate_rx_timestamp(local, status,
+ mpdulen, 0),
+ pos);
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
pos += 8;
}
@@ -152,7 +198,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++;
/* IEEE80211_RADIOTAP_RATE */
- if (!rate || status->flag & RX_FLAG_HT) {
+ if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
/*
* Without rate information don't add it. If we have,
* MCS information is a separate field in radiotap,
@@ -172,7 +218,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
if (status->band == IEEE80211_BAND_5GHZ)
put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
pos);
- else if (status->flag & RX_FLAG_HT)
+ else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
pos);
else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
@@ -205,7 +251,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_RX_FLAGS */
/* ensure 2 byte alignment for the 2 byte field as required */
if ((pos - (u8 *)rthdr) & 1)
- pos++;
+ *pos++ = 0;
if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
put_unaligned_le16(rx_flags, pos);
@@ -255,6 +301,56 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
*pos++ = 0;
*pos++ = 0;
}
+
+ if (status->flag & RX_FLAG_VHT) {
+ u16 known = local->hw.radiotap_vht_details;
+
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
+ /* known field - how to handle 80+80? */
+ if (status->flag & RX_FLAG_80P80MHZ)
+ known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+ put_unaligned_le16(known, pos);
+ pos += 2;
+ /* flags */
+ if (status->flag & RX_FLAG_SHORT_GI)
+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
+ pos++;
+ /* bandwidth */
+ if (status->flag & RX_FLAG_80MHZ)
+ *pos++ = 4;
+ else if (status->flag & RX_FLAG_80P80MHZ)
+ *pos++ = 0; /* marked not known above */
+ else if (status->flag & RX_FLAG_160MHZ)
+ *pos++ = 11;
+ else if (status->flag & RX_FLAG_40MHZ)
+ *pos++ = 1;
+ else /* 20 MHz */
+ *pos++ = 0;
+ /* MCS/NSS */
+ *pos = (status->rate_idx << 4) | status->vht_nss;
+ pos += 4;
+ /* coding field */
+ pos++;
+ /* group ID */
+ pos++;
+ /* partial_aid */
+ pos += 2;
+ }
+
+ if (status->vendor_radiotap_len) {
+ /* ensure 2 byte alignment for the vendor field as required */
+ if ((pos - (u8 *)rthdr) & 1)
+ *pos++ = 0;
+ *pos++ = status->vendor_radiotap_oui[0];
+ *pos++ = status->vendor_radiotap_oui[1];
+ *pos++ = status->vendor_radiotap_oui[2];
+ *pos++ = status->vendor_radiotap_subns;
+ put_unaligned_le16(status->vendor_radiotap_len, pos);
+ pos += 2;
+ /* align the actual payload as requested */
+ while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1))
+ *pos++ = 0;
+ }
}
/*
@@ -282,14 +378,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
* the SKB because it has a bad FCS/PLCP checksum.
*/
- /* room for the radiotap header based on driver features */
- needed_headroom = ieee80211_rx_radiotap_len(local, status);
-
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN;
- /* make sure hdr->frame_control is on the linear part */
- if (!pskb_may_pull(origskb, 2)) {
+ /* ensure hdr->frame_control and vendor radiotap data are in skb head */
+ if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) {
dev_kfree_skb(origskb);
return NULL;
}
@@ -303,6 +396,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
return remove_monitor_info(local, origskb);
}
+ /* room for the radiotap header based on driver features */
+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
+
if (should_drop_frame(origskb, present_fcs_len)) {
/* only need to expand headroom if necessary */
skb = origskb;
@@ -374,7 +470,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
return origskb;
}
-
static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -403,10 +498,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
*
* We also use that counter for non-QoS STAs.
*/
- seqno_idx = NUM_RX_DATA_QUEUES;
+ seqno_idx = IEEE80211_NUM_TIDS;
security_idx = 0;
if (ieee80211_is_mgmt(hdr->frame_control))
- security_idx = NUM_RX_DATA_QUEUES;
+ security_idx = IEEE80211_NUM_TIDS;
tid = 0;
}
@@ -481,8 +576,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
struct ieee80211_mmie *mmie;
- if (skb->len < 24 + sizeof(*mmie) ||
- !is_multicast_ether_addr(hdr->da))
+ if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
return -1;
if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
@@ -497,9 +591,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
return le16_to_cpu(mmie->key_id);
}
-
-static ieee80211_rx_result
-ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
+static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
char *dev_addr = rx->sdata->vif.addr;
@@ -507,7 +599,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) {
if (is_multicast_ether_addr(hdr->addr1)) {
if (ieee80211_has_tods(hdr->frame_control) ||
- !ieee80211_has_fromds(hdr->frame_control))
+ !ieee80211_has_fromds(hdr->frame_control))
return RX_DROP_MONITOR;
if (ether_addr_equal(hdr->addr3, dev_addr))
return RX_DROP_MONITOR;
@@ -539,7 +631,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
mgmt = (struct ieee80211_mgmt *)hdr;
category = mgmt->u.action.category;
if (category != WLAN_CATEGORY_MESH_ACTION &&
- category != WLAN_CATEGORY_SELF_PROTECTED)
+ category != WLAN_CATEGORY_SELF_PROTECTED)
return RX_DROP_MONITOR;
return RX_CONTINUE;
}
@@ -551,7 +643,6 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
return RX_DROP_MONITOR;
-
}
return RX_CONTINUE;
@@ -575,7 +666,6 @@ static inline u16 seq_sub(u16 sq1, u16 sq2)
return (sq1 - sq2) & SEQ_MASK;
}
-
static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
int index)
@@ -1148,12 +1238,19 @@ ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
}
-static void ap_sta_ps_start(struct sta_info *sta)
+static void sta_ps_start(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
+ struct ps_data *ps;
+
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ ps = &sdata->bss->ps;
+ else
+ return;
- atomic_inc(&sdata->bss->num_sta_ps);
+ atomic_inc(&ps->num_sta_ps);
set_sta_flag(sta, WLAN_STA_PS_STA);
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
@@ -1161,7 +1258,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
sta->sta.addr, sta->sta.aid);
}
-static void ap_sta_ps_end(struct sta_info *sta)
+static void sta_ps_end(struct sta_info *sta)
{
ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n",
sta->sta.addr, sta->sta.aid);
@@ -1188,9 +1285,9 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
return -EINVAL;
if (start)
- ap_sta_ps_start(sta_inf);
+ sta_ps_start(sta_inf);
else
- ap_sta_ps_end(sta_inf);
+ sta_ps_end(sta_inf);
return 0;
}
@@ -1284,17 +1381,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
/*
* Update last_rx only for IBSS packets which are for the current
- * BSSID to avoid keeping the current IBSS network alive in cases
- * where other STAs start using different BSSID.
+ * BSSID and for station already AUTHORIZED to avoid keeping the
+ * current IBSS network alive in cases where other STAs start
+ * using different BSSID. This will also give the station another
+ * chance to restart the authentication/authorization in case
+ * something went wrong the first time.
*/
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
NL80211_IFTYPE_ADHOC);
- if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid)) {
+ if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
+ test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
sta->last_rx = jiffies;
if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag;
+ sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
} else if (!is_multicast_ether_addr(hdr->addr1)) {
@@ -1306,6 +1408,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag;
+ sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
@@ -1342,10 +1445,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
*/
if (ieee80211_is_data(hdr->frame_control) &&
!ieee80211_has_pm(hdr->frame_control))
- ap_sta_ps_end(sta);
+ sta_ps_end(sta);
} else {
if (ieee80211_has_pm(hdr->frame_control))
- ap_sta_ps_start(sta);
+ sta_ps_start(sta);
}
}
@@ -1391,9 +1494,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
struct sk_buff **skb)
{
struct ieee80211_fragment_entry *entry;
- int idx;
- idx = sdata->fragment_next;
entry = &sdata->fragments[sdata->fragment_next++];
if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
sdata->fragment_next = 0;
@@ -1580,18 +1681,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
}
-static int
-ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
+static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{
- if (unlikely(!rx->sta ||
- !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
+ if (unlikely(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
return -EACCES;
return 0;
}
-static int
-ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
+static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
@@ -1613,8 +1711,7 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
return 0;
}
-static int
-ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
+static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
@@ -1998,7 +2095,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
} else {
/* unable to resolve next hop */
mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3,
- 0, reason, fwd_hdr->addr2, sdata);
+ 0, reason, fwd_hdr->addr2, sdata);
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
kfree_skb(fwd_skb);
return RX_DROP_MONITOR;
@@ -2207,7 +2304,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
cfg80211_report_obss_beacon(rx->local->hw.wiphy,
rx->skb->data, rx->skb->len,
- status->freq, sig, GFP_ATOMIC);
+ status->freq, sig);
rx->flags |= IEEE80211_RX_BEACON_REPORTED;
}
@@ -2236,7 +2333,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_UNUSABLE;
- if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
+ if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
+ mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED)
return RX_DROP_UNUSABLE;
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
@@ -2407,7 +2505,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (!ieee80211_vif_is_mesh(&sdata->vif))
break;
if (mesh_action_is_path_sel(mgmt) &&
- (!mesh_path_sel_is_hwmp(sdata)))
+ !mesh_path_sel_is_hwmp(sdata))
break;
goto queue;
}
@@ -2463,7 +2561,6 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
return RX_QUEUED;
}
-
return RX_CONTINUE;
}
@@ -2593,7 +2690,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
goto out_free_skb;
/* room for the radiotap header based on driver features */
- needed_headroom = ieee80211_rx_radiotap_len(local, status);
+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
if (skb_headroom(skb) < needed_headroom &&
pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
@@ -2656,7 +2753,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
status = IEEE80211_SKB_RXCB((rx->skb));
sband = rx->local->hw.wiphy->bands[status->band];
- if (!(status->flag & RX_FLAG_HT))
+ if (!(status->flag & RX_FLAG_HT) &&
+ !(status->flag & RX_FLAG_VHT))
rate = &sband->bitrates[status->rate_idx];
ieee80211_rx_cooked_monitor(rx, rate);
@@ -2823,8 +2921,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta) {
int rate_idx;
- if (status->flag & RX_FLAG_HT)
- rate_idx = 0; /* TODO: HT rates */
+ if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
+ rate_idx = 0; /* TODO: HT/VHT rates */
else
rate_idx = status->rate_idx;
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
@@ -3048,8 +3146,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
WARN_ON_ONCE(softirq_count() == 0);
- if (WARN_ON(status->band < 0 ||
- status->band >= IEEE80211_NUM_BANDS))
+ if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
goto drop;
sband = local->hw.wiphy->bands[status->band];
@@ -3094,17 +3191,22 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
* hardware error. The driver should catch hardware
* errors.
*/
- if (WARN((status->rate_idx < 0 ||
- status->rate_idx > 76),
+ if (WARN(status->rate_idx > 76,
"Rate marked as an HT rate but passed "
"status->rate_idx is not "
"an MCS index [0-76]: %d (0x%02x)\n",
status->rate_idx,
status->rate_idx))
goto drop;
+ } else if (status->flag & RX_FLAG_VHT) {
+ if (WARN_ONCE(status->rate_idx > 9 ||
+ !status->vht_nss ||
+ status->vht_nss > 8,
+ "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
+ status->rate_idx, status->vht_nss))
+ goto drop;
} else {
- if (WARN_ON(status->rate_idx < 0 ||
- status->rate_idx >= sband->n_bitrates))
+ if (WARN_ON(status->rate_idx >= sband->n_bitrates))
goto drop;
rate = &sband->bitrates[status->rate_idx];
}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 43e60b5a7546..8ed83dcc149f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -118,7 +118,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_tim_ie *tim_ie = elems->tim;
bss->dtim_period = tim_ie->dtim_period;
if (!elems->parse_error)
- bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
+ bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
}
/* If the beacon had no TIM IE, or it was invalid, use 1 */
@@ -174,7 +174,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
u8 *elements;
struct ieee80211_channel *channel;
size_t baselen;
- int freq;
bool beacon;
struct ieee802_11_elems elems;
@@ -209,13 +208,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
- if (elems.ds_params && elems.ds_params_len == 1)
- freq = ieee80211_channel_to_frequency(elems.ds_params[0],
- rx_status->band);
- else
- freq = rx_status->freq;
-
- channel = ieee80211_get_channel(local->hw.wiphy, freq);
+ channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;
@@ -254,6 +247,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
local->hw_scan_req->n_channels = n_chans;
ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
+ local->hw_scan_ies_bufsize,
req->ie, req->ie_len, band,
req->rates[band], 0);
local->hw_scan_req->ie_len = ielen;
@@ -336,6 +330,10 @@ EXPORT_SYMBOL(ieee80211_scan_completed);
static int ieee80211_start_sw_scan(struct ieee80211_local *local)
{
+ /* Software scan is not supported in multi-channel cases */
+ if (local->use_chanctx)
+ return -EOPNOTSUPP;
+
/*
* Hardware/driver doesn't support hw_scan, so use software
* scanning instead. First send a nullfunc frame with power save
@@ -417,7 +415,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
local->scan_req->ie, local->scan_req->ie_len,
local->scan_req->rates[band], false,
local->scan_req->no_cck,
- local->hw.conf.channel);
+ local->hw.conf.channel, true);
/*
* After sending probe requests, wait for probe responses
@@ -448,11 +446,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (local->ops->hw_scan) {
u8 *ies;
+ local->hw_scan_ies_bufsize = 2 + IEEE80211_MAX_SSID_LEN +
+ local->scan_ies_len +
+ req->ie_len;
local->hw_scan_req = kmalloc(
sizeof(*local->hw_scan_req) +
req->n_channels * sizeof(req->channels[0]) +
- 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len +
- req->ie_len, GFP_KERNEL);
+ local->hw_scan_ies_bufsize, GFP_KERNEL);
if (!local->hw_scan_req)
return -ENOMEM;
@@ -462,6 +462,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
sizeof(*local->hw_scan_req) +
req->n_channels * sizeof(req->channels[0]);
local->hw_scan_req->ie = ies;
+ local->hw_scan_req->flags = req->flags;
local->hw_scan_band = 0;
@@ -480,7 +481,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
- (req->channels[0] == local->oper_channel)) {
+ (req->channels[0] == local->_oper_channel)) {
/*
* If we are scanning only on the operating channel
* then we do not need to stop normal activities
@@ -562,6 +563,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
unsigned long min_beacon_int = 0;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *next_chan;
+ enum mac80211_scan_state next_scan_state;
/*
* check if at least one STA interface is associated,
@@ -620,10 +622,18 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
usecs_to_jiffies(min_beacon_int * 1024) *
local->hw.conf.listen_interval);
- if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
- local->next_scan_state = SCAN_SUSPEND;
- else
- local->next_scan_state = SCAN_SET_CHANNEL;
+ if (associated && !tx_empty) {
+ if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+ next_scan_state = SCAN_ABORT;
+ else
+ next_scan_state = SCAN_SUSPEND;
+ } else if (associated && (bad_latency || listen_int_exceeded)) {
+ next_scan_state = SCAN_SUSPEND;
+ } else {
+ next_scan_state = SCAN_SET_CHANNEL;
+ }
+
+ local->next_scan_state = next_scan_state;
*next_delay = 0;
}
@@ -794,6 +804,9 @@ void ieee80211_scan_work(struct work_struct *work)
case SCAN_RESUME:
ieee80211_scan_state_resume(local, &next_delay);
break;
+ case SCAN_ABORT:
+ aborted = true;
+ goto out_complete;
}
} while (next_delay == 0);
@@ -918,7 +931,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sched_scan_ies sched_scan_ies = {};
- int ret, i;
+ int ret, i, iebufsz;
+
+ iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
+ local->scan_ies_len + req->ie_len;
mutex_lock(&local->mtx);
@@ -936,10 +952,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
if (!local->hw.wiphy->bands[i])
continue;
- sched_scan_ies.ie[i] = kzalloc(2 + IEEE80211_MAX_SSID_LEN +
- local->scan_ies_len +
- req->ie_len,
- GFP_KERNEL);
+ sched_scan_ies.ie[i] = kzalloc(iebufsz, GFP_KERNEL);
if (!sched_scan_ies.ie[i]) {
ret = -ENOMEM;
goto out_free;
@@ -947,8 +960,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
sched_scan_ies.len[i] =
ieee80211_build_preq_ies(local, sched_scan_ies.ie[i],
- req->ie, req->ie_len, i,
- (u32) -1, 0);
+ iebufsz, req->ie, req->ie_len,
+ i, (u32) -1, 0);
}
ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index d2eb64e12353..f3e502502fee 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -98,6 +98,7 @@ static void free_sta_work(struct work_struct *wk)
struct tid_ampdu_tx *tid_tx;
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
+ struct ps_data *ps;
/*
* At this point, when being called as call_rcu callback,
@@ -107,11 +108,15 @@ static void free_sta_work(struct work_struct *wk)
*/
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
- BUG_ON(!sdata->bss);
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ ps = &sdata->bss->ps;
+ else
+ return;
clear_sta_flag(sta, WLAN_STA_PS_STA);
- atomic_dec(&sdata->bss->num_sta_ps);
+ atomic_dec(&ps->num_sta_ps);
sta_info_recalc_tim(sta);
}
@@ -137,7 +142,7 @@ static void free_sta_work(struct work_struct *wk)
* drivers have to handle aggregation stop being requested, followed
* directly by station destruction.
*/
- for (i = 0; i < STA_TID_NUM; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
if (!tid_tx)
continue;
@@ -325,7 +330,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
return NULL;
}
- for (i = 0; i < STA_TID_NUM; i++) {
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
/*
* timer_to_tid must be initialized with identity mapping
* to enable session_timer's data differentiation. See
@@ -338,7 +343,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
skb_queue_head_init(&sta->tx_filtered[i]);
}
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ for (i = 0; i < IEEE80211_NUM_TIDS; i++)
sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
@@ -502,22 +507,22 @@ int sta_info_insert(struct sta_info *sta)
return err;
}
-static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+static inline void __bss_tim_set(u8 *tim, u16 id)
{
/*
* This format has been mandated by the IEEE specifications,
* so this line may not be changed to use the __set_bit() format.
*/
- bss->tim[aid / 8] |= (1 << (aid % 8));
+ tim[id / 8] |= (1 << (id % 8));
}
-static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
+static inline void __bss_tim_clear(u8 *tim, u16 id)
{
/*
* This format has been mandated by the IEEE specifications,
* so this line may not be changed to use the __clear_bit() format.
*/
- bss->tim[aid / 8] &= ~(1 << (aid % 8));
+ tim[id / 8] &= ~(1 << (id % 8));
}
static unsigned long ieee80211_tids_for_ac(int ac)
@@ -541,14 +546,23 @@ static unsigned long ieee80211_tids_for_ac(int ac)
void sta_info_recalc_tim(struct sta_info *sta)
{
struct ieee80211_local *local = sta->local;
- struct ieee80211_if_ap *bss = sta->sdata->bss;
+ struct ps_data *ps;
unsigned long flags;
bool indicate_tim = false;
u8 ignore_for_tim = sta->sta.uapsd_queues;
int ac;
+ u16 id;
+
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ if (WARN_ON_ONCE(!sta->sdata->bss))
+ return;
- if (WARN_ON_ONCE(!sta->sdata->bss))
+ ps = &sta->sdata->bss->ps;
+ id = sta->sta.aid;
+ } else {
return;
+ }
/* No need to do anything if the driver does all */
if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
@@ -587,9 +601,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
spin_lock_irqsave(&local->tim_lock, flags);
if (indicate_tim)
- __bss_tim_set(bss, sta->sta.aid);
+ __bss_tim_set(ps->tim, id);
else
- __bss_tim_clear(bss, sta->sta.aid);
+ __bss_tim_clear(ps->tim, id);
if (local->ops->set_tim) {
local->tim_in_locked_section = true;
@@ -893,8 +907,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
continue;
if (time_after(jiffies, sta->last_rx + exp_time)) {
- ibss_dbg(sdata, "expiring inactive STA %pM\n",
- sta->sta.addr);
+ sta_dbg(sta->sdata, "expiring inactive STA %pM\n",
+ sta->sta.addr);
WARN_ON(__sta_info_destroy(sta));
}
}
@@ -948,10 +962,17 @@ static void clear_sta_ps_flags(void *_sta)
{
struct sta_info *sta = _sta;
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ps_data *ps;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ ps = &sdata->bss->ps;
+ else
+ return;
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
- atomic_dec(&sdata->bss->num_sta_ps);
+ atomic_dec(&ps->num_sta_ps);
}
/* powersave support code */
@@ -965,7 +986,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
clear_sta_flag(sta, WLAN_STA_SP);
- BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1);
+ BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
sta->driver_buffered_tids = 0;
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
@@ -1013,6 +1034,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
__le16 fc;
bool qos = test_sta_flag(sta, WLAN_STA_WME);
struct ieee80211_tx_info *info;
+ struct ieee80211_chanctx_conf *chanctx_conf;
if (qos) {
fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
@@ -1062,7 +1084,16 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false);
- ieee80211_xmit(sdata, skb);
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return;
+ }
+
+ ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band);
+ rcu_read_unlock();
}
static void
@@ -1343,7 +1374,7 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
- if (WARN_ON(tid >= STA_TID_NUM))
+ if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
return;
if (buffered)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c88f161f8118..1489bca9ea97 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -80,7 +80,6 @@ enum ieee80211_sta_info_flags {
WLAN_STA_TOFFSET_KNOWN,
};
-#define STA_TID_NUM 16
#define ADDBA_RESP_INTERVAL HZ
#define HT_AGG_MAX_RETRIES 15
#define HT_AGG_BURST_RETRIES 3
@@ -197,15 +196,15 @@ struct tid_ampdu_rx {
struct sta_ampdu_mlme {
struct mutex mtx;
/* rx */
- struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM];
- unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
- unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)];
+ struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
+ unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
+ unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
/* tx */
struct work_struct work;
- struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM];
- struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM];
- unsigned long last_addba_req_time[STA_TID_NUM];
- u8 addba_req_num[STA_TID_NUM];
+ struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS];
+ struct tid_ampdu_tx *tid_start_tx[IEEE80211_NUM_TIDS];
+ unsigned long last_addba_req_time[IEEE80211_NUM_TIDS];
+ u8 addba_req_num[IEEE80211_NUM_TIDS];
u8 dialog_token_allocator;
};
@@ -228,6 +227,7 @@ struct sta_ampdu_mlme {
* "the" transmit rate
* @last_rx_rate_idx: rx status rate index of the last data packet
* @last_rx_rate_flag: rx status flag of the last data packet
+ * @last_rx_rate_vht_nss: rx status nss of last data packet
* @lock: used for locking all fields that require locking, see comments
* in the header file.
* @drv_unblock_wk: used for driver PS unblocking
@@ -250,6 +250,7 @@ struct sta_ampdu_mlme {
* @rx_dropped: number of dropped MPDUs from this STA
* @last_signal: signal of last received frame from this STA
* @avg_signal: moving average of signal of received frames from this STA
+ * @last_ack_signal: signal of last received Ack frame from this STA
* @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
* @tx_filtered_count: number of frames the hardware filtered for this STA
* @tx_retry_failed: number of frames that failed retry
@@ -273,7 +274,7 @@ struct sta_ampdu_mlme {
* @t_offset: timing offset relative to this host
* @t_offset_setpoint: reference timing offset of this sta to be used when
* calculating clockdrift
- * @ch_type: peer's channel type
+ * @ch_width: peer's channel width
* @debugfs: debug filesystem info
* @dead: set to true when sta is unlinked
* @uploaded: set to true when sta is uploaded to the driver
@@ -329,8 +330,9 @@ struct sta_info {
unsigned long rx_dropped;
int last_signal;
struct ewma avg_signal;
+ int last_ack_signal;
/* Plus 1 for non-QoS frames */
- __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1];
+ __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
/* Updated from TX status path only, no locking requirements */
unsigned long tx_filtered_count;
@@ -344,14 +346,15 @@ struct sta_info {
unsigned long tx_fragments;
struct ieee80211_tx_rate last_tx_rate;
int last_rx_rate_idx;
- int last_rx_rate_flag;
+ u32 last_rx_rate_flag;
+ u8 last_rx_rate_vht_nss;
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
/*
* Aggregation information, locked with lock.
*/
struct sta_ampdu_mlme ampdu_mlme;
- u8 timer_to_tid[STA_TID_NUM];
+ u8 timer_to_tid[IEEE80211_NUM_TIDS];
#ifdef CONFIG_MAC80211_MESH
/*
@@ -369,7 +372,7 @@ struct sta_info {
struct timer_list plink_timer;
s64 t_offset;
s64 t_offset_setpoint;
- enum nl80211_channel_type ch_type;
+ enum nl80211_chan_width ch_width;
#endif
#ifdef CONFIG_MAC80211_DEBUGFS
@@ -551,6 +554,8 @@ int sta_info_flush(struct ieee80211_local *local,
void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo);
+void sta_set_rate_info_rx(struct sta_info *sta,
+ struct rate_info *rinfo);
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 101eb88a2b78..07d99578a2b1 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -189,30 +189,31 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
}
if (ieee80211_is_action(mgmt->frame_control) &&
- sdata->vif.type == NL80211_IFTYPE_STATION &&
mgmt->u.action.category == WLAN_CATEGORY_HT &&
- mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) {
+ mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS &&
+ sdata->vif.type == NL80211_IFTYPE_STATION &&
+ ieee80211_sdata_running(sdata)) {
/*
* This update looks racy, but isn't -- if we come
* here we've definitely got a station that we're
* talking to, and on a managed interface that can
* only be the AP. And the only other place updating
- * this variable is before we're associated.
+ * this variable in managed mode is before association.
*/
switch (mgmt->u.action.u.ht_smps.smps_control) {
case WLAN_HT_SMPS_CONTROL_DYNAMIC:
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC;
+ sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
break;
case WLAN_HT_SMPS_CONTROL_STATIC:
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC;
+ sdata->smps_mode = IEEE80211_SMPS_STATIC;
break;
case WLAN_HT_SMPS_CONTROL_DISABLED:
default: /* shouldn't happen since we don't send that */
- sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF;
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
break;
}
- ieee80211_queue_work(&local->hw, &local->recalc_smps);
+ ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
}
}
@@ -324,6 +325,75 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
}
+static void ieee80211_report_used_skb(struct ieee80211_local *local,
+ struct sk_buff *skb, bool dropped)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ bool acked = info->flags & IEEE80211_TX_STAT_ACK;
+
+ if (dropped)
+ acked = false;
+
+ if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
+ struct ieee80211_sub_if_data *sdata = NULL;
+ struct ieee80211_sub_if_data *iter_sdata;
+ u64 cookie = (unsigned long)skb;
+
+ rcu_read_lock();
+
+ if (skb->dev) {
+ list_for_each_entry_rcu(iter_sdata, &local->interfaces,
+ list) {
+ if (!iter_sdata->dev)
+ continue;
+
+ if (skb->dev == iter_sdata->dev) {
+ sdata = iter_sdata;
+ break;
+ }
+ }
+ } else {
+ sdata = rcu_dereference(local->p2p_sdata);
+ }
+
+ if (!sdata)
+ skb->dev = NULL;
+ else if (ieee80211_is_nullfunc(hdr->frame_control) ||
+ ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+ cfg80211_probe_status(sdata->dev, hdr->addr1,
+ cookie, acked, GFP_ATOMIC);
+ } else {
+ cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
+ skb->len, acked, GFP_ATOMIC);
+ }
+
+ rcu_read_unlock();
+ }
+
+ if (unlikely(info->ack_frame_id)) {
+ struct sk_buff *ack_skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->ack_status_lock, flags);
+ ack_skb = idr_find(&local->ack_status_frames,
+ info->ack_frame_id);
+ if (ack_skb)
+ idr_remove(&local->ack_status_frames,
+ info->ack_frame_id);
+ spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+ if (ack_skb) {
+ if (!dropped) {
+ /* consumes ack_skb */
+ skb_complete_wifi_ack(ack_skb, acked);
+ } else {
+ dev_kfree_skb_any(ack_skb);
+ }
+ }
+ }
+}
+
/*
* Use a static threshold for now, best value to be determined
* by testing ...
@@ -432,7 +502,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
- ieee80211_set_bar_pending(sta, tid, ssn);
+ if (local->hw.flags &
+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL)
+ ieee80211_stop_tx_ba_session(&sta->sta, tid);
+ else
+ ieee80211_set_bar_pending(sta, tid, ssn);
}
}
@@ -469,6 +543,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
sta->lost_packets = 0;
}
}
+
+ if (acked)
+ sta->last_ack_signal = info->status.ack_signal;
}
rcu_read_unlock();
@@ -515,62 +592,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
msecs_to_jiffies(10));
}
- if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
- u64 cookie = (unsigned long)skb;
- bool found = false;
-
- acked = info->flags & IEEE80211_TX_STAT_ACK;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!sdata->dev)
- continue;
-
- if (skb->dev != sdata->dev)
- continue;
-
- found = true;
- break;
- }
-
- if (!skb->dev) {
- sdata = rcu_dereference(local->p2p_sdata);
- if (sdata)
- found = true;
- }
-
- if (!found)
- skb->dev = NULL;
- else if (ieee80211_is_nullfunc(hdr->frame_control) ||
- ieee80211_is_qos_nullfunc(hdr->frame_control)) {
- cfg80211_probe_status(sdata->dev, hdr->addr1,
- cookie, acked, GFP_ATOMIC);
- } else {
- cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
- skb->len, acked, GFP_ATOMIC);
- }
-
- rcu_read_unlock();
- }
-
- if (unlikely(info->ack_frame_id)) {
- struct sk_buff *ack_skb;
- unsigned long flags;
-
- spin_lock_irqsave(&local->ack_status_lock, flags);
- ack_skb = idr_find(&local->ack_status_frames,
- info->ack_frame_id);
- if (ack_skb)
- idr_remove(&local->ack_status_frames,
- info->ack_frame_id);
- spin_unlock_irqrestore(&local->ack_status_lock, flags);
-
- /* consumes ack_skb */
- if (ack_skb)
- skb_complete_wifi_ack(ack_skb,
- info->flags & IEEE80211_TX_STAT_ACK);
- }
+ ieee80211_report_used_skb(local, skb, false);
/* this was a transmitted frame, but now we want to reuse it */
skb_orphan(skb);
@@ -646,25 +668,8 @@ EXPORT_SYMBOL(ieee80211_report_low_ack);
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
- if (unlikely(info->ack_frame_id)) {
- struct sk_buff *ack_skb;
- unsigned long flags;
-
- spin_lock_irqsave(&local->ack_status_lock, flags);
- ack_skb = idr_find(&local->ack_status_frames,
- info->ack_frame_id);
- if (ack_skb)
- idr_remove(&local->ack_status_frames,
- info->ack_frame_id);
- spin_unlock_irqrestore(&local->ack_status_lock, flags);
-
- /* consumes ack_skb */
- if (ack_skb)
- dev_kfree_skb_any(ack_skb);
- }
+ ieee80211_report_used_skb(local, skb, true);
dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(ieee80211_free_txskb);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 18d9c8a52e9e..a8270b441a6f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -28,6 +28,25 @@
#define VIF_PR_FMT " vif:%s(%d%s)"
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
+#define CHANCTX_ENTRY __field(u32, control_freq) \
+ __field(u32, chan_width) \
+ __field(u32, center_freq1) \
+ __field(u32, center_freq2) \
+ __field(u8, rx_chains_static) \
+ __field(u8, rx_chains_dynamic)
+#define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\
+ __entry->chan_width = ctx->conf.def.width; \
+ __entry->center_freq1 = ctx->conf.def.center_freq1; \
+ __entry->center_freq2 = ctx->conf.def.center_freq2; \
+ __entry->rx_chains_static = ctx->conf.rx_chains_static; \
+ __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
+#define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d"
+#define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \
+ __entry->center_freq1, __entry->center_freq2, \
+ __entry->rx_chains_static, __entry->rx_chains_dynamic
+
+
+
/*
* Tracing for driver callbacks.
*/
@@ -301,20 +320,37 @@ TRACE_EVENT(drv_bss_info_changed,
TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
+ __field(u32, changed)
__field(bool, assoc)
+ __field(bool, ibss_joined)
+ __field(bool, ibss_creator)
__field(u16, aid)
__field(bool, cts)
__field(bool, shortpre)
__field(bool, shortslot)
+ __field(bool, enable_beacon)
__field(u8, dtimper)
__field(u16, bcnint)
__field(u16, assoc_cap)
__field(u64, sync_tsf)
__field(u32, sync_device_ts)
__field(u32, basic_rates)
- __field(u32, changed)
- __field(bool, enable_beacon)
+ __array(int, mcast_rate, IEEE80211_NUM_BANDS)
__field(u16, ht_operation_mode)
+ __field(s32, cqm_rssi_thold);
+ __field(s32, cqm_rssi_hyst);
+ __field(u32, channel_width);
+ __field(u32, channel_cfreq1);
+ __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt);
+ __field(bool, arp_filter_enabled);
+ __field(bool, qos);
+ __field(bool, idle);
+ __field(bool, ps);
+ __dynamic_array(u8, ssid, info->ssid_len);
+ __field(bool, hidden_ssid);
+ __field(int, txpower)
+ __field(u8, p2p_ctwindow)
+ __field(bool, p2p_oppps)
),
TP_fast_assign(
@@ -323,17 +359,36 @@ TRACE_EVENT(drv_bss_info_changed,
__entry->changed = changed;
__entry->aid = info->aid;
__entry->assoc = info->assoc;
+ __entry->ibss_joined = info->ibss_joined;
+ __entry->ibss_creator = info->ibss_creator;
__entry->shortpre = info->use_short_preamble;
__entry->cts = info->use_cts_prot;
__entry->shortslot = info->use_short_slot;
+ __entry->enable_beacon = info->enable_beacon;
__entry->dtimper = info->dtim_period;
__entry->bcnint = info->beacon_int;
__entry->assoc_cap = info->assoc_capability;
__entry->sync_tsf = info->sync_tsf;
__entry->sync_device_ts = info->sync_device_ts;
__entry->basic_rates = info->basic_rates;
- __entry->enable_beacon = info->enable_beacon;
+ memcpy(__entry->mcast_rate, info->mcast_rate,
+ sizeof(__entry->mcast_rate));
__entry->ht_operation_mode = info->ht_operation_mode;
+ __entry->cqm_rssi_thold = info->cqm_rssi_thold;
+ __entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
+ __entry->channel_width = info->chandef.width;
+ __entry->channel_cfreq1 = info->chandef.center_freq1;
+ memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
+ sizeof(u32) * info->arp_addr_cnt);
+ __entry->arp_filter_enabled = info->arp_filter_enabled;
+ __entry->qos = info->qos;
+ __entry->idle = info->idle;
+ __entry->ps = info->ps;
+ memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
+ __entry->hidden_ssid = info->hidden_ssid;
+ __entry->txpower = info->txpower;
+ __entry->p2p_ctwindow = info->p2p_ctwindow;
+ __entry->p2p_oppps = info->p2p_oppps;
),
TP_printk(
@@ -971,28 +1026,31 @@ TRACE_EVENT(drv_get_antenna,
);
TRACE_EVENT(drv_remain_on_channel,
- TP_PROTO(struct ieee80211_local *local, struct ieee80211_channel *chan,
- enum nl80211_channel_type chantype, unsigned int duration),
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_channel *chan,
+ unsigned int duration),
- TP_ARGS(local, chan, chantype, duration),
+ TP_ARGS(local, sdata, chan, duration),
TP_STRUCT__entry(
LOCAL_ENTRY
+ VIF_ENTRY
__field(int, center_freq)
- __field(int, channel_type)
__field(unsigned int, duration)
),
TP_fast_assign(
LOCAL_ASSIGN;
+ VIF_ASSIGN;
__entry->center_freq = chan->center_freq;
- __entry->channel_type = chantype;
__entry->duration = duration;
),
TP_printk(
- LOCAL_PR_FMT " freq:%dMHz duration:%dms",
- LOCAL_PR_ARG, __entry->center_freq, __entry->duration
+ LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms",
+ LOCAL_PR_ARG, VIF_PR_ARG,
+ __entry->center_freq, __entry->duration
)
);
@@ -1001,34 +1059,6 @@ DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel,
TP_ARGS(local)
);
-TRACE_EVENT(drv_offchannel_tx,
- TP_PROTO(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int wait),
-
- TP_ARGS(local, skb, chan, channel_type, wait),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- __field(int, center_freq)
- __field(int, channel_type)
- __field(unsigned int, wait)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- __entry->center_freq = chan->center_freq;
- __entry->channel_type = channel_type;
- __entry->wait = wait;
- ),
-
- TP_printk(
- LOCAL_PR_FMT " freq:%dMHz, wait:%dms",
- LOCAL_PR_ARG, __entry->center_freq, __entry->wait
- )
-);
-
TRACE_EVENT(drv_set_ringparam,
TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx),
@@ -1256,6 +1286,146 @@ DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
TP_ARGS(local, sdata)
);
+DECLARE_EVENT_CLASS(local_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx),
+
+ TP_ARGS(local, ctx),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ CHANCTX_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ CHANCTX_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT CHANCTX_PR_FMT,
+ LOCAL_PR_ARG, CHANCTX_PR_ARG
+ )
+);
+
+DEFINE_EVENT(local_chanctx, drv_add_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx),
+ TP_ARGS(local, ctx)
+);
+
+DEFINE_EVENT(local_chanctx, drv_remove_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx),
+ TP_ARGS(local, ctx)
+);
+
+TRACE_EVENT(drv_change_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx,
+ u32 changed),
+
+ TP_ARGS(local, ctx, changed),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ CHANCTX_ENTRY
+ __field(u32, changed)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ CHANCTX_ASSIGN;
+ __entry->changed = changed;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT CHANCTX_PR_FMT " changed:%#x",
+ LOCAL_PR_ARG, CHANCTX_PR_ARG, __entry->changed
+ )
+);
+
+DECLARE_EVENT_CLASS(local_sdata_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx),
+
+ TP_ARGS(local, sdata, ctx),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ CHANCTX_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ CHANCTX_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT CHANCTX_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG, CHANCTX_PR_ARG
+ )
+);
+
+DEFINE_EVENT(local_sdata_chanctx, drv_assign_vif_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx),
+ TP_ARGS(local, sdata, ctx)
+);
+
+DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_chanctx *ctx),
+ TP_ARGS(local, sdata, ctx)
+);
+
+TRACE_EVENT(drv_start_ap,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_bss_conf *info),
+
+ TP_ARGS(local, sdata, info),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(u8, dtimper)
+ __field(u16, bcnint)
+ __dynamic_array(u8, ssid, info->ssid_len);
+ __field(bool, hidden_ssid);
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->dtimper = info->dtim_period;
+ __entry->bcnint = info->beacon_int;
+ memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
+ __entry->hidden_ssid = info->hidden_ssid;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG
+ )
+);
+
+DEFINE_EVENT(local_sdata_evt, drv_stop_ap,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+ TP_ARGS(local, sdata)
+);
+
+DEFINE_EVENT(local_only_evt, drv_restart_complete,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
+);
+
/*
* Tracing for API calls that drivers call.
*/
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b858ebe41fda..e9eadc40c09c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -324,22 +324,20 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
- /*
- * virtual interfaces are protected by RCU
- */
- rcu_read_lock();
-
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- struct ieee80211_if_ap *ap;
- if (sdata->vif.type != NL80211_IFTYPE_AP)
+ struct ps_data *ps;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ ps = &sdata->u.ap.ps;
+ else
continue;
- ap = &sdata->u.ap;
- skb = skb_dequeue(&ap->ps_bc_buf);
+
+ skb = skb_dequeue(&ps->bc_buf);
if (skb) {
purged++;
dev_kfree_skb(skb);
}
- total += skb_queue_len(&ap->ps_bc_buf);
+ total += skb_queue_len(&ps->bc_buf);
}
/*
@@ -360,8 +358,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
}
}
- rcu_read_unlock();
-
local->total_ps_buffered = total;
ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
}
@@ -371,6 +367,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+ struct ps_data *ps;
/*
* broadcast/multicast frame
@@ -380,16 +377,24 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
* This is done either by the hardware or us.
*/
- /* powersaving STAs only in AP/VLAN mode */
- if (!tx->sdata->bss)
+ /* powersaving STAs currently only in AP/VLAN mode */
+ if (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
+ tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ if (!tx->sdata->bss)
+ return TX_CONTINUE;
+
+ ps = &tx->sdata->bss->ps;
+ } else {
return TX_CONTINUE;
+ }
+
/* no buffering for ordered frames */
if (ieee80211_has_order(hdr->frame_control))
return TX_CONTINUE;
/* no stations in PS mode */
- if (!atomic_read(&tx->sdata->bss->num_sta_ps))
+ if (!atomic_read(&ps->num_sta_ps))
return TX_CONTINUE;
info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
@@ -404,14 +409,14 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
purge_old_ps_buffers(tx->local);
- if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
+ if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
ps_dbg(tx->sdata,
"BC TX buffer full - dropping the oldest frame\n");
- dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
+ dev_kfree_skb(skb_dequeue(&ps->bc_buf));
} else
tx->local->total_ps_buffered++;
- skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+ skb_queue_tail(&ps->bc_buf, tx->skb);
return TX_QUEUED;
}
@@ -951,7 +956,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
fragnum = 0;
skb_queue_walk(&tx->skbs, skb) {
- int next_len;
const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
hdr = (void *)skb->data;
@@ -970,7 +974,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
hdr->frame_control &= ~morefrags;
- next_len = 0;
}
hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
fragnum++;
@@ -1372,7 +1375,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, bool txpending)
+ struct sk_buff *skb, bool txpending,
+ enum ieee80211_band band)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_data tx;
@@ -1386,20 +1390,18 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
return true;
}
- rcu_read_lock();
-
/* initialises tx */
led_len = skb->len;
res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
if (unlikely(res_prepare == TX_DROP)) {
ieee80211_free_txskb(&local->hw, skb);
- goto out;
+ return true;
} else if (unlikely(res_prepare == TX_QUEUED)) {
- goto out;
+ return true;
}
- info->band = local->hw.conf.channel->band;
+ info->band = band;
/* set up hw_queue value early */
if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
@@ -1410,8 +1412,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
if (!invoke_tx_handlers(&tx))
result = __ieee80211_tx(local, &tx.skbs, led_len,
tx.sta, txpending);
- out:
- rcu_read_unlock();
+
return result;
}
@@ -1446,7 +1447,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
return 0;
}
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+ enum ieee80211_band band)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1454,8 +1456,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
int headroom;
bool may_encrypt;
- rcu_read_lock();
-
may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
headroom = local->tx_headroom;
@@ -1466,7 +1466,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
ieee80211_free_txskb(&local->hw, skb);
- rcu_read_unlock();
return;
}
@@ -1478,13 +1477,11 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
!is_multicast_ether_addr(hdr->addr1) &&
mesh_nexthop_resolve(skb, sdata)) {
/* skb queued: don't free */
- rcu_read_unlock();
return;
}
ieee80211_set_qos_hdr(sdata, skb);
- ieee80211_tx(sdata, skb, false);
- rcu_read_unlock();
+ ieee80211_tx(sdata, skb, false, band);
}
static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
@@ -1574,7 +1571,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_channel *chan = local->hw.conf.channel;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_channel *chan;
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1583,26 +1581,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
u16 len_rthdr;
int hdrlen;
- /*
- * Frame injection is not allowed if beaconing is not allowed
- * or if we need radar detection. Beaconing is usually not allowed when
- * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
- * Passive scan is also used in world regulatory domains where
- * your country is not known and as such it should be treated as
- * NO TX unless the channel is explicitly allowed in which case
- * your current regulatory domain would not have the passive scan
- * flag.
- *
- * Since AP mode uses monitor interfaces to inject/TX management
- * frames we can make AP mode the exception to this rule once it
- * supports radar detection as its implementation can deal with
- * 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)))
- goto fail;
-
/* check for not even having the fixed radiotap header part */
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
goto fail; /* too short to be possibly valid */
@@ -1688,11 +1666,45 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
}
}
- ieee80211_xmit(sdata, skb);
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf) {
+ tmp_sdata = rcu_dereference(local->monitor_sdata);
+ if (tmp_sdata)
+ chanctx_conf =
+ rcu_dereference(tmp_sdata->vif.chanctx_conf);
+ }
+ if (!chanctx_conf)
+ goto fail_rcu;
+
+ chan = chanctx_conf->def.chan;
+
+ /*
+ * Frame injection is not allowed if beaconing is not allowed
+ * or if we need radar detection. Beaconing is usually not allowed when
+ * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
+ * Passive scan is also used in world regulatory domains where
+ * your country is not known and as such it should be treated as
+ * NO TX unless the channel is explicitly allowed in which case
+ * your current regulatory domain would not have the passive scan
+ * flag.
+ *
+ * Since AP mode uses monitor interfaces to inject/TX management
+ * frames we can make AP mode the exception to this rule once it
+ * supports radar detection as its implementation can deal with
+ * 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)))
+ goto fail_rcu;
+
+ ieee80211_xmit(sdata, skb, chan->band);
rcu_read_unlock();
return NETDEV_TX_OK;
+fail_rcu:
+ rcu_read_unlock();
fail:
dev_kfree_skb(skb);
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
@@ -1734,6 +1746,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
bool multicast;
u32 info_flags = 0;
u16 info_id = 0;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_sub_if_data *ap_sdata;
+ enum ieee80211_band band;
if (unlikely(skb->len < ETH_HLEN))
goto fail;
@@ -1743,9 +1758,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
+ rcu_read_lock();
+
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
- rcu_read_lock();
sta = rcu_dereference(sdata->u.vlan.sta);
if (sta) {
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@@ -1758,7 +1774,12 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = test_sta_flag(sta, WLAN_STA_WME);
}
- rcu_read_unlock();
+ ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+ u.ap);
+ chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto fail_rcu;
+ band = chanctx_conf->def.chan->band;
if (sta)
break;
/* fall through */
@@ -1769,6 +1790,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 24;
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto fail_rcu;
+ band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_WDS:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@@ -1778,15 +1804,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
+ /*
+ * This is the exception! WDS style interfaces are prohibited
+ * when channel contexts are in used so this must be valid
+ */
+ band = local->hw.conf.channel->band;
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.mesh.mshstats.dropped_frames_ttl++;
- goto fail;
+ goto fail_rcu;
}
- rcu_read_lock();
+
if (!is_multicast_ether_addr(skb->data)) {
mpath = mesh_path_lookup(skb->data, sdata);
if (!mpath)
@@ -1803,7 +1834,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
!(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
skb->data, skb->data + ETH_ALEN);
- rcu_read_unlock();
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
sdata, NULL, NULL);
} else {
@@ -1819,7 +1849,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
mesh_da = mppath->mpp;
else if (mpath)
mesh_da = mpath->dst;
- rcu_read_unlock();
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
mesh_da, sdata->vif.addr);
@@ -1839,13 +1868,16 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
skb->data + ETH_ALEN);
}
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto fail_rcu;
+ band = chanctx_conf->def.chan->band;
break;
#endif
case NL80211_IFTYPE_STATION:
if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
bool tdls_peer = false;
- rcu_read_lock();
sta = sta_info_get(sdata, skb->data);
if (sta) {
authorized = test_sta_flag(sta,
@@ -1856,7 +1888,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
tdls_auth = test_sta_flag(sta,
WLAN_STA_TDLS_PEER_AUTH);
}
- rcu_read_unlock();
/*
* If the TDLS link is enabled, send everything
@@ -1871,7 +1902,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
if (tdls_direct) {
/* link during setup - throw out frames to peer */
if (!tdls_auth)
- goto fail;
+ goto fail_rcu;
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1896,6 +1927,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr3, skb->data, ETH_ALEN);
hdrlen = 24;
}
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto fail_rcu;
+ band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */
@@ -1903,9 +1938,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
hdrlen = 24;
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto fail_rcu;
+ band = chanctx_conf->def.chan->band;
break;
default:
- goto fail;
+ goto fail_rcu;
}
/*
@@ -1915,13 +1954,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
*/
multicast = is_multicast_ether_addr(hdr.addr1);
if (!multicast) {
- rcu_read_lock();
sta = sta_info_get(sdata, hdr.addr1);
if (sta) {
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = test_sta_flag(sta, WLAN_STA_WME);
}
- rcu_read_unlock();
}
/* For mesh, the use of the QoS header is mandatory */
@@ -1949,7 +1986,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
- goto fail;
+ goto fail_rcu;
}
if (unlikely(!multicast && skb->sk &&
@@ -2004,7 +2041,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
kfree_skb(tmp_skb);
if (!skb)
- goto fail;
+ goto fail_rcu;
}
hdr.frame_control = fc;
@@ -2052,7 +2089,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
head_need = max_t(int, 0, head_need);
if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
ieee80211_free_txskb(&local->hw, skb);
- return NETDEV_TX_OK;
+ skb = NULL;
+ goto fail_rcu;
}
}
@@ -2104,10 +2142,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
info->flags = info_flags;
info->ack_frame_id = info_id;
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, band);
+ rcu_read_unlock();
return NETDEV_TX_OK;
+ fail_rcu:
+ rcu_read_unlock();
fail:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
@@ -2142,11 +2183,18 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
struct sta_info *sta;
struct ieee80211_hdr *hdr;
bool result;
+ struct ieee80211_chanctx_conf *chanctx_conf;
sdata = vif_to_sdata(info->control.vif);
if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
- result = ieee80211_tx(sdata, skb, true);
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (unlikely(!chanctx_conf)) {
+ dev_kfree_skb(skb);
+ return true;
+ }
+ result = ieee80211_tx(sdata, skb, true,
+ chanctx_conf->def.chan->band);
} else {
struct sk_buff_head skbs;
@@ -2214,9 +2262,8 @@ void ieee80211_tx_pending(unsigned long data)
/* functions for drivers to get certain frames */
static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_if_ap *bss,
- struct sk_buff *skb,
- struct beacon_data *beacon)
+ struct ps_data *ps,
+ struct sk_buff *skb)
{
u8 *pos, *tim;
int aid0 = 0;
@@ -2224,27 +2271,27 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
/* Generate bitmap for TIM only if there are any STAs in power save
* mode. */
- if (atomic_read(&bss->num_sta_ps) > 0)
+ if (atomic_read(&ps->num_sta_ps) > 0)
/* in the hope that this is faster than
* checking byte-for-byte */
- have_bits = !bitmap_empty((unsigned long*)bss->tim,
+ have_bits = !bitmap_empty((unsigned long*)ps->tim,
IEEE80211_MAX_AID+1);
- if (bss->dtim_count == 0)
- bss->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
+ if (ps->dtim_count == 0)
+ ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
else
- bss->dtim_count--;
+ ps->dtim_count--;
tim = pos = (u8 *) skb_put(skb, 6);
*pos++ = WLAN_EID_TIM;
*pos++ = 4;
- *pos++ = bss->dtim_count;
+ *pos++ = ps->dtim_count;
*pos++ = sdata->vif.bss_conf.dtim_period;
- if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
+ if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf))
aid0 = 1;
- bss->dtim_bc_mc = aid0 == 1;
+ ps->dtim_bc_mc = aid0 == 1;
if (have_bits) {
/* Find largest even number N1 so that bits numbered 1 through
@@ -2252,14 +2299,14 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
* (N2 + 1) x 8 through 2007 are 0. */
n1 = 0;
for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
- if (bss->tim[i]) {
+ if (ps->tim[i]) {
n1 = i & 0xfe;
break;
}
}
n2 = n1;
for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
- if (bss->tim[i]) {
+ if (ps->tim[i]) {
n2 = i;
break;
}
@@ -2269,7 +2316,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
*pos++ = n1 | aid0;
/* Part Virt Bitmap */
skb_put(skb, n2 - n1);
- memcpy(pos, bss->tim + n1, n2 - n1 + 1);
+ memcpy(pos, ps->tim + n1, n2 - n1 + 1);
tim[1] = n2 - n1 + 4;
} else {
@@ -2286,16 +2333,16 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
struct ieee80211_tx_info *info;
struct ieee80211_sub_if_data *sdata = NULL;
- struct ieee80211_if_ap *ap = NULL;
- struct beacon_data *beacon;
- enum ieee80211_band band = local->oper_channel->band;
+ enum ieee80211_band band;
struct ieee80211_tx_rate_control txrc;
+ struct ieee80211_chanctx_conf *chanctx_conf;
rcu_read_lock();
sdata = vif_to_sdata(vif);
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!ieee80211_sdata_running(sdata))
+ if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
goto out;
if (tim_offset)
@@ -2304,8 +2351,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
*tim_length = 0;
if (sdata->vif.type == NL80211_IFTYPE_AP) {
- ap = &sdata->u.ap;
- beacon = rcu_dereference(ap->beacon);
+ struct ieee80211_if_ap *ap = &sdata->u.ap;
+ struct beacon_data *beacon = rcu_dereference(ap->beacon);
+
if (beacon) {
/*
* headroom, head length,
@@ -2329,14 +2377,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
* of the tim bitmap in mac80211 and the driver.
*/
if (local->tim_in_locked_section) {
- ieee80211_beacon_add_tim(sdata, ap, skb,
- beacon);
+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
} else {
unsigned long flags;
spin_lock_irqsave(&local->tim_lock, flags);
- ieee80211_beacon_add_tim(sdata, ap, skb,
- beacon);
+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
spin_unlock_irqrestore(&local->tim_lock, flags);
}
@@ -2412,6 +2458,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
*pos++ = WLAN_EID_SSID;
*pos++ = 0x0;
+ band = chanctx_conf->def.chan->band;
+
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
mesh_add_ds_params_ie(skb, sdata) ||
ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
@@ -2429,6 +2477,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
goto out;
}
+ band = chanctx_conf->def.chan->band;
+
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -2573,7 +2623,7 @@ EXPORT_SYMBOL(ieee80211_nullfunc_get);
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len)
+ size_t tailroom)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local;
@@ -2587,7 +2637,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
ie_ssid_len = 2 + ssid_len;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
- ie_ssid_len + ie_len);
+ ie_ssid_len + tailroom);
if (!skb)
return NULL;
@@ -2608,11 +2658,6 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
memcpy(pos, ssid, ssid_len);
pos += ssid_len;
- if (ie) {
- pos = skb_put(skb, ie_len);
- memcpy(pos, ie, ie_len);
- }
-
return skb;
}
EXPORT_SYMBOL(ieee80211_probereq_get);
@@ -2656,29 +2701,40 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
struct ieee80211_tx_data tx;
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_ap *bss = NULL;
- struct beacon_data *beacon;
+ struct ps_data *ps;
struct ieee80211_tx_info *info;
+ struct ieee80211_chanctx_conf *chanctx_conf;
sdata = vif_to_sdata(vif);
- bss = &sdata->u.ap;
rcu_read_lock();
- beacon = rcu_dereference(bss->beacon);
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+ if (!chanctx_conf)
+ goto out;
- if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
+ if (sdata->vif.type == NL80211_IFTYPE_AP) {
+ struct beacon_data *beacon =
+ rcu_dereference(sdata->u.ap.beacon);
+
+ if (!beacon || !beacon->head)
+ goto out;
+
+ ps = &sdata->u.ap.ps;
+ } else {
goto out;
+ }
- if (bss->dtim_count != 0 || !bss->dtim_bc_mc)
+ if (ps->dtim_count != 0 || !ps->dtim_bc_mc)
goto out; /* send buffered bc/mc only after DTIM beacon */
while (1) {
- skb = skb_dequeue(&bss->ps_bc_buf);
+ skb = skb_dequeue(&ps->bc_buf);
if (!skb)
goto out;
local->total_ps_buffered--;
- if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
+ if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) {
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *) skb->data;
/* more buffered multicast/broadcast frames ==> set
@@ -2696,7 +2752,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb);
tx.flags |= IEEE80211_TX_PS_BUFFERED;
- info->band = local->oper_channel->band;
+ info->band = chanctx_conf->def.chan->band;
if (invoke_tx_handlers(&tx))
skb = NULL;
@@ -2707,8 +2763,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_get_buffered_bc);
-void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, int tid)
+void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int tid,
+ enum ieee80211_band band)
{
int ac = ieee802_1d_to_ac[tid & 7];
@@ -2725,6 +2782,6 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
* requirements are that we do not come into tx with bhs on.
*/
local_bh_disable();
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, band);
local_bh_enable();
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0151ae33c4cd..f11e8c540db4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -512,7 +512,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
EXPORT_SYMBOL(ieee80211_wake_queues);
void ieee80211_iterate_active_interfaces(
- struct ieee80211_hw *hw,
+ struct ieee80211_hw *hw, u32 iter_flags,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data)
@@ -530,6 +530,9 @@ void ieee80211_iterate_active_interfaces(
default:
break;
}
+ if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
+ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+ continue;
if (ieee80211_sdata_running(sdata))
iterator(data, sdata->vif.addr,
&sdata->vif);
@@ -537,7 +540,9 @@ void ieee80211_iterate_active_interfaces(
sdata = rcu_dereference_protected(local->monitor_sdata,
lockdep_is_held(&local->iflist_mtx));
- if (sdata)
+ if (sdata &&
+ (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+ sdata->flags & IEEE80211_SDATA_IN_DRIVER))
iterator(data, sdata->vif.addr, &sdata->vif);
mutex_unlock(&local->iflist_mtx);
@@ -545,7 +550,7 @@ void ieee80211_iterate_active_interfaces(
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
void ieee80211_iterate_active_interfaces_atomic(
- struct ieee80211_hw *hw,
+ struct ieee80211_hw *hw, u32 iter_flags,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data)
@@ -563,13 +568,18 @@ void ieee80211_iterate_active_interfaces_atomic(
default:
break;
}
+ if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
+ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+ continue;
if (ieee80211_sdata_running(sdata))
iterator(data, sdata->vif.addr,
&sdata->vif);
}
sdata = rcu_dereference(local->monitor_sdata);
- if (sdata)
+ if (sdata &&
+ (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+ sdata->flags & IEEE80211_SDATA_IN_DRIVER))
iterator(data, sdata->vif.addr, &sdata->vif);
rcu_read_unlock();
@@ -769,6 +779,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
else
elem_parse_failed = true;
break;
+ case WLAN_EID_VHT_CAPABILITY:
+ if (elen >= sizeof(struct ieee80211_vht_cap))
+ elems->vht_cap_elem = (void *)pos;
+ else
+ elem_parse_failed = true;
+ break;
+ case WLAN_EID_VHT_OPERATION:
+ if (elen >= sizeof(struct ieee80211_vht_operation))
+ elems->vht_operation = (void *)pos;
+ else
+ elem_parse_failed = true;
+ break;
case WLAN_EID_MESH_ID:
elems->mesh_id = pos;
elems->mesh_id_len = elen;
@@ -837,7 +859,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
if (elem_parse_failed)
elems->parse_error = true;
else
- set_bit(id, seen_elems);
+ __set_bit(id, seen_elems);
left -= elen;
pos += elen;
@@ -860,6 +882,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_queue_params qparam;
+ struct ieee80211_chanctx_conf *chanctx_conf;
int ac;
bool use_11b, enable_qos;
int aCWmin, aCWmax;
@@ -872,8 +895,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
memset(&qparam, 0, sizeof(qparam));
- use_11b = (local->oper_channel->band == IEEE80211_BAND_2GHZ) &&
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ use_11b = (chanctx_conf &&
+ chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) &&
!(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
+ rcu_read_unlock();
/*
* By default disable QoS in STA mode for old access points, which do
@@ -952,7 +979,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
const size_t supp_rates_len,
const u8 *supp_rates)
{
- struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *chanctx_conf;
int i, have_higher_than_11mbit = 0;
/* cf. IEEE 802.11 9.2.12 */
@@ -960,11 +987,16 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
if ((supp_rates[i] & 0x7f) * 5 > 110)
have_higher_than_11mbit = 1;
- if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+ if (chanctx_conf &&
+ chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ &&
have_higher_than_11mbit)
sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
else
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
+ rcu_read_unlock();
ieee80211_set_wmm_default(sdata, true);
}
@@ -996,7 +1028,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
}
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
- u16 transaction, u16 auth_alg,
+ u16 transaction, u16 auth_alg, u16 status,
u8 *extra, size_t extra_len, const u8 *da,
const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx)
{
@@ -1021,7 +1053,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
- mgmt->u.auth.status_code = cpu_to_le16(0);
+ mgmt->u.auth.status_code = cpu_to_le16(status);
if (extra)
memcpy(skb_put(skb, extra_len), extra, extra_len);
@@ -1075,12 +1107,12 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
}
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
- const u8 *ie, size_t ie_len,
+ size_t buffer_len, const u8 *ie, size_t ie_len,
enum ieee80211_band band, u32 rate_mask,
u8 channel)
{
struct ieee80211_supported_band *sband;
- u8 *pos;
+ u8 *pos = buffer, *end = buffer + buffer_len;
size_t offset = 0, noffset;
int supp_rates_len, i;
u8 rates[32];
@@ -1091,8 +1123,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
if (WARN_ON_ONCE(!sband))
return 0;
- pos = buffer;
-
num_rates = 0;
for (i = 0; i < sband->n_bitrates; i++) {
if ((BIT(i) & rate_mask) == 0)
@@ -1102,6 +1132,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
supp_rates_len = min_t(int, num_rates, 8);
+ if (end - pos < 2 + supp_rates_len)
+ goto out_err;
*pos++ = WLAN_EID_SUPP_RATES;
*pos++ = supp_rates_len;
memcpy(pos, rates, supp_rates_len);
@@ -1118,6 +1150,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
before_extrates,
ARRAY_SIZE(before_extrates),
offset);
+ if (end - pos < noffset - offset)
+ goto out_err;
memcpy(pos, ie + offset, noffset - offset);
pos += noffset - offset;
offset = noffset;
@@ -1125,6 +1159,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
ext_rates_len = num_rates - supp_rates_len;
if (ext_rates_len > 0) {
+ if (end - pos < 2 + ext_rates_len)
+ goto out_err;
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos++ = ext_rates_len;
memcpy(pos, rates + supp_rates_len, ext_rates_len);
@@ -1132,6 +1168,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
}
if (channel && sband->band == IEEE80211_BAND_2GHZ) {
+ if (end - pos < 3)
+ goto out_err;
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
*pos++ = channel;
@@ -1150,14 +1188,19 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
noffset = ieee80211_ie_split(ie, ie_len,
before_ht, ARRAY_SIZE(before_ht),
offset);
+ if (end - pos < noffset - offset)
+ goto out_err;
memcpy(pos, ie + offset, noffset - offset);
pos += noffset - offset;
offset = noffset;
}
- if (sband->ht_cap.ht_supported)
+ if (sband->ht_cap.ht_supported) {
+ if (end - pos < 2 + sizeof(struct ieee80211_ht_cap))
+ goto out_err;
pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
sband->ht_cap.cap);
+ }
/*
* If adding more here, adjust code in main.c
@@ -1167,15 +1210,23 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
/* add any remaining custom IEs */
if (ie && ie_len) {
noffset = ie_len;
+ if (end - pos < noffset - offset)
+ goto out_err;
memcpy(pos, ie + offset, noffset - offset);
pos += noffset - offset;
}
- if (sband->vht_cap.vht_supported)
+ if (sband->vht_cap.vht_supported) {
+ if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
+ goto out_err;
pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
sband->vht_cap.cap);
+ }
return pos - buffer;
+ out_err:
+ WARN_ONCE(1, "not enough space for preq IEs\n");
+ return pos - buffer;
}
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -1188,14 +1239,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- size_t buf_len;
- u8 *buf;
u8 chan_no;
-
- /* FIXME: come up with a proper value */
- buf = kmalloc(200 + ie_len, GFP_KERNEL);
- if (!buf)
- return NULL;
+ int ies_len;
/*
* Do not send DS Channel parameter for directed probe requests
@@ -1207,14 +1252,16 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
else
chan_no = ieee80211_frequency_to_channel(chan->center_freq);
- buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band,
- ratemask, chan_no);
-
skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
- ssid, ssid_len,
- buf, buf_len);
+ ssid, ssid_len, 100 + ie_len);
if (!skb)
- goto out;
+ return NULL;
+
+ ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb),
+ skb_tailroom(skb),
+ ie, ie_len, chan->band,
+ ratemask, chan_no);
+ skb_put(skb, ies_len);
if (dst) {
mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -1224,9 +1271,6 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- out:
- kfree(buf);
-
return skb;
}
@@ -1234,7 +1278,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
u32 ratemask, bool directed, bool no_cck,
- struct ieee80211_channel *channel)
+ struct ieee80211_channel *channel, bool scan)
{
struct sk_buff *skb;
@@ -1245,7 +1289,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
if (no_cck)
IEEE80211_SKB_CB(skb)->flags |=
IEEE80211_TX_CTL_NO_CCK_RATE;
- ieee80211_tx_skb(sdata, skb);
+ if (scan)
+ ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
+ else
+ ieee80211_tx_skb(sdata, skb);
}
}
@@ -1308,6 +1355,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
{
struct ieee80211_hw *hw = &local->hw;
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_chanctx *ctx;
struct sta_info *sta;
int res, i;
@@ -1380,6 +1428,46 @@ int ieee80211_reconfig(struct ieee80211_local *local)
res = drv_add_interface(local, sdata);
}
+ /* add channel contexts */
+ if (local->use_chanctx) {
+ mutex_lock(&local->chanctx_mtx);
+ list_for_each_entry(ctx, &local->chanctx_list, list)
+ WARN_ON(drv_add_chanctx(local, ctx));
+ mutex_unlock(&local->chanctx_mtx);
+ }
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ struct ieee80211_chanctx_conf *ctx_conf;
+
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+ mutex_lock(&local->chanctx_mtx);
+ ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (ctx_conf) {
+ ctx = container_of(ctx_conf, struct ieee80211_chanctx,
+ conf);
+ drv_assign_vif_chanctx(local, sdata, ctx);
+ }
+ mutex_unlock(&local->chanctx_mtx);
+ }
+
+ sdata = rtnl_dereference(local->monitor_sdata);
+ if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) {
+ struct ieee80211_chanctx_conf *ctx_conf;
+
+ mutex_lock(&local->chanctx_mtx);
+ ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (ctx_conf) {
+ ctx = container_of(ctx_conf, struct ieee80211_chanctx,
+ conf);
+ drv_assign_vif_chanctx(local, sdata, ctx);
+ }
+ mutex_unlock(&local->chanctx_mtx);
+ }
+
/* add STAs back */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
@@ -1435,7 +1523,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
BSS_CHANGED_BSSID |
BSS_CHANGED_CQM |
BSS_CHANGED_QOS |
- BSS_CHANGED_IDLE;
+ BSS_CHANGED_IDLE |
+ BSS_CHANGED_TXPOWER;
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
@@ -1450,11 +1539,15 @@ int ieee80211_reconfig(struct ieee80211_local *local)
changed |= BSS_CHANGED_IBSS;
/* fall through */
case NL80211_IFTYPE_AP:
- changed |= BSS_CHANGED_SSID;
+ changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;
- if (sdata->vif.type == NL80211_IFTYPE_AP)
+ if (sdata->vif.type == NL80211_IFTYPE_AP) {
changed |= BSS_CHANGED_AP_PROBE_RESP;
+ if (rcu_access_pointer(sdata->u.ap.beacon))
+ drv_start_ap(local, sdata);
+ }
+
/* fall through */
case NL80211_IFTYPE_MESH_POINT:
changed |= BSS_CHANGED_BEACON |
@@ -1553,8 +1646,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
* If this is for hw restart things are still running.
* We may want to change that later, however.
*/
- if (!local->suspended)
+ if (!local->suspended) {
+ drv_restart_complete(local);
return 0;
+ }
#ifdef CONFIG_PM
/* first set suspended false, then resuming */
@@ -1617,68 +1712,24 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
-static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
- enum ieee80211_smps_mode *smps_mode)
-{
- if (ifmgd->associated) {
- *smps_mode = ifmgd->ap_smps;
-
- if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
- if (ifmgd->powersave)
- *smps_mode = IEEE80211_SMPS_DYNAMIC;
- else
- *smps_mode = IEEE80211_SMPS_OFF;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-void ieee80211_recalc_smps(struct ieee80211_local *local)
+void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata;
- enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
- int count = 0;
-
- mutex_lock(&local->iflist_mtx);
-
- /*
- * This function could be improved to handle multiple
- * interfaces better, but right now it makes any
- * non-station interfaces force SM PS to be turned
- * off. If there are multiple station interfaces it
- * could also use the best possible mode, e.g. if
- * one is in static and the other in dynamic then
- * dynamic is ok.
- */
-
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata))
- continue;
- if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
- continue;
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- goto set;
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_chanctx *chanctx;
- count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
+ mutex_lock(&local->chanctx_mtx);
- if (count > 1) {
- smps_mode = IEEE80211_SMPS_OFF;
- break;
- }
- }
+ chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
- if (smps_mode == local->smps_mode)
+ if (WARN_ON_ONCE(!chanctx_conf))
goto unlock;
- set:
- local->smps_mode = smps_mode;
- /* changed flag is auto-detected for this */
- ieee80211_hw_config(local, 0);
+ chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+ ieee80211_recalc_smps_chanctx(local, chanctx);
unlock:
- mutex_unlock(&local->iflist_mtx);
+ mutex_unlock(&local->chanctx_mtx);
}
static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
@@ -1818,8 +1869,8 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
__le32 tmp;
*pos++ = WLAN_EID_VHT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_vht_capabilities);
- memset(pos, 0, sizeof(struct ieee80211_vht_capabilities));
+ *pos++ = sizeof(struct ieee80211_vht_cap);
+ memset(pos, 0, sizeof(struct ieee80211_vht_cap));
/* capability flags */
tmp = cpu_to_le32(cap);
@@ -1834,8 +1885,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
}
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
- struct ieee80211_channel *channel,
- enum nl80211_channel_type channel_type,
+ const struct cfg80211_chan_def *chandef,
u16 prot_mode)
{
struct ieee80211_ht_operation *ht_oper;
@@ -1843,23 +1893,25 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
*pos++ = WLAN_EID_HT_OPERATION;
*pos++ = sizeof(struct ieee80211_ht_operation);
ht_oper = (struct ieee80211_ht_operation *)pos;
- ht_oper->primary_chan =
- ieee80211_frequency_to_channel(channel->center_freq);
- switch (channel_type) {
- case NL80211_CHAN_HT40MINUS:
- ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- break;
- case NL80211_CHAN_HT40PLUS:
- ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ht_oper->primary_chan = ieee80211_frequency_to_channel(
+ chandef->chan->center_freq);
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_160:
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ else
+ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
- case NL80211_CHAN_HT20:
default:
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
break;
}
if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
- channel_type != NL80211_CHAN_NO_HT &&
- channel_type != NL80211_CHAN_HT20)
+ chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
+ chandef->width != NL80211_CHAN_WIDTH_20)
ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
ht_oper->operation_mode = cpu_to_le16(prot_mode);
@@ -1873,13 +1925,17 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
return pos + sizeof(struct ieee80211_ht_operation);
}
-enum nl80211_channel_type
-ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
+void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
+ struct ieee80211_ht_operation *ht_oper,
+ struct cfg80211_chan_def *chandef)
{
enum nl80211_channel_type channel_type;
- if (!ht_oper)
- return NL80211_CHAN_NO_HT;
+ if (!ht_oper) {
+ cfg80211_chandef_create(chandef, control_chan,
+ NL80211_CHAN_NO_HT);
+ return;
+ }
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_NONE:
@@ -1895,7 +1951,7 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
channel_type = NL80211_CHAN_NO_HT;
}
- return channel_type;
+ cfg80211_chandef_create(chandef, control_chan, channel_type);
}
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
@@ -1977,3 +2033,84 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif)
return ifmgd->ave_beacon_signal;
}
EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
+
+u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs)
+{
+ if (!mcs)
+ return 1;
+
+ /* TODO: consider rx_highest */
+
+ if (mcs->rx_mask[3])
+ return 4;
+ if (mcs->rx_mask[2])
+ return 3;
+ if (mcs->rx_mask[1])
+ return 2;
+ return 1;
+}
+
+/**
+ * ieee80211_calculate_rx_timestamp - calculate timestamp in frame
+ * @local: mac80211 hw info struct
+ * @status: RX status
+ * @mpdu_len: total MPDU length (including FCS)
+ * @mpdu_offset: offset into MPDU to calculate timestamp at
+ *
+ * This function calculates the RX timestamp at the given MPDU offset, taking
+ * into account what the RX timestamp was. An offset of 0 will just normalize
+ * the timestamp to TSF at beginning of MPDU reception.
+ */
+u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status,
+ unsigned int mpdu_len,
+ unsigned int mpdu_offset)
+{
+ u64 ts = status->mactime;
+ struct rate_info ri;
+ u16 rate;
+
+ if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
+ return 0;
+
+ memset(&ri, 0, sizeof(ri));
+
+ /* Fill cfg80211 rate info */
+ if (status->flag & RX_FLAG_HT) {
+ ri.mcs = status->rate_idx;
+ ri.flags |= RATE_INFO_FLAGS_MCS;
+ if (status->flag & RX_FLAG_40MHZ)
+ ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (status->flag & RX_FLAG_SHORT_GI)
+ ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ } else if (status->flag & RX_FLAG_VHT) {
+ ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
+ ri.mcs = status->rate_idx;
+ ri.nss = status->vht_nss;
+ if (status->flag & RX_FLAG_40MHZ)
+ ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ if (status->flag & RX_FLAG_80MHZ)
+ ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
+ if (status->flag & RX_FLAG_80P80MHZ)
+ ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
+ if (status->flag & RX_FLAG_160MHZ)
+ ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
+ if (status->flag & RX_FLAG_SHORT_GI)
+ ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ } else {
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[status->band];
+ ri.legacy = sband->bitrates[status->rate_idx].bitrate;
+ }
+
+ rate = cfg80211_calculate_bitrate(&ri);
+
+ /* rewind from end of MPDU */
+ if (status->flag & RX_FLAG_MACTIME_END)
+ ts -= mpdu_len * 8 * 10 / rate;
+
+ ts += mpdu_offset * 8 * 10 / rate;
+
+ return ts;
+}
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
new file mode 100644
index 000000000000..f311388aeedf
--- /dev/null
+++ b/net/mac80211/vht.c
@@ -0,0 +1,35 @@
+/*
+ * VHT handling
+ *
+ * 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/ieee80211.h>
+#include <linux/export.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+
+
+void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_vht_cap *vht_cap_ie,
+ struct ieee80211_sta_vht_cap *vht_cap)
+{
+ if (WARN_ON_ONCE(!vht_cap))
+ return;
+
+ memset(vht_cap, 0, sizeof(*vht_cap));
+
+ if (!vht_cap_ie || !sband->vht_cap.vht_supported)
+ return;
+
+ vht_cap->vht_supported = true;
+
+ vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info);
+
+ /* Copy peer MCS info, the driver might need them. */
+ memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs,
+ sizeof(struct ieee80211_vht_mcs_info));
+}
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index cea06e9f26f4..906f00cd6d2f 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -160,31 +160,37 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
return ieee80211_downgrade_queue(sdata, skb);
}
+/**
+ * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
+ *
+ * @sdata: local subif
+ * @skb: packet to be updated
+ */
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ u8 *p;
+ u8 ack_policy, tid;
- /* Fill in the QoS header if there is one. */
- if (ieee80211_is_data_qos(hdr->frame_control)) {
- u8 *p = ieee80211_get_qos_ctl(hdr);
- u8 ack_policy, tid;
-
- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ if (!ieee80211_is_data_qos(hdr->frame_control))
+ return;
- /* preserve EOSP bit */
- ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
+ p = ieee80211_get_qos_ctl(hdr);
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- if (is_multicast_ether_addr(hdr->addr1) ||
- sdata->noack_map & BIT(tid)) {
- ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
- info->flags |= IEEE80211_TX_CTL_NO_ACK;
- }
+ /* preserve EOSP bit */
+ ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
- /* qos header is 2 bytes */
- *p++ = ack_policy | tid;
- *p = ieee80211_vif_is_mesh(&sdata->vif) ?
- (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
+ if (is_multicast_ether_addr(hdr->addr1) ||
+ sdata->noack_map & BIT(tid)) {
+ ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
}
+
+ /* qos header is 2 bytes */
+ *p++ = ack_policy | tid;
+ *p = ieee80211_vif_is_mesh(&sdata->vif) ?
+ (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 8bd2f5c6a56e..c175ee866ff4 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -104,7 +104,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
*/
if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) {
if (status->flag & RX_FLAG_MMIC_ERROR)
- goto mic_fail;
+ goto mic_fail_no_key;
if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
@@ -161,6 +161,9 @@ update_iv:
return RX_CONTINUE;
mic_fail:
+ rx->key->u.tkip.mic_failures++;
+
+mic_fail_no_key:
/*
* In some cases the key can be unset - e.g. a multicast packet, in
* a driver that supports HW encryption. Send up the key idx only if
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 1a4df39c722e..4e09d070995a 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -85,6 +85,7 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
if (!(priv->phy->channels_supported[page] & (1 << chan))) {
WARN_ON(1);
+ kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -98,13 +99,15 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
}
if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
- dev_kfree_skb(skb);
+ kfree_skb(skb);
return NETDEV_TX_OK;
}
work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
- if (!work)
+ if (!work) {
+ kfree_skb(skb);
return NETDEV_TX_BUSY;
+ }
INIT_WORK(&work->work, mac802154_xmit_worker);
work->skb = skb;
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index f30f6d4beea1..1191039c2b1b 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -327,8 +327,10 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
if (chan == MAC802154_CHAN_NONE ||
page >= WPAN_NUM_PAGES ||
- chan >= WPAN_NUM_CHANNELS)
+ chan >= WPAN_NUM_CHANNELS) {
+ kfree_skb(skb);
return NETDEV_TX_OK;
+ }
skb->skb_iif = dev->ifindex;
dev->stats.tx_packets++;
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 68912dadf13d..a9c488b6c50d 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -295,8 +295,6 @@ void __init netfilter_init(void)
panic("cannot create netfilter proc entry");
#endif
- if (netfilter_queue_init() < 0)
- panic("cannot initialize nf_queue");
if (netfilter_log_init() < 0)
panic("cannot initialize nf_log");
}
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 778465f217fa..6d6d8f2b033e 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -28,9 +28,10 @@ static LIST_HEAD(ip_set_type_list); /* all registered set types */
static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
-static struct ip_set **ip_set_list; /* all individual sets */
+static struct ip_set * __rcu *ip_set_list; /* all individual sets */
static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
+#define IP_SET_INC 64
#define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
static unsigned int max_sets;
@@ -42,6 +43,12 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
MODULE_DESCRIPTION("core IP set support");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
+/* When the nfnl mutex is held: */
+#define nfnl_dereference(p) \
+ rcu_dereference_protected(p, 1)
+#define nfnl_set(id) \
+ nfnl_dereference(ip_set_list)[id]
+
/*
* The set types are implemented in modules and registered set types
* can be found in ip_set_type_list. Adding/deleting types is
@@ -321,19 +328,19 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
*/
static inline void
-__ip_set_get(ip_set_id_t index)
+__ip_set_get(struct ip_set *set)
{
write_lock_bh(&ip_set_ref_lock);
- ip_set_list[index]->ref++;
+ set->ref++;
write_unlock_bh(&ip_set_ref_lock);
}
static inline void
-__ip_set_put(ip_set_id_t index)
+__ip_set_put(struct ip_set *set)
{
write_lock_bh(&ip_set_ref_lock);
- BUG_ON(ip_set_list[index]->ref == 0);
- ip_set_list[index]->ref--;
+ BUG_ON(set->ref == 0);
+ set->ref--;
write_unlock_bh(&ip_set_ref_lock);
}
@@ -344,12 +351,25 @@ __ip_set_put(ip_set_id_t index)
* so it can't be destroyed (or changed) under our foot.
*/
+static inline struct ip_set *
+ip_set_rcu_get(ip_set_id_t index)
+{
+ struct ip_set *set;
+
+ rcu_read_lock();
+ /* ip_set_list itself needs to be protected */
+ set = rcu_dereference(ip_set_list)[index];
+ rcu_read_unlock();
+
+ return set;
+}
+
int
ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par,
const struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_list[index];
+ struct ip_set *set = ip_set_rcu_get(index);
int ret = 0;
BUG_ON(set == NULL);
@@ -388,7 +408,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par,
const struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_list[index];
+ struct ip_set *set = ip_set_rcu_get(index);
int ret;
BUG_ON(set == NULL);
@@ -411,7 +431,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par,
const struct ip_set_adt_opt *opt)
{
- struct ip_set *set = ip_set_list[index];
+ struct ip_set *set = ip_set_rcu_get(index);
int ret = 0;
BUG_ON(set == NULL);
@@ -440,14 +460,17 @@ ip_set_get_byname(const char *name, struct ip_set **set)
ip_set_id_t i, index = IPSET_INVALID_ID;
struct ip_set *s;
+ rcu_read_lock();
for (i = 0; i < ip_set_max; i++) {
- s = ip_set_list[i];
+ s = rcu_dereference(ip_set_list)[i];
if (s != NULL && STREQ(s->name, name)) {
- __ip_set_get(i);
+ __ip_set_get(s);
index = i;
*set = s;
+ break;
}
}
+ rcu_read_unlock();
return index;
}
@@ -462,8 +485,13 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname);
void
ip_set_put_byindex(ip_set_id_t index)
{
- if (ip_set_list[index] != NULL)
- __ip_set_put(index);
+ struct ip_set *set;
+
+ rcu_read_lock();
+ set = rcu_dereference(ip_set_list)[index];
+ if (set != NULL)
+ __ip_set_put(set);
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ip_set_put_byindex);
@@ -477,7 +505,7 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex);
const char *
ip_set_name_byindex(ip_set_id_t index)
{
- const struct ip_set *set = ip_set_list[index];
+ const struct ip_set *set = ip_set_rcu_get(index);
BUG_ON(set == NULL);
BUG_ON(set->ref == 0);
@@ -501,11 +529,18 @@ EXPORT_SYMBOL_GPL(ip_set_name_byindex);
ip_set_id_t
ip_set_nfnl_get(const char *name)
{
+ ip_set_id_t i, index = IPSET_INVALID_ID;
struct ip_set *s;
- ip_set_id_t index;
nfnl_lock();
- index = ip_set_get_byname(name, &s);
+ for (i = 0; i < ip_set_max; i++) {
+ s = nfnl_set(i);
+ if (s != NULL && STREQ(s->name, name)) {
+ __ip_set_get(s);
+ index = i;
+ break;
+ }
+ }
nfnl_unlock();
return index;
@@ -521,12 +556,15 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
ip_set_id_t
ip_set_nfnl_get_byindex(ip_set_id_t index)
{
+ struct ip_set *set;
+
if (index > ip_set_max)
return IPSET_INVALID_ID;
nfnl_lock();
- if (ip_set_list[index])
- __ip_set_get(index);
+ set = nfnl_set(index);
+ if (set)
+ __ip_set_get(set);
else
index = IPSET_INVALID_ID;
nfnl_unlock();
@@ -545,8 +583,11 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
void
ip_set_nfnl_put(ip_set_id_t index)
{
+ struct ip_set *set;
nfnl_lock();
- ip_set_put_byindex(index);
+ set = nfnl_set(index);
+ if (set != NULL)
+ __ip_set_put(set);
nfnl_unlock();
}
EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
@@ -603,41 +644,46 @@ static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
[IPSET_ATTR_DATA] = { .type = NLA_NESTED },
};
-static ip_set_id_t
-find_set_id(const char *name)
+static struct ip_set *
+find_set_and_id(const char *name, ip_set_id_t *id)
{
- ip_set_id_t i, index = IPSET_INVALID_ID;
- const struct ip_set *set;
+ struct ip_set *set = NULL;
+ ip_set_id_t i;
- for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
- set = ip_set_list[i];
- if (set != NULL && STREQ(set->name, name))
- index = i;
+ *id = IPSET_INVALID_ID;
+ for (i = 0; i < ip_set_max; i++) {
+ set = nfnl_set(i);
+ if (set != NULL && STREQ(set->name, name)) {
+ *id = i;
+ break;
+ }
}
- return index;
+ return (*id == IPSET_INVALID_ID ? NULL : set);
}
static inline struct ip_set *
find_set(const char *name)
{
- ip_set_id_t index = find_set_id(name);
+ ip_set_id_t id;
- return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
+ return find_set_and_id(name, &id);
}
static int
find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
{
+ struct ip_set *s;
ip_set_id_t i;
*index = IPSET_INVALID_ID;
for (i = 0; i < ip_set_max; i++) {
- if (ip_set_list[i] == NULL) {
+ s = nfnl_set(i);
+ if (s == NULL) {
if (*index == IPSET_INVALID_ID)
*index = i;
- } else if (STREQ(name, ip_set_list[i]->name)) {
+ } else if (STREQ(name, s->name)) {
/* Name clash */
- *set = ip_set_list[i];
+ *set = s;
return -EEXIST;
}
}
@@ -730,10 +776,9 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
* and check clashing.
*/
ret = find_free_id(set->name, &index, &clash);
- if (ret != 0) {
+ if (ret == -EEXIST) {
/* If this is the same set and requested, ignore error */
- if (ret == -EEXIST &&
- (flags & IPSET_FLAG_EXIST) &&
+ if ((flags & IPSET_FLAG_EXIST) &&
STREQ(set->type->name, clash->type->name) &&
set->type->family == clash->type->family &&
set->type->revision_min == clash->type->revision_min &&
@@ -741,13 +786,36 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
set->variant->same_set(set, clash))
ret = 0;
goto cleanup;
- }
+ } else if (ret == -IPSET_ERR_MAX_SETS) {
+ struct ip_set **list, **tmp;
+ ip_set_id_t i = ip_set_max + IP_SET_INC;
+
+ if (i < ip_set_max || i == IPSET_INVALID_ID)
+ /* Wraparound */
+ goto cleanup;
+
+ list = kzalloc(sizeof(struct ip_set *) * i, GFP_KERNEL);
+ if (!list)
+ goto cleanup;
+ /* nfnl mutex is held, both lists are valid */
+ tmp = nfnl_dereference(ip_set_list);
+ memcpy(list, tmp, sizeof(struct ip_set *) * ip_set_max);
+ rcu_assign_pointer(ip_set_list, list);
+ /* Make sure all current packets have passed through */
+ synchronize_net();
+ /* Use new list */
+ index = ip_set_max;
+ ip_set_max = i;
+ kfree(tmp);
+ ret = 0;
+ } else if (ret)
+ goto cleanup;
/*
* Finally! Add our shiny new set to the list, and be done.
*/
pr_debug("create: '%s' created with index %u!\n", set->name, index);
- ip_set_list[index] = set;
+ nfnl_set(index) = set;
return ret;
@@ -772,10 +840,10 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
static void
ip_set_destroy_set(ip_set_id_t index)
{
- struct ip_set *set = ip_set_list[index];
+ struct ip_set *set = nfnl_set(index);
pr_debug("set: %s\n", set->name);
- ip_set_list[index] = NULL;
+ nfnl_set(index) = NULL;
/* Must call it without holding any lock */
set->variant->destroy(set);
@@ -788,6 +856,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const attr[])
{
+ struct ip_set *s;
ip_set_id_t i;
int ret = 0;
@@ -807,22 +876,24 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
read_lock_bh(&ip_set_ref_lock);
if (!attr[IPSET_ATTR_SETNAME]) {
for (i = 0; i < ip_set_max; i++) {
- if (ip_set_list[i] != NULL && ip_set_list[i]->ref) {
+ s = nfnl_set(i);
+ if (s != NULL && s->ref) {
ret = -IPSET_ERR_BUSY;
goto out;
}
}
read_unlock_bh(&ip_set_ref_lock);
for (i = 0; i < ip_set_max; i++) {
- if (ip_set_list[i] != NULL)
+ s = nfnl_set(i);
+ if (s != NULL)
ip_set_destroy_set(i);
}
} else {
- i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (i == IPSET_INVALID_ID) {
+ s = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &i);
+ if (s == NULL) {
ret = -ENOENT;
goto out;
- } else if (ip_set_list[i]->ref) {
+ } else if (s->ref) {
ret = -IPSET_ERR_BUSY;
goto out;
}
@@ -853,21 +924,24 @@ ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const attr[])
{
+ struct ip_set *s;
ip_set_id_t i;
if (unlikely(protocol_failed(attr)))
return -IPSET_ERR_PROTOCOL;
if (!attr[IPSET_ATTR_SETNAME]) {
- for (i = 0; i < ip_set_max; i++)
- if (ip_set_list[i] != NULL)
- ip_set_flush_set(ip_set_list[i]);
+ for (i = 0; i < ip_set_max; i++) {
+ s = nfnl_set(i);
+ if (s != NULL)
+ ip_set_flush_set(s);
+ }
} else {
- i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (i == IPSET_INVALID_ID)
+ s = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+ if (s == NULL)
return -ENOENT;
- ip_set_flush_set(ip_set_list[i]);
+ ip_set_flush_set(s);
}
return 0;
@@ -889,7 +963,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const attr[])
{
- struct ip_set *set;
+ struct ip_set *set, *s;
const char *name2;
ip_set_id_t i;
int ret = 0;
@@ -911,8 +985,8 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
for (i = 0; i < ip_set_max; i++) {
- if (ip_set_list[i] != NULL &&
- STREQ(ip_set_list[i]->name, name2)) {
+ s = nfnl_set(i);
+ if (s != NULL && STREQ(s->name, name2)) {
ret = -IPSET_ERR_EXIST_SETNAME2;
goto out;
}
@@ -947,17 +1021,14 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
attr[IPSET_ATTR_SETNAME2] == NULL))
return -IPSET_ERR_PROTOCOL;
- from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (from_id == IPSET_INVALID_ID)
+ from = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &from_id);
+ if (from == NULL)
return -ENOENT;
- to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
- if (to_id == IPSET_INVALID_ID)
+ to = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME2]), &to_id);
+ if (to == NULL)
return -IPSET_ERR_EXIST_SETNAME2;
- from = ip_set_list[from_id];
- to = ip_set_list[to_id];
-
/* Features must not change.
* Not an artificial restriction anymore, as we must prevent
* possible loops created by swapping in setlist type of sets. */
@@ -971,8 +1042,8 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
write_lock_bh(&ip_set_ref_lock);
swap(from->ref, to->ref);
- ip_set_list[from_id] = to;
- ip_set_list[to_id] = from;
+ nfnl_set(from_id) = to;
+ nfnl_set(to_id) = from;
write_unlock_bh(&ip_set_ref_lock);
return 0;
@@ -992,7 +1063,7 @@ static int
ip_set_dump_done(struct netlink_callback *cb)
{
if (cb->args[2]) {
- pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
+ pr_debug("release set %s\n", nfnl_set(cb->args[1])->name);
ip_set_put_byindex((ip_set_id_t) cb->args[1]);
}
return 0;
@@ -1030,8 +1101,11 @@ dump_init(struct netlink_callback *cb)
*/
if (cda[IPSET_ATTR_SETNAME]) {
- index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
- if (index == IPSET_INVALID_ID)
+ struct ip_set *set;
+
+ set = find_set_and_id(nla_data(cda[IPSET_ATTR_SETNAME]),
+ &index);
+ if (set == NULL)
return -ENOENT;
dump_type = DUMP_ONE;
@@ -1081,7 +1155,7 @@ dump_last:
dump_type, dump_flags, cb->args[1]);
for (; cb->args[1] < max; cb->args[1]++) {
index = (ip_set_id_t) cb->args[1];
- set = ip_set_list[index];
+ set = nfnl_set(index);
if (set == NULL) {
if (dump_type == DUMP_ONE) {
ret = -ENOENT;
@@ -1100,7 +1174,7 @@ dump_last:
if (!cb->args[2]) {
/* Start listing: make sure set won't be destroyed */
pr_debug("reference set\n");
- __ip_set_get(index);
+ __ip_set_get(set);
}
nlh = start_msg(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, flags,
@@ -1159,7 +1233,7 @@ next_set:
release_refcount:
/* If there was an error or set is done, release set */
if (ret || !cb->args[2]) {
- pr_debug("release set %s\n", ip_set_list[index]->name);
+ pr_debug("release set %s\n", nfnl_set(index)->name);
ip_set_put_byindex(index);
cb->args[2] = 0;
}
@@ -1409,17 +1483,15 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb,
const struct ip_set *set;
struct sk_buff *skb2;
struct nlmsghdr *nlh2;
- ip_set_id_t index;
int ret = 0;
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL))
return -IPSET_ERR_PROTOCOL;
- index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (index == IPSET_INVALID_ID)
+ set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+ if (set == NULL)
return -ENOENT;
- set = ip_set_list[index];
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL)
@@ -1643,7 +1715,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
void *data;
int copylen = *len, ret = 0;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (optval != SO_IP_SET)
return -EBADF;
@@ -1684,6 +1756,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
}
case IP_SET_OP_GET_BYNAME: {
struct ip_set_req_get_set *req_get = data;
+ ip_set_id_t id;
if (*len != sizeof(struct ip_set_req_get_set)) {
ret = -EINVAL;
@@ -1691,12 +1764,14 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
}
req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
nfnl_lock();
- req_get->set.index = find_set_id(req_get->set.name);
+ find_set_and_id(req_get->set.name, &id);
+ req_get->set.index = id;
nfnl_unlock();
goto copy;
}
case IP_SET_OP_GET_BYINDEX: {
struct ip_set_req_get_set *req_get = data;
+ struct ip_set *set;
if (*len != sizeof(struct ip_set_req_get_set) ||
req_get->set.index >= ip_set_max) {
@@ -1704,9 +1779,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
goto done;
}
nfnl_lock();
- strncpy(req_get->set.name,
- ip_set_list[req_get->set.index]
- ? ip_set_list[req_get->set.index]->name : "",
+ set = nfnl_set(req_get->set.index);
+ strncpy(req_get->set.name, set ? set->name : "",
IPSET_MAXNAMELEN);
nfnl_unlock();
goto copy;
@@ -1737,6 +1811,7 @@ static struct nf_sockopt_ops so_set __read_mostly = {
static int __init
ip_set_init(void)
{
+ struct ip_set **list;
int ret;
if (max_sets)
@@ -1744,22 +1819,22 @@ ip_set_init(void)
if (ip_set_max >= IPSET_INVALID_ID)
ip_set_max = IPSET_INVALID_ID - 1;
- ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
- GFP_KERNEL);
- if (!ip_set_list)
+ list = kzalloc(sizeof(struct ip_set *) * ip_set_max, GFP_KERNEL);
+ if (!list)
return -ENOMEM;
+ rcu_assign_pointer(ip_set_list, list);
ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
if (ret != 0) {
pr_err("ip_set: cannot register with nfnetlink.\n");
- kfree(ip_set_list);
+ kfree(list);
return ret;
}
ret = nf_register_sockopt(&so_set);
if (ret != 0) {
pr_err("SO_SET registry failed: %d\n", ret);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
- kfree(ip_set_list);
+ kfree(list);
return ret;
}
@@ -1770,10 +1845,12 @@ ip_set_init(void)
static void __exit
ip_set_fini(void)
{
+ struct ip_set **list = rcu_dereference_protected(ip_set_list, 1);
+
/* There can't be any existing set */
nf_unregister_sockopt(&so_set);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
- kfree(ip_set_list);
+ kfree(list);
pr_debug("these are the famous last words\n");
}
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index 8b2cffdfdd99..0c3b1670b0d1 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -28,12 +28,11 @@ if IP_VS
config IP_VS_IPV6
bool "IPv6 support for IPVS"
depends on IPV6 = y || IP_VS = IPV6
+ select IP6_NF_IPTABLES
---help---
- Add IPv6 support to IPVS. This is incomplete and might be dangerous.
+ Add IPv6 support to IPVS.
- See http://www.mindbasket.com/ipvs for more information.
-
- Say N if unsure.
+ Say Y if unsure.
config IP_VS_DEBUG
bool "IP virtual server debugging"
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 1548df9a7524..30e764ad021f 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -308,13 +308,12 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
static int
ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off, int inverse,
- struct ip_vs_conn_param *p)
+ int inverse, struct ip_vs_conn_param *p)
{
__be16 _ports[2], *pptr;
struct net *net = skb_net(skb);
- pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+ pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
if (pptr == NULL)
return 1;
@@ -329,12 +328,11 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
struct ip_vs_conn *
ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
- const struct ip_vs_iphdr *iph,
- unsigned int proto_off, int inverse)
+ const struct ip_vs_iphdr *iph, int inverse)
{
struct ip_vs_conn_param p;
- if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
+ if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
return NULL;
return ip_vs_conn_in_get(&p);
@@ -432,12 +430,11 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
struct ip_vs_conn *
ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
- const struct ip_vs_iphdr *iph,
- unsigned int proto_off, int inverse)
+ const struct ip_vs_iphdr *iph, int inverse)
{
struct ip_vs_conn_param p;
- if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
+ if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
return NULL;
return ip_vs_conn_out_get(&p);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 58918e20f9d5..47edf5a40a59 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -222,11 +222,10 @@ ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
*/
static struct ip_vs_conn *
ip_vs_sched_persist(struct ip_vs_service *svc,
- struct sk_buff *skb,
- __be16 src_port, __be16 dst_port, int *ignored)
+ struct sk_buff *skb, __be16 src_port, __be16 dst_port,
+ int *ignored, struct ip_vs_iphdr *iph)
{
struct ip_vs_conn *cp = NULL;
- struct ip_vs_iphdr iph;
struct ip_vs_dest *dest;
struct ip_vs_conn *ct;
__be16 dport = 0; /* destination port to forward */
@@ -236,20 +235,18 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
union nf_inet_addr snet; /* source network of the client,
after masking */
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
-
/* Mask saddr with the netmask to adjust template granularity */
#ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6)
- ipv6_addr_prefix(&snet.in6, &iph.saddr.in6, svc->netmask);
+ ipv6_addr_prefix(&snet.in6, &iph->saddr.in6, svc->netmask);
else
#endif
- snet.ip = iph.saddr.ip & svc->netmask;
+ snet.ip = iph->saddr.ip & svc->netmask;
IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
"mnet %s\n",
- IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(src_port),
- IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(dst_port),
+ IP_VS_DBG_ADDR(svc->af, &iph->saddr), ntohs(src_port),
+ IP_VS_DBG_ADDR(svc->af, &iph->daddr), ntohs(dst_port),
IP_VS_DBG_ADDR(svc->af, &snet));
/*
@@ -266,8 +263,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
* is created for other persistent services.
*/
{
- int protocol = iph.protocol;
- const union nf_inet_addr *vaddr = &iph.daddr;
+ int protocol = iph->protocol;
+ const union nf_inet_addr *vaddr = &iph->daddr;
__be16 vport = 0;
if (dst_port == svc->port) {
@@ -342,14 +339,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
dport = dest->port;
flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
- && iph.protocol == IPPROTO_UDP)?
+ && iph->protocol == IPPROTO_UDP) ?
IP_VS_CONN_F_ONE_PACKET : 0;
/*
* Create a new connection according to the template
*/
- ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol, &iph.saddr,
- src_port, &iph.daddr, dst_port, &param);
+ ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
+ src_port, &iph->daddr, dst_port, &param);
cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark);
if (cp == NULL) {
@@ -392,18 +389,20 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/
struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd, int *ignored)
+ struct ip_vs_proto_data *pd, int *ignored,
+ struct ip_vs_iphdr *iph)
{
struct ip_vs_protocol *pp = pd->pp;
struct ip_vs_conn *cp = NULL;
- struct ip_vs_iphdr iph;
struct ip_vs_dest *dest;
__be16 _ports[2], *pptr;
unsigned int flags;
*ignored = 1;
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
- pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
+ /*
+ * IPv6 frags, only the first hit here.
+ */
+ pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
if (pptr == NULL)
return NULL;
@@ -423,7 +422,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* Do not schedule replies from local real server.
*/
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
- (cp = pp->conn_in_get(svc->af, skb, &iph, iph.len, 1))) {
+ (cp = pp->conn_in_get(svc->af, skb, iph, 1))) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
"Not scheduling reply for existing connection");
__ip_vs_conn_put(cp);
@@ -434,7 +433,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* Persistent service
*/
if (svc->flags & IP_VS_SVC_F_PERSISTENT)
- return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored);
+ return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored,
+ iph);
*ignored = 0;
@@ -456,7 +456,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
}
flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
- && iph.protocol == IPPROTO_UDP)?
+ && iph->protocol == IPPROTO_UDP) ?
IP_VS_CONN_F_ONE_PACKET : 0;
/*
@@ -465,9 +465,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
{
struct ip_vs_conn_param p;
- ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
- &iph.saddr, pptr[0], &iph.daddr, pptr[1],
- &p);
+ ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
+ &iph->saddr, pptr[0], &iph->daddr,
+ pptr[1], &p);
cp = ip_vs_conn_new(&p, &dest->addr,
dest->port ? dest->port : pptr[1],
flags, dest, skb->mark);
@@ -496,19 +496,16 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* no destination is available for a new connection.
*/
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd)
+ struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
{
__be16 _ports[2], *pptr;
- struct ip_vs_iphdr iph;
#ifdef CONFIG_SYSCTL
struct net *net;
struct netns_ipvs *ipvs;
int unicast;
#endif
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
-
- pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
+ pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
if (pptr == NULL) {
ip_vs_service_put(svc);
return NF_DROP;
@@ -519,10 +516,10 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
#ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6)
- unicast = ipv6_addr_type(&iph.daddr.in6) & IPV6_ADDR_UNICAST;
+ unicast = ipv6_addr_type(&iph->daddr.in6) & IPV6_ADDR_UNICAST;
else
#endif
- unicast = (inet_addr_type(net, iph.daddr.ip) == RTN_UNICAST);
+ unicast = (inet_addr_type(net, iph->daddr.ip) == RTN_UNICAST);
/* if it is fwmark-based service, the cache_bypass sysctl is up
and the destination is a non-local unicast, then create
@@ -532,7 +529,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
int ret;
struct ip_vs_conn *cp;
unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
- iph.protocol == IPPROTO_UDP)?
+ iph->protocol == IPPROTO_UDP) ?
IP_VS_CONN_F_ONE_PACKET : 0;
union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } };
@@ -542,9 +539,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
{
struct ip_vs_conn_param p;
- ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
- &iph.saddr, pptr[0],
- &iph.daddr, pptr[1], &p);
+ ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
+ &iph->saddr, pptr[0],
+ &iph->daddr, pptr[1], &p);
cp = ip_vs_conn_new(&p, &daddr, 0,
IP_VS_CONN_F_BYPASS | flags,
NULL, skb->mark);
@@ -559,7 +556,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
/* transmit the first SYN packet */
- ret = cp->packet_xmit(skb, cp, pd->pp);
+ ret = cp->packet_xmit(skb, cp, pd->pp, iph);
/* do not touch skb anymore */
atomic_inc(&cp->in_pkts);
@@ -654,14 +651,6 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
return err;
}
-#ifdef CONFIG_IP_VS_IPV6
-static inline int ip_vs_gather_frags_v6(struct sk_buff *skb, u_int32_t user)
-{
- /* TODO IPv6: Find out what to do here for IPv6 */
- return 0;
-}
-#endif
-
static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
{
#ifdef CONFIG_IP_VS_IPV6
@@ -732,10 +721,19 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, int inout)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
- unsigned int icmp_offset = sizeof(struct ipv6hdr);
- struct icmp6hdr *icmph = (struct icmp6hdr *)(skb_network_header(skb) +
- icmp_offset);
- struct ipv6hdr *ciph = (struct ipv6hdr *)(icmph + 1);
+ unsigned int icmp_offset = 0;
+ unsigned int offs = 0; /* header offset*/
+ int protocol;
+ struct icmp6hdr *icmph;
+ struct ipv6hdr *ciph;
+ unsigned short fragoffs;
+
+ ipv6_find_hdr(skb, &icmp_offset, IPPROTO_ICMPV6, &fragoffs, NULL);
+ icmph = (struct icmp6hdr *)(skb_network_header(skb) + icmp_offset);
+ offs = icmp_offset + sizeof(struct icmp6hdr);
+ ciph = (struct ipv6hdr *)(skb_network_header(skb) + offs);
+
+ protocol = ipv6_find_hdr(skb, &offs, -1, &fragoffs, NULL);
if (inout) {
iph->saddr = cp->vaddr.in6;
@@ -746,10 +744,13 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
}
/* the TCP/UDP/SCTP port */
- if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr ||
- IPPROTO_SCTP == ciph->nexthdr) {
- __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr);
+ if (!fragoffs && (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol ||
+ IPPROTO_SCTP == protocol)) {
+ __be16 *ports = (void *)(skb_network_header(skb) + offs);
+ IP_VS_DBG(11, "%s() changed port %d to %d\n", __func__,
+ ntohs(inout ? ports[1] : ports[0]),
+ ntohs(inout ? cp->vport : cp->dport));
if (inout)
ports[1] = cp->vport;
else
@@ -898,51 +899,35 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
"Checking outgoing ICMP for");
- offset += cih->ihl * 4;
-
- ip_vs_fill_iphdr(AF_INET, cih, &ciph);
+ ip_vs_fill_ip4hdr(cih, &ciph);
+ ciph.len += offset;
/* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
+ cp = pp->conn_out_get(AF_INET, skb, &ciph, 1);
if (!cp)
return NF_ACCEPT;
snet.ip = iph->saddr;
return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
- pp, offset, ihl);
+ pp, ciph.len, ihl);
}
#ifdef CONFIG_IP_VS_IPV6
static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
- unsigned int hooknum)
+ unsigned int hooknum, struct ip_vs_iphdr *ipvsh)
{
- struct ipv6hdr *iph;
struct icmp6hdr _icmph, *ic;
- struct ipv6hdr _ciph, *cih; /* The ip header contained
- within the ICMP */
- struct ip_vs_iphdr ciph;
+ struct ipv6hdr _ip6h, *ip6h; /* The ip header contained within ICMP */
+ struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
- unsigned int offset;
union nf_inet_addr snet;
+ unsigned int writable;
*related = 1;
-
- /* reassemble IP fragments */
- if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
- if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
- return NF_STOLEN;
- }
-
- iph = ipv6_hdr(skb);
- offset = sizeof(struct ipv6hdr);
- ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+ ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh);
if (ic == NULL)
return NF_DROP;
- IP_VS_DBG(12, "Outgoing ICMPv6 (%d,%d) %pI6->%pI6\n",
- ic->icmp6_type, ntohs(icmpv6_id(ic)),
- &iph->saddr, &iph->daddr);
-
/*
* Work through seeing if this is for us.
* These checks are supposed to be in an order that means easy
@@ -950,42 +935,45 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
* this means that some packets will manage to get a long way
* down this stack and then be rejected, but that's life.
*/
- if ((ic->icmp6_type != ICMPV6_DEST_UNREACH) &&
- (ic->icmp6_type != ICMPV6_PKT_TOOBIG) &&
- (ic->icmp6_type != ICMPV6_TIME_EXCEED)) {
+ if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) {
*related = 0;
return NF_ACCEPT;
}
+ /* Fragment header that is before ICMP header tells us that:
+ * it's not an error message since they can't be fragmented.
+ */
+ if (ipvsh->flags & IP6_FH_F_FRAG)
+ return NF_DROP;
+
+ IP_VS_DBG(8, "Outgoing ICMPv6 (%d,%d) %pI6c->%pI6c\n",
+ ic->icmp6_type, ntohs(icmpv6_id(ic)),
+ &ipvsh->saddr, &ipvsh->daddr);
/* Now find the contained IP header */
- offset += sizeof(_icmph);
- cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
- if (cih == NULL)
+ ciph.len = ipvsh->len + sizeof(_icmph);
+ ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
+ if (ip6h == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */
-
- pp = ip_vs_proto_get(cih->nexthdr);
+ ciph.saddr.in6 = ip6h->saddr; /* conn_out_get() handles reverse order */
+ ciph.daddr.in6 = ip6h->daddr;
+ /* skip possible IPv6 exthdrs of contained IPv6 packet */
+ ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
+ if (ciph.protocol < 0)
+ return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
+
+ pp = ip_vs_proto_get(ciph.protocol);
if (!pp)
return NF_ACCEPT;
- /* Is the embedded protocol header present? */
- /* TODO: we don't support fragmentation at the moment anyways */
- if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
- return NF_ACCEPT;
-
- IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
- "Checking outgoing ICMPv6 for");
-
- offset += sizeof(struct ipv6hdr);
-
- ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
/* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
+ cp = pp->conn_out_get(AF_INET6, skb, &ciph, 1);
if (!cp)
return NF_ACCEPT;
- snet.in6 = iph->saddr;
- return handle_response_icmp(AF_INET6, skb, &snet, cih->nexthdr, cp,
- pp, offset, sizeof(struct ipv6hdr));
+ snet.in6 = ciph.saddr.in6;
+ writable = ciph.len;
+ return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
+ pp, writable, sizeof(struct ipv6hdr));
}
#endif
@@ -1018,17 +1006,17 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
*/
static unsigned int
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
- struct ip_vs_conn *cp, int ihl)
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
struct ip_vs_protocol *pp = pd->pp;
IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
- if (!skb_make_writable(skb, ihl))
+ if (!skb_make_writable(skb, iph->len))
goto drop;
/* mangle the packet */
- if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
+ if (pp->snat_handler && !pp->snat_handler(skb, pp, cp, iph))
goto drop;
#ifdef CONFIG_IP_VS_IPV6
@@ -1115,17 +1103,22 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
if (!net_ipvs(net)->enable)
return NF_ACCEPT;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_skb(af, skb, &iph);
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
+ if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+ struct sk_buff *reasm = skb_nfct_reasm(skb);
+ /* Save fw mark for coming frags */
+ reasm->ipvs_property = 1;
+ reasm->mark = skb->mark;
+ }
if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
int related;
int verdict = ip_vs_out_icmp_v6(skb, &related,
- hooknum);
+ hooknum, &iph);
if (related)
return verdict;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
}
} else
#endif
@@ -1135,7 +1128,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
if (related)
return verdict;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
}
pd = ip_vs_proto_data_get(net, iph.protocol);
@@ -1145,39 +1137,31 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
/* reassemble IP fragments */
#ifdef CONFIG_IP_VS_IPV6
- if (af == AF_INET6) {
- if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
- if (ip_vs_gather_frags_v6(skb,
- ip_vs_defrag_user(hooknum)))
- return NF_STOLEN;
- }
-
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
- } else
+ if (af == AF_INET)
#endif
if (unlikely(ip_is_fragment(ip_hdr(skb)) && !pp->dont_defrag)) {
if (ip_vs_gather_frags(skb,
ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+ ip_vs_fill_ip4hdr(skb_network_header(skb), &iph);
}
/*
* Check if the packet belongs to an existing entry
*/
- cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
+ cp = pp->conn_out_get(af, skb, &iph, 0);
if (likely(cp))
- return handle_response(af, skb, pd, cp, iph.len);
+ return handle_response(af, skb, pd, cp, &iph);
if (sysctl_nat_icmp_send(net) &&
(pp->protocol == IPPROTO_TCP ||
pp->protocol == IPPROTO_UDP ||
pp->protocol == IPPROTO_SCTP)) {
__be16 _ports[2], *pptr;
- pptr = skb_header_pointer(skb, iph.len,
- sizeof(_ports), _ports);
+ pptr = frag_safe_skb_hp(skb, iph.len,
+ sizeof(_ports), _ports, &iph);
if (pptr == NULL)
return NF_ACCEPT; /* Not for me */
if (ip_vs_lookup_real_service(net, af, iph.protocol,
@@ -1375,13 +1359,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
"Checking incoming ICMP for");
offset2 = offset;
- offset += cih->ihl * 4;
-
- ip_vs_fill_iphdr(AF_INET, cih, &ciph);
+ ip_vs_fill_ip4hdr(cih, &ciph);
+ ciph.len += offset;
+ offset = ciph.len;
/* The embedded headers contain source and dest in reverse order.
* For IPIP this is error for request, not for reply.
*/
- cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, ipip ? 0 : 1);
+ cp = pp->conn_in_get(AF_INET, skb, &ciph, ipip ? 0 : 1);
if (!cp)
return NF_ACCEPT;
@@ -1450,7 +1434,7 @@ ignore_ipip:
ip_vs_in_stats(cp, skb);
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
offset += 2 * sizeof(__u16);
- verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum);
+ verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph);
out:
__ip_vs_conn_put(cp);
@@ -1459,38 +1443,24 @@ out:
}
#ifdef CONFIG_IP_VS_IPV6
-static int
-ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
+static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related,
+ unsigned int hooknum, struct ip_vs_iphdr *iph)
{
struct net *net = NULL;
- struct ipv6hdr *iph;
+ struct ipv6hdr _ip6h, *ip6h;
struct icmp6hdr _icmph, *ic;
- struct ipv6hdr _ciph, *cih; /* The ip header contained
- within the ICMP */
- struct ip_vs_iphdr ciph;
+ struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
- unsigned int offset, verdict;
+ unsigned int offs_ciph, writable, verdict;
*related = 1;
- /* reassemble IP fragments */
- if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
- if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
- return NF_STOLEN;
- }
-
- iph = ipv6_hdr(skb);
- offset = sizeof(struct ipv6hdr);
- ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+ ic = frag_safe_skb_hp(skb, iph->len, sizeof(_icmph), &_icmph, iph);
if (ic == NULL)
return NF_DROP;
- IP_VS_DBG(12, "Incoming ICMPv6 (%d,%d) %pI6->%pI6\n",
- ic->icmp6_type, ntohs(icmpv6_id(ic)),
- &iph->saddr, &iph->daddr);
-
/*
* Work through seeing if this is for us.
* These checks are supposed to be in an order that means easy
@@ -1498,47 +1468,71 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
* this means that some packets will manage to get a long way
* down this stack and then be rejected, but that's life.
*/
- if ((ic->icmp6_type != ICMPV6_DEST_UNREACH) &&
- (ic->icmp6_type != ICMPV6_PKT_TOOBIG) &&
- (ic->icmp6_type != ICMPV6_TIME_EXCEED)) {
+ if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) {
*related = 0;
return NF_ACCEPT;
}
+ /* Fragment header that is before ICMP header tells us that:
+ * it's not an error message since they can't be fragmented.
+ */
+ if (iph->flags & IP6_FH_F_FRAG)
+ return NF_DROP;
+
+ IP_VS_DBG(8, "Incoming ICMPv6 (%d,%d) %pI6c->%pI6c\n",
+ ic->icmp6_type, ntohs(icmpv6_id(ic)),
+ &iph->saddr, &iph->daddr);
/* Now find the contained IP header */
- offset += sizeof(_icmph);
- cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
- if (cih == NULL)
+ ciph.len = iph->len + sizeof(_icmph);
+ offs_ciph = ciph.len; /* Save ip header offset */
+ ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
+ if (ip6h == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */
+ ciph.saddr.in6 = ip6h->saddr; /* conn_in_get() handles reverse order */
+ ciph.daddr.in6 = ip6h->daddr;
+ /* skip possible IPv6 exthdrs of contained IPv6 packet */
+ ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
+ if (ciph.protocol < 0)
+ return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
net = skb_net(skb);
- pd = ip_vs_proto_data_get(net, cih->nexthdr);
+ pd = ip_vs_proto_data_get(net, ciph.protocol);
if (!pd)
return NF_ACCEPT;
pp = pd->pp;
- /* Is the embedded protocol header present? */
- /* TODO: we don't support fragmentation at the moment anyways */
- if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
+ /* Cannot handle fragmented embedded protocol */
+ if (ciph.fragoffs)
return NF_ACCEPT;
- IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
+ IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offs_ciph,
"Checking incoming ICMPv6 for");
- offset += sizeof(struct ipv6hdr);
+ /* The embedded headers contain source and dest in reverse order
+ * if not from localhost
+ */
+ cp = pp->conn_in_get(AF_INET6, skb, &ciph,
+ (hooknum == NF_INET_LOCAL_OUT) ? 0 : 1);
- ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
- /* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
if (!cp)
return NF_ACCEPT;
+ /* VS/TUN, VS/DR and LOCALNODE just let it go */
+ if ((hooknum == NF_INET_LOCAL_OUT) &&
+ (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)) {
+ __ip_vs_conn_put(cp);
+ return NF_ACCEPT;
+ }
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
- if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr ||
- IPPROTO_SCTP == cih->nexthdr)
- offset += 2 * sizeof(__u16);
- verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum);
+
+ /* Need to mangle contained IPv6 header in ICMPv6 packet */
+ writable = ciph.len;
+ if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol ||
+ IPPROTO_SCTP == ciph.protocol)
+ writable += 2 * sizeof(__u16); /* Also mangle ports */
+
+ verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, writable, hooknum, &ciph);
__ip_vs_conn_put(cp);
@@ -1574,7 +1568,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
if (unlikely((skb->pkt_type != PACKET_HOST &&
hooknum != NF_INET_LOCAL_OUT) ||
!skb_dst(skb))) {
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_skb(af, skb, &iph);
IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s"
" ignored in hook %u\n",
skb->pkt_type, iph.protocol,
@@ -1586,7 +1580,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
if (!net_ipvs(net)->enable)
return NF_ACCEPT;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_skb(af, skb, &iph);
/* Bad... Do not break raw sockets */
if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
@@ -1600,13 +1594,19 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
+ if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+ struct sk_buff *reasm = skb_nfct_reasm(skb);
+ /* Save fw mark for coming frags. */
+ reasm->ipvs_property = 1;
+ reasm->mark = skb->mark;
+ }
if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
int related;
- int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum);
+ int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum,
+ &iph);
if (related)
return verdict;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
}
} else
#endif
@@ -1616,7 +1616,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
if (related)
return verdict;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
}
/* Protocol supported? */
@@ -1627,12 +1626,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
/*
* Check if the packet belongs to an existing connection entry
*/
- cp = pp->conn_in_get(af, skb, &iph, iph.len, 0);
-
- if (unlikely(!cp)) {
+ cp = pp->conn_in_get(af, skb, &iph, 0);
+ if (unlikely(!cp) && !iph.fragoffs) {
+ /* No (second) fragments need to enter here, as nf_defrag_ipv6
+ * replayed fragment zero will already have created the cp
+ */
int v;
- if (!pp->conn_schedule(af, skb, pd, &v, &cp))
+ /* Schedule and create new connection entry into &cp */
+ if (!pp->conn_schedule(af, skb, pd, &v, &cp, &iph))
return v;
}
@@ -1640,6 +1642,14 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
/* sorry, all this trouble for a no-hit :) */
IP_VS_DBG_PKT(12, af, pp, skb, 0,
"ip_vs_in: packet continues traversal as normal");
+ if (iph.fragoffs && !skb_nfct_reasm(skb)) {
+ /* Fragment that couldn't be mapped to a conn entry
+ * and don't have any pointer to a reasm skb
+ * is missing module nf_defrag_ipv6
+ */
+ IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+ IP_VS_DBG_PKT(7, af, pp, skb, 0, "unhandled fragment");
+ }
return NF_ACCEPT;
}
@@ -1662,7 +1672,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
ip_vs_in_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
if (cp->packet_xmit)
- ret = cp->packet_xmit(skb, cp, pp);
+ ret = cp->packet_xmit(skb, cp, pp, &iph);
/* do not touch skb anymore */
else {
IP_VS_DBG_RL("warning: packet_xmit is null");
@@ -1724,6 +1734,38 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb,
#ifdef CONFIG_IP_VS_IPV6
/*
+ * AF_INET6 fragment handling
+ * Copy info from first fragment, to the rest of them.
+ */
+static unsigned int
+ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct sk_buff *reasm = skb_nfct_reasm(skb);
+ struct net *net;
+
+ /* Skip if not a "replay" from nf_ct_frag6_output or first fragment.
+ * ipvs_property is set when checking first fragment
+ * in ip_vs_in() and ip_vs_out().
+ */
+ if (reasm)
+ IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property);
+ if (!reasm || !reasm->ipvs_property)
+ return NF_ACCEPT;
+
+ net = skb_net(skb);
+ if (!net_ipvs(net)->enable)
+ return NF_ACCEPT;
+
+ /* Copy stored fw mark, saved in ip_vs_{in,out} */
+ skb->mark = reasm->mark;
+
+ return NF_ACCEPT;
+}
+
+/*
* AF_INET6 handler in NF_INET_LOCAL_IN chain
* Schedule and forward packets from remote clients
*/
@@ -1793,8 +1835,10 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
{
int r;
struct net *net;
+ struct ip_vs_iphdr iphdr;
- if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
+ ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr);
+ if (iphdr.protocol != IPPROTO_ICMPV6)
return NF_ACCEPT;
/* ipvs enabled in this netns ? */
@@ -1802,7 +1846,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
if (!net_ipvs(net)->enable)
return NF_ACCEPT;
- return ip_vs_in_icmp_v6(skb, &r, hooknum);
+ return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr);
}
#endif
@@ -1860,6 +1904,14 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.priority = 100,
},
#ifdef CONFIG_IP_VS_IPV6
+ /* After mangle & nat fetch 2:nd fragment and following */
+ {
+ .hook = ip_vs_preroute_frag6,
+ .owner = THIS_MODULE,
+ .pf = NFPROTO_IPV6,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP6_PRI_NAT_DST + 1,
+ },
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_reply6,
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index c4ee43710aab..ec664cbb119f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2339,7 +2339,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
struct ip_vs_dest_user_kern udest;
struct netns_ipvs *ipvs = net_ipvs(net);
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (cmd < IP_VS_BASE_CTL || cmd > IP_VS_SO_SET_MAX)
@@ -2632,7 +2632,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
struct netns_ipvs *ipvs = net_ipvs(net);
BUG_ON(!net);
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
return -EPERM;
if (cmd < IP_VS_BASE_CTL || cmd > IP_VS_SO_GET_MAX)
@@ -3699,6 +3699,10 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
tbl = kmemdup(vs_vars, sizeof(vs_vars), GFP_KERNEL);
if (tbl == NULL)
return -ENOMEM;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ tbl[0].procname = NULL;
} else
tbl = vs_vars;
/* Initialize sysctl defaults */
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index 8b7dca9ea422..7f3b0cc00b7a 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -215,7 +215,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dh_bucket *tbl;
struct ip_vs_iphdr iph;
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index df646ccf08a7..fdd89b9564ea 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -479,7 +479,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dest *dest = NULL;
struct ip_vs_lblc_entry *en;
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
@@ -560,6 +560,11 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
GFP_KERNEL);
if (ipvs->lblc_ctl_table == NULL)
return -ENOMEM;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ ipvs->lblc_ctl_table[0].procname = NULL;
+
} else
ipvs->lblc_ctl_table = vs_vars_table;
ipvs->sysctl_lblc_expiration = DEFAULT_EXPIRATION;
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 570e31ea427a..c03b6a3ade2f 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -649,7 +649,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dest *dest = NULL;
struct ip_vs_lblcr_entry *en;
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
@@ -754,6 +754,10 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
GFP_KERNEL);
if (ipvs->lblcr_ctl_table == NULL)
return -ENOMEM;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ ipvs->lblcr_ctl_table[0].procname = NULL;
} else
ipvs->lblcr_ctl_table = vs_vars_table;
ipvs->sysctl_lblcr_expiration = DEFAULT_EXPIRATION;
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index 022e77e1e766..c8beafd401aa 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -82,7 +82,7 @@ void
ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
{
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conntrack_tuple new_tuple;
if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) ||
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
index 1aa5cac748c4..12475ef88daf 100644
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -68,23 +68,31 @@ static int get_callid(const char *dptr, unsigned int dataoff,
static int
ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
{
+ struct sk_buff *reasm = skb_nfct_reasm(skb);
struct ip_vs_iphdr iph;
unsigned int dataoff, datalen, matchoff, matchlen;
const char *dptr;
int retc;
- ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_skb(p->af, skb, &iph);
/* Only useful with UDP */
if (iph.protocol != IPPROTO_UDP)
return -EINVAL;
+ /* todo: IPv6 fragments:
+ * I think this only should be done for the first fragment. /HS
+ */
+ if (reasm) {
+ skb = reasm;
+ dataoff = iph.thoff_reasm + sizeof(struct udphdr);
+ } else
+ dataoff = iph.len + sizeof(struct udphdr);
- /* No Data ? */
- dataoff = iph.len + sizeof(struct udphdr);
if (dataoff >= skb->len)
return -EINVAL;
-
- if ((retc=skb_linearize(skb)) < 0)
+ /* todo: Check if this will mess-up the reasm skb !!! /HS */
+ retc = skb_linearize(skb);
+ if (retc < 0)
return retc;
dptr = skb->data + dataoff;
datalen = skb->len - dataoff;
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 50d82186da87..939f7fbe9b46 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -280,17 +280,17 @@ ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,
if (ih == NULL)
sprintf(buf, "TRUNCATED");
else if (ih->nexthdr == IPPROTO_FRAGMENT)
- sprintf(buf, "%pI6->%pI6 frag", &ih->saddr, &ih->daddr);
+ sprintf(buf, "%pI6c->%pI6c frag", &ih->saddr, &ih->daddr);
else {
__be16 _ports[2], *pptr;
pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
sizeof(_ports), _ports);
if (pptr == NULL)
- sprintf(buf, "TRUNCATED %pI6->%pI6",
+ sprintf(buf, "TRUNCATED %pI6c->%pI6c",
&ih->saddr, &ih->daddr);
else
- sprintf(buf, "%pI6:%u->%pI6:%u",
+ sprintf(buf, "%pI6c:%u->%pI6c:%u",
&ih->saddr, ntohs(pptr[0]),
&ih->daddr, ntohs(pptr[1]));
}
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 5b8eb8b12c3e..5de3dd312c0f 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -57,7 +57,7 @@ ah_esp_conn_fill_param_proto(struct net *net, int af,
static struct ip_vs_conn *
ah_esp_conn_in_get(int af, const struct sk_buff *skb,
- const struct ip_vs_iphdr *iph, unsigned int proto_off,
+ const struct ip_vs_iphdr *iph,
int inverse)
{
struct ip_vs_conn *cp;
@@ -85,9 +85,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb,
static struct ip_vs_conn *
ah_esp_conn_out_get(int af, const struct sk_buff *skb,
- const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
- int inverse)
+ const struct ip_vs_iphdr *iph, int inverse)
{
struct ip_vs_conn *cp;
struct ip_vs_conn_param p;
@@ -110,7 +108,8 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
static int
ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp)
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph)
{
/*
* AH/ESP is only related traffic. Pass the packet to IP stack.
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 9f3fb751c491..746048b13ef3 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -10,28 +10,26 @@
static int
sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp)
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph)
{
struct net *net;
struct ip_vs_service *svc;
sctp_chunkhdr_t _schunkh, *sch;
sctp_sctphdr_t *sh, _sctph;
- struct ip_vs_iphdr iph;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
- sh = skb_header_pointer(skb, iph.len, sizeof(_sctph), &_sctph);
+ sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
if (sh == NULL)
return 0;
- sch = skb_header_pointer(skb, iph.len + sizeof(sctp_sctphdr_t),
+ sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
sizeof(_schunkh), &_schunkh);
if (sch == NULL)
return 0;
net = skb_net(skb);
if ((sch->type == SCTP_CID_INIT) &&
- (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
- &iph.daddr, sh->dest))) {
+ (svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+ &iph->daddr, sh->dest))) {
int ignored;
if (ip_vs_todrop(net_ipvs(net))) {
@@ -47,10 +45,10 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
* Let the virtual server select a real server for the
* incoming connection, and create a connection entry.
*/
- *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+ *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
if (!*cpp && ignored <= 0) {
if (!ignored)
- *verdict = ip_vs_leave(svc, skb, pd);
+ *verdict = ip_vs_leave(svc, skb, pd, iph);
else {
ip_vs_service_put(svc);
*verdict = NF_DROP;
@@ -64,20 +62,18 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
}
static int
-sctp_snat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
sctp_sctphdr_t *sctph;
- unsigned int sctphoff;
+ unsigned int sctphoff = iph->len;
struct sk_buff *iter;
__be32 crc32;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- sctphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- sctphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
@@ -108,20 +104,18 @@ sctp_snat_handler(struct sk_buff *skb,
}
static int
-sctp_dnat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
sctp_sctphdr_t *sctph;
- unsigned int sctphoff;
+ unsigned int sctphoff = iph->len;
struct sk_buff *iter;
__be32 crc32;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- sctphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- sctphoff = ip_hdrlen(skb);
/* csum_check requires unshared skb */
if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index cd609cc62721..9af653a75825 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -33,16 +33,14 @@
static int
tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp)
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph)
{
struct net *net;
struct ip_vs_service *svc;
struct tcphdr _tcph, *th;
- struct ip_vs_iphdr iph;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
- th = skb_header_pointer(skb, iph.len, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
if (th == NULL) {
*verdict = NF_DROP;
return 0;
@@ -50,8 +48,8 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
net = skb_net(skb);
/* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
if (th->syn &&
- (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
- &iph.daddr, th->dest))) {
+ (svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+ &iph->daddr, th->dest))) {
int ignored;
if (ip_vs_todrop(net_ipvs(net))) {
@@ -68,10 +66,10 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
* Let the virtual server select a real server for the
* incoming connection, and create a connection entry.
*/
- *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+ *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
if (!*cpp && ignored <= 0) {
if (!ignored)
- *verdict = ip_vs_leave(svc, skb, pd);
+ *verdict = ip_vs_leave(svc, skb, pd, iph);
else {
ip_vs_service_put(svc);
*verdict = NF_DROP;
@@ -128,20 +126,18 @@ tcp_partial_csum_update(int af, struct tcphdr *tcph,
static int
-tcp_snat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
struct tcphdr *tcph;
- unsigned int tcphoff;
+ unsigned int tcphoff = iph->len;
int oldlen;
int payload_csum = 0;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- tcphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- tcphoff = ip_hdrlen(skb);
oldlen = skb->len - tcphoff;
/* csum_check requires unshared skb */
@@ -208,20 +204,18 @@ tcp_snat_handler(struct sk_buff *skb,
static int
-tcp_dnat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
struct tcphdr *tcph;
- unsigned int tcphoff;
+ unsigned int tcphoff = iph->len;
int oldlen;
int payload_csum = 0;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- tcphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- tcphoff = ip_hdrlen(skb);
oldlen = skb->len - tcphoff;
/* csum_check requires unshared skb */
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 2fedb2dcb3d1..503a842c90d2 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -30,23 +30,22 @@
static int
udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp)
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph)
{
struct net *net;
struct ip_vs_service *svc;
struct udphdr _udph, *uh;
- struct ip_vs_iphdr iph;
- ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
- uh = skb_header_pointer(skb, iph.len, sizeof(_udph), &_udph);
+ /* IPv6 fragments, only first fragment will hit this */
+ uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
if (uh == NULL) {
*verdict = NF_DROP;
return 0;
}
net = skb_net(skb);
- svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
- &iph.daddr, uh->dest);
+ svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+ &iph->daddr, uh->dest);
if (svc) {
int ignored;
@@ -64,10 +63,10 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
* Let the virtual server select a real server for the
* incoming connection, and create a connection entry.
*/
- *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+ *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
if (!*cpp && ignored <= 0) {
if (!ignored)
- *verdict = ip_vs_leave(svc, skb, pd);
+ *verdict = ip_vs_leave(svc, skb, pd, iph);
else {
ip_vs_service_put(svc);
*verdict = NF_DROP;
@@ -125,20 +124,18 @@ udp_partial_csum_update(int af, struct udphdr *uhdr,
static int
-udp_snat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
struct udphdr *udph;
- unsigned int udphoff;
+ unsigned int udphoff = iph->len;
int oldlen;
int payload_csum = 0;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- udphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- udphoff = ip_hdrlen(skb);
oldlen = skb->len - udphoff;
/* csum_check requires unshared skb */
@@ -210,20 +207,18 @@ udp_snat_handler(struct sk_buff *skb,
static int
-udp_dnat_handler(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{
struct udphdr *udph;
- unsigned int udphoff;
+ unsigned int udphoff = iph->len;
int oldlen;
int payload_csum = 0;
#ifdef CONFIG_IP_VS_IPV6
- if (cp->af == AF_INET6)
- udphoff = sizeof(struct ipv6hdr);
- else
+ if (cp->af == AF_INET6 && iph->fragoffs)
+ return 1;
#endif
- udphoff = ip_hdrlen(skb);
oldlen = skb->len - udphoff;
/* csum_check requires unshared skb */
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index 08dbdd5bc18f..d6bf20d6cdbe 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -159,7 +159,7 @@ void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
svc->fwmark, msg);
#ifdef CONFIG_IP_VS_IPV6
} else if (svc->af == AF_INET6) {
- IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+ IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n",
svc->scheduler->name,
ip_vs_proto_name(svc->protocol),
&svc->addr.in6, ntohs(svc->port), msg);
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 05126521743e..e33126994628 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -228,7 +228,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_sh_bucket *tbl;
struct ip_vs_iphdr iph;
- ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index cc4c8095681a..ee6b7a9f1ec2 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -338,7 +338,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
local = __ip_vs_is_local_route6(rt);
if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) &
rt_mode)) {
- IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n",
+ IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6c\n",
local ? "local":"non-local", daddr);
dst_release(&rt->dst);
return NULL;
@@ -346,8 +346,8 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
if (local && !(rt_mode & IP_VS_RT_MODE_RDR) &&
!((ort = (struct rt6_info *) skb_dst(skb)) &&
__ip_vs_is_local_route6(ort))) {
- IP_VS_DBG_RL("Redirect from non-local address %pI6 to local "
- "requires NAT method, dest: %pI6\n",
+ IP_VS_DBG_RL("Redirect from non-local address %pI6c to local "
+ "requires NAT method, dest: %pI6c\n",
&ipv6_hdr(skb)->daddr, daddr);
dst_release(&rt->dst);
return NULL;
@@ -355,8 +355,8 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
if (unlikely(!local && (!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
ipv6_addr_type(&ipv6_hdr(skb)->saddr) &
IPV6_ADDR_LOOPBACK)) {
- IP_VS_DBG_RL("Stopping traffic from loopback address %pI6 "
- "to non-local address, dest: %pI6\n",
+ IP_VS_DBG_RL("Stopping traffic from loopback address %pI6c "
+ "to non-local address, dest: %pI6c\n",
&ipv6_hdr(skb)->saddr, daddr);
dst_release(&rt->dst);
return NULL;
@@ -427,7 +427,7 @@ do { \
*/
int
ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
/* we do not touch skb and do not need pskb ptr */
IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 1);
@@ -441,7 +441,7 @@ ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
*/
int
ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct rtable *rt; /* Route to the other host */
struct iphdr *iph = ip_hdr(skb);
@@ -496,16 +496,16 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
{
struct rt6_info *rt; /* Route to the other host */
- struct ipv6hdr *iph = ipv6_hdr(skb);
int mtu;
EnterFunction(10);
- if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0,
- IP_VS_RT_MODE_NON_LOCAL)))
+ rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr.in6, NULL, 0,
+ IP_VS_RT_MODE_NON_LOCAL);
+ if (!rt)
goto tx_error_icmp;
/* MTU checking */
@@ -516,7 +516,9 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dev = net->loopback_dev;
}
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ /* only send ICMP too big on first fragment */
+ if (!iph->fragoffs)
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
dst_release(&rt->dst);
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
@@ -559,7 +561,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
*/
int
ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct rtable *rt; /* Route to the other host */
int mtu;
@@ -592,7 +594,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (cp->flags & IP_VS_CONN_F_SYNC && local) {
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0,
@@ -629,7 +631,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error_put;
/* mangle the packet */
- if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
+ if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh))
goto tx_error_put;
ip_hdr(skb)->daddr = cp->daddr.ip;
ip_send_check(ip_hdr(skb));
@@ -677,7 +679,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
{
struct rt6_info *rt; /* Route to the other host */
int mtu;
@@ -686,10 +688,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
EnterFunction(10);
/* check if it is a connection of no-client-port */
- if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+ if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT && !iph->fragoffs)) {
__be16 _pt, *p;
- p = skb_header_pointer(skb, sizeof(struct ipv6hdr),
- sizeof(_pt), &_pt);
+ p = skb_header_pointer(skb, iph->len, sizeof(_pt), &_pt);
if (p == NULL)
goto tx_error;
ip_vs_conn_fill_cport(cp, *p);
@@ -709,7 +710,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (cp->flags & IP_VS_CONN_F_SYNC && local) {
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0,
@@ -737,7 +738,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dev = net->loopback_dev;
}
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ /* only send ICMP too big on first fragment */
+ if (!iph->fragoffs)
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
IP_VS_DBG_RL_PKT(0, AF_INET6, pp, skb, 0,
"ip_vs_nat_xmit_v6(): frag needed for");
goto tx_error_put;
@@ -751,7 +754,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error_put;
/* mangle the packet */
- if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
+ if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, iph))
goto tx_error;
ipv6_hdr(skb)->daddr = cp->daddr.in6;
@@ -812,7 +815,7 @@ tx_error_put:
*/
int
ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
struct rtable *rt; /* Route to the other host */
@@ -932,7 +935,7 @@ tx_error_put:
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct rt6_info *rt; /* Route to the other host */
struct in6_addr saddr; /* Source for tunnel */
@@ -972,7 +975,9 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dev = net->loopback_dev;
}
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ /* only send ICMP too big on first fragment */
+ if (!ipvsh->fragoffs)
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error_put;
}
@@ -1053,7 +1058,7 @@ tx_error_put:
*/
int
ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct rtable *rt; /* Route to the other host */
struct iphdr *iph = ip_hdr(skb);
@@ -1115,7 +1120,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp)
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
{
struct rt6_info *rt; /* Route to the other host */
int mtu;
@@ -1139,7 +1144,9 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dev = net->loopback_dev;
}
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ /* only send ICMP too big on first fragment */
+ if (!iph->fragoffs)
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
dst_release(&rt->dst);
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
@@ -1183,7 +1190,8 @@ tx_error:
*/
int
ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset, unsigned int hooknum)
+ struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
+ struct ip_vs_iphdr *iph)
{
struct rtable *rt; /* Route to the other host */
int mtu;
@@ -1198,7 +1206,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
translate address/port back */
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
if (cp->packet_xmit)
- rc = cp->packet_xmit(skb, cp, pp);
+ rc = cp->packet_xmit(skb, cp, pp, iph);
else
rc = NF_ACCEPT;
/* do not touch skb anymore */
@@ -1227,7 +1235,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (cp->flags & IP_VS_CONN_F_SYNC && local) {
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG(10, "%s(): "
@@ -1304,7 +1312,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset, unsigned int hooknum)
+ struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
+ struct ip_vs_iphdr *iph)
{
struct rt6_info *rt; /* Route to the other host */
int mtu;
@@ -1319,7 +1328,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
translate address/port back */
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
if (cp->packet_xmit)
- rc = cp->packet_xmit(skb, cp, pp);
+ rc = cp->packet_xmit(skb, cp, pp, iph);
else
rc = NF_ACCEPT;
/* do not touch skb anymore */
@@ -1347,7 +1356,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (cp->flags & IP_VS_CONN_F_SYNC && local) {
enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG(10, "%s(): "
@@ -1375,7 +1384,9 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->dev = net->loopback_dev;
}
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ /* only send ICMP too big on first fragment */
+ if (!iph->fragoffs)
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error_put;
}
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index d61e0782a797..7df424e2d10c 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -69,6 +69,10 @@ static int nf_conntrack_acct_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_acct;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->ct.acct_sysctl_header = register_net_sysctl(net, "net/netfilter",
table);
if (!net->ct.acct_sysctl_header) {
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0f241be28f9e..08cdc71d8e87 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -221,11 +221,9 @@ destroy_conntrack(struct nf_conntrack *nfct)
* too. */
nf_ct_remove_expectations(ct);
- /* We overload first tuple to link into unconfirmed list. */
- if (!nf_ct_is_confirmed(ct)) {
- BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
- hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
- }
+ /* We overload first tuple to link into unconfirmed or dying list.*/
+ BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
+ hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
NF_CT_STAT_INC(net, delete);
spin_unlock_bh(&nf_conntrack_lock);
@@ -247,6 +245,9 @@ void nf_ct_delete_from_lists(struct nf_conn *ct)
* Otherwise we can get spurious warnings. */
NF_CT_STAT_INC(net, delete_list);
clean_from_lists(ct);
+ /* add this conntrack to the dying list */
+ hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+ &net->ct.dying);
spin_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_ct_delete_from_lists);
@@ -268,31 +269,23 @@ static void death_by_event(unsigned long ul_conntrack)
}
/* we've got the event delivered, now it's dying */
set_bit(IPS_DYING_BIT, &ct->status);
- spin_lock(&nf_conntrack_lock);
- hlist_nulls_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
- spin_unlock(&nf_conntrack_lock);
nf_ct_put(ct);
}
-void nf_ct_insert_dying_list(struct nf_conn *ct)
+void nf_ct_dying_timeout(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
BUG_ON(ecache == NULL);
- /* add this conntrack to the dying list */
- spin_lock_bh(&nf_conntrack_lock);
- hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
- &net->ct.dying);
- spin_unlock_bh(&nf_conntrack_lock);
/* set a new timer to retry event delivery */
setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
ecache->timeout.expires = jiffies +
(random32() % net->ct.sysctl_events_retry_timeout);
add_timer(&ecache->timeout);
}
-EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
+EXPORT_SYMBOL_GPL(nf_ct_dying_timeout);
static void death_by_timeout(unsigned long ul_conntrack)
{
@@ -307,7 +300,7 @@ static void death_by_timeout(unsigned long ul_conntrack)
unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
/* destroy event was not delivered */
nf_ct_delete_from_lists(ct);
- nf_ct_insert_dying_list(ct);
+ nf_ct_dying_timeout(ct);
return;
}
set_bit(IPS_DYING_BIT, &ct->status);
@@ -1416,7 +1409,7 @@ EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
{
- int i, bucket;
+ int i, bucket, rc;
unsigned int hashsize, old_size;
struct hlist_nulls_head *hash, *old_hash;
struct nf_conntrack_tuple_hash *h;
@@ -1429,7 +1422,9 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
if (!nf_conntrack_htable_size)
return param_set_uint(val, kp);
- hashsize = simple_strtoul(val, NULL, 0);
+ rc = kstrtouint(val, 0, &hashsize);
+ if (rc)
+ return rc;
if (!hashsize)
return -EINVAL;
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index de9781b6464f..faa978f1714b 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -196,6 +196,10 @@ static int nf_conntrack_event_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_events;
table[1].data = &net->ct.sysctl_events_retry_timeout;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->ct.event_sysctl_header =
register_net_sysctl(net, "net/netfilter", table);
if (!net->ct.event_sysctl_header) {
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index c4bc637feb76..884f2b39319a 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -64,6 +64,10 @@ static int nf_conntrack_helper_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_auto_assign_helper;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->ct.helper_sysctl_header =
register_net_sysctl(net, "net/netfilter", table);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 7bbfb3deea30..4e078cd84d83 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -898,7 +898,8 @@ ctnetlink_parse_zone(const struct nlattr *attr, u16 *zone)
}
static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
- [CTA_HELP_NAME] = { .type = NLA_NUL_STRING },
+ [CTA_HELP_NAME] = { .type = NLA_NUL_STRING,
+ .len = NF_CT_HELPER_NAME_LEN - 1 },
};
static inline int
@@ -932,6 +933,8 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
[CTA_ID] = { .type = NLA_U32 },
[CTA_NAT_DST] = { .type = NLA_NESTED },
[CTA_TUPLE_MASTER] = { .type = NLA_NESTED },
+ [CTA_NAT_SEQ_ADJ_ORIG] = { .type = NLA_NESTED },
+ [CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED },
[CTA_ZONE] = { .type = NLA_U16 },
[CTA_MARK_MASK] = { .type = NLA_U32 },
};
@@ -989,7 +992,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
nlmsg_report(nlh)) < 0) {
nf_ct_delete_from_lists(ct);
/* we failed to report the event, try later */
- nf_ct_insert_dying_list(ct);
+ nf_ct_dying_timeout(ct);
nf_ct_put(ct);
return 0;
}
@@ -1089,6 +1092,112 @@ out:
return err == -EAGAIN ? -ENOBUFS : err;
}
+static int ctnetlink_done_list(struct netlink_callback *cb)
+{
+ if (cb->args[1])
+ nf_ct_put((struct nf_conn *)cb->args[1]);
+ return 0;
+}
+
+static int
+ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb,
+ struct hlist_nulls_head *list)
+{
+ struct nf_conn *ct, *last;
+ struct nf_conntrack_tuple_hash *h;
+ struct hlist_nulls_node *n;
+ struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
+ u_int8_t l3proto = nfmsg->nfgen_family;
+ int res;
+
+ if (cb->args[2])
+ return 0;
+
+ spin_lock_bh(&nf_conntrack_lock);
+ last = (struct nf_conn *)cb->args[1];
+restart:
+ hlist_nulls_for_each_entry(h, n, list, hnnode) {
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (l3proto && nf_ct_l3num(ct) != l3proto)
+ continue;
+ if (cb->args[1]) {
+ if (ct != last)
+ continue;
+ cb->args[1] = 0;
+ }
+ rcu_read_lock();
+ res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
+ ct);
+ rcu_read_unlock();
+ if (res < 0) {
+ nf_conntrack_get(&ct->ct_general);
+ cb->args[1] = (unsigned long)ct;
+ goto out;
+ }
+ }
+ if (cb->args[1]) {
+ cb->args[1] = 0;
+ goto restart;
+ } else
+ cb->args[2] = 1;
+out:
+ spin_unlock_bh(&nf_conntrack_lock);
+ if (last)
+ nf_ct_put(last);
+
+ return skb->len;
+}
+
+static int
+ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct net *net = sock_net(skb->sk);
+
+ return ctnetlink_dump_list(skb, cb, &net->ct.dying);
+}
+
+static int
+ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const cda[])
+{
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct netlink_dump_control c = {
+ .dump = ctnetlink_dump_dying,
+ .done = ctnetlink_done_list,
+ };
+ return netlink_dump_start(ctnl, skb, nlh, &c);
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int
+ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct net *net = sock_net(skb->sk);
+
+ return ctnetlink_dump_list(skb, cb, &net->ct.unconfirmed);
+}
+
+static int
+ctnetlink_get_ct_unconfirmed(struct sock *ctnl, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const cda[])
+{
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct netlink_dump_control c = {
+ .dump = ctnetlink_dump_unconfirmed,
+ .done = ctnetlink_done_list,
+ };
+ return netlink_dump_start(ctnl, skb, nlh, &c);
+ }
+
+ return -EOPNOTSUPP;
+}
+
#ifdef CONFIG_NF_NAT_NEEDED
static int
ctnetlink_parse_nat_setup(struct nf_conn *ct,
@@ -2216,7 +2325,8 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
[CTA_EXPECT_MASK] = { .type = NLA_NESTED },
[CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
[CTA_EXPECT_ID] = { .type = NLA_U32 },
- [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING },
+ [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
+ .len = NF_CT_HELPER_NAME_LEN - 1 },
[CTA_EXPECT_ZONE] = { .type = NLA_U16 },
[CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
[CTA_EXPECT_CLASS] = { .type = NLA_U32 },
@@ -2712,6 +2822,8 @@ static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
.policy = ct_nla_policy },
[IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu },
[IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct },
+ [IPCTNL_MSG_CT_GET_DYING] = { .call = ctnetlink_get_ct_dying },
+ [IPCTNL_MSG_CT_GET_UNCONFIRMED] = { .call = ctnetlink_get_ct_unconfirmed },
};
static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 6535326cf07c..a8ae287bc7af 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -815,7 +815,7 @@ static struct ctl_table dccp_sysctl_table[] = {
};
#endif /* CONFIG_SYSCTL */
-static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn,
+static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
struct dccp_net *dn)
{
#ifdef CONFIG_SYSCTL
@@ -836,6 +836,10 @@ static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn,
pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
pn->ctl_table[7].data = &dn->dccp_loose;
+
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ pn->ctl_table[0].procname = NULL;
#endif
return 0;
}
@@ -857,7 +861,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto)
dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
}
- return dccp_kmemdup_sysctl_table(pn, dn);
+ return dccp_kmemdup_sysctl_table(net, pn, dn);
}
static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 61f9285111d1..83876e9877f1 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1353,6 +1353,8 @@ static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] = {
[CTA_TIMEOUT_TCP_TIME_WAIT] = { .type = NLA_U32 },
[CTA_TIMEOUT_TCP_CLOSE] = { .type = NLA_U32 },
[CTA_TIMEOUT_TCP_SYN_SENT2] = { .type = NLA_U32 },
+ [CTA_TIMEOUT_TCP_RETRANS] = { .type = NLA_U32 },
+ [CTA_TIMEOUT_TCP_UNACK] = { .type = NLA_U32 },
};
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 9b3943252a5e..363285d544a1 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -489,6 +489,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
table[3].data = &net->ct.sysctl_checksum;
table[4].data = &net->ct.sysctl_log_invalid;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table);
if (!net->ct.sysctl_header)
goto out_unregister_netfilter;
diff --git a/net/netfilter/nf_conntrack_timestamp.c b/net/netfilter/nf_conntrack_timestamp.c
index dbb364f62d6f..7ea8026f07c9 100644
--- a/net/netfilter/nf_conntrack_timestamp.c
+++ b/net/netfilter/nf_conntrack_timestamp.c
@@ -51,6 +51,10 @@ static int nf_conntrack_tstamp_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_tstamp;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->ct.tstamp_sysctl_header = register_net_sysctl(net, "net/netfilter",
table);
if (!net->ct.tstamp_sysctl_header) {
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 703fb26aa48d..9e312695c818 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -32,7 +32,7 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger)
return NULL;
}
-/* return EEXIST if the same logger is registred, 0 on success. */
+/* return EEXIST if the same logger is registered, 0 on success. */
int nf_log_register(u_int8_t pf, struct nf_logger *logger)
{
const struct nf_logger *llog;
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 8d2cf9ec37a8..d812c1235b30 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -14,84 +14,32 @@
#include "nf_internals.h"
/*
- * A queue handler may be registered for each protocol. Each is protected by
- * long term mutex. The handler must provide an an outfn() to accept packets
- * for queueing and must reinject all packets it receives, no matter what.
+ * Hook for nfnetlink_queue to register its queue handler.
+ * We do this so that most of the NFQUEUE code can be modular.
+ *
+ * Once the queue is registered it must reinject all packets it
+ * receives, no matter what.
*/
-static const struct nf_queue_handler __rcu *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
-
-static DEFINE_MUTEX(queue_handler_mutex);
+static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
/* return EBUSY when somebody else is registered, return EEXIST if the
* same handler is registered, return 0 in case of success. */
-int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
+void nf_register_queue_handler(const struct nf_queue_handler *qh)
{
- int ret;
- const struct nf_queue_handler *old;
-
- if (pf >= ARRAY_SIZE(queue_handler))
- return -EINVAL;
-
- mutex_lock(&queue_handler_mutex);
- old = rcu_dereference_protected(queue_handler[pf],
- lockdep_is_held(&queue_handler_mutex));
- if (old == qh)
- ret = -EEXIST;
- else if (old)
- ret = -EBUSY;
- else {
- rcu_assign_pointer(queue_handler[pf], qh);
- ret = 0;
- }
- mutex_unlock(&queue_handler_mutex);
-
- return ret;
+ /* should never happen, we only have one queueing backend in kernel */
+ WARN_ON(rcu_access_pointer(queue_handler));
+ rcu_assign_pointer(queue_handler, qh);
}
EXPORT_SYMBOL(nf_register_queue_handler);
/* The caller must flush their queue before this */
-int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
+void nf_unregister_queue_handler(void)
{
- const struct nf_queue_handler *old;
-
- if (pf >= ARRAY_SIZE(queue_handler))
- return -EINVAL;
-
- mutex_lock(&queue_handler_mutex);
- old = rcu_dereference_protected(queue_handler[pf],
- lockdep_is_held(&queue_handler_mutex));
- if (old && old != qh) {
- mutex_unlock(&queue_handler_mutex);
- return -EINVAL;
- }
-
- RCU_INIT_POINTER(queue_handler[pf], NULL);
- mutex_unlock(&queue_handler_mutex);
-
+ RCU_INIT_POINTER(queue_handler, NULL);
synchronize_rcu();
-
- return 0;
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
-void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
-{
- u_int8_t pf;
-
- mutex_lock(&queue_handler_mutex);
- for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
- if (rcu_dereference_protected(
- queue_handler[pf],
- lockdep_is_held(&queue_handler_mutex)
- ) == qh)
- RCU_INIT_POINTER(queue_handler[pf], NULL);
- }
- mutex_unlock(&queue_handler_mutex);
-
- synchronize_rcu();
-}
-EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
-
static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
{
/* Release those devices we held, or Alexey will kill me. */
@@ -137,7 +85,7 @@ static int __nf_queue(struct sk_buff *skb,
/* QUEUE == DROP if no one is waiting, to be safe. */
rcu_read_lock();
- qh = rcu_dereference(queue_handler[pf]);
+ qh = rcu_dereference(queue_handler);
if (!qh) {
status = -ESRCH;
goto err_unlock;
@@ -344,77 +292,3 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
kfree(entry);
}
EXPORT_SYMBOL(nf_reinject);
-
-#ifdef CONFIG_PROC_FS
-static void *seq_start(struct seq_file *seq, loff_t *pos)
-{
- if (*pos >= ARRAY_SIZE(queue_handler))
- return NULL;
-
- return pos;
-}
-
-static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- (*pos)++;
-
- if (*pos >= ARRAY_SIZE(queue_handler))
- return NULL;
-
- return pos;
-}
-
-static void seq_stop(struct seq_file *s, void *v)
-{
-
-}
-
-static int seq_show(struct seq_file *s, void *v)
-{
- int ret;
- loff_t *pos = v;
- const struct nf_queue_handler *qh;
-
- rcu_read_lock();
- qh = rcu_dereference(queue_handler[*pos]);
- if (!qh)
- ret = seq_printf(s, "%2lld NONE\n", *pos);
- else
- ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
- rcu_read_unlock();
-
- return ret;
-}
-
-static const struct seq_operations nfqueue_seq_ops = {
- .start = seq_start,
- .next = seq_next,
- .stop = seq_stop,
- .show = seq_show,
-};
-
-static int nfqueue_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &nfqueue_seq_ops);
-}
-
-static const struct file_operations nfqueue_file_ops = {
- .owner = THIS_MODULE,
- .open = nfqueue_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-#endif /* PROC_FS */
-
-
-int __init netfilter_queue_init(void)
-{
-#ifdef CONFIG_PROC_FS
- if (!proc_create("nf_queue", S_IRUGO,
- proc_net_netfilter, &nfqueue_file_ops))
- return -1;
-#endif
- return 0;
-}
-
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index ffb92c03a358..58a09b7c3f6d 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -138,7 +138,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
const struct nfnetlink_subsystem *ss;
int type, err;
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
/* All the messages must at least contain nfgenmsg */
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index e12d44e75b21..3158d87b56a8 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -809,7 +809,6 @@ static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
};
static const struct nf_queue_handler nfqh = {
- .name = "nf_queue",
.outfn = &nfqnl_enqueue_packet,
};
@@ -827,14 +826,10 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
if (nfqa[NFQA_CFG_CMD]) {
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
- /* Commands without queue context - might sleep */
+ /* Obsolete commands without queue context */
switch (cmd->command) {
- case NFQNL_CFG_CMD_PF_BIND:
- return nf_register_queue_handler(ntohs(cmd->pf),
- &nfqh);
- case NFQNL_CFG_CMD_PF_UNBIND:
- return nf_unregister_queue_handler(ntohs(cmd->pf),
- &nfqh);
+ case NFQNL_CFG_CMD_PF_BIND: return 0;
+ case NFQNL_CFG_CMD_PF_UNBIND: return 0;
}
}
@@ -1074,6 +1069,7 @@ static int __init nfnetlink_queue_init(void)
#endif
register_netdevice_notifier(&nfqnl_dev_notifier);
+ nf_register_queue_handler(&nfqh);
return status;
#ifdef CONFIG_PROC_FS
@@ -1087,7 +1083,7 @@ cleanup_netlink_notifier:
static void __exit nfnetlink_queue_fini(void)
{
- nf_unregister_queue_handlers(&nfqh);
+ nf_unregister_queue_handler();
unregister_netdevice_notifier(&nfqnl_dev_notifier);
#ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
diff --git a/net/netfilter/xt_HMARK.c b/net/netfilter/xt_HMARK.c
index 1686ca1b53a1..73b73f687c58 100644
--- a/net/netfilter/xt_HMARK.c
+++ b/net/netfilter/xt_HMARK.c
@@ -167,7 +167,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
const struct xt_hmark_info *info)
{
struct ipv6hdr *ip6, _ip6;
- int flag = IP6T_FH_F_AUTH;
+ int flag = IP6_FH_F_AUTH;
unsigned int nhoff = 0;
u16 fragoff = 0;
int nexthdr;
@@ -177,7 +177,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
if (nexthdr < 0)
return 0;
/* No need to check for icmp errors on fragments */
- if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
+ if ((flag & IP6_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
goto noicmp;
/* Use inner header in case of ICMP errors */
if (get_inner6_hdr(skb, &nhoff)) {
@@ -185,7 +185,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
if (ip6 == NULL)
return -1;
/* If AH present, use SPI like in ESP. */
- flag = IP6T_FH_F_AUTH;
+ flag = IP6_FH_F_AUTH;
nexthdr = ipv6_find_hdr(skb, &nhoff, -1, &fragoff, &flag);
if (nexthdr < 0)
return -1;
@@ -201,7 +201,7 @@ noicmp:
if (t->proto == IPPROTO_ICMPV6)
return 0;
- if (flag & IP6T_FH_F_FRAG)
+ if (flag & IP6_FH_F_FRAG)
return 0;
hmark_set_tuple_ports(skb, nhoff, t, info);
diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c
index bb10b0717f1b..8d47c3780fda 100644
--- a/net/netfilter/xt_ipvs.c
+++ b/net/netfilter/xt_ipvs.c
@@ -67,7 +67,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
goto out;
}
- ip_vs_fill_iphdr(family, skb_network_header(skb), &iph);
+ ip_vs_fill_iph_skb(family, skb, &iph);
if (data->bitmask & XT_IPVS_PROTO)
if ((iph.protocol == data->l4proto) ^
@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
/*
* Check if the packet belongs to an existing entry
*/
- cp = pp->conn_out_get(family, skb, &iph, iph.len, 1 /* inverse */);
+ cp = pp->conn_out_get(family, skb, &iph, 1 /* inverse */);
if (unlikely(cp == NULL)) {
match = false;
goto out;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 4da797fa5ec5..c8a1eb6eca2d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -612,7 +612,7 @@ retry:
static inline int netlink_capable(const struct socket *sock, unsigned int flag)
{
return (nl_table[sock->sk->sk_protocol].flags & flag) ||
- capable(CAP_NET_ADMIN);
+ ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN);
}
static void
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
index 8d8d9bc4b6ff..60c3bbb63e8e 100644
--- a/net/nfc/Kconfig
+++ b/net/nfc/Kconfig
@@ -3,8 +3,8 @@
#
menuconfig NFC
- depends on NET && EXPERIMENTAL
- tristate "NFC subsystem support (EXPERIMENTAL)"
+ depends on NET
+ tristate "NFC subsystem support"
default n
help
Say Y here if you want to build support for NFC (Near field
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 479bee36dc3e..aa64ea441676 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -40,6 +40,9 @@
int nfc_devlist_generation;
DEFINE_MUTEX(nfc_devlist_mutex);
+/* NFC device ID bitmap */
+static DEFINE_IDA(nfc_index_ida);
+
/**
* nfc_dev_up - turn on the NFC device
*
@@ -181,6 +184,7 @@ int nfc_stop_poll(struct nfc_dev *dev)
dev->ops->stop_poll(dev);
dev->polling = false;
+ dev->rf_mode = NFC_RF_NONE;
error:
device_unlock(&dev->dev);
@@ -194,7 +198,7 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
if (dev->n_targets == 0)
return NULL;
- for (i = 0; i < dev->n_targets ; i++) {
+ for (i = 0; i < dev->n_targets; i++) {
if (dev->targets[i].idx == target_idx)
return &dev->targets[i];
}
@@ -274,12 +278,14 @@ int nfc_dep_link_down(struct nfc_dev *dev)
if (!rc) {
dev->dep_link_up = false;
dev->active_target = NULL;
+ dev->rf_mode = NFC_RF_NONE;
nfc_llcp_mac_is_down(dev);
nfc_genl_dep_link_down_event(dev);
}
error:
device_unlock(&dev->dev);
+
return rc;
}
@@ -503,6 +509,7 @@ EXPORT_SYMBOL(nfc_tm_activated);
int nfc_tm_deactivated(struct nfc_dev *dev)
{
dev->dep_link_up = false;
+ dev->rf_mode = NFC_RF_NONE;
return nfc_genl_tm_deactivated(dev);
}
@@ -697,6 +704,8 @@ static void nfc_check_pres_work(struct work_struct *work)
if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) {
rc = dev->ops->check_presence(dev, dev->active_target);
+ if (rc == -EOPNOTSUPP)
+ goto exit;
if (!rc) {
mod_timer(&dev->check_pres_timer, jiffies +
msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
@@ -708,6 +717,7 @@ static void nfc_check_pres_work(struct work_struct *work)
}
}
+exit:
device_unlock(&dev->dev);
}
@@ -753,7 +763,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
u32 supported_protocols,
int tx_headroom, int tx_tailroom)
{
- static atomic_t dev_no = ATOMIC_INIT(0);
struct nfc_dev *dev;
if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
@@ -767,11 +776,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
if (!dev)
return NULL;
- dev->dev.class = &nfc_class;
- dev->idx = atomic_inc_return(&dev_no) - 1;
- dev_set_name(&dev->dev, "nfc%d", dev->idx);
- device_initialize(&dev->dev);
-
dev->ops = ops;
dev->supported_protocols = supported_protocols;
dev->tx_headroom = tx_headroom;
@@ -779,6 +783,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
nfc_genl_data_init(&dev->genl_data);
+ dev->rf_mode = NFC_RF_NONE;
/* first generation must not be 0 */
dev->targets_generation = 1;
@@ -806,6 +811,14 @@ int nfc_register_device(struct nfc_dev *dev)
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+ dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
+ if (dev->idx < 0)
+ return dev->idx;
+
+ dev->dev.class = &nfc_class;
+ dev_set_name(&dev->dev, "nfc%d", dev->idx);
+ device_initialize(&dev->dev);
+
mutex_lock(&nfc_devlist_mutex);
nfc_devlist_generation++;
rc = device_add(&dev->dev);
@@ -834,10 +847,12 @@ EXPORT_SYMBOL(nfc_register_device);
*/
void nfc_unregister_device(struct nfc_dev *dev)
{
- int rc;
+ int rc, id;
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+ id = dev->idx;
+
mutex_lock(&nfc_devlist_mutex);
nfc_devlist_generation++;
@@ -856,6 +871,8 @@ void nfc_unregister_device(struct nfc_dev *dev)
pr_debug("The userspace won't be notified that the device %s was removed\n",
dev_name(&dev->dev));
+ ida_simple_remove(&nfc_index_ida, id);
+
}
EXPORT_SYMBOL(nfc_unregister_device);
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 71c6a7086b8f..7d99410e6c1a 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -257,16 +257,16 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host,
*result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
NFC_HCI_ADM_CREATE_PIPE,
(u8 *) &params, sizeof(params), &skb);
- if (*result == 0) {
- resp = (struct hci_create_pipe_resp *)skb->data;
- pipe = resp->pipe;
- kfree_skb(skb);
+ if (*result < 0)
+ return NFC_HCI_INVALID_PIPE;
- pr_debug("pipe created=%d\n", pipe);
+ resp = (struct hci_create_pipe_resp *)skb->data;
+ pipe = resp->pipe;
+ kfree_skb(skb);
- return pipe;
- } else
- return NFC_HCI_INVALID_PIPE;
+ pr_debug("pipe created=%d\n", pipe);
+
+ return pipe;
}
static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe)
@@ -279,8 +279,6 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe)
static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev)
{
- int r;
-
u8 param[2];
/* TODO: Find out what the identity reference data is
@@ -288,10 +286,8 @@ static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev)
pr_debug("\n");
- r = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
- NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL);
-
- return 0;
+ return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
+ NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL);
}
int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate)
@@ -348,7 +344,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
return -EADDRINUSE;
if (pipe != NFC_HCI_INVALID_PIPE)
- goto pipe_is_open;
+ goto open_pipe;
switch (dest_gate) {
case NFC_HCI_LINK_MGMT_GATE:
@@ -365,6 +361,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
break;
}
+open_pipe:
r = nfc_hci_open_pipe(hdev, pipe);
if (r < 0) {
if (pipe_created)
@@ -375,7 +372,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
return r;
}
-pipe_is_open:
hdev->gate2pipe[dest_gate] = pipe;
return 0;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 5fbb6e40793e..7bea574d5934 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -33,17 +33,20 @@
/* Largest headroom needed for outgoing HCI commands */
#define HCI_CMDS_HEADROOM 1
-static int nfc_hci_result_to_errno(u8 result)
+int nfc_hci_result_to_errno(u8 result)
{
switch (result) {
case NFC_HCI_ANY_OK:
return 0;
+ case NFC_HCI_ANY_E_REG_PAR_UNKNOWN:
+ return -EOPNOTSUPP;
case NFC_HCI_ANY_E_TIMEOUT:
return -ETIME;
default:
return -1;
}
}
+EXPORT_SYMBOL(nfc_hci_result_to_errno);
static void nfc_hci_msg_tx_work(struct work_struct *work)
{
@@ -65,8 +68,9 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
-ETIME);
kfree(hdev->cmd_pending_msg);
hdev->cmd_pending_msg = NULL;
- } else
+ } else {
goto exit;
+ }
}
next_msg:
@@ -166,7 +170,7 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
kfree_skb(skb);
}
-static u32 nfc_hci_sak_to_protocol(u8 sak)
+u32 nfc_hci_sak_to_protocol(u8 sak)
{
switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) {
case NFC_HCI_TYPE_A_SEL_PROT_MIFARE:
@@ -181,8 +185,9 @@ static u32 nfc_hci_sak_to_protocol(u8 sak)
return 0xffffffff;
}
}
+EXPORT_SYMBOL(nfc_hci_sak_to_protocol);
-static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
+int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
{
struct nfc_target *targets;
struct sk_buff *atqa_skb = NULL;
@@ -263,7 +268,9 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
break;
}
- targets->hci_reader_gate = gate;
+ /* if driver set the new gate, we will skip the old one */
+ if (targets->hci_reader_gate == 0x00)
+ targets->hci_reader_gate = gate;
r = nfc_targets_found(hdev->ndev, targets, 1);
@@ -275,11 +282,18 @@ exit:
return r;
}
+EXPORT_SYMBOL(nfc_hci_target_discovered);
void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
struct sk_buff *skb)
{
int r = 0;
+ u8 gate = nfc_hci_pipe2gate(hdev, pipe);
+
+ if (gate == 0xff) {
+ pr_err("Discarded event %x to unopened pipe %x\n", event, pipe);
+ goto exit;
+ }
switch (event) {
case NFC_HCI_EVT_TARGET_DISCOVERED:
@@ -303,12 +317,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
goto exit;
}
- r = nfc_hci_target_discovered(hdev,
- nfc_hci_pipe2gate(hdev, pipe));
+ r = nfc_hci_target_discovered(hdev, gate);
break;
default:
- /* TODO: Unknown events are hardware specific
- * pass them to the driver (needs a new hci_ops) */
+ if (hdev->ops->event_received) {
+ hdev->ops->event_received(hdev, gate, event, skb);
+ return;
+ }
+
break;
}
@@ -410,6 +426,10 @@ static int hci_dev_version(struct nfc_hci_dev *hdev)
r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
NFC_HCI_ID_MGMT_VERSION_SW, &skb);
+ if (r == -EOPNOTSUPP) {
+ pr_info("Software/Hardware info not available\n");
+ return 0;
+ }
if (r < 0)
return r;
@@ -527,7 +547,8 @@ static int hci_start_poll(struct nfc_dev *nfc_dev,
return hdev->ops->start_poll(hdev, im_protocols, tm_protocols);
else
return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
- NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+ NFC_HCI_EVT_READER_REQUESTED,
+ NULL, 0);
}
static void hci_stop_poll(struct nfc_dev *nfc_dev)
@@ -538,6 +559,28 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev)
NFC_HCI_EVT_END_OPERATION, NULL, 0);
}
+static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
+ __u8 comm_mode, __u8 *gb, size_t gb_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+ if (hdev->ops->dep_link_up)
+ return hdev->ops->dep_link_up(hdev, target, comm_mode,
+ gb, gb_len);
+
+ return 0;
+}
+
+static int hci_dep_link_down(struct nfc_dev *nfc_dev)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+ if (hdev->ops->dep_link_down)
+ return hdev->ops->dep_link_down(hdev);
+
+ return 0;
+}
+
static int hci_activate_target(struct nfc_dev *nfc_dev,
struct nfc_target *target, u32 protocol)
{
@@ -586,8 +629,8 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
switch (target->hci_reader_gate) {
case NFC_HCI_RF_READER_A_GATE:
case NFC_HCI_RF_READER_B_GATE:
- if (hdev->ops->data_exchange) {
- r = hdev->ops->data_exchange(hdev, target, skb, cb,
+ if (hdev->ops->im_transceive) {
+ r = hdev->ops->im_transceive(hdev, target, skb, cb,
cb_context);
if (r <= 0) /* handled */
break;
@@ -604,14 +647,14 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
skb->len, hci_transceive_cb, hdev);
break;
default:
- if (hdev->ops->data_exchange) {
- r = hdev->ops->data_exchange(hdev, target, skb, cb,
+ if (hdev->ops->im_transceive) {
+ r = hdev->ops->im_transceive(hdev, target, skb, cb,
cb_context);
if (r == 1)
r = -ENOTSUPP;
- }
- else
+ } else {
r = -ENOTSUPP;
+ }
break;
}
@@ -620,6 +663,16 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
return r;
}
+static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+ if (hdev->ops->tm_send)
+ return hdev->ops->tm_send(hdev, skb);
+ else
+ return -ENOTSUPP;
+}
+
static int hci_check_presence(struct nfc_dev *nfc_dev,
struct nfc_target *target)
{
@@ -723,9 +776,12 @@ static struct nfc_ops hci_nfc_ops = {
.dev_down = hci_dev_down,
.start_poll = hci_start_poll,
.stop_poll = hci_stop_poll,
+ .dep_link_up = hci_dep_link_up,
+ .dep_link_down = hci_dep_link_down,
.activate_target = hci_activate_target,
.deactivate_target = hci_deactivate_target,
.im_transceive = hci_transceive,
+ .tm_send = hci_tm_send,
.check_presence = hci_check_presence,
};
@@ -848,7 +904,7 @@ void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err)
}
EXPORT_SYMBOL(nfc_hci_driver_failure);
-void inline nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
{
nfc_llc_rcv_from_drv(hdev->llc, skb);
}
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c
index ae1205ded87f..fe5e966e5b88 100644
--- a/net/nfc/hci/llc.c
+++ b/net/nfc/hci/llc.c
@@ -72,7 +72,7 @@ int nfc_llc_register(const char *name, struct nfc_llc_ops *ops)
llc_engine->ops = ops;
INIT_LIST_HEAD(&llc_engine->entry);
- list_add_tail (&llc_engine->entry, &llc_engines);
+ list_add_tail(&llc_engine->entry, &llc_engines);
return 0;
}
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
index 01cbc72943cd..27b313befc35 100644
--- a/net/nfc/hci/llc_shdlc.c
+++ b/net/nfc/hci/llc_shdlc.c
@@ -634,9 +634,9 @@ static void llc_shdlc_sm_work(struct work_struct *work)
r = llc_shdlc_connect_initiate(shdlc);
else
r = -ETIME;
- if (r < 0)
+ if (r < 0) {
llc_shdlc_connect_complete(shdlc, r);
- else {
+ } else {
mod_timer(&shdlc->connect_timer, jiffies +
msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS));
@@ -682,9 +682,8 @@ static void llc_shdlc_sm_work(struct work_struct *work)
llc_shdlc_handle_send_queue(shdlc);
}
- if (shdlc->hard_fault) {
+ if (shdlc->hard_fault)
shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault);
- }
break;
default:
break;
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig
index fbf5e8150908..a1a41cd68255 100644
--- a/net/nfc/llcp/Kconfig
+++ b/net/nfc/llcp/Kconfig
@@ -1,6 +1,6 @@
config NFC_LLCP
- depends on NFC && EXPERIMENTAL
- bool "NFC LLCP support (EXPERIMENTAL)"
+ depends on NFC
+ bool "NFC LLCP support"
default n
help
Say Y here if you want to build support for a kernel NFC LLCP
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index c45ccd6c094c..df24be48d4da 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -261,7 +261,6 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
struct sk_buff *skb;
struct nfc_dev *dev;
struct nfc_llcp_local *local;
- u16 size = 0;
pr_debug("Sending DISC\n");
@@ -273,17 +272,10 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
if (dev == NULL)
return -ENODEV;
- size += LLCP_HEADER_SIZE;
- size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
-
- skb = alloc_skb(size, GFP_ATOMIC);
+ skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
if (skb == NULL)
return -ENOMEM;
- skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
-
- skb = llcp_add_header(skb, sock->dsap, sock->ssap, LLCP_PDU_DISC);
-
skb_queue_tail(&local->tx_queue, skb);
return 0;
@@ -324,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
struct sk_buff *skb;
u8 *service_name_tlv = NULL, service_name_tlv_length;
u8 *miux_tlv = NULL, miux_tlv_length;
- u8 *rw_tlv = NULL, rw_tlv_length, rw;
- __be16 miux;
+ u8 *rw_tlv = NULL, rw_tlv_length;
int err;
u16 size = 0;
@@ -343,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
size += service_name_tlv_length;
}
- miux = cpu_to_be16(LLCP_MAX_MIUX);
- miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+ miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
&miux_tlv_length);
size += miux_tlv_length;
- rw = LLCP_MAX_RW;
- rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+ rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
size += rw_tlv_length;
pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
@@ -386,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
struct nfc_llcp_local *local;
struct sk_buff *skb;
u8 *miux_tlv = NULL, miux_tlv_length;
- u8 *rw_tlv = NULL, rw_tlv_length, rw;
- __be16 miux;
+ u8 *rw_tlv = NULL, rw_tlv_length;
int err;
u16 size = 0;
@@ -397,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
if (local == NULL)
return -ENODEV;
- miux = cpu_to_be16(LLCP_MAX_MIUX);
- miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+ miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
&miux_tlv_length);
size += miux_tlv_length;
- rw = LLCP_MAX_RW;
- rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+ rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
size += rw_tlv_length;
skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
@@ -428,6 +414,52 @@ error_tlv:
return err;
}
+int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap)
+{
+ struct sk_buff *skb;
+ struct nfc_dev *dev;
+ u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2];
+ u16 size = 0;
+
+ pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap);
+
+ if (local == NULL)
+ return -ENODEV;
+
+ dev = local->dev;
+ if (dev == NULL)
+ return -ENODEV;
+
+ sdres[0] = tid;
+ sdres[1] = sap;
+ sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0,
+ &sdres_tlv_length);
+ if (sdres_tlv == NULL)
+ return -ENOMEM;
+
+ size += LLCP_HEADER_SIZE;
+ size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+ size += sdres_tlv_length;
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (skb == NULL) {
+ kfree(sdres_tlv);
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+ skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);
+
+ memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length);
+
+ skb_queue_tail(&local->tx_queue, skb);
+
+ kfree(sdres_tlv);
+
+ return 0;
+}
+
int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
{
struct sk_buff *skb;
@@ -496,6 +528,23 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
if (local == NULL)
return -ENODEV;
+ /* Remote is ready but has not acknowledged our frames */
+ if((sock->remote_ready &&
+ skb_queue_len(&sock->tx_pending_queue) >= sock->rw &&
+ skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
+ pr_err("Pending queue is full %d frames\n",
+ skb_queue_len(&sock->tx_pending_queue));
+ return -ENOBUFS;
+ }
+
+ /* Remote is not ready and we've been queueing enough frames */
+ if ((!sock->remote_ready &&
+ skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
+ pr_err("Tx queue is full %d frames\n",
+ skb_queue_len(&sock->tx_queue));
+ return -ENOBUFS;
+ }
+
msg_data = kzalloc(len, GFP_KERNEL);
if (msg_data == NULL)
return -ENOMEM;
@@ -541,6 +590,63 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
return len;
}
+int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
+ struct msghdr *msg, size_t len)
+{
+ struct sk_buff *pdu;
+ struct nfc_llcp_local *local;
+ size_t frag_len = 0, remaining_len;
+ u8 *msg_ptr, *msg_data;
+ int err;
+
+ pr_debug("Send UI frame len %zd\n", len);
+
+ local = sock->local;
+ if (local == NULL)
+ return -ENODEV;
+
+ msg_data = kzalloc(len, GFP_KERNEL);
+ if (msg_data == NULL)
+ return -ENOMEM;
+
+ if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
+ kfree(msg_data);
+ return -EFAULT;
+ }
+
+ remaining_len = len;
+ msg_ptr = msg_data;
+
+ while (remaining_len > 0) {
+
+ frag_len = min_t(size_t, sock->miu, remaining_len);
+
+ pr_debug("Fragment %zd bytes remaining %zd",
+ frag_len, remaining_len);
+
+ pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
+ frag_len + LLCP_HEADER_SIZE, &err);
+ if (pdu == NULL) {
+ pr_err("Could not allocate PDU\n");
+ continue;
+ }
+
+ pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
+
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+
+ /* No need to check for the peer RW for UI frames */
+ skb_queue_tail(&local->tx_queue, pdu);
+
+ remaining_len -= frag_len;
+ msg_ptr += frag_len;
+ }
+
+ kfree(msg_data);
+
+ return len;
+}
+
int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
{
struct sk_buff *skb;
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 9e8f4b2801f6..ec43914c92a9 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -45,12 +45,38 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
write_unlock(&l->lock);
}
+static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
+{
+ struct nfc_llcp_local *local = sock->local;
+ struct sk_buff *s, *tmp;
+
+ pr_debug("%p\n", &sock->sk);
+
+ skb_queue_purge(&sock->tx_queue);
+ skb_queue_purge(&sock->tx_pending_queue);
+ skb_queue_purge(&sock->tx_backlog_queue);
+
+ if (local == NULL)
+ return;
+
+ /* Search for local pending SKBs that are related to this socket */
+ skb_queue_walk_safe(&local->tx_queue, s, tmp) {
+ if (s->sk != &sock->sk)
+ continue;
+
+ skb_unlink(s, &local->tx_queue);
+ kfree_skb(s);
+ }
+}
+
static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
{
struct sock *sk;
struct hlist_node *node, *tmp;
struct nfc_llcp_sock *llcp_sock;
+ skb_queue_purge(&local->tx_queue);
+
write_lock(&local->sockets.lock);
sk_for_each_safe(sk, node, tmp, &local->sockets.head) {
@@ -58,6 +84,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
bh_lock_sock(sk);
+ nfc_llcp_socket_purge(llcp_sock);
+
if (sk->sk_state == LLCP_CONNECTED)
nfc_put_device(llcp_sock->dev);
@@ -65,7 +93,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
struct nfc_llcp_sock *lsk, *n;
struct sock *accept_sk;
- list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
+ list_for_each_entry_safe(lsk, n,
+ &llcp_sock->accept_queue,
accept_queue) {
accept_sk = &lsk->sk;
bh_lock_sock(accept_sk);
@@ -85,6 +114,16 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
}
}
+ /*
+ * If we have a connection less socket bound, we keep it alive
+ * if the device is still present.
+ */
+ if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM &&
+ listen == true) {
+ bh_unlock_sock(sk);
+ continue;
+ }
+
sk->sk_state = LLCP_CLOSED;
bh_unlock_sock(sk);
@@ -134,7 +173,7 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
{
struct sock *sk;
struct hlist_node *node;
- struct nfc_llcp_sock *llcp_sock;
+ struct nfc_llcp_sock *llcp_sock, *tmp_sock;
pr_debug("ssap dsap %d %d\n", ssap, dsap);
@@ -146,10 +185,12 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
llcp_sock = NULL;
sk_for_each(sk, node, &local->sockets.head) {
- llcp_sock = nfc_llcp_sock(sk);
+ tmp_sock = nfc_llcp_sock(sk);
- if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap)
+ if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) {
+ llcp_sock = tmp_sock;
break;
+ }
}
read_unlock(&local->sockets.lock);
@@ -249,7 +290,12 @@ struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
pr_debug("llcp sock %p\n", tmp_sock);
- if (tmp_sock->sk.sk_state != LLCP_LISTEN)
+ if (tmp_sock->sk.sk_type == SOCK_STREAM &&
+ tmp_sock->sk.sk_state != LLCP_LISTEN)
+ continue;
+
+ if (tmp_sock->sk.sk_type == SOCK_DGRAM &&
+ tmp_sock->sk.sk_state != LLCP_BOUND)
continue;
if (tmp_sock->service_name == NULL ||
@@ -421,10 +467,9 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
{
u8 *gb_cur, *version_tlv, version, version_length;
- u8 *lto_tlv, lto, lto_length;
+ u8 *lto_tlv, lto_length;
u8 *wks_tlv, wks_length;
u8 *miux_tlv, miux_length;
- __be16 miux;
u8 gb_len = 0;
int ret = 0;
@@ -433,9 +478,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
1, &version_length);
gb_len += version_length;
- /* 1500 ms */
- lto = 150;
- lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &lto, 1, &lto_length);
+ lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, &lto_length);
gb_len += lto_length;
pr_debug("Local wks 0x%lx\n", local->local_wks);
@@ -443,8 +486,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
&wks_length);
gb_len += wks_length;
- miux = cpu_to_be16(LLCP_MAX_MIUX);
- miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+ miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
&miux_length);
gb_len += miux_length;
@@ -610,7 +652,12 @@ static void nfc_llcp_tx_work(struct work_struct *work)
if (skb != NULL) {
sk = skb->sk;
llcp_sock = nfc_llcp_sock(sk);
- if (llcp_sock != NULL) {
+
+ if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) {
+ nfc_llcp_send_symm(local->dev);
+ } else {
+ struct sk_buff *copy_skb = NULL;
+ u8 ptype = nfc_llcp_ptype(skb);
int ret;
pr_debug("Sending pending skb\n");
@@ -618,24 +665,29 @@ static void nfc_llcp_tx_work(struct work_struct *work)
DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb->len, true);
+ if (ptype == LLCP_PDU_I)
+ copy_skb = skb_copy(skb, GFP_ATOMIC);
+
nfc_llcp_send_to_raw_sock(local, skb,
NFC_LLCP_DIRECTION_TX);
ret = nfc_data_exchange(local->dev, local->target_idx,
skb, nfc_llcp_recv, local);
- if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) {
- skb = skb_get(skb);
- skb_queue_tail(&llcp_sock->tx_pending_queue,
- skb);
+ if (ret) {
+ kfree_skb(copy_skb);
+ goto out;
}
- } else {
- nfc_llcp_send_symm(local->dev);
+
+ if (ptype == LLCP_PDU_I && copy_skb)
+ skb_queue_tail(&llcp_sock->tx_pending_queue,
+ copy_skb);
}
} else {
nfc_llcp_send_symm(local->dev);
}
+out:
mod_timer(&local->link_timer,
jiffies + msecs_to_jiffies(2 * local->remote_lto));
}
@@ -704,6 +756,39 @@ static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
return NULL;
}
+static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
+ struct sk_buff *skb)
+{
+ struct nfc_llcp_sock *llcp_sock;
+ struct nfc_llcp_ui_cb *ui_cb;
+ u8 dsap, ssap;
+
+ dsap = nfc_llcp_dsap(skb);
+ ssap = nfc_llcp_ssap(skb);
+
+ ui_cb = nfc_llcp_ui_skb_cb(skb);
+ ui_cb->dsap = dsap;
+ ui_cb->ssap = ssap;
+
+ printk("%s %d %d\n", __func__, dsap, ssap);
+
+ pr_debug("%d %d\n", dsap, ssap);
+
+ /* We're looking for a bound socket, not a client one */
+ llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
+ if (llcp_sock == NULL || llcp_sock->sk.sk_type != SOCK_DGRAM)
+ return;
+
+ /* There is no sequence with UI frames */
+ skb_pull(skb, LLCP_HEADER_SIZE);
+ if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
+ pr_err("receive queue is full\n");
+ skb_queue_head(&llcp_sock->tx_backlog_queue, skb);
+ }
+
+ nfc_llcp_sock_put(llcp_sock);
+}
+
static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
struct sk_buff *skb)
{
@@ -823,9 +908,6 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
fail:
/* Send DM */
nfc_llcp_send_dm(local, dsap, ssap, reason);
-
- return;
-
}
int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
@@ -903,15 +985,18 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
/* Remove skbs from the pending queue */
if (llcp_sock->send_ack_n != nr) {
struct sk_buff *s, *tmp;
+ u8 n;
llcp_sock->send_ack_n = nr;
/* Remove and free all skbs until ns == nr */
skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) {
+ n = nfc_llcp_ns(s);
+
skb_unlink(s, &llcp_sock->tx_pending_queue);
kfree_skb(s);
- if (nfc_llcp_ns(s) == nr)
+ if (n == nr)
break;
}
@@ -953,6 +1038,9 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
sk = &llcp_sock->sk;
lock_sock(sk);
+
+ nfc_llcp_socket_purge(llcp_sock);
+
if (sk->sk_state == LLCP_CLOSED) {
release_sock(sk);
nfc_llcp_sock_put(llcp_sock);
@@ -1027,7 +1115,7 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
}
if (llcp_sock == NULL) {
- pr_err("Invalid DM\n");
+ pr_debug("Already closed\n");
return;
}
@@ -1038,8 +1126,100 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
sk->sk_state_change(sk);
nfc_llcp_sock_put(llcp_sock);
+}
- return;
+static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
+ struct sk_buff *skb)
+{
+ struct nfc_llcp_sock *llcp_sock;
+ u8 dsap, ssap, *tlv, type, length, tid, sap;
+ u16 tlv_len, offset;
+ char *service_name;
+ size_t service_name_len;
+
+ dsap = nfc_llcp_dsap(skb);
+ ssap = nfc_llcp_ssap(skb);
+
+ pr_debug("%d %d\n", dsap, ssap);
+
+ if (dsap != LLCP_SAP_SDP || ssap != LLCP_SAP_SDP) {
+ pr_err("Wrong SNL SAP\n");
+ return;
+ }
+
+ tlv = &skb->data[LLCP_HEADER_SIZE];
+ tlv_len = skb->len - LLCP_HEADER_SIZE;
+ offset = 0;
+
+ while (offset < tlv_len) {
+ type = tlv[0];
+ length = tlv[1];
+
+ switch (type) {
+ case LLCP_TLV_SDREQ:
+ tid = tlv[2];
+ service_name = (char *) &tlv[3];
+ service_name_len = length - 1;
+
+ pr_debug("Looking for %.16s\n", service_name);
+
+ if (service_name_len == strlen("urn:nfc:sn:sdp") &&
+ !strncmp(service_name, "urn:nfc:sn:sdp",
+ service_name_len)) {
+ sap = 1;
+ goto send_snl;
+ }
+
+ llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
+ service_name_len);
+ if (!llcp_sock) {
+ sap = 0;
+ goto send_snl;
+ }
+
+ /*
+ * We found a socket but its ssap has not been reserved
+ * yet. We need to assign it for good and send a reply.
+ * The ssap will be freed when the socket is closed.
+ */
+ if (llcp_sock->ssap == LLCP_SDP_UNBOUND) {
+ atomic_t *client_count;
+
+ sap = nfc_llcp_reserve_sdp_ssap(local);
+
+ pr_debug("Reserving %d\n", sap);
+
+ if (sap == LLCP_SAP_MAX) {
+ sap = 0;
+ goto send_snl;
+ }
+
+ client_count =
+ &local->local_sdp_cnt[sap -
+ LLCP_WKS_NUM_SAP];
+
+ atomic_inc(client_count);
+
+ llcp_sock->ssap = sap;
+ llcp_sock->reserved_ssap = sap;
+ } else {
+ sap = llcp_sock->ssap;
+ }
+
+ pr_debug("%p %d\n", llcp_sock, sap);
+
+send_snl:
+ nfc_llcp_send_snl(local, tid, sap);
+ break;
+
+ default:
+ pr_err("Invalid SNL tlv value 0x%x\n", type);
+ break;
+ }
+
+ offset += length + 2;
+ tlv += length + 2;
+ }
}
static void nfc_llcp_rx_work(struct work_struct *work)
@@ -1072,6 +1252,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
pr_debug("SYMM\n");
break;
+ case LLCP_PDU_UI:
+ pr_debug("UI\n");
+ nfc_llcp_recv_ui(local, skb);
+ break;
+
case LLCP_PDU_CONNECT:
pr_debug("CONNECT\n");
nfc_llcp_recv_connect(local, skb);
@@ -1092,6 +1277,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
nfc_llcp_recv_dm(local, skb);
break;
+ case LLCP_PDU_SNL:
+ pr_debug("SNL\n");
+ nfc_llcp_recv_snl(local, skb);
+ break;
+
case LLCP_PDU_I:
case LLCP_PDU_RR:
case LLCP_PDU_RNR:
@@ -1104,8 +1294,6 @@ static void nfc_llcp_rx_work(struct work_struct *work)
schedule_work(&local->tx_work);
kfree_skb(local->rx_pending);
local->rx_pending = NULL;
-
- return;
}
void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
@@ -1121,8 +1309,6 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
local->rx_pending = skb_get(skb);
del_timer(&local->link_timer);
schedule_work(&local->rx_work);
-
- return;
}
int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
@@ -1205,6 +1391,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
rwlock_init(&local->connecting_sockets.lock);
rwlock_init(&local->raw_sockets.lock);
+ local->lto = 150; /* 1500 ms */
+ local->rw = LLCP_MAX_RW;
+ local->miux = cpu_to_be16(LLCP_MAX_MIUX);
+
nfc_llcp_build_gb(local);
local->remote_miu = LLCP_DEFAULT_MIU;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index fdb2d24e60bd..0d62366f8cc3 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -64,6 +64,9 @@ struct nfc_llcp_local {
u32 target_idx;
u8 rf_mode;
u8 comm_mode;
+ u8 lto;
+ u8 rw;
+ __be16 miux;
unsigned long local_wks; /* Well known services */
unsigned long local_sdp; /* Local services */
unsigned long local_sap; /* Local SAPs, not available for discovery */
@@ -124,6 +127,13 @@ struct nfc_llcp_sock {
struct sock *parent;
};
+struct nfc_llcp_ui_cb {
+ __u8 dsap;
+ __u8 ssap;
+};
+
+#define nfc_llcp_ui_skb_cb(__skb) ((struct nfc_llcp_ui_cb *)&((__skb)->cb[0]))
+
#define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk))
#define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev)
@@ -209,10 +219,13 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_symm(struct nfc_dev *dev);
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap);
int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
struct msghdr *msg, size_t len);
+int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
+ struct msghdr *msg, size_t len);
int nfc_llcp_send_rr(struct nfc_llcp_sock *sock);
/* Socket API */
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 63e4cdc92376..0fa1e92ceac8 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -205,8 +205,8 @@ static int llcp_sock_listen(struct socket *sock, int backlog)
lock_sock(sk);
- if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
- || sk->sk_state != LLCP_BOUND) {
+ if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) ||
+ sk->sk_state != LLCP_BOUND) {
ret = -EBADFD;
goto error;
}
@@ -608,6 +608,25 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
+ if (sk->sk_type == SOCK_DGRAM) {
+ struct sockaddr_nfc_llcp *addr =
+ (struct sockaddr_nfc_llcp *)msg->msg_name;
+
+ if (msg->msg_namelen < sizeof(*addr)) {
+ release_sock(sk);
+
+ pr_err("Invalid socket address length %d\n",
+ msg->msg_namelen);
+
+ return -EINVAL;
+ }
+
+ release_sock(sk);
+
+ return nfc_llcp_send_ui_frame(llcp_sock, addr->dsap, addr->ssap,
+ msg, len);
+ }
+
if (sk->sk_state != LLCP_CONNECTED) {
release_sock(sk);
return -ENOTCONN;
@@ -663,11 +682,28 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return -EFAULT;
}
+ if (sk->sk_type == SOCK_DGRAM && msg->msg_name) {
+ struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb);
+ struct sockaddr_nfc_llcp sockaddr;
+
+ pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
+
+ sockaddr.sa_family = AF_NFC;
+ sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP;
+ sockaddr.dsap = ui_cb->dsap;
+ sockaddr.ssap = ui_cb->ssap;
+
+ memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr));
+ msg->msg_namelen = sizeof(sockaddr);
+ }
+
/* Mark read part of skb as used */
if (!(flags & MSG_PEEK)) {
/* SOCK_STREAM: re-queue skb if it contains unreceived data */
- if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) {
+ if (sk->sk_type == SOCK_STREAM ||
+ sk->sk_type == SOCK_DGRAM ||
+ sk->sk_type == SOCK_RAW) {
skb_pull(skb, copied);
if (skb->len) {
skb_queue_head(&sk->sk_receive_queue, skb);
diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig
index decdc49b26d8..6d69b5f0f19b 100644
--- a/net/nfc/nci/Kconfig
+++ b/net/nfc/nci/Kconfig
@@ -1,6 +1,6 @@
config NFC_NCI
- depends on NFC && EXPERIMENTAL
- tristate "NCI protocol support (EXPERIMENTAL)"
+ depends on NFC
+ tristate "NCI protocol support"
default n
help
NCI (NFC Controller Interface) is a communication protocol between
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index acf9abb7d99b..5f98dc1bf039 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -205,10 +205,10 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
cmd.num_disc_configs = 0;
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_JEWEL_MASK
- || protocols & NFC_PROTO_MIFARE_MASK
- || protocols & NFC_PROTO_ISO14443_MASK
- || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_JEWEL_MASK ||
+ protocols & NFC_PROTO_MIFARE_MASK ||
+ protocols & NFC_PROTO_ISO14443_MASK ||
+ protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_A_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -224,8 +224,8 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_FELICA_MASK
- || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_FELICA_MASK ||
+ protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_F_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -414,13 +414,13 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_set_config_param param;
__u8 local_gb[NFC_MAX_GT_LEN];
- int i, rc = 0;
+ int i;
param.val = nfc_get_local_general_bytes(nfc_dev, &param.len);
if ((param.val == NULL) || (param.len == 0))
- return rc;
+ return 0;
- if (param.len > NCI_MAX_PARAM_LEN)
+ if (param.len > NFC_MAX_GT_LEN)
return -EINVAL;
for (i = 0; i < param.len; i++)
@@ -429,10 +429,8 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
param.id = NCI_PN_ATR_REQ_GEN_BYTES;
param.val = local_gb;
- rc = nci_request(ndev, nci_set_config_req, (unsigned long)&param,
- msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
-
- return rc;
+ return nci_request(ndev, nci_set_config_req, (unsigned long)&param,
+ msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
}
static int nci_start_poll(struct nfc_dev *nfc_dev,
@@ -579,7 +577,6 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
}
}
-
static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
__u8 comm_mode, __u8 *gb, size_t gb_len)
{
@@ -806,8 +803,8 @@ int nci_recv_frame(struct sk_buff *skb)
pr_debug("len %d\n", skb->len);
- if (!ndev || (!test_bit(NCI_UP, &ndev->flags)
- && !test_bit(NCI_INIT, &ndev->flags))) {
+ if (!ndev || (!test_bit(NCI_UP, &ndev->flags) &&
+ !test_bit(NCI_INIT, &ndev->flags))) {
kfree_skb(skb);
return -ENXIO;
}
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index c1b5285cbde7..3568ae16786d 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -29,6 +29,8 @@
#include "nfc.h"
+#include "llcp/llcp.h"
+
static struct genl_multicast_group nfc_genl_event_mcgrp = {
.name = NFC_GENL_MCAST_EVENT_NAME,
};
@@ -364,7 +366,8 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) ||
nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) ||
- nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up))
+ nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) ||
+ nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode))
goto nla_put_failure;
return genlmsg_end(msg, hdr);
@@ -590,7 +593,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
((!info->attrs[NFC_ATTR_IM_PROTOCOLS] &&
!info->attrs[NFC_ATTR_PROTOCOLS]) &&
- !info->attrs[NFC_ATTR_TM_PROTOCOLS]))
+ !info->attrs[NFC_ATTR_TM_PROTOCOLS]))
return -EINVAL;
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -715,6 +718,146 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
return rc;
}
+static int nfc_genl_send_params(struct sk_buff *msg,
+ struct nfc_llcp_local *local,
+ u32 portid, u32 seq)
+{
+ void *hdr;
+
+ hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, 0,
+ NFC_CMD_LLC_GET_PARAMS);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, local->dev->idx) ||
+ nla_put_u8(msg, NFC_ATTR_LLC_PARAM_LTO, local->lto) ||
+ nla_put_u8(msg, NFC_ATTR_LLC_PARAM_RW, local->rw) ||
+ nla_put_u16(msg, NFC_ATTR_LLC_PARAM_MIUX, be16_to_cpu(local->miux)))
+ goto nla_put_failure;
+
+ return genlmsg_end(msg, hdr);
+
+nla_put_failure:
+
+ genlmsg_cancel(msg, hdr);
+ return -EMSGSIZE;
+}
+
+static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
+{
+ struct nfc_dev *dev;
+ struct nfc_llcp_local *local;
+ int rc = 0;
+ struct sk_buff *msg = NULL;
+ u32 idx;
+
+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+ return -EINVAL;
+
+ idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+ dev = nfc_get_device(idx);
+ if (!dev)
+ return -ENODEV;
+
+ device_lock(&dev->dev);
+
+ local = nfc_llcp_find_local(dev);
+ if (!local) {
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
+
+exit:
+ device_unlock(&dev->dev);
+
+ nfc_put_device(dev);
+
+ if (rc < 0) {
+ if (msg)
+ nlmsg_free(msg);
+
+ return rc;
+ }
+
+ return genlmsg_reply(msg, info);
+}
+
+static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
+{
+ struct nfc_dev *dev;
+ struct nfc_llcp_local *local;
+ u8 rw = 0;
+ u16 miux = 0;
+ u32 idx;
+ int rc = 0;
+
+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+ (!info->attrs[NFC_ATTR_LLC_PARAM_LTO] &&
+ !info->attrs[NFC_ATTR_LLC_PARAM_RW] &&
+ !info->attrs[NFC_ATTR_LLC_PARAM_MIUX]))
+ return -EINVAL;
+
+ if (info->attrs[NFC_ATTR_LLC_PARAM_RW]) {
+ rw = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_RW]);
+
+ if (rw > LLCP_MAX_RW)
+ return -EINVAL;
+ }
+
+ if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) {
+ miux = nla_get_u16(info->attrs[NFC_ATTR_LLC_PARAM_MIUX]);
+
+ if (miux > LLCP_MAX_MIUX)
+ return -EINVAL;
+ }
+
+ idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+ dev = nfc_get_device(idx);
+ if (!dev)
+ return -ENODEV;
+
+ device_lock(&dev->dev);
+
+ local = nfc_llcp_find_local(dev);
+ if (!local) {
+ nfc_put_device(dev);
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
+ if (dev->dep_link_up) {
+ rc = -EINPROGRESS;
+ goto exit;
+ }
+
+ local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
+ }
+
+ if (info->attrs[NFC_ATTR_LLC_PARAM_RW])
+ local->rw = rw;
+
+ if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
+ local->miux = cpu_to_be16(miux);
+
+exit:
+ device_unlock(&dev->dev);
+
+ nfc_put_device(dev);
+
+ return rc;
+}
+
static struct genl_ops nfc_genl_ops[] = {
{
.cmd = NFC_CMD_GET_DEVICE,
@@ -759,6 +902,16 @@ static struct genl_ops nfc_genl_ops[] = {
.done = nfc_genl_dump_targets_done,
.policy = nfc_genl_policy,
},
+ {
+ .cmd = NFC_CMD_LLC_GET_PARAMS,
+ .doit = nfc_genl_llc_get_params,
+ .policy = nfc_genl_policy,
+ },
+ {
+ .cmd = NFC_CMD_LLC_SET_PARAMS,
+ .doit = nfc_genl_llc_set_params,
+ .policy = nfc_genl_policy,
+ },
};
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index c5e42b79a418..87d914d2876a 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -56,6 +56,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev);
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
+struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
int __init nfc_llcp_init(void);
void nfc_llcp_exit(void);
@@ -97,6 +98,11 @@ static inline int nfc_llcp_data_received(struct nfc_dev *dev,
return 0;
}
+static inline struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
+{
+ return NULL;
+}
+
static inline int nfc_llcp_init(void)
{
return 0;
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 8b8a6a2b2bad..313bf1bc848a 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -256,7 +256,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
return rc ? : copied;
}
-
static const struct proto_ops rawsock_ops = {
.family = PF_NFC,
.owner = THIS_MODULE,
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 08114478cb85..ac2defeeba83 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -28,6 +28,7 @@
#include <linux/if_arp.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
+#include <net/ipv6.h>
#include <net/checksum.h>
#include <net/dsfield.h>
@@ -162,6 +163,53 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
*addr = new_addr;
}
+static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
+ __be32 addr[4], const __be32 new_addr[4])
+{
+ int transport_len = skb->len - skb_transport_offset(skb);
+
+ if (l4_proto == IPPROTO_TCP) {
+ if (likely(transport_len >= sizeof(struct tcphdr)))
+ inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
+ addr, new_addr, 1);
+ } else if (l4_proto == IPPROTO_UDP) {
+ if (likely(transport_len >= sizeof(struct udphdr))) {
+ struct udphdr *uh = udp_hdr(skb);
+
+ if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+ inet_proto_csum_replace16(&uh->check, skb,
+ addr, new_addr, 1);
+ if (!uh->check)
+ uh->check = CSUM_MANGLED_0;
+ }
+ }
+ }
+}
+
+static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
+ __be32 addr[4], const __be32 new_addr[4],
+ bool recalculate_csum)
+{
+ if (recalculate_csum)
+ update_ipv6_checksum(skb, l4_proto, addr, new_addr);
+
+ skb->rxhash = 0;
+ memcpy(addr, new_addr, sizeof(__be32[4]));
+}
+
+static void set_ipv6_tc(struct ipv6hdr *nh, u8 tc)
+{
+ nh->priority = tc >> 4;
+ nh->flow_lbl[0] = (nh->flow_lbl[0] & 0x0F) | ((tc & 0x0F) << 4);
+}
+
+static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl)
+{
+ nh->flow_lbl[0] = (nh->flow_lbl[0] & 0xF0) | (fl & 0x000F0000) >> 16;
+ nh->flow_lbl[1] = (fl & 0x0000FF00) >> 8;
+ nh->flow_lbl[2] = fl & 0x000000FF;
+}
+
static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl)
{
csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8));
@@ -195,6 +243,47 @@ static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key)
return 0;
}
+static int set_ipv6(struct sk_buff *skb, const struct ovs_key_ipv6 *ipv6_key)
+{
+ struct ipv6hdr *nh;
+ int err;
+ __be32 *saddr;
+ __be32 *daddr;
+
+ err = make_writable(skb, skb_network_offset(skb) +
+ sizeof(struct ipv6hdr));
+ if (unlikely(err))
+ return err;
+
+ nh = ipv6_hdr(skb);
+ saddr = (__be32 *)&nh->saddr;
+ daddr = (__be32 *)&nh->daddr;
+
+ if (memcmp(ipv6_key->ipv6_src, saddr, sizeof(ipv6_key->ipv6_src)))
+ set_ipv6_addr(skb, ipv6_key->ipv6_proto, saddr,
+ ipv6_key->ipv6_src, true);
+
+ if (memcmp(ipv6_key->ipv6_dst, daddr, sizeof(ipv6_key->ipv6_dst))) {
+ unsigned int offset = 0;
+ int flags = IP6_FH_F_SKIP_RH;
+ bool recalc_csum = true;
+
+ if (ipv6_ext_hdr(nh->nexthdr))
+ recalc_csum = ipv6_find_hdr(skb, &offset,
+ NEXTHDR_ROUTING, NULL,
+ &flags) != NEXTHDR_ROUTING;
+
+ set_ipv6_addr(skb, ipv6_key->ipv6_proto, daddr,
+ ipv6_key->ipv6_dst, recalc_csum);
+ }
+
+ set_ipv6_tc(nh, ipv6_key->ipv6_tclass);
+ set_ipv6_fl(nh, ntohl(ipv6_key->ipv6_label));
+ nh->hop_limit = ipv6_key->ipv6_hlimit;
+
+ return 0;
+}
+
/* Must follow make_writable() since that can move the skb data. */
static void set_tp_port(struct sk_buff *skb, __be16 *port,
__be16 new_port, __sum16 *check)
@@ -339,6 +428,10 @@ static int execute_set_action(struct sk_buff *skb,
skb->priority = nla_get_u32(nested_attr);
break;
+ case OVS_KEY_ATTR_SKB_MARK:
+ skb->mark = nla_get_u32(nested_attr);
+ break;
+
case OVS_KEY_ATTR_ETHERNET:
err = set_eth_addr(skb, nla_data(nested_attr));
break;
@@ -347,6 +440,10 @@ static int execute_set_action(struct sk_buff *skb,
err = set_ipv4(skb, nla_data(nested_attr));
break;
+ case OVS_KEY_ATTR_IPV6:
+ err = set_ipv6(skb, nla_data(nested_attr));
+ break;
+
case OVS_KEY_ATTR_TCP:
err = set_tcp(skb, nla_data(nested_attr));
break;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 4c4b62ccc7d7..f996db343247 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -208,7 +208,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
int error;
int key_len;
- stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
+ stats = this_cpu_ptr(dp->stats_percpu);
/* Extract flow from 'skb' into 'key'. */
error = ovs_flow_extract(skb, p->port_no, &key, &key_len);
@@ -282,7 +282,7 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
return 0;
err:
- stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
+ stats = this_cpu_ptr(dp->stats_percpu);
u64_stats_update_begin(&stats->sync);
stats->n_lost++;
@@ -479,8 +479,10 @@ static int validate_set(const struct nlattr *a,
switch (key_type) {
const struct ovs_key_ipv4 *ipv4_key;
+ const struct ovs_key_ipv6 *ipv6_key;
case OVS_KEY_ATTR_PRIORITY:
+ case OVS_KEY_ATTR_SKB_MARK:
case OVS_KEY_ATTR_ETHERNET:
break;
@@ -500,6 +502,25 @@ static int validate_set(const struct nlattr *a,
break;
+ case OVS_KEY_ATTR_IPV6:
+ if (flow_key->eth.type != htons(ETH_P_IPV6))
+ return -EINVAL;
+
+ if (!flow_key->ip.proto)
+ return -EINVAL;
+
+ ipv6_key = nla_data(ovs_key);
+ if (ipv6_key->ipv6_proto != flow_key->ip.proto)
+ return -EINVAL;
+
+ if (ipv6_key->ipv6_frag != flow_key->ip.frag)
+ return -EINVAL;
+
+ if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000)
+ return -EINVAL;
+
+ break;
+
case OVS_KEY_ATTR_TCP:
if (flow_key->ip.proto != IPPROTO_TCP)
return -EINVAL;
@@ -675,6 +696,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
goto err_flow_free;
err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority,
+ &flow->key.phy.skb_mark,
&flow->key.phy.in_port,
a[OVS_PACKET_ATTR_KEY]);
if (err)
@@ -694,6 +716,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
OVS_CB(packet)->flow = flow;
packet->priority = flow->key.phy.priority;
+ packet->mark = flow->key.phy.skb_mark;
rcu_read_lock();
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 733cbf49ed1f..c3294cebc4f2 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -604,6 +604,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
key->phy.priority = skb->priority;
key->phy.in_port = in_port;
+ key->phy.skb_mark = skb->mark;
skb_reset_mac_header(skb);
@@ -689,7 +690,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
}
}
- } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
+ } else if ((key->eth.type == htons(ETH_P_ARP) ||
+ key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) {
struct arp_eth_header *arp;
arp = (struct arp_eth_header *)skb_network_header(skb);
@@ -802,6 +804,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ENCAP] = -1,
[OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
[OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
+ [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32),
[OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
[OVS_KEY_ATTR_VLAN] = sizeof(__be16),
[OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
@@ -987,6 +990,10 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
} else {
swkey->phy.in_port = DP_MAX_PORTS;
}
+ if (attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
+ swkey->phy.skb_mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
+ attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
+ }
/* Data attributes. */
if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET)))
@@ -1086,7 +1093,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
if (err)
return err;
}
- } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+ } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+ swkey->eth.type == htons(ETH_P_RARP)) {
const struct ovs_key_arp *arp_key;
if (!(attrs & (1 << OVS_KEY_ATTR_ARP)))
@@ -1113,6 +1121,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
/**
* ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
+ * @priority: receives the skb priority
+ * @mark: receives the skb mark
* @in_port: receives the extracted input port.
* @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence.
@@ -1122,7 +1132,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
* get the metadata, that is, the parts of the flow key that cannot be
* extracted from the packet itself.
*/
-int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
+int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
const struct nlattr *attr)
{
const struct nlattr *nla;
@@ -1130,6 +1140,7 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
*in_port = DP_MAX_PORTS;
*priority = 0;
+ *mark = 0;
nla_for_each_nested(nla, attr, rem) {
int type = nla_type(nla);
@@ -1148,6 +1159,10 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
return -EINVAL;
*in_port = nla_get_u32(nla);
break;
+
+ case OVS_KEY_ATTR_SKB_MARK:
+ *mark = nla_get_u32(nla);
+ break;
}
}
}
@@ -1169,6 +1184,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port))
goto nla_put_failure;
+ if (swkey->phy.skb_mark &&
+ nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, swkey->phy.skb_mark))
+ goto nla_put_failure;
+
nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
if (!nla)
goto nla_put_failure;
@@ -1222,7 +1241,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
ipv6_key->ipv6_tclass = swkey->ip.tos;
ipv6_key->ipv6_hlimit = swkey->ip.ttl;
ipv6_key->ipv6_frag = swkey->ip.frag;
- } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+ } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+ swkey->eth.type == htons(ETH_P_RARP)) {
struct ovs_key_arp *arp_key;
nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 14a324eb017b..a7bb60ff3b5b 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -43,6 +43,7 @@ struct sw_flow_actions {
struct sw_flow_key {
struct {
u32 priority; /* Packet QoS priority. */
+ u32 skb_mark; /* SKB mark. */
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
} phy;
struct {
@@ -144,6 +145,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
* ------ --- ------ -----
* OVS_KEY_ATTR_PRIORITY 4 -- 4 8
* OVS_KEY_ATTR_IN_PORT 4 -- 4 8
+ * OVS_KEY_ATTR_SKB_MARK 4 -- 4 8
* OVS_KEY_ATTR_ETHERNET 12 -- 4 16
* OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype)
* OVS_KEY_ATTR_8021Q 4 -- 4 8
@@ -153,14 +155,14 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
* OVS_KEY_ATTR_ICMPV6 2 2 4 8
* OVS_KEY_ATTR_ND 28 -- 4 32
* -------------------------------------------------
- * total 144
+ * total 152
*/
-#define FLOW_BUFSIZE 144
+#define FLOW_BUFSIZE 152
int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
const struct nlattr *);
-int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
+int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
const struct nlattr *);
#define MAX_ACTIONS_BUFSIZE (16 * 1024)
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index a9033481fa5e..a9327e2e48ce 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -114,6 +114,15 @@ error:
return ERR_PTR(err);
}
+static void free_port_rcu(struct rcu_head *rcu)
+{
+ struct netdev_vport *netdev_vport = container_of(rcu,
+ struct netdev_vport, rcu);
+
+ dev_put(netdev_vport->dev);
+ ovs_vport_free(vport_from_priv(netdev_vport));
+}
+
static void netdev_destroy(struct vport *vport)
{
struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
@@ -122,10 +131,7 @@ static void netdev_destroy(struct vport *vport)
netdev_rx_handler_unregister(netdev_vport->dev);
dev_set_promiscuity(netdev_vport->dev, -1);
- synchronize_rcu();
-
- dev_put(netdev_vport->dev);
- ovs_vport_free(vport);
+ call_rcu(&netdev_vport->rcu, free_port_rcu);
}
const char *ovs_netdev_get_name(const struct vport *vport)
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index f7072a25c604..6478079b3417 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -20,12 +20,15 @@
#define VPORT_NETDEV_H 1
#include <linux/netdevice.h>
+#include <linux/rcupdate.h>
#include "vport.h"
struct vport *ovs_netdev_get_vport(struct net_device *dev);
struct netdev_vport {
+ struct rcu_head rcu;
+
struct net_device *dev;
};
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 03779e8a2622..70af0bedbac4 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -333,8 +333,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
{
struct vport_percpu_stats *stats;
- stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
-
+ stats = this_cpu_ptr(vport->percpu_stats);
u64_stats_update_begin(&stats->sync);
stats->rx_packets++;
stats->rx_bytes += skb->len;
@@ -359,7 +358,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
if (likely(sent)) {
struct vport_percpu_stats *stats;
- stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+ stats = this_cpu_ptr(vport->percpu_stats);
u64_stats_update_begin(&stats->sync);
stats->tx_packets++;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 94060edbbd70..e639645e8fec 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1881,7 +1881,35 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
skb_reserve(skb, hlen);
skb_reset_network_header(skb);
- data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
+ if (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;
+ if (sock->type == SOCK_DGRAM) {
+ switch (po->tp_version) {
+ case TPACKET_V2:
+ off = ph.h2->tp_net;
+ break;
+ default:
+ off = ph.h1->tp_net;
+ break;
+ }
+ } else {
+ switch (po->tp_version) {
+ case TPACKET_V2:
+ off = ph.h2->tp_mac;
+ break;
+ default:
+ off = ph.h1->tp_mac;
+ break;
+ }
+ }
+ if (unlikely((off < off_min) || (off_max < off)))
+ return -EINVAL;
+ data = ph.raw + off;
+ } else {
+ data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
+ }
to_write = tp_len;
if (sock->type == SOCK_DGRAM) {
@@ -1907,7 +1935,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
to_write -= dev->hard_header_len;
}
- err = -EFAULT;
offset = offset_in_page(data);
len_max = PAGE_SIZE - offset;
len = ((to_write > len_max) ? len_max : to_write);
@@ -1957,7 +1984,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
mutex_lock(&po->pg_vec_lock);
- err = -EBUSY;
if (saddr == NULL) {
dev = po->prot_hook.dev;
proto = po->num;
@@ -2478,7 +2504,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
__be16 proto = (__force __be16)protocol; /* weird, but documented */
int err;
- if (!capable(CAP_NET_RAW))
+ if (!ns_capable(net->user_ns, CAP_NET_RAW))
return -EPERM;
if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
sock->type != SOCK_PACKET)
@@ -3111,6 +3137,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return fanout_add(sk, val & 0xffff, val >> 16);
}
+ case PACKET_TX_HAS_OFF:
+ {
+ unsigned int val;
+
+ if (optlen != sizeof(val))
+ return -EINVAL;
+ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
+ return -EBUSY;
+ if (copy_from_user(&val, optval, sizeof(val)))
+ return -EFAULT;
+ po->tp_tx_has_off = !!val;
+ return 0;
+ }
default:
return -ENOPROTOOPT;
}
@@ -3202,6 +3241,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
((u32)po->fanout->type << 16)) :
0);
break;
+ case PACKET_TX_HAS_OFF:
+ val = po->tp_tx_has_off;
+ break;
default:
return -ENOPROTOOPT;
}
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 44945f6b7252..e84cab8cb7a9 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -109,6 +109,7 @@ struct packet_sock {
unsigned int tp_hdrlen;
unsigned int tp_reserve;
unsigned int tp_loss:1;
+ unsigned int tp_tx_has_off:1;
unsigned int tp_tstamp;
struct packet_type prot_hook ____cacheline_aligned_in_smp;
};
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 83a8389619aa..0193630d3061 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -70,6 +70,9 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
int err;
u8 pnaddr;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -230,6 +233,9 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
int err;
u8 dst;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 8d2b3d5a7c21..7280ab8810c2 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -50,7 +50,7 @@ struct rds_ib_cache_head {
};
struct rds_ib_refill_cache {
- struct rds_ib_cache_head *percpu;
+ struct rds_ib_cache_head __percpu *percpu;
struct list_head *xfer;
struct list_head *ready;
};
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index 8d194912c695..8c5bc857f04d 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -418,20 +418,21 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
struct rds_ib_refill_cache *cache)
{
unsigned long flags;
- struct rds_ib_cache_head *chp;
struct list_head *old;
+ struct list_head __percpu *chpfirst;
local_irq_save(flags);
- chp = per_cpu_ptr(cache->percpu, smp_processor_id());
- if (!chp->first)
+ chpfirst = __this_cpu_read(cache->percpu->first);
+ if (!chpfirst)
INIT_LIST_HEAD(new_item);
else /* put on front */
- list_add_tail(new_item, chp->first);
- chp->first = new_item;
- chp->count++;
+ list_add_tail(new_item, chpfirst);
- if (chp->count < RDS_IB_RECYCLE_BATCH_COUNT)
+ __this_cpu_write(chpfirst, new_item);
+ __this_cpu_inc(cache->percpu->count);
+
+ if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT)
goto end;
/*
@@ -443,12 +444,13 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
do {
old = xchg(&cache->xfer, NULL);
if (old)
- list_splice_entire_tail(old, chp->first);
- old = cmpxchg(&cache->xfer, NULL, chp->first);
+ list_splice_entire_tail(old, chpfirst);
+ old = cmpxchg(&cache->xfer, NULL, chpfirst);
} while (old);
- chp->first = NULL;
- chp->count = 0;
+
+ __this_cpu_write(chpfirst, NULL);
+ __this_cpu_write(cache->percpu->count, 0);
end:
local_irq_restore(flags);
}
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index a5c952741279..9b9be5279f5d 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -676,7 +676,7 @@ static ssize_t rfkill_soft_store(struct device *dev,
rfkill_set_block(rfkill, state);
mutex_unlock(&rfkill_global_mutex);
- return err ?: count;
+ return count;
}
static u8 user_state_from_blocked(unsigned long state)
@@ -721,7 +721,7 @@ static ssize_t rfkill_state_store(struct device *dev,
rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
mutex_unlock(&rfkill_global_mutex);
- return err ?: count;
+ return count;
}
static ssize_t rfkill_claim_show(struct device *dev,
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 865adb61685a..78fc0937948d 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -213,7 +213,7 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
static struct platform_driver rfkill_gpio_driver = {
.probe = rfkill_gpio_probe,
- .remove = __devexit_p(rfkill_gpio_remove),
+ .remove = rfkill_gpio_remove,
.driver = {
.name = "rfkill_gpio",
.owner = THIS_MODULE,
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
index 11da3018a853..4b5ab21ecb24 100644
--- a/net/rfkill/rfkill-regulator.c
+++ b/net/rfkill/rfkill-regulator.c
@@ -55,7 +55,7 @@ struct rfkill_ops rfkill_regulator_ops = {
.set_block = rfkill_regulator_set_block,
};
-static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
+static int rfkill_regulator_probe(struct platform_device *pdev)
{
struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
struct rfkill_regulator_data *rfkill_data;
@@ -122,7 +122,7 @@ out:
return ret;
}
-static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
+static int rfkill_regulator_remove(struct platform_device *pdev)
{
struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
struct rfkill *rf_kill = rfkill_data->rf_kill;
@@ -137,7 +137,7 @@ static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
static struct platform_driver rfkill_regulator_driver = {
.probe = rfkill_regulator_probe,
- .remove = __devexit_p(rfkill_regulator_remove),
+ .remove = rfkill_regulator_remove,
.driver = {
.name = "rfkill-regulator",
.owner = THIS_MODULE,
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 62fb51face8a..235e01acac51 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -509,7 +509,7 @@ config NET_EMATCH_TEXT
config NET_EMATCH_CANID
tristate "CAN Identifier"
- depends on NET_EMATCH && CAN
+ depends on NET_EMATCH && (CAN=y || CAN=m)
---help---
Say Y here if you want to be able to classify CAN frames based
on CAN Identifier.
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 102761d294cb..65d240cbf74b 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -987,6 +987,9 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
u32 portid = skb ? NETLINK_CB(skb).portid : 0;
int ret = 0, ovr = 0;
+ if ((n->nlmsg_type != RTM_GETACTION) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL);
if (ret < 0)
return ret;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 7ae02892437c..ff55ed6c49b2 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -139,6 +139,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
int err;
int tp_created = 0;
+ if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
replay:
t = nlmsg_data(n);
protocol = TC_H_MIN(t->tcm_info);
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 31f06b633574..6db7855b9029 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -17,6 +17,7 @@
#include <linux/skbuff.h>
#include <linux/cgroup.h>
#include <linux/rcupdate.h>
+#include <linux/fdtable.h>
#include <net/rtnetlink.h>
#include <net/pkt_cls.h>
#include <net/sock.h>
@@ -57,6 +58,28 @@ static void cgrp_css_free(struct cgroup *cgrp)
kfree(cgrp_cls_state(cgrp));
}
+static int update_classid(const void *v, struct file *file, unsigned n)
+{
+ int err;
+ struct socket *sock = sock_from_file(file, &err);
+ if (sock)
+ sock->sk->sk_classid = (u32)(unsigned long)v;
+ return 0;
+}
+
+static void cgrp_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+{
+ struct task_struct *p;
+ void *v;
+
+ cgroup_taskset_for_each(p, cgrp, tset) {
+ task_lock(p);
+ v = (void *)(unsigned long)task_cls_classid(p);
+ iterate_fd(p->files, 0, update_classid, v);
+ task_unlock(p);
+ }
+}
+
static u64 read_classid(struct cgroup *cgrp, struct cftype *cft)
{
return cgrp_cls_state(cgrp)->classid;
@@ -82,6 +105,7 @@ struct cgroup_subsys net_cls_subsys = {
.css_alloc = cgrp_css_alloc,
.css_online = cgrp_css_online,
.css_free = cgrp_css_free,
+ .attach = cgrp_attach,
.subsys_id = net_cls_subsys_id,
.base_cftypes = ss_files,
.module = THIS_MODULE,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index a18d975db59c..d84f7e734cd7 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -495,16 +495,15 @@ EXPORT_SYMBOL(qdisc_watchdog_init);
void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
{
- ktime_t time;
-
if (test_bit(__QDISC_STATE_DEACTIVATED,
&qdisc_root_sleeping(wd->qdisc)->state))
return;
qdisc_throttled(wd->qdisc);
- time = ktime_set(0, 0);
- time = ktime_add_ns(time, PSCHED_TICKS2NS(expires));
- hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
+
+ hrtimer_start(&wd->timer,
+ ns_to_ktime(PSCHED_TICKS2NS(expires)),
+ HRTIMER_MODE_ABS);
}
EXPORT_SYMBOL(qdisc_watchdog_schedule);
@@ -834,6 +833,8 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
goto err_out3;
}
lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
+ if (!netif_is_multiqueue(dev))
+ sch->flags |= TCQ_F_ONETXQUEUE;
}
sch->handle = handle;
@@ -981,6 +982,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
struct Qdisc *p = NULL;
int err;
+ if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;
@@ -1044,6 +1048,9 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
struct Qdisc *q, *p;
int err;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
replay:
/* Reinit, just in case something touches this. */
tcm = nlmsg_data(n);
@@ -1380,6 +1387,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
u32 qid = TC_H_MAJ(clid);
int err;
+ if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 564b9fc8efd3..0e19948470b8 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -509,8 +509,7 @@ static void cbq_ovl_delay(struct cbq_class *cl)
cl->cpriority = TC_CBQ_MAXPRIO;
q->pmask |= (1<<TC_CBQ_MAXPRIO);
- expires = ktime_set(0, 0);
- expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched));
+ expires = ns_to_ktime(PSCHED_TICKS2NS(sched));
if (hrtimer_try_to_cancel(&q->delay_timer) &&
ktime_to_ns(ktime_sub(
hrtimer_get_expires(&q->delay_timer),
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index aefc1504dc88..5d81a4478514 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -53,20 +53,19 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
static inline struct sk_buff *dequeue_skb(struct Qdisc *q)
{
struct sk_buff *skb = q->gso_skb;
+ const struct netdev_queue *txq = q->dev_queue;
if (unlikely(skb)) {
- struct net_device *dev = qdisc_dev(q);
- struct netdev_queue *txq;
-
/* check the reason of requeuing without tx lock first */
- txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+ txq = netdev_get_tx_queue(txq->dev, skb_get_queue_mapping(skb));
if (!netif_xmit_frozen_or_stopped(txq)) {
q->gso_skb = NULL;
q->q.qlen--;
} else
skb = NULL;
} else {
- skb = q->dequeue(q);
+ if (!(q->flags & TCQ_F_ONETXQUEUE) || !netif_xmit_frozen_or_stopped(txq))
+ skb = q->dequeue(q);
}
return skb;
@@ -686,6 +685,8 @@ static void attach_one_default_qdisc(struct net_device *dev,
netdev_info(dev, "activation failed\n");
return;
}
+ if (!netif_is_multiqueue(dev))
+ qdisc->flags |= TCQ_F_ONETXQUEUE;
}
dev_queue->qdisc_sleeping = qdisc;
}
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 9d75b7761313..d2922c0ef57a 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -71,6 +71,12 @@ enum htb_cmode {
HTB_CAN_SEND /* class can send */
};
+struct htb_rate_cfg {
+ u64 rate_bps;
+ u32 mult;
+ u32 shift;
+};
+
/* interior & leaf nodes; props specific to leaves are marked L: */
struct htb_class {
struct Qdisc_class_common common;
@@ -118,11 +124,11 @@ struct htb_class {
int filter_cnt;
/* token bucket parameters */
- struct qdisc_rate_table *rate; /* rate table of the class itself */
- struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
- long buffer, cbuffer; /* token bucket depth/rate */
+ struct htb_rate_cfg rate;
+ struct htb_rate_cfg ceil;
+ s64 buffer, cbuffer; /* token bucket depth/rate */
psched_tdiff_t mbuffer; /* max wait time */
- long tokens, ctokens; /* current number of tokens */
+ s64 tokens, ctokens; /* current number of tokens */
psched_time_t t_c; /* checkpoint time */
};
@@ -162,6 +168,45 @@ struct htb_sched {
struct work_struct work;
};
+static u64 l2t_ns(struct htb_rate_cfg *r, unsigned int len)
+{
+ return ((u64)len * r->mult) >> r->shift;
+}
+
+static void htb_precompute_ratedata(struct htb_rate_cfg *r)
+{
+ u64 factor;
+ u64 mult;
+ int shift;
+
+ r->shift = 0;
+ r->mult = 1;
+ /*
+ * Calibrate mult, shift so that token counting is accurate
+ * for smallest packet size (64 bytes). Token (time in ns) is
+ * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps. It will
+ * work as long as the smallest packet transfer time can be
+ * accurately represented in nanosec.
+ */
+ if (r->rate_bps > 0) {
+ /*
+ * Higher shift gives better accuracy. Find the largest
+ * shift such that mult fits in 32 bits.
+ */
+ for (shift = 0; shift < 16; shift++) {
+ r->shift = shift;
+ factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
+ mult = div64_u64(factor, r->rate_bps);
+ if (mult > UINT_MAX)
+ break;
+ }
+
+ r->shift = shift - 1;
+ factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
+ r->mult = div64_u64(factor, r->rate_bps);
+ }
+}
+
/* find class in global hash table using given handle */
static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
{
@@ -273,7 +318,7 @@ static void htb_add_to_id_tree(struct rb_root *root,
* already in the queue.
*/
static void htb_add_to_wait_tree(struct htb_sched *q,
- struct htb_class *cl, long delay)
+ struct htb_class *cl, s64 delay)
{
struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
@@ -441,14 +486,14 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
htb_remove_class_from_row(q, cl, mask);
}
-static inline long htb_lowater(const struct htb_class *cl)
+static inline s64 htb_lowater(const struct htb_class *cl)
{
if (htb_hysteresis)
return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
else
return 0;
}
-static inline long htb_hiwater(const struct htb_class *cl)
+static inline s64 htb_hiwater(const struct htb_class *cl)
{
if (htb_hysteresis)
return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
@@ -469,9 +514,9 @@ static inline long htb_hiwater(const struct htb_class *cl)
* mode transitions per time unit. The speed gain is about 1/6.
*/
static inline enum htb_cmode
-htb_class_mode(struct htb_class *cl, long *diff)
+htb_class_mode(struct htb_class *cl, s64 *diff)
{
- long toks;
+ s64 toks;
if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
*diff = -toks;
@@ -495,7 +540,7 @@ htb_class_mode(struct htb_class *cl, long *diff)
* to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
*/
static void
-htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
+htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
{
enum htb_cmode new_mode = htb_class_mode(cl, diff);
@@ -581,26 +626,26 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_SUCCESS;
}
-static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, long diff)
+static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff)
{
- long toks = diff + cl->tokens;
+ s64 toks = diff + cl->tokens;
if (toks > cl->buffer)
toks = cl->buffer;
- toks -= (long) qdisc_l2t(cl->rate, bytes);
+ toks -= (s64) l2t_ns(&cl->rate, bytes);
if (toks <= -cl->mbuffer)
toks = 1 - cl->mbuffer;
cl->tokens = toks;
}
-static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, long diff)
+static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff)
{
- long toks = diff + cl->ctokens;
+ s64 toks = diff + cl->ctokens;
if (toks > cl->cbuffer)
toks = cl->cbuffer;
- toks -= (long) qdisc_l2t(cl->ceil, bytes);
+ toks -= (s64) l2t_ns(&cl->ceil, bytes);
if (toks <= -cl->mbuffer)
toks = 1 - cl->mbuffer;
@@ -623,10 +668,10 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
{
int bytes = qdisc_pkt_len(skb);
enum htb_cmode old_mode;
- long diff;
+ s64 diff;
while (cl) {
- diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
+ diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
if (cl->level >= level) {
if (cl->level == level)
cl->xstats.lends++;
@@ -673,7 +718,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
unsigned long stop_at = start + 2;
while (time_before(jiffies, stop_at)) {
struct htb_class *cl;
- long diff;
+ s64 diff;
struct rb_node *p = rb_first(&q->wait_pq[level]);
if (!p)
@@ -684,7 +729,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
return cl->pq_key;
htb_safe_rb_erase(p, q->wait_pq + level);
- diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
+ diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
htb_change_class_mode(q, cl, &diff);
if (cl->cmode != HTB_CAN_SEND)
htb_add_to_wait_tree(q, cl, diff);
@@ -871,10 +916,10 @@ ok:
if (!sch->q.qlen)
goto fin;
- q->now = psched_get_time();
+ q->now = ktime_to_ns(ktime_get());
start_at = jiffies;
- next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
+ next_event = q->now + 5 * NSEC_PER_SEC;
for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
/* common case optimization - skip event handler quickly */
@@ -884,7 +929,7 @@ ok:
if (q->now >= q->near_ev_cache[level]) {
event = htb_do_events(q, level, start_at);
if (!event)
- event = q->now + PSCHED_TICKS_PER_SEC;
+ event = q->now + NSEC_PER_SEC;
q->near_ev_cache[level] = event;
} else
event = q->near_ev_cache[level];
@@ -903,10 +948,17 @@ ok:
}
}
sch->qstats.overlimits++;
- if (likely(next_event > q->now))
- qdisc_watchdog_schedule(&q->watchdog, next_event);
- else
+ if (likely(next_event > q->now)) {
+ if (!test_bit(__QDISC_STATE_DEACTIVATED,
+ &qdisc_root_sleeping(q->watchdog.qdisc)->state)) {
+ ktime_t time = ns_to_ktime(next_event);
+ qdisc_throttled(q->watchdog.qdisc);
+ hrtimer_start(&q->watchdog.timer, time,
+ HRTIMER_MODE_ABS);
+ }
+ } else {
schedule_work(&q->work);
+ }
fin:
return skb;
}
@@ -1082,9 +1134,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
memset(&opt, 0, sizeof(opt));
- opt.rate = cl->rate->rate;
+ opt.rate.rate = cl->rate.rate_bps >> 3;
opt.buffer = cl->buffer;
- opt.ceil = cl->ceil->rate;
+ opt.ceil.rate = cl->ceil.rate_bps >> 3;
opt.cbuffer = cl->cbuffer;
opt.quantum = cl->quantum;
opt.prio = cl->prio;
@@ -1203,9 +1255,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
qdisc_destroy(cl->un.leaf.q);
}
gen_kill_estimator(&cl->bstats, &cl->rate_est);
- qdisc_put_rtab(cl->rate);
- qdisc_put_rtab(cl->ceil);
-
tcf_destroy_chain(&cl->filter_list);
kfree(cl);
}
@@ -1307,7 +1356,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];
struct tc_htb_opt *hopt;
@@ -1326,10 +1374,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
hopt = nla_data(tb[TCA_HTB_PARMS]);
-
- rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
- ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
- if (!rtab || !ctab)
+ if (!hopt->rate.rate || !hopt->ceil.rate)
goto failure;
if (!cl) { /* new class */
@@ -1439,7 +1484,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
* is really leaf before changing cl->un.leaf !
*/
if (!cl->level) {
- cl->quantum = rtab->rate.rate / q->rate2quantum;
+ cl->quantum = hopt->rate.rate / q->rate2quantum;
if (!hopt->quantum && cl->quantum < 1000) {
pr_warning(
"HTB: quantum of class %X is small. Consider r2q change.\n",
@@ -1460,12 +1505,16 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
cl->buffer = hopt->buffer;
cl->cbuffer = hopt->cbuffer;
- if (cl->rate)
- qdisc_put_rtab(cl->rate);
- cl->rate = rtab;
- if (cl->ceil)
- qdisc_put_rtab(cl->ceil);
- cl->ceil = ctab;
+
+ cl->rate.rate_bps = (u64)hopt->rate.rate << 3;
+ cl->ceil.rate_bps = (u64)hopt->ceil.rate << 3;
+
+ htb_precompute_ratedata(&cl->rate);
+ htb_precompute_ratedata(&cl->ceil);
+
+ cl->buffer = hopt->buffer << PSCHED_SHIFT;
+ cl->cbuffer = hopt->buffer << PSCHED_SHIFT;
+
sch_tree_unlock(sch);
qdisc_class_hash_grow(sch, &q->clhash);
@@ -1474,10 +1523,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
return 0;
failure:
- if (rtab)
- qdisc_put_rtab(rtab);
- if (ctab)
- qdisc_put_rtab(ctab);
return err;
}
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 0a4b2f9a0094..5da78a19ac9a 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -63,6 +63,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)
if (qdisc == NULL)
goto err;
priv->qdiscs[ntx] = qdisc;
+ qdisc->flags |= TCQ_F_ONETXQUEUE;
}
sch->flags |= TCQ_F_MQROOT;
@@ -150,7 +151,8 @@ static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
dev_deactivate(dev);
*old = dev_graft_qdisc(dev_queue, new);
-
+ if (new)
+ new->flags |= TCQ_F_ONETXQUEUE;
if (dev->flags & IFF_UP)
dev_activate(dev);
return 0;
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index d1831ca966d4..accec33c454c 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -132,6 +132,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
goto err;
}
priv->qdiscs[i] = qdisc;
+ qdisc->flags |= TCQ_F_ONETXQUEUE;
}
/* If the mqprio options indicate that hardware should own
@@ -205,6 +206,9 @@ static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
*old = dev_graft_qdisc(dev_queue, new);
+ if (new)
+ new->flags |= TCQ_F_ONETXQUEUE;
+
if (dev->flags & IFF_UP)
dev_activate(dev);
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 9687fa1c2275..6ed37652a4c3 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -1,7 +1,8 @@
/*
- * net/sched/sch_qfq.c Quick Fair Queueing Scheduler.
+ * net/sched/sch_qfq.c Quick Fair Queueing Plus Scheduler.
*
* Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente.
+ * Copyright (c) 2012 Paolo Valente.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,12 +20,18 @@
#include <net/pkt_cls.h>
-/* Quick Fair Queueing
- ===================
+/* Quick Fair Queueing Plus
+ ========================
Sources:
- Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient
+ [1] Paolo Valente,
+ "Reducing the Execution Time of Fair-Queueing Schedulers."
+ http://algo.ing.unimo.it/people/paolo/agg-sched/agg-sched.pdf
+
+ Sources for QFQ:
+
+ [2] Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient
Packet Scheduling with Tight Bandwidth Distribution Guarantees."
See also:
@@ -33,6 +40,20 @@
/*
+ QFQ+ divides classes into aggregates of at most MAX_AGG_CLASSES
+ classes. Each aggregate is timestamped with a virtual start time S
+ and a virtual finish time F, and scheduled according to its
+ timestamps. S and F are computed as a function of a system virtual
+ time function V. The classes within each aggregate are instead
+ scheduled with DRR.
+
+ To speed up operations, QFQ+ divides also aggregates into a limited
+ number of groups. Which group a class belongs to depends on the
+ ratio between the maximum packet length for the class and the weight
+ of the class. Groups have their own S and F. In the end, QFQ+
+ schedules groups, then aggregates within groups, then classes within
+ aggregates. See [1] and [2] for a full description.
+
Virtual time computations.
S, F and V are all computed in fixed point arithmetic with
@@ -76,27 +97,28 @@
#define QFQ_MAX_SLOTS 32
/*
- * Shifts used for class<->group mapping. We allow class weights that are
- * in the range [1, 2^MAX_WSHIFT], and we try to map each class i to the
+ * Shifts used for aggregate<->group mapping. We allow class weights that are
+ * in the range [1, 2^MAX_WSHIFT], and we try to map each aggregate i to the
* group with the smallest index that can support the L_i / r_i configured
- * for the class.
+ * for the classes in the aggregate.
*
* grp->index is the index of the group; and grp->slot_shift
* is the shift for the corresponding (scaled) sigma_i.
*/
#define QFQ_MAX_INDEX 24
-#define QFQ_MAX_WSHIFT 12
+#define QFQ_MAX_WSHIFT 10
-#define QFQ_MAX_WEIGHT (1<<QFQ_MAX_WSHIFT)
-#define QFQ_MAX_WSUM (16*QFQ_MAX_WEIGHT)
+#define QFQ_MAX_WEIGHT (1<<QFQ_MAX_WSHIFT) /* see qfq_slot_insert */
+#define QFQ_MAX_WSUM (64*QFQ_MAX_WEIGHT)
#define FRAC_BITS 30 /* fixed point arithmetic */
#define ONE_FP (1UL << FRAC_BITS)
#define IWSUM (ONE_FP/QFQ_MAX_WSUM)
#define QFQ_MTU_SHIFT 16 /* to support TSO/GSO */
-#define QFQ_MIN_SLOT_SHIFT (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX)
-#define QFQ_MIN_LMAX 256 /* min possible lmax for a class */
+#define QFQ_MIN_LMAX 512 /* see qfq_slot_insert */
+
+#define QFQ_MAX_AGG_CLASSES 8 /* max num classes per aggregate allowed */
/*
* Possible group states. These values are used as indexes for the bitmaps
@@ -106,6 +128,8 @@ enum qfq_state { ER, IR, EB, IB, QFQ_MAX_STATE };
struct qfq_group;
+struct qfq_aggregate;
+
struct qfq_class {
struct Qdisc_class_common common;
@@ -116,7 +140,12 @@ struct qfq_class {
struct gnet_stats_queue qstats;
struct gnet_stats_rate_est rate_est;
struct Qdisc *qdisc;
+ struct list_head alist; /* Link for active-classes list. */
+ struct qfq_aggregate *agg; /* Parent aggregate. */
+ int deficit; /* DRR deficit counter. */
+};
+struct qfq_aggregate {
struct hlist_node next; /* Link for the slot list. */
u64 S, F; /* flow timestamps (exact) */
@@ -127,8 +156,18 @@ struct qfq_class {
struct qfq_group *grp;
/* these are copied from the flowset. */
- u32 inv_w; /* ONE_FP/weight */
- u32 lmax; /* Max packet size for this flow. */
+ u32 class_weight; /* Weight of each class in this aggregate. */
+ /* Max pkt size for the classes in this aggregate, DRR quantum. */
+ int lmax;
+
+ u32 inv_w; /* ONE_FP/(sum of weights of classes in aggr.). */
+ u32 budgetmax; /* Max budget for this aggregate. */
+ u32 initial_budget, budget; /* Initial and current budget. */
+
+ int num_classes; /* Number of classes in this aggr. */
+ struct list_head active; /* DRR queue of active classes. */
+
+ struct hlist_node nonfull_next; /* See nonfull_aggs in qfq_sched. */
};
struct qfq_group {
@@ -138,7 +177,7 @@ struct qfq_group {
unsigned int front; /* Index of the front slot. */
unsigned long full_slots; /* non-empty slots */
- /* Array of RR lists of active classes. */
+ /* Array of RR lists of active aggregates. */
struct hlist_head slots[QFQ_MAX_SLOTS];
};
@@ -146,13 +185,28 @@ struct qfq_sched {
struct tcf_proto *filter_list;
struct Qdisc_class_hash clhash;
- u64 V; /* Precise virtual time. */
- u32 wsum; /* weight sum */
+ u64 oldV, V; /* Precise virtual times. */
+ struct qfq_aggregate *in_serv_agg; /* Aggregate being served. */
+ u32 num_active_agg; /* Num. of active aggregates */
+ u32 wsum; /* weight sum */
unsigned long bitmaps[QFQ_MAX_STATE]; /* Group bitmaps. */
struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */
+ u32 min_slot_shift; /* Index of the group-0 bit in the bitmaps. */
+
+ u32 max_agg_classes; /* Max number of classes per aggr. */
+ struct hlist_head nonfull_aggs; /* Aggs with room for more classes. */
};
+/*
+ * Possible reasons why the timestamps of an aggregate are updated
+ * enqueue: the aggregate switches from idle to active and must scheduled
+ * for service
+ * requeue: the aggregate finishes its budget, so it stops being served and
+ * must be rescheduled for service
+ */
+enum update_reason {enqueue, requeue};
+
static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid)
{
struct qfq_sched *q = qdisc_priv(sch);
@@ -182,18 +236,18 @@ static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
* index = log_2(maxlen/weight) but we need to apply the scaling.
* This is used only once at flow creation.
*/
-static int qfq_calc_index(u32 inv_w, unsigned int maxlen)
+static int qfq_calc_index(u32 inv_w, unsigned int maxlen, u32 min_slot_shift)
{
u64 slot_size = (u64)maxlen * inv_w;
unsigned long size_map;
int index = 0;
- size_map = slot_size >> QFQ_MIN_SLOT_SHIFT;
+ size_map = slot_size >> min_slot_shift;
if (!size_map)
goto out;
index = __fls(size_map) + 1; /* basically a log_2 */
- index -= !(slot_size - (1ULL << (index + QFQ_MIN_SLOT_SHIFT - 1)));
+ index -= !(slot_size - (1ULL << (index + min_slot_shift - 1)));
if (index < 0)
index = 0;
@@ -204,66 +258,150 @@ out:
return index;
}
-/* Length of the next packet (0 if the queue is empty). */
-static unsigned int qdisc_peek_len(struct Qdisc *sch)
+static void qfq_deactivate_agg(struct qfq_sched *, struct qfq_aggregate *);
+static void qfq_activate_agg(struct qfq_sched *, struct qfq_aggregate *,
+ enum update_reason);
+
+static void qfq_init_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+ u32 lmax, u32 weight)
{
- struct sk_buff *skb;
+ INIT_LIST_HEAD(&agg->active);
+ hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
+
+ agg->lmax = lmax;
+ agg->class_weight = weight;
+}
+
+static struct qfq_aggregate *qfq_find_agg(struct qfq_sched *q,
+ u32 lmax, u32 weight)
+{
+ struct qfq_aggregate *agg;
+ struct hlist_node *n;
+
+ hlist_for_each_entry(agg, n, &q->nonfull_aggs, nonfull_next)
+ if (agg->lmax == lmax && agg->class_weight == weight)
+ return agg;
+
+ return NULL;
+}
+
- skb = sch->ops->peek(sch);
- return skb ? qdisc_pkt_len(skb) : 0;
+/* Update aggregate as a function of the new number of classes. */
+static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+ int new_num_classes)
+{
+ u32 new_agg_weight;
+
+ if (new_num_classes == q->max_agg_classes)
+ hlist_del_init(&agg->nonfull_next);
+
+ if (agg->num_classes > new_num_classes &&
+ new_num_classes == q->max_agg_classes - 1) /* agg no more full */
+ hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
+
+ agg->budgetmax = new_num_classes * agg->lmax;
+ new_agg_weight = agg->class_weight * new_num_classes;
+ agg->inv_w = ONE_FP/new_agg_weight;
+
+ if (agg->grp == NULL) {
+ int i = qfq_calc_index(agg->inv_w, agg->budgetmax,
+ q->min_slot_shift);
+ agg->grp = &q->groups[i];
+ }
+
+ q->wsum +=
+ (int) agg->class_weight * (new_num_classes - agg->num_classes);
+
+ agg->num_classes = new_num_classes;
+}
+
+/* Add class to aggregate. */
+static void qfq_add_to_agg(struct qfq_sched *q,
+ struct qfq_aggregate *agg,
+ struct qfq_class *cl)
+{
+ cl->agg = agg;
+
+ qfq_update_agg(q, agg, agg->num_classes+1);
+ if (cl->qdisc->q.qlen > 0) { /* adding an active class */
+ list_add_tail(&cl->alist, &agg->active);
+ if (list_first_entry(&agg->active, struct qfq_class, alist) ==
+ cl && q->in_serv_agg != agg) /* agg was inactive */
+ qfq_activate_agg(q, agg, enqueue); /* schedule agg */
+ }
}
-static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *);
-static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
- unsigned int len);
+static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *);
-static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,
- u32 lmax, u32 inv_w, int delta_w)
+static void qfq_destroy_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
{
- int i;
+ if (!hlist_unhashed(&agg->nonfull_next))
+ hlist_del_init(&agg->nonfull_next);
+ if (q->in_serv_agg == agg)
+ q->in_serv_agg = qfq_choose_next_agg(q);
+ kfree(agg);
+}
- /* update qfq-specific data */
- cl->lmax = lmax;
- cl->inv_w = inv_w;
- i = qfq_calc_index(cl->inv_w, cl->lmax);
+/* Deschedule class from within its parent aggregate. */
+static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
+{
+ struct qfq_aggregate *agg = cl->agg;
- cl->grp = &q->groups[i];
- q->wsum += delta_w;
+ list_del(&cl->alist); /* remove from RR queue of the aggregate */
+ if (list_empty(&agg->active)) /* agg is now inactive */
+ qfq_deactivate_agg(q, agg);
}
-static void qfq_update_reactivate_class(struct qfq_sched *q,
- struct qfq_class *cl,
- u32 inv_w, u32 lmax, int delta_w)
+/* Remove class from its parent aggregate. */
+static void qfq_rm_from_agg(struct qfq_sched *q, struct qfq_class *cl)
{
- bool need_reactivation = false;
- int i = qfq_calc_index(inv_w, lmax);
+ struct qfq_aggregate *agg = cl->agg;
- if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
- /*
- * shift cl->F back, to not charge the
- * class for the not-yet-served head
- * packet
- */
- cl->F = cl->S;
- /* remove class from its slot in the old group */
- qfq_deactivate_class(q, cl);
- need_reactivation = true;
+ cl->agg = NULL;
+ if (agg->num_classes == 1) { /* agg being emptied, destroy it */
+ qfq_destroy_agg(q, agg);
+ return;
}
+ qfq_update_agg(q, agg, agg->num_classes-1);
+}
- qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+/* Deschedule class and remove it from its parent aggregate. */
+static void qfq_deact_rm_from_agg(struct qfq_sched *q, struct qfq_class *cl)
+{
+ if (cl->qdisc->q.qlen > 0) /* class is active */
+ qfq_deactivate_class(q, cl);
- if (need_reactivation) /* activate in new group */
- qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+ qfq_rm_from_agg(q, cl);
}
+/* Move class to a new aggregate, matching the new class weight and/or lmax */
+static int qfq_change_agg(struct Qdisc *sch, struct qfq_class *cl, u32 weight,
+ u32 lmax)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_aggregate *new_agg = qfq_find_agg(q, lmax, weight);
+
+ if (new_agg == NULL) { /* create new aggregate */
+ new_agg = kzalloc(sizeof(*new_agg), GFP_ATOMIC);
+ if (new_agg == NULL)
+ return -ENOBUFS;
+ qfq_init_agg(q, new_agg, lmax, weight);
+ }
+ qfq_deact_rm_from_agg(q, cl);
+ qfq_add_to_agg(q, new_agg, cl);
+
+ return 0;
+}
static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct nlattr **tca, unsigned long *arg)
{
struct qfq_sched *q = qdisc_priv(sch);
struct qfq_class *cl = (struct qfq_class *)*arg;
+ bool existing = false;
struct nlattr *tb[TCA_QFQ_MAX + 1];
+ struct qfq_aggregate *new_agg = NULL;
u32 weight, lmax, inv_w;
int err;
int delta_w;
@@ -286,15 +424,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
} else
weight = 1;
- inv_w = ONE_FP / weight;
- weight = ONE_FP / inv_w;
- delta_w = weight - (cl ? ONE_FP / cl->inv_w : 0);
- if (q->wsum + delta_w > QFQ_MAX_WSUM) {
- pr_notice("qfq: total weight out of range (%u + %u)\n",
- delta_w, q->wsum);
- return -EINVAL;
- }
-
if (tb[TCA_QFQ_LMAX]) {
lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
@@ -304,7 +433,23 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
} else
lmax = psched_mtu(qdisc_dev(sch));
- if (cl != NULL) {
+ inv_w = ONE_FP / weight;
+ weight = ONE_FP / inv_w;
+
+ if (cl != NULL &&
+ lmax == cl->agg->lmax &&
+ weight == cl->agg->class_weight)
+ return 0; /* nothing to change */
+
+ delta_w = weight - (cl ? cl->agg->class_weight : 0);
+
+ if (q->wsum + delta_w > QFQ_MAX_WSUM) {
+ pr_notice("qfq: total weight out of range (%d + %u)\n",
+ delta_w, q->wsum);
+ return -EINVAL;
+ }
+
+ if (cl != NULL) { /* modify existing class */
if (tca[TCA_RATE]) {
err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_sleeping_lock(sch),
@@ -312,25 +457,18 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (err)
return err;
}
-
- if (lmax == cl->lmax && inv_w == cl->inv_w)
- return 0; /* nothing to update */
-
- sch_tree_lock(sch);
- qfq_update_reactivate_class(q, cl, inv_w, lmax, delta_w);
- sch_tree_unlock(sch);
-
- return 0;
+ existing = true;
+ goto set_change_agg;
}
+ /* create and init new class */
cl = kzalloc(sizeof(struct qfq_class), GFP_KERNEL);
if (cl == NULL)
return -ENOBUFS;
cl->refcnt = 1;
cl->common.classid = classid;
-
- qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+ cl->deficit = lmax;
cl->qdisc = qdisc_create_dflt(sch->dev_queue,
&pfifo_qdisc_ops, classid);
@@ -341,11 +479,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
err = gen_new_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_sleeping_lock(sch),
tca[TCA_RATE]);
- if (err) {
- qdisc_destroy(cl->qdisc);
- kfree(cl);
- return err;
- }
+ if (err)
+ goto destroy_class;
}
sch_tree_lock(sch);
@@ -354,19 +489,39 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
qdisc_class_hash_grow(sch, &q->clhash);
+set_change_agg:
+ sch_tree_lock(sch);
+ new_agg = qfq_find_agg(q, lmax, weight);
+ if (new_agg == NULL) { /* create new aggregate */
+ sch_tree_unlock(sch);
+ new_agg = kzalloc(sizeof(*new_agg), GFP_KERNEL);
+ if (new_agg == NULL) {
+ err = -ENOBUFS;
+ gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ goto destroy_class;
+ }
+ sch_tree_lock(sch);
+ qfq_init_agg(q, new_agg, lmax, weight);
+ }
+ if (existing)
+ qfq_deact_rm_from_agg(q, cl);
+ qfq_add_to_agg(q, new_agg, cl);
+ sch_tree_unlock(sch);
+
*arg = (unsigned long)cl;
return 0;
+
+destroy_class:
+ qdisc_destroy(cl->qdisc);
+ kfree(cl);
+ return err;
}
static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
{
struct qfq_sched *q = qdisc_priv(sch);
- if (cl->inv_w) {
- q->wsum -= ONE_FP / cl->inv_w;
- cl->inv_w = 0;
- }
-
+ qfq_rm_from_agg(q, cl);
gen_kill_estimator(&cl->bstats, &cl->rate_est);
qdisc_destroy(cl->qdisc);
kfree(cl);
@@ -481,8 +636,8 @@ static int qfq_dump_class(struct Qdisc *sch, unsigned long arg,
nest = nla_nest_start(skb, TCA_OPTIONS);
if (nest == NULL)
goto nla_put_failure;
- if (nla_put_u32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w) ||
- nla_put_u32(skb, TCA_QFQ_LMAX, cl->lmax))
+ if (nla_put_u32(skb, TCA_QFQ_WEIGHT, cl->agg->class_weight) ||
+ nla_put_u32(skb, TCA_QFQ_LMAX, cl->agg->lmax))
goto nla_put_failure;
return nla_nest_end(skb, nest);
@@ -500,8 +655,8 @@ static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
memset(&xstats, 0, sizeof(xstats));
cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
- xstats.weight = ONE_FP/cl->inv_w;
- xstats.lmax = cl->lmax;
+ xstats.weight = cl->agg->class_weight;
+ xstats.lmax = cl->agg->lmax;
if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
@@ -652,16 +807,16 @@ static void qfq_unblock_groups(struct qfq_sched *q, int index, u64 old_F)
* perhaps
*
old_V ^= q->V;
- old_V >>= QFQ_MIN_SLOT_SHIFT;
+ old_V >>= q->min_slot_shift;
if (old_V) {
...
}
*
*/
-static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
+static void qfq_make_eligible(struct qfq_sched *q)
{
- unsigned long vslot = q->V >> QFQ_MIN_SLOT_SHIFT;
- unsigned long old_vslot = old_V >> QFQ_MIN_SLOT_SHIFT;
+ unsigned long vslot = q->V >> q->min_slot_shift;
+ unsigned long old_vslot = q->oldV >> q->min_slot_shift;
if (vslot != old_vslot) {
unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1;
@@ -672,34 +827,38 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
/*
- * If the weight and lmax (max_pkt_size) of the classes do not change,
- * then QFQ guarantees that the slot index is never higher than
- * 2 + ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM).
+ * The index of the slot in which the aggregate is to be inserted must
+ * not be higher than QFQ_MAX_SLOTS-2. There is a '-2' and not a '-1'
+ * because the start time of the group may be moved backward by one
+ * slot after the aggregate has been inserted, and this would cause
+ * non-empty slots to be right-shifted by one position.
*
- * With the current values of the above constants, the index is
- * then guaranteed to never be higher than 2 + 256 * (1 / 16) = 18.
+ * If the weight and lmax (max_pkt_size) of the classes do not change,
+ * then QFQ+ does meet the above contraint according to the current
+ * values of its parameters. In fact, if the weight and lmax of the
+ * classes do not change, then, from the theory, QFQ+ guarantees that
+ * the slot index is never higher than
+ * 2 + QFQ_MAX_AGG_CLASSES * ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) *
+ * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM) = 2 + 8 * 128 * (1 / 64) = 18
*
* When the weight of a class is increased or the lmax of the class is
- * decreased, a new class with smaller slot size may happen to be
- * activated. The activation of this class should be properly delayed
- * to when the service of the class has finished in the ideal system
- * tracked by QFQ. If the activation of the class is not delayed to
- * this reference time instant, then this class may be unjustly served
- * before other classes waiting for service. This may cause
- * (unfrequently) the above bound to the slot index to be violated for
- * some of these unlucky classes.
+ * decreased, a new aggregate with smaller slot size than the original
+ * parent aggregate of the class may happen to be activated. The
+ * activation of this aggregate should be properly delayed to when the
+ * service of the class has finished in the ideal system tracked by
+ * QFQ+. If the activation of the aggregate is not delayed to this
+ * reference time instant, then this aggregate may be unjustly served
+ * before other aggregates waiting for service. This may cause the
+ * above bound to the slot index to be violated for some of these
+ * unlucky aggregates.
*
- * Instead of delaying the activation of the new class, which is quite
- * complex, the following inaccurate but simple solution is used: if
- * the slot index is higher than QFQ_MAX_SLOTS-2, then the timestamps
- * of the class are shifted backward so as to let the slot index
- * become equal to QFQ_MAX_SLOTS-2. This threshold is used because, if
- * the slot index is above it, then the data structure implementing
- * the bucket list either gets immediately corrupted or may get
- * corrupted on a possible next packet arrival that causes the start
- * time of the group to be shifted backward.
+ * Instead of delaying the activation of the new aggregate, which is
+ * quite complex, the following inaccurate but simple solution is used:
+ * if the slot index is higher than QFQ_MAX_SLOTS-2, then the
+ * timestamps of the aggregate are shifted backward so as to let the
+ * slot index become equal to QFQ_MAX_SLOTS-2.
*/
-static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
+static void qfq_slot_insert(struct qfq_group *grp, struct qfq_aggregate *agg,
u64 roundedS)
{
u64 slot = (roundedS - grp->S) >> grp->slot_shift;
@@ -708,22 +867,22 @@ static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
if (unlikely(slot > QFQ_MAX_SLOTS - 2)) {
u64 deltaS = roundedS - grp->S -
((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift);
- cl->S -= deltaS;
- cl->F -= deltaS;
+ agg->S -= deltaS;
+ agg->F -= deltaS;
slot = QFQ_MAX_SLOTS - 2;
}
i = (grp->front + slot) % QFQ_MAX_SLOTS;
- hlist_add_head(&cl->next, &grp->slots[i]);
+ hlist_add_head(&agg->next, &grp->slots[i]);
__set_bit(slot, &grp->full_slots);
}
/* Maybe introduce hlist_first_entry?? */
-static struct qfq_class *qfq_slot_head(struct qfq_group *grp)
+static struct qfq_aggregate *qfq_slot_head(struct qfq_group *grp)
{
return hlist_entry(grp->slots[grp->front].first,
- struct qfq_class, next);
+ struct qfq_aggregate, next);
}
/*
@@ -731,20 +890,20 @@ static struct qfq_class *qfq_slot_head(struct qfq_group *grp)
*/
static void qfq_front_slot_remove(struct qfq_group *grp)
{
- struct qfq_class *cl = qfq_slot_head(grp);
+ struct qfq_aggregate *agg = qfq_slot_head(grp);
- BUG_ON(!cl);
- hlist_del(&cl->next);
+ BUG_ON(!agg);
+ hlist_del(&agg->next);
if (hlist_empty(&grp->slots[grp->front]))
__clear_bit(0, &grp->full_slots);
}
/*
- * Returns the first full queue in a group. As a side effect,
- * adjust the bucket list so the first non-empty bucket is at
- * position 0 in full_slots.
+ * Returns the first aggregate in the first non-empty bucket of the
+ * group. As a side effect, adjusts the bucket list so the first
+ * non-empty bucket is at position 0 in full_slots.
*/
-static struct qfq_class *qfq_slot_scan(struct qfq_group *grp)
+static struct qfq_aggregate *qfq_slot_scan(struct qfq_group *grp)
{
unsigned int i;
@@ -780,7 +939,7 @@ static void qfq_slot_rotate(struct qfq_group *grp, u64 roundedS)
grp->front = (grp->front - i) % QFQ_MAX_SLOTS;
}
-static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
+static void qfq_update_eligible(struct qfq_sched *q)
{
struct qfq_group *grp;
unsigned long ineligible;
@@ -792,137 +951,226 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
if (qfq_gt(grp->S, q->V))
q->V = grp->S;
}
- qfq_make_eligible(q, old_V);
+ qfq_make_eligible(q);
}
}
-/*
- * Updates the class, returns true if also the group needs to be updated.
- */
-static bool qfq_update_class(struct qfq_group *grp, struct qfq_class *cl)
+/* Dequeue head packet of the head class in the DRR queue of the aggregate. */
+static void agg_dequeue(struct qfq_aggregate *agg,
+ struct qfq_class *cl, unsigned int len)
{
- unsigned int len = qdisc_peek_len(cl->qdisc);
+ qdisc_dequeue_peeked(cl->qdisc);
- cl->S = cl->F;
- if (!len)
- qfq_front_slot_remove(grp); /* queue is empty */
- else {
- u64 roundedS;
+ cl->deficit -= (int) len;
- cl->F = cl->S + (u64)len * cl->inv_w;
- roundedS = qfq_round_down(cl->S, grp->slot_shift);
- if (roundedS == grp->S)
- return false;
-
- qfq_front_slot_remove(grp);
- qfq_slot_insert(grp, cl, roundedS);
+ if (cl->qdisc->q.qlen == 0) /* no more packets, remove from list */
+ list_del(&cl->alist);
+ else if (cl->deficit < qdisc_pkt_len(cl->qdisc->ops->peek(cl->qdisc))) {
+ cl->deficit += agg->lmax;
+ list_move_tail(&cl->alist, &agg->active);
}
+}
+
+static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg,
+ struct qfq_class **cl,
+ unsigned int *len)
+{
+ struct sk_buff *skb;
- return true;
+ *cl = list_first_entry(&agg->active, struct qfq_class, alist);
+ skb = (*cl)->qdisc->ops->peek((*cl)->qdisc);
+ if (skb == NULL)
+ WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n");
+ else
+ *len = qdisc_pkt_len(skb);
+
+ return skb;
+}
+
+/* Update F according to the actual service received by the aggregate. */
+static inline void charge_actual_service(struct qfq_aggregate *agg)
+{
+ /* compute the service received by the aggregate */
+ u32 service_received = agg->initial_budget - agg->budget;
+
+ agg->F = agg->S + (u64)service_received * agg->inv_w;
}
static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
{
struct qfq_sched *q = qdisc_priv(sch);
- struct qfq_group *grp;
+ struct qfq_aggregate *in_serv_agg = q->in_serv_agg;
struct qfq_class *cl;
- struct sk_buff *skb;
- unsigned int len;
- u64 old_V;
+ struct sk_buff *skb = NULL;
+ /* next-packet len, 0 means no more active classes in in-service agg */
+ unsigned int len = 0;
- if (!q->bitmaps[ER])
+ if (in_serv_agg == NULL)
return NULL;
- grp = qfq_ffs(q, q->bitmaps[ER]);
+ if (!list_empty(&in_serv_agg->active))
+ skb = qfq_peek_skb(in_serv_agg, &cl, &len);
- cl = qfq_slot_head(grp);
- skb = qdisc_dequeue_peeked(cl->qdisc);
- if (!skb) {
- WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n");
- return NULL;
+ /*
+ * If there are no active classes in the in-service aggregate,
+ * or if the aggregate has not enough budget to serve its next
+ * class, then choose the next aggregate to serve.
+ */
+ if (len == 0 || in_serv_agg->budget < len) {
+ charge_actual_service(in_serv_agg);
+
+ /* recharge the budget of the aggregate */
+ in_serv_agg->initial_budget = in_serv_agg->budget =
+ in_serv_agg->budgetmax;
+
+ if (!list_empty(&in_serv_agg->active))
+ /*
+ * Still active: reschedule for
+ * service. Possible optimization: if no other
+ * aggregate is active, then there is no point
+ * in rescheduling this aggregate, and we can
+ * just keep it as the in-service one. This
+ * should be however a corner case, and to
+ * handle it, we would need to maintain an
+ * extra num_active_aggs field.
+ */
+ qfq_activate_agg(q, in_serv_agg, requeue);
+ else if (sch->q.qlen == 0) { /* no aggregate to serve */
+ q->in_serv_agg = NULL;
+ return NULL;
+ }
+
+ /*
+ * If we get here, there are other aggregates queued:
+ * choose the new aggregate to serve.
+ */
+ in_serv_agg = q->in_serv_agg = qfq_choose_next_agg(q);
+ skb = qfq_peek_skb(in_serv_agg, &cl, &len);
}
+ if (!skb)
+ return NULL;
sch->q.qlen--;
qdisc_bstats_update(sch, skb);
- old_V = q->V;
- len = qdisc_pkt_len(skb);
+ agg_dequeue(in_serv_agg, cl, len);
+ in_serv_agg->budget -= len;
q->V += (u64)len * IWSUM;
pr_debug("qfq dequeue: len %u F %lld now %lld\n",
- len, (unsigned long long) cl->F, (unsigned long long) q->V);
+ len, (unsigned long long) in_serv_agg->F,
+ (unsigned long long) q->V);
- if (qfq_update_class(grp, cl)) {
- u64 old_F = grp->F;
+ return skb;
+}
- cl = qfq_slot_scan(grp);
- if (!cl)
- __clear_bit(grp->index, &q->bitmaps[ER]);
- else {
- u64 roundedS = qfq_round_down(cl->S, grp->slot_shift);
- unsigned int s;
+static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
+{
+ struct qfq_group *grp;
+ struct qfq_aggregate *agg, *new_front_agg;
+ u64 old_F;
- if (grp->S == roundedS)
- goto skip_unblock;
- grp->S = roundedS;
- grp->F = roundedS + (2ULL << grp->slot_shift);
- __clear_bit(grp->index, &q->bitmaps[ER]);
- s = qfq_calc_state(q, grp);
- __set_bit(grp->index, &q->bitmaps[s]);
- }
+ qfq_update_eligible(q);
+ q->oldV = q->V;
+
+ if (!q->bitmaps[ER])
+ return NULL;
+
+ grp = qfq_ffs(q, q->bitmaps[ER]);
+ old_F = grp->F;
+
+ agg = qfq_slot_head(grp);
- qfq_unblock_groups(q, grp->index, old_F);
+ /* agg starts to be served, remove it from schedule */
+ qfq_front_slot_remove(grp);
+
+ new_front_agg = qfq_slot_scan(grp);
+
+ if (new_front_agg == NULL) /* group is now inactive, remove from ER */
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ else {
+ u64 roundedS = qfq_round_down(new_front_agg->S,
+ grp->slot_shift);
+ unsigned int s;
+
+ if (grp->S == roundedS)
+ return agg;
+ grp->S = roundedS;
+ grp->F = roundedS + (2ULL << grp->slot_shift);
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ s = qfq_calc_state(q, grp);
+ __set_bit(grp->index, &q->bitmaps[s]);
}
-skip_unblock:
- qfq_update_eligible(q, old_V);
+ qfq_unblock_groups(q, grp->index, old_F);
- return skb;
+ return agg;
}
/*
- * Assign a reasonable start time for a new flow k in group i.
+ * Assign a reasonable start time for a new aggregate in group i.
* Admissible values for \hat(F) are multiples of \sigma_i
* no greater than V+\sigma_i . Larger values mean that
* we had a wraparound so we consider the timestamp to be stale.
*
* If F is not stale and F >= V then we set S = F.
* Otherwise we should assign S = V, but this may violate
- * the ordering in ER. So, if we have groups in ER, set S to
- * the F_j of the first group j which would be blocking us.
+ * the ordering in EB (see [2]). So, if we have groups in ER,
+ * set S to the F_j of the first group j which would be blocking us.
* We are guaranteed not to move S backward because
* otherwise our group i would still be blocked.
*/
-static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
+static void qfq_update_start(struct qfq_sched *q, struct qfq_aggregate *agg)
{
unsigned long mask;
u64 limit, roundedF;
- int slot_shift = cl->grp->slot_shift;
+ int slot_shift = agg->grp->slot_shift;
- roundedF = qfq_round_down(cl->F, slot_shift);
+ roundedF = qfq_round_down(agg->F, slot_shift);
limit = qfq_round_down(q->V, slot_shift) + (1ULL << slot_shift);
- if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) {
+ if (!qfq_gt(agg->F, q->V) || qfq_gt(roundedF, limit)) {
/* timestamp was stale */
- mask = mask_from(q->bitmaps[ER], cl->grp->index);
+ mask = mask_from(q->bitmaps[ER], agg->grp->index);
if (mask) {
struct qfq_group *next = qfq_ffs(q, mask);
if (qfq_gt(roundedF, next->F)) {
if (qfq_gt(limit, next->F))
- cl->S = next->F;
+ agg->S = next->F;
else /* preserve timestamp correctness */
- cl->S = limit;
+ agg->S = limit;
return;
}
}
- cl->S = q->V;
+ agg->S = q->V;
} else /* timestamp is not stale */
- cl->S = cl->F;
+ agg->S = agg->F;
}
+/*
+ * Update the timestamps of agg before scheduling/rescheduling it for
+ * service. In particular, assign to agg->F its maximum possible
+ * value, i.e., the virtual finish time with which the aggregate
+ * should be labeled if it used all its budget once in service.
+ */
+static inline void
+qfq_update_agg_ts(struct qfq_sched *q,
+ struct qfq_aggregate *agg, enum update_reason reason)
+{
+ if (reason != requeue)
+ qfq_update_start(q, agg);
+ else /* just charge agg for the service received */
+ agg->S = agg->F;
+
+ agg->F = agg->S + (u64)agg->budgetmax * agg->inv_w;
+}
+
+static void qfq_schedule_agg(struct qfq_sched *, struct qfq_aggregate *);
+
static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct qfq_sched *q = qdisc_priv(sch);
struct qfq_class *cl;
+ struct qfq_aggregate *agg;
int err = 0;
cl = qfq_classify(skb, sch, &err);
@@ -934,11 +1182,13 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
}
pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
- if (unlikely(cl->lmax < qdisc_pkt_len(skb))) {
+ if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) {
pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
- cl->lmax, qdisc_pkt_len(skb), cl->common.classid);
- qfq_update_reactivate_class(q, cl, cl->inv_w,
- qdisc_pkt_len(skb), 0);
+ cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
+ err = qfq_change_agg(sch, cl, cl->agg->class_weight,
+ qdisc_pkt_len(skb));
+ if (err)
+ return err;
}
err = qdisc_enqueue(skb, cl->qdisc);
@@ -954,35 +1204,50 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
bstats_update(&cl->bstats, skb);
++sch->q.qlen;
- /* If the new skb is not the head of queue, then done here. */
- if (cl->qdisc->q.qlen != 1)
+ agg = cl->agg;
+ /* if the queue was not empty, then done here */
+ if (cl->qdisc->q.qlen != 1) {
+ if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
+ list_first_entry(&agg->active, struct qfq_class, alist)
+ == cl && cl->deficit < qdisc_pkt_len(skb))
+ list_move_tail(&cl->alist, &agg->active);
+
return err;
+ }
+
+ /* schedule class for service within the aggregate */
+ cl->deficit = agg->lmax;
+ list_add_tail(&cl->alist, &agg->active);
- /* If reach this point, queue q was idle */
- qfq_activate_class(q, cl, qdisc_pkt_len(skb));
+ if (list_first_entry(&agg->active, struct qfq_class, alist) != cl)
+ return err; /* aggregate was not empty, nothing else to do */
+
+ /* recharge budget */
+ agg->initial_budget = agg->budget = agg->budgetmax;
+
+ qfq_update_agg_ts(q, agg, enqueue);
+ if (q->in_serv_agg == NULL)
+ q->in_serv_agg = agg;
+ else if (agg != q->in_serv_agg)
+ qfq_schedule_agg(q, agg);
return err;
}
/*
- * Handle class switch from idle to backlogged.
+ * Schedule aggregate according to its timestamps.
*/
-static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
- unsigned int pkt_len)
+static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
{
- struct qfq_group *grp = cl->grp;
+ struct qfq_group *grp = agg->grp;
u64 roundedS;
int s;
- qfq_update_start(q, cl);
-
- /* compute new finish time and rounded start. */
- cl->F = cl->S + (u64)pkt_len * cl->inv_w;
- roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ roundedS = qfq_round_down(agg->S, grp->slot_shift);
/*
- * insert cl in the correct bucket.
- * If cl->S >= grp->S we don't need to adjust the
+ * Insert agg in the correct bucket.
+ * If agg->S >= grp->S we don't need to adjust the
* bucket list and simply go to the insertion phase.
* Otherwise grp->S is decreasing, we must make room
* in the bucket list, and also recompute the group state.
@@ -990,10 +1255,10 @@ static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
* was in ER make sure to adjust V.
*/
if (grp->full_slots) {
- if (!qfq_gt(grp->S, cl->S))
+ if (!qfq_gt(grp->S, agg->S))
goto skip_update;
- /* create a slot for this cl->S */
+ /* create a slot for this agg->S */
qfq_slot_rotate(grp, roundedS);
/* group was surely ineligible, remove */
__clear_bit(grp->index, &q->bitmaps[IR]);
@@ -1008,46 +1273,61 @@ static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
pr_debug("qfq enqueue: new state %d %#lx S %lld F %lld V %lld\n",
s, q->bitmaps[s],
- (unsigned long long) cl->S,
- (unsigned long long) cl->F,
+ (unsigned long long) agg->S,
+ (unsigned long long) agg->F,
(unsigned long long) q->V);
skip_update:
- qfq_slot_insert(grp, cl, roundedS);
+ qfq_slot_insert(grp, agg, roundedS);
}
+/* Update agg ts and schedule agg for service */
+static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+ enum update_reason reason)
+{
+ qfq_update_agg_ts(q, agg, reason);
+ qfq_schedule_agg(q, agg);
+}
+
static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp,
- struct qfq_class *cl)
+ struct qfq_aggregate *agg)
{
unsigned int i, offset;
u64 roundedS;
- roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ roundedS = qfq_round_down(agg->S, grp->slot_shift);
offset = (roundedS - grp->S) >> grp->slot_shift;
+
i = (grp->front + offset) % QFQ_MAX_SLOTS;
- hlist_del(&cl->next);
+ hlist_del(&agg->next);
if (hlist_empty(&grp->slots[i]))
__clear_bit(offset, &grp->full_slots);
}
/*
- * called to forcibly destroy a queue.
- * If the queue is not in the front bucket, or if it has
- * other queues in the front bucket, we can simply remove
- * the queue with no other side effects.
+ * Called to forcibly deschedule an aggregate. If the aggregate is
+ * not in the front bucket, or if the latter has other aggregates in
+ * the front bucket, we can simply remove the aggregate with no other
+ * side effects.
* Otherwise we must propagate the event up.
*/
-static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
+static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
{
- struct qfq_group *grp = cl->grp;
+ struct qfq_group *grp = agg->grp;
unsigned long mask;
u64 roundedS;
int s;
- cl->F = cl->S;
- qfq_slot_remove(q, grp, cl);
+ if (agg == q->in_serv_agg) {
+ charge_actual_service(agg);
+ q->in_serv_agg = qfq_choose_next_agg(q);
+ return;
+ }
+
+ agg->F = agg->S;
+ qfq_slot_remove(q, grp, agg);
if (!grp->full_slots) {
__clear_bit(grp->index, &q->bitmaps[IR]);
@@ -1066,8 +1346,8 @@ static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
}
__clear_bit(grp->index, &q->bitmaps[ER]);
} else if (hlist_empty(&grp->slots[grp->front])) {
- cl = qfq_slot_scan(grp);
- roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ agg = qfq_slot_scan(grp);
+ roundedS = qfq_round_down(agg->S, grp->slot_shift);
if (grp->S != roundedS) {
__clear_bit(grp->index, &q->bitmaps[ER]);
__clear_bit(grp->index, &q->bitmaps[IR]);
@@ -1080,7 +1360,7 @@ static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
}
}
- qfq_update_eligible(q, q->V);
+ qfq_update_eligible(q);
}
static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
@@ -1092,6 +1372,32 @@ static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
qfq_deactivate_class(q, cl);
}
+static unsigned int qfq_drop_from_slot(struct qfq_sched *q,
+ struct hlist_head *slot)
+{
+ struct qfq_aggregate *agg;
+ struct hlist_node *n;
+ struct qfq_class *cl;
+ unsigned int len;
+
+ hlist_for_each_entry(agg, n, slot, next) {
+ list_for_each_entry(cl, &agg->active, alist) {
+
+ if (!cl->qdisc->ops->drop)
+ continue;
+
+ len = cl->qdisc->ops->drop(cl->qdisc);
+ if (len > 0) {
+ if (cl->qdisc->q.qlen == 0)
+ qfq_deactivate_class(q, cl);
+
+ return len;
+ }
+ }
+ }
+ return 0;
+}
+
static unsigned int qfq_drop(struct Qdisc *sch)
{
struct qfq_sched *q = qdisc_priv(sch);
@@ -1101,24 +1407,13 @@ static unsigned int qfq_drop(struct Qdisc *sch)
for (i = 0; i <= QFQ_MAX_INDEX; i++) {
grp = &q->groups[i];
for (j = 0; j < QFQ_MAX_SLOTS; j++) {
- struct qfq_class *cl;
- struct hlist_node *n;
-
- hlist_for_each_entry(cl, n, &grp->slots[j], next) {
-
- if (!cl->qdisc->ops->drop)
- continue;
-
- len = cl->qdisc->ops->drop(cl->qdisc);
- if (len > 0) {
- sch->q.qlen--;
- if (!cl->qdisc->q.qlen)
- qfq_deactivate_class(q, cl);
-
- return len;
- }
+ len = qfq_drop_from_slot(q, &grp->slots[j]);
+ if (len > 0) {
+ sch->q.qlen--;
+ return len;
}
}
+
}
return 0;
@@ -1129,44 +1424,51 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
struct qfq_sched *q = qdisc_priv(sch);
struct qfq_group *grp;
int i, j, err;
+ u32 max_cl_shift, maxbudg_shift, max_classes;
err = qdisc_class_hash_init(&q->clhash);
if (err < 0)
return err;
+ if (qdisc_dev(sch)->tx_queue_len + 1 > QFQ_MAX_AGG_CLASSES)
+ max_classes = QFQ_MAX_AGG_CLASSES;
+ else
+ max_classes = qdisc_dev(sch)->tx_queue_len + 1;
+ /* max_cl_shift = floor(log_2(max_classes)) */
+ max_cl_shift = __fls(max_classes);
+ q->max_agg_classes = 1<<max_cl_shift;
+
+ /* maxbudg_shift = log2(max_len * max_classes_per_agg) */
+ maxbudg_shift = QFQ_MTU_SHIFT + max_cl_shift;
+ q->min_slot_shift = FRAC_BITS + maxbudg_shift - QFQ_MAX_INDEX;
+
for (i = 0; i <= QFQ_MAX_INDEX; i++) {
grp = &q->groups[i];
grp->index = i;
- grp->slot_shift = QFQ_MTU_SHIFT + FRAC_BITS
- - (QFQ_MAX_INDEX - i);
+ grp->slot_shift = q->min_slot_shift + i;
for (j = 0; j < QFQ_MAX_SLOTS; j++)
INIT_HLIST_HEAD(&grp->slots[j]);
}
+ INIT_HLIST_HEAD(&q->nonfull_aggs);
+
return 0;
}
static void qfq_reset_qdisc(struct Qdisc *sch)
{
struct qfq_sched *q = qdisc_priv(sch);
- struct qfq_group *grp;
struct qfq_class *cl;
- struct hlist_node *n, *tmp;
- unsigned int i, j;
+ struct hlist_node *n;
+ unsigned int i;
- for (i = 0; i <= QFQ_MAX_INDEX; i++) {
- grp = &q->groups[i];
- for (j = 0; j < QFQ_MAX_SLOTS; j++) {
- hlist_for_each_entry_safe(cl, n, tmp,
- &grp->slots[j], next) {
+ for (i = 0; i < q->clhash.hashsize; i++) {
+ hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
+ if (cl->qdisc->q.qlen > 0)
qfq_deactivate_class(q, cl);
- }
- }
- }
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
qdisc_reset(cl->qdisc);
+ }
}
sch->q.qlen = 0;
}
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig
index 126b014eb79b..a9edd2e205f4 100644
--- a/net/sctp/Kconfig
+++ b/net/sctp/Kconfig
@@ -9,7 +9,6 @@ menuconfig IP_SCTP
select CRYPTO
select CRYPTO_HMAC
select CRYPTO_SHA1
- select CRYPTO_MD5 if SCTP_HMAC_MD5
select LIBCRC32C
---help---
Stream Control Transmission Protocol
@@ -68,33 +67,21 @@ config SCTP_DBG_OBJCNT
If unsure, say N
-choice
- prompt "SCTP: Cookie HMAC Algorithm"
- default SCTP_HMAC_MD5
+config SCTP_COOKIE_HMAC_MD5
+ bool "Enable optional MD5 hmac cookie generation"
help
- HMAC algorithm to be used during association initialization. It
- is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See
- configuration for Cryptographic API and enable those algorithms
- to make usable by SCTP.
-
-config SCTP_HMAC_NONE
- bool "None"
- help
- Choosing this disables the use of an HMAC during association
- establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1.
-
-config SCTP_HMAC_SHA1
- bool "HMAC-SHA1"
- help
- Enable the use of HMAC-SHA1 during association establishment. It
- is advised to use either HMAC-MD5 or HMAC-SHA1.
-
-config SCTP_HMAC_MD5
- bool "HMAC-MD5"
+ Enable optional MD5 hmac based SCTP cookie generation
+ default y
+ select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5
+ select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5
+
+config SCTP_COOKIE_HMAC_SHA1
+ bool "Enable optional SHA1 hmac cookie generation"
help
- Enable the use of HMAC-MD5 during association establishment. It is
- advised to use either HMAC-MD5 or HMAC-SHA1.
+ Enable optional SHA1 hmac based SCTP cookie generation
+ default y
+ select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1
+ select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1
-endchoice
endif # IP_SCTP
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b1ef3bc301a5..b45ed1f96921 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -321,6 +321,9 @@ 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);
@@ -445,7 +448,7 @@ void sctp_association_free(struct sctp_association *asoc)
/* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);
- list_del(pos);
+ list_del_rcu(pos);
sctp_transport_free(transport);
}
@@ -565,7 +568,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
sctp_assoc_update_retran_path(asoc);
/* Remove this peer from the list. */
- list_del(&peer->transports);
+ list_del_rcu(&peer->transports);
/* Get the first transport of asoc. */
pos = asoc->peer.transport_addr_list.next;
@@ -760,12 +763,13 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
+ sctp_max_rto(asoc, peer);
/* Set the peer's active state. */
peer->state = peer_state;
/* Attach the remote transport to our asoc. */
- list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+ list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
asoc->peer.transport_count++;
/* If we do not yet have a primary path, set one. */
@@ -1152,8 +1156,12 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
*/
if (sctp_chunk_is_data(chunk))
asoc->peer.last_data_from = chunk->transport;
- else
+ else {
SCTP_INC_STATS(net, SCTP_MIB_INCTRLCHUNKS);
+ asoc->stats.ictrlchunks++;
+ if (chunk->chunk_hdr->type == SCTP_CID_SACK)
+ asoc->stats.isacks++;
+ }
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 1859e2bc83d1..17a001bac2cc 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -163,7 +163,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
list_add(&null_key->key_list, &ep->endpoint_shared_keys);
- /* Allocate and initialize transorms arrays for suported HMACs. */
+ /* Allocate and initialize transorms arrays for supported HMACs. */
err = sctp_auth_init_hmacs(ep, gfp);
if (err)
goto nomem_hmacs;
@@ -480,8 +480,11 @@ normal:
*/
if (asoc && sctp_chunk_is_data(chunk))
asoc->peer.last_data_from = chunk->transport;
- else
+ else {
SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
+ if (asoc)
+ asoc->stats.ictrlchunks++;
+ }
if (chunk->transport)
chunk->transport->last_time_heard = jiffies;
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 397296fb156f..2d5ad280de38 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -104,6 +104,8 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
* on the BH related data structures.
*/
list_add_tail(&chunk->list, &q->in_chunk_list);
+ if (chunk->asoc)
+ chunk->asoc->stats.ipackets++;
q->immediate.func(&q->immediate);
}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ea14cb445295..f3f0f4dc31dd 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -345,7 +345,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
}
out:
- if (!IS_ERR(dst)) {
+ if (!IS_ERR_OR_NULL(dst)) {
struct rt6_info *rt;
rt = (struct rt6_info *)dst;
t->dst = dst;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 4e90188bf489..f5200a2ad852 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -311,6 +311,8 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
case SCTP_CID_SACK:
packet->has_sack = 1;
+ if (chunk->asoc)
+ chunk->asoc->stats.osacks++;
break;
case SCTP_CID_AUTH:
@@ -584,11 +586,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
/* Dump that on IP! */
- if (asoc && asoc->peer.last_sent_to != tp) {
- /* Considering the multiple CPU scenario, this is a
- * "correcter" place for last_sent_to. --xguo
- */
- asoc->peer.last_sent_to = tp;
+ if (asoc) {
+ asoc->stats.opackets++;
+ if (asoc->peer.last_sent_to != tp)
+ /* Considering the multiple CPU scenario, this is a
+ * "correcter" place for last_sent_to. --xguo
+ */
+ asoc->peer.last_sent_to = tp;
}
if (has_data) {
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1b4a7f8ec3fd..379c81dee9d1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -667,6 +667,7 @@ redo:
chunk->fast_retransmit = SCTP_DONT_FRTX;
q->empty = 0;
+ q->asoc->stats.rtxchunks++;
break;
}
@@ -876,12 +877,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
if (status != SCTP_XMIT_OK) {
/* put the chunk back */
list_add(&chunk->list, &q->control_chunk_list);
- } else if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
+ } else {
+ asoc->stats.octrlchunks++;
/* PR-SCTP C5) If a FORWARD TSN is sent, the
* sender MUST assure that at least one T3-rtx
* timer is running.
*/
- sctp_transport_reset_timers(transport);
+ if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN)
+ sctp_transport_reset_timers(transport);
}
break;
@@ -1055,6 +1058,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
*/
if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
+ if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+ asoc->stats.ouodchunks++;
+ else
+ asoc->stats.oodchunks++;
break;
@@ -1162,6 +1169,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
sack_ctsn = ntohl(sack->cum_tsn_ack);
gap_ack_blocks = ntohs(sack->num_gap_ack_blocks);
+ asoc->stats.gapcnt += gap_ack_blocks;
/*
* SFR-CACC algorithm:
* On receipt of a SACK the sender SHOULD execute the
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 9966e7b16451..8c19e97262ca 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -139,7 +139,11 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
primary = &peer->saddr;
}
- list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
+ if (!laddr->valid)
+ continue;
+
addr = &laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
if (primary && af->cmp_addr(addr, primary)) {
@@ -147,6 +151,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
/* Dump remote addresses of an association. */
@@ -157,15 +162,20 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
struct sctp_af *af;
primary = &assoc->peer.primary_addr;
- list_for_each_entry(transport, &assoc->peer.transport_addr_list,
+ rcu_read_lock();
+ list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
transports) {
addr = &transport->ipaddr;
+ if (transport->dead)
+ continue;
+
af = sctp_get_af_specific(addr->sa.sa_family);
if (af->cmp_addr(addr, primary)) {
seq_printf(seq, "*");
}
af->seq_dump_addr(seq, addr);
}
+ rcu_read_unlock();
}
static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
@@ -436,12 +446,16 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
+ rcu_read_lock();
sctp_for_each_hentry(epb, node, &head->chain) {
if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
continue;
assoc = sctp_assoc(epb);
- list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
+ list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
transports) {
+ if (tsp->dead)
+ continue;
+
/*
* The remote address (ADDR)
*/
@@ -487,6 +501,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
}
}
+ rcu_read_unlock();
read_unlock(&head->lock);
sctp_local_bh_enable();
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2d518425d598..2c7785bacf74 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -86,7 +86,7 @@ int sysctl_sctp_rmem[3];
int sysctl_sctp_wmem[3];
/* Set up the proc fs entry for the SCTP protocol. */
-static __net_init int sctp_proc_init(struct net *net)
+static int __net_init sctp_proc_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
@@ -1165,7 +1165,7 @@ static void sctp_v4_del_protocol(void)
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
}
-static int sctp_net_init(struct net *net)
+static int __net_init sctp_net_init(struct net *net)
{
int status;
@@ -1190,6 +1190,15 @@ static int sctp_net_init(struct net *net)
/* Whether Cookie Preservative is enabled(1) or not(0) */
net->sctp.cookie_preserve_enable = 1;
+ /* Default sctp sockets to use md5 as their hmac alg */
+#if defined (CONFIG_CRYPTO_MD5)
+ net->sctp.sctp_hmac_alg = "md5";
+#elif defined (CONFIG_CRYPTO_SHA1)
+ net->sctp.sctp_hmac_alg = "sha1";
+#else
+ net->sctp.sctp_hmac_alg = NULL;
+#endif
+
/* Max.Burst - 4 */
net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST;
@@ -1281,7 +1290,7 @@ err_sysctl_register:
return status;
}
-static void sctp_net_exit(struct net *net)
+static void __net_exit sctp_net_exit(struct net *net)
{
/* Free the local address list */
sctp_free_addr_wq(net);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fbe1636309a7..e1c5fc2be6b8 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -804,10 +804,11 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
gabs);
/* Add the duplicate TSN information. */
- if (num_dup_tsns)
+ if (num_dup_tsns) {
+ aptr->stats.idupchunks += num_dup_tsns;
sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
sctp_tsnmap_get_dups(map));
-
+ }
/* Once we have a sack generated, check to see what our sack
* generation is, if its 0, reset the transports to 0, and reset
* the association generation to 1
@@ -1090,6 +1091,25 @@ nodata:
return retval;
}
+struct sctp_chunk *sctp_make_violation_max_retrans(
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk)
+{
+ struct sctp_chunk *retval;
+ static const char error[] = "Association exceeded its max_retans count";
+ size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t);
+
+ retval = sctp_make_abort(asoc, chunk, payload_len);
+ if (!retval)
+ goto nodata;
+
+ sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error));
+ sctp_addto_chunk(retval, sizeof(error), error);
+
+nodata:
+ return retval;
+}
+
/* Make a HEARTBEAT chunk. */
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
const struct sctp_transport *transport)
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 6773d7803627..c9577754a708 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -542,6 +542,7 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
*/
if (!is_hb || transport->hb_sent) {
transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
+ sctp_max_rto(asoc, transport);
}
}
@@ -577,7 +578,7 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
unsigned int error)
{
struct sctp_ulpevent *event;
-
+ struct sctp_chunk *abort;
/* Cancel any partial delivery in progress. */
sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
@@ -593,6 +594,13 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(event));
+ if (asoc->overall_error_count >= asoc->max_retrans) {
+ abort = sctp_make_violation_max_retrans(asoc, chunk);
+ if (abort)
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+ SCTP_CHUNK(abort));
+ }
+
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
@@ -1268,14 +1276,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_outq_uncork(&asoc->outqueue);
local_cork = 0;
}
- asoc = cmd->obj.ptr;
+ asoc = cmd->obj.asoc;
/* Register with the endpoint. */
sctp_endpoint_add_asoc(ep, asoc);
sctp_hash_established(asoc);
break;
case SCTP_CMD_UPDATE_ASSOC:
- sctp_assoc_update(asoc, cmd->obj.ptr);
+ sctp_assoc_update(asoc, cmd->obj.asoc);
break;
case SCTP_CMD_PURGE_OUTQUEUE:
@@ -1315,7 +1323,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
case SCTP_CMD_PROCESS_FWDTSN:
- sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr);
+ sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.chunk);
break;
case SCTP_CMD_GEN_SACK:
@@ -1331,7 +1339,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_PROCESS_SACK:
/* Process an inbound SACK. */
error = sctp_cmd_process_sack(commands, asoc,
- cmd->obj.ptr);
+ cmd->obj.chunk);
break;
case SCTP_CMD_GEN_INIT_ACK:
@@ -1352,15 +1360,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* layer which will bail.
*/
error = sctp_cmd_process_init(commands, asoc, chunk,
- cmd->obj.ptr, gfp);
+ cmd->obj.init, gfp);
break;
case SCTP_CMD_GEN_COOKIE_ECHO:
/* Generate a COOKIE ECHO chunk. */
new_obj = sctp_make_cookie_echo(asoc, chunk);
if (!new_obj) {
- if (cmd->obj.ptr)
- sctp_chunk_free(cmd->obj.ptr);
+ if (cmd->obj.chunk)
+ sctp_chunk_free(cmd->obj.chunk);
goto nomem;
}
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
@@ -1369,9 +1377,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
/* If there is an ERROR chunk to be sent along with
* the COOKIE_ECHO, send it, too.
*/
- if (cmd->obj.ptr)
+ if (cmd->obj.chunk)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
- SCTP_CHUNK(cmd->obj.ptr));
+ SCTP_CHUNK(cmd->obj.chunk));
if (new_obj->transport) {
new_obj->transport->init_sent_count++;
@@ -1417,18 +1425,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_CHUNK_ULP:
/* Send a chunk to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
- "chunk_up:", cmd->obj.ptr,
+ "chunk_up:", cmd->obj.chunk,
"ulpq:", &asoc->ulpq);
- sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.ptr,
+ sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC);
break;
case SCTP_CMD_EVENT_ULP:
/* Send a notification to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
- "event_up:",cmd->obj.ptr,
+ "event_up:",cmd->obj.ulpevent,
"ulpq:",&asoc->ulpq);
- sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ptr);
+ sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ulpevent);
break;
case SCTP_CMD_REPLY:
@@ -1438,12 +1446,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
local_cork = 1;
}
/* Send a chunk to our peer. */
- error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr);
+ error = sctp_outq_tail(&asoc->outqueue, cmd->obj.chunk);
break;
case SCTP_CMD_SEND_PKT:
/* Send a full packet to our peer. */
- packet = cmd->obj.ptr;
+ packet = cmd->obj.packet;
sctp_packet_transmit(packet);
sctp_ootb_pkt_free(packet);
break;
@@ -1480,7 +1488,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
case SCTP_CMD_SETUP_T2:
- sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr);
+ sctp_cmd_setup_t2(commands, asoc, cmd->obj.chunk);
break;
case SCTP_CMD_TIMER_START_ONCE:
@@ -1514,7 +1522,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
- chunk = cmd->obj.ptr;
+ chunk = cmd->obj.chunk;
t = sctp_assoc_choose_alter_transport(asoc,
asoc->init_last_sent_to);
asoc->init_last_sent_to = t;
@@ -1665,17 +1673,16 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
case SCTP_CMD_PART_DELIVER:
- sctp_ulpq_partial_delivery(&asoc->ulpq, cmd->obj.ptr,
- GFP_ATOMIC);
+ sctp_ulpq_partial_delivery(&asoc->ulpq, GFP_ATOMIC);
break;
case SCTP_CMD_RENEGE:
- sctp_ulpq_renege(&asoc->ulpq, cmd->obj.ptr,
+ sctp_ulpq_renege(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC);
break;
case SCTP_CMD_SETUP_T4:
- sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);
+ sctp_cmd_setup_t4(commands, asoc, cmd->obj.chunk);
break;
case SCTP_CMD_PROCESS_OPERR:
@@ -1734,8 +1741,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;
default:
- pr_warn("Impossible command: %u, %p\n",
- cmd->verb, cmd->obj.ptr);
+ pr_warn("Impossible command: %u\n",
+ cmd->verb);
break;
}
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index b6adef8a1e93..618ec7e216ca 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1055,6 +1055,7 @@ sctp_disposition_t sctp_sf_beat_8_3(struct net *net,
void *arg,
sctp_cmd_seq_t *commands)
{
+ sctp_paramhdr_t *param_hdr;
struct sctp_chunk *chunk = arg;
struct sctp_chunk *reply;
size_t paylen = 0;
@@ -1072,12 +1073,17 @@ sctp_disposition_t sctp_sf_beat_8_3(struct net *net,
* Information field copied from the received HEARTBEAT chunk.
*/
chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
+ param_hdr = (sctp_paramhdr_t *) chunk->subh.hb_hdr;
paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
+
+ if (ntohs(param_hdr->length) > paylen)
+ return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
+ param_hdr, commands);
+
if (!pskb_pull(chunk->skb, paylen))
goto nomem;
- reply = sctp_make_heartbeat_ack(asoc, chunk,
- chunk->subh.hb_hdr, paylen);
+ reply = sctp_make_heartbeat_ack(asoc, chunk, param_hdr, paylen);
if (!reply)
goto nomem;
@@ -3994,7 +4000,7 @@ static sctp_ierror_t sctp_sf_authenticate(struct net *net,
chunk->subh.auth_hdr = auth_hdr;
skb_pull(chunk->skb, sizeof(struct sctp_authhdr));
- /* Make sure that we suport the HMAC algorithm from the auth
+ /* Make sure that we support the HMAC algorithm from the auth
* chunk.
*/
if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id))
@@ -6127,6 +6133,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
/* The TSN is too high--silently discard the chunk and
* count on it getting retransmitted later.
*/
+ if (chunk->asoc)
+ chunk->asoc->stats.outofseqtsns++;
return SCTP_IERROR_HIGH_TSN;
} else if (tmp > 0) {
/* This is a duplicate. Record it. */
@@ -6226,10 +6234,14 @@ static int sctp_eat_data(const struct sctp_association *asoc,
/* Note: Some chunks may get overcounted (if we drop) or overcounted
* if we renege and the chunk arrives again.
*/
- if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+ if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
- else {
+ if (chunk->asoc)
+ chunk->asoc->stats.iuodchunks++;
+ } else {
SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
+ if (chunk->asoc)
+ chunk->asoc->stats.iodchunks++;
ordered = 1;
}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 406d957d08fb..9e65758cb038 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -110,7 +110,6 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static int sctp_autobind(struct sock *sk);
static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t);
-static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
extern struct kmem_cache *sctp_bucket_cachep;
extern long sysctl_sctp_mem[3];
@@ -336,6 +335,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
/* Bind a local address either to an endpoint or to an association. */
SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
{
+ struct net *net = sock_net(sk);
struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep;
struct sctp_bind_addr *bp = &ep->base.bind_addr;
@@ -379,7 +379,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
}
}
- if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ if (snum && snum < PROT_SOCK &&
+ !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
return -EACCES;
/* See if the address matches any of the addresses we may have
@@ -610,6 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
2*asoc->pathmtu, 4380));
trans->ssthresh = asoc->peer.i.a_rwnd;
trans->rto = asoc->rto_initial;
+ sctp_max_rto(asoc, trans);
trans->rtt = trans->srtt = trans->rttvar = 0;
sctp_transport_route(trans, NULL,
sctp_sk(asoc->base.sk));
@@ -1162,7 +1164,7 @@ static int __sctp_connect(struct sock* sk,
* be permitted to open new associations.
*/
if (ep->base.bind_addr.port < PROT_SOCK &&
- !capable(CAP_NET_BIND_SERVICE)) {
+ !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
err = -EACCES;
goto out_free;
}
@@ -1791,7 +1793,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
* associations.
*/
if (ep->base.bind_addr.port < PROT_SOCK &&
- !capable(CAP_NET_BIND_SERVICE)) {
+ !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
err = -EACCES;
goto out_unlock;
}
@@ -3890,6 +3892,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->default_rcv_context = 0;
sp->max_burst = net->sctp.max_burst;
+ sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg;
+
/* Initialize default setup parameters. These parameters
* can be modified with the SCTP_INITMSG socket option or
* overridden by the SCTP_INIT CMSG.
@@ -5632,6 +5636,71 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
return 0;
}
+/*
+ * SCTP_GET_ASSOC_STATS
+ *
+ * This option retrieves local per endpoint statistics. It is modeled
+ * after OpenSolaris' implementation
+ */
+static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_stats sas;
+ struct sctp_association *asoc = NULL;
+
+ /* User must provide at least the assoc id */
+ if (len < sizeof(sctp_assoc_t))
+ return -EINVAL;
+
+ if (copy_from_user(&sas, optval, len))
+ return -EFAULT;
+
+ asoc = sctp_id2assoc(sk, sas.sas_assoc_id);
+ if (!asoc)
+ return -EINVAL;
+
+ sas.sas_rtxchunks = asoc->stats.rtxchunks;
+ sas.sas_gapcnt = asoc->stats.gapcnt;
+ sas.sas_outofseqtsns = asoc->stats.outofseqtsns;
+ sas.sas_osacks = asoc->stats.osacks;
+ sas.sas_isacks = asoc->stats.isacks;
+ sas.sas_octrlchunks = asoc->stats.octrlchunks;
+ sas.sas_ictrlchunks = asoc->stats.ictrlchunks;
+ sas.sas_oodchunks = asoc->stats.oodchunks;
+ sas.sas_iodchunks = asoc->stats.iodchunks;
+ sas.sas_ouodchunks = asoc->stats.ouodchunks;
+ sas.sas_iuodchunks = asoc->stats.iuodchunks;
+ sas.sas_idupchunks = asoc->stats.idupchunks;
+ sas.sas_opackets = asoc->stats.opackets;
+ sas.sas_ipackets = asoc->stats.ipackets;
+
+ /* New high max rto observed, will return 0 if not a single
+ * RTO update took place. obs_rto_ipaddr will be bogus
+ * in such a case
+ */
+ sas.sas_maxrto = asoc->stats.max_obs_rto;
+ memcpy(&sas.sas_obs_rto_ipaddr, &asoc->stats.obs_rto_ipaddr,
+ sizeof(struct sockaddr_storage));
+
+ /* Mark beginning of a new observation period */
+ asoc->stats.max_obs_rto = asoc->rto_min;
+
+ /* Allow the struct to grow and fill in as much as possible */
+ len = min_t(size_t, len, sizeof(sas));
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+
+ SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n",
+ len, sas.sas_assoc_id);
+
+ if (copy_to_user(optval, &sas, len))
+ return -EFAULT;
+
+ return 0;
+}
+
SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -5773,6 +5842,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case SCTP_PEER_ADDR_THLDS:
retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen);
break;
+ case SCTP_GET_ASSOC_STATS:
+ retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -5981,13 +6053,15 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog)
struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep;
struct crypto_hash *tfm = NULL;
+ char alg[32];
/* Allocate HMAC for generating cookie. */
- if (!sctp_sk(sk)->hmac && sctp_hmac_alg) {
- tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
+ if (!sp->hmac && sp->sctp_hmac_alg) {
+ sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg);
+ tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
net_info_ratelimited("failed to load transform for %s: %ld\n",
- sctp_hmac_alg, PTR_ERR(tfm));
+ sp->sctp_hmac_alg, PTR_ERR(tfm));
return -ENOSYS;
}
sctp_sk(sk)->hmac = tfm;
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 70e3ba5cb50b..043889ac86c0 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -62,6 +62,11 @@ 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(ctl_table *ctl,
+ int write,
+ void __user *buffer, size_t *lenp,
+
+ loff_t *ppos);
static ctl_table sctp_table[] = {
{
.procname = "sctp_mem",
@@ -147,6 +152,12 @@ static ctl_table sctp_net_table[] = {
.proc_handler = proc_dointvec,
},
{
+ .procname = "cookie_hmac_alg",
+ .maxlen = 8,
+ .mode = 0644,
+ .proc_handler = proc_sctp_do_hmac_alg,
+ },
+ {
.procname = "valid_cookie_life",
.data = &init_net.sctp.valid_cookie_life,
.maxlen = sizeof(unsigned int),
@@ -289,6 +300,54 @@ static ctl_table sctp_net_table[] = {
{ /* sentinel */ }
};
+static int proc_sctp_do_hmac_alg(ctl_table *ctl,
+ int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ struct net *net = current->nsproxy->net_ns;
+ char tmp[8];
+ ctl_table tbl;
+ int ret;
+ int changed = 0;
+ char *none = "none";
+
+ memset(&tbl, 0, sizeof(struct ctl_table));
+
+ if (write) {
+ tbl.data = tmp;
+ tbl.maxlen = 8;
+ } else {
+ tbl.data = net->sctp.sctp_hmac_alg ? : none;
+ tbl.maxlen = strlen(tbl.data);
+ }
+ ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+
+ if (write) {
+#ifdef CONFIG_CRYPTO_MD5
+ if (!strncmp(tmp, "md5", 3)) {
+ net->sctp.sctp_hmac_alg = "md5";
+ changed = 1;
+ }
+#endif
+#ifdef CONFIG_CRYPTO_SHA1
+ if (!strncmp(tmp, "sha1", 4)) {
+ net->sctp.sctp_hmac_alg = "sha1";
+ changed = 1;
+ }
+#endif
+ if (!strncmp(tmp, "none", 4)) {
+ net->sctp.sctp_hmac_alg = NULL;
+ changed = 1;
+ }
+
+ if (!changed)
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
int sctp_sysctl_net_register(struct net *net)
{
struct ctl_table *table;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 206cf5238fd3..4e45bb68aef0 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
sctp_transport_put(transport);
}
-/* Destroy the transport data structure.
- * Assumes there are no more users of this structure.
- */
-static void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy_rcu(struct rcu_head *head)
{
- SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+ struct sctp_transport *transport;
+ transport = container_of(head, struct sctp_transport, rcu);
if (transport->asoc)
sctp_association_put(transport->asoc);
@@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
SCTP_DBG_OBJCNT_DEC(transport);
}
+/* Destroy the transport data structure.
+ * Assumes there are no more users of this structure.
+ */
+static void sctp_transport_destroy(struct sctp_transport *transport)
+{
+ SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+
+ call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+}
+
/* Start T3_rtx timer if it is not already running and update the heartbeat
* timer. This routine is called every time a DATA chunk is sent.
*/
@@ -363,6 +371,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
if (tp->rto > tp->asoc->rto_max)
tp->rto = tp->asoc->rto_max;
+ sctp_max_rto(tp->asoc, tp);
tp->rtt = rtt;
/* Reset rto_pending so that a new RTT measurement is started when a
@@ -620,6 +629,7 @@ void sctp_transport_reset(struct sctp_transport *t)
t->burst_limited = 0;
t->ssthresh = asoc->peer.i.a_rwnd;
t->rto = asoc->rto_initial;
+ sctp_max_rto(asoc, t);
t->rtt = 0;
t->srtt = 0;
t->rttvar = 0;
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index b5fb7c409023..5f25e0c92c31 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -272,7 +272,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
__u32 max_tsn = map->max_tsn_seen;
__u32 base_tsn = map->base_tsn;
__u16 pending_data;
- u32 gap, i;
+ u32 gap;
pending_data = max_tsn - cum_tsn;
gap = max_tsn - base_tsn;
@@ -280,11 +280,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
if (gap == 0 || gap >= map->len)
goto out;
- for (i = 0; i < gap+1; i++) {
- if (test_bit(i, map->tsn_map))
- pending_data--;
- }
-
+ pending_data -= bitmap_weight(map->tsn_map, gap + 1);
out:
return pending_data;
}
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 360d8697b95c..ada17464b65b 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -997,7 +997,6 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
/* Partial deliver the first message as there is pressure on rwnd. */
void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
- struct sctp_chunk *chunk,
gfp_t gfp)
{
struct sctp_ulpevent *event;
@@ -1060,7 +1059,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
sctp_ulpq_tail_data(ulpq, chunk, gfp);
- sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
+ sctp_ulpq_partial_delivery(ulpq, gfp);
}
sk_mem_reclaim(asoc->base.sk);
diff --git a/net/socket.c b/net/socket.c
index d92c490e66fa..2ca51c719ef9 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -620,8 +620,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
{
struct sock_iocb *si = kiocb_to_siocb(iocb);
- sock_update_classid(sock->sk);
-
si->sock = sock;
si->scm = NULL;
si->msg = msg;
@@ -784,8 +782,6 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
{
struct sock_iocb *si = kiocb_to_siocb(iocb);
- sock_update_classid(sock->sk);
-
si->sock = sock;
si->scm = NULL;
si->msg = msg;
@@ -896,8 +892,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
if (unlikely(!sock->ops->splice_read))
return -EINVAL;
- sock_update_classid(sock->sk);
-
return sock->ops->splice_read(sock, ppos, pipe, len, flags);
}
@@ -3437,8 +3431,6 @@ EXPORT_SYMBOL(kernel_setsockopt);
int kernel_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags)
{
- sock_update_classid(sock->sk);
-
if (sock->ops->sendpage)
return sock->ops->sendpage(sock, page, offset, size, flags);
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index e3a6e37cd1c5..9bc6db04be3e 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -38,15 +38,24 @@ static int is_seen(struct ctl_table_set *set)
}
/* Return standard mode bits for table entry. */
-static int net_ctl_permissions(struct ctl_table_root *root,
- struct nsproxy *nsproxy,
+static int net_ctl_permissions(struct ctl_table_header *head,
struct ctl_table *table)
{
+ struct net *net = container_of(head->set, struct net, sysctls);
+ kuid_t root_uid = make_kuid(net->user_ns, 0);
+ kgid_t root_gid = make_kgid(net->user_ns, 0);
+
/* Allow network administrator to have same access as root. */
- if (capable(CAP_NET_ADMIN)) {
+ if (ns_capable(net->user_ns, CAP_NET_ADMIN) ||
+ uid_eq(root_uid, current_uid())) {
int mode = (table->mode >> 6) & 7;
return (mode << 6) | (mode << 3) | mode;
}
+ /* Allow netns root group to have the same access as the root group */
+ if (gid_eq(root_gid, current_gid())) {
+ int mode = (table->mode >> 3) & 7;
+ return (mode << 3) | mode;
+ }
return table->mode;
}
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index 585460180ffb..bc41bd31eadc 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -20,18 +20,9 @@ menuconfig TIPC
If in doubt, say N.
-if TIPC
-
-config TIPC_ADVANCED
- bool "Advanced TIPC configuration"
- default n
- help
- Saying Y here will open some advanced configuration for TIPC.
- Most users do not need to bother; if unsure, just say N.
-
config TIPC_PORTS
int "Maximum number of ports in a node"
- depends on TIPC_ADVANCED
+ depends on TIPC
range 127 65535
default "8191"
help
@@ -40,5 +31,3 @@ config TIPC_PORTS
Setting this to a smaller value saves some memory,
setting it to higher allows for more ports.
-
-endif # TIPC
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index e4e6d8cd47e6..54f89f90ac33 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -347,7 +347,7 @@ static void bclink_peek_nack(struct tipc_msg *msg)
tipc_node_lock(n_ptr);
- if (n_ptr->bclink.supported &&
+ if (n_ptr->bclink.recv_permitted &&
(n_ptr->bclink.last_in != n_ptr->bclink.last_sent) &&
(n_ptr->bclink.last_in == msg_bcgap_after(msg)))
n_ptr->bclink.oos_state = 2;
@@ -429,7 +429,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
goto exit;
tipc_node_lock(node);
- if (unlikely(!node->bclink.supported))
+ if (unlikely(!node->bclink.recv_permitted))
goto unlock;
/* Handle broadcast protocol message */
@@ -564,7 +564,7 @@ exit:
u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
{
- return (n_ptr->bclink.supported &&
+ return (n_ptr->bclink.recv_permitted &&
(tipc_bclink_get_last_sent() != n_ptr->bclink.acked));
}
@@ -619,16 +619,14 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
if (bcbearer->remains_new.count == bcbearer->remains.count)
continue; /* bearer pair doesn't add anything */
- if (p->blocked ||
- p->media->send_msg(buf, p, &p->media->bcast_addr)) {
+ if (!tipc_bearer_blocked(p))
+ tipc_bearer_send(p, buf, &p->media->bcast_addr);
+ else if (s && !tipc_bearer_blocked(s))
/* unable to send on primary bearer */
- if (!s || s->blocked ||
- s->media->send_msg(buf, s,
- &s->media->bcast_addr)) {
- /* unable to send on either bearer */
- continue;
- }
- }
+ tipc_bearer_send(s, buf, &s->media->bcast_addr);
+ else
+ /* unable to send on either bearer */
+ continue;
if (s) {
bcbearer->bpairs[bp_index].primary = s;
@@ -731,8 +729,8 @@ int tipc_bclink_stats(char *buf, const u32 buf_size)
" TX naks:%u acks:%u dups:%u\n",
s->sent_nacks, s->sent_acks, s->retransmitted);
ret += tipc_snprintf(buf + ret, buf_size - ret,
- " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
- s->bearer_congs, s->link_congs, s->max_queue_sz,
+ " Congestion link:%u Send queue max:%u avg:%u\n",
+ s->link_congs, s->max_queue_sz,
s->queue_sz_counts ?
(s->accu_queue_sz / s->queue_sz_counts) : 0);
@@ -766,7 +764,6 @@ int tipc_bclink_set_queue_limits(u32 limit)
void tipc_bclink_init(void)
{
- INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
bcbearer->bearer.media = &bcbearer->media;
bcbearer->media.send_msg = tipc_bcbearer_send;
sprintf(bcbearer->media.name, "tipc-broadcast");
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 4ec5c80e8a7c..aa62f93a9127 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -279,116 +279,31 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest)
}
/*
- * bearer_push(): Resolve bearer congestion. Force the waiting
- * links to push out their unsent packets, one packet per link
- * per iteration, until all packets are gone or congestion reoccurs.
- * 'tipc_net_lock' is read_locked when this function is called
- * bearer.lock must be taken before calling
- * Returns binary true(1) ore false(0)
- */
-static int bearer_push(struct tipc_bearer *b_ptr)
-{
- u32 res = 0;
- struct tipc_link *ln, *tln;
-
- if (b_ptr->blocked)
- return 0;
-
- while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
- list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
- res = tipc_link_push_packet(ln);
- if (res == PUSH_FAILED)
- break;
- if (res == PUSH_FINISHED)
- list_move_tail(&ln->link_list, &b_ptr->links);
- }
- }
- return list_empty(&b_ptr->cong_links);
-}
-
-void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
-{
- spin_lock_bh(&b_ptr->lock);
- bearer_push(b_ptr);
- spin_unlock_bh(&b_ptr->lock);
-}
-
-
-/*
- * Interrupt enabling new requests after bearer congestion or blocking:
+ * Interrupt enabling new requests after bearer blocking:
* See bearer_send().
*/
-void tipc_continue(struct tipc_bearer *b_ptr)
+void tipc_continue(struct tipc_bearer *b)
{
- spin_lock_bh(&b_ptr->lock);
- if (!list_empty(&b_ptr->cong_links))
- tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
- b_ptr->blocked = 0;
- spin_unlock_bh(&b_ptr->lock);
+ spin_lock_bh(&b->lock);
+ b->blocked = 0;
+ spin_unlock_bh(&b->lock);
}
/*
- * Schedule link for sending of messages after the bearer
- * has been deblocked by 'continue()'. This method is called
- * when somebody tries to send a message via this link while
- * the bearer is congested. 'tipc_net_lock' is in read_lock here
- * bearer.lock is busy
+ * tipc_bearer_blocked - determines if bearer is currently blocked
*/
-static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr,
- struct tipc_link *l_ptr)
+int tipc_bearer_blocked(struct tipc_bearer *b)
{
- list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
-}
-
-/*
- * Schedule link for sending of messages after the bearer
- * has been deblocked by 'continue()'. This method is called
- * when somebody tries to send a message via this link while
- * the bearer is congested. 'tipc_net_lock' is in read_lock here,
- * bearer.lock is free
- */
-void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr)
-{
- spin_lock_bh(&b_ptr->lock);
- tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
- spin_unlock_bh(&b_ptr->lock);
-}
-
+ int res;
-/*
- * tipc_bearer_resolve_congestion(): Check if there is bearer congestion,
- * and if there is, try to resolve it before returning.
- * 'tipc_net_lock' is read_locked when this function is called
- */
-int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr,
- struct tipc_link *l_ptr)
-{
- int res = 1;
+ spin_lock_bh(&b->lock);
+ res = b->blocked;
+ spin_unlock_bh(&b->lock);
- if (list_empty(&b_ptr->cong_links))
- return 1;
- spin_lock_bh(&b_ptr->lock);
- if (!bearer_push(b_ptr)) {
- tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
- res = 0;
- }
- spin_unlock_bh(&b_ptr->lock);
return res;
}
/**
- * tipc_bearer_congested - determines if bearer is currently congested
- */
-int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr)
-{
- if (unlikely(b_ptr->blocked))
- return 1;
- if (likely(list_empty(&b_ptr->cong_links)))
- return 0;
- return !tipc_bearer_resolve_congestion(b_ptr, l_ptr);
-}
-
-/**
* tipc_enable_bearer - enable bearer with the given name
*/
int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
@@ -489,7 +404,6 @@ restart:
b_ptr->net_plane = bearer_id + 'A';
b_ptr->active = 1;
b_ptr->priority = priority;
- INIT_LIST_HEAD(&b_ptr->cong_links);
INIT_LIST_HEAD(&b_ptr->links);
spin_lock_init(&b_ptr->lock);
@@ -528,7 +442,6 @@ int tipc_block_bearer(const char *name)
pr_info("Blocking bearer <%s>\n", name);
spin_lock_bh(&b_ptr->lock);
b_ptr->blocked = 1;
- list_splice_init(&b_ptr->cong_links, &b_ptr->links);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
struct tipc_node *n_ptr = l_ptr->owner;
@@ -555,7 +468,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
spin_lock_bh(&b_ptr->lock);
b_ptr->blocked = 1;
b_ptr->media->disable_bearer(b_ptr);
- list_splice_init(&b_ptr->cong_links, &b_ptr->links);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
tipc_link_delete(l_ptr);
}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index dd4c2abf08e7..39f1192d04bf 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -120,7 +120,6 @@ struct tipc_media {
* @identity: array index of this bearer within TIPC bearer array
* @link_req: ptr to (optional) structure making periodic link setup requests
* @links: list of non-congested links associated with bearer
- * @cong_links: list of congested links associated with bearer
* @active: non-zero if bearer structure is represents a bearer
* @net_plane: network plane ('A' through 'H') currently associated with bearer
* @nodes: indicates which nodes in cluster can be reached through bearer
@@ -143,7 +142,6 @@ struct tipc_bearer {
u32 identity;
struct tipc_link_req *link_req;
struct list_head links;
- struct list_head cong_links;
int active;
char net_plane;
struct tipc_node_map nodes;
@@ -185,39 +183,23 @@ struct sk_buff *tipc_media_get_names(void);
struct sk_buff *tipc_bearer_get_names(void);
void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
-void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr);
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_resolve_congestion(struct tipc_bearer *b_ptr,
- struct tipc_link *l_ptr);
-int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr);
+int tipc_bearer_blocked(struct tipc_bearer *b_ptr);
void tipc_bearer_stop(void);
-void tipc_bearer_lock_push(struct tipc_bearer *b_ptr);
-
/**
* tipc_bearer_send- sends buffer to destination over bearer
*
- * Returns true (1) if successful, or false (0) if unable to send
- *
* IMPORTANT:
* The media send routine must not alter the buffer being passed in
* as it may be needed for later retransmission!
- *
- * If the media send routine returns a non-zero value (indicating that
- * it was unable to send the buffer), it must:
- * 1) mark the bearer as blocked,
- * 2) call tipc_continue() once the bearer is able to send again.
- * Media types that are unable to meet these two critera must ensure their
- * send routine always returns success -- even if the buffer was not sent --
- * and let TIPC's link code deal with the undelivered message.
*/
-static inline int tipc_bearer_send(struct tipc_bearer *b_ptr,
- struct sk_buff *buf,
+static inline void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
struct tipc_media_addr *dest)
{
- return !b_ptr->media->send_msg(buf, b_ptr, dest);
+ b->media->send_msg(buf, b, dest);
}
#endif /* _TIPC_BEARER_H */
diff --git a/net/tipc/core.c b/net/tipc/core.c
index bfe8af88469a..fc05cecd7481 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -42,11 +42,6 @@
#include <linux/module.h>
-#ifndef CONFIG_TIPC_PORTS
-#define CONFIG_TIPC_PORTS 8191
-#endif
-
-
/* global variables used by multiple sub-systems within TIPC */
int tipc_random __read_mostly;
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 50eaa403eb6e..1074b9587e81 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -243,7 +243,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
if (rbuf) {
- b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
+ tipc_bearer_send(b_ptr, rbuf, &media_addr);
kfree_skb(rbuf);
}
}
diff --git a/net/tipc/link.c b/net/tipc/link.c
index a79c755cb417..daa6080a2a0c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1,7 +1,7 @@
/*
* net/tipc/link.c: TIPC link code
*
- * Copyright (c) 1996-2007, Ericsson AB
+ * Copyright (c) 1996-2007, 2012, Ericsson AB
* Copyright (c) 2004-2007, 2010-2011, Wind River Systems
* All rights reserved.
*
@@ -97,12 +97,13 @@ static int link_send_sections_long(struct tipc_port *sender,
struct iovec const *msg_sect,
u32 num_sect, unsigned int total_len,
u32 destnode);
-static void link_check_defragm_bufs(struct tipc_link *l_ptr);
static void link_state_event(struct tipc_link *l_ptr, u32 event);
static void link_reset_statistics(struct tipc_link *l_ptr);
static void link_print(struct tipc_link *l_ptr, const char *str);
static void link_start(struct tipc_link *l_ptr);
static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
+static void tipc_link_send_sync(struct tipc_link *l);
+static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
/*
* Simple link routines
@@ -269,7 +270,6 @@ static void link_timeout(struct tipc_link *l_ptr)
}
/* do all other link processing performed on a periodic basis */
- link_check_defragm_bufs(l_ptr);
link_state_event(l_ptr, TIMEOUT_EVT);
@@ -712,6 +712,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
link_activate(l_ptr);
tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
l_ptr->fsm_msg_cnt++;
+ if (l_ptr->owner->working_links == 1)
+ tipc_link_send_sync(l_ptr);
link_set_timer(l_ptr, cont_intv);
break;
case RESET_MSG:
@@ -745,6 +747,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
link_activate(l_ptr);
tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
l_ptr->fsm_msg_cnt++;
+ if (l_ptr->owner->working_links == 1)
+ tipc_link_send_sync(l_ptr);
link_set_timer(l_ptr, cont_intv);
break;
case RESET_MSG:
@@ -872,17 +876,12 @@ 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_congested(l_ptr->b_ptr, l_ptr) &&
+ if (likely(!tipc_bearer_blocked(l_ptr->b_ptr) &&
!link_congested(l_ptr))) {
link_add_to_outqueue(l_ptr, buf, msg);
- if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
- l_ptr->unacked_window = 0;
- } else {
- tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
- l_ptr->stats.bearer_congs++;
- l_ptr->next_out = buf;
- }
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+ l_ptr->unacked_window = 0;
return dsz;
}
/* Congestion: can message be bundled ? */
@@ -891,10 +890,8 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
/* Try adding message to an existing bundle */
if (l_ptr->next_out &&
- link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
- tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+ link_bundle_buf(l_ptr, l_ptr->last_out, buf))
return dsz;
- }
/* Try creating a new bundle */
if (size <= max_packet * 2 / 3) {
@@ -917,7 +914,6 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
if (!l_ptr->next_out)
l_ptr->next_out = buf;
link_add_to_outqueue(l_ptr, buf, msg);
- tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
return dsz;
}
@@ -949,7 +945,48 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
return res;
}
-/**
+/*
+ * tipc_link_send_sync - synchronize broadcast link endpoints.
+ *
+ * Give a newly added peer node the sequence number where it should
+ * start receiving and acking broadcast packets.
+ *
+ * Called with node locked
+ */
+static void tipc_link_send_sync(struct tipc_link *l)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+
+ buf = tipc_buf_acquire(INT_H_SIZE);
+ if (!buf)
+ return;
+
+ msg = buf_msg(buf);
+ tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, l->addr);
+ msg_set_last_bcast(msg, l->owner->bclink.acked);
+ link_add_chain_to_outqueue(l, buf, 0);
+ tipc_link_push_queue(l);
+}
+
+/*
+ * tipc_link_recv_sync - synchronize broadcast link endpoints.
+ * Receive the sequence number where we should start receiving and
+ * acking broadcast packets from a newly added peer node, and open
+ * up for reception of such packets.
+ *
+ * Called with node locked
+ */
+static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+
+ n->bclink.last_sent = n->bclink.last_in = msg_last_bcast(msg);
+ n->bclink.recv_permitted = true;
+ kfree_skb(buf);
+}
+
+/*
* tipc_link_send_names - send name table entries to new neighbor
*
* Send routine for bulk delivery of name table messages when contact
@@ -1006,16 +1043,11 @@ 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(list_empty(&l_ptr->b_ptr->cong_links))) {
+ if (likely(!tipc_bearer_blocked(l_ptr->b_ptr))) {
link_add_to_outqueue(l_ptr, buf, msg);
- if (likely(tipc_bearer_send(l_ptr->b_ptr, buf,
- &l_ptr->media_addr))) {
- l_ptr->unacked_window = 0;
- return res;
- }
- tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
- l_ptr->stats.bearer_congs++;
- l_ptr->next_out = buf;
+ tipc_bearer_send(l_ptr->b_ptr, buf,
+ &l_ptr->media_addr);
+ l_ptr->unacked_window = 0;
return res;
}
} else
@@ -1106,7 +1138,7 @@ exit:
/* Exit if link (or bearer) is congested */
if (link_congested(l_ptr) ||
- !list_empty(&l_ptr->b_ptr->cong_links)) {
+ tipc_bearer_blocked(l_ptr->b_ptr)) {
res = link_schedule_port(l_ptr,
sender->ref, res);
goto exit;
@@ -1329,15 +1361,11 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
if (r_q_size && buf) {
msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
- if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
- l_ptr->retransm_queue_head = mod(++r_q_head);
- l_ptr->retransm_queue_size = --r_q_size;
- l_ptr->stats.retransmitted++;
- return 0;
- } else {
- l_ptr->stats.bearer_congs++;
- return PUSH_FAILED;
- }
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+ l_ptr->retransm_queue_head = mod(++r_q_head);
+ l_ptr->retransm_queue_size = --r_q_size;
+ l_ptr->stats.retransmitted++;
+ return 0;
}
/* Send deferred protocol message, if any: */
@@ -1345,15 +1373,11 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
if (buf) {
msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
- if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
- l_ptr->unacked_window = 0;
- kfree_skb(buf);
- l_ptr->proto_msg_queue = NULL;
- return 0;
- } else {
- l_ptr->stats.bearer_congs++;
- return PUSH_FAILED;
- }
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+ l_ptr->unacked_window = 0;
+ kfree_skb(buf);
+ l_ptr->proto_msg_queue = NULL;
+ return 0;
}
/* Send one deferred data message, if send window not full: */
@@ -1366,18 +1390,14 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
if (mod(next - first) < l_ptr->queue_limit[0]) {
msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
- if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
- if (msg_user(msg) == MSG_BUNDLER)
- msg_set_type(msg, CLOSED_MSG);
- l_ptr->next_out = buf->next;
- return 0;
- } else {
- l_ptr->stats.bearer_congs++;
- return PUSH_FAILED;
- }
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+ if (msg_user(msg) == MSG_BUNDLER)
+ msg_set_type(msg, CLOSED_MSG);
+ l_ptr->next_out = buf->next;
+ return 0;
}
}
- return PUSH_FINISHED;
+ return 1;
}
/*
@@ -1388,15 +1408,12 @@ void tipc_link_push_queue(struct tipc_link *l_ptr)
{
u32 res;
- if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr))
+ if (tipc_bearer_blocked(l_ptr->b_ptr))
return;
do {
res = tipc_link_push_packet(l_ptr);
} while (!res);
-
- if (res == PUSH_FAILED)
- tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
}
static void link_reset_all(unsigned long addr)
@@ -1454,9 +1471,8 @@ static void link_retransmit_failure(struct tipc_link *l_ptr,
tipc_addr_string_fill(addr_string, n_ptr->addr);
pr_info("Broadcast link info for %s\n", addr_string);
- pr_info("Supportable: %d, Supported: %d, Acked: %u\n",
- n_ptr->bclink.supportable,
- n_ptr->bclink.supported,
+ pr_info("Reception permitted: %d, Acked: %u\n",
+ n_ptr->bclink.recv_permitted,
n_ptr->bclink.acked);
pr_info("Last in: %u, Oos state: %u, Last sent: %u\n",
n_ptr->bclink.last_in,
@@ -1481,7 +1497,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
msg = buf_msg(buf);
- if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
+ 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;
@@ -1491,7 +1507,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
}
return;
} else {
- /* Detect repeated retransmit failures on uncongested bearer */
+ /* 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);
@@ -1507,17 +1523,10 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
msg = buf_msg(buf);
msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
- if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
- buf = buf->next;
- retransmits--;
- l_ptr->stats.retransmitted++;
- } else {
- tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
- l_ptr->stats.bearer_congs++;
- l_ptr->retransm_queue_head = buf_seqno(buf);
- l_ptr->retransm_queue_size = retransmits;
- return;
- }
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+ buf = buf->next;
+ retransmits--;
+ l_ptr->stats.retransmitted++;
}
l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
@@ -1676,7 +1685,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
ackd = msg_ack(msg);
/* Release acked messages */
- if (n_ptr->bclink.supported)
+ if (n_ptr->bclink.recv_permitted)
tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
crs = l_ptr->first_out;
@@ -1727,9 +1736,14 @@ deliver:
tipc_link_recv_bundle(buf);
continue;
case NAME_DISTRIBUTOR:
+ n_ptr->bclink.recv_permitted = true;
tipc_node_unlock(n_ptr);
tipc_named_recv(buf);
continue;
+ case BCAST_PROTOCOL:
+ tipc_link_recv_sync(n_ptr, buf);
+ tipc_node_unlock(n_ptr);
+ continue;
case CONN_MANAGER:
tipc_node_unlock(n_ptr);
tipc_port_recv_proto_msg(buf);
@@ -1772,16 +1786,19 @@ deliver:
continue;
}
+ /* Link is not in state WORKING_WORKING */
if (msg_user(msg) == LINK_PROTOCOL) {
link_recv_proto_msg(l_ptr, buf);
head = link_insert_deferred_queue(l_ptr, head);
tipc_node_unlock(n_ptr);
continue;
}
+
+ /* Traffic message. Conditionally activate link */
link_state_event(l_ptr, TRAFFIC_MSG_EVT);
if (link_working_working(l_ptr)) {
- /* Re-insert in front of queue */
+ /* Re-insert buffer in front of queue */
buf->next = head;
head = buf;
tipc_node_unlock(n_ptr);
@@ -1972,21 +1989,13 @@ 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));
- /* Defer message if bearer is already congested */
- if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
- l_ptr->proto_msg_queue = buf;
- return;
- }
-
- /* Defer message if attempting to send results in bearer congestion */
- if (!tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
- tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+ /* Defer message if bearer is already blocked */
+ if (tipc_bearer_blocked(l_ptr->b_ptr)) {
l_ptr->proto_msg_queue = buf;
- l_ptr->stats.bearer_congs++;
return;
}
- /* Discard message if it was sent successfully */
+ tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
l_ptr->unacked_window = 0;
kfree_skb(buf);
}
@@ -2057,7 +2066,6 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
} else {
l_ptr->max_pkt = l_ptr->max_pkt_target;
}
- l_ptr->owner->bclink.supportable = (max_pkt_info != 0);
/* Synchronize broadcast link info, if not done previously */
if (!tipc_node_is_up(l_ptr->owner)) {
@@ -2112,7 +2120,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
}
/* Protocol message before retransmits, reduce loss risk */
- if (l_ptr->owner->bclink.supported)
+ if (l_ptr->owner->bclink.recv_permitted)
tipc_bclink_update_link_state(l_ptr->owner,
msg_last_bcast(msg));
@@ -2487,16 +2495,6 @@ static void set_expected_frags(struct sk_buff *buf, u32 exp)
msg_set_bcast_ack(buf_msg(buf), exp);
}
-static u32 get_timer_cnt(struct sk_buff *buf)
-{
- return msg_reroute_cnt(buf_msg(buf));
-}
-
-static void incr_timer_cnt(struct sk_buff *buf)
-{
- msg_incr_reroute_cnt(buf_msg(buf));
-}
-
/*
* tipc_link_recv_fragment(): Called with node lock on. Returns
* the reassembled buffer if message is complete.
@@ -2575,38 +2573,6 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
return 0;
}
-/**
- * link_check_defragm_bufs - flush stale incoming message fragments
- * @l_ptr: pointer to link
- */
-static void link_check_defragm_bufs(struct tipc_link *l_ptr)
-{
- struct sk_buff *prev = NULL;
- struct sk_buff *next = NULL;
- struct sk_buff *buf = l_ptr->defragm_buf;
-
- if (!buf)
- return;
- if (!link_working_working(l_ptr))
- return;
- while (buf) {
- u32 cnt = get_timer_cnt(buf);
-
- next = buf->next;
- if (cnt < 4) {
- incr_timer_cnt(buf);
- prev = buf;
- } else {
- if (prev)
- prev->next = buf->next;
- else
- l_ptr->defragm_buf = buf->next;
- kfree_skb(buf);
- }
- buf = next;
- }
-}
-
static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance)
{
if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL))
@@ -2937,8 +2903,8 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
s->sent_nacks, s->sent_acks, s->retransmitted);
ret += tipc_snprintf(buf + ret, buf_size - ret,
- " Congestion bearer:%u link:%u Send queue"
- " max:%u avg:%u\n", s->bearer_congs, s->link_congs,
+ " Congestion link:%u Send queue"
+ " max:%u avg:%u\n", s->link_congs,
s->max_queue_sz, s->queue_sz_counts ?
(s->accu_queue_sz / s->queue_sz_counts) : 0);
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 6e921121be06..c048ed1cbd76 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -40,9 +40,6 @@
#include "msg.h"
#include "node.h"
-#define PUSH_FAILED 1
-#define PUSH_FINISHED 2
-
/*
* Out-of-range value for link sequence numbers
*/
@@ -82,7 +79,6 @@ struct tipc_stats {
u32 recv_fragmented;
u32 recv_fragments;
u32 link_congs; /* # port sends blocked by congestion */
- u32 bearer_congs;
u32 deferred_recv;
u32 duplicates;
u32 max_queue_sz; /* send queue size high water mark */
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 55d3928dfd67..e0d08055754e 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -262,7 +262,7 @@ void tipc_named_node_up(unsigned long nodearg)
named_distribute(&message_list, node, &publ_zone, max_item_buf);
read_unlock_bh(&tipc_nametbl_lock);
- tipc_link_send_names(&message_list, (u32)node);
+ tipc_link_send_names(&message_list, node);
}
/**
diff --git a/net/tipc/node.c b/net/tipc/node.c
index d21db204e25a..48f39dd3eae8 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1,7 +1,7 @@
/*
* net/tipc/node.c: TIPC node management routines
*
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2012 Ericsson AB
* Copyright (c) 2005-2006, 2010-2011, Wind River Systems
* All rights reserved.
*
@@ -263,12 +263,9 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
static void node_established_contact(struct tipc_node *n_ptr)
{
tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
-
- if (n_ptr->bclink.supportable) {
- n_ptr->bclink.acked = tipc_bclink_get_last_sent();
- tipc_bclink_add_node(n_ptr->addr);
- n_ptr->bclink.supported = 1;
- }
+ n_ptr->bclink.oos_state = 0;
+ n_ptr->bclink.acked = tipc_bclink_get_last_sent();
+ tipc_bclink_add_node(n_ptr->addr);
}
static void node_name_purge_complete(unsigned long node_addr)
@@ -294,7 +291,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
tipc_addr_string_fill(addr_string, n_ptr->addr));
/* Flush broadcast link info associated with lost node */
- if (n_ptr->bclink.supported) {
+ 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;
@@ -310,7 +307,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
tipc_bclink_remove_node(n_ptr->addr);
tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
- n_ptr->bclink.supported = 0;
+ n_ptr->bclink.recv_permitted = false;
}
/* Abort link changeover */
diff --git a/net/tipc/node.h b/net/tipc/node.h
index cfcaf4d6e480..3c189b35b102 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -67,8 +67,6 @@
* @permit_changeover: non-zero if node has redundant links to this system
* @signature: node instance identifier
* @bclink: broadcast-related info
- * @supportable: non-zero if node supports TIPC b'cast link capability
- * @supported: non-zero if node supports TIPC b'cast capability
* @acked: sequence # of last outbound b'cast message acknowledged by node
* @last_in: sequence # of last in-sequence b'cast message received from node
* @last_sent: sequence # of last b'cast message sent by node
@@ -77,6 +75,7 @@
* @deferred_head: oldest OOS b'cast message received from node
* @deferred_tail: newest OOS b'cast message received from node
* @defragm: list of partially reassembled b'cast message fragments from node
+ * @recv_permitted: true if node is allowed to receive b'cast messages
*/
struct tipc_node {
u32 addr;
@@ -92,8 +91,6 @@ struct tipc_node {
int permit_changeover;
u32 signature;
struct {
- u8 supportable;
- u8 supported;
u32 acked;
u32 last_in;
u32 last_sent;
@@ -102,6 +99,7 @@ struct tipc_node {
struct sk_buff *deferred_head;
struct sk_buff *deferred_tail;
struct sk_buff *defragm;
+ bool recv_permitted;
} bclink;
};
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 07c42fba672b..18098cac62f2 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -726,7 +726,7 @@ static void port_dispatcher_sigh(void *dummy)
if (unlikely(!cb))
goto reject;
if (unlikely(!connected)) {
- if (tipc_connect2port(dref, &orig))
+ if (tipc_connect(dref, &orig))
goto reject;
} else if (peer_invalid)
goto reject;
@@ -1036,15 +1036,30 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
return res;
}
-int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
+int tipc_connect(u32 ref, struct tipc_portid const *peer)
{
struct tipc_port *p_ptr;
- struct tipc_msg *msg;
- int res = -EINVAL;
+ int res;
p_ptr = tipc_port_lock(ref);
if (!p_ptr)
return -EINVAL;
+ res = __tipc_connect(ref, p_ptr, peer);
+ tipc_port_unlock(p_ptr);
+ return res;
+}
+
+/*
+ * __tipc_connect - connect to a remote peer
+ *
+ * Port must be locked.
+ */
+int __tipc_connect(u32 ref, struct tipc_port *p_ptr,
+ struct tipc_portid const *peer)
+{
+ struct tipc_msg *msg;
+ int res = -EINVAL;
+
if (p_ptr->published || p_ptr->connected)
goto exit;
if (!peer->ref)
@@ -1067,17 +1082,16 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
(net_ev_handler)port_handle_node_down);
res = 0;
exit:
- tipc_port_unlock(p_ptr);
p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
return res;
}
-/**
- * tipc_disconnect_port - disconnect port from peer
+/*
+ * __tipc_disconnect - disconnect port from peer
*
* Port must be locked.
*/
-int tipc_disconnect_port(struct tipc_port *tp_ptr)
+int __tipc_disconnect(struct tipc_port *tp_ptr)
{
int res;
@@ -1104,7 +1118,7 @@ int tipc_disconnect(u32 ref)
p_ptr = tipc_port_lock(ref);
if (!p_ptr)
return -EINVAL;
- res = tipc_disconnect_port(p_ptr);
+ res = __tipc_disconnect(p_ptr);
tipc_port_unlock(p_ptr);
return res;
}
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 4660e3065790..fb66e2e5f4d1 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -190,7 +190,7 @@ int tipc_publish(u32 portref, unsigned int scope,
int tipc_withdraw(u32 portref, unsigned int scope,
struct tipc_name_seq const *name_seq);
-int tipc_connect2port(u32 portref, struct tipc_portid const *port);
+int tipc_connect(u32 portref, struct tipc_portid const *port);
int tipc_disconnect(u32 portref);
@@ -200,7 +200,9 @@ int tipc_shutdown(u32 ref);
/*
* The following routines require that the port be locked on entry
*/
-int tipc_disconnect_port(struct tipc_port *tp_ptr);
+int __tipc_disconnect(struct tipc_port *tp_ptr);
+int __tipc_connect(u32 ref, struct tipc_port *p_ptr,
+ struct tipc_portid const *peer);
int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg);
/*
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index fd5f042dbff4..9b4e4833a484 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,8 +1,8 @@
/*
* net/tipc/socket.c: TIPC socket API
*
- * Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
+ * Copyright (c) 2001-2007, 2012 Ericsson AB
+ * Copyright (c) 2004-2008, 2010-2012, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
#define SS_LISTENING -1 /* socket is listening */
#define SS_READY -2 /* socket is connectionless */
-#define OVERLOAD_LIMIT_BASE 5000
+#define OVERLOAD_LIMIT_BASE 10000
#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
struct tipc_sock {
@@ -62,6 +62,8 @@ struct tipc_sock {
static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
static void wakeupdispatch(struct tipc_port *tport);
+static void tipc_data_ready(struct sock *sk, int len);
+static void tipc_write_space(struct sock *sk);
static const struct proto_ops packet_ops;
static const struct proto_ops stream_ops;
@@ -71,8 +73,6 @@ static struct proto tipc_proto;
static int sockets_enabled;
-static atomic_t tipc_queue_size = ATOMIC_INIT(0);
-
/*
* Revised TIPC socket locking policy:
*
@@ -126,7 +126,6 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
static void advance_rx_queue(struct sock *sk)
{
kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
- atomic_dec(&tipc_queue_size);
}
/**
@@ -138,10 +137,8 @@ static void discard_rx_queue(struct sock *sk)
{
struct sk_buff *buf;
- while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
- atomic_dec(&tipc_queue_size);
+ while ((buf = __skb_dequeue(&sk->sk_receive_queue)))
kfree_skb(buf);
- }
}
/**
@@ -153,10 +150,8 @@ static void reject_rx_queue(struct sock *sk)
{
struct sk_buff *buf;
- while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
+ while ((buf = __skb_dequeue(&sk->sk_receive_queue)))
tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
- atomic_dec(&tipc_queue_size);
- }
}
/**
@@ -221,6 +216,8 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
sock_init_data(sock, sk);
sk->sk_backlog_rcv = backlog_rcv;
sk->sk_rcvbuf = TIPC_FLOW_CONTROL_WIN * 2 * TIPC_MAX_USER_MSG_SIZE * 2;
+ sk->sk_data_ready = tipc_data_ready;
+ sk->sk_write_space = tipc_write_space;
tipc_sk(sk)->p = tp_ptr;
tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT;
@@ -276,7 +273,6 @@ static int release(struct socket *sock)
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf == NULL)
break;
- atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0)
kfree_skb(buf);
else {
@@ -408,7 +404,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
* socket state flags set
* ------------ ---------
* unconnected no read flags
- * no write flags
+ * POLLOUT if port is not congested
*
* connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
* no write flags
@@ -435,9 +431,13 @@ static unsigned int poll(struct file *file, struct socket *sock,
struct sock *sk = sock->sk;
u32 mask = 0;
- poll_wait(file, sk_sleep(sk), wait);
+ sock_poll_wait(file, sk_sleep(sk), wait);
switch ((int)sock->state) {
+ case SS_UNCONNECTED:
+ if (!tipc_sk_port(sk)->congested)
+ mask |= POLLOUT;
+ break;
case SS_READY:
case SS_CONNECTED:
if (!tipc_sk_port(sk)->congested)
@@ -775,16 +775,19 @@ exit:
static int auto_connect(struct socket *sock, struct tipc_msg *msg)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
-
- if (msg_errcode(msg)) {
- sock->state = SS_DISCONNECTING;
- return -ECONNREFUSED;
- }
+ struct tipc_port *p_ptr;
tsock->peer_name.ref = msg_origport(msg);
tsock->peer_name.node = msg_orignode(msg);
- tipc_connect2port(tsock->p->ref, &tsock->peer_name);
- tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
+ p_ptr = tipc_port_deref(tsock->p->ref);
+ if (!p_ptr)
+ return -EINVAL;
+
+ __tipc_connect(tsock->p->ref, p_ptr, &tsock->peer_name);
+
+ if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE)
+ return -EINVAL;
+ msg_set_importance(&p_ptr->phdr, (u32)msg_importance(msg));
sock->state = SS_CONNECTED;
return 0;
}
@@ -943,13 +946,6 @@ restart:
sz = msg_data_sz(msg);
err = msg_errcode(msg);
- /* Complete connection setup for an implied connect */
- if (unlikely(sock->state == SS_CONNECTING)) {
- res = auto_connect(sock, msg);
- if (res)
- goto exit;
- }
-
/* Discard an empty non-errored message & try again */
if ((!sz) && (!err)) {
advance_rx_queue(sk);
@@ -1126,6 +1122,39 @@ exit:
}
/**
+ * tipc_write_space - wake up thread if port congestion is released
+ * @sk: socket
+ */
+static void tipc_write_space(struct sock *sk)
+{
+ struct socket_wq *wq;
+
+ rcu_read_lock();
+ wq = rcu_dereference(sk->sk_wq);
+ if (wq_has_sleeper(wq))
+ wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
+ POLLWRNORM | POLLWRBAND);
+ rcu_read_unlock();
+}
+
+/**
+ * tipc_data_ready - wake up threads to indicate messages have been received
+ * @sk: socket
+ * @len: the length of messages
+ */
+static void tipc_data_ready(struct sock *sk, int len)
+{
+ struct socket_wq *wq;
+
+ rcu_read_lock();
+ wq = rcu_dereference(sk->sk_wq);
+ if (wq_has_sleeper(wq))
+ wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
+ POLLRDNORM | POLLRDBAND);
+ rcu_read_unlock();
+}
+
+/**
* rx_queue_full - determine if receive queue can accept another message
* @msg: message to be added to queue
* @queue_size: current size of queue
@@ -1154,6 +1183,83 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
}
/**
+ * filter_connect - Handle all incoming messages for a connection-based socket
+ * @tsock: TIPC socket
+ * @msg: message
+ *
+ * Returns TIPC error status code and socket error status code
+ * once it encounters some errors
+ */
+static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
+{
+ struct socket *sock = tsock->sk.sk_socket;
+ struct tipc_msg *msg = buf_msg(*buf);
+ struct sock *sk = &tsock->sk;
+ u32 retval = TIPC_ERR_NO_PORT;
+ int res;
+
+ if (msg_mcast(msg))
+ return retval;
+
+ switch ((int)sock->state) {
+ case SS_CONNECTED:
+ /* Accept only connection-based messages sent by peer */
+ if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) {
+ if (unlikely(msg_errcode(msg))) {
+ sock->state = SS_DISCONNECTING;
+ __tipc_disconnect(tsock->p);
+ }
+ retval = TIPC_OK;
+ }
+ break;
+ case SS_CONNECTING:
+ /* Accept only ACK or NACK message */
+ if (unlikely(msg_errcode(msg))) {
+ sock->state = SS_DISCONNECTING;
+ sk->sk_err = -ECONNREFUSED;
+ retval = TIPC_OK;
+ break;
+ }
+
+ if (unlikely(!msg_connected(msg)))
+ break;
+
+ res = auto_connect(sock, msg);
+ if (res) {
+ sock->state = SS_DISCONNECTING;
+ sk->sk_err = res;
+ retval = TIPC_OK;
+ break;
+ }
+
+ /* If an incoming message is an 'ACK-', it should be
+ * discarded here because it doesn't contain useful
+ * data. In addition, we should try to wake up
+ * connect() routine if sleeping.
+ */
+ if (msg_data_sz(msg) == 0) {
+ kfree_skb(*buf);
+ *buf = NULL;
+ if (waitqueue_active(sk_sleep(sk)))
+ wake_up_interruptible(sk_sleep(sk));
+ }
+ retval = TIPC_OK;
+ break;
+ case SS_LISTENING:
+ case SS_UNCONNECTED:
+ /* Accept only SYN message */
+ if (!msg_connected(msg) && !(msg_errcode(msg)))
+ retval = TIPC_OK;
+ break;
+ case SS_DISCONNECTING:
+ break;
+ default:
+ pr_err("Unknown socket state %u\n", sock->state);
+ }
+ return retval;
+}
+
+/**
* filter_rcv - validate incoming message
* @sk: socket
* @buf: message
@@ -1170,6 +1276,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
struct socket *sock = sk->sk_socket;
struct tipc_msg *msg = buf_msg(buf);
u32 recv_q_len;
+ u32 res = TIPC_OK;
/* Reject message if it is wrong sort of message for socket */
if (msg_type(msg) > TIPC_DIRECT_MSG)
@@ -1179,32 +1286,12 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
if (msg_connected(msg))
return TIPC_ERR_NO_PORT;
} else {
- if (msg_mcast(msg))
- return TIPC_ERR_NO_PORT;
- if (sock->state == SS_CONNECTED) {
- if (!msg_connected(msg) ||
- !tipc_port_peer_msg(tipc_sk_port(sk), msg))
- return TIPC_ERR_NO_PORT;
- } else if (sock->state == SS_CONNECTING) {
- if (!msg_connected(msg) && (msg_errcode(msg) == 0))
- return TIPC_ERR_NO_PORT;
- } else if (sock->state == SS_LISTENING) {
- if (msg_connected(msg) || msg_errcode(msg))
- return TIPC_ERR_NO_PORT;
- } else if (sock->state == SS_DISCONNECTING) {
- return TIPC_ERR_NO_PORT;
- } else /* (sock->state == SS_UNCONNECTED) */ {
- if (msg_connected(msg) || msg_errcode(msg))
- return TIPC_ERR_NO_PORT;
- }
+ res = filter_connect(tipc_sk(sk), &buf);
+ if (res != TIPC_OK || buf == NULL)
+ return res;
}
/* Reject message if there isn't room to queue it */
- recv_q_len = (u32)atomic_read(&tipc_queue_size);
- if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
- if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
- return TIPC_ERR_OVERLOAD;
- }
recv_q_len = skb_queue_len(&sk->sk_receive_queue);
if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
@@ -1213,17 +1300,9 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
/* Enqueue message (finally!) */
TIPC_SKB_CB(buf)->handle = 0;
- atomic_inc(&tipc_queue_size);
__skb_queue_tail(&sk->sk_receive_queue, buf);
- /* Initiate connection termination for an incoming 'FIN' */
- if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
- sock->state = SS_DISCONNECTING;
- tipc_disconnect_port(tipc_sk_port(sk));
- }
-
- if (waitqueue_active(sk_sleep(sk)))
- wake_up_interruptible(sk_sleep(sk));
+ sk->sk_data_ready(sk, 0);
return TIPC_OK;
}
@@ -1290,8 +1369,7 @@ static void wakeupdispatch(struct tipc_port *tport)
{
struct sock *sk = (struct sock *)tport->usr_handle;
- if (waitqueue_active(sk_sleep(sk)))
- wake_up_interruptible(sk_sleep(sk));
+ sk->sk_write_space(sk);
}
/**
@@ -1309,8 +1387,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
struct sock *sk = sock->sk;
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
struct msghdr m = {NULL,};
- struct sk_buff *buf;
- struct tipc_msg *msg;
unsigned int timeout;
int res;
@@ -1322,26 +1398,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
goto exit;
}
- /* For now, TIPC does not support the non-blocking form of connect() */
- if (flags & O_NONBLOCK) {
- res = -EOPNOTSUPP;
- goto exit;
- }
-
- /* Issue Posix-compliant error code if socket is in the wrong state */
- if (sock->state == SS_LISTENING) {
- res = -EOPNOTSUPP;
- goto exit;
- }
- if (sock->state == SS_CONNECTING) {
- res = -EALREADY;
- goto exit;
- }
- if (sock->state != SS_UNCONNECTED) {
- res = -EISCONN;
- goto exit;
- }
-
/*
* Reject connection attempt using multicast address
*
@@ -1353,49 +1409,66 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
goto exit;
}
- /* Reject any messages already in receive queue (very unlikely) */
- reject_rx_queue(sk);
+ timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout;
- /* Send a 'SYN-' to destination */
- m.msg_name = dest;
- m.msg_namelen = destlen;
- res = send_msg(NULL, sock, &m, 0);
- if (res < 0)
+ switch (sock->state) {
+ case SS_UNCONNECTED:
+ /* Send a 'SYN-' to destination */
+ m.msg_name = dest;
+ m.msg_namelen = destlen;
+
+ /* If connect is in non-blocking case, set MSG_DONTWAIT to
+ * indicate send_msg() is never blocked.
+ */
+ if (!timeout)
+ m.msg_flags = MSG_DONTWAIT;
+
+ res = send_msg(NULL, sock, &m, 0);
+ if ((res < 0) && (res != -EWOULDBLOCK))
+ goto exit;
+
+ /* Just entered SS_CONNECTING state; the only
+ * difference is that return value in non-blocking
+ * case is EINPROGRESS, rather than EALREADY.
+ */
+ res = -EINPROGRESS;
+ break;
+ case SS_CONNECTING:
+ res = -EALREADY;
+ break;
+ case SS_CONNECTED:
+ res = -EISCONN;
+ break;
+ default:
+ res = -EINVAL;
goto exit;
+ }
- /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
- timeout = tipc_sk(sk)->conn_timeout;
- release_sock(sk);
- res = wait_event_interruptible_timeout(*sk_sleep(sk),
- (!skb_queue_empty(&sk->sk_receive_queue) ||
- (sock->state != SS_CONNECTING)),
- timeout ? (long)msecs_to_jiffies(timeout)
- : MAX_SCHEDULE_TIMEOUT);
- lock_sock(sk);
+ if (sock->state == SS_CONNECTING) {
+ if (!timeout)
+ goto exit;
- if (res > 0) {
- buf = skb_peek(&sk->sk_receive_queue);
- if (buf != NULL) {
- msg = buf_msg(buf);
- res = auto_connect(sock, msg);
- if (!res) {
- if (!msg_data_sz(msg))
- advance_rx_queue(sk);
- }
- } else {
- if (sock->state == SS_CONNECTED)
- res = -EISCONN;
+ /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
+ release_sock(sk);
+ res = wait_event_interruptible_timeout(*sk_sleep(sk),
+ sock->state != SS_CONNECTING,
+ timeout ? (long)msecs_to_jiffies(timeout)
+ : MAX_SCHEDULE_TIMEOUT);
+ lock_sock(sk);
+ if (res <= 0) {
+ if (res == 0)
+ res = -ETIMEDOUT;
else
- res = -ECONNREFUSED;
+ ; /* leave "res" unchanged */
+ goto exit;
}
- } else {
- if (res == 0)
- res = -ETIMEDOUT;
- else
- ; /* leave "res" unchanged */
- sock->state = SS_DISCONNECTING;
}
+ if (unlikely(sock->state == SS_DISCONNECTING))
+ res = sock_error(sk);
+ else
+ res = 0;
+
exit:
release_sock(sk);
return res;
@@ -1436,8 +1509,13 @@ static int listen(struct socket *sock, int len)
*/
static int accept(struct socket *sock, struct socket *new_sock, int flags)
{
- struct sock *sk = sock->sk;
+ struct sock *new_sk, *sk = sock->sk;
struct sk_buff *buf;
+ struct tipc_sock *new_tsock;
+ struct tipc_port *new_tport;
+ struct tipc_msg *msg;
+ u32 new_ref;
+
int res;
lock_sock(sk);
@@ -1463,48 +1541,51 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
buf = skb_peek(&sk->sk_receive_queue);
res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
- if (!res) {
- struct sock *new_sk = new_sock->sk;
- struct tipc_sock *new_tsock = tipc_sk(new_sk);
- struct tipc_port *new_tport = new_tsock->p;
- u32 new_ref = new_tport->ref;
- struct tipc_msg *msg = buf_msg(buf);
-
- lock_sock(new_sk);
-
- /*
- * Reject any stray messages received by new socket
- * before the socket lock was taken (very, very unlikely)
- */
- reject_rx_queue(new_sk);
-
- /* Connect new socket to it's peer */
- new_tsock->peer_name.ref = msg_origport(msg);
- new_tsock->peer_name.node = msg_orignode(msg);
- tipc_connect2port(new_ref, &new_tsock->peer_name);
- new_sock->state = SS_CONNECTED;
-
- tipc_set_portimportance(new_ref, msg_importance(msg));
- if (msg_named(msg)) {
- new_tport->conn_type = msg_nametype(msg);
- new_tport->conn_instance = msg_nameinst(msg);
- }
+ if (res)
+ goto exit;
- /*
- * Respond to 'SYN-' by discarding it & returning 'ACK'-.
- * Respond to 'SYN+' by queuing it on new socket.
- */
- if (!msg_data_sz(msg)) {
- struct msghdr m = {NULL,};
+ new_sk = new_sock->sk;
+ new_tsock = tipc_sk(new_sk);
+ new_tport = new_tsock->p;
+ new_ref = new_tport->ref;
+ msg = buf_msg(buf);
- advance_rx_queue(sk);
- send_packet(NULL, new_sock, &m, 0);
- } else {
- __skb_dequeue(&sk->sk_receive_queue);
- __skb_queue_head(&new_sk->sk_receive_queue, buf);
- }
- release_sock(new_sk);
+ /* we lock on new_sk; but lockdep sees the lock on sk */
+ lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING);
+
+ /*
+ * Reject any stray messages received by new socket
+ * before the socket lock was taken (very, very unlikely)
+ */
+ reject_rx_queue(new_sk);
+
+ /* Connect new socket to it's peer */
+ new_tsock->peer_name.ref = msg_origport(msg);
+ new_tsock->peer_name.node = msg_orignode(msg);
+ tipc_connect(new_ref, &new_tsock->peer_name);
+ new_sock->state = SS_CONNECTED;
+
+ tipc_set_portimportance(new_ref, msg_importance(msg));
+ if (msg_named(msg)) {
+ new_tport->conn_type = msg_nametype(msg);
+ new_tport->conn_instance = msg_nameinst(msg);
}
+
+ /*
+ * Respond to 'SYN-' by discarding it & returning 'ACK'-.
+ * Respond to 'SYN+' by queuing it on new socket.
+ */
+ if (!msg_data_sz(msg)) {
+ struct msghdr m = {NULL,};
+
+ advance_rx_queue(sk);
+ send_packet(NULL, new_sock, &m, 0);
+ } else {
+ __skb_dequeue(&sk->sk_receive_queue);
+ __skb_queue_head(&new_sk->sk_receive_queue, buf);
+ }
+ release_sock(new_sk);
+
exit:
release_sock(sk);
return res;
@@ -1539,7 +1620,6 @@ restart:
/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
buf = __skb_dequeue(&sk->sk_receive_queue);
if (buf) {
- atomic_dec(&tipc_queue_size);
if (TIPC_SKB_CB(buf)->handle != 0) {
kfree_skb(buf);
goto restart;
@@ -1556,10 +1636,11 @@ restart:
case SS_DISCONNECTING:
- /* Discard any unreceived messages; wake up sleeping tasks */
+ /* Discard any unreceived messages */
discard_rx_queue(sk);
- if (waitqueue_active(sk_sleep(sk)))
- wake_up_interruptible(sk_sleep(sk));
+
+ /* Wake up anyone sleeping in poll */
+ sk->sk_state_change(sk);
res = 0;
break;
@@ -1677,7 +1758,7 @@ static int getsockopt(struct socket *sock,
/* no need to set "res", since already 0 at this point */
break;
case TIPC_NODE_RECVQ_DEPTH:
- value = (u32)atomic_read(&tipc_queue_size);
+ value = 0; /* was tipc_queue_size, now obsolete */
break;
case TIPC_SOCK_RECVQ_DEPTH:
value = skb_queue_len(&sk->sk_receive_queue);
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 0f7d0d007e22..6b42d47029af 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -462,7 +462,7 @@ static void subscr_named_msg_event(void *usr_handle,
kfree(subscriber);
return;
}
- tipc_connect2port(subscriber->port_ref, orig);
+ tipc_connect(subscriber->port_ref, orig);
/* Lock server port (& save lock address for future use) */
subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock;
diff --git a/net/unix/diag.c b/net/unix/diag.c
index 06748f108a57..5ac19dc1d5e4 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -151,6 +151,9 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
goto out_nlmsg_trim;
+ if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, sk->sk_shutdown))
+ goto out_nlmsg_trim;
+
return nlmsg_end(skb, nlh);
out_nlmsg_trim:
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index b34b5b9792f0..8800604c93f4 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -34,6 +34,10 @@ int __net_init unix_sysctl_register(struct net *net)
if (table == NULL)
goto err_alloc;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
table[0].data = &net->unx.sysctl_max_dgram_qlen;
net->unx.ctl = register_net_sysctl(net, "net/unix", table);
if (net->unx.ctl == NULL)
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index fe4adb12b3ef..16d08b399210 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -140,14 +140,13 @@ config CFG80211_WEXT
extensions with cfg80211-based drivers.
config LIB80211
- tristate "Common routines for IEEE802.11 drivers"
+ tristate
default n
help
This options enables a library of common routines used
by IEEE802.11 wireless LAN drivers.
- Drivers should select this themselves if needed. Say Y if
- you want this built into your kernel.
+ Drivers should select this themselves if needed.
config LIB80211_CRYPT_WEP
tristate
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 0f7e0d621ab0..a761670af31d 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,11 +10,13 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
-cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
+CFLAGS_trace.o := -I$(src)
+
ccflags-y += -D__CHECK_ENDIAN__
$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index fcc60d8dbefa..324e8d851dc4 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -3,6 +3,7 @@
#include <net/cfg80211.h>
#include "nl80211.h"
#include "core.h"
+#include "rdev-ops.h"
static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
@@ -23,10 +24,11 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
if (!wdev->beacon_interval)
return -ENOENT;
- err = rdev->ops->stop_ap(&rdev->wiphy, dev);
+ err = rdev_stop_ap(rdev, dev);
if (!err) {
wdev->beacon_interval = 0;
wdev->channel = NULL;
+ wdev->ssid_len = 0;
}
return err;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 2f876b9ee344..a7990bb16529 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -9,90 +9,303 @@
#include <linux/export.h>
#include <net/cfg80211.h>
#include "core.h"
+#include "rdev-ops.h"
-struct ieee80211_channel *
-rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type channel_type)
+void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type chan_type)
{
- struct ieee80211_channel *chan;
- struct ieee80211_sta_ht_cap *ht_cap;
+ if (WARN_ON(!chan))
+ return;
+
+ chandef->chan = chan;
+ chandef->center_freq2 = 0;
+
+ switch (chan_type) {
+ case NL80211_CHAN_NO_HT:
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = chan->center_freq;
+ break;
+ case NL80211_CHAN_HT20:
+ chandef->width = NL80211_CHAN_WIDTH_20;
+ chandef->center_freq1 = chan->center_freq;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ chandef->width = NL80211_CHAN_WIDTH_40;
+ chandef->center_freq1 = chan->center_freq + 10;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ chandef->width = NL80211_CHAN_WIDTH_40;
+ chandef->center_freq1 = chan->center_freq - 10;
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+EXPORT_SYMBOL(cfg80211_chandef_create);
+
+bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
+{
+ u32 control_freq;
+
+ if (!chandef->chan)
+ return false;
- chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ control_freq = chandef->chan->center_freq;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ if (chandef->center_freq1 != control_freq)
+ return false;
+ if (chandef->center_freq2)
+ return false;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 != control_freq + 10 &&
+ chandef->center_freq1 != control_freq - 10)
+ return false;
+ if (chandef->center_freq2)
+ return false;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ if (chandef->center_freq1 != control_freq + 30 &&
+ chandef->center_freq1 != control_freq + 10 &&
+ chandef->center_freq1 != control_freq - 10 &&
+ chandef->center_freq1 != control_freq - 30)
+ return false;
+ if (!chandef->center_freq2)
+ return false;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ if (chandef->center_freq1 != control_freq + 30 &&
+ chandef->center_freq1 != control_freq + 10 &&
+ chandef->center_freq1 != control_freq - 10 &&
+ chandef->center_freq1 != control_freq - 30)
+ return false;
+ if (chandef->center_freq2)
+ return false;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ if (chandef->center_freq1 != control_freq + 70 &&
+ chandef->center_freq1 != control_freq + 50 &&
+ chandef->center_freq1 != control_freq + 30 &&
+ chandef->center_freq1 != control_freq + 10 &&
+ chandef->center_freq1 != control_freq - 10 &&
+ chandef->center_freq1 != control_freq - 30 &&
+ chandef->center_freq1 != control_freq - 50 &&
+ chandef->center_freq1 != control_freq - 70)
+ return false;
+ if (chandef->center_freq2)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(cfg80211_chandef_valid);
+
+static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
+ int *pri40, int *pri80)
+{
+ int tmp;
+
+ switch (c->width) {
+ case NL80211_CHAN_WIDTH_40:
+ *pri40 = c->center_freq1;
+ *pri80 = 0;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ *pri80 = c->center_freq1;
+ /* n_P20 */
+ tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
+ /* n_P40 */
+ tmp /= 2;
+ /* freq_P40 */
+ *pri40 = c->center_freq1 - 20 + 40 * tmp;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ /* n_P20 */
+ tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
+ /* n_P40 */
+ tmp /= 2;
+ /* freq_P40 */
+ *pri40 = c->center_freq1 - 60 + 40 * tmp;
+ /* n_P80 */
+ tmp /= 2;
+ *pri80 = c->center_freq1 - 40 + 80 * tmp;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
+}
- /* Primary channel not allowed */
- if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+const struct cfg80211_chan_def *
+cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
+ const struct cfg80211_chan_def *c2)
+{
+ u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80;
+
+ /* If they are identical, return */
+ if (cfg80211_chandef_identical(c1, c2))
+ return c1;
+
+ /* otherwise, must have same control channel */
+ if (c1->chan != c2->chan)
return NULL;
- if (channel_type == NL80211_CHAN_HT40MINUS &&
- chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
+ /*
+ * If they have the same width, but aren't identical,
+ * then they can't be compatible.
+ */
+ if (c1->width == c2->width)
return NULL;
- else if (channel_type == NL80211_CHAN_HT40PLUS &&
- chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
+
+ if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
+ c1->width == NL80211_CHAN_WIDTH_20)
+ return c2;
+
+ if (c2->width == NL80211_CHAN_WIDTH_20_NOHT ||
+ c2->width == NL80211_CHAN_WIDTH_20)
+ return c1;
+
+ chandef_primary_freqs(c1, &c1_pri40, &c1_pri80);
+ chandef_primary_freqs(c2, &c2_pri40, &c2_pri80);
+
+ if (c1_pri40 != c2_pri40)
return NULL;
- ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
+ WARN_ON(!c1_pri80 && !c2_pri80);
+ if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80)
+ return NULL;
- if (channel_type != NL80211_CHAN_NO_HT) {
- if (!ht_cap->ht_supported)
- return NULL;
+ if (c1->width > c2->width)
+ return c1;
+ return c2;
+}
+EXPORT_SYMBOL(cfg80211_chandef_compatible);
- if (channel_type != NL80211_CHAN_HT20 &&
- (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
- ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
- return NULL;
+static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
+ u32 center_freq, u32 bandwidth,
+ u32 prohibited_flags)
+{
+ struct ieee80211_channel *c;
+ u32 freq;
+
+ for (freq = center_freq - bandwidth/2 + 10;
+ freq <= center_freq + bandwidth/2 - 10;
+ freq += 20) {
+ c = ieee80211_get_channel(wiphy, freq);
+ if (!c || c->flags & prohibited_flags)
+ return false;
}
- return chan;
+ return true;
}
-bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
+bool cfg80211_chandef_usable(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 prohibited_flags)
{
- struct ieee80211_channel *sec_chan;
- int diff;
+ struct ieee80211_sta_ht_cap *ht_cap;
+ struct ieee80211_sta_vht_cap *vht_cap;
+ u32 width, control_freq;
- switch (channel_type) {
- case NL80211_CHAN_HT40PLUS:
- diff = 20;
+ if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+ return false;
+
+ ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
+ vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
+
+ control_freq = chandef->chan->center_freq;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20:
+ if (!ht_cap->ht_supported)
+ return false;
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ width = 20;
break;
- case NL80211_CHAN_HT40MINUS:
- diff = -20;
+ case NL80211_CHAN_WIDTH_40:
+ width = 40;
+ if (!ht_cap->ht_supported)
+ return false;
+ if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
+ ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
+ return false;
+ if (chandef->center_freq1 < control_freq &&
+ chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
+ return false;
+ if (chandef->center_freq1 > control_freq &&
+ chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
+ return false;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+ return false;
+ case NL80211_CHAN_WIDTH_80:
+ if (!vht_cap->vht_supported)
+ return false;
+ width = 80;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ if (!vht_cap->vht_supported)
+ return false;
+ if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
+ return false;
+ width = 160;
break;
default:
- return true;
+ WARN_ON_ONCE(1);
+ return false;
}
- sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
- if (!sec_chan)
- return false;
+ /* TODO: missing regulatory check on 80/160 bandwidth */
- /* we'll need a DFS capability later */
- if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_PASSIVE_SCAN |
- IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_RADAR))
+ if (width > 20)
+ prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
+
+ if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
+ width, prohibited_flags))
return false;
- return true;
+ if (!chandef->center_freq2)
+ return true;
+ return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
+ width, prohibited_flags);
}
-EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
+EXPORT_SYMBOL(cfg80211_chandef_usable);
-int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type chantype)
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef)
{
- struct ieee80211_channel *chan;
+ bool res;
+
+ 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);
+
+ trace_cfg80211_return_bool(res);
+ return res;
+}
+EXPORT_SYMBOL(cfg80211_reg_can_beacon);
+
+int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct cfg80211_chan_def *chandef)
+{
if (!rdev->ops->set_monitor_channel)
return -EOPNOTSUPP;
if (!cfg80211_has_monitors_only(rdev))
return -EBUSY;
- chan = rdev_freq_to_chan(rdev, freq, chantype);
- if (!chan)
- return -EINVAL;
-
- return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+ return rdev_set_monitor_channel(rdev, chandef);
}
void
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 3f7253052088..14d990400354 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -26,6 +26,7 @@
#include "debugfs.h"
#include "wext-compat.h"
#include "ethtool.h"
+#include "rdev-ops.h"
/* name for sysfs, %d is appended */
#define PHY_NAME "phy"
@@ -216,7 +217,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
{
struct cfg80211_registered_device *rdev = data;
- rdev->ops->rfkill_poll(&rdev->wiphy);
+ rdev_rfkill_poll(rdev);
}
static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -240,7 +241,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
case NL80211_IFTYPE_P2P_DEVICE:
if (!wdev->p2p_started)
break;
- rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
+ rdev_stop_p2p_device(rdev, wdev);
wdev->p2p_started = false;
rdev->opencount--;
break;
@@ -325,6 +326,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
mutex_init(&rdev->devlist_mtx);
mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->wdev_list);
+ INIT_LIST_HEAD(&rdev->beacon_registrations);
+ spin_lock_init(&rdev->beacon_registrations_lock);
spin_lock_init(&rdev->bss_lock);
INIT_LIST_HEAD(&rdev->bss_list);
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
@@ -370,6 +373,8 @@ 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);
@@ -687,7 +692,7 @@ void wiphy_unregister(struct wiphy *wiphy)
flush_work(&rdev->event_work);
if (rdev->wowlan && rdev->ops->set_wakeup)
- rdev->ops->set_wakeup(&rdev->wiphy, false);
+ rdev_set_wakeup(rdev, false);
cfg80211_rdev_free_wowlan(rdev);
}
EXPORT_SYMBOL(wiphy_unregister);
@@ -695,10 +700,15 @@ EXPORT_SYMBOL(wiphy_unregister);
void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
{
struct cfg80211_internal_bss *scan, *tmp;
+ struct cfg80211_beacon_registration *reg, *treg;
rfkill_destroy(rdev->rfkill);
mutex_destroy(&rdev->mtx);
mutex_destroy(&rdev->devlist_mtx);
mutex_destroy(&rdev->sched_scan_mtx);
+ list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
+ list_del(&reg->list);
+ kfree(reg);
+ }
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
cfg80211_put_bss(&scan->pub);
kfree(rdev);
@@ -770,7 +780,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
case NL80211_IFTYPE_P2P_DEVICE:
if (!wdev->p2p_started)
break;
- rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
+ rdev_stop_p2p_device(rdev, wdev);
wdev->p2p_started = false;
rdev->opencount--;
break;
@@ -961,9 +971,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
if ((wdev->iftype == NL80211_IFTYPE_STATION ||
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
rdev->ops->set_power_mgmt)
- if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
- wdev->ps,
- wdev->ps_timeout)) {
+ if (rdev_set_power_mgmt(rdev, dev, wdev->ps,
+ wdev->ps_timeout)) {
/* assume this means it's off */
wdev->ps = false;
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a343be4a52bd..3563097169cb 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -55,7 +55,8 @@ struct cfg80211_registered_device {
int opencount; /* also protected by devlist_mtx */
wait_queue_head_t dev_wait;
- u32 ap_beacons_nlportid;
+ struct list_head beacon_registrations;
+ spinlock_t beacon_registrations_lock;
/* protected by RTNL only */
int num_running_ifaces;
@@ -137,8 +138,6 @@ struct cfg80211_internal_bss {
unsigned long ts;
struct kref ref;
atomic_t hold;
- bool beacon_ies_allocated;
- bool proberesp_ies_allocated;
/* must be last because of priv member */
struct cfg80211_bss pub;
@@ -260,6 +259,10 @@ enum cfg80211_chan_mode {
CHAN_MODE_EXCLUSIVE,
};
+struct cfg80211_beacon_registration {
+ struct list_head list;
+ u32 nlportid;
+};
/* free object */
extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
@@ -304,9 +307,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
const struct mesh_config *conf);
int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev);
-int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, int freq,
- enum nl80211_channel_type channel_type);
+int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef);
/* AP */
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
@@ -320,13 +323,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
- const u8 *key, int key_len, int key_idx);
+ const u8 *key, int key_len, int key_idx,
+ const u8 *sae_data, int sae_data_len);
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type, const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
- const u8 *key, int key_len, int key_idx);
+ const u8 *key, int key_len, int key_idx,
+ const u8 *sae_data, int sae_data_len);
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ieee80211_channel *chan,
@@ -371,10 +376,8 @@ 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,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie);
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie);
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
const struct ieee80211_ht_cap *ht_capa_mask);
@@ -465,11 +468,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
struct ieee80211_channel **chan,
enum cfg80211_chan_mode *chanmode);
-struct ieee80211_channel *
-rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type channel_type);
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type chantype);
+ struct cfg80211_chan_def *chandef);
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index 7eecdf40cf80..48c48ffafa1d 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -2,6 +2,7 @@
#include <net/cfg80211.h>
#include "core.h"
#include "ethtool.h"
+#include "rdev-ops.h"
static void cfg80211_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -47,9 +48,8 @@ static void cfg80211_get_ringparam(struct net_device *dev,
memset(rp, 0, sizeof(*rp));
if (rdev->ops->get_ringparam)
- rdev->ops->get_ringparam(wdev->wiphy,
- &rp->tx_pending, &rp->tx_max_pending,
- &rp->rx_pending, &rp->rx_max_pending);
+ rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending,
+ &rp->rx_pending, &rp->rx_max_pending);
}
static int cfg80211_set_ringparam(struct net_device *dev,
@@ -62,8 +62,7 @@ static int cfg80211_set_ringparam(struct net_device *dev,
return -EINVAL;
if (rdev->ops->set_ringparam)
- return rdev->ops->set_ringparam(wdev->wiphy,
- rp->tx_pending, rp->rx_pending);
+ return rdev_set_ringparam(rdev, rp->tx_pending, rp->rx_pending);
return -ENOTSUPP;
}
@@ -73,7 +72,7 @@ static int cfg80211_get_sset_count(struct net_device *dev, int sset)
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
if (rdev->ops->get_et_sset_count)
- return rdev->ops->get_et_sset_count(wdev->wiphy, dev, sset);
+ return rdev_get_et_sset_count(rdev, dev, sset);
return -EOPNOTSUPP;
}
@@ -83,7 +82,7 @@ static void cfg80211_get_stats(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
if (rdev->ops->get_et_stats)
- rdev->ops->get_et_stats(wdev->wiphy, dev, stats, data);
+ rdev_get_et_stats(rdev, dev, stats, data);
}
static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
@@ -91,7 +90,7 @@ static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
if (rdev->ops->get_et_strings)
- rdev->ops->get_et_strings(wdev->wiphy, dev, sset, data);
+ rdev_get_et_strings(rdev, dev, sset, data);
}
const struct ethtool_ops cfg80211_ethtool_ops = {
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index ca5672f6ee2f..9b9551e4a6f9 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -11,6 +11,7 @@
#include <net/cfg80211.h>
#include "wext-compat.h"
#include "nl80211.h"
+#include "rdev-ops.h"
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
@@ -61,6 +62,8 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
struct cfg80211_event *ev;
unsigned long flags;
+ trace_cfg80211_ibss_joined(dev, bssid);
+
CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
ev = kzalloc(sizeof(*ev), gfp);
@@ -97,9 +100,9 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
* 11a for maximum compatibility.
*/
struct ieee80211_supported_band *sband =
- rdev->wiphy.bands[params->channel->band];
+ rdev->wiphy.bands[params->chandef.chan->band];
int j;
- u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
+ u32 flag = params->chandef.chan->band == IEEE80211_BAND_5GHZ ?
IEEE80211_RATE_MANDATORY_A :
IEEE80211_RATE_MANDATORY_B;
@@ -115,11 +118,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
wdev->ibss_fixed = params->channel_fixed;
#ifdef CONFIG_CFG80211_WEXT
- wdev->wext.ibss.channel = params->channel;
+ wdev->wext.ibss.chandef = params->chandef;
#endif
wdev->sme_state = CFG80211_SME_CONNECTING;
- err = cfg80211_can_use_chan(rdev, wdev, params->channel,
+ err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan,
params->channel_fixed
? CHAN_MODE_SHARED
: CHAN_MODE_EXCLUSIVE);
@@ -128,7 +131,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
return err;
}
- err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
+ err = rdev_join_ibss(rdev, dev, params);
if (err) {
wdev->connect_keys = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
@@ -175,7 +178,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
*/
if (rdev->ops->del_key)
for (i = 0; i < 6; i++)
- rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
+ rdev_del_key(rdev, dev, i, false, NULL);
if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss);
@@ -211,7 +214,7 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
if (!wdev->ssid_len)
return -ENOLINK;
- err = rdev->ops->leave_ibss(&rdev->wiphy, dev);
+ err = rdev_leave_ibss(rdev, dev);
if (err)
return err;
@@ -248,7 +251,9 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
wdev->wext.ibss.beacon_interval = 100;
/* try to find an IBSS channel if none requested ... */
- if (!wdev->wext.ibss.channel) {
+ if (!wdev->wext.ibss.chandef.chan) {
+ wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
@@ -263,15 +268,15 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
continue;
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
- wdev->wext.ibss.channel = chan;
+ wdev->wext.ibss.chandef.chan = chan;
break;
}
- if (wdev->wext.ibss.channel)
+ if (wdev->wext.ibss.chandef.chan)
break;
}
- if (!wdev->wext.ibss.channel)
+ if (!wdev->wext.ibss.chandef.chan)
return -EINVAL;
}
@@ -333,7 +338,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
return -EINVAL;
}
- if (wdev->wext.ibss.channel == chan)
+ if (wdev->wext.ibss.chandef.chan == chan)
return 0;
wdev_lock(wdev);
@@ -346,7 +351,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
return err;
if (chan) {
- wdev->wext.ibss.channel = chan;
+ wdev->wext.ibss.chandef.chan = chan;
+ wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
wdev->wext.ibss.channel_fixed = true;
} else {
/* cfg80211_ibss_wext_join will pick one if needed */
@@ -376,8 +382,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
wdev_lock(wdev);
if (wdev->current_bss)
chan = wdev->current_bss->pub.channel;
- else if (wdev->wext.ibss.channel)
- chan = wdev->wext.ibss.channel;
+ else if (wdev->wext.ibss.chandef.chan)
+ chan = wdev->wext.ibss.chandef.chan;
wdev_unlock(wdev);
if (chan) {
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index c384e77ff77a..f9d6ce5cfabb 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -3,6 +3,7 @@
#include <net/cfg80211.h>
#include "nl80211.h"
#include "core.h"
+#include "rdev-ops.h"
/* Default values, timeouts in ms */
#define MESH_TTL 31
@@ -72,8 +73,6 @@ const struct mesh_config default_mesh_config = {
const struct mesh_setup default_mesh_setup = {
/* cfg80211_join_mesh() will pick a channel if needed */
- .channel = NULL,
- .channel_type = NL80211_CHAN_NO_HT,
.sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
.path_metric = IEEE80211_PATH_METRIC_AIRTIME,
@@ -110,13 +109,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
if (!rdev->ops->join_mesh)
return -EOPNOTSUPP;
- if (!setup->channel) {
+ if (!setup->chandef.chan) {
/* if no channel explicitly given, use preset channel */
- setup->channel = wdev->preset_chan;
- setup->channel_type = wdev->preset_chantype;
+ setup->chandef = wdev->preset_chandef;
}
- if (!setup->channel) {
+ if (!setup->chandef.chan) {
/* if we don't have that either, use the first usable channel */
enum ieee80211_band band;
@@ -136,35 +134,35 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
IEEE80211_CHAN_DISABLED |
IEEE80211_CHAN_RADAR))
continue;
- setup->channel = chan;
+ setup->chandef.chan = chan;
break;
}
- if (setup->channel)
+ if (setup->chandef.chan)
break;
}
/* no usable channel ... */
- if (!setup->channel)
+ if (!setup->chandef.chan)
return -EINVAL;
- setup->channel_type = NL80211_CHAN_NO_HT;
+ setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ setup->chandef.center_freq1 = setup->chandef.chan->center_freq;
}
- if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel,
- setup->channel_type))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
return -EINVAL;
- err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
+ err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan,
CHAN_MODE_SHARED);
if (err)
return err;
- err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
+ err = rdev_join_mesh(rdev, dev, conf, setup);
if (!err) {
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
wdev->mesh_id_len = setup->mesh_id_len;
- wdev->channel = setup->channel;
+ wdev->channel = setup->chandef.chan;
}
return err;
@@ -187,20 +185,12 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
return err;
}
-int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, int freq,
- enum nl80211_channel_type channel_type)
+int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef)
{
- struct ieee80211_channel *channel;
int err;
- channel = rdev_freq_to_chan(rdev, freq, channel_type);
- if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
- channel,
- channel_type)) {
- return -EINVAL;
- }
-
/*
* Workaround for libertas (only!), it puts the interface
* into mesh mode but doesn't implement join_mesh. Instead,
@@ -209,22 +199,21 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
* compatible with 802.11 mesh.
*/
if (rdev->ops->libertas_set_mesh_channel) {
- if (channel_type != NL80211_CHAN_NO_HT)
+ if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
return -EINVAL;
if (!netif_running(wdev->netdev))
return -ENETDOWN;
- err = cfg80211_can_use_chan(rdev, wdev, channel,
+ err = cfg80211_can_use_chan(rdev, wdev, chandef->chan,
CHAN_MODE_SHARED);
if (err)
return err;
- err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
- wdev->netdev,
- channel);
+ err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
+ chandef->chan);
if (!err)
- wdev->channel = channel;
+ wdev->channel = chandef->chan;
return err;
}
@@ -232,8 +221,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
if (wdev->mesh_id_len)
return -EBUSY;
- wdev->preset_chan = channel;
- wdev->preset_chantype = channel_type;
+ wdev->preset_chandef = *chandef;
return 0;
}
@@ -242,6 +230,7 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ trace_cfg80211_notify_new_peer_candidate(dev, macaddr);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
return;
@@ -267,7 +256,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
if (!wdev->mesh_id_len)
return -ENOTCONN;
- err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
+ err = rdev_leave_mesh(rdev, dev);
if (!err) {
wdev->mesh_id_len = 0;
wdev->channel = NULL;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 904a7f368325..5e8123ee63fd 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -15,6 +15,8 @@
#include <net/iw_handler.h>
#include "core.h"
#include "nl80211.h"
+#include "rdev-ops.h"
+
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
{
@@ -22,6 +24,7 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_send_rx_auth(dev);
wdev_lock(wdev);
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
@@ -42,6 +45,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
u8 *ie = mgmt->u.assoc_resp.variable;
int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+ trace_cfg80211_send_rx_assoc(dev, bss);
wdev_lock(wdev);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -98,6 +102,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
const u8 *bssid = mgmt->bssid;
bool was_current = false;
+ trace___cfg80211_send_deauth(dev);
ASSERT_WDEV_LOCK(wdev);
if (wdev->current_bss &&
@@ -147,6 +152,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
u16 reason_code;
bool from_ap;
+ trace___cfg80211_send_disassoc(dev);
ASSERT_WDEV_LOCK(wdev);
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -188,6 +194,7 @@ void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_send_unprot_deauth(dev);
nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
}
EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
@@ -199,6 +206,7 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_send_unprot_disassoc(dev);
nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
}
EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
@@ -209,6 +217,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_send_auth_timeout(dev, addr);
wdev_lock(wdev);
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
@@ -227,6 +236,7 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_send_assoc_timeout(dev, addr);
wdev_lock(wdev);
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
@@ -261,6 +271,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
}
#endif
+ trace_cfg80211_michael_mic_failure(dev, addr, key_type, key_id, tsc);
nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
}
EXPORT_SYMBOL(cfg80211_michael_mic_failure);
@@ -273,7 +284,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
- const u8 *key, int key_len, int key_idx)
+ const u8 *key, int key_len, int key_idx,
+ const u8 *sae_data, int sae_data_len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_auth_request req;
@@ -293,6 +305,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
req.ie = ie;
req.ie_len = ie_len;
+ req.sae_data = sae_data;
+ req.sae_data_len = sae_data_len;
req.auth_type = auth_type;
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
@@ -307,7 +321,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
if (err)
goto out;
- err = rdev->ops->auth(&rdev->wiphy, dev, &req);
+ err = rdev_auth(rdev, dev, &req);
out:
cfg80211_put_bss(req.bss);
@@ -319,7 +333,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
enum nl80211_auth_type auth_type, const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
- const u8 *key, int key_len, int key_idx)
+ const u8 *key, int key_len, int key_idx,
+ const u8 *sae_data, int sae_data_len)
{
int err;
@@ -327,7 +342,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
- key, key_len, key_idx);
+ key, key_len, key_idx,
+ sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr);
mutex_unlock(&rdev->devlist_mtx);
@@ -410,7 +426,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
if (err)
goto out;
- err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
+ err = rdev_assoc(rdev, dev, &req);
out:
if (err) {
@@ -466,7 +482,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
return 0;
- return rdev->ops->deauth(&rdev->wiphy, dev, &req);
+ return rdev_deauth(rdev, dev, &req);
}
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
@@ -511,7 +527,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
else
return -ENOTCONN;
- return rdev->ops->disassoc(&rdev->wiphy, dev, &req);
+ return rdev_disassoc(rdev, dev, &req);
}
int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
@@ -552,7 +568,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
req.bssid = bssid;
- rdev->ops->deauth(&rdev->wiphy, dev, &req);
+ rdev_deauth(rdev, dev, &req);
if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss);
@@ -563,27 +579,25 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
- duration, gfp);
+ trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
+ nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp);
}
EXPORT_SYMBOL(cfg80211_ready_on_channel);
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
gfp_t gfp)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
- channel_type, gfp);
+ trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
+ nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp);
}
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
@@ -593,6 +607,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_new_sta(dev, mac_addr, sinfo);
nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
}
EXPORT_SYMBOL(cfg80211_new_sta);
@@ -602,6 +617,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_del_sta(dev, mac_addr);
nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
}
EXPORT_SYMBOL(cfg80211_del_sta);
@@ -682,7 +698,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
list_add(&nreg->list, &wdev->mgmt_registrations);
if (rdev->ops->mgmt_frame_register)
- rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
+ rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
out:
spin_unlock_bh(&wdev->mgmt_registrations_lock);
@@ -705,8 +721,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
if (rdev->ops->mgmt_frame_register) {
u16 frame_type = le16_to_cpu(reg->frame_type);
- rdev->ops->mgmt_frame_register(wiphy, wdev,
- frame_type, false);
+ rdev_mgmt_frame_register(rdev, wdev,
+ frame_type, false);
}
list_del(&reg->list);
@@ -736,10 +752,8 @@ 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,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie)
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie)
{
const struct ieee80211_mgmt *mgmt;
u16 stype;
@@ -832,10 +846,9 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
return -EINVAL;
/* Transmit the Action frame as requested by user space */
- return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
- channel_type, channel_type_valid,
- wait, buf, len, no_cck, dont_wait_for_ack,
- cookie);
+ return rdev_mgmt_tx(rdev, wdev, chan, offchan,
+ wait, buf, len, no_cck, dont_wait_for_ack,
+ cookie);
}
bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
@@ -854,10 +867,13 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
u16 stype;
+ trace_cfg80211_rx_mgmt(wdev, freq, sig_mbm);
stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
- if (!(stypes->rx & BIT(stype)))
+ if (!(stypes->rx & BIT(stype))) {
+ trace_cfg80211_return_bool(false);
return false;
+ }
data = buf + ieee80211_hdrlen(mgmt->frame_control);
data_len = len - ieee80211_hdrlen(mgmt->frame_control);
@@ -888,6 +904,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
spin_unlock_bh(&wdev->mgmt_registrations_lock);
+ trace_cfg80211_return_bool(result);
return result;
}
EXPORT_SYMBOL(cfg80211_rx_mgmt);
@@ -898,6 +915,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
+
/* Indicate TX status of the Action frame to user space */
nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
}
@@ -911,6 +930,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+
/* Indicate roaming trigger event to user space */
nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
}
@@ -923,6 +944,8 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
+
/* Indicate roaming trigger event to user space */
nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
}
@@ -948,6 +971,7 @@ void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_gtk_rekey_notify(dev, bssid);
nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
}
EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
@@ -959,17 +983,19 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
}
EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
-void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
- enum nl80211_channel_type type)
+void cfg80211_ch_switch_notify(struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- struct ieee80211_channel *chan;
+
+ trace_cfg80211_ch_switch_notify(dev, chandef);
wdev_lock(wdev);
@@ -977,12 +1003,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
wdev->iftype != NL80211_IFTYPE_P2P_GO))
goto out;
- chan = rdev_freq_to_chan(rdev, freq, type);
- if (WARN_ON(!chan))
- goto out;
-
- wdev->channel = chan;
- nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
+ wdev->channel = chandef->chan;
+ nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
out:
wdev_unlock(wdev);
return;
@@ -993,12 +1015,18 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev,
const u8 *addr, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ bool ret;
+
+ trace_cfg80211_rx_spurious_frame(dev, addr);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
- wdev->iftype != NL80211_IFTYPE_P2P_GO))
+ wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
+ trace_cfg80211_return_bool(false);
return false;
-
- return nl80211_unexpected_frame(dev, addr, gfp);
+ }
+ ret = nl80211_unexpected_frame(dev, addr, gfp);
+ trace_cfg80211_return_bool(ret);
+ return ret;
}
EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
@@ -1006,12 +1034,18 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
const u8 *addr, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ bool ret;
+
+ trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
- wdev->iftype != NL80211_IFTYPE_AP_VLAN))
+ wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
+ trace_cfg80211_return_bool(false);
return false;
-
- return nl80211_unexpected_4addr_frame(dev, addr, gfp);
+ }
+ ret = nl80211_unexpected_4addr_frame(dev, addr, gfp);
+ trace_cfg80211_return_bool(ret);
+ return ret;
}
EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0418a6d5c1a6..f45706adaf34 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -22,8 +22,8 @@
#include "core.h"
#include "nl80211.h"
#include "reg.h"
+#include "rdev-ops.h"
-static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type);
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
struct genl_info *info,
struct cfg80211_crypto_settings *settings,
@@ -223,8 +223,13 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
.len = 20-1 },
[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
+
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
+ [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
+ [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
+ [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
+
[NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
@@ -355,6 +360,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
+ [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+ [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+ [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
+ [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
+ [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
};
/* policy for the key attributes */
@@ -690,7 +700,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
static struct cfg80211_cached_keys *
nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
- struct nlattr *keys)
+ struct nlattr *keys, bool *no_ht)
{
struct key_parse parse;
struct nlattr *key;
@@ -733,6 +743,12 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
result->params[parse.idx].key_len = parse.p.key_len;
result->params[parse.idx].key = result->data[parse.idx];
memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
+
+ if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) {
+ if (no_ht)
+ *no_ht = true;
+ }
}
return result;
@@ -943,7 +959,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
u32 tx_ant = 0, rx_ant = 0;
int res;
- res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant);
+ res = rdev_get_antenna(dev, &tx_ant, &rx_ant);
if (!res) {
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX,
tx_ant) ||
@@ -1101,6 +1117,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
goto nla_put_failure;
}
CMD(start_p2p_device, START_P2P_DEVICE);
+ CMD(set_mcast_rate, SET_MCAST_RATE);
#ifdef CONFIG_NL80211_TESTMODE
CMD(testmode_cmd, TESTMODE);
@@ -1350,51 +1367,83 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
wdev->iftype == NL80211_IFTYPE_P2P_GO;
}
-static bool nl80211_valid_channel_type(struct genl_info *info,
- enum nl80211_channel_type *channel_type)
+static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
+ struct genl_info *info,
+ struct cfg80211_chan_def *chandef)
{
- enum nl80211_channel_type tmp;
+ u32 control_freq;
- if (!info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
- return false;
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
- tmp = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (tmp != NL80211_CHAN_NO_HT &&
- tmp != NL80211_CHAN_HT20 &&
- tmp != NL80211_CHAN_HT40PLUS &&
- tmp != NL80211_CHAN_HT40MINUS)
- return false;
+ control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- if (channel_type)
- *channel_type = tmp;
+ chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = control_freq;
+ chandef->center_freq2 = 0;
- return true;
+ /* Primary channel not allowed */
+ if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ enum nl80211_channel_type chantype;
+
+ chantype = nla_get_u32(
+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+
+ switch (chantype) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
+ case NL80211_CHAN_HT40PLUS:
+ case NL80211_CHAN_HT40MINUS:
+ cfg80211_chandef_create(chandef, chandef->chan,
+ chantype);
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
+ chandef->width =
+ nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
+ if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
+ chandef->center_freq1 =
+ nla_get_u32(
+ info->attrs[NL80211_ATTR_CENTER_FREQ1]);
+ if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
+ chandef->center_freq2 =
+ nla_get_u32(
+ info->attrs[NL80211_ATTR_CENTER_FREQ2]);
+ }
+
+ if (!cfg80211_chandef_valid(chandef))
+ return -EINVAL;
+
+ if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
+ IEEE80211_CHAN_DISABLED))
+ return -EINVAL;
+
+ return 0;
}
static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct genl_info *info)
{
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq;
+ struct cfg80211_chan_def chandef;
int result;
enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
if (wdev)
iftype = wdev->iftype;
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
- return -EINVAL;
-
if (!nl80211_can_set_dev_channel(wdev))
return -EOPNOTSUPP;
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+ result = nl80211_parse_chandef(rdev, info, &chandef);
+ if (result)
+ return result;
mutex_lock(&rdev->devlist_mtx);
switch (iftype) {
@@ -1404,22 +1453,18 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
result = -EBUSY;
break;
}
- channel = rdev_freq_to_chan(rdev, freq, channel_type);
- if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
- channel,
- channel_type)) {
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) {
result = -EINVAL;
break;
}
- wdev->preset_chan = channel;
- wdev->preset_chantype = channel_type;
+ wdev->preset_chandef = chandef;
result = 0;
break;
case NL80211_IFTYPE_MESH_POINT:
- result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type);
+ result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
break;
case NL80211_IFTYPE_MONITOR:
- result = cfg80211_set_monitor_channel(rdev, freq, channel_type);
+ result = cfg80211_set_monitor_channel(rdev, &chandef);
break;
default:
result = -EINVAL;
@@ -1457,7 +1502,7 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
- return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid);
+ return rdev_set_wds_peer(rdev, dev, bssid);
}
@@ -1507,10 +1552,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = 0;
mutex_lock(&rdev->mtx);
- } else if (nl80211_can_set_dev_channel(netdev->ieee80211_ptr))
+ } else
wdev = netdev->ieee80211_ptr;
- else
- wdev = NULL;
/*
* end workaround code, by now the rdev is available
@@ -1562,24 +1605,29 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (result)
goto bad_res;
- result = rdev->ops->set_txq_params(&rdev->wiphy,
- netdev,
- &txq_params);
+ result = rdev_set_txq_params(rdev, netdev,
+ &txq_params);
if (result)
goto bad_res;
}
}
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- result = __nl80211_set_channel(rdev, wdev, info);
+ result = __nl80211_set_channel(rdev,
+ nl80211_can_set_dev_channel(wdev) ? wdev : NULL,
+ info);
if (result)
goto bad_res;
}
if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
+ struct wireless_dev *txp_wdev = wdev;
enum nl80211_tx_power_setting type;
int idx, mbm = 0;
+ if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
+ txp_wdev = NULL;
+
if (!rdev->ops->set_tx_power) {
result = -EOPNOTSUPP;
goto bad_res;
@@ -1599,7 +1647,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
mbm = nla_get_u32(info->attrs[idx]);
}
- result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
+ result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
if (result)
goto bad_res;
}
@@ -1628,7 +1676,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
- result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ result = rdev_set_antenna(rdev, tx_ant, rx_ant);
if (result)
goto bad_res;
}
@@ -1713,7 +1761,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
rdev->wiphy.coverage_class = coverage_class;
- result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
+ result = rdev_set_wiphy_params(rdev, changed);
if (result) {
rdev->wiphy.retry_short = old_retry_short;
rdev->wiphy.retry_long = old_retry_long;
@@ -1736,6 +1784,35 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
}
+static int nl80211_send_chandef(struct sk_buff *msg,
+ struct cfg80211_chan_def *chandef)
+{
+ WARN_ON(!cfg80211_chandef_valid(chandef));
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ chandef->chan->center_freq))
+ return -ENOBUFS;
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+ cfg80211_get_chandef_type(chandef)))
+ return -ENOBUFS;
+ break;
+ default:
+ break;
+ }
+ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
+ return -ENOBUFS;
+ if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
+ return -ENOBUFS;
+ if (chandef->center_freq2 &&
+ nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
+ return -ENOBUFS;
+ return 0;
+}
+
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
@@ -1762,16 +1839,18 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
goto nla_put_failure;
if (rdev->ops->get_channel) {
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type;
-
- chan = rdev->ops->get_channel(&rdev->wiphy, wdev,
- &channel_type);
- if (chan &&
- (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
- chan->center_freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- channel_type)))
+ int ret;
+ struct cfg80211_chan_def chandef;
+
+ ret = rdev_get_channel(rdev, wdev, &chandef);
+ if (ret == 0) {
+ if (nl80211_send_chandef(msg, &chandef))
+ goto nla_put_failure;
+ }
+ }
+
+ if (wdev->ssid_len) {
+ if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
goto nla_put_failure;
}
@@ -2014,9 +2093,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
&flags);
- wdev = rdev->ops->add_virtual_intf(&rdev->wiphy,
- nla_data(info->attrs[NL80211_ATTR_IFNAME]),
- type, err ? NULL : &flags, &params);
+ wdev = rdev_add_virtual_intf(rdev,
+ nla_data(info->attrs[NL80211_ATTR_IFNAME]),
+ type, err ? NULL : &flags, &params);
if (IS_ERR(wdev)) {
nlmsg_free(msg);
return PTR_ERR(wdev);
@@ -2083,7 +2162,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
if (!wdev->netdev)
info->user_ptr[1] = NULL;
- return rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
+ return rdev_del_virtual_intf(rdev, wdev);
}
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -2100,7 +2179,7 @@ static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
- return rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map);
+ return rdev_set_noack_map(rdev, dev, noack_map);
}
struct get_key_cookie {
@@ -2210,8 +2289,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
return -ENOENT;
- err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
- mac_addr, &cookie, get_key_callback);
+ err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
+ get_key_callback);
if (err)
goto free_msg;
@@ -2259,7 +2338,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
- err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
+ err = rdev_set_default_key(rdev, dev, key.idx,
key.def_uni, key.def_multi);
if (err)
@@ -2283,8 +2362,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
- err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
- dev, key.idx);
+ err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
if (err)
goto out;
@@ -2340,9 +2418,9 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
wdev_lock(dev->ieee80211_ptr);
err = nl80211_key_allowed(dev->ieee80211_ptr);
if (!err)
- err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
- key.type == NL80211_KEYTYPE_PAIRWISE,
- mac_addr, &key.p);
+ err = rdev_add_key(rdev, dev, key.idx,
+ key.type == NL80211_KEYTYPE_PAIRWISE,
+ mac_addr, &key.p);
wdev_unlock(dev->ieee80211_ptr);
return err;
@@ -2386,9 +2464,9 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
err = -ENOENT;
if (!err)
- err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
- key.type == NL80211_KEYTYPE_PAIRWISE,
- mac_addr);
+ err = rdev_del_key(rdev, dev, key.idx,
+ key.type == NL80211_KEYTYPE_PAIRWISE,
+ mac_addr);
#ifdef CONFIG_CFG80211_WEXT
if (!err) {
@@ -2476,11 +2554,10 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
wdev->iftype != NL80211_IFTYPE_P2P_GO)
continue;
- if (!wdev->preset_chan)
+ if (!wdev->preset_chandef.chan)
continue;
- params->channel = wdev->preset_chan;
- params->channel_type = wdev->preset_chantype;
+ params->chandef = wdev->preset_chandef;
ret = true;
break;
}
@@ -2490,6 +2567,30 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
return ret;
}
+static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
+ enum nl80211_auth_type auth_type,
+ enum nl80211_commands cmd)
+{
+ if (auth_type > NL80211_AUTHTYPE_MAX)
+ return false;
+
+ switch (cmd) {
+ case NL80211_CMD_AUTHENTICATE:
+ if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
+ auth_type == NL80211_AUTHTYPE_SAE)
+ return false;
+ return true;
+ case NL80211_CMD_CONNECT:
+ case NL80211_CMD_START_AP:
+ /* SAE not supported yet */
+ if (auth_type == NL80211_AUTHTYPE_SAE)
+ return false;
+ return true;
+ default:
+ return false;
+ }
+}
+
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2559,7 +2660,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
params.auth_type = nla_get_u32(
info->attrs[NL80211_ATTR_AUTH_TYPE]);
- if (!nl80211_valid_auth_type(params.auth_type))
+ if (!nl80211_valid_auth_type(rdev, params.auth_type,
+ NL80211_CMD_START_AP))
return -EINVAL;
} else
params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
@@ -2576,43 +2678,59 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
}
- if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
+ if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
return -EINVAL;
+ params.p2p_ctwindow =
+ nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
+ if (params.p2p_ctwindow > 127)
+ return -EINVAL;
+ if (params.p2p_ctwindow != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
+ u8 tmp;
- params.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- channel_type);
- if (!params.channel)
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
return -EINVAL;
- params.channel_type = channel_type;
- } else if (wdev->preset_chan) {
- params.channel = wdev->preset_chan;
- params.channel_type = wdev->preset_chantype;
+ tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
+ if (tmp > 1)
+ return -EINVAL;
+ params.p2p_opp_ps = tmp;
+ if (params.p2p_opp_ps != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ err = nl80211_parse_chandef(rdev, info, &params.chandef);
+ if (err)
+ return err;
+ } else if (wdev->preset_chandef.chan) {
+ params.chandef = wdev->preset_chandef;
} else if (!nl80211_get_ap_channel(rdev, &params))
return -EINVAL;
- if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
- params.channel_type))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_can_use_chan(rdev, wdev, params.channel,
+ err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan,
CHAN_MODE_SHARED);
mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
- err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
+ err = rdev_start_ap(rdev, dev, &params);
if (!err) {
- wdev->preset_chan = params.channel;
- wdev->preset_chantype = params.channel_type;
+ wdev->preset_chandef = params.chandef;
wdev->beacon_interval = params.beacon_interval;
- wdev->channel = params.channel;
+ wdev->channel = params.chandef.chan;
+ wdev->ssid_len = params.ssid_len;
+ memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
}
return err;
}
@@ -2639,7 +2757,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- return rdev->ops->change_beacon(&rdev->wiphy, dev, &params);
+ return rdev_change_beacon(rdev, dev, &params);
}
static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@ -2744,29 +2862,52 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
rate = nla_nest_start(msg, attr);
if (!rate)
- goto nla_put_failure;
+ return false;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info);
/* report 16-bit bitrate only if we can */
bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
- if ((bitrate > 0 &&
- nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) ||
- (bitrate_compat > 0 &&
- nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) ||
- ((info->flags & RATE_INFO_FLAGS_MCS) &&
- nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) ||
- ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
- nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) ||
- ((info->flags & RATE_INFO_FLAGS_SHORT_GI) &&
- nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)))
- goto nla_put_failure;
+ if (bitrate > 0 &&
+ nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
+ return false;
+ if (bitrate_compat > 0 &&
+ nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
+ return false;
+
+ if (info->flags & RATE_INFO_FLAGS_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
+ return false;
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ }
nla_nest_end(msg, rate);
return true;
-
-nla_put_failure:
- return false;
}
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
@@ -2923,8 +3064,8 @@ static int nl80211_dump_station(struct sk_buff *skb,
while (1) {
memset(&sinfo, 0, sizeof(sinfo));
- err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
- mac_addr, &sinfo);
+ err = rdev_dump_station(dev, netdev, sta_idx,
+ mac_addr, &sinfo);
if (err == -ENOENT)
break;
if (err)
@@ -2969,7 +3110,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->get_station)
return -EOPNOTSUPP;
- err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
+ err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
if (err)
return err;
@@ -3146,7 +3287,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
/* be aware of params.vlan when changing code here */
- err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
+ err = rdev_change_station(rdev, dev, mac_addr, &params);
if (params.vlan)
dev_put(params.vlan);
@@ -3198,6 +3339,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
params.ht_capa =
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+ if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ params.vht_capa =
+ nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+
if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
@@ -3275,7 +3420,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
/* be aware of params.vlan when changing code here */
- err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
+ err = rdev_add_station(rdev, dev, mac_addr, &params);
if (params.vlan)
dev_put(params.vlan);
@@ -3300,7 +3445,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->del_station)
return -EOPNOTSUPP;
- return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
+ return rdev_del_station(rdev, dev, mac_addr);
}
static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
@@ -3382,8 +3527,8 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
}
while (1) {
- err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
- dst, next_hop, &pinfo);
+ err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop,
+ &pinfo);
if (err == -ENOENT)
break;
if (err)
@@ -3430,7 +3575,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
return -EOPNOTSUPP;
- err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
+ err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
if (err)
return err;
@@ -3469,7 +3614,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
return -EOPNOTSUPP;
- return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
+ return rdev_change_mpath(rdev, dev, dst, next_hop);
}
static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -3494,7 +3639,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
return -EOPNOTSUPP;
- return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
+ return rdev_add_mpath(rdev, dev, dst, next_hop);
}
static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
@@ -3509,7 +3654,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->del_mpath)
return -EOPNOTSUPP;
- return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
+ return rdev_del_mpath(rdev, dev, dst);
}
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
@@ -3525,6 +3670,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
params.use_short_slot_time = -1;
params.ap_isolate = -1;
params.ht_opmode = -1;
+ params.p2p_ctwindow = -1;
+ params.p2p_opp_ps = -1;
if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
params.use_cts_prot =
@@ -3547,6 +3694,32 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
params.ht_opmode =
nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
+ if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
+ params.p2p_ctwindow =
+ nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
+ if (params.p2p_ctwindow < 0)
+ return -EINVAL;
+ if (params.p2p_ctwindow != 0 &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
+ u8 tmp;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
+ tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
+ if (tmp > 1)
+ return -EINVAL;
+ params.p2p_opp_ps = tmp;
+ if (params.p2p_opp_ps &&
+ !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
+ return -EINVAL;
+ }
+
if (!rdev->ops->change_bss)
return -EOPNOTSUPP;
@@ -3554,7 +3727,7 @@ 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->ops->change_bss(&rdev->wiphy, dev, &params);
+ return rdev_change_bss(rdev, dev, &params);
}
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -3668,8 +3841,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
if (!wdev->mesh_id_len)
memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
else
- err = rdev->ops->get_mesh_config(&rdev->wiphy, dev,
- &cur_params);
+ err = rdev_get_mesh_config(rdev, dev, &cur_params);
wdev_unlock(wdev);
if (err)
@@ -3971,8 +4143,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
err = -ENOLINK;
if (!err)
- err = rdev->ops->update_mesh_config(&rdev->wiphy, dev,
- mask, &cfg);
+ err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
wdev_unlock(wdev);
@@ -4337,14 +4508,27 @@ 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))) {
+ err = -EOPNOTSUPP;
+ goto out_free;
+ }
+ }
+
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
+ request->scan_start = jiffies;
rdev->scan_req = request;
- err = rdev->ops->scan(&rdev->wiphy, request);
+ err = rdev_scan(rdev, request);
if (!err) {
nl80211_send_scan_start(rdev, wdev);
@@ -4568,11 +4752,24 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->ie_len);
}
+ 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))) {
+ err = -EOPNOTSUPP;
+ goto out_free;
+ }
+ }
+
request->dev = dev;
request->wiphy = &rdev->wiphy;
request->interval = interval;
+ request->scan_start = jiffies;
- err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
+ err = rdev_sched_scan_start(rdev, dev, request);
if (!err) {
rdev->sched_scan_req = request;
nl80211_send_sched_scan(rdev, dev,
@@ -4611,6 +4808,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
struct cfg80211_internal_bss *intbss)
{
struct cfg80211_bss *res = &intbss->pub;
+ const struct cfg80211_bss_ies *ies;
void *hdr;
struct nlattr *bss;
@@ -4631,16 +4829,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
if (!bss)
goto nla_put_failure;
if ((!is_zero_ether_addr(res->bssid) &&
- nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) ||
- (res->information_elements && res->len_information_elements &&
- nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
- res->len_information_elements,
- res->information_elements)) ||
- (res->beacon_ies && res->len_beacon_ies &&
- res->beacon_ies != res->information_elements &&
- nla_put(msg, NL80211_BSS_BEACON_IES,
- res->len_beacon_ies, res->beacon_ies)))
+ nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
+ goto nla_put_failure;
+
+ rcu_read_lock();
+ ies = rcu_dereference(res->ies);
+ if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
+ ies->len, ies->data)) {
+ rcu_read_unlock();
+ goto nla_put_failure;
+ }
+ ies = rcu_dereference(res->beacon_ies);
+ if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
+ ies->len, ies->data)) {
+ rcu_read_unlock();
goto nla_put_failure;
+ }
+ rcu_read_unlock();
+
if (res->tsf &&
nla_put_u64(msg, NL80211_BSS_TSF, res->tsf))
goto nla_put_failure;
@@ -4815,8 +5021,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
while (1) {
struct ieee80211_channel *chan;
- res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
- &survey);
+ res = rdev_dump_survey(dev, netdev, survey_idx, &survey);
if (res == -ENOENT)
break;
if (res)
@@ -4852,11 +5057,6 @@ static int nl80211_dump_survey(struct sk_buff *skb,
return res;
}
-static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
-{
- return auth_type <= NL80211_AUTHTYPE_MAX;
-}
-
static bool nl80211_valid_wpa_versions(u32 wpa_versions)
{
return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
@@ -4868,8 +5068,8 @@ static int nl80211_authenticate(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 ieee80211_channel *chan;
- const u8 *bssid, *ssid, *ie = NULL;
- int err, ssid_len, ie_len = 0;
+ const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
+ int err, ssid_len, ie_len = 0, sae_data_len = 0;
enum nl80211_auth_type auth_type;
struct key_parse key;
bool local_state_change;
@@ -4945,9 +5145,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
}
auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
- if (!nl80211_valid_auth_type(auth_type))
+ if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
+ return -EINVAL;
+
+ if (auth_type == NL80211_AUTHTYPE_SAE &&
+ !info->attrs[NL80211_ATTR_SAE_DATA])
return -EINVAL;
+ if (info->attrs[NL80211_ATTR_SAE_DATA]) {
+ if (auth_type != NL80211_AUTHTYPE_SAE)
+ return -EINVAL;
+ sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
+ sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
+ /* need to include at least Auth Transaction and Status Code */
+ if (sae_data_len < 4)
+ return -EINVAL;
+ }
+
local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
/*
@@ -4959,7 +5173,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
- key.p.key, key.p.key_len, key.idx);
+ key.p.key, key.p.key_len, key.idx,
+ sae_data, sae_data_len);
}
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
@@ -5250,8 +5465,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
- !info->attrs[NL80211_ATTR_SSID] ||
+ if (!info->attrs[NL80211_ATTR_SSID] ||
!nla_len(info->attrs[NL80211_ATTR_SSID]))
return -EINVAL;
@@ -5286,34 +5500,17 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- enum nl80211_channel_type channel_type;
-
- if (!nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- if (channel_type != NL80211_CHAN_NO_HT &&
- !(wiphy->features & NL80211_FEATURE_HT_IBSS))
- return -EINVAL;
-
- ibss.channel_type = channel_type;
- } else {
- ibss.channel_type = NL80211_CHAN_NO_HT;
- }
+ err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
+ if (err)
+ return err;
- ibss.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- ibss.channel_type);
- if (!ibss.channel ||
- ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
return -EINVAL;
- /* Both channels should be able to initiate communication */
- if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
- ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
- !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
- ibss.channel_type))
+ if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
+ return -EINVAL;
+ if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
+ !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
return -EINVAL;
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
@@ -5325,7 +5522,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
int n_rates =
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
struct ieee80211_supported_band *sband =
- wiphy->bands[ibss.channel->band];
+ wiphy->bands[ibss.chandef.chan->band];
err = ieee80211_get_ratemask(sband, rates, n_rates,
&ibss.basic_rates);
@@ -5339,10 +5536,19 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+ bool no_ht = false;
+
connkeys = nl80211_parse_connkeys(rdev,
- info->attrs[NL80211_ATTR_KEYS]);
+ info->attrs[NL80211_ATTR_KEYS],
+ &no_ht);
if (IS_ERR(connkeys))
return PTR_ERR(connkeys);
+
+ if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
+ no_ht) {
+ kfree(connkeys);
+ return -EINVAL;
+ }
}
ibss.control_port =
@@ -5368,6 +5574,36 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
return cfg80211_leave_ibss(rdev, dev, false);
}
+static int nl80211_set_mcast_rate(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];
+ int mcast_rate[IEEE80211_NUM_BANDS];
+ u32 nla_rate;
+ int err;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+ return -EOPNOTSUPP;
+
+ if (!rdev->ops->set_mcast_rate)
+ return -EOPNOTSUPP;
+
+ memset(mcast_rate, 0, sizeof(mcast_rate));
+
+ if (!info->attrs[NL80211_ATTR_MCAST_RATE])
+ return -EINVAL;
+
+ nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
+ if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
+ return -EINVAL;
+
+ err = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate);
+
+ return err;
+}
+
+
#ifdef CONFIG_NL80211_TESTMODE
static struct genl_multicast_group nl80211_testmode_mcgrp = {
.name = "testmode",
@@ -5384,7 +5620,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
err = -EOPNOTSUPP;
if (rdev->ops->testmode_cmd) {
rdev->testmode_info = info;
- err = rdev->ops->testmode_cmd(&rdev->wiphy,
+ err = rdev_testmode_cmd(rdev,
nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
rdev->testmode_info = NULL;
@@ -5466,8 +5702,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
genlmsg_cancel(skb, hdr);
break;
}
- err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
- data, data_len);
+ err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
nla_nest_end(skb, tmdata);
if (err == -ENOBUFS || err == -ENOENT) {
@@ -5596,7 +5831,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
connect.auth_type =
nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
- if (!nl80211_valid_auth_type(connect.auth_type))
+ if (!nl80211_valid_auth_type(rdev, connect.auth_type,
+ NL80211_CMD_CONNECT))
return -EINVAL;
} else
connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
@@ -5642,7 +5878,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
connkeys = nl80211_parse_connkeys(rdev,
- info->attrs[NL80211_ATTR_KEYS]);
+ info->attrs[NL80211_ATTR_KEYS], NULL);
if (IS_ERR(connkeys))
return PTR_ERR(connkeys);
}
@@ -5771,7 +6007,7 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->flush_pmksa)
return -EOPNOTSUPP;
- return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+ return rdev_flush_pmksa(rdev, dev);
}
static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
@@ -5798,10 +6034,10 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
- return rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
- dialog_token, status_code,
- nla_data(info->attrs[NL80211_ATTR_IE]),
- nla_len(info->attrs[NL80211_ATTR_IE]));
+ return rdev_tdls_mgmt(rdev, dev, peer, action_code,
+ dialog_token, status_code,
+ nla_data(info->attrs[NL80211_ATTR_IE]),
+ nla_len(info->attrs[NL80211_ATTR_IE]));
}
static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
@@ -5822,7 +6058,7 @@ static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
- return rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, operation);
+ return rdev_tdls_oper(rdev, dev, peer, operation);
}
static int nl80211_remain_on_channel(struct sk_buff *skb,
@@ -5830,12 +6066,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
- struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chandef;
struct sk_buff *msg;
void *hdr;
u64 cookie;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq, duration;
+ u32 duration;
int err;
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
@@ -5856,14 +6091,9 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
duration > rdev->wiphy.max_remain_on_channel_duration)
return -EINVAL;
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, channel_type);
- if (chan == NULL)
- return -EINVAL;
+ err = nl80211_parse_chandef(rdev, info, &chandef);
+ if (err)
+ return err;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
@@ -5877,8 +6107,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
goto free_msg;
}
- err = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
- channel_type, duration, &cookie);
+ err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
+ duration, &cookie);
if (err)
goto free_msg;
@@ -5912,7 +6142,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
- return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+ return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
}
static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -6055,7 +6285,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
}
}
- return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
+ return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
}
static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
@@ -6097,10 +6327,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- bool channel_type_valid = false;
- u32 freq;
+ struct cfg80211_chan_def chandef;
int err;
void *hdr = NULL;
u64 cookie;
@@ -6110,8 +6337,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
- if (!info->attrs[NL80211_ATTR_FRAME] ||
- !info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ if (!info->attrs[NL80211_ATTR_FRAME])
return -EINVAL;
if (!rdev->ops->mgmt_tx)
@@ -6146,12 +6372,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
}
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- if (!nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
- channel_type_valid = true;
- }
-
offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
@@ -6159,10 +6379,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = rdev_freq_to_chan(rdev, freq, channel_type);
- if (chan == NULL)
- return -EINVAL;
+ err = nl80211_parse_chandef(rdev, info, &chandef);
+ if (err)
+ return err;
if (!dont_wait_for_ack) {
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -6178,8 +6397,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
}
}
- err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type,
- channel_type_valid, wait,
+ 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);
@@ -6230,7 +6448,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
- return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+ return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
}
static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
@@ -6260,8 +6478,7 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
if (state == wdev->ps)
return 0;
- err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state,
- wdev->ps_timeout);
+ err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
if (!err)
wdev->ps = state;
return err;
@@ -6322,14 +6539,13 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
};
static int nl80211_set_cqm_txe(struct genl_info *info,
- u32 rate, u32 pkts, u32 intvl)
+ u32 rate, u32 pkts, u32 intvl)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev;
struct net_device *dev = info->user_ptr[1];
- if ((rate < 0 || rate > 100) ||
- (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL))
+ if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
return -EINVAL;
wdev = dev->ieee80211_ptr;
@@ -6341,8 +6557,7 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
return -EOPNOTSUPP;
- return rdev->ops->set_cqm_txe_config(wdev->wiphy, dev,
- rate, pkts, intvl);
+ return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
}
static int nl80211_set_cqm_rssi(struct genl_info *info,
@@ -6364,8 +6579,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
return -EOPNOTSUPP;
- return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
- threshold, hysteresis);
+ return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis);
}
static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -6446,21 +6660,12 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
- !nl80211_valid_channel_type(info, &channel_type))
- return -EINVAL;
-
- setup.channel = rdev_freq_to_chan(rdev,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
- channel_type);
- if (!setup.channel)
- return -EINVAL;
- setup.channel_type = channel_type;
+ err = nl80211_parse_chandef(rdev, info, &setup.chandef);
+ if (err)
+ return err;
} else {
/* cfg80211_join_mesh() will sort it out */
- setup.channel = NULL;
+ setup.chandef.chan = NULL;
}
return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
@@ -6690,7 +6895,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
set_wakeup:
if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
- rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan);
+ rdev_set_wakeup(rdev, rdev->wowlan);
return 0;
error:
@@ -6746,7 +6951,7 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
+ err = rdev_set_rekey_data(rdev, dev, &rekey_data);
out:
wdev_unlock(wdev);
return err;
@@ -6805,7 +7010,7 @@ static int nl80211_probe_client(struct sk_buff *skb,
addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- err = rdev->ops->probe_client(&rdev->wiphy, dev, addr, &cookie);
+ err = rdev_probe_client(rdev, dev, addr, &cookie);
if (err)
goto free_msg;
@@ -6826,16 +7031,35 @@ static int nl80211_probe_client(struct sk_buff *skb,
static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct cfg80211_beacon_registration *reg, *nreg;
+ int rv;
if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
return -EOPNOTSUPP;
- if (rdev->ap_beacons_nlportid)
- return -EBUSY;
+ nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
+ if (!nreg)
+ return -ENOMEM;
+
+ /* First, check if already registered. */
+ spin_lock_bh(&rdev->beacon_registrations_lock);
+ list_for_each_entry(reg, &rdev->beacon_registrations, list) {
+ if (reg->nlportid == info->snd_portid) {
+ rv = -EALREADY;
+ goto out_err;
+ }
+ }
+ /* Add it to the list */
+ nreg->nlportid = info->snd_portid;
+ list_add(&nreg->list, &rdev->beacon_registrations);
- rdev->ap_beacons_nlportid = info->snd_portid;
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
return 0;
+out_err:
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
+ kfree(nreg);
+ return rv;
}
static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
@@ -6859,7 +7083,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- err = rdev->ops->start_p2p_device(&rdev->wiphy, wdev);
+ err = rdev_start_p2p_device(rdev, wdev);
if (err)
return err;
@@ -6885,7 +7109,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!wdev->p2p_started)
return 0;
- rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
+ rdev_stop_p2p_device(rdev, wdev);
wdev->p2p_started = false;
mutex_lock(&rdev->devlist_mtx);
@@ -7552,6 +7776,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_SET_MCAST_RATE,
+ .doit = nl80211_set_mcast_rate,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7622,6 +7854,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);
+
return 0;
nla_put_failure:
return -ENOBUFS;
@@ -8250,7 +8485,6 @@ static void nl80211_send_remain_on_chan_event(
int cmd, struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
{
struct sk_buff *msg;
@@ -8271,7 +8505,8 @@ static void nl80211_send_remain_on_chan_event(
wdev->netdev->ifindex)) ||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+ NL80211_CHAN_NO_HT) ||
nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
goto nla_put_failure;
@@ -8293,23 +8528,20 @@ static void nl80211_send_remain_on_chan_event(
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
{
nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
rdev, wdev, cookie, chan,
- channel_type, duration, gfp);
+ duration, gfp);
}
void nl80211_send_remain_on_channel_cancel(
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
- u64 cookie, struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type, gfp_t gfp)
+ u64 cookie, struct ieee80211_channel *chan, gfp_t gfp)
{
nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
- rdev, wdev, cookie, chan,
- channel_type, 0, gfp);
+ rdev, wdev, cookie, chan, 0, gfp);
}
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
@@ -8665,8 +8897,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
}
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, int freq,
- enum nl80211_channel_type type, gfp_t gfp)
+ struct net_device *netdev,
+ struct cfg80211_chan_def *chandef, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
@@ -8681,9 +8913,10 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
return;
}
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type))
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+ goto nla_put_failure;
+
+ if (nl80211_send_chandef(msg, chandef))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@@ -8800,7 +9033,10 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
void *hdr;
int err;
+ trace_cfg80211_probe_status(dev, addr, cookie, acked);
+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+
if (!msg)
return;
@@ -8835,44 +9071,96 @@ EXPORT_SYMBOL(cfg80211_probe_status);
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
- int freq, int sig_dbm, gfp_t gfp)
+ int freq, int sig_dbm)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct sk_buff *msg;
void *hdr;
- u32 nlportid = ACCESS_ONCE(rdev->ap_beacons_nlportid);
+ struct cfg80211_beacon_registration *reg;
- if (!nlportid)
- return;
+ trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
+
+ spin_lock_bh(&rdev->beacon_registrations_lock);
+ list_for_each_entry(reg, &rdev->beacon_registrations, list) {
+ msg = nlmsg_new(len + 100, GFP_ATOMIC);
+ if (!msg) {
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
+ return;
+ }
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
+ if (!hdr)
+ goto nla_put_failure;
- msg = nlmsg_new(len + 100, gfp);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ (freq &&
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
+ (sig_dbm &&
+ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
+ nla_put(msg, NL80211_ATTR_FRAME, len, frame))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
+ }
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
+ return;
+
+ nla_put_failure:
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
+ if (hdr)
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_report_obss_beacon);
+
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+ enum nl80211_tdls_operation oper,
+ u16 reason_code, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct sk_buff *msg;
+ void *hdr;
+ int err;
+
+ trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
+ reason_code);
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
if (!hdr) {
nlmsg_free(msg);
return;
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- (freq &&
- nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
- (sig_dbm &&
- nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
- nla_put(msg, NL80211_ATTR_FRAME, len, frame))
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
+ (reason_code > 0 &&
+ nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
goto nla_put_failure;
- genlmsg_end(msg, hdr);
+ err = genlmsg_end(msg, hdr);
+ if (err < 0) {
+ nlmsg_free(msg);
+ return;
+ }
- genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}
-EXPORT_SYMBOL(cfg80211_report_obss_beacon);
+EXPORT_SYMBOL(cfg80211_tdls_oper_request);
static int nl80211_netlink_notify(struct notifier_block * nb,
unsigned long state,
@@ -8881,6 +9169,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
struct netlink_notify *notify = _notify;
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
+ struct cfg80211_beacon_registration *reg, *tmp;
if (state != NETLINK_URELEASE)
return NOTIFY_DONE;
@@ -8890,8 +9179,17 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
list_for_each_entry_rcu(wdev, &rdev->wdev_list, list)
cfg80211_mlme_unregister_socket(wdev, notify->portid);
- if (rdev->ap_beacons_nlportid == notify->portid)
- rdev->ap_beacons_nlportid = 0;
+
+ spin_lock_bh(&rdev->beacon_registrations_lock);
+ list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
+ list) {
+ if (reg->nlportid == notify->portid) {
+ list_del(&reg->list);
+ kfree(reg);
+ break;
+ }
+ }
+ spin_unlock_bh(&rdev->beacon_registrations_lock);
}
rcu_read_unlock();
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index f6153516068c..2acba8477e9d 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -76,13 +76,11 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp);
void nl80211_send_remain_on_channel_cancel(
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
- u64 cookie, struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type, gfp_t gfp);
+ u64 cookie, struct ieee80211_channel *chan, gfp_t gfp);
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *mac_addr,
@@ -129,8 +127,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
const u8 *bssid, bool preauth, gfp_t gfp);
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
- struct net_device *dev, int freq,
- enum nl80211_channel_type type, gfp_t gfp);
+ struct net_device *dev,
+ struct cfg80211_chan_def *chandef, gfp_t gfp);
bool nl80211_unexpected_frame(struct net_device *dev,
const u8 *addr, gfp_t gfp);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
new file mode 100644
index 000000000000..6c0c8191f837
--- /dev/null
+++ b/net/wireless/rdev-ops.h
@@ -0,0 +1,878 @@
+#ifndef __CFG80211_RDEV_OPS
+#define __CFG80211_RDEV_OPS
+
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "core.h"
+#include "trace.h"
+
+static inline int rdev_suspend(struct cfg80211_registered_device *rdev)
+{
+ int ret;
+ trace_rdev_suspend(&rdev->wiphy, rdev->wowlan);
+ ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_resume(struct cfg80211_registered_device *rdev)
+{
+ int ret;
+ trace_rdev_resume(&rdev->wiphy);
+ ret = rdev->ops->resume(&rdev->wiphy);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_set_wakeup(struct cfg80211_registered_device *rdev,
+ bool enabled)
+{
+ trace_rdev_set_wakeup(&rdev->wiphy, enabled);
+ rdev->ops->set_wakeup(&rdev->wiphy, enabled);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline struct wireless_dev
+*rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct wireless_dev *ret;
+ trace_rdev_add_virtual_intf(&rdev->wiphy, name, type);
+ ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, type, flags,
+ params);
+ trace_rdev_return_wdev(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_del_virtual_intf(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ int ret;
+ trace_rdev_del_virtual_intf(&rdev->wiphy, wdev);
+ ret = rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_change_virtual_intf(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, enum nl80211_iftype type,
+ u32 *flags, struct vif_params *params)
+{
+ int ret;
+ trace_rdev_change_virtual_intf(&rdev->wiphy, dev, type);
+ ret = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, type, flags,
+ params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr,
+ struct key_params *params)
+{
+ int ret;
+ trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+ ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
+ mac_addr, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_get_key(struct cfg80211_registered_device *rdev, struct net_device *netdev,
+ u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie, struct key_params*))
+{
+ int ret;
+ trace_rdev_get_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+ ret = rdev->ops->get_key(&rdev->wiphy, netdev, key_index, pairwise,
+ mac_addr, cookie, callback);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_del_key(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr)
+{
+ int ret;
+ trace_rdev_del_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+ ret = rdev->ops->del_key(&rdev->wiphy, netdev, key_index, pairwise,
+ mac_addr);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_default_key(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u8 key_index, bool unicast,
+ bool multicast)
+{
+ int ret;
+ trace_rdev_set_default_key(&rdev->wiphy, netdev, key_index,
+ unicast, multicast);
+ ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, key_index,
+ unicast, multicast);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u8 key_index)
+{
+ int ret;
+ trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, key_index);
+ ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev,
+ key_index);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_start_ap(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ap_settings *settings)
+{
+ int ret;
+ trace_rdev_start_ap(&rdev->wiphy, dev, settings);
+ ret = rdev->ops->start_ap(&rdev->wiphy, dev, settings);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_change_beacon(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_beacon_data *info)
+{
+ int ret;
+ trace_rdev_change_beacon(&rdev->wiphy, dev, info);
+ ret = rdev->ops->change_beacon(&rdev->wiphy, dev, info);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_stop_ap(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ int ret;
+ trace_rdev_stop_ap(&rdev->wiphy, dev);
+ ret = rdev->ops->stop_ap(&rdev->wiphy, dev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_add_station(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *mac,
+ struct station_parameters *params)
+{
+ int ret;
+ trace_rdev_add_station(&rdev->wiphy, dev, mac, params);
+ ret = rdev->ops->add_station(&rdev->wiphy, dev, mac, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_del_station(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *mac)
+{
+ int ret;
+ trace_rdev_del_station(&rdev->wiphy, dev, mac);
+ ret = rdev->ops->del_station(&rdev->wiphy, dev, mac);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_change_station(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *mac,
+ struct station_parameters *params)
+{
+ int ret;
+ trace_rdev_change_station(&rdev->wiphy, dev, mac, params);
+ ret = rdev->ops->change_station(&rdev->wiphy, dev, mac, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_get_station(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *mac,
+ struct station_info *sinfo)
+{
+ int ret;
+ trace_rdev_get_station(&rdev->wiphy, dev, mac);
+ ret = rdev->ops->get_station(&rdev->wiphy, dev, mac, sinfo);
+ trace_rdev_return_int_station_info(&rdev->wiphy, ret, sinfo);
+ return ret;
+}
+
+static inline int rdev_dump_station(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, int idx, u8 *mac,
+ struct station_info *sinfo)
+{
+ int ret;
+ trace_rdev_dump_station(&rdev->wiphy, dev, idx, mac);
+ ret = rdev->ops->dump_station(&rdev->wiphy, dev, idx, mac, sinfo);
+ trace_rdev_return_int_station_info(&rdev->wiphy, ret, sinfo);
+ return ret;
+}
+
+static inline int rdev_add_mpath(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *dst, u8 *next_hop)
+{
+ int ret;
+ trace_rdev_add_mpath(&rdev->wiphy, dev, dst, next_hop);
+ ret = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_del_mpath(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *dst)
+{
+ int ret;
+ trace_rdev_del_mpath(&rdev->wiphy, dev, dst);
+ ret = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_change_mpath(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *dst,
+ u8 *next_hop)
+{
+ int ret;
+ trace_rdev_change_mpath(&rdev->wiphy, dev, dst, next_hop);
+ ret = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_get_mpath(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *dst, u8 *next_hop,
+ struct mpath_info *pinfo)
+{
+ int ret;
+ trace_rdev_get_mpath(&rdev->wiphy, dev, dst, next_hop);
+ ret = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, pinfo);
+ trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
+ return ret;
+
+}
+
+static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, int idx, u8 *dst,
+ u8 *next_hop, struct mpath_info *pinfo)
+
+{
+ int ret;
+ trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop);
+ ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop,
+ pinfo);
+ trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
+ return ret;
+}
+
+static inline int
+rdev_get_mesh_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, struct mesh_config *conf)
+{
+ int ret;
+ trace_rdev_get_mesh_config(&rdev->wiphy, dev);
+ ret = rdev->ops->get_mesh_config(&rdev->wiphy, dev, conf);
+ trace_rdev_return_int_mesh_config(&rdev->wiphy, ret, conf);
+ return ret;
+}
+
+static inline int
+rdev_update_mesh_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u32 mask,
+ const struct mesh_config *nconf)
+{
+ int ret;
+ trace_rdev_update_mesh_config(&rdev->wiphy, dev, mask, nconf);
+ ret = rdev->ops->update_mesh_config(&rdev->wiphy, dev, mask, nconf);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_join_mesh(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ const struct mesh_config *conf,
+ const struct mesh_setup *setup)
+{
+ int ret;
+ trace_rdev_join_mesh(&rdev->wiphy, dev, conf, setup);
+ ret = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+
+static inline int rdev_leave_mesh(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ int ret;
+ trace_rdev_leave_mesh(&rdev->wiphy, dev);
+ ret = rdev->ops->leave_mesh(&rdev->wiphy, dev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct bss_parameters *params)
+
+{
+ int ret;
+ trace_rdev_change_bss(&rdev->wiphy, dev, params);
+ ret = rdev->ops->change_bss(&rdev->wiphy, dev, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_set_txq_params(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_txq_params *params)
+
+{
+ int ret;
+ trace_rdev_set_txq_params(&rdev->wiphy, dev, params);
+ ret = rdev->ops->set_txq_params(&rdev->wiphy, dev, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan)
+{
+ int ret;
+ trace_rdev_libertas_set_mesh_channel(&rdev->wiphy, dev, chan);
+ ret = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, dev, chan);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct cfg80211_chan_def *chandef)
+{
+ int ret;
+ trace_rdev_set_monitor_channel(&rdev->wiphy, chandef);
+ ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_scan(struct cfg80211_registered_device *rdev,
+ struct cfg80211_scan_request *request)
+{
+ int ret;
+ trace_rdev_scan(&rdev->wiphy, request);
+ ret = rdev->ops->scan(&rdev->wiphy, request);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_auth_request *req)
+{
+ int ret;
+ trace_rdev_auth(&rdev->wiphy, dev, req);
+ ret = rdev->ops->auth(&rdev->wiphy, dev, req);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_assoc_request *req)
+{
+ int ret;
+ trace_rdev_assoc(&rdev->wiphy, dev, req);
+ ret = rdev->ops->assoc(&rdev->wiphy, dev, req);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_deauth_request *req)
+{
+ int ret;
+ trace_rdev_deauth(&rdev->wiphy, dev, req);
+ ret = rdev->ops->deauth(&rdev->wiphy, dev, req);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_disassoc_request *req)
+{
+ int ret;
+ trace_rdev_disassoc(&rdev->wiphy, dev, req);
+ ret = rdev->ops->disassoc(&rdev->wiphy, dev, req);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ int ret;
+ trace_rdev_connect(&rdev->wiphy, dev, sme);
+ ret = rdev->ops->connect(&rdev->wiphy, dev, sme);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason_code)
+{
+ int ret;
+ trace_rdev_disconnect(&rdev->wiphy, dev, reason_code);
+ ret = rdev->ops->disconnect(&rdev->wiphy, dev, reason_code);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_join_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ int ret;
+ trace_rdev_join_ibss(&rdev->wiphy, dev, params);
+ ret = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_leave_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ int ret;
+ trace_rdev_leave_ibss(&rdev->wiphy, dev);
+ ret = rdev->ops->leave_ibss(&rdev->wiphy, dev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed)
+{
+ int ret;
+ trace_rdev_set_wiphy_params(&rdev->wiphy, changed);
+ ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, int mbm)
+{
+ int ret;
+ trace_rdev_set_tx_power(&rdev->wiphy, wdev, type, mbm);
+ ret = rdev->ops->set_tx_power(&rdev->wiphy, wdev, type, mbm);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int *dbm)
+{
+ int ret;
+ trace_rdev_get_tx_power(&rdev->wiphy, wdev);
+ ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, dbm);
+ trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm);
+ return ret;
+}
+
+static inline int rdev_set_wds_peer(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *addr)
+{
+ int ret;
+ trace_rdev_set_wds_peer(&rdev->wiphy, dev, addr);
+ ret = rdev->ops->set_wds_peer(&rdev->wiphy, dev, addr);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
+{
+ trace_rdev_rfkill_poll(&rdev->wiphy);
+ rdev->ops->rfkill_poll(&rdev->wiphy);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
+
+#ifdef CONFIG_NL80211_TESTMODE
+static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev,
+ void *data, int len)
+{
+ int ret;
+ trace_rdev_testmode_cmd(&rdev->wiphy);
+ ret = rdev->ops->testmode_cmd(&rdev->wiphy, data, len);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_testmode_dump(struct cfg80211_registered_device *rdev,
+ struct sk_buff *skb,
+ struct netlink_callback *cb, void *data,
+ int len)
+{
+ int ret;
+ trace_rdev_testmode_dump(&rdev->wiphy);
+ ret = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb, data, len);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+#endif
+
+static inline int
+rdev_set_bitrate_mask(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int ret;
+ trace_rdev_set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+ ret = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_dump_survey(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, int idx,
+ struct survey_info *info)
+{
+ int ret;
+ trace_rdev_dump_survey(&rdev->wiphy, netdev, idx);
+ ret = rdev->ops->dump_survey(&rdev->wiphy, netdev, idx, info);
+ if (ret < 0)
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ else
+ trace_rdev_return_int_survey_info(&rdev->wiphy, ret, info);
+ return ret;
+}
+
+static inline int rdev_set_pmksa(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ int ret;
+ trace_rdev_set_pmksa(&rdev->wiphy, netdev, pmksa);
+ ret = rdev->ops->set_pmksa(&rdev->wiphy, netdev, pmksa);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_del_pmksa(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ int ret;
+ trace_rdev_del_pmksa(&rdev->wiphy, netdev, pmksa);
+ ret = rdev->ops->del_pmksa(&rdev->wiphy, netdev, pmksa);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_flush_pmksa(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev)
+{
+ int ret;
+ trace_rdev_flush_pmksa(&rdev->wiphy, netdev);
+ ret = rdev->ops->flush_pmksa(&rdev->wiphy, netdev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct ieee80211_channel *chan,
+ unsigned int duration, u64 *cookie)
+{
+ int ret;
+ trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration);
+ ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
+ duration, cookie);
+ trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+ return ret;
+}
+
+static inline int
+rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, u64 cookie)
+{
+ int ret;
+ trace_rdev_cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+ ret = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+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)
+{
+ 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_return_int_cookie(&rdev->wiphy, ret, *cookie);
+ return ret;
+}
+
+static inline int
+rdev_mgmt_tx_cancel_wait(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, u64 cookie)
+{
+ int ret;
+ trace_rdev_mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+ ret = rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_set_power_mgmt(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, bool enabled,
+ int timeout)
+{
+ int ret;
+ trace_rdev_set_power_mgmt(&rdev->wiphy, dev, enabled, timeout);
+ ret = rdev->ops->set_power_mgmt(&rdev->wiphy, dev, enabled, timeout);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_cqm_rssi_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, s32 rssi_thold, u32 rssi_hyst)
+{
+ int ret;
+ trace_rdev_set_cqm_rssi_config(&rdev->wiphy, dev, rssi_thold,
+ rssi_hyst);
+ ret = rdev->ops->set_cqm_rssi_config(&rdev->wiphy, dev, rssi_thold,
+ rssi_hyst);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u32 rate, u32 pkts, u32 intvl)
+{
+ int ret;
+ trace_rdev_set_cqm_txe_config(&rdev->wiphy, dev, rate, pkts, intvl);
+ ret = rdev->ops->set_cqm_txe_config(&rdev->wiphy, dev, rate, pkts,
+ intvl);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void
+rdev_mgmt_frame_register(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, u16 frame_type, bool reg)
+{
+ trace_rdev_mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
+ rdev->ops->mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline int rdev_set_antenna(struct cfg80211_registered_device *rdev,
+ u32 tx_ant, u32 rx_ant)
+{
+ int ret;
+ trace_rdev_set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ ret = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_get_antenna(struct cfg80211_registered_device *rdev,
+ u32 *tx_ant, u32 *rx_ant)
+{
+ int ret;
+ trace_rdev_get_antenna(&rdev->wiphy);
+ ret = rdev->ops->get_antenna(&rdev->wiphy, tx_ant, rx_ant);
+ if (ret)
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ else
+ trace_rdev_return_int_tx_rx(&rdev->wiphy, ret, *tx_ant,
+ *rx_ant);
+ return ret;
+}
+
+static inline int rdev_set_ringparam(struct cfg80211_registered_device *rdev,
+ u32 tx, u32 rx)
+{
+ int ret;
+ trace_rdev_set_ringparam(&rdev->wiphy, tx, rx);
+ ret = rdev->ops->set_ringparam(&rdev->wiphy, tx, rx);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_get_ringparam(struct cfg80211_registered_device *rdev,
+ u32 *tx, u32 *tx_max, u32 *rx,
+ u32 *rx_max)
+{
+ trace_rdev_get_ringparam(&rdev->wiphy);
+ rdev->ops->get_ringparam(&rdev->wiphy, tx, tx_max, rx, rx_max);
+ trace_rdev_return_void_tx_rx(&rdev->wiphy, *tx, *tx_max, *rx, *rx_max);
+}
+
+static inline int
+rdev_sched_scan_start(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *request)
+{
+ int ret;
+ trace_rdev_sched_scan_start(&rdev->wiphy, dev, request);
+ ret = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_sched_scan_stop(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ int ret;
+ trace_rdev_sched_scan_stop(&rdev->wiphy, dev);
+ ret = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_set_rekey_data(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_gtk_rekey_data *data)
+{
+ int ret;
+ trace_rdev_set_rekey_data(&rdev->wiphy, dev);
+ ret = rdev->ops->set_rekey_data(&rdev->wiphy, dev, data);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_tdls_mgmt(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *peer,
+ u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf, size_t len)
+{
+ int ret;
+ trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
+ dialog_token, status_code, buf, len);
+ ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
+ dialog_token, status_code, buf, len);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_tdls_oper(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u8 *peer,
+ enum nl80211_tdls_operation oper)
+{
+ int ret;
+ trace_rdev_tdls_oper(&rdev->wiphy, dev, peer, oper);
+ ret = rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, oper);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_probe_client(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *peer,
+ u64 *cookie)
+{
+ int ret;
+ trace_rdev_probe_client(&rdev->wiphy, dev, peer);
+ ret = rdev->ops->probe_client(&rdev->wiphy, dev, peer, cookie);
+ trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+ return ret;
+}
+
+static inline int rdev_set_noack_map(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 noack_map)
+{
+ int ret;
+ trace_rdev_set_noack_map(&rdev->wiphy, dev, noack_map);
+ ret = rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int
+rdev_get_et_sset_count(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, int sset)
+{
+ int ret;
+ trace_rdev_get_et_sset_count(&rdev->wiphy, dev, sset);
+ ret = rdev->ops->get_et_sset_count(&rdev->wiphy, dev, sset);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_get_et_stats(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ trace_rdev_get_et_stats(&rdev->wiphy, dev);
+ rdev->ops->get_et_stats(&rdev->wiphy, dev, stats, data);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u32 sset,
+ u8 *data)
+{
+ trace_rdev_get_et_strings(&rdev->wiphy, dev, sset);
+ rdev->ops->get_et_strings(&rdev->wiphy, dev, sset, data);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
+static inline int
+rdev_get_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef)
+{
+ int ret;
+
+ trace_rdev_get_channel(&rdev->wiphy, wdev);
+ ret = rdev->ops->get_channel(&rdev->wiphy, wdev, chandef);
+ trace_rdev_return_chandef(&rdev->wiphy, ret, chandef);
+
+ return ret;
+}
+
+static inline int rdev_start_p2p_device(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ int ret;
+
+ trace_rdev_start_p2p_device(&rdev->wiphy, wdev);
+ ret = rdev->ops->start_p2p_device(&rdev->wiphy, wdev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_stop_p2p_device(&rdev->wiphy, wdev);
+ rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index b75756b05af7..6e5308998e30 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1796,7 +1796,7 @@ EXPORT_SYMBOL(regulatory_hint);
*/
void regulatory_hint_11d(struct wiphy *wiphy,
enum ieee80211_band band,
- u8 *country_ie,
+ const u8 *country_ie,
u8 country_ie_len)
{
char alpha2[2];
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index f023c8a31c60..4c0a32ffd530 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -81,7 +81,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
*/
void regulatory_hint_11d(struct wiphy *wiphy,
enum ieee80211_band band,
- u8 *country_ie,
+ const u8 *country_ie,
u8 country_ie_len);
/**
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9730c9862bdc..01592d7d4789 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -17,9 +17,63 @@
#include "core.h"
#include "nl80211.h"
#include "wext-compat.h"
+#include "rdev-ops.h"
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
+static void bss_release(struct kref *ref)
+{
+ struct cfg80211_bss_ies *ies;
+ struct cfg80211_internal_bss *bss;
+
+ bss = container_of(ref, struct cfg80211_internal_bss, ref);
+
+ if (WARN_ON(atomic_read(&bss->hold)))
+ return;
+
+ if (bss->pub.free_priv)
+ bss->pub.free_priv(&bss->pub);
+
+ ies = (void *)rcu_access_pointer(bss->pub.beacon_ies);
+ if (ies)
+ kfree_rcu(ies, rcu_head);
+ ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies);
+ if (ies)
+ kfree_rcu(ies, rcu_head);
+
+ kfree(bss);
+}
+
+/* must hold dev->bss_lock! */
+static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
+ struct cfg80211_internal_bss *bss)
+{
+ list_del_init(&bss->list);
+ rb_erase(&bss->rbn, &dev->bss_tree);
+ kref_put(&bss->ref, bss_release);
+}
+
+/* must hold dev->bss_lock! */
+static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
+ unsigned long expire_time)
+{
+ struct cfg80211_internal_bss *bss, *tmp;
+ bool expired = false;
+
+ list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
+ if (atomic_read(&bss->hold))
+ continue;
+ if (!time_after(expire_time, bss->ts))
+ continue;
+
+ __cfg80211_unlink_bss(dev, bss);
+ expired = true;
+ }
+
+ if (expired)
+ dev->bss_generation++;
+}
+
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
{
struct cfg80211_scan_request *request;
@@ -45,10 +99,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
if (wdev->netdev)
cfg80211_sme_scan_done(wdev->netdev);
- if (request->aborted)
+ if (request->aborted) {
nl80211_send_scan_aborted(rdev, wdev);
- else
+ } else {
+ if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+ /* flush entries from previous scans */
+ spin_lock_bh(&rdev->bss_lock);
+ __cfg80211_bss_expire(rdev, request->scan_start);
+ spin_unlock_bh(&rdev->bss_lock);
+ }
nl80211_send_scan_done(rdev, wdev);
+ }
#ifdef CONFIG_CFG80211_WEXT
if (wdev->netdev && !request->aborted) {
@@ -89,6 +150,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
{
+ trace_cfg80211_scan_done(request, aborted);
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted;
@@ -99,22 +161,34 @@ EXPORT_SYMBOL(cfg80211_scan_done);
void __cfg80211_sched_scan_results(struct work_struct *wk)
{
struct cfg80211_registered_device *rdev;
+ struct cfg80211_sched_scan_request *request;
rdev = container_of(wk, struct cfg80211_registered_device,
sched_scan_results_wk);
+ request = rdev->sched_scan_req;
+
mutex_lock(&rdev->sched_scan_mtx);
/* we don't have sched_scan_req anymore if the scan is stopping */
- if (rdev->sched_scan_req)
- nl80211_send_sched_scan_results(rdev,
- rdev->sched_scan_req->dev);
+ if (request) {
+ if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+ /* flush entries from previous scans */
+ spin_lock_bh(&rdev->bss_lock);
+ __cfg80211_bss_expire(rdev, request->scan_start);
+ spin_unlock_bh(&rdev->bss_lock);
+ request->scan_start =
+ jiffies + msecs_to_jiffies(request->interval);
+ }
+ nl80211_send_sched_scan_results(rdev, request->dev);
+ }
mutex_unlock(&rdev->sched_scan_mtx);
}
void cfg80211_sched_scan_results(struct wiphy *wiphy)
{
+ trace_cfg80211_sched_scan_results(wiphy);
/* ignore if we're not scanning */
if (wiphy_to_dev(wiphy)->sched_scan_req)
queue_work(cfg80211_wq,
@@ -126,6 +200,8 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ trace_cfg80211_sched_scan_stopped(wiphy);
+
mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, true);
mutex_unlock(&rdev->sched_scan_mtx);
@@ -145,7 +221,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
dev = rdev->sched_scan_req->dev;
if (!driver_initiated) {
- int err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
+ int err = rdev_sched_scan_stop(rdev, dev);
if (err)
return err;
}
@@ -158,24 +234,6 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
return 0;
}
-static void bss_release(struct kref *ref)
-{
- struct cfg80211_internal_bss *bss;
-
- bss = container_of(ref, struct cfg80211_internal_bss, ref);
- if (bss->pub.free_priv)
- bss->pub.free_priv(&bss->pub);
-
- if (bss->beacon_ies_allocated)
- kfree(bss->pub.beacon_ies);
- if (bss->proberesp_ies_allocated)
- kfree(bss->pub.proberesp_ies);
-
- BUG_ON(atomic_read(&bss->hold));
-
- kfree(bss);
-}
-
/* must hold dev->bss_lock! */
void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs)
@@ -183,37 +241,13 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
struct cfg80211_internal_bss *bss;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
- list_for_each_entry(bss, &dev->bss_list, list) {
+ list_for_each_entry(bss, &dev->bss_list, list)
bss->ts -= age_jiffies;
- }
-}
-
-/* must hold dev->bss_lock! */
-static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *bss)
-{
- list_del_init(&bss->list);
- rb_erase(&bss->rbn, &dev->bss_tree);
- kref_put(&bss->ref, bss_release);
}
-/* must hold dev->bss_lock! */
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
{
- struct cfg80211_internal_bss *bss, *tmp;
- bool expired = false;
-
- list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
- if (atomic_read(&bss->hold))
- continue;
- if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
- continue;
- __cfg80211_unlink_bss(dev, bss);
- expired = true;
- }
-
- if (expired)
- dev->bss_generation++;
+ __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
}
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
@@ -257,7 +291,7 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
}
EXPORT_SYMBOL(cfg80211_find_vendor_ie);
-static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
+static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2)
{
const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
@@ -277,10 +311,10 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
}
-static bool is_bss(struct cfg80211_bss *a,
- const u8 *bssid,
+static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
const u8 *ssid, size_t ssid_len)
{
+ const struct cfg80211_bss_ies *ies;
const u8 *ssidie;
if (bssid && !ether_addr_equal(a->bssid, bssid))
@@ -289,9 +323,10 @@ static bool is_bss(struct cfg80211_bss *a,
if (!ssid)
return true;
- ssidie = cfg80211_find_ie(WLAN_EID_SSID,
- a->information_elements,
- a->len_information_elements);
+ ies = rcu_access_pointer(a->ies);
+ if (!ies)
+ return false;
+ ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
if (!ssidie)
return false;
if (ssidie[1] != ssid_len)
@@ -301,20 +336,21 @@ static bool is_bss(struct cfg80211_bss *a,
static bool is_mesh_bss(struct cfg80211_bss *a)
{
+ const struct cfg80211_bss_ies *ies;
const u8 *ie;
if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
- a->information_elements,
- a->len_information_elements);
+ ies = rcu_access_pointer(a->ies);
+ if (!ies)
+ return false;
+
+ ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len);
if (!ie)
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
- a->information_elements,
- a->len_information_elements);
+ ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len);
if (!ie)
return false;
@@ -325,14 +361,17 @@ static bool is_mesh(struct cfg80211_bss *a,
const u8 *meshid, size_t meshidlen,
const u8 *meshcfg)
{
+ const struct cfg80211_bss_ies *ies;
const u8 *ie;
if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
- a->information_elements,
- a->len_information_elements);
+ ies = rcu_access_pointer(a->ies);
+ if (!ies)
+ return false;
+
+ ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len);
if (!ie)
return false;
if (ie[1] != meshidlen)
@@ -340,9 +379,7 @@ static bool is_mesh(struct cfg80211_bss *a,
if (memcmp(ie + 2, meshid, meshidlen))
return false;
- ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
- a->information_elements,
- a->len_information_elements);
+ ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len);
if (!ie)
return false;
if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
@@ -354,30 +391,33 @@ static bool is_mesh(struct cfg80211_bss *a,
* part in the same mesh.
*/
return memcmp(ie + 2, meshcfg,
- sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
+ sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
}
-static int cmp_bss_core(struct cfg80211_bss *a,
- struct cfg80211_bss *b)
+static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b)
{
+ const struct cfg80211_bss_ies *a_ies, *b_ies;
int r;
if (a->channel != b->channel)
return b->channel->center_freq - a->channel->center_freq;
if (is_mesh_bss(a) && is_mesh_bss(b)) {
+ a_ies = rcu_access_pointer(a->ies);
+ if (!a_ies)
+ return -1;
+ b_ies = rcu_access_pointer(b->ies);
+ if (!b_ies)
+ return 1;
+
r = cmp_ies(WLAN_EID_MESH_ID,
- a->information_elements,
- a->len_information_elements,
- b->information_elements,
- b->len_information_elements);
+ a_ies->data, a_ies->len,
+ b_ies->data, b_ies->len);
if (r)
return r;
return cmp_ies(WLAN_EID_MESH_CONFIG,
- a->information_elements,
- a->len_information_elements,
- b->information_elements,
- b->len_information_elements);
+ a_ies->data, a_ies->len,
+ b_ies->data, b_ies->len);
}
/*
@@ -390,22 +430,28 @@ static int cmp_bss_core(struct cfg80211_bss *a,
static int cmp_bss(struct cfg80211_bss *a,
struct cfg80211_bss *b)
{
+ const struct cfg80211_bss_ies *a_ies, *b_ies;
int r;
r = cmp_bss_core(a, b);
if (r)
return r;
+ a_ies = rcu_access_pointer(a->ies);
+ if (!a_ies)
+ return -1;
+ b_ies = rcu_access_pointer(b->ies);
+ if (!b_ies)
+ return 1;
+
return cmp_ies(WLAN_EID_SSID,
- a->information_elements,
- a->len_information_elements,
- b->information_elements,
- b->len_information_elements);
+ a_ies->data, a_ies->len,
+ b_ies->data, b_ies->len);
}
-static int cmp_hidden_bss(struct cfg80211_bss *a,
- struct cfg80211_bss *b)
+static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b)
{
+ const struct cfg80211_bss_ies *a_ies, *b_ies;
const u8 *ie1;
const u8 *ie2;
int i;
@@ -415,17 +461,26 @@ static int cmp_hidden_bss(struct cfg80211_bss *a,
if (r)
return r;
- ie1 = cfg80211_find_ie(WLAN_EID_SSID,
- a->information_elements,
- a->len_information_elements);
- ie2 = cfg80211_find_ie(WLAN_EID_SSID,
- b->information_elements,
- b->len_information_elements);
+ a_ies = rcu_access_pointer(a->ies);
+ if (!a_ies)
+ return -1;
+ b_ies = rcu_access_pointer(b->ies);
+ if (!b_ies)
+ return 1;
+
+ ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len);
+ ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len);
- /* Key comparator must use same algorithm in any rb-tree
+ /*
+ * Key comparator must use same algorithm in any rb-tree
* search function (order is important), otherwise ordering
* of items in the tree is broken and search gives incorrect
- * results. This code uses same order as cmp_ies() does. */
+ * results. This code uses same order as cmp_ies() does.
+ *
+ * Note that due to the differring behaviour with hidden SSIDs
+ * this function only works when "b" is the tree element and
+ * "a" is the key we're looking for.
+ */
/* sort missing IE before (left of) present IE */
if (!ie1)
@@ -441,10 +496,14 @@ static int cmp_hidden_bss(struct cfg80211_bss *a,
if (ie1[1] != ie2[1])
return ie2[1] - ie1[1];
- /* zeroed SSID ie is another indication of a hidden bss */
+ /*
+ * zeroed SSID ie is another indication of a hidden bss;
+ * if it isn't zeroed just return the regular sort value
+ * to find the next candidate
+ */
for (i = 0; i < ie2[1]; i++)
if (ie2[i + 2])
- return -1;
+ return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
return 0;
}
@@ -459,6 +518,9 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
struct cfg80211_internal_bss *bss, *res = NULL;
unsigned long now = jiffies;
+ trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
+ capa_val);
+
spin_lock_bh(&dev->bss_lock);
list_for_each_entry(bss, &dev->bss_list, list) {
@@ -480,6 +542,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
spin_unlock_bh(&dev->bss_lock);
if (!res)
return NULL;
+ trace_cfg80211_return_bss(&res->pub);
return &res->pub;
}
EXPORT_SYMBOL(cfg80211_get_bss);
@@ -566,7 +629,7 @@ rb_find_bss(struct cfg80211_registered_device *dev,
static struct cfg80211_internal_bss *
rb_find_hidden_bss(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *res)
+ struct cfg80211_internal_bss *res)
{
struct rb_node *n = dev->bss_tree.rb_node;
struct cfg80211_internal_bss *bss;
@@ -589,127 +652,86 @@ rb_find_hidden_bss(struct cfg80211_registered_device *dev,
static void
copy_hidden_ies(struct cfg80211_internal_bss *res,
- struct cfg80211_internal_bss *hidden)
+ struct cfg80211_internal_bss *hidden)
{
- if (unlikely(res->pub.beacon_ies))
- return;
- if (WARN_ON(!hidden->pub.beacon_ies))
+ const struct cfg80211_bss_ies *ies;
+
+ if (rcu_access_pointer(res->pub.beacon_ies))
return;
- res->pub.beacon_ies = kmalloc(hidden->pub.len_beacon_ies, GFP_ATOMIC);
- if (unlikely(!res->pub.beacon_ies))
+ ies = rcu_access_pointer(hidden->pub.beacon_ies);
+ if (WARN_ON(!ies))
return;
- res->beacon_ies_allocated = true;
- res->pub.len_beacon_ies = hidden->pub.len_beacon_ies;
- memcpy(res->pub.beacon_ies, hidden->pub.beacon_ies,
- res->pub.len_beacon_ies);
+ ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC);
+ if (unlikely(!ies))
+ return;
+ rcu_assign_pointer(res->pub.beacon_ies, ies);
}
static struct cfg80211_internal_bss *
cfg80211_bss_update(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *res)
+ struct cfg80211_internal_bss *tmp)
{
struct cfg80211_internal_bss *found = NULL;
- /*
- * The reference to "res" is donated to this function.
- */
-
- if (WARN_ON(!res->pub.channel)) {
- kref_put(&res->ref, bss_release);
+ if (WARN_ON(!tmp->pub.channel))
return NULL;
- }
- res->ts = jiffies;
+ tmp->ts = jiffies;
spin_lock_bh(&dev->bss_lock);
- found = rb_find_bss(dev, res);
+ if (WARN_ON(!rcu_access_pointer(tmp->pub.ies))) {
+ spin_unlock_bh(&dev->bss_lock);
+ return NULL;
+ }
+
+ found = rb_find_bss(dev, tmp);
if (found) {
- found->pub.beacon_interval = res->pub.beacon_interval;
- found->pub.tsf = res->pub.tsf;
- found->pub.signal = res->pub.signal;
- found->pub.capability = res->pub.capability;
- found->ts = res->ts;
+ found->pub.beacon_interval = tmp->pub.beacon_interval;
+ found->pub.tsf = tmp->pub.tsf;
+ found->pub.signal = tmp->pub.signal;
+ found->pub.capability = tmp->pub.capability;
+ found->ts = tmp->ts;
/* Update IEs */
- if (res->pub.proberesp_ies) {
- size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
- size_t ielen = res->pub.len_proberesp_ies;
-
- if (found->pub.proberesp_ies &&
- !found->proberesp_ies_allocated &&
- ksize(found) >= used + ielen) {
- memcpy(found->pub.proberesp_ies,
- res->pub.proberesp_ies, ielen);
- found->pub.len_proberesp_ies = ielen;
- } else {
- u8 *ies = found->pub.proberesp_ies;
-
- if (found->proberesp_ies_allocated)
- ies = krealloc(ies, ielen, GFP_ATOMIC);
- else
- ies = kmalloc(ielen, GFP_ATOMIC);
-
- if (ies) {
- memcpy(ies, res->pub.proberesp_ies,
- ielen);
- found->proberesp_ies_allocated = true;
- found->pub.proberesp_ies = ies;
- found->pub.len_proberesp_ies = ielen;
- }
- }
+ if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
+ const struct cfg80211_bss_ies *old;
+
+ old = rcu_access_pointer(found->pub.proberesp_ies);
+ rcu_assign_pointer(found->pub.proberesp_ies,
+ tmp->pub.proberesp_ies);
/* Override possible earlier Beacon frame IEs */
- found->pub.information_elements =
- found->pub.proberesp_ies;
- found->pub.len_information_elements =
- found->pub.len_proberesp_ies;
- }
- if (res->pub.beacon_ies) {
- size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
- size_t ielen = res->pub.len_beacon_ies;
- bool information_elements_is_beacon_ies =
- (found->pub.information_elements ==
- found->pub.beacon_ies);
-
- if (found->pub.beacon_ies &&
- !found->beacon_ies_allocated &&
- ksize(found) >= used + ielen) {
- memcpy(found->pub.beacon_ies,
- res->pub.beacon_ies, ielen);
- found->pub.len_beacon_ies = ielen;
- } else {
- u8 *ies = found->pub.beacon_ies;
-
- if (found->beacon_ies_allocated)
- ies = krealloc(ies, ielen, GFP_ATOMIC);
- else
- ies = kmalloc(ielen, GFP_ATOMIC);
-
- if (ies) {
- memcpy(ies, res->pub.beacon_ies,
- ielen);
- found->beacon_ies_allocated = true;
- found->pub.beacon_ies = ies;
- found->pub.len_beacon_ies = ielen;
- }
- }
+ rcu_assign_pointer(found->pub.ies,
+ tmp->pub.proberesp_ies);
+ if (old)
+ kfree_rcu((struct cfg80211_bss_ies *)old,
+ rcu_head);
+ } else if (rcu_access_pointer(tmp->pub.beacon_ies)) {
+ const struct cfg80211_bss_ies *old, *ies;
+
+ old = rcu_access_pointer(found->pub.beacon_ies);
+ ies = rcu_access_pointer(found->pub.ies);
+
+ rcu_assign_pointer(found->pub.beacon_ies,
+ tmp->pub.beacon_ies);
/* Override IEs if they were from a beacon before */
- if (information_elements_is_beacon_ies) {
- found->pub.information_elements =
- found->pub.beacon_ies;
- found->pub.len_information_elements =
- found->pub.len_beacon_ies;
- }
- }
+ if (old == ies)
+ rcu_assign_pointer(found->pub.ies,
+ tmp->pub.beacon_ies);
- kref_put(&res->ref, bss_release);
+ if (old)
+ kfree_rcu((struct cfg80211_bss_ies *)old,
+ rcu_head);
+ }
} else {
+ struct cfg80211_internal_bss *new;
struct cfg80211_internal_bss *hidden;
+ struct cfg80211_bss_ies *ies;
/* First check if the beacon is a probe response from
* a hidden bss. If so, copy beacon ies (with nullified
@@ -720,14 +742,32 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
/* TODO: The code is not trying to update existing probe
* response bss entries when beacon ies are
* getting changed. */
- hidden = rb_find_hidden_bss(dev, res);
+ hidden = rb_find_hidden_bss(dev, tmp);
if (hidden)
- copy_hidden_ies(res, hidden);
-
- /* this "consumes" the reference */
- list_add_tail(&res->list, &dev->bss_list);
- rb_insert_bss(dev, res);
- found = res;
+ copy_hidden_ies(tmp, hidden);
+
+ /*
+ * create a copy -- the "res" variable that is passed in
+ * is allocated on the stack since it's not needed in the
+ * more common case of an update
+ */
+ new = kzalloc(sizeof(*new) + dev->wiphy.bss_priv_size,
+ GFP_ATOMIC);
+ if (!new) {
+ ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
+ if (ies)
+ kfree_rcu(ies, rcu_head);
+ ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
+ if (ies)
+ kfree_rcu(ies, rcu_head);
+ spin_unlock_bh(&dev->bss_lock);
+ return NULL;
+ }
+ memcpy(new, tmp, sizeof(*new));
+ kref_init(&new->ref);
+ list_add_tail(&new->list, &dev->bss_list);
+ rb_insert_bss(dev, new);
+ found = new;
}
dev->bss_generation++;
@@ -737,6 +777,38 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
return found;
}
+static struct ieee80211_channel *
+cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
+ struct ieee80211_channel *channel)
+{
+ const u8 *tmp;
+ u32 freq;
+ int channel_number = -1;
+
+ tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
+ if (tmp && tmp[1] == 1) {
+ channel_number = tmp[2];
+ } else {
+ tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
+ if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
+ struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
+
+ channel_number = htop->primary_chan;
+ }
+ }
+
+ if (channel_number < 0)
+ return channel;
+
+ freq = ieee80211_channel_to_frequency(channel_number, channel->band);
+ channel = ieee80211_get_channel(wiphy, freq);
+ if (!channel)
+ return NULL;
+ if (channel->flags & IEEE80211_CHAN_DISABLED)
+ return NULL;
+ return channel;
+}
+
struct cfg80211_bss*
cfg80211_inform_bss(struct wiphy *wiphy,
struct ieee80211_channel *channel,
@@ -744,54 +816,54 @@ cfg80211_inform_bss(struct wiphy *wiphy,
u16 beacon_interval, const u8 *ie, size_t ielen,
s32 signal, gfp_t gfp)
{
- struct cfg80211_internal_bss *res;
- size_t privsz;
+ struct cfg80211_bss_ies *ies;
+ struct cfg80211_internal_bss tmp = {}, *res;
if (WARN_ON(!wiphy))
return NULL;
- privsz = wiphy->bss_priv_size;
-
if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
(signal < 0 || signal > 100)))
return NULL;
- res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
- if (!res)
+ channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel);
+ if (!channel)
return NULL;
- memcpy(res->pub.bssid, bssid, ETH_ALEN);
- res->pub.channel = channel;
- res->pub.signal = signal;
- res->pub.tsf = tsf;
- res->pub.beacon_interval = beacon_interval;
- res->pub.capability = capability;
+ memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
+ tmp.pub.channel = channel;
+ tmp.pub.signal = signal;
+ tmp.pub.tsf = tsf;
+ tmp.pub.beacon_interval = beacon_interval;
+ tmp.pub.capability = capability;
/*
* Since we do not know here whether the IEs are from a Beacon or Probe
* Response frame, we need to pick one of the options and only use it
* with the driver that does not provide the full Beacon/Probe Response
* frame. Use Beacon frame pointer to avoid indicating that this should
- * override the information_elements pointer should we have received an
- * earlier indication of Probe Response data.
+ * override the iies pointer should we have received an earlier
+ * indication of Probe Response data.
*
* The initial buffer for the IEs is allocated with the BSS entry and
* is located after the private area.
*/
- res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz;
- memcpy(res->pub.beacon_ies, ie, ielen);
- res->pub.len_beacon_ies = ielen;
- res->pub.information_elements = res->pub.beacon_ies;
- res->pub.len_information_elements = res->pub.len_beacon_ies;
+ ies = kmalloc(sizeof(*ies) + ielen, gfp);
+ if (!ies)
+ return NULL;
+ ies->len = ielen;
+ memcpy(ies->data, ie, ielen);
- kref_init(&res->ref);
+ rcu_assign_pointer(tmp.pub.beacon_ies, ies);
+ rcu_assign_pointer(tmp.pub.ies, ies);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
if (!res)
return NULL;
if (res->pub.capability & WLAN_CAPABILITY_ESS)
regulatory_hint_found_beacon(wiphy, channel, gfp);
+ trace_cfg80211_return_bss(&res->pub);
/* cfg80211_bss_update gives us a referenced result */
return &res->pub;
}
@@ -803,10 +875,15 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
struct ieee80211_mgmt *mgmt, size_t len,
s32 signal, gfp_t gfp)
{
- struct cfg80211_internal_bss *res;
+ struct cfg80211_internal_bss tmp = {}, *res;
+ struct cfg80211_bss_ies *ies;
size_t ielen = len - offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
- size_t privsz;
+
+ BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
+ offsetof(struct ieee80211_mgmt, u.beacon.variable));
+
+ trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
if (WARN_ON(!mgmt))
return NULL;
@@ -821,46 +898,38 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
return NULL;
- privsz = wiphy->bss_priv_size;
-
- res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
- if (!res)
+ channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
+ ielen, channel);
+ if (!channel)
return NULL;
- memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN);
- res->pub.channel = channel;
- res->pub.signal = signal;
- res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
- res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
- res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
- /*
- * The initial buffer for the IEs is allocated with the BSS entry and
- * is located after the private area.
- */
- if (ieee80211_is_probe_resp(mgmt->frame_control)) {
- res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz;
- memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable,
- ielen);
- res->pub.len_proberesp_ies = ielen;
- res->pub.information_elements = res->pub.proberesp_ies;
- res->pub.len_information_elements = res->pub.len_proberesp_ies;
- } else {
- res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
- memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
- res->pub.len_beacon_ies = ielen;
- res->pub.information_elements = res->pub.beacon_ies;
- res->pub.len_information_elements = res->pub.len_beacon_ies;
- }
-
- kref_init(&res->ref);
+ ies = kmalloc(sizeof(*ies) + ielen, gfp);
+ if (!ies)
+ return NULL;
+ ies->len = ielen;
+ memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
- res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
+ if (ieee80211_is_probe_resp(mgmt->frame_control))
+ rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
+ else
+ rcu_assign_pointer(tmp.pub.beacon_ies, ies);
+ rcu_assign_pointer(tmp.pub.ies, ies);
+
+ memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
+ tmp.pub.channel = channel;
+ tmp.pub.signal = signal;
+ tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
+ tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
+ tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
+
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
if (!res)
return NULL;
if (res->pub.capability & WLAN_CAPABILITY_ESS)
regulatory_hint_found_beacon(wiphy, channel, gfp);
+ trace_cfg80211_return_bss(&res->pub);
/* cfg80211_bss_update gives us a referenced result */
return &res->pub;
}
@@ -962,6 +1031,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
creq->ssids = (void *)&creq->channels[n_channels];
creq->n_channels = n_channels;
creq->n_ssids = 1;
+ creq->scan_start = jiffies;
/* translate "Scan on frequencies" request */
i = 0;
@@ -1026,7 +1096,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
rdev->scan_req = creq;
- err = rdev->ops->scan(wiphy, creq);
+ err = rdev_scan(rdev, creq);
if (err) {
rdev->scan_req = NULL;
/* creq will be freed below */
@@ -1044,22 +1114,21 @@ int cfg80211_wext_siwscan(struct net_device *dev,
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
static void ieee80211_scan_add_ies(struct iw_request_info *info,
- struct cfg80211_bss *bss,
+ const struct cfg80211_bss_ies *ies,
char **current_ev, char *end_buf)
{
- u8 *pos, *end, *next;
+ const u8 *pos, *end, *next;
struct iw_event iwe;
- if (!bss->information_elements ||
- !bss->len_information_elements)
+ if (!ies)
return;
/*
* If needed, fragment the IEs buffer (at IE boundaries) into short
* enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
*/
- pos = bss->information_elements;
- end = pos + bss->len_information_elements;
+ pos = ies->data;
+ end = pos + ies->len;
while (end - pos > IW_GENERIC_IE_MAX) {
next = pos + 2 + pos[1];
@@ -1070,7 +1139,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
iwe.cmd = IWEVGENIE;
iwe.u.data.length = next - pos;
*current_ev = iwe_stream_add_point(info, *current_ev,
- end_buf, &iwe, pos);
+ end_buf, &iwe,
+ (void *)pos);
pos = next;
}
@@ -1080,7 +1150,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
iwe.cmd = IWEVGENIE;
iwe.u.data.length = end - pos;
*current_ev = iwe_stream_add_point(info, *current_ev,
- end_buf, &iwe, pos);
+ end_buf, &iwe,
+ (void *)pos);
}
}
@@ -1099,10 +1170,11 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
struct cfg80211_internal_bss *bss, char *current_ev,
char *end_buf)
{
+ const struct cfg80211_bss_ies *ies;
struct iw_event iwe;
+ const u8 *ie;
u8 *buf, *cfg, *p;
- u8 *ie = bss->pub.information_elements;
- int rem = bss->pub.len_information_elements, i, sig;
+ int rem, i, sig;
bool ismesh = false;
memset(&iwe, 0, sizeof(iwe));
@@ -1167,7 +1239,17 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
&iwe, "");
- while (rem >= 2) {
+ rcu_read_lock();
+ ies = rcu_dereference(bss->pub.ies);
+ if (ies) {
+ rem = ies->len;
+ ie = ies->data;
+ } else {
+ rem = 0;
+ ie = NULL;
+ }
+
+ while (ies && rem >= 2) {
/* invalid data */
if (ie[1] > rem - 2)
break;
@@ -1179,7 +1261,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
iwe.u.data.length = ie[1];
iwe.u.data.flags = 1;
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, ie + 2);
+ &iwe, (u8 *)ie + 2);
break;
case WLAN_EID_MESH_ID:
memset(&iwe, 0, sizeof(iwe));
@@ -1187,7 +1269,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
iwe.u.data.length = ie[1];
iwe.u.data.flags = 1;
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, ie + 2);
+ &iwe, (u8 *)ie + 2);
break;
case WLAN_EID_MESH_CONFIG:
ismesh = true;
@@ -1196,7 +1278,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
buf = kmalloc(50, GFP_ATOMIC);
if (!buf)
break;
- cfg = ie + 2;
+ cfg = (u8 *)ie + 2;
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
sprintf(buf, "Mesh Network Path Selection Protocol ID: "
@@ -1294,7 +1376,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
kfree(buf);
}
- ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf);
+ ieee80211_scan_add_ies(info, ies, &current_ev, end_buf);
+ rcu_read_unlock();
return current_ev;
}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6f39cb808302..f2431e41a373 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -16,6 +16,7 @@
#include <net/rtnetlink.h>
#include "nl80211.h"
#include "reg.h"
+#include "rdev-ops.h"
struct cfg80211_conn {
struct cfg80211_connect_params params;
@@ -138,10 +139,11 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
+ request->scan_start = jiffies;
rdev->scan_req = request;
- err = rdev->ops->scan(wdev->wiphy, request);
+ err = rdev_scan(rdev, request);
if (!err) {
wdev->conn->state = CFG80211_CONN_SCANNING;
nl80211_send_scan_start(rdev, wdev);
@@ -179,7 +181,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
params->ssid, params->ssid_len,
NULL, 0,
params->key, params->key_len,
- params->key_idx);
+ params->key_idx, NULL, 0);
case CFG80211_CONN_ASSOCIATE_NEXT:
BUG_ON(!rdev->ops->assoc);
wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -415,7 +417,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- u8 *country_ie;
+ const u8 *country_ie;
#ifdef CONFIG_CFG80211_WEXT
union iwreq_data wrqu;
#endif
@@ -499,7 +501,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
wdev->sme_state = CFG80211_SME_CONNECTED;
cfg80211_upload_connect_keys(wdev);
- country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+ rcu_read_lock();
+ country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+ if (!country_ie) {
+ rcu_read_unlock();
+ return;
+ }
+
+ country_ie = kmemdup(country_ie, 2 + country_ie[1], GFP_ATOMIC);
+ rcu_read_unlock();
if (!country_ie)
return;
@@ -513,6 +523,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
bss->channel->band,
country_ie + 2,
country_ie[1]);
+ kfree(country_ie);
}
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
@@ -716,7 +727,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
*/
if (rdev->ops->del_key)
for (i = 0; i < 6; i++)
- rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
+ rdev_del_key(rdev, dev, i, false, NULL);
#ifdef CONFIG_CFG80211_WEXT
memset(&wrqu, 0, sizeof(wrqu));
@@ -892,7 +903,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
} else {
wdev->sme_state = CFG80211_SME_CONNECTING;
wdev->connect_keys = connkeys;
- err = rdev->ops->connect(&rdev->wiphy, dev, connect);
+ err = rdev_connect(rdev, dev, connect);
if (err) {
wdev->connect_keys = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
@@ -964,7 +975,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
if (err)
return err;
} else {
- err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
+ err = rdev_disconnect(rdev, dev, reason);
if (err)
return err;
}
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index ff574597a854..9bf6d5e32166 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -16,6 +16,7 @@
#include <net/cfg80211.h>
#include "sysfs.h"
#include "core.h"
+#include "rdev-ops.h"
static inline struct cfg80211_registered_device *dev_to_rdev(
struct device *dev)
@@ -94,7 +95,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
if (rdev->ops->suspend) {
rtnl_lock();
if (rdev->wiphy.registered)
- ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+ ret = rdev_suspend(rdev);
rtnl_unlock();
}
@@ -114,7 +115,7 @@ static int wiphy_resume(struct device *dev)
if (rdev->ops->resume) {
rtnl_lock();
if (rdev->wiphy.registered)
- ret = rdev->ops->resume(&rdev->wiphy);
+ ret = rdev_resume(rdev);
rtnl_unlock();
}
diff --git a/net/wireless/trace.c b/net/wireless/trace.c
new file mode 100644
index 000000000000..95f997fad755
--- /dev/null
+++ b/net/wireless/trace.c
@@ -0,0 +1,7 @@
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#endif
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
new file mode 100644
index 000000000000..2134576f426e
--- /dev/null
+++ b/net/wireless/trace.h
@@ -0,0 +1,2324 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cfg80211
+
+#if !defined(__RDEV_OPS_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __RDEV_OPS_TRACE
+
+#include <linux/tracepoint.h>
+
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "core.h"
+
+#define MAC_ENTRY(entry_mac) __array(u8, entry_mac, ETH_ALEN)
+#define MAC_ASSIGN(entry_mac, given_mac) do { \
+ if (given_mac) \
+ memcpy(__entry->entry_mac, given_mac, ETH_ALEN); \
+ else \
+ memset(__entry->entry_mac, 0, ETH_ALEN); \
+ } while (0)
+#define MAC_PR_FMT "%pM"
+#define MAC_PR_ARG(entry_mac) (__entry->entry_mac)
+
+#define MAXNAME 32
+#define WIPHY_ENTRY __array(char, wiphy_name, 32)
+#define WIPHY_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(wiphy), MAXNAME)
+#define WIPHY_PR_FMT "%s"
+#define WIPHY_PR_ARG __entry->wiphy_name
+
+#define WDEV_ENTRY __field(u32, id)
+#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0)
+#define WDEV_PR_FMT "wdev(%u)"
+#define WDEV_PR_ARG (__entry->id)
+
+#define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \
+ __field(int, ifindex)
+#define NETDEV_ASSIGN \
+ do { \
+ memcpy(__entry->name, netdev->name, IFNAMSIZ); \
+ (__entry->ifindex) = (netdev->ifindex); \
+ } while (0)
+#define NETDEV_PR_FMT "netdev:%s(%d)"
+#define NETDEV_PR_ARG __entry->name, __entry->ifindex
+
+#define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \
+ __field(u16, dot11MeshConfirmTimeout) \
+ __field(u16, dot11MeshHoldingTimeout) \
+ __field(u16, dot11MeshMaxPeerLinks) \
+ __field(u8, dot11MeshMaxRetries) \
+ __field(u8, dot11MeshTTL) \
+ __field(u8, element_ttl) \
+ __field(bool, auto_open_plinks) \
+ __field(u32, dot11MeshNbrOffsetMaxNeighbor) \
+ __field(u8, dot11MeshHWMPmaxPREQretries) \
+ __field(u32, path_refresh_time) \
+ __field(u32, dot11MeshHWMPactivePathTimeout) \
+ __field(u16, min_discovery_timeout) \
+ __field(u16, dot11MeshHWMPpreqMinInterval) \
+ __field(u16, dot11MeshHWMPperrMinInterval) \
+ __field(u16, dot11MeshHWMPnetDiameterTraversalTime) \
+ __field(u8, dot11MeshHWMPRootMode) \
+ __field(u16, dot11MeshHWMPRannInterval) \
+ __field(bool, dot11MeshGateAnnouncementProtocol) \
+ __field(bool, dot11MeshForwarding) \
+ __field(s32, rssi_threshold) \
+ __field(u16, ht_opmode) \
+ __field(u32, dot11MeshHWMPactivePathToRootTimeout) \
+ __field(u16, dot11MeshHWMProotInterval) \
+ __field(u16, dot11MeshHWMPconfirmationInterval)
+#define MESH_CFG_ASSIGN \
+ do { \
+ __entry->dot11MeshRetryTimeout = conf->dot11MeshRetryTimeout; \
+ __entry->dot11MeshConfirmTimeout = \
+ conf->dot11MeshConfirmTimeout; \
+ __entry->dot11MeshHoldingTimeout = \
+ conf->dot11MeshHoldingTimeout; \
+ __entry->dot11MeshMaxPeerLinks = conf->dot11MeshMaxPeerLinks; \
+ __entry->dot11MeshMaxRetries = conf->dot11MeshMaxRetries; \
+ __entry->dot11MeshTTL = conf->dot11MeshTTL; \
+ __entry->element_ttl = conf->element_ttl; \
+ __entry->auto_open_plinks = conf->auto_open_plinks; \
+ __entry->dot11MeshNbrOffsetMaxNeighbor = \
+ conf->dot11MeshNbrOffsetMaxNeighbor; \
+ __entry->dot11MeshHWMPmaxPREQretries = \
+ conf->dot11MeshHWMPmaxPREQretries; \
+ __entry->path_refresh_time = conf->path_refresh_time; \
+ __entry->dot11MeshHWMPactivePathTimeout = \
+ conf->dot11MeshHWMPactivePathTimeout; \
+ __entry->min_discovery_timeout = conf->min_discovery_timeout; \
+ __entry->dot11MeshHWMPpreqMinInterval = \
+ conf->dot11MeshHWMPpreqMinInterval; \
+ __entry->dot11MeshHWMPperrMinInterval = \
+ conf->dot11MeshHWMPperrMinInterval; \
+ __entry->dot11MeshHWMPnetDiameterTraversalTime = \
+ conf->dot11MeshHWMPnetDiameterTraversalTime; \
+ __entry->dot11MeshHWMPRootMode = conf->dot11MeshHWMPRootMode; \
+ __entry->dot11MeshHWMPRannInterval = \
+ conf->dot11MeshHWMPRannInterval; \
+ __entry->dot11MeshGateAnnouncementProtocol = \
+ conf->dot11MeshGateAnnouncementProtocol; \
+ __entry->dot11MeshForwarding = conf->dot11MeshForwarding; \
+ __entry->rssi_threshold = conf->rssi_threshold; \
+ __entry->ht_opmode = conf->ht_opmode; \
+ __entry->dot11MeshHWMPactivePathToRootTimeout = \
+ conf->dot11MeshHWMPactivePathToRootTimeout; \
+ __entry->dot11MeshHWMProotInterval = \
+ conf->dot11MeshHWMProotInterval; \
+ __entry->dot11MeshHWMPconfirmationInterval = \
+ conf->dot11MeshHWMPconfirmationInterval; \
+ } while (0)
+
+#define CHAN_ENTRY __field(enum ieee80211_band, band) \
+ __field(u16, center_freq)
+#define CHAN_ASSIGN(chan) \
+ do { \
+ if (chan) { \
+ __entry->band = chan->band; \
+ __entry->center_freq = chan->center_freq; \
+ } else { \
+ __entry->band = 0; \
+ __entry->center_freq = 0; \
+ } \
+ } while (0)
+#define CHAN_PR_FMT "band: %d, freq: %u"
+#define CHAN_PR_ARG __entry->band, __entry->center_freq
+
+#define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \
+ __field(u32, control_freq) \
+ __field(u32, width) \
+ __field(u32, center_freq1) \
+ __field(u32, center_freq2)
+#define CHAN_DEF_ASSIGN(chandef) \
+ do { \
+ if ((chandef) && (chandef)->chan) { \
+ __entry->band = (chandef)->chan->band; \
+ __entry->control_freq = \
+ (chandef)->chan->center_freq; \
+ __entry->width = (chandef)->width; \
+ __entry->center_freq1 = (chandef)->center_freq1;\
+ __entry->center_freq2 = (chandef)->center_freq2;\
+ } else { \
+ __entry->band = 0; \
+ __entry->control_freq = 0; \
+ __entry->width = 0; \
+ __entry->center_freq1 = 0; \
+ __entry->center_freq2 = 0; \
+ } \
+ } while (0)
+#define CHAN_DEF_PR_FMT \
+ "band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u"
+#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \
+ __entry->width, __entry->center_freq1, \
+ __entry->center_freq2
+
+#define SINFO_ENTRY __field(int, generation) \
+ __field(u32, connected_time) \
+ __field(u32, inactive_time) \
+ __field(u32, rx_bytes) \
+ __field(u32, tx_bytes) \
+ __field(u32, rx_packets) \
+ __field(u32, tx_packets) \
+ __field(u32, tx_retries) \
+ __field(u32, tx_failed) \
+ __field(u32, rx_dropped_misc) \
+ __field(u32, beacon_loss_count) \
+ __field(u16, llid) \
+ __field(u16, plid) \
+ __field(u8, plink_state)
+#define SINFO_ASSIGN \
+ do { \
+ __entry->generation = sinfo->generation; \
+ __entry->connected_time = sinfo->connected_time; \
+ __entry->inactive_time = sinfo->inactive_time; \
+ __entry->rx_bytes = sinfo->rx_bytes; \
+ __entry->tx_bytes = sinfo->tx_bytes; \
+ __entry->rx_packets = sinfo->rx_packets; \
+ __entry->tx_packets = sinfo->tx_packets; \
+ __entry->tx_retries = sinfo->tx_retries; \
+ __entry->tx_failed = sinfo->tx_failed; \
+ __entry->rx_dropped_misc = sinfo->rx_dropped_misc; \
+ __entry->beacon_loss_count = sinfo->beacon_loss_count; \
+ __entry->llid = sinfo->llid; \
+ __entry->plid = sinfo->plid; \
+ __entry->plink_state = sinfo->plink_state; \
+ } while (0)
+
+#define BOOL_TO_STR(bo) (bo) ? "true" : "false"
+
+/*************************************************************
+ * rdev->ops traces *
+ *************************************************************/
+
+TRACE_EVENT(rdev_suspend,
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_wowlan *wow),
+ TP_ARGS(wiphy, wow),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(bool, any)
+ __field(bool, disconnect)
+ __field(bool, magic_pkt)
+ __field(bool, gtk_rekey_failure)
+ __field(bool, eap_identity_req)
+ __field(bool, four_way_handshake)
+ __field(bool, rfkill_release)
+ __field(bool, valid_wow)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ if (wow) {
+ __entry->any = wow->any;
+ __entry->disconnect = wow->disconnect;
+ __entry->magic_pkt = wow->magic_pkt;
+ __entry->gtk_rekey_failure = wow->gtk_rekey_failure;
+ __entry->eap_identity_req = wow->eap_identity_req;
+ __entry->four_way_handshake = wow->four_way_handshake;
+ __entry->rfkill_release = wow->rfkill_release;
+ __entry->valid_wow = true;
+ } else {
+ __entry->valid_wow = false;
+ }
+ ),
+ TP_printk(WIPHY_PR_FMT ", wow%s - any: %d, disconnect: %d, "
+ "magic pkt: %d, gtk rekey failure: %d, eap identify req: %d, "
+ "four way handshake: %d, rfkill release: %d.",
+ WIPHY_PR_ARG, __entry->valid_wow ? "" : "(Not configured!)",
+ __entry->any, __entry->disconnect, __entry->magic_pkt,
+ __entry->gtk_rekey_failure, __entry->eap_identity_req,
+ __entry->four_way_handshake, __entry->rfkill_release)
+);
+
+TRACE_EVENT(rdev_return_int,
+ TP_PROTO(struct wiphy *wiphy, int ret),
+ TP_ARGS(wiphy, ret),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->ret = ret;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned: %d", WIPHY_PR_ARG, __entry->ret)
+);
+
+TRACE_EVENT(rdev_scan,
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_scan_request *request),
+ TP_ARGS(wiphy, request),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(wiphy_only_evt,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_resume,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_return_void,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_get_ringparam,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, rdev_rfkill_poll,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DECLARE_EVENT_CLASS(wiphy_enabled_evt,
+ TP_PROTO(struct wiphy *wiphy, bool enabled),
+ TP_ARGS(wiphy, enabled),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(bool, enabled)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->enabled = enabled;
+ ),
+ TP_printk(WIPHY_PR_FMT ", %senabled ",
+ WIPHY_PR_ARG, __entry->enabled ? "" : "not ")
+);
+
+DEFINE_EVENT(wiphy_enabled_evt, rdev_set_wakeup,
+ TP_PROTO(struct wiphy *wiphy, bool enabled),
+ TP_ARGS(wiphy, enabled)
+);
+
+TRACE_EVENT(rdev_add_virtual_intf,
+ TP_PROTO(struct wiphy *wiphy, char *name, enum nl80211_iftype type),
+ TP_ARGS(wiphy, name, type),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __string(vir_intf_name, name ? name : "<noname>")
+ __field(enum nl80211_iftype, type)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __assign_str(vir_intf_name, name ? name : "<noname>");
+ __entry->type = type;
+ ),
+ TP_printk(WIPHY_PR_FMT ", virtual intf name: %s, type: %d",
+ WIPHY_PR_ARG, __get_str(vir_intf_name), __entry->type)
+);
+
+DECLARE_EVENT_CLASS(wiphy_wdev_evt,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_del_virtual_intf,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+TRACE_EVENT(rdev_change_virtual_intf,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ enum nl80211_iftype type),
+ TP_ARGS(wiphy, netdev, type),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(enum nl80211_iftype, type)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->type = type;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", type: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type)
+);
+
+DECLARE_EVENT_CLASS(key_handle,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(mac_addr)
+ __field(u8, key_index)
+ __field(bool, pairwise)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(mac_addr, mac_addr);
+ __entry->key_index = key_index;
+ __entry->pairwise = pairwise;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+ BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
+);
+
+DEFINE_EVENT(key_handle, rdev_add_key,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+DEFINE_EVENT(key_handle, rdev_get_key,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+DEFINE_EVENT(key_handle, rdev_del_key,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+ bool pairwise, const u8 *mac_addr),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+);
+
+TRACE_EVENT(rdev_set_default_key,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
+ bool unicast, bool multicast),
+ TP_ARGS(wiphy, netdev, key_index, unicast, multicast),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u8, key_index)
+ __field(bool, unicast)
+ __field(bool, multicast)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->key_index = key_index;
+ __entry->unicast = unicast;
+ __entry->multicast = multicast;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+ BOOL_TO_STR(__entry->unicast),
+ BOOL_TO_STR(__entry->multicast))
+);
+
+TRACE_EVENT(rdev_set_default_mgmt_key,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index),
+ TP_ARGS(wiphy, netdev, key_index),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u8, key_index)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->key_index = key_index;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
+);
+
+TRACE_EVENT(rdev_start_ap,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_ap_settings *settings),
+ TP_ARGS(wiphy, netdev, settings),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ CHAN_DEF_ENTRY
+ __field(int, beacon_interval)
+ __field(int, dtim_period)
+ __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+ __field(enum nl80211_hidden_ssid, hidden_ssid)
+ __field(u32, wpa_ver)
+ __field(bool, privacy)
+ __field(enum nl80211_auth_type, auth_type)
+ __field(int, inactivity_timeout)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ CHAN_DEF_ASSIGN(&settings->chandef);
+ __entry->beacon_interval = settings->beacon_interval;
+ __entry->dtim_period = settings->dtim_period;
+ __entry->hidden_ssid = settings->hidden_ssid;
+ __entry->wpa_ver = settings->crypto.wpa_versions;
+ __entry->privacy = settings->privacy;
+ __entry->auth_type = settings->auth_type;
+ __entry->inactivity_timeout = settings->inactivity_timeout;
+ memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+ memcpy(__entry->ssid, settings->ssid, settings->ssid_len);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", AP settings - ssid: %s, "
+ CHAN_DEF_PR_FMT ", beacon interval: %d, dtim period: %d, "
+ "hidden ssid: %d, wpa versions: %u, privacy: %s, "
+ "auth type: %d, inactivity timeout: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_DEF_PR_ARG,
+ __entry->beacon_interval, __entry->dtim_period,
+ __entry->hidden_ssid, __entry->wpa_ver,
+ BOOL_TO_STR(__entry->privacy), __entry->auth_type,
+ __entry->inactivity_timeout)
+);
+
+TRACE_EVENT(rdev_change_beacon,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_beacon_data *info),
+ TP_ARGS(wiphy, netdev, info),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __dynamic_array(u8, head, info ? info->head_len : 0)
+ __dynamic_array(u8, tail, info ? info->tail_len : 0)
+ __dynamic_array(u8, beacon_ies, info ? info->beacon_ies_len : 0)
+ __dynamic_array(u8, proberesp_ies,
+ info ? info->proberesp_ies_len : 0)
+ __dynamic_array(u8, assocresp_ies,
+ info ? info->assocresp_ies_len : 0)
+ __dynamic_array(u8, probe_resp, info ? info->probe_resp_len : 0)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ if (info) {
+ if (info->head)
+ memcpy(__get_dynamic_array(head), info->head,
+ info->head_len);
+ if (info->tail)
+ memcpy(__get_dynamic_array(tail), info->tail,
+ info->tail_len);
+ if (info->beacon_ies)
+ memcpy(__get_dynamic_array(beacon_ies),
+ info->beacon_ies, info->beacon_ies_len);
+ if (info->proberesp_ies)
+ memcpy(__get_dynamic_array(proberesp_ies),
+ info->proberesp_ies,
+ info->proberesp_ies_len);
+ if (info->assocresp_ies)
+ memcpy(__get_dynamic_array(assocresp_ies),
+ info->assocresp_ies,
+ info->assocresp_ies_len);
+ if (info->probe_resp)
+ memcpy(__get_dynamic_array(probe_resp),
+ info->probe_resp, info->probe_resp_len);
+ }
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(wiphy_netdev_evt,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_get_et_stats,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_set_rekey_data,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_get_mesh_config,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_mesh,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ibss,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+);
+
+DECLARE_EVENT_CLASS(station_add_change,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+ struct station_parameters *params),
+ TP_ARGS(wiphy, netdev, mac, params),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(sta_mac)
+ __field(u32, sta_flags_mask)
+ __field(u32, sta_flags_set)
+ __field(u32, sta_modify_mask)
+ __field(int, listen_interval)
+ __field(u16, aid)
+ __field(u8, plink_action)
+ __field(u8, plink_state)
+ __field(u8, uapsd_queues)
+ __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap))
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(sta_mac, mac);
+ __entry->sta_flags_mask = params->sta_flags_mask;
+ __entry->sta_flags_set = params->sta_flags_set;
+ __entry->sta_modify_mask = params->sta_modify_mask;
+ __entry->listen_interval = params->listen_interval;
+ __entry->aid = params->aid;
+ __entry->plink_action = params->plink_action;
+ __entry->plink_state = params->plink_state;
+ __entry->uapsd_queues = params->uapsd_queues;
+ memset(__entry->ht_capa, 0, sizeof(struct ieee80211_ht_cap));
+ if (params->ht_capa)
+ memcpy(__entry->ht_capa, params->ht_capa,
+ sizeof(struct ieee80211_ht_cap));
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+ ", station flags mask: %u, station flags set: %u, "
+ "station modify mask: %u, listen interval: %d, aid: %u, "
+ "plink action: %u, plink state: %u, uapsd queues: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+ __entry->sta_flags_mask, __entry->sta_flags_set,
+ __entry->sta_modify_mask, __entry->listen_interval,
+ __entry->aid, __entry->plink_action, __entry->plink_state,
+ __entry->uapsd_queues)
+);
+
+DEFINE_EVENT(station_add_change, rdev_add_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+ struct station_parameters *params),
+ TP_ARGS(wiphy, netdev, mac, params)
+);
+
+DEFINE_EVENT(station_add_change, rdev_change_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
+ struct station_parameters *params),
+ TP_ARGS(wiphy, netdev, mac, params)
+);
+
+DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(sta_mac)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(sta_mac, mac);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_mpath,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac)
+);
+
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_set_wds_peer,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac)
+);
+
+TRACE_EVENT(rdev_dump_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
+ u8 *mac),
+ TP_ARGS(wiphy, netdev, idx, mac),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(sta_mac)
+ __field(int, idx)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(sta_mac, mac);
+ __entry->idx = idx;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+ __entry->idx)
+);
+
+TRACE_EVENT(rdev_return_int_station_info,
+ TP_PROTO(struct wiphy *wiphy, int ret, struct station_info *sinfo),
+ TP_ARGS(wiphy, ret, sinfo),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ SINFO_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->ret = ret;
+ SINFO_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned %d" ,
+ WIPHY_PR_ARG, __entry->ret)
+);
+
+DECLARE_EVENT_CLASS(mpath_evt,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+ u8 *next_hop),
+ TP_ARGS(wiphy, netdev, dst, next_hop),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(dst)
+ MAC_ENTRY(next_hop)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(dst, dst);
+ MAC_ASSIGN(next_hop, next_hop);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst),
+ MAC_PR_ARG(next_hop))
+);
+
+DEFINE_EVENT(mpath_evt, rdev_add_mpath,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+ u8 *next_hop),
+ TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+DEFINE_EVENT(mpath_evt, rdev_change_mpath,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+ u8 *next_hop),
+ TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+DEFINE_EVENT(mpath_evt, rdev_get_mpath,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *dst,
+ u8 *next_hop),
+ TP_ARGS(wiphy, netdev, dst, next_hop)
+);
+
+TRACE_EVENT(rdev_dump_mpath,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
+ u8 *dst, u8 *next_hop),
+ TP_ARGS(wiphy, netdev, idx, dst, next_hop),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(dst)
+ MAC_ENTRY(next_hop)
+ __field(int, idx)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(dst, dst);
+ MAC_ASSIGN(next_hop, next_hop);
+ __entry->idx = idx;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
+ MAC_PR_FMT ", next hop: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
+ MAC_PR_ARG(next_hop))
+);
+
+TRACE_EVENT(rdev_return_int_mpath_info,
+ TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo),
+ TP_ARGS(wiphy, ret, pinfo),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ __field(int, generation)
+ __field(u32, filled)
+ __field(u32, frame_qlen)
+ __field(u32, sn)
+ __field(u32, metric)
+ __field(u32, exptime)
+ __field(u32, discovery_timeout)
+ __field(u8, discovery_retries)
+ __field(u8, flags)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->ret = ret;
+ __entry->generation = pinfo->generation;
+ __entry->filled = pinfo->filled;
+ __entry->frame_qlen = pinfo->frame_qlen;
+ __entry->sn = pinfo->sn;
+ __entry->metric = pinfo->metric;
+ __entry->exptime = pinfo->exptime;
+ __entry->discovery_timeout = pinfo->discovery_timeout;
+ __entry->discovery_retries = pinfo->discovery_retries;
+ __entry->flags = pinfo->flags;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned %d. mpath info - generation: %d, "
+ "filled: %u, frame qlen: %u, sn: %u, metric: %u, exptime: %u,"
+ " discovery timeout: %u, discovery retries: %u, flags: %u",
+ WIPHY_PR_ARG, __entry->ret, __entry->generation,
+ __entry->filled, __entry->frame_qlen, __entry->sn,
+ __entry->metric, __entry->exptime, __entry->discovery_timeout,
+ __entry->discovery_retries, __entry->flags)
+);
+
+TRACE_EVENT(rdev_return_int_mesh_config,
+ TP_PROTO(struct wiphy *wiphy, int ret, struct mesh_config *conf),
+ TP_ARGS(wiphy, ret, conf),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ MESH_CFG_ENTRY
+ __field(int, ret)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ MESH_CFG_ASSIGN;
+ __entry->ret = ret;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned: %d",
+ WIPHY_PR_ARG, __entry->ret)
+);
+
+TRACE_EVENT(rdev_update_mesh_config,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 mask,
+ const struct mesh_config *conf),
+ TP_ARGS(wiphy, netdev, mask, conf),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MESH_CFG_ENTRY
+ __field(u32, mask)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MESH_CFG_ASSIGN;
+ __entry->mask = mask;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mask: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask)
+);
+
+TRACE_EVENT(rdev_join_mesh,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ const struct mesh_config *conf,
+ const struct mesh_setup *setup),
+ TP_ARGS(wiphy, netdev, conf, setup),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MESH_CFG_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MESH_CFG_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+TRACE_EVENT(rdev_change_bss,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct bss_parameters *params),
+ TP_ARGS(wiphy, netdev, params),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(int, use_cts_prot)
+ __field(int, use_short_preamble)
+ __field(int, use_short_slot_time)
+ __field(int, ap_isolate)
+ __field(int, ht_opmode)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->use_cts_prot = params->use_cts_prot;
+ __entry->use_short_preamble = params->use_short_preamble;
+ __entry->use_short_slot_time = params->use_short_slot_time;
+ __entry->ap_isolate = params->ap_isolate;
+ __entry->ht_opmode = params->ht_opmode;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", use cts prot: %d, "
+ "use short preamble: %d, use short slot time: %d, "
+ "ap isolate: %d, ht opmode: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot,
+ __entry->use_short_preamble, __entry->use_short_slot_time,
+ __entry->ap_isolate, __entry->ht_opmode)
+);
+
+TRACE_EVENT(rdev_set_txq_params,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct ieee80211_txq_params *params),
+ TP_ARGS(wiphy, netdev, params),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(enum nl80211_ac, ac)
+ __field(u16, txop)
+ __field(u16, cwmin)
+ __field(u16, cwmax)
+ __field(u8, aifs)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->ac = params->ac;
+ __entry->txop = params->txop;
+ __entry->cwmin = params->cwmin;
+ __entry->cwmax = params->cwmax;
+ __entry->aifs = params->aifs;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop,
+ __entry->cwmin, __entry->cwmax, __entry->aifs)
+);
+
+TRACE_EVENT(rdev_libertas_set_mesh_channel,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct ieee80211_channel *chan),
+ TP_ARGS(wiphy, netdev, chan),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ CHAN_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ CHAN_ASSIGN(chan);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_PR_FMT, WIPHY_PR_ARG,
+ NETDEV_PR_ARG, CHAN_PR_ARG)
+);
+
+TRACE_EVENT(rdev_set_monitor_channel,
+ TP_PROTO(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef),
+ TP_ARGS(wiphy, chandef),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_DEF_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+);
+
+TRACE_EVENT(rdev_auth,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_auth_request *req),
+ TP_ARGS(wiphy, netdev, req),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __field(enum nl80211_auth_type, auth_type)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ if (req->bss)
+ MAC_ASSIGN(bssid, req->bss->bssid);
+ else
+ memset(__entry->bssid, 0, ETH_ALEN);
+ __entry->auth_type = req->auth_type;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type,
+ MAC_PR_ARG(bssid))
+);
+
+TRACE_EVENT(rdev_assoc,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_assoc_request *req),
+ TP_ARGS(wiphy, netdev, req),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ MAC_ENTRY(prev_bssid)
+ __field(bool, use_mfp)
+ __field(u32, flags)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ if (req->bss)
+ MAC_ASSIGN(bssid, req->bss->bssid);
+ else
+ memset(__entry->bssid, 0, ETH_ALEN);
+ MAC_ASSIGN(prev_bssid, req->prev_bssid);
+ __entry->use_mfp = req->use_mfp;
+ __entry->flags = req->flags;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+ MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp),
+ __entry->flags)
+);
+
+TRACE_EVENT(rdev_deauth,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_deauth_request *req),
+ TP_ARGS(wiphy, netdev, req),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __field(u16, reason_code)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, req->bssid);
+ __entry->reason_code = req->reason_code;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+ __entry->reason_code)
+);
+
+TRACE_EVENT(rdev_disassoc,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_disassoc_request *req),
+ TP_ARGS(wiphy, netdev, req),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __field(u16, reason_code)
+ __field(bool, local_state_change)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ if (req->bss)
+ MAC_ASSIGN(bssid, req->bss->bssid);
+ else
+ memset(__entry->bssid, 0, ETH_ALEN);
+ __entry->reason_code = req->reason_code;
+ __entry->local_state_change = req->local_state_change;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ ", reason: %u, local state change: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+ __entry->reason_code,
+ BOOL_TO_STR(__entry->local_state_change))
+);
+
+TRACE_EVENT(rdev_mgmt_tx_cancel_wait,
+ TP_PROTO(struct wiphy *wiphy,
+ struct wireless_dev *wdev, u64 cookie),
+ TP_ARGS(wiphy, wdev, cookie),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u64, cookie)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu ",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
+);
+
+TRACE_EVENT(rdev_set_power_mgmt,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ bool enabled, int timeout),
+ TP_ARGS(wiphy, netdev, enabled, timeout),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(bool, enabled)
+ __field(int, timeout)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->enabled = enabled;
+ __entry->timeout = timeout;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %senabled, timeout: %d ",
+ WIPHY_PR_ARG, NETDEV_PR_ARG,
+ __entry->enabled ? "" : "not ", __entry->timeout)
+);
+
+TRACE_EVENT(rdev_connect,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_connect_params *sme),
+ TP_ARGS(wiphy, netdev, sme),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+ __field(enum nl80211_auth_type, auth_type)
+ __field(bool, privacy)
+ __field(u32, wpa_versions)
+ __field(u32, flags)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, sme->bssid);
+ memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+ memcpy(__entry->ssid, sme->ssid, sme->ssid_len);
+ __entry->auth_type = sme->auth_type;
+ __entry->privacy = sme->privacy;
+ __entry->wpa_versions = sme->crypto.wpa_versions;
+ __entry->flags = sme->flags;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, "
+ "flags: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid,
+ __entry->auth_type, BOOL_TO_STR(__entry->privacy),
+ __entry->wpa_versions, __entry->flags)
+);
+
+TRACE_EVENT(rdev_set_cqm_rssi_config,
+ TP_PROTO(struct wiphy *wiphy,
+ struct net_device *netdev, s32 rssi_thold,
+ u32 rssi_hyst),
+ TP_ARGS(wiphy, netdev, rssi_thold, rssi_hyst),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(s32, rssi_thold)
+ __field(u32, rssi_hyst)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->rssi_thold = rssi_thold;
+ __entry->rssi_hyst = rssi_hyst;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
+ ", rssi_thold: %d, rssi_hyst: %u ",
+ WIPHY_PR_ARG, NETDEV_PR_ARG,
+ __entry->rssi_thold, __entry->rssi_hyst)
+);
+
+TRACE_EVENT(rdev_set_cqm_txe_config,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate,
+ u32 pkts, u32 intvl),
+ TP_ARGS(wiphy, netdev, rate, pkts, intvl),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u32, rate)
+ __field(u32, pkts)
+ __field(u32, intvl)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->rate = rate;
+ __entry->pkts = pkts;
+ __entry->intvl = intvl;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts,
+ __entry->intvl)
+);
+
+TRACE_EVENT(rdev_disconnect,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ u16 reason_code),
+ TP_ARGS(wiphy, netdev, reason_code),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u16, reason_code)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->reason_code = reason_code;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG,
+ NETDEV_PR_ARG, __entry->reason_code)
+);
+
+TRACE_EVENT(rdev_join_ibss,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_ibss_params *params),
+ TP_ARGS(wiphy, netdev, params),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, params->bssid);
+ memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+ memcpy(__entry->ssid, params->ssid, params->ssid_len);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
+);
+
+TRACE_EVENT(rdev_set_wiphy_params,
+ TP_PROTO(struct wiphy *wiphy, u32 changed),
+ TP_ARGS(wiphy, changed),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(u32, changed)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->changed = changed;
+ ),
+ TP_printk(WIPHY_PR_FMT ", changed: %u",
+ WIPHY_PR_ARG, __entry->changed)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_get_tx_power,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+TRACE_EVENT(rdev_set_tx_power,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, int mbm),
+ TP_ARGS(wiphy, wdev, type, mbm),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(enum nl80211_tx_power_setting, type)
+ __field(int, mbm)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->type = type;
+ __entry->mbm = mbm;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d",
+ WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm)
+);
+
+TRACE_EVENT(rdev_return_int_int,
+ TP_PROTO(struct wiphy *wiphy, int func_ret, int func_fill),
+ TP_ARGS(wiphy, func_ret, func_fill),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, func_ret)
+ __field(int, func_fill)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->func_ret = func_ret;
+ __entry->func_fill = func_fill;
+ ),
+ TP_printk(WIPHY_PR_FMT ", function returns: %d, function filled: %d",
+ WIPHY_PR_ARG, __entry->func_ret, __entry->func_fill)
+);
+
+#ifdef CONFIG_NL80211_TESTMODE
+TRACE_EVENT(rdev_testmode_cmd,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+
+TRACE_EVENT(rdev_testmode_dump,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
+);
+#endif /* CONFIG_NL80211_TESTMODE */
+
+TRACE_EVENT(rdev_set_bitrate_mask,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ const u8 *peer, const struct cfg80211_bitrate_mask *mask),
+ TP_ARGS(wiphy, netdev, peer, mask),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
+TRACE_EVENT(rdev_mgmt_frame_register,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ u16 frame_type, bool reg),
+ TP_ARGS(wiphy, wdev, frame_type, reg),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u16, frame_type)
+ __field(bool, reg)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->frame_type = frame_type;
+ __entry->reg = reg;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,
+ __entry->reg ? "true" : "false")
+);
+
+TRACE_EVENT(rdev_return_int_tx_rx,
+ TP_PROTO(struct wiphy *wiphy, int ret, u32 tx, u32 rx),
+ TP_ARGS(wiphy, ret, tx, rx),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ __field(u32, tx)
+ __field(u32, rx)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->ret = ret;
+ __entry->tx = tx;
+ __entry->rx = rx;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned %d, tx: %u, rx: %u",
+ WIPHY_PR_ARG, __entry->ret, __entry->tx, __entry->rx)
+);
+
+TRACE_EVENT(rdev_return_void_tx_rx,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 tx_max,
+ u32 rx, u32 rx_max),
+ TP_ARGS(wiphy, tx, tx_max, rx, rx_max),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(u32, tx)
+ __field(u32, tx_max)
+ __field(u32, rx)
+ __field(u32, rx_max)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->tx = tx;
+ __entry->tx_max = tx_max;
+ __entry->rx = rx;
+ __entry->rx_max = rx_max;
+ ),
+ TP_printk(WIPHY_PR_FMT ", tx: %u, tx_max: %u, rx: %u, rx_max: %u ",
+ WIPHY_PR_ARG, __entry->tx, __entry->tx_max, __entry->rx,
+ __entry->rx_max)
+);
+
+DECLARE_EVENT_CLASS(tx_rx_evt,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+ TP_ARGS(wiphy, rx, tx),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(u32, tx)
+ __field(u32, rx)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->tx = tx;
+ __entry->rx = rx;
+ ),
+ TP_printk(WIPHY_PR_FMT ", tx: %u, rx: %u ",
+ WIPHY_PR_ARG, __entry->tx, __entry->rx)
+);
+
+DEFINE_EVENT(tx_rx_evt, rdev_set_ringparam,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+ TP_ARGS(wiphy, rx, tx)
+);
+
+DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+ TP_ARGS(wiphy, rx, tx)
+);
+
+TRACE_EVENT(rdev_sched_scan_start,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_sched_scan_request *request),
+ TP_ARGS(wiphy, netdev, request),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
+TRACE_EVENT(rdev_tdls_mgmt,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ u8 *peer, u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf, size_t len),
+ TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code,
+ buf, len),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ __field(u8, action_code)
+ __field(u8, dialog_token)
+ __field(u16, status_code)
+ __dynamic_array(u8, buf, len)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ __entry->action_code = action_code;
+ __entry->dialog_token = dialog_token;
+ __entry->status_code = status_code;
+ memcpy(__get_dynamic_array(buf), buf, len);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, "
+ "dialog_token: %u, status_code: %u, buf: %#.2x ",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ __entry->action_code, __entry->dialog_token,
+ __entry->status_code, ((u8 *)__get_dynamic_array(buf))[0])
+);
+
+TRACE_EVENT(rdev_dump_survey,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx),
+ TP_ARGS(wiphy, netdev, idx),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(int, idx)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->idx = idx;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx)
+);
+
+TRACE_EVENT(rdev_return_int_survey_info,
+ TP_PROTO(struct wiphy *wiphy, int ret, struct survey_info *info),
+ TP_ARGS(wiphy, ret, info),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_ENTRY
+ __field(int, ret)
+ __field(u64, channel_time)
+ __field(u64, channel_time_busy)
+ __field(u64, channel_time_ext_busy)
+ __field(u64, channel_time_rx)
+ __field(u64, channel_time_tx)
+ __field(u32, filled)
+ __field(s8, noise)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_ASSIGN(info->channel);
+ __entry->ret = ret;
+ __entry->channel_time = info->channel_time;
+ __entry->channel_time_busy = info->channel_time_busy;
+ __entry->channel_time_ext_busy = info->channel_time_ext_busy;
+ __entry->channel_time_rx = info->channel_time_rx;
+ __entry->channel_time_tx = info->channel_time_tx;
+ __entry->filled = info->filled;
+ __entry->noise = info->noise;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT
+ ", channel time: %llu, channel time busy: %llu, "
+ "channel time extension busy: %llu, channel time rx: %llu, "
+ "channel time tx: %llu, filled: %u, noise: %d",
+ WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG,
+ __entry->channel_time, __entry->channel_time_busy,
+ __entry->channel_time_ext_busy, __entry->channel_time_rx,
+ __entry->channel_time_tx, __entry->filled, __entry->noise)
+);
+
+TRACE_EVENT(rdev_tdls_oper,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ u8 *peer, enum nl80211_tdls_operation oper),
+ TP_ARGS(wiphy, netdev, peer, oper),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ __field(enum nl80211_tdls_operation, oper)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ __entry->oper = oper;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", oper: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper)
+);
+
+DECLARE_EVENT_CLASS(rdev_pmksa,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa),
+ TP_ARGS(wiphy, netdev, pmksa),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, pmksa->bssid);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid))
+);
+
+TRACE_EVENT(rdev_probe_client,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ const u8 *peer),
+ TP_ARGS(wiphy, netdev, peer),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
+DEFINE_EVENT(rdev_pmksa, rdev_set_pmksa,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa),
+ TP_ARGS(wiphy, netdev, pmksa)
+);
+
+DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa),
+ TP_ARGS(wiphy, netdev, pmksa)
+);
+
+TRACE_EVENT(rdev_remain_on_channel,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct ieee80211_channel *chan,
+ unsigned int duration),
+ TP_ARGS(wiphy, wdev, chan, duration),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ CHAN_ENTRY
+ __field(unsigned int, duration)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ CHAN_ASSIGN(chan);
+ __entry->duration = duration;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u",
+ WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration)
+);
+
+TRACE_EVENT(rdev_return_int_cookie,
+ TP_PROTO(struct wiphy *wiphy, int ret, u64 cookie),
+ TP_ARGS(wiphy, ret, cookie),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ __field(u64, cookie)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->ret = ret;
+ __entry->cookie = cookie;
+ ),
+ TP_printk(WIPHY_PR_FMT ", returned %d, cookie: %llu",
+ WIPHY_PR_ARG, __entry->ret, __entry->cookie)
+);
+
+TRACE_EVENT(rdev_cancel_remain_on_channel,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
+ TP_ARGS(wiphy, wdev, cookie),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u64, cookie)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
+);
+
+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),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ CHAN_ENTRY
+ __field(bool, offchan)
+ __field(unsigned int, wait)
+ __field(bool, no_cck)
+ __field(bool, dont_wait_for_ack)
+ ),
+ 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;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
+ " wait: %u, no cck: %s, dont wait for ack: %s",
+ WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG,
+ BOOL_TO_STR(__entry->offchan), __entry->wait,
+ BOOL_TO_STR(__entry->no_cck),
+ BOOL_TO_STR(__entry->dont_wait_for_ack))
+);
+
+TRACE_EVENT(rdev_set_noack_map,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ u16 noack_map),
+ TP_ARGS(wiphy, netdev, noack_map),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u16, noack_map)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->noack_map = noack_map;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", noack_map: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
+);
+
+TRACE_EVENT(rdev_get_et_sset_count,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int sset),
+ TP_ARGS(wiphy, netdev, sset),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(int, sset)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->sset = sset;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+);
+
+TRACE_EVENT(rdev_get_et_strings,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 sset),
+ TP_ARGS(wiphy, netdev, sset),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ __field(u32, sset)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ __entry->sset = sset;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+TRACE_EVENT(rdev_return_chandef,
+ TP_PROTO(struct wiphy *wiphy, int ret,
+ struct cfg80211_chan_def *chandef),
+ TP_ARGS(wiphy, ret, chandef),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, ret)
+ CHAN_DEF_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ if (ret == 0)
+ CHAN_DEF_ASSIGN(chandef);
+ else
+ CHAN_DEF_ASSIGN((struct cfg80211_chan_def *)NULL);
+ __entry->ret = ret;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", ret: %d",
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->ret)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_p2p_device,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+/*************************************************************
+ * cfg80211 exported functions traces *
+ *************************************************************/
+
+TRACE_EVENT(cfg80211_return_bool,
+ TP_PROTO(bool ret),
+ TP_ARGS(ret),
+ TP_STRUCT__entry(
+ __field(bool, ret)
+ ),
+ TP_fast_assign(
+ __entry->ret = ret;
+ ),
+ TP_printk("returned %s", BOOL_TO_STR(__entry->ret))
+);
+
+DECLARE_EVENT_CLASS(cfg80211_netdev_mac_evt,
+ TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+ TP_ARGS(netdev, macaddr),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(macaddr)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(macaddr, macaddr);
+ ),
+ TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+ NETDEV_PR_ARG, MAC_PR_ARG(macaddr))
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_notify_new_peer_candidate,
+ TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+ TP_ARGS(netdev, macaddr)
+);
+
+DECLARE_EVENT_CLASS(netdev_evt_only,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ ),
+ TP_printk(NETDEV_PR_FMT , NETDEV_PR_ARG)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_rx_auth,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev)
+);
+
+TRACE_EVENT(cfg80211_send_rx_assoc,
+ TP_PROTO(struct net_device *netdev, struct cfg80211_bss *bss),
+ TP_ARGS(netdev, bss),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ CHAN_ENTRY
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, bss->bssid);
+ CHAN_ASSIGN(bss->channel);
+ ),
+ TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", " CHAN_PR_FMT,
+ NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+);
+
+DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_deauth,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev)
+);
+
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_disassoc,
+ TP_PROTO(struct net_device *netdev),
+ TP_ARGS(netdev)
+);
+
+DECLARE_EVENT_CLASS(netdev_mac_evt,
+ TP_PROTO(struct net_device *netdev, const u8 *mac),
+ TP_ARGS(netdev, mac),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(mac)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(mac, mac)
+ ),
+ TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
+ NETDEV_PR_ARG, MAC_PR_ARG(mac))
+);
+
+DEFINE_EVENT(netdev_mac_evt, cfg80211_send_auth_timeout,
+ TP_PROTO(struct net_device *netdev, const u8 *mac),
+ TP_ARGS(netdev, mac)
+);
+
+DEFINE_EVENT(netdev_mac_evt, cfg80211_send_assoc_timeout,
+ TP_PROTO(struct net_device *netdev, const u8 *mac),
+ TP_ARGS(netdev, mac)
+);
+
+TRACE_EVENT(cfg80211_michael_mic_failure,
+ TP_PROTO(struct net_device *netdev, const u8 *addr,
+ enum nl80211_key_type key_type, int key_id, const u8 *tsc),
+ TP_ARGS(netdev, addr, key_type, key_id, tsc),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(addr)
+ __field(enum nl80211_key_type, key_type)
+ __field(int, key_id)
+ __array(u8, tsc, 6)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(addr, addr);
+ __entry->key_type = key_type;
+ __entry->key_id = key_id;
+ memcpy(__entry->tsc, tsc, 6);
+ ),
+ TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm",
+ NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type,
+ __entry->key_id, __entry->tsc)
+);
+
+TRACE_EVENT(cfg80211_ready_on_channel,
+ TP_PROTO(struct wireless_dev *wdev, u64 cookie,
+ struct ieee80211_channel *chan,
+ unsigned int duration),
+ TP_ARGS(wdev, cookie, chan, duration),
+ TP_STRUCT__entry(
+ WDEV_ENTRY
+ __field(u64, cookie)
+ CHAN_ENTRY
+ __field(unsigned int, duration)
+ ),
+ TP_fast_assign(
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ CHAN_ASSIGN(chan);
+ __entry->duration = duration;
+ ),
+ TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", duration: %u",
+ WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG,
+ __entry->duration)
+);
+
+TRACE_EVENT(cfg80211_ready_on_channel_expired,
+ TP_PROTO(struct wireless_dev *wdev, u64 cookie,
+ struct ieee80211_channel *chan),
+ TP_ARGS(wdev, cookie, chan),
+ TP_STRUCT__entry(
+ WDEV_ENTRY
+ __field(u64, cookie)
+ CHAN_ENTRY
+ ),
+ TP_fast_assign(
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ CHAN_ASSIGN(chan);
+ ),
+ TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT,
+ WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG)
+);
+
+TRACE_EVENT(cfg80211_new_sta,
+ TP_PROTO(struct net_device *netdev, const u8 *mac_addr,
+ struct station_info *sinfo),
+ TP_ARGS(netdev, mac_addr, sinfo),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(mac_addr)
+ SINFO_ENTRY
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(mac_addr, mac_addr);
+ SINFO_ASSIGN;
+ ),
+ TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT,
+ NETDEV_PR_ARG, MAC_PR_ARG(mac_addr))
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_del_sta,
+ TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+ TP_ARGS(netdev, macaddr)
+);
+
+TRACE_EVENT(cfg80211_rx_mgmt,
+ TP_PROTO(struct wireless_dev *wdev, int freq, int sig_mbm),
+ TP_ARGS(wdev, freq, sig_mbm),
+ TP_STRUCT__entry(
+ WDEV_ENTRY
+ __field(int, freq)
+ __field(int, sig_mbm)
+ ),
+ TP_fast_assign(
+ WDEV_ASSIGN;
+ __entry->freq = freq;
+ __entry->sig_mbm = sig_mbm;
+ ),
+ TP_printk(WDEV_PR_FMT ", freq: %d, sig mbm: %d",
+ WDEV_PR_ARG, __entry->freq, __entry->sig_mbm)
+);
+
+TRACE_EVENT(cfg80211_mgmt_tx_status,
+ TP_PROTO(struct wireless_dev *wdev, u64 cookie, bool ack),
+ TP_ARGS(wdev, cookie, ack),
+ TP_STRUCT__entry(
+ WDEV_ENTRY
+ __field(u64, cookie)
+ __field(bool, ack)
+ ),
+ TP_fast_assign(
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ __entry->ack = ack;
+ ),
+ TP_printk(WDEV_PR_FMT", cookie: %llu, ack: %s",
+ WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
+);
+
+TRACE_EVENT(cfg80211_cqm_rssi_notify,
+ TP_PROTO(struct net_device *netdev,
+ enum nl80211_cqm_rssi_threshold_event rssi_event),
+ TP_ARGS(netdev, rssi_event),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ __field(enum nl80211_cqm_rssi_threshold_event, rssi_event)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ __entry->rssi_event = rssi_event;
+ ),
+ TP_printk(NETDEV_PR_FMT ", rssi event: %d",
+ NETDEV_PR_ARG, __entry->rssi_event)
+);
+
+TRACE_EVENT(cfg80211_reg_can_beacon,
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
+ TP_ARGS(wiphy, chandef),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_DEF_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+);
+
+TRACE_EVENT(cfg80211_ch_switch_notify,
+ TP_PROTO(struct net_device *netdev,
+ struct cfg80211_chan_def *chandef),
+ TP_ARGS(netdev, chandef),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ CHAN_DEF_ENTRY
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ ),
+ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
+ NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(cfg80211_rx_evt,
+ TP_PROTO(struct net_device *netdev, const u8 *addr),
+ TP_ARGS(netdev, addr),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(addr)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(addr, addr);
+ ),
+ TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
+ TP_PROTO(struct net_device *netdev, const u8 *addr),
+ TP_ARGS(netdev, addr)
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
+ TP_PROTO(struct net_device *netdev, const u8 *addr),
+ TP_ARGS(netdev, addr)
+);
+
+DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
+ TP_PROTO(struct net_device *netdev, const u8 *addr),
+ TP_ARGS(netdev, addr)
+);
+
+TRACE_EVENT(cfg80211_probe_status,
+ TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
+ bool acked),
+ TP_ARGS(netdev, addr, cookie, acked),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(addr)
+ __field(u64, cookie)
+ __field(bool, acked)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(addr, addr);
+ __entry->cookie = cookie;
+ __entry->acked = acked;
+ ),
+ TP_printk(NETDEV_PR_FMT " addr:" MAC_PR_FMT ", cookie: %llu, acked: %s",
+ NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie,
+ BOOL_TO_STR(__entry->acked))
+);
+
+TRACE_EVENT(cfg80211_cqm_pktloss_notify,
+ TP_PROTO(struct net_device *netdev, const u8 *peer, u32 num_packets),
+ TP_ARGS(netdev, peer, num_packets),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ __field(u32, num_packets)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ __entry->num_packets = num_packets;
+ ),
+ TP_printk(NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", num of lost packets: %u",
+ NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->num_packets)
+);
+
+DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_gtk_rekey_notify,
+ TP_PROTO(struct net_device *netdev, const u8 *macaddr),
+ TP_ARGS(netdev, macaddr)
+);
+
+TRACE_EVENT(cfg80211_pmksa_candidate_notify,
+ TP_PROTO(struct net_device *netdev, int index, const u8 *bssid,
+ bool preauth),
+ TP_ARGS(netdev, index, bssid, preauth),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ __field(int, index)
+ MAC_ENTRY(bssid)
+ __field(bool, preauth)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ __entry->index = index;
+ MAC_ASSIGN(bssid, bssid);
+ __entry->preauth = preauth;
+ ),
+ TP_printk(NETDEV_PR_FMT ", index:%d, bssid: " MAC_PR_FMT ", pre auth: %s",
+ NETDEV_PR_ARG, __entry->index, MAC_PR_ARG(bssid),
+ BOOL_TO_STR(__entry->preauth))
+);
+
+TRACE_EVENT(cfg80211_report_obss_beacon,
+ TP_PROTO(struct wiphy *wiphy, const u8 *frame, size_t len,
+ int freq, int sig_dbm),
+ TP_ARGS(wiphy, frame, len, freq, sig_dbm),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(int, freq)
+ __field(int, sig_dbm)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ __entry->freq = freq;
+ __entry->sig_dbm = sig_dbm;
+ ),
+ TP_printk(WIPHY_PR_FMT ", freq: %d, sig_dbm: %d",
+ WIPHY_PR_ARG, __entry->freq, __entry->sig_dbm)
+);
+
+TRACE_EVENT(cfg80211_tdls_oper_request,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *peer,
+ enum nl80211_tdls_operation oper, u16 reason_code),
+ TP_ARGS(wiphy, netdev, peer, oper, reason_code),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ __field(enum nl80211_tdls_operation, oper)
+ __field(u16, reason_code)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ __entry->oper = oper;
+ __entry->reason_code = reason_code;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", oper: %d, reason_code %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper,
+ __entry->reason_code)
+ );
+
+TRACE_EVENT(cfg80211_scan_done,
+ TP_PROTO(struct cfg80211_scan_request *request, bool aborted),
+ TP_ARGS(request, aborted),
+ TP_STRUCT__entry(
+ __field(u32, n_channels)
+ __dynamic_array(u8, ie, request ? request->ie_len : 0)
+ __array(u32, rates, IEEE80211_NUM_BANDS)
+ __field(u32, wdev_id)
+ MAC_ENTRY(wiphy_mac)
+ __field(bool, no_cck)
+ __field(bool, aborted)
+ ),
+ TP_fast_assign(
+ if (request) {
+ memcpy(__get_dynamic_array(ie), request->ie,
+ request->ie_len);
+ memcpy(__entry->rates, request->rates,
+ IEEE80211_NUM_BANDS);
+ __entry->wdev_id = request->wdev ?
+ request->wdev->identifier : 0;
+ if (request->wiphy)
+ MAC_ASSIGN(wiphy_mac,
+ request->wiphy->perm_addr);
+ __entry->no_cck = request->no_cck;
+ }
+ __entry->aborted = aborted;
+ ),
+ TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted))
+);
+
+DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_stopped,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+);
+
+TRACE_EVENT(cfg80211_get_bss,
+ TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+ const u8 *bssid, const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val),
+ TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, capa_mask, capa_val),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_ENTRY
+ MAC_ENTRY(bssid)
+ __dynamic_array(u8, ssid, ssid_len)
+ __field(u16, capa_mask)
+ __field(u16, capa_val)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_ASSIGN(channel);
+ MAC_ASSIGN(bssid, bssid);
+ memcpy(__get_dynamic_array(ssid), ssid, ssid_len);
+ __entry->capa_mask = capa_mask;
+ __entry->capa_val = capa_val;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, "
+ "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG,
+ MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0],
+ __entry->capa_mask, __entry->capa_val)
+);
+
+TRACE_EVENT(cfg80211_inform_bss_frame,
+ TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ s32 signal),
+ TP_ARGS(wiphy, channel, mgmt, len, signal),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_ENTRY
+ __dynamic_array(u8, mgmt, len)
+ __field(s32, signal)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_ASSIGN(channel);
+ if (mgmt)
+ memcpy(__get_dynamic_array(mgmt), mgmt, len);
+ __entry->signal = signal;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d",
+ WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal)
+);
+
+DECLARE_EVENT_CLASS(cfg80211_bss_evt,
+ TP_PROTO(struct cfg80211_bss *pub),
+ TP_ARGS(pub),
+ TP_STRUCT__entry(
+ MAC_ENTRY(bssid)
+ CHAN_ENTRY
+ ),
+ TP_fast_assign(
+ MAC_ASSIGN(bssid, pub->bssid);
+ CHAN_ASSIGN(pub->channel);
+ ),
+ TP_printk(MAC_PR_FMT ", " CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+);
+
+DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss,
+ TP_PROTO(struct cfg80211_bss *pub),
+ TP_ARGS(pub)
+);
+
+TRACE_EVENT(cfg80211_return_uint,
+ TP_PROTO(unsigned int ret),
+ TP_ARGS(ret),
+ TP_STRUCT__entry(
+ __field(unsigned int, ret)
+ ),
+ TP_fast_assign(
+ __entry->ret = ret;
+ ),
+ TP_printk("ret: %d", __entry->ret)
+);
+
+TRACE_EVENT(cfg80211_return_u32,
+ TP_PROTO(u32 ret),
+ TP_ARGS(ret),
+ TP_STRUCT__entry(
+ __field(u32, ret)
+ ),
+ TP_fast_assign(
+ __entry->ret = ret;
+ ),
+ TP_printk("ret: %u", __entry->ret)
+);
+
+#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2762e8329986..16d76a807c2f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -11,6 +11,8 @@
#include <net/ip.h>
#include <net/dsfield.h>
#include "core.h"
+#include "rdev-ops.h"
+
struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
@@ -686,10 +688,13 @@ EXPORT_SYMBOL(cfg80211_classify8021d);
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
{
- if (bss->information_elements == NULL)
+ const struct cfg80211_bss_ies *ies;
+
+ ies = rcu_dereference(bss->ies);
+ if (!ies)
return NULL;
- return cfg80211_find_ie(ie, bss->information_elements,
- bss->len_information_elements);
+
+ return cfg80211_find_ie(ie, ies->data, ies->len);
}
EXPORT_SYMBOL(ieee80211_bss_get_ie);
@@ -705,19 +710,18 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
for (i = 0; i < 6; i++) {
if (!wdev->connect_keys->params[i].cipher)
continue;
- if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
- &wdev->connect_keys->params[i])) {
+ if (rdev_add_key(rdev, dev, i, false, NULL,
+ &wdev->connect_keys->params[i])) {
netdev_err(dev, "failed to set key %d\n", i);
continue;
}
if (wdev->connect_keys->def == i)
- if (rdev->ops->set_default_key(wdev->wiphy, dev,
- i, true, true)) {
+ if (rdev_set_default_key(rdev, dev, i, true, true)) {
netdev_err(dev, "failed to set defkey %d\n", i);
continue;
}
if (wdev->connect_keys->defmgmt == i)
- if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
+ if (rdev_set_default_mgmt_key(rdev, dev, i))
netdev_err(dev, "failed to set mgtdef %d\n", i);
}
@@ -850,8 +854,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
cfg80211_process_rdev_events(rdev);
}
- err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
- ntype, flags, params);
+ err = rdev_change_virtual_intf(rdev, dev, ntype, flags, params);
WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
@@ -944,14 +947,86 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
return __mcs2bitrate[rate->mcs];
}
+static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
+{
+ static const u32 base[4][10] = {
+ { 6500000,
+ 13000000,
+ 19500000,
+ 26000000,
+ 39000000,
+ 52000000,
+ 58500000,
+ 65000000,
+ 78000000,
+ 0,
+ },
+ { 13500000,
+ 27000000,
+ 40500000,
+ 54000000,
+ 81000000,
+ 108000000,
+ 121500000,
+ 135000000,
+ 162000000,
+ 180000000,
+ },
+ { 29300000,
+ 58500000,
+ 87800000,
+ 117000000,
+ 175500000,
+ 234000000,
+ 263300000,
+ 292500000,
+ 351000000,
+ 390000000,
+ },
+ { 58500000,
+ 117000000,
+ 175500000,
+ 234000000,
+ 351000000,
+ 468000000,
+ 526500000,
+ 585000000,
+ 702000000,
+ 780000000,
+ },
+ };
+ u32 bitrate;
+ int idx;
+
+ if (WARN_ON_ONCE(rate->mcs > 9))
+ return 0;
+
+ idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH |
+ RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 :
+ rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 :
+ rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0;
+
+ bitrate = base[idx][rate->mcs];
+ bitrate *= rate->nss;
+
+ if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ bitrate = (bitrate / 9) * 10;
+
+ /* do NOT round down here */
+ return (bitrate + 50000) / 100000;
+}
+
u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
int modulation, streams, bitrate;
- if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+ if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
+ !(rate->flags & RATE_INFO_FLAGS_VHT_MCS))
return rate->legacy;
if (rate->flags & RATE_INFO_FLAGS_60G)
return cfg80211_calculate_bitrate_60g(rate);
+ if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
+ return cfg80211_calculate_bitrate_vht(rate);
/* the formula below does only work for MCS values smaller than 32 */
if (WARN_ON_ONCE(rate->mcs >= 32))
@@ -980,6 +1055,106 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
}
EXPORT_SYMBOL(cfg80211_calculate_bitrate);
+int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
+ enum ieee80211_p2p_attr_id attr,
+ u8 *buf, unsigned int bufsize)
+{
+ u8 *out = buf;
+ u16 attr_remaining = 0;
+ bool desired_attr = false;
+ u16 desired_len = 0;
+
+ while (len > 0) {
+ unsigned int iedatalen;
+ unsigned int copy;
+ const u8 *iedata;
+
+ if (len < 2)
+ return -EILSEQ;
+ iedatalen = ies[1];
+ if (iedatalen + 2 > len)
+ return -EILSEQ;
+
+ if (ies[0] != WLAN_EID_VENDOR_SPECIFIC)
+ goto cont;
+
+ if (iedatalen < 4)
+ goto cont;
+
+ iedata = ies + 2;
+
+ /* check WFA OUI, P2P subtype */
+ if (iedata[0] != 0x50 || iedata[1] != 0x6f ||
+ iedata[2] != 0x9a || iedata[3] != 0x09)
+ goto cont;
+
+ iedatalen -= 4;
+ iedata += 4;
+
+ /* check attribute continuation into this IE */
+ copy = min_t(unsigned int, attr_remaining, iedatalen);
+ if (copy && desired_attr) {
+ desired_len += copy;
+ if (out) {
+ memcpy(out, iedata, min(bufsize, copy));
+ out += min(bufsize, copy);
+ bufsize -= min(bufsize, copy);
+ }
+
+
+ if (copy == attr_remaining)
+ return desired_len;
+ }
+
+ attr_remaining -= copy;
+ if (attr_remaining)
+ goto cont;
+
+ iedatalen -= copy;
+ iedata += copy;
+
+ while (iedatalen > 0) {
+ u16 attr_len;
+
+ /* P2P attribute ID & size must fit */
+ if (iedatalen < 3)
+ return -EILSEQ;
+ desired_attr = iedata[0] == attr;
+ attr_len = get_unaligned_le16(iedata + 1);
+ iedatalen -= 3;
+ iedata += 3;
+
+ copy = min_t(unsigned int, attr_len, iedatalen);
+
+ if (desired_attr) {
+ desired_len += copy;
+ if (out) {
+ memcpy(out, iedata, min(bufsize, copy));
+ out += min(bufsize, copy);
+ bufsize -= min(bufsize, copy);
+ }
+
+ if (copy == attr_len)
+ return desired_len;
+ }
+
+ iedata += copy;
+ iedatalen -= copy;
+ attr_remaining = attr_len - copy;
+ }
+
+ cont:
+ len -= ies[1] + 2;
+ ies += ies[1] + 2;
+ }
+
+ if (attr_remaining && desired_attr)
+ return -EILSEQ;
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL(cfg80211_get_p2p_attr);
+
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int)
{
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 494379eb464f..d997d0f0c54a 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -19,6 +19,7 @@
#include <net/cfg80211-wext.h>
#include "wext-compat.h"
#include "core.h"
+#include "rdev-ops.h"
int cfg80211_wext_giwname(struct net_device *dev,
struct iw_request_info *info,
@@ -175,7 +176,7 @@ int cfg80211_wext_giwrange(struct net_device *dev,
case CFG80211_SIGNAL_TYPE_NONE:
break;
case CFG80211_SIGNAL_TYPE_MBM:
- range->max_qual.level = -110;
+ range->max_qual.level = (u8)-110;
range->max_qual.qual = 70;
range->avg_qual.qual = 35;
range->max_qual.updated |= IW_QUAL_DBM;
@@ -301,8 +302,7 @@ int cfg80211_wext_siwrts(struct net_device *dev,
else
wdev->wiphy->rts_threshold = rts->value;
- err = rdev->ops->set_wiphy_params(wdev->wiphy,
- WIPHY_PARAM_RTS_THRESHOLD);
+ err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD);
if (err)
wdev->wiphy->rts_threshold = orts;
@@ -342,8 +342,7 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
wdev->wiphy->frag_threshold = frag->value & ~0x1;
}
- err = rdev->ops->set_wiphy_params(wdev->wiphy,
- WIPHY_PARAM_FRAG_THRESHOLD);
+ err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD);
if (err)
wdev->wiphy->frag_threshold = ofrag;
@@ -396,7 +395,7 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
if (!changed)
return 0;
- err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
+ err = rdev_set_wiphy_params(rdev, changed);
if (err) {
wdev->wiphy->retry_short = oshort;
wdev->wiphy->retry_long = olong;
@@ -490,8 +489,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
err = -ENOENT;
else
- err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
- pairwise, addr);
+ err = rdev_del_key(rdev, dev, idx, pairwise,
+ addr);
}
wdev->wext.connect.privacy = false;
/*
@@ -525,8 +524,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
err = 0;
if (wdev->current_bss)
- err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
- pairwise, addr, params);
+ err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
if (err)
return err;
@@ -552,8 +550,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
__cfg80211_leave_ibss(rdev, wdev->netdev, true);
rejoin = true;
}
- err = rdev->ops->set_default_key(&rdev->wiphy, dev,
- idx, true, true);
+ err = rdev_set_default_key(rdev, dev, idx, true, true);
}
if (!err) {
wdev->wext.default_key = idx;
@@ -566,8 +563,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
(tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
if (wdev->current_bss)
- err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
- dev, idx);
+ err = rdev_set_default_mgmt_key(rdev, dev, idx);
if (!err)
wdev->wext.default_mgmt_key = idx;
return err;
@@ -631,8 +627,8 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
err = 0;
wdev_lock(wdev);
if (wdev->current_bss)
- err = rdev->ops->set_default_key(&rdev->wiphy, dev,
- idx, true, true);
+ err = rdev_set_default_key(rdev, dev, idx, true,
+ true);
if (!err)
wdev->wext.default_key = idx;
wdev_unlock(wdev);
@@ -788,6 +784,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_chan_def chandef = {
+ .width = NL80211_CHAN_WIDTH_20_NOHT,
+ };
int freq, err;
switch (wdev->iftype) {
@@ -801,8 +800,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
return freq;
if (freq == 0)
return -EINVAL;
+ chandef.center_freq1 = freq;
+ chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (!chandef.chan)
+ return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT);
+ err = cfg80211_set_monitor_channel(rdev, &chandef);
mutex_unlock(&rdev->devlist_mtx);
return err;
case NL80211_IFTYPE_MESH_POINT:
@@ -811,9 +814,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
return freq;
if (freq == 0)
return -EINVAL;
+ chandef.center_freq1 = freq;
+ chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (!chandef.chan)
+ return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_mesh_freq(rdev, wdev, freq,
- NL80211_CHAN_NO_HT);
+ err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
mutex_unlock(&rdev->devlist_mtx);
return err;
default:
@@ -827,8 +833,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
+ int ret;
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -839,10 +845,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
if (!rdev->ops->get_channel)
return -EINVAL;
- chan = rdev->ops->get_channel(wdev->wiphy, wdev, &channel_type);
- if (!chan)
- return -EINVAL;
- freq->m = chan->center_freq;
+ ret = rdev_get_channel(rdev, wdev, &chandef);
+ if (ret)
+ return ret;
+ freq->m = chandef.chan->center_freq;
freq->e = 6;
return 0;
default:
@@ -899,7 +905,7 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
return 0;
}
- return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm));
+ return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
}
static int cfg80211_wext_giwtxpower(struct net_device *dev,
@@ -918,7 +924,7 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev,
if (!rdev->ops->get_tx_power)
return -EOPNOTSUPP;
- err = rdev->ops->get_tx_power(wdev->wiphy, &val);
+ err = rdev_get_tx_power(rdev, wdev, &val);
if (err)
return err;
@@ -1158,7 +1164,7 @@ static int cfg80211_wext_siwpower(struct net_device *dev,
timeout = wrq->value / 1000;
}
- err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
+ err = rdev_set_power_mgmt(rdev, dev, ps, timeout);
if (err)
return err;
@@ -1200,7 +1206,7 @@ static int cfg80211_wds_wext_siwap(struct net_device *dev,
if (!rdev->ops->set_wds_peer)
return -EOPNOTSUPP;
- err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
+ err = rdev_set_wds_peer(rdev, dev, (u8 *)&addr->sa_data);
if (err)
return err;
@@ -1272,7 +1278,7 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
if (!match)
return -EINVAL;
- return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
+ return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
}
static int cfg80211_wext_giwrate(struct net_device *dev,
@@ -1302,7 +1308,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
if (err)
return err;
- err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
+ err = rdev_get_station(rdev, dev, addr, &sinfo);
if (err)
return err;
@@ -1339,7 +1345,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
wdev_unlock(wdev);
- if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
+ if (rdev_get_station(rdev, dev, bssid, &sinfo))
return NULL;
memset(&wstats, 0, sizeof(wstats));
@@ -1474,19 +1480,19 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
if (!rdev->ops->set_pmksa)
return -EOPNOTSUPP;
- return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+ return rdev_set_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_REMOVE:
if (!rdev->ops->del_pmksa)
return -EOPNOTSUPP;
- return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+ return rdev_del_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_FLUSH:
if (!rdev->ops->flush_pmksa)
return -EOPNOTSUPP;
- return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+ return rdev_flush_pmksa(rdev, dev);
default:
return -EOPNOTSUPP;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 1f773f668d1a..fb9622f6d99c 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -119,7 +119,16 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
* channel we disconnected above and reconnect below.
*/
if (chan && !wdev->wext.connect.ssid_len) {
- err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT);
+ struct cfg80211_chan_def chandef = {
+ .width = NL80211_CHAN_WIDTH_20_NOHT,
+ .center_freq1 = freq,
+ };
+
+ chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (chandef.chan)
+ err = cfg80211_set_monitor_channel(rdev, &chandef);
+ else
+ err = -EINVAL;
goto out;
}
@@ -233,13 +242,17 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
wdev_lock(wdev);
if (wdev->current_bss) {
- const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
- WLAN_EID_SSID);
+ const u8 *ie;
+
+ rcu_read_lock();
+ ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
+ WLAN_EID_SSID);
if (ie) {
data->flags = 1;
data->length = ie[1];
memcpy(ssid, ie + 2, data->length);
}
+ rcu_read_unlock();
} else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
data->flags = 1;
data->length = wdev->wext.connect.ssid_len;
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index e5246fbe36c4..2906d520eea7 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -276,18 +276,16 @@ static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
struct crypto_comp * __percpu *tfms;
int cpu;
- /* This can be any valid CPU ID so we don't need locking. */
- cpu = raw_smp_processor_id();
list_for_each_entry(pos, &ipcomp_tfms_list, list) {
struct crypto_comp *tfm;
- tfms = pos->tfms;
- tfm = *per_cpu_ptr(tfms, cpu);
+ /* This can be any valid CPU ID so we don't need locking. */
+ tfm = __this_cpu_read(*pos->tfms);
if (!strcmp(crypto_comp_name(tfm), alg_name)) {
pos->users++;
- return tfms;
+ return pos->tfms;
}
}
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 3efb07d3eb27..765f6fe951eb 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -521,13 +521,12 @@ int xfrm_init_replay(struct xfrm_state *x)
replay_esn->bmp_len * sizeof(__u32) * 8)
return -EINVAL;
- if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0)
- return -EINVAL;
-
- if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
- x->repl = &xfrm_replay_esn;
- else
- x->repl = &xfrm_replay_bmp;
+ if (x->props.flags & XFRM_STATE_ESN) {
+ if (replay_esn->replay_window == 0)
+ return -EINVAL;
+ x->repl = &xfrm_replay_esn;
+ } else
+ x->repl = &xfrm_replay_bmp;
} else
x->repl = &xfrm_replay_legacy;
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 380976f74c4c..05a6e3d9c258 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -54,6 +54,10 @@ int __net_init xfrm_sysctl_init(struct net *net)
table[2].data = &net->xfrm.sysctl_larval_drop;
table[3].data = &net->xfrm.sysctl_acq_expires;
+ /* Don't export sysctls to unprivileged users */
+ if (net->user_ns != &init_user_ns)
+ table[0].procname = NULL;
+
net->xfrm.sysctl_hdr = register_net_sysctl(net, "net/core", table);
if (!net->xfrm.sysctl_hdr)
goto out_register;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 421f98444335..eb872b2e366e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2349,7 +2349,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
link = &xfrm_dispatch[type];
/* All operations require privileges, even GET */
- if (!capable(CAP_NET_ADMIN))
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 46e7aff80d1a..28b761567815 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -137,6 +137,8 @@ use strict;
# should document the "Context:" of the function, e.g. whether the functions
# can be called form interrupts. Unlike other sections you can end it with an
# empty line.
+# A non-void function should have a "Return:" section describing the return
+# value(s).
# Example-sections should contain the string EXAMPLE so that they are marked
# appropriately in DocBook.
#
@@ -315,6 +317,7 @@ my $section_default = "Description"; # default section
my $section_intro = "Introduction";
my $section = $section_default;
my $section_context = "Context";
+my $section_return = "Return";
my $undescribed = "-- undescribed --";
@@ -2039,6 +2042,28 @@ sub check_sections($$$$$$) {
}
##
+# Checks the section describing the return value of a function.
+sub check_return_section {
+ my $file = shift;
+ my $declaration_name = shift;
+ my $return_type = shift;
+
+ # Ignore an empty return type (It's a macro)
+ # Ignore functions with a "void" return type. (But don't ignore "void *")
+ if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
+ return;
+ }
+
+ if (!defined($sections{$section_return}) ||
+ $sections{$section_return} eq "") {
+ print STDERR "Warning(${file}:$.): " .
+ "No description found for return value of " .
+ "'$declaration_name'\n";
+ ++$warnings;
+ }
+}
+
+##
# takes a function prototype and the name of the current file being
# processed and spits out all the details stored in the global
# arrays/hashes.
@@ -2109,6 +2134,15 @@ sub dump_function($$) {
my $prms = join " ", @parameterlist;
check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
+ # This check emits a lot of warnings at the moment, because many
+ # functions don't have a 'Return' doc section. So until the number
+ # of warnings goes sufficiently down, the check is only performed in
+ # verbose mode.
+ # TODO: always perform the check.
+ if ($verbose) {
+ check_return_section($file, $declaration_name, $return_type);
+ }
+
output_declaration($declaration_name,
'function',
{'function' => $declaration_name,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a58f712605d8..86468f385fc8 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -358,8 +358,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
- if (ret)
- break;
case -ENOKEY: /* negative key */
ret = key_ref;
break;
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index d309e7f472d8..370a6468b3ba 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -67,6 +67,9 @@ static struct nlmsg_perm nlmsg_route_perms[] =
{ RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+ { RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+ { RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
};
static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 5119fdabcb98..aa5d8034890b 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -786,7 +786,7 @@ static int aaci_resume(struct amba_device *dev)
#endif
-static struct ac97_pcm ac97_defs[] __devinitdata = {
+static struct ac97_pcm ac97_defs[] = {
[0] = { /* Front PCM */
.exclusive = 1,
.r = {
@@ -832,7 +832,7 @@ static struct snd_ac97_bus_ops aaci_bus_ops = {
.read = aaci_ac97_read,
};
-static int __devinit aaci_probe_ac97(struct aaci *aaci)
+static int aaci_probe_ac97(struct aaci *aaci)
{
struct snd_ac97_template ac97_template;
struct snd_ac97_bus *ac97_bus;
@@ -893,7 +893,7 @@ static void aaci_free_card(struct snd_card *card)
iounmap(aaci->base);
}
-static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+static struct aaci *aaci_init_card(struct amba_device *dev)
{
struct aaci *aaci;
struct snd_card *card;
@@ -926,7 +926,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
return aaci;
}
-static int __devinit aaci_init_pcm(struct aaci *aaci)
+static int aaci_init_pcm(struct aaci *aaci)
{
struct snd_pcm *pcm;
int ret;
@@ -948,7 +948,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
return ret;
}
-static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+static unsigned int aaci_size_fifo(struct aaci *aaci)
{
struct aaci_runtime *aacirun = &aaci->playback;
int i;
@@ -984,8 +984,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
return i;
}
-static int __devinit aaci_probe(struct amba_device *dev,
- const struct amba_id *id)
+static int aaci_probe(struct amba_device *dev,
+ const struct amba_id *id)
{
struct aaci *aaci;
int ret, i;
@@ -1072,7 +1072,7 @@ static int __devinit aaci_probe(struct amba_device *dev,
return ret;
}
-static int __devexit aaci_remove(struct amba_device *dev)
+static int aaci_remove(struct amba_device *dev)
{
struct snd_card *card = amba_get_drvdata(dev);
@@ -1104,7 +1104,7 @@ static struct amba_driver aaci_driver = {
.name = DRIVER_NAME,
},
.probe = aaci_probe,
- .remove = __devexit_p(aaci_remove),
+ .remove = aaci_remove,
.suspend = aaci_suspend,
.resume = aaci_resume,
.id_table = aaci_ids,
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 48d7c0aa5073..6fc0ae90e5b1 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -314,7 +314,7 @@ int pxa2xx_ac97_hw_resume(void)
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
#endif
-int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
+int pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
int ret;
pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 4e1fda75c1c9..ec54be4efff0 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -163,7 +163,7 @@ static int pxa2xx_ac97_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
#endif
-static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+static int pxa2xx_ac97_probe(struct platform_device *dev)
{
struct snd_card *card;
struct snd_ac97_bus *ac97_bus;
@@ -224,7 +224,7 @@ err_dev:
return ret;
}
-static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
+static int pxa2xx_ac97_remove(struct platform_device *dev)
{
struct snd_card *card = platform_get_drvdata(dev);
@@ -239,7 +239,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
static struct platform_driver pxa2xx_ac97_driver = {
.probe = pxa2xx_ac97_probe,
- .remove = __devexit_p(pxa2xx_ac97_remove),
+ .remove = pxa2xx_ac97_remove,
.driver = {
.name = "pxa2xx-ac97",
.owner = THIS_MODULE,
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
index 277ebce23a45..071ce1b5f2b4 100644
--- a/sound/atmel/abdac.c
+++ b/sound/atmel/abdac.c
@@ -309,7 +309,7 @@ static struct snd_pcm_ops atmel_abdac_ops = {
.pointer = atmel_abdac_pointer,
};
-static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac)
+static int atmel_abdac_pcm_new(struct atmel_abdac *dac)
{
struct snd_pcm_hardware hw = atmel_abdac_hw;
struct snd_pcm *pcm;
@@ -386,7 +386,7 @@ static int set_sample_rates(struct atmel_abdac *dac)
return retval;
}
-static int __devinit atmel_abdac_probe(struct platform_device *pdev)
+static int atmel_abdac_probe(struct platform_device *pdev)
{
struct snd_card *card;
struct atmel_abdac *dac;
@@ -567,7 +567,7 @@ static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume
#define ATMEL_ABDAC_PM_OPS NULL
#endif
-static int __devexit atmel_abdac_remove(struct platform_device *pdev)
+static int atmel_abdac_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
struct atmel_abdac *dac = get_dac(card);
@@ -589,7 +589,7 @@ static int __devexit atmel_abdac_remove(struct platform_device *pdev)
}
static struct platform_driver atmel_abdac_driver = {
- .remove = __devexit_p(atmel_abdac_remove),
+ .remove = atmel_abdac_remove,
.driver = {
.name = "atmel_abdac",
.owner = THIS_MODULE,
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 9052aff37f64..79d6bda58753 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -728,7 +728,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
return retval;
}
-static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
+static struct ac97_pcm at91_ac97_pcm_defs[] = {
/* Playback */
{
.exclusive = 1,
@@ -756,7 +756,7 @@ static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
},
};
-static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
+static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_hardware hw = atmel_ac97c_hw;
@@ -902,7 +902,7 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip)
}
}
-static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
+static int atmel_ac97c_probe(struct platform_device *pdev)
{
struct snd_card *card;
struct atmel_ac97c *chip;
@@ -1168,7 +1168,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume
#define ATMEL_AC97C_PM_OPS NULL
#endif
-static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
+static int atmel_ac97c_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
struct atmel_ac97c *chip = get_chip(card);
@@ -1205,7 +1205,7 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
}
static struct platform_driver atmel_ac97c_driver = {
- .remove = __devexit_p(atmel_ac97c_remove),
+ .remove = atmel_ac97c_remove,
.driver = {
.name = "atmel_ac97c",
.owner = THIS_MODULE,
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 71cc3ddf5c15..727ac44d39f4 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -199,12 +199,13 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
{
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
- int stream = snd_pcm_plug_stream(plug);
+ int stream;
if (snd_BUG_ON(!plug))
return -ENXIO;
if (drv_frames == 0)
return 0;
+ stream = snd_pcm_plug_stream(plug);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
plugin = snd_pcm_plug_last(plug);
while (plugin && drv_frames > 0) {
@@ -230,13 +231,14 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
{
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
snd_pcm_sframes_t frames;
- int stream = snd_pcm_plug_stream(plug);
+ int stream;
if (snd_BUG_ON(!plug))
return -ENXIO;
if (clt_frames == 0)
return 0;
frames = clt_frames;
+ stream = snd_pcm_plug_stream(plug);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
plugin = snd_pcm_plug_first(plug);
while (plugin && frames > 0) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 030102caeee9..61798f85d030 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -981,8 +981,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
kfree(runtime->hw_constraints.rules);
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- if (runtime->hwptr_log)
- kfree(runtime->hwptr_log);
+ kfree(runtime->hwptr_log);
#endif
kfree(runtime);
substream->runtime = NULL;
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 91cdf9435fec..af49721ba0e3 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -190,7 +190,9 @@ struct snd_pcm_status32 {
u32 avail_max;
u32 overrange;
s32 suspended_state;
- unsigned char reserved[60];
+ u32 reserved_alignment;
+ struct compat_timespec audio_tstamp;
+ unsigned char reserved[56-sizeof(struct compat_timespec)];
} __attribute__((packed));
@@ -205,17 +207,16 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
return err;
if (put_user(status.state, &src->state) ||
- put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
- put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
- put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
- put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+ compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+ compat_put_timespec(&status.tstamp, &src->tstamp) ||
put_user(status.appl_ptr, &src->appl_ptr) ||
put_user(status.hw_ptr, &src->hw_ptr) ||
put_user(status.delay, &src->delay) ||
put_user(status.avail, &src->avail) ||
put_user(status.avail_max, &src->avail_max) ||
put_user(status.overrange, &src->overrange) ||
- put_user(status.suspended_state, &src->suspended_state))
+ put_user(status.suspended_state, &src->suspended_state) ||
+ compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp))
return -EFAULT;
return err;
@@ -364,6 +365,7 @@ struct snd_pcm_mmap_status32 {
u32 hw_ptr;
struct compat_timespec tstamp;
s32 suspended_state;
+ struct compat_timespec audio_tstamp;
} __attribute__((packed));
struct snd_pcm_mmap_control32 {
@@ -426,12 +428,14 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
sstatus.hw_ptr = status->hw_ptr % boundary;
sstatus.tstamp = status->tstamp;
sstatus.suspended_state = status->suspended_state;
+ sstatus.audio_tstamp = status->audio_tstamp;
snd_pcm_stream_unlock_irq(substream);
if (put_user(sstatus.state, &src->s.status.state) ||
put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
- put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
- put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
+ compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+ compat_put_timespec(&sstatus.audio_tstamp,
+ &src->s.status.audio_tstamp) ||
put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
put_user(scontrol.avail_min, &src->c.control.avail_min))
return -EFAULT;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f42c10a43315..c4840ff75d00 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -316,6 +316,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
unsigned long jdelta;
unsigned long curr_jiffies;
struct timespec curr_tstamp;
+ struct timespec audio_tstamp;
+ int crossed_boundary = 0;
old_hw_ptr = runtime->status->hw_ptr;
@@ -327,9 +329,14 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
*/
pos = substream->ops->pointer(substream);
curr_jiffies = jiffies;
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
+ if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) &&
+ (substream->ops->wall_clock))
+ substream->ops->wall_clock(substream, &audio_tstamp);
+ }
+
if (pos == SNDRV_PCM_POS_XRUN) {
xrun(substream);
return -EPIPE;
@@ -360,8 +367,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
+ if (hw_base >= runtime->boundary) {
hw_base = 0;
+ crossed_boundary++;
+ }
new_hw_ptr = hw_base + pos;
goto __delta;
}
@@ -371,8 +380,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
/* pointer crosses the end of the ring buffer */
if (new_hw_ptr < old_hw_ptr) {
hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
+ if (hw_base >= runtime->boundary) {
hw_base = 0;
+ crossed_boundary++;
+ }
new_hw_ptr = hw_base + pos;
}
__delta:
@@ -410,8 +421,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
while (hdelta > xrun_threshold) {
delta += runtime->buffer_size;
hw_base += runtime->buffer_size;
- if (hw_base >= runtime->boundary)
+ if (hw_base >= runtime->boundary) {
hw_base = 0;
+ crossed_boundary++;
+ }
new_hw_ptr = hw_base + pos;
hdelta -= runtime->hw_ptr_buffer_jiffies;
}
@@ -456,8 +469,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
/* the delta value is small or zero in most cases */
while (delta > 0) {
new_hw_ptr += runtime->period_size;
- if (new_hw_ptr >= runtime->boundary)
+ if (new_hw_ptr >= runtime->boundary) {
new_hw_ptr -= runtime->boundary;
+ crossed_boundary--;
+ }
delta--;
}
/* align hw_base to buffer_size */
@@ -507,9 +522,35 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
runtime->hw_ptr_jiffies = curr_jiffies;
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ if (crossed_boundary) {
+ snd_BUG_ON(crossed_boundary != 1);
+ runtime->hw_ptr_wrap += runtime->boundary;
+ }
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
runtime->status->tstamp = curr_tstamp;
+ if (!(runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)) {
+ /*
+ * no wall clock available, provide audio timestamp
+ * derived from pointer position+delay
+ */
+ u64 audio_frames, audio_nsecs;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ audio_frames = runtime->hw_ptr_wrap
+ + runtime->status->hw_ptr
+ - runtime->delay;
+ else
+ audio_frames = runtime->hw_ptr_wrap
+ + runtime->status->hw_ptr
+ + runtime->delay;
+ audio_nsecs = div_u64(audio_frames * 1000000000LL,
+ runtime->rate);
+ audio_tstamp = ns_to_timespec(audio_nsecs);
+ }
+ runtime->status->audio_tstamp = audio_tstamp;
+ }
+
return snd_pcm_update_state(substream, runtime);
}
@@ -1661,8 +1702,10 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
if (snd_pcm_running(substream) &&
snd_pcm_update_hw_ptr(substream) >= 0)
runtime->status->hw_ptr %= runtime->buffer_size;
- else
+ else {
runtime->status->hw_ptr = 0;
+ runtime->hw_ptr_wrap = 0;
+ }
snd_pcm_stream_unlock_irqrestore(substream, flags);
return 0;
}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index f9ddecf2f4cd..09b4286c65f9 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -602,6 +602,8 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
snd_pcm_update_hw_ptr(substream);
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
status->tstamp = runtime->status->tstamp;
+ status->audio_tstamp =
+ runtime->status->audio_tstamp;
goto _tstamp_end;
}
}
@@ -1998,7 +2000,7 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
if (runtime->dma_bytes) {
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
if (err < 0)
- return -EINVAL;
+ return err;
}
if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 60e8fc1b3440..040c60e1da28 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -66,7 +66,7 @@ struct ops_list {
/* operators */
struct snd_seq_dev_ops ops;
- /* registred devices */
+ /* registered devices */
struct list_head dev_list; /* list of devices */
int num_devices; /* number of associated devices */
int num_init_devices; /* number of initialized devices */
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index fe5ae09ffccb..7d02c322ed93 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -14,6 +14,7 @@ config SND_OPL4_LIB
config SND_VX_LIB
tristate
+ select FW_LOADER
select SND_HWDEP
select SND_PCM
@@ -35,7 +36,6 @@ config SND_PCSP
tristate "PC-Speaker support (READ HELP!)"
depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS
depends on INPUT
- depends on EXPERIMENTAL
select SND_PCM
help
If you don't have a sound card in your computer, you can include a
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 0fe6d64ff840..3d822328d383 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -120,7 +120,6 @@ struct loopback_pcm {
unsigned int last_drift;
unsigned long last_jiffies;
struct timer_list timer;
- spinlock_t timer_lock;
};
static struct platform_device *devices[SNDRV_CARDS];
@@ -166,12 +165,12 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
return get_setup(dpcm)->rate_shift;
}
+/* call in cable->lock */
static void loopback_timer_start(struct loopback_pcm *dpcm)
{
unsigned long tick;
unsigned int rate_shift = get_rate_shift(dpcm);
- spin_lock(&dpcm->timer_lock);
if (rate_shift != dpcm->pcm_rate_shift) {
dpcm->pcm_rate_shift = rate_shift;
dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -184,15 +183,13 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
dpcm->timer.expires = jiffies + tick;
add_timer(&dpcm->timer);
- spin_unlock(&dpcm->timer_lock);
}
+/* call in cable->lock */
static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
{
- spin_lock(&dpcm->timer_lock);
del_timer(&dpcm->timer);
dpcm->timer.expires = 0;
- spin_unlock(&dpcm->timer_lock);
}
#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -274,8 +271,8 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
spin_lock(&cable->lock);
cable->running |= stream;
cable->pause &= ~stream;
- spin_unlock(&cable->lock);
loopback_timer_start(dpcm);
+ spin_unlock(&cable->lock);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
@@ -283,23 +280,23 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
spin_lock(&cable->lock);
cable->running &= ~stream;
cable->pause &= ~stream;
- spin_unlock(&cable->lock);
loopback_timer_stop(dpcm);
+ spin_unlock(&cable->lock);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
loopback_active_notify(dpcm);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
spin_lock(&cable->lock);
cable->pause |= stream;
- spin_unlock(&cable->lock);
loopback_timer_stop(dpcm);
+ spin_unlock(&cable->lock);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
spin_lock(&cable->lock);
dpcm->last_jiffies = jiffies;
cable->pause &= ~stream;
- spin_unlock(&cable->lock);
loopback_timer_start(dpcm);
+ spin_unlock(&cable->lock);
break;
default:
return -EINVAL;
@@ -477,6 +474,7 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm,
dpcm->buf_pos %= dpcm->pcm_buffer_size;
}
+/* call in cable->lock */
static unsigned int loopback_pos_update(struct loopback_cable *cable)
{
struct loopback_pcm *dpcm_play =
@@ -485,9 +483,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
cable->streams[SNDRV_PCM_STREAM_CAPTURE];
unsigned long delta_play = 0, delta_capt = 0;
unsigned int running, count1, count2;
- unsigned long flags;
- spin_lock_irqsave(&cable->lock, flags);
running = cable->running ^ cable->pause;
if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
delta_play = jiffies - dpcm_play->last_jiffies;
@@ -529,32 +525,39 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
bytepos_finish(dpcm_play, count1);
bytepos_finish(dpcm_capt, count1);
unlock:
- spin_unlock_irqrestore(&cable->lock, flags);
return running;
}
static void loopback_timer_function(unsigned long data)
{
struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
- unsigned int running;
+ unsigned long flags;
- running = loopback_pos_update(dpcm->cable);
- if (running & (1 << dpcm->substream->stream)) {
+ spin_lock_irqsave(&dpcm->cable->lock, flags);
+ if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) {
loopback_timer_start(dpcm);
if (dpcm->period_update_pending) {
dpcm->period_update_pending = 0;
+ spin_unlock_irqrestore(&dpcm->cable->lock, flags);
+ /* need to unlock before calling below */
snd_pcm_period_elapsed(dpcm->substream);
+ return;
}
}
+ spin_unlock_irqrestore(&dpcm->cable->lock, flags);
}
static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct loopback_pcm *dpcm = runtime->private_data;
+ snd_pcm_uframes_t pos;
+ spin_lock(&dpcm->cable->lock);
loopback_pos_update(dpcm->cable);
- return bytes_to_frames(runtime, dpcm->buf_pos);
+ pos = dpcm->buf_pos;
+ spin_unlock(&dpcm->cable->lock);
+ return bytes_to_frames(runtime, pos);
}
static struct snd_pcm_hardware loopback_pcm_hardware =
@@ -672,7 +675,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
dpcm->substream = substream;
setup_timer(&dpcm->timer, loopback_timer_function,
(unsigned long)dpcm);
- spin_lock_init(&dpcm->timer_lock);
cable = loopback->cables[substream->number][dev];
if (!cable) {
@@ -772,8 +774,8 @@ static struct snd_pcm_ops loopback_capture_ops = {
.mmap = snd_pcm_lib_mmap_vmalloc,
};
-static int __devinit loopback_pcm_new(struct loopback *loopback,
- int device, int substreams)
+static int loopback_pcm_new(struct loopback *loopback,
+ int device, int substreams)
{
struct snd_pcm *pcm;
int err;
@@ -947,7 +949,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new loopback_controls[] __devinitdata = {
+static struct snd_kcontrol_new loopback_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Rate Shift 100000",
@@ -996,7 +998,7 @@ static struct snd_kcontrol_new loopback_controls[] __devinitdata = {
}
};
-static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
+static int loopback_mixer_new(struct loopback *loopback, int notify)
{
struct snd_card *card = loopback->card;
struct snd_pcm *pcm;
@@ -1109,7 +1111,7 @@ static void print_cable_info(struct snd_info_entry *entry,
mutex_unlock(&loopback->cable_lock);
}
-static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
+static int loopback_proc_new(struct loopback *loopback, int cidx)
{
char name[32];
struct snd_info_entry *entry;
@@ -1130,7 +1132,7 @@ static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
#endif
-static int __devinit loopback_probe(struct platform_device *devptr)
+static int loopback_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct loopback *loopback;
@@ -1175,7 +1177,7 @@ static int __devinit loopback_probe(struct platform_device *devptr)
return err;
}
-static int __devexit loopback_remove(struct platform_device *devptr)
+static int loopback_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -1213,7 +1215,7 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
static struct platform_driver loopback_driver = {
.probe = loopback_probe,
- .remove = __devexit_p(loopback_remove),
+ .remove = loopback_remove,
.driver = {
.name = SND_LOOPBACK_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 54bb6644a598..fd798f753609 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -134,6 +134,9 @@ struct snd_dummy {
spinlock_t mixer_lock;
int mixer_volume[MIXER_ADDR_LAST+1][2];
int capture_source[MIXER_ADDR_LAST+1][2];
+ int iobox;
+ struct snd_kcontrol *cd_volume_ctl;
+ struct snd_kcontrol *cd_switch_ctl;
const struct dummy_timer_ops *timer_ops;
};
@@ -685,8 +688,8 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
.page = dummy_pcm_page,
};
-static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
- int substreams)
+static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
+ int substreams)
{
struct snd_pcm *pcm;
struct snd_pcm_ops *ops;
@@ -817,6 +820,57 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
return change;
}
+static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
+{
+ const char *const names[] = { "None", "CD Player" };
+
+ return snd_ctl_enum_info(info, 1, 2, names);
+}
+
+static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+
+ value->value.enumerated.item[0] = dummy->iobox;
+ return 0;
+}
+
+static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
+{
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+ int changed;
+
+ if (value->value.enumerated.item[0] > 1)
+ return -EINVAL;
+
+ changed = value->value.enumerated.item[0] != dummy->iobox;
+ if (changed) {
+ dummy->iobox = value->value.enumerated.item[0];
+
+ if (dummy->iobox) {
+ dummy->cd_volume_ctl->vd[0].access &=
+ ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ dummy->cd_switch_ctl->vd[0].access &=
+ ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ } else {
+ dummy->cd_volume_ctl->vd[0].access |=
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ dummy->cd_switch_ctl->vd[0].access |=
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ }
+
+ snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+ &dummy->cd_volume_ctl->id);
+ snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+ &dummy->cd_switch_ctl->id);
+ }
+
+ return changed;
+}
+
static struct snd_kcontrol_new snd_dummy_controls[] = {
DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
@@ -827,22 +881,37 @@ DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE),
DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC),
DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
-DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
+DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "External I/O Box",
+ .info = snd_dummy_iobox_info,
+ .get = snd_dummy_iobox_get,
+ .put = snd_dummy_iobox_put,
+},
};
-static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+static int snd_card_dummy_new_mixer(struct snd_dummy *dummy)
{
struct snd_card *card = dummy->card;
+ struct snd_kcontrol *kcontrol;
unsigned int idx;
int err;
spin_lock_init(&dummy->mixer_lock);
strcpy(card->mixername, "Dummy Mixer");
+ dummy->iobox = 1;
for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
- err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy));
+ kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy);
+ err = snd_ctl_add(card, kcontrol);
if (err < 0)
return err;
+ if (!strcmp(kcontrol->id.name, "CD Volume"))
+ dummy->cd_volume_ctl = kcontrol;
+ else if (!strcmp(kcontrol->id.name, "CD Capture Switch"))
+ dummy->cd_switch_ctl = kcontrol;
+
}
return 0;
}
@@ -962,7 +1031,7 @@ static void dummy_proc_write(struct snd_info_entry *entry,
}
}
-static void __devinit dummy_proc_init(struct snd_dummy *chip)
+static void dummy_proc_init(struct snd_dummy *chip)
{
struct snd_info_entry *entry;
@@ -977,7 +1046,7 @@ static void __devinit dummy_proc_init(struct snd_dummy *chip)
#define dummy_proc_init(x)
#endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */
-static int __devinit snd_dummy_probe(struct platform_device *devptr)
+static int snd_dummy_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct snd_dummy *dummy;
@@ -1057,7 +1126,7 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
return err;
}
-static int __devexit snd_dummy_remove(struct platform_device *devptr)
+static int snd_dummy_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -1093,7 +1162,7 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
static struct platform_driver snd_dummy_driver = {
.probe = snd_dummy_probe,
- .remove = __devexit_p(snd_dummy_remove),
+ .remove = snd_dummy_remove,
.driver = {
.name = SND_DUMMY_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index 6c83b1aed288..8125a7e95ee4 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1063,7 +1063,7 @@ snd_ml403_ac97cr_codec_write(struct snd_ac97 *ac97, unsigned short reg,
return;
}
-static int __devinit
+static int
snd_ml403_ac97cr_chip_init(struct snd_ml403_ac97cr *ml403_ac97cr)
{
unsigned long end_time;
@@ -1108,7 +1108,7 @@ static int snd_ml403_ac97cr_dev_free(struct snd_device *snddev)
return snd_ml403_ac97cr_free(ml403_ac97cr);
}
-static int __devinit
+static int
snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
struct snd_ml403_ac97cr **rml403_ac97cr)
{
@@ -1204,7 +1204,7 @@ static void snd_ml403_ac97cr_mixer_free(struct snd_ac97 *ac97)
PDEBUG(INIT_INFO, "mixer_free(): (done)\n");
}
-static int __devinit
+static int
snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
{
struct snd_ac97_bus *bus;
@@ -1237,7 +1237,7 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
return err;
}
-static int __devinit
+static int
snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
struct snd_pcm **rpcm)
{
@@ -1268,7 +1268,7 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
return 0;
}
-static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev)
+static int snd_ml403_ac97cr_probe(struct platform_device *pfdev)
{
struct snd_card *card;
struct snd_ml403_ac97cr *ml403_ac97cr = NULL;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index bc03a2046c9c..da1a29bfc85d 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -100,7 +100,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
return err;
}
-static int __devinit snd_mpu401_probe(struct platform_device *devptr)
+static int snd_mpu401_probe(struct platform_device *devptr)
{
int dev = devptr->id;
int err;
@@ -126,7 +126,7 @@ static int __devinit snd_mpu401_probe(struct platform_device *devptr)
return 0;
}
-static int __devexit snd_mpu401_remove(struct platform_device *devptr)
+static int snd_mpu401_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -137,7 +137,7 @@ static int __devexit snd_mpu401_remove(struct platform_device *devptr)
static struct platform_driver snd_mpu401_driver = {
.probe = snd_mpu401_probe,
- .remove = __devexit_p(snd_mpu401_remove),
+ .remove = snd_mpu401_remove,
.driver = {
.name = SND_MPU401_DRIVER,
.owner = THIS_MODULE,
@@ -156,8 +156,8 @@ static struct pnp_device_id snd_mpu401_pnpids[] = {
MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
-static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
- const struct pnp_device_id *id)
+static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
+ const struct pnp_device_id *id)
{
if (!pnp_port_valid(device, 0) ||
pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
@@ -182,8 +182,8 @@ static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
return 0;
}
-static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
- const struct pnp_device_id *id)
+static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
+ const struct pnp_device_id *id)
{
static int dev;
struct snd_card *card;
@@ -211,7 +211,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
return -ENODEV;
}
-static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
+static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
{
struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
@@ -223,7 +223,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = {
.name = "mpu401",
.id_table = snd_mpu401_pnpids,
.probe = snd_mpu401_pnp_probe,
- .remove = __devexit_p(snd_mpu401_pnp_remove),
+ .remove = snd_mpu401_pnp_remove,
};
#else
static struct pnp_driver snd_mpu401_pnp_driver;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index cad73af3860c..9f1815b99a15 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -583,7 +583,7 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
/*
* get ISA resources
*/
-static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
+static int snd_mtpav_get_ISA(struct mtpav *mcard)
{
if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
@@ -619,8 +619,8 @@ static struct snd_rawmidi_ops snd_mtpav_input = {
* get RAWMIDI resources
*/
-static void __devinit snd_mtpav_set_name(struct mtpav *chip,
- struct snd_rawmidi_substream *substream)
+static void snd_mtpav_set_name(struct mtpav *chip,
+ struct snd_rawmidi_substream *substream)
{
if (substream->number >= 0 && substream->number < chip->num_ports)
sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
@@ -634,7 +634,7 @@ static void __devinit snd_mtpav_set_name(struct mtpav *chip,
strcpy(substream->name, "MTP broadcast");
}
-static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
+static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
{
int rval;
struct snd_rawmidi *rawmidi;
@@ -691,7 +691,7 @@ static void snd_mtpav_free(struct snd_card *card)
/*
*/
-static int __devinit snd_mtpav_probe(struct platform_device *dev)
+static int snd_mtpav_probe(struct platform_device *dev)
{
struct snd_card *card;
int err;
@@ -746,7 +746,7 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
return err;
}
-static int __devexit snd_mtpav_remove(struct platform_device *devptr)
+static int snd_mtpav_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -757,7 +757,7 @@ static int __devexit snd_mtpav_remove(struct platform_device *devptr)
static struct platform_driver snd_mtpav_driver = {
.probe = snd_mtpav_probe,
- .remove = __devexit_p(snd_mtpav_remove),
+ .remove = snd_mtpav_remove,
.driver = {
.name = SND_MTPAV_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 2d5514b0a290..4e0dd22ba08e 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -83,9 +83,9 @@ static int snd_mts64_free(struct mts64 *mts)
return 0;
}
-static int __devinit snd_mts64_create(struct snd_card *card,
- struct pardevice *pardev,
- struct mts64 **rchip)
+static int snd_mts64_create(struct snd_card *card,
+ struct pardevice *pardev,
+ struct mts64 **rchip)
{
struct mts64 *mts;
@@ -214,7 +214,7 @@ static int mts64_device_ready(struct parport *p)
* 0 init ok
* -EIO failure
*/
-static int __devinit mts64_device_init(struct parport *p)
+static int mts64_device_init(struct parport *p)
{
int i;
@@ -290,7 +290,7 @@ static u8 mts64_map_midi_input(u8 c)
* 0 device found
* -ENODEV no device
*/
-static int __devinit mts64_probe(struct parport *p)
+static int mts64_probe(struct parport *p)
{
u8 c;
@@ -483,7 +483,7 @@ __out:
return changed;
}
-static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Playback Switch",
.index = 0,
@@ -556,7 +556,7 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,
return changed;
}
-static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Time Hours",
.index = 0,
@@ -567,7 +567,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
.put = snd_mts64_ctl_smpte_time_put
};
-static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Time Minutes",
.index = 0,
@@ -578,7 +578,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
.put = snd_mts64_ctl_smpte_time_put
};
-static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Time Seconds",
.index = 0,
@@ -589,7 +589,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
.put = snd_mts64_ctl_smpte_time_put
};
-static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Time Frames",
.index = 0,
@@ -651,7 +651,7 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,
return changed;
}
-static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_fps = {
.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
.name = "SMPTE Fps",
.index = 0,
@@ -663,11 +663,11 @@ static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
};
-static int __devinit snd_mts64_ctl_create(struct snd_card *card,
- struct mts64 *mts)
+static int snd_mts64_ctl_create(struct snd_card *card,
+ struct mts64 *mts)
{
int err, i;
- static struct snd_kcontrol_new *control[] __devinitdata = {
+ static struct snd_kcontrol_new *control[] = {
&mts64_ctl_smpte_switch,
&mts64_ctl_smpte_time_hours,
&mts64_ctl_smpte_time_minutes,
@@ -774,7 +774,7 @@ static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
};
/* Create and initialize the rawmidi component */
-static int __devinit snd_mts64_rawmidi_create(struct snd_card *card)
+static int snd_mts64_rawmidi_create(struct snd_card *card)
{
struct mts64 *mts = card->private_data;
struct snd_rawmidi *rmidi;
@@ -860,7 +860,7 @@ __out:
spin_unlock(&mts->lock);
}
-static int __devinit snd_mts64_probe_port(struct parport *p)
+static int snd_mts64_probe_port(struct parport *p)
{
struct pardevice *pardev;
int res;
@@ -884,7 +884,7 @@ static int __devinit snd_mts64_probe_port(struct parport *p)
return res;
}
-static void __devinit snd_mts64_attach(struct parport *p)
+static void snd_mts64_attach(struct parport *p)
{
struct platform_device *device;
@@ -940,7 +940,7 @@ static void snd_mts64_card_private_free(struct snd_card *card)
snd_mts64_free(mts);
}
-static int __devinit snd_mts64_probe(struct platform_device *pdev)
+static int snd_mts64_probe(struct platform_device *pdev)
{
struct pardevice *pardev;
struct parport *p;
@@ -1025,7 +1025,7 @@ __err:
return err;
}
-static int __devexit snd_mts64_remove(struct platform_device *pdev)
+static int snd_mts64_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
@@ -1038,7 +1038,7 @@ static int __devexit snd_mts64_remove(struct platform_device *pdev)
static struct platform_driver snd_mts64_driver = {
.probe = snd_mts64_probe,
- .remove = __devexit_p(snd_mts64_remove),
+ .remove = snd_mts64_remove,
.driver = {
.name = PLATFORM_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index ef171295f6d4..7a5fdb9b0afc 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -39,7 +39,7 @@ MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain.");
struct snd_pcsp pcsp_chip;
-static int __devinit snd_pcsp_create(struct snd_card *card)
+static int snd_pcsp_create(struct snd_card *card)
{
static struct snd_device_ops ops = { };
struct timespec tp;
@@ -93,7 +93,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card)
return 0;
}
-static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
+static int snd_card_pcsp_probe(int devnum, struct device *dev)
{
struct snd_card *card;
int err;
@@ -142,7 +142,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
return 0;
}
-static int __devinit alsa_card_pcsp_init(struct device *dev)
+static int alsa_card_pcsp_init(struct device *dev)
{
int err;
@@ -161,12 +161,12 @@ static int __devinit alsa_card_pcsp_init(struct device *dev)
return 0;
}
-static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
+static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
{
snd_card_free(chip->card);
}
-static int __devinit pcsp_probe(struct platform_device *dev)
+static int pcsp_probe(struct platform_device *dev)
{
int err;
@@ -184,7 +184,7 @@ static int __devinit pcsp_probe(struct platform_device *dev)
return 0;
}
-static int __devexit pcsp_remove(struct platform_device *dev)
+static int pcsp_remove(struct platform_device *dev)
{
struct snd_pcsp *chip = platform_get_drvdata(dev);
alsa_card_pcsp_exit(chip);
@@ -227,7 +227,7 @@ static struct platform_driver pcsp_platform_driver = {
.pm = PCSP_PM_OPS,
},
.probe = pcsp_probe,
- .remove = __devexit_p(pcsp_remove),
+ .remove = pcsp_remove,
.shutdown = pcsp_shutdown,
};
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index b5e2b54c2604..b874b0ad99cd 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -77,7 +77,7 @@ static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
return 0;
}
-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
+int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
{
int err;
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
index e66738c78333..d692749b8c9b 100644
--- a/sound/drivers/pcsp/pcsp_input.h
+++ b/sound/drivers/pcsp/pcsp_input.h
@@ -7,7 +7,7 @@
#ifndef __PCSP_INPUT_H__
#define __PCSP_INPUT_H__
-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
+int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
int pcspkr_input_remove(struct input_dev *dev);
void pcspkr_stop_sound(void);
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 434981dd4a61..29ebaa4ec0fd 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -334,7 +334,7 @@ static struct snd_pcm_ops snd_pcsp_playback_ops = {
.pointer = snd_pcsp_playback_pointer,
};
-int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
+int snd_pcsp_new_pcm(struct snd_pcsp *chip)
{
int err;
diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
index 6f633f4f3b96..f1e1defc09b1 100644
--- a/sound/drivers/pcsp/pcsp_mixer.c
+++ b/sound/drivers/pcsp/pcsp_mixer.c
@@ -119,17 +119,17 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
.put = pcsp_##ctl_type##_put, \
}
-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = {
+static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
};
-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = {
+static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
};
-static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
- struct snd_kcontrol_new *ctls, int num)
+static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
+ struct snd_kcontrol_new *ctls, int num)
{
int i, err;
struct snd_card *card = chip->card;
@@ -141,7 +141,7 @@ static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
return 0;
}
-int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
+int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
{
int err;
struct snd_card *card = chip->card;
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index 8364855ed14f..991018df7131 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -96,9 +96,9 @@ static int portman_free(struct portman *pm)
return 0;
}
-static int __devinit portman_create(struct snd_card *card,
- struct pardevice *pardev,
- struct portman **rchip)
+static int portman_create(struct snd_card *card,
+ struct pardevice *pardev,
+ struct portman **rchip)
{
struct portman *pm;
@@ -561,7 +561,7 @@ static struct snd_rawmidi_ops snd_portman_midi_input = {
};
/* Create and initialize the rawmidi component */
-static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
+static int snd_portman_rawmidi_create(struct snd_card *card)
{
struct portman *pm = card->private_data;
struct snd_rawmidi *rmidi;
@@ -648,7 +648,7 @@ static void snd_portman_interrupt(void *userdata)
spin_unlock(&pm->reg_lock);
}
-static int __devinit snd_portman_probe_port(struct parport *p)
+static int snd_portman_probe_port(struct parport *p)
{
struct pardevice *pardev;
int res;
@@ -672,7 +672,7 @@ static int __devinit snd_portman_probe_port(struct parport *p)
return res ? -EIO : 0;
}
-static void __devinit snd_portman_attach(struct parport *p)
+static void snd_portman_attach(struct parport *p)
{
struct platform_device *device;
@@ -728,7 +728,7 @@ static void snd_portman_card_private_free(struct snd_card *card)
portman_free(pm);
}
-static int __devinit snd_portman_probe(struct platform_device *pdev)
+static int snd_portman_probe(struct platform_device *pdev)
{
struct pardevice *pardev;
struct parport *p;
@@ -814,7 +814,7 @@ __err:
return err;
}
-static int __devexit snd_portman_remove(struct platform_device *pdev)
+static int snd_portman_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
@@ -827,7 +827,7 @@ static int __devexit snd_portman_remove(struct platform_device *pdev)
static struct platform_driver snd_portman_driver = {
.probe = snd_portman_probe,
- .remove = __devexit_p(snd_portman_remove),
+ .remove = snd_portman_remove,
.driver = {
.name = PLATFORM_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 86700671d1ac..7425dd8c1f09 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -328,7 +328,7 @@ static void snd_uart16550_buffer_timer(unsigned long data)
* return 0 if found
* return negative error if not found
*/
-static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
+static int snd_uart16550_detect(struct snd_uart16550 *uart)
{
unsigned long io_base = uart->base;
int ok;
@@ -783,14 +783,14 @@ static int snd_uart16550_dev_free(struct snd_device *device)
return snd_uart16550_free(uart);
}
-static int __devinit snd_uart16550_create(struct snd_card *card,
- unsigned long iobase,
- int irq,
- unsigned int speed,
- unsigned int base,
- int adaptor,
- int droponfull,
- struct snd_uart16550 **ruart)
+static int snd_uart16550_create(struct snd_card *card,
+ unsigned long iobase,
+ int irq,
+ unsigned int speed,
+ unsigned int base,
+ int adaptor,
+ int droponfull,
+ struct snd_uart16550 **ruart)
{
static struct snd_device_ops ops = {
.dev_free = snd_uart16550_dev_free,
@@ -863,7 +863,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
return 0;
}
-static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+static void snd_uart16550_substreams(struct snd_rawmidi_str *stream)
{
struct snd_rawmidi_substream *substream;
@@ -872,9 +872,9 @@ static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
}
}
-static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
- int outs, int ins,
- struct snd_rawmidi **rmidi)
+static int snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+ int outs, int ins,
+ struct snd_rawmidi **rmidi)
{
struct snd_rawmidi *rrawmidi;
int err;
@@ -899,7 +899,7 @@ static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
return 0;
}
-static int __devinit snd_serial_probe(struct platform_device *devptr)
+static int snd_serial_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct snd_uart16550 *uart;
@@ -982,7 +982,7 @@ static int __devinit snd_serial_probe(struct platform_device *devptr)
return err;
}
-static int __devexit snd_serial_remove(struct platform_device *devptr)
+static int snd_serial_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -993,7 +993,7 @@ static int __devexit snd_serial_remove(struct platform_device *devptr)
static struct platform_driver snd_serial_driver = {
.probe = snd_serial_probe,
- .remove = __devexit_p( snd_serial_remove),
+ .remove = snd_serial_remove,
.driver = {
.name = SND_SERIAL_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index d7d514df9058..cc4be88d7318 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -83,7 +83,7 @@ struct snd_card_virmidi {
static struct platform_device *devices[SNDRV_CARDS];
-static int __devinit snd_virmidi_probe(struct platform_device *devptr)
+static int snd_virmidi_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct snd_card_virmidi *vmidi;
@@ -129,7 +129,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
return err;
}
-static int __devexit snd_virmidi_remove(struct platform_device *devptr)
+static int snd_virmidi_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -140,7 +140,7 @@ static int __devexit snd_virmidi_remove(struct platform_device *devptr)
static struct platform_driver snd_virmidi_driver = {
.probe = snd_virmidi_probe,
- .remove = __devexit_p(snd_virmidi_remove),
+ .remove = snd_virmidi_remove,
.driver = {
.name = SND_VIRMIDI_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index 4a1fae99ac55..3014b86362bd 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -29,8 +29,6 @@
#include <sound/hwdep.h>
#include <sound/vx_core.h>
-#ifdef SND_VX_FW_LOADER
-
MODULE_FIRMWARE("vx/bx_1_vxp.b56");
MODULE_FIRMWARE("vx/bx_1_vp4.b56");
MODULE_FIRMWARE("vx/x1_1_vx2.xlx");
@@ -119,142 +117,5 @@ void snd_vx_free_firmware(struct vx_core *chip)
#endif
}
-#else /* old style firmware loading */
-
-static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_status *info)
-{
- static char *type_ids[VX_TYPE_NUMS] = {
- [VX_TYPE_BOARD] = "vxboard",
- [VX_TYPE_V2] = "vx222",
- [VX_TYPE_MIC] = "vx222",
- [VX_TYPE_VXPOCKET] = "vxpocket",
- [VX_TYPE_VXP440] = "vxp440",
- };
- struct vx_core *vx = hw->private_data;
-
- if (snd_BUG_ON(!type_ids[vx->type]))
- return -EINVAL;
- strcpy(info->id, type_ids[vx->type]);
- if (vx_is_pcmcia(vx))
- info->num_dsps = 4;
- else
- info->num_dsps = 3;
- if (vx->chip_status & VX_STAT_CHIP_INIT)
- info->chip_ready = 1;
- info->version = VX_DRIVER_VERSION;
- return 0;
-}
-
-static void free_fw(const struct firmware *fw)
-{
- if (fw) {
- vfree(fw->data);
- kfree(fw);
- }
-}
-
-static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_image *dsp)
-{
- struct vx_core *vx = hw->private_data;
- int index, err;
- struct firmware *fw;
-
- if (snd_BUG_ON(!vx->ops->load_dsp))
- return -ENXIO;
-
- fw = kmalloc(sizeof(*fw), GFP_KERNEL);
- if (! fw) {
- snd_printk(KERN_ERR "cannot allocate firmware\n");
- return -ENOMEM;
- }
- fw->size = dsp->length;
- fw->data = vmalloc(fw->size);
- if (! fw->data) {
- snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n",
- (int)fw->size);
- kfree(fw);
- return -ENOMEM;
- }
- if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) {
- free_fw(fw);
- return -EFAULT;
- }
-
- index = dsp->index;
- if (! vx_is_pcmcia(vx))
- index++;
- err = vx->ops->load_dsp(vx, index, fw);
- if (err < 0) {
- free_fw(fw);
- return err;
- }
-#ifdef CONFIG_PM
- vx->firmware[index] = fw;
-#else
- free_fw(fw);
-#endif
-
- if (index == 1)
- vx->chip_status |= VX_STAT_XILINX_LOADED;
- if (index < 3)
- return 0;
-
- /* ok, we reached to the last one */
- /* create the devices if not built yet */
- if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
- if ((err = snd_vx_pcm_new(vx)) < 0)
- return err;
-
- if ((err = snd_vx_mixer_new(vx)) < 0)
- return err;
-
- if (vx->ops->add_controls)
- if ((err = vx->ops->add_controls(vx)) < 0)
- return err;
-
- if ((err = snd_card_register(vx->card)) < 0)
- return err;
-
- vx->chip_status |= VX_STAT_DEVICE_INIT;
- }
- vx->chip_status |= VX_STAT_CHIP_INIT;
- return 0;
-}
-
-
-/* exported */
-int snd_vx_setup_firmware(struct vx_core *chip)
-{
- int err;
- struct snd_hwdep *hw;
-
- if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
- return err;
-
- hw->iface = SNDRV_HWDEP_IFACE_VX;
- hw->private_data = chip;
- hw->ops.dsp_status = vx_hwdep_dsp_status;
- hw->ops.dsp_load = vx_hwdep_dsp_load;
- hw->exclusive = 1;
- sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
- chip->hwdep = hw;
-
- return snd_card_register(chip->card);
-}
-
-/* exported */
-void snd_vx_free_firmware(struct vx_core *chip)
-{
-#ifdef CONFIG_PM
- int i;
- for (i = 0; i < 4; i++)
- free_fw(chip->firmware[i]);
-#endif
-}
-
-#endif /* SND_VX_FW_LOADER */
-
EXPORT_SYMBOL(snd_vx_setup_firmware);
EXPORT_SYMBOL(snd_vx_free_firmware);
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 26071489970b..ea063e1f8722 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -33,4 +33,17 @@ config SND_ISIGHT
To compile this driver as a module, choose M here: the module
will be called snd-isight.
+config SND_SCS1X
+ tristate "Stanton Control System 1 MIDI"
+ select SND_PCM
+ select SND_RAWMIDI
+ select SND_FIREWIRE_LIB
+ help
+ Say Y here to include support for the MIDI ports of the Stanton
+ SCS.1d/SCS.1m DJ controllers. (SCS.1m audio is still handled
+ by FFADO.)
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-scs1x.
+
endif # SND_FIREWIRE
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile
index d71ed8935f76..460179df5bb5 100644
--- a/sound/firewire/Makefile
+++ b/sound/firewire/Makefile
@@ -2,7 +2,9 @@ snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
fcp.o cmp.o amdtp.o
snd-firewire-speakers-objs := speakers.o
snd-isight-objs := isight.o
+snd-scs1x-objs := scs1x.o
obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
+obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c
new file mode 100644
index 000000000000..844a555c3b1e
--- /dev/null
+++ b/sound/firewire/scs1x.c
@@ -0,0 +1,527 @@
+/*
+ * Stanton Control System 1 MIDI driver
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include "lib.h"
+
+#define OUI_STANTON 0x001260
+#define MODEL_SCS_1M 0x001000
+#define MODEL_SCS_1D 0x002000
+
+#define HSS1394_ADDRESS 0xc007dedadadaULL
+#define HSS1394_MAX_PACKET_SIZE 64
+
+#define HSS1394_TAG_USER_DATA 0x00
+#define HSS1394_TAG_CHANGE_ADDRESS 0xf1
+
+struct scs {
+ struct snd_card *card;
+ struct fw_unit *unit;
+ struct fw_address_handler hss_handler;
+ struct fw_transaction transaction;
+ bool transaction_running;
+ bool output_idle;
+ u8 output_status;
+ u8 output_bytes;
+ bool output_escaped;
+ bool output_escape_high_nibble;
+ u8 input_escape_count;
+ struct snd_rawmidi_substream *output;
+ struct snd_rawmidi_substream *input;
+ struct tasklet_struct tasklet;
+ wait_queue_head_t idle_wait;
+ u8 *buffer;
+};
+
+static const u8 sysex_escape_prefix[] = {
+ 0xf0, /* SysEx begin */
+ 0x00, 0x01, 0x60, /* Stanton DJ */
+ 0x48, 0x53, 0x53, /* "HSS" */
+};
+
+static int scs_output_open(struct snd_rawmidi_substream *stream)
+{
+ struct scs *scs = stream->rmidi->private_data;
+
+ scs->output_status = 0;
+ scs->output_bytes = 1;
+ scs->output_escaped = false;
+
+ return 0;
+}
+
+static int scs_output_close(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static void scs_output_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+ struct scs *scs = stream->rmidi->private_data;
+
+ ACCESS_ONCE(scs->output) = up ? stream : NULL;
+ if (up) {
+ scs->output_idle = false;
+ tasklet_schedule(&scs->tasklet);
+ }
+}
+
+static void scs_write_callback(struct fw_card *card, int rcode,
+ void *data, size_t length, void *callback_data)
+{
+ struct scs *scs = callback_data;
+
+ if (rcode == RCODE_GENERATION) {
+ /* TODO: retry this packet */
+ }
+
+ scs->transaction_running = false;
+ tasklet_schedule(&scs->tasklet);
+}
+
+static bool is_valid_running_status(u8 status)
+{
+ return status >= 0x80 && status <= 0xef;
+}
+
+static bool is_one_byte_cmd(u8 status)
+{
+ return status == 0xf6 ||
+ status >= 0xf8;
+}
+
+static bool is_two_bytes_cmd(u8 status)
+{
+ return (status >= 0xc0 && status <= 0xdf) ||
+ status == 0xf1 ||
+ status == 0xf3;
+}
+
+static bool is_three_bytes_cmd(u8 status)
+{
+ return (status >= 0x80 && status <= 0xbf) ||
+ (status >= 0xe0 && status <= 0xef) ||
+ status == 0xf2;
+}
+
+static bool is_invalid_cmd(u8 status)
+{
+ return status == 0xf4 ||
+ status == 0xf5 ||
+ status == 0xf9 ||
+ status == 0xfd;
+}
+
+static void scs_output_tasklet(unsigned long data)
+{
+ struct scs *scs = (void *)data;
+ struct snd_rawmidi_substream *stream;
+ unsigned int i;
+ u8 byte;
+ struct fw_device *dev;
+ int generation;
+
+ if (scs->transaction_running)
+ return;
+
+ stream = ACCESS_ONCE(scs->output);
+ if (!stream) {
+ scs->output_idle = true;
+ wake_up(&scs->idle_wait);
+ return;
+ }
+
+ i = scs->output_bytes;
+ for (;;) {
+ if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
+ scs->output_bytes = i;
+ scs->output_idle = true;
+ wake_up(&scs->idle_wait);
+ return;
+ }
+ /*
+ * Convert from real MIDI to what I think the device expects (no
+ * running status, one command per packet, unescaped SysExs).
+ */
+ if (scs->output_escaped && byte < 0x80) {
+ if (scs->output_escape_high_nibble) {
+ if (i < HSS1394_MAX_PACKET_SIZE) {
+ scs->buffer[i] = byte << 4;
+ scs->output_escape_high_nibble = false;
+ }
+ } else {
+ scs->buffer[i++] |= byte & 0x0f;
+ scs->output_escape_high_nibble = true;
+ }
+ } else if (byte < 0x80) {
+ if (i == 1) {
+ if (!is_valid_running_status(scs->output_status))
+ continue;
+ scs->buffer[0] = HSS1394_TAG_USER_DATA;
+ scs->buffer[i++] = scs->output_status;
+ }
+ scs->buffer[i++] = byte;
+ if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
+ (i == 4 && is_three_bytes_cmd(scs->output_status)))
+ break;
+ if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
+ !memcmp(scs->buffer + 1, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix))) {
+ scs->output_escaped = true;
+ scs->output_escape_high_nibble = true;
+ i = 0;
+ }
+ if (i >= HSS1394_MAX_PACKET_SIZE)
+ i = 1;
+ } else if (byte == 0xf7) {
+ if (scs->output_escaped) {
+ if (i >= 1 && scs->output_escape_high_nibble &&
+ scs->buffer[0] != HSS1394_TAG_CHANGE_ADDRESS)
+ break;
+ } else {
+ if (i > 1 && scs->output_status == 0xf0) {
+ scs->buffer[i++] = 0xf7;
+ break;
+ }
+ }
+ i = 1;
+ scs->output_escaped = false;
+ } else if (!is_invalid_cmd(byte) &&
+ byte < 0xf8) {
+ i = 1;
+ scs->buffer[0] = HSS1394_TAG_USER_DATA;
+ scs->buffer[i++] = byte;
+ scs->output_status = byte;
+ scs->output_escaped = false;
+ if (is_one_byte_cmd(byte))
+ break;
+ }
+ }
+ scs->output_bytes = 1;
+ scs->output_escaped = false;
+
+ scs->transaction_running = true;
+ dev = fw_parent_device(scs->unit);
+ generation = dev->generation;
+ smp_rmb(); /* node_id vs. generation */
+ fw_send_request(dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST,
+ dev->node_id, generation, dev->max_speed,
+ HSS1394_ADDRESS, scs->buffer, i,
+ scs_write_callback, scs);
+}
+
+static void scs_output_drain(struct snd_rawmidi_substream *stream)
+{
+ struct scs *scs = stream->rmidi->private_data;
+
+ wait_event(scs->idle_wait, scs->output_idle);
+}
+
+static struct snd_rawmidi_ops output_ops = {
+ .open = scs_output_open,
+ .close = scs_output_close,
+ .trigger = scs_output_trigger,
+ .drain = scs_output_drain,
+};
+
+static int scs_input_open(struct snd_rawmidi_substream *stream)
+{
+ struct scs *scs = stream->rmidi->private_data;
+
+ scs->input_escape_count = 0;
+
+ return 0;
+}
+
+static int scs_input_close(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static void scs_input_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+ struct scs *scs = stream->rmidi->private_data;
+
+ ACCESS_ONCE(scs->input) = up ? stream : NULL;
+}
+
+static void scs_input_escaped_byte(struct snd_rawmidi_substream *stream,
+ u8 byte)
+{
+ u8 nibbles[2];
+
+ nibbles[0] = byte >> 4;
+ nibbles[1] = byte & 0x0f;
+ snd_rawmidi_receive(stream, nibbles, 2);
+}
+
+static void scs_input_midi_byte(struct scs *scs,
+ struct snd_rawmidi_substream *stream,
+ u8 byte)
+{
+ if (scs->input_escape_count > 0) {
+ scs_input_escaped_byte(stream, byte);
+ scs->input_escape_count--;
+ if (scs->input_escape_count == 0)
+ snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
+ } else if (byte == 0xf9) {
+ snd_rawmidi_receive(stream, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix));
+ scs_input_escaped_byte(stream, 0x00);
+ scs_input_escaped_byte(stream, 0xf9);
+ scs->input_escape_count = 3;
+ } else {
+ snd_rawmidi_receive(stream, &byte, 1);
+ }
+}
+
+static void scs_input_packet(struct scs *scs,
+ struct snd_rawmidi_substream *stream,
+ const u8 *data, unsigned int bytes)
+{
+ unsigned int i;
+
+ if (data[0] == HSS1394_TAG_USER_DATA) {
+ for (i = 1; i < bytes; ++i)
+ scs_input_midi_byte(scs, stream, data[i]);
+ } else {
+ snd_rawmidi_receive(stream, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix));
+ for (i = 0; i < bytes; ++i)
+ scs_input_escaped_byte(stream, data[i]);
+ snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
+ }
+}
+
+static struct snd_rawmidi_ops input_ops = {
+ .open = scs_input_open,
+ .close = scs_input_close,
+ .trigger = scs_input_trigger,
+};
+
+static int scs_create_midi(struct scs *scs)
+{
+ struct snd_rawmidi *rmidi;
+ int err;
+
+ err = snd_rawmidi_new(scs->card, "SCS.1x", 0, 1, 1, &rmidi);
+ if (err < 0)
+ return err;
+ snprintf(rmidi->name, sizeof(rmidi->name),
+ "%s MIDI", scs->card->shortname);
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+ rmidi->private_data = scs;
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &output_ops);
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &input_ops);
+
+ return 0;
+}
+
+static void handle_hss(struct fw_card *card, struct fw_request *request,
+ int tcode, int destination, int source, int generation,
+ unsigned long long offset, void *data, size_t length,
+ void *callback_data)
+{
+ struct scs *scs = callback_data;
+ struct snd_rawmidi_substream *stream;
+
+ if (offset != scs->hss_handler.offset) {
+ fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+ return;
+ }
+ if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
+ tcode != TCODE_WRITE_BLOCK_REQUEST) {
+ fw_send_response(card, request, RCODE_TYPE_ERROR);
+ return;
+ }
+
+ if (length >= 1) {
+ stream = ACCESS_ONCE(scs->input);
+ if (stream)
+ scs_input_packet(scs, stream, data, length);
+ }
+
+ fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static int scs_init_hss_address(struct scs *scs)
+{
+ __be64 data;
+ int err;
+
+ data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
+ scs->hss_handler.offset);
+ err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
+ HSS1394_ADDRESS, &data, 8);
+ if (err < 0)
+ dev_err(&scs->unit->device, "HSS1394 communication failed\n");
+
+ return err;
+}
+
+static void scs_card_free(struct snd_card *card)
+{
+ struct scs *scs = card->private_data;
+
+ fw_core_remove_address_handler(&scs->hss_handler);
+ kfree(scs->buffer);
+}
+
+static int scs_probe(struct device *unit_dev)
+{
+ struct fw_unit *unit = fw_unit(unit_dev);
+ struct fw_device *fw_dev = fw_parent_device(unit);
+ struct snd_card *card;
+ struct scs *scs;
+ int err;
+
+ err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card);
+ if (err < 0)
+ return err;
+ snd_card_set_dev(card, unit_dev);
+
+ scs = card->private_data;
+ scs->card = card;
+ scs->unit = unit;
+ tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
+ init_waitqueue_head(&scs->idle_wait);
+ scs->output_idle = true;
+
+ scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL);
+ if (!scs->buffer)
+ goto err_card;
+
+ scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
+ scs->hss_handler.address_callback = handle_hss;
+ scs->hss_handler.callback_data = scs;
+ err = fw_core_add_address_handler(&scs->hss_handler,
+ &fw_high_memory_region);
+ if (err < 0)
+ goto err_buffer;
+
+ card->private_free = scs_card_free;
+
+ strcpy(card->driver, "SCS.1x");
+ strcpy(card->shortname, "SCS.1x");
+ fw_csr_string(unit->directory, CSR_MODEL,
+ card->shortname, sizeof(card->shortname));
+ snprintf(card->longname, sizeof(card->longname),
+ "Stanton DJ %s (GUID %08x%08x) at %s, S%d",
+ card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4],
+ dev_name(&unit->device), 100 << fw_dev->max_speed);
+ strcpy(card->mixername, card->shortname);
+
+ err = scs_init_hss_address(scs);
+ if (err < 0)
+ goto err_card;
+
+ err = scs_create_midi(scs);
+ if (err < 0)
+ goto err_card;
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto err_card;
+
+ dev_set_drvdata(unit_dev, scs);
+
+ return 0;
+
+err_buffer:
+ kfree(scs->buffer);
+err_card:
+ snd_card_free(card);
+ return err;
+}
+
+static int scs_remove(struct device *dev)
+{
+ struct scs *scs = dev_get_drvdata(dev);
+
+ snd_card_disconnect(scs->card);
+
+ ACCESS_ONCE(scs->output) = NULL;
+ ACCESS_ONCE(scs->input) = NULL;
+
+ wait_event(scs->idle_wait, scs->output_idle);
+
+ tasklet_kill(&scs->tasklet);
+
+ snd_card_free_when_closed(scs->card);
+
+ return 0;
+}
+
+static void scs_update(struct fw_unit *unit)
+{
+ struct scs *scs = dev_get_drvdata(&unit->device);
+ __be64 data;
+
+ data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
+ scs->hss_handler.offset);
+ snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
+ HSS1394_ADDRESS, &data, 8);
+}
+
+static const struct ieee1394_device_id scs_id_table[] = {
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_STANTON,
+ .model_id = MODEL_SCS_1M,
+ },
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_STANTON,
+ .model_id = MODEL_SCS_1D,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(ieee1394, scs_id_table);
+
+MODULE_DESCRIPTION("SCS.1x MIDI driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static struct fw_driver scs_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .bus = &fw_bus_type,
+ .probe = scs_probe,
+ .remove = scs_remove,
+ },
+ .update = scs_update,
+ .id_table = scs_id_table,
+};
+
+static int __init alsa_scs1x_init(void)
+{
+ return driver_register(&scs_driver.driver);
+}
+
+static void __exit alsa_scs1x_exit(void)
+{
+ driver_unregister(&scs_driver.driver);
+}
+
+module_init(alsa_scs1x_init);
+module_exit(alsa_scs1x_exit);
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index 297244e658d9..d6846557f270 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -663,7 +663,7 @@ static void fwspk_card_free(struct snd_card *card)
mutex_destroy(&fwspk->mutex);
}
-static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
+static const struct device_info *fwspk_detect(struct fw_device *dev)
{
static const struct device_info griffin_firewave = {
.driver_name = "FireWave",
@@ -699,7 +699,7 @@ static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
return NULL;
}
-static int __devinit fwspk_probe(struct device *unit_dev)
+static int fwspk_probe(struct device *unit_dev)
{
struct fw_unit *unit = fw_unit(unit_dev);
struct fw_device *fw_dev = fw_parent_device(unit);
@@ -770,7 +770,7 @@ error:
return err;
}
-static int __devexit fwspk_remove(struct device *dev)
+static int fwspk_remove(struct device *dev)
{
struct fwspk *fwspk = dev_get_drvdata(dev);
@@ -834,7 +834,7 @@ static struct fw_driver fwspk_driver = {
.name = KBUILD_MODNAME,
.bus = &fw_bus_type,
.probe = fwspk_probe,
- .remove = __devexit_p(fwspk_remove),
+ .remove = fwspk_remove,
},
.update = fwspk_bus_reset,
.id_table = fwspk_id_table,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index a38d9643e9d8..affa13480659 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -425,7 +425,7 @@ config SND_WAVEFRONT
config SND_MSND_PINNACLE
tristate "Turtle Beach MultiSound Pinnacle/Fiji driver"
- depends on X86 && EXPERIMENTAL
+ depends on X86
select FW_LOADER
select SND_MPU401_UART
select SND_PCM
@@ -438,7 +438,7 @@ config SND_MSND_PINNACLE
config SND_MSND_CLASSIC
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
- depends on X86 && EXPERIMENTAL
+ depends on X86
select FW_LOADER
select SND_MPU401_UART
select SND_PCM
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 2c2f829c3fd7..26ce26a5884d 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -94,8 +94,8 @@ MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids);
#define DRIVER_NAME "snd-card-ad1816a"
-static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -135,8 +135,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
return 0;
}
-static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
int error;
struct snd_card *card;
@@ -217,10 +217,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
return 0;
}
-static unsigned int __devinitdata ad1816a_devices;
+static unsigned int ad1816a_devices;
-static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
static int dev;
int res;
@@ -238,7 +238,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
+static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -270,7 +270,7 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
.name = "ad1816a",
.id_table = snd_ad1816a_pnpids,
.probe = snd_ad1816a_pnp_detect,
- .remove = __devexit_p(snd_ad1816a_pnp_remove),
+ .remove = snd_ad1816a_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_ad1816a_pnp_suspend,
.resume = snd_ad1816a_pnp_resume,
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index db64df6023e0..f0fd98e695e3 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -537,7 +537,7 @@ void snd_ad1816a_resume(struct snd_ad1816a *chip)
}
#endif
-static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip)
+static int snd_ad1816a_probe(struct snd_ad1816a *chip)
{
unsigned long flags;
@@ -583,7 +583,7 @@ static int snd_ad1816a_dev_free(struct snd_device *device)
return snd_ad1816a_free(chip);
}
-static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
+static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
{
switch (chip->hardware) {
case AD1816A_HW_AD1816A: return "AD1816A";
@@ -596,9 +596,9 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
}
}
-int __devinit snd_ad1816a_create(struct snd_card *card,
- unsigned long port, int irq, int dma1, int dma2,
- struct snd_ad1816a *chip)
+int snd_ad1816a_create(struct snd_card *card,
+ unsigned long port, int irq, int dma1, int dma2,
+ struct snd_ad1816a *chip)
{
static struct snd_device_ops ops = {
.dev_free = snd_ad1816a_dev_free,
@@ -675,7 +675,7 @@ static struct snd_pcm_ops snd_ad1816a_capture_ops = {
.pointer = snd_ad1816a_capture_pointer,
};
-int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
+int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
{
int error;
struct snd_pcm *pcm;
@@ -702,7 +702,8 @@ int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_p
return 0;
}
-int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer)
+int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
+ struct snd_timer **rtimer)
{
struct snd_timer *timer;
struct snd_timer_id tid;
@@ -923,7 +924,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
-static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ad1816a_controls[] = {
AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1,
db_scale_5bit),
@@ -969,7 +970,7 @@ AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
};
-int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
+int snd_ad1816a_mixer(struct snd_ad1816a *chip)
{
struct snd_card *card;
unsigned int idx;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 2af77faefbb1..c214ecf45400 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
module_param_array(thinkpad, bool, NULL, 0444);
MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
-static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
+static int snd_ad1848_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
@@ -84,7 +84,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
return 1;
}
-static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
+static int snd_ad1848_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_wss *chip;
@@ -132,7 +132,7 @@ out: snd_card_free(card);
return error;
}
-static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
+static int snd_ad1848_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -164,7 +164,7 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_ad1848_driver = {
.match = snd_ad1848_match,
.probe = snd_ad1848_probe,
- .remove = __devexit_p(snd_ad1848_remove),
+ .remove = snd_ad1848_remove,
#ifdef CONFIG_PM
.suspend = snd_ad1848_suspend,
.resume = snd_ad1848_resume,
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index 4d50c69f3290..d26545543732 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -30,7 +30,7 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
+static int snd_adlib_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
@@ -47,7 +47,7 @@ static void snd_adlib_free(struct snd_card *card)
release_and_free_resource(card->private_data);
}
-static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
+static int snd_adlib_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_opl3 *opl3;
@@ -98,7 +98,7 @@ out: snd_card_free(card);
return error;
}
-static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
+static int snd_adlib_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -108,7 +108,7 @@ static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
static struct isa_driver snd_adlib_driver = {
.match = snd_adlib_match,
.probe = snd_adlib_probe,
- .remove = __devexit_p(snd_adlib_remove),
+ .remove = snd_adlib_remove,
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index f7cdaf51512d..10f08a18fe3b 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -117,9 +117,9 @@ static struct pnp_card_device_id snd_als100_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
-static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -183,9 +183,9 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
return 0;
}
-static int __devinit snd_card_als100_probe(int dev,
- struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_als100_probe(int dev,
+ struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
int error;
struct snd_sb *chip;
@@ -286,10 +286,10 @@ static int __devinit snd_card_als100_probe(int dev,
return 0;
}
-static unsigned int __devinitdata als100_devices;
+static unsigned int als100_devices;
-static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_als100_pnp_detect(struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
static int dev;
int res;
@@ -307,7 +307,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
+static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -344,7 +344,7 @@ static struct pnp_card_driver als100_pnpc_driver = {
.name = "als100",
.id_table = snd_als100_pnpids,
.probe = snd_als100_pnp_detect,
- .remove = __devexit_p(snd_als100_pnp_remove),
+ .remove = snd_als100_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_als100_pnp_suspend,
.resume = snd_als100_pnp_resume,
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index 6a2c78ef1d8f..db301ff94ec2 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -99,9 +99,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
#define DRIVER_NAME "snd-card-azt2320"
-static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -147,7 +147,7 @@ static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acar
}
/* same of snd_sbdsp_command by Jaroslav Kysela */
-static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val)
+static int snd_card_azt2320_command(unsigned long port, unsigned char val)
{
int i;
unsigned long limit;
@@ -161,7 +161,7 @@ static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char
return -EBUSY;
}
-static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
+static int snd_card_azt2320_enable_wss(unsigned long port)
{
int error;
@@ -174,9 +174,9 @@ static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
return 0;
}
-static int __devinit snd_card_azt2320_probe(int dev,
- struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_azt2320_probe(int dev,
+ struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
int error;
struct snd_card *card;
@@ -264,10 +264,10 @@ static int __devinit snd_card_azt2320_probe(int dev,
return 0;
}
-static unsigned int __devinitdata azt2320_devices;
+static unsigned int azt2320_devices;
-static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
static int dev;
int res;
@@ -285,7 +285,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
+static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -320,7 +320,7 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
.name = "azt2320",
.id_table = snd_azt2320_pnpids,
.probe = snd_azt2320_pnp_detect,
- .remove = __devexit_p(snd_azt2320_pnp_remove),
+ .remove = snd_azt2320_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_azt2320_pnp_suspend,
.resume = snd_azt2320_pnp_resume,
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index bde60139bb95..a7369fe19a6f 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -140,7 +140,7 @@ static void snd_cmi8328_cfg_restore(u16 port, u8 cfg[])
snd_cmi8328_cfg_write(port, CFG3, cfg[2]);
}
-static int __devinit snd_cmi8328_mixer(struct snd_wss *chip)
+static int snd_cmi8328_mixer(struct snd_wss *chip)
{
struct snd_card *card;
struct snd_ctl_elem_id id1, id2;
@@ -212,7 +212,7 @@ int array_find_l(long array[], long item)
return -1;
}
-static int __devinit snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
+static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
{
struct snd_card *card;
struct snd_opl3 *opl3;
@@ -401,7 +401,7 @@ error:
return err;
}
-static int __devexit snd_cmi8328_remove(struct device *pdev, unsigned int dev)
+static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(pdev);
struct snd_cmi8328 *cmi = card->private_data;
@@ -459,7 +459,7 @@ static int snd_cmi8328_resume(struct device *pdev, unsigned int n)
static struct isa_driver snd_cmi8328_driver = {
.probe = snd_cmi8328_probe,
- .remove = __devexit_p(snd_cmi8328_remove),
+ .remove = snd_cmi8328_remove,
#ifdef CONFIG_PM
.suspend = snd_cmi8328_suspend,
.resume = snd_cmi8328_resume,
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 7bd5e337ee93..c707c52268ab 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -193,7 +193,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
#endif
-static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmi8330_controls[] = {
WSS_DOUBLE("Master Playback Volume", 0,
CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
WSS_SINGLE("Loud Playback Switch", 0,
@@ -249,7 +249,7 @@ WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
};
#ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
+static struct sbmix_elem cmi8330_sb_mixers[] = {
SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
@@ -267,7 +267,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
};
-static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
+static unsigned char cmi8330_sb_init_values[][2] = {
{ SB_DSP4_MASTER_DEV + 0, 0 },
{ SB_DSP4_MASTER_DEV + 1, 0 },
{ SB_DSP4_PCM_DEV + 0, 0 },
@@ -281,7 +281,7 @@ static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
};
-static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
+static int cmi8330_add_sb_mixers(struct snd_sb *chip)
{
int idx, err;
unsigned long flags;
@@ -306,7 +306,7 @@ static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
}
#endif
-static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
+static int snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
{
unsigned int idx;
int err;
@@ -329,9 +329,9 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
}
#ifdef CONFIG_PNP
-static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -437,7 +437,7 @@ static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream)
return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
}
-static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
+static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
{
struct snd_pcm *pcm;
const struct snd_pcm_ops *ops;
@@ -532,7 +532,7 @@ static int snd_cmi8330_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
+static int snd_cmi8330_probe(struct snd_card *card, int dev)
{
struct snd_cmi8330 *acard;
int i, err;
@@ -613,8 +613,8 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __devinit snd_cmi8330_isa_match(struct device *pdev,
- unsigned int dev)
+static int snd_cmi8330_isa_match(struct device *pdev,
+ unsigned int dev)
{
if (!enable[dev] || is_isapnp_selected(dev))
return 0;
@@ -629,8 +629,8 @@ static int __devinit snd_cmi8330_isa_match(struct device *pdev,
return 1;
}
-static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
- unsigned int dev)
+static int snd_cmi8330_isa_probe(struct device *pdev,
+ unsigned int dev)
{
struct snd_card *card;
int err;
@@ -647,8 +647,8 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
return 0;
}
-static int __devexit snd_cmi8330_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_cmi8330_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -673,7 +673,7 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_cmi8330_driver = {
.match = snd_cmi8330_isa_match,
.probe = snd_cmi8330_isa_probe,
- .remove = __devexit_p(snd_cmi8330_isa_remove),
+ .remove = snd_cmi8330_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_cmi8330_isa_suspend,
.resume = snd_cmi8330_isa_resume,
@@ -685,8 +685,8 @@ static struct isa_driver snd_cmi8330_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -717,7 +717,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
+static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -740,7 +740,7 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
.name = "cmi8330",
.id_table = snd_cmi8330_pnpids,
.probe = snd_cmi8330_pnp_detect,
- .remove = __devexit_p(snd_cmi8330_pnp_remove),
+ .remove = snd_cmi8330_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_cmi8330_pnp_suspend,
.resume = snd_cmi8330_pnp_resume,
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 99dda45e82f5..aa7a5d86e480 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
-static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
+static int snd_cs4231_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
@@ -88,7 +88,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
return 1;
}
-static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
+static int snd_cs4231_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_wss *chip;
@@ -148,7 +148,7 @@ out: snd_card_free(card);
return error;
}
-static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
+static int snd_cs4231_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -180,7 +180,7 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_cs4231_driver = {
.match = snd_cs4231_match,
.probe = snd_cs4231_probe,
- .remove = __devexit_p(snd_cs4231_remove),
+ .remove = snd_cs4231_remove,
#ifdef CONFIG_PM
.suspend = snd_cs4231_suspend,
.resume = snd_cs4231_resume,
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 740c51a1ed7b..252e9fb37db3 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -251,7 +251,7 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
/* WSS initialization */
-static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
{
if (pnp_activate_dev(pdev) < 0) {
printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n");
@@ -272,7 +272,7 @@ static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
}
/* CTRL initialization */
-static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
{
if (pnp_activate_dev(pdev) < 0) {
printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
@@ -284,7 +284,7 @@ static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
}
/* MPU initialization */
-static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
{
if (pnp_activate_dev(pdev) < 0) {
printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
@@ -303,9 +303,9 @@ static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
return 0;
}
-static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
- struct pnp_dev *pdev,
- struct pnp_dev *cdev)
+static int snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
+ struct pnp_dev *pdev,
+ struct pnp_dev *cdev)
{
acard->wss = pdev;
if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0)
@@ -317,9 +317,9 @@ static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
return 0;
}
-static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
if (acard->wss == NULL)
@@ -378,7 +378,7 @@ static int snd_cs423x_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
+static int snd_cs423x_probe(struct snd_card *card, int dev)
{
struct snd_card_cs4236 *acard;
struct snd_pcm *pcm;
@@ -456,8 +456,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __devinit snd_cs423x_isa_match(struct device *pdev,
- unsigned int dev)
+static int snd_cs423x_isa_match(struct device *pdev,
+ unsigned int dev)
{
if (!enable[dev] || is_isapnp_selected(dev))
return 0;
@@ -481,8 +481,8 @@ static int __devinit snd_cs423x_isa_match(struct device *pdev,
return 1;
}
-static int __devinit snd_cs423x_isa_probe(struct device *pdev,
- unsigned int dev)
+static int snd_cs423x_isa_probe(struct device *pdev,
+ unsigned int dev)
{
struct snd_card *card;
int err;
@@ -500,8 +500,8 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev,
return 0;
}
-static int __devexit snd_cs423x_isa_remove(struct device *pdev,
- unsigned int dev)
+static int snd_cs423x_isa_remove(struct device *pdev,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
@@ -540,7 +540,7 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver cs423x_isa_driver = {
.match = snd_cs423x_isa_match,
.probe = snd_cs423x_isa_probe,
- .remove = __devexit_p(snd_cs423x_isa_remove),
+ .remove = snd_cs423x_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_isa_suspend,
.resume = snd_cs423x_isa_resume,
@@ -552,8 +552,8 @@ static struct isa_driver cs423x_isa_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
- const struct pnp_device_id *id)
+static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+ const struct pnp_device_id *id)
{
static int dev;
int err;
@@ -597,7 +597,7 @@ static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
return 0;
}
-static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev)
+static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
{
snd_card_free(pnp_get_drvdata(pdev));
pnp_set_drvdata(pdev, NULL);
@@ -619,15 +619,15 @@ static struct pnp_driver cs423x_pnp_driver = {
.name = "cs423x-pnpbios",
.id_table = snd_cs423x_pnpbiosids,
.probe = snd_cs423x_pnpbios_detect,
- .remove = __devexit_p(snd_cs423x_pnp_remove),
+ .remove = snd_cs423x_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_pnp_suspend,
.resume = snd_cs423x_pnp_resume,
#endif
};
-static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -659,7 +659,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
+static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -682,7 +682,7 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
.name = CS423X_ISAPNP_DRIVER,
.id_table = snd_cs423x_pnpids,
.probe = snd_cs423x_pnpc_detect,
- .remove = __devexit_p(snd_cs423x_pnpc_remove),
+ .remove = snd_cs423x_pnpc_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_pnpc_suspend,
.resume = snd_cs423x_pnpc_resume,
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index b036e60f62d1..102874a703d4 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -90,13 +90,13 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
#define is_isapnp_selected(dev) 0
#endif
-static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
+static int snd_es1688_match(struct device *dev, unsigned int n)
{
return enable[n] && !is_isapnp_selected(n);
}
-static int __devinit snd_es1688_legacy_create(struct snd_card *card,
- struct device *dev, unsigned int n)
+static int snd_es1688_legacy_create(struct snd_card *card,
+ struct device *dev, unsigned int n)
{
struct snd_es1688 *chip = card->private_data;
static long possible_ports[] = {0x220, 0x240, 0x260};
@@ -134,7 +134,7 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card,
return error;
}
-static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
+static int snd_es1688_probe(struct snd_card *card, unsigned int n)
{
struct snd_es1688 *chip = card->private_data;
struct snd_opl3 *opl3;
@@ -182,7 +182,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
return snd_card_register(card);
}
-static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n)
+static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
int error;
@@ -210,7 +210,7 @@ out:
return error;
}
-static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
+static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -220,7 +220,7 @@ static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
static struct isa_driver snd_es1688_driver = {
.match = snd_es1688_match,
.probe = snd_es1688_isa_probe,
- .remove = __devexit_p(snd_es1688_isa_remove),
+ .remove = snd_es1688_isa_remove,
#if 0 /* FIXME */
.suspend = snd_es1688_suspend,
.resume = snd_es1688_resume,
@@ -233,9 +233,9 @@ static struct isa_driver snd_es1688_driver = {
static int snd_es968_pnp_is_probed;
#ifdef CONFIG_PNP
-static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
- struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_es968_pnp(struct snd_card *card, unsigned int n,
+ struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
struct snd_es1688 *chip = card->private_data;
struct pnp_dev *pdev;
@@ -258,8 +258,8 @@ static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
mpu_irq[n], dma8[n], ES1688_HW_AUTO);
}
-static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
struct snd_card *card;
static unsigned int dev;
@@ -295,7 +295,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
+static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -338,7 +338,7 @@ static struct pnp_card_driver es968_pnpc_driver = {
.name = DEV_NAME " PnP",
.id_table = snd_es968_pnpids,
.probe = snd_es968_pnp_detect,
- .remove = __devexit_p(snd_es968_pnp_remove),
+ .remove = snd_es968_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_es968_pnp_suspend,
.resume = snd_es968_pnp_resume,
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index c20baafd9b7c..24380efe31a1 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -348,7 +348,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
}
-static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
+static int snd_es18xx_reset(struct snd_es18xx *chip)
{
int i;
outb(0x03, chip->port + 0x06);
@@ -1363,7 +1363,7 @@ static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
};
-static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
+static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
{
int data;
@@ -1372,8 +1372,8 @@ static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned ch
return data;
}
-static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
- unsigned char reg, unsigned char data)
+static void snd_es18xx_config_write(struct snd_es18xx *chip,
+ unsigned char reg, unsigned char data)
{
/* No need for spinlocks, this function is used only in
otherwise protected init code */
@@ -1384,9 +1384,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
#endif
}
-static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
- unsigned long mpu_port,
- unsigned long fm_port)
+static int snd_es18xx_initialize(struct snd_es18xx *chip,
+ unsigned long mpu_port,
+ unsigned long fm_port)
{
int mask = 0;
@@ -1549,7 +1549,7 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
return 0;
}
-static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
+static int snd_es18xx_identify(struct snd_es18xx *chip)
{
int hi,lo;
@@ -1618,9 +1618,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
return 0;
}
-static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
- unsigned long mpu_port,
- unsigned long fm_port)
+static int snd_es18xx_probe(struct snd_es18xx *chip,
+ unsigned long mpu_port,
+ unsigned long fm_port)
{
if (snd_es18xx_identify(chip) < 0) {
snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1680,8 +1680,8 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
.pointer = snd_es18xx_capture_pointer,
};
-static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
- struct snd_pcm **rpcm)
+static int snd_es18xx_pcm(struct snd_card *card, int device,
+ struct snd_pcm **rpcm)
{
struct snd_es18xx *chip = card->private_data;
struct snd_pcm *pcm;
@@ -1777,11 +1777,11 @@ static int snd_es18xx_dev_free(struct snd_device *device)
return snd_es18xx_free(device->card);
}
-static int __devinit snd_es18xx_new_device(struct snd_card *card,
- unsigned long port,
- unsigned long mpu_port,
- unsigned long fm_port,
- int irq, int dma1, int dma2)
+static int snd_es18xx_new_device(struct snd_card *card,
+ unsigned long port,
+ unsigned long mpu_port,
+ unsigned long fm_port,
+ int irq, int dma1, int dma2)
{
struct snd_es18xx *chip = card->private_data;
static struct snd_device_ops ops = {
@@ -1839,7 +1839,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
return 0;
}
-static int __devinit snd_es18xx_mixer(struct snd_card *card)
+static int snd_es18xx_mixer(struct snd_card *card)
{
struct snd_es18xx *chip = card->private_data;
int err;
@@ -2016,7 +2016,7 @@ static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
/* PnP main device initialization */
-static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
+static int snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
{
if (pnp_activate_dev(pdev) < 0) {
snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
@@ -2043,8 +2043,8 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
return 0;
}
-static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
- struct pnp_dev *pdev)
+static int snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
+ struct pnp_dev *pdev)
{
chip->dev = pdev;
if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
@@ -2073,9 +2073,9 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
if (chip->dev == NULL)
@@ -2111,7 +2111,7 @@ static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
sizeof(struct snd_es18xx), cardp);
}
-static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
+static int snd_audiodrive_probe(struct snd_card *card, int dev)
{
struct snd_es18xx *chip = card->private_data;
struct snd_opl3 *opl3;
@@ -2169,12 +2169,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
+static int snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
{
return enable[dev] && !is_isapnp_selected(dev);
}
-static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
+static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
{
struct snd_card *card;
int err;
@@ -2191,7 +2191,7 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
return 0;
}
-static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
+static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
{
int err;
static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
@@ -2231,8 +2231,8 @@ static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static int __devexit snd_es18xx_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_es18xx_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -2257,7 +2257,7 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_es18xx_isa_driver = {
.match = snd_es18xx_isa_match,
.probe = snd_es18xx_isa_probe,
- .remove = __devexit_p(snd_es18xx_isa_remove),
+ .remove = snd_es18xx_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_es18xx_isa_suspend,
.resume = snd_es18xx_isa_resume,
@@ -2269,8 +2269,8 @@ static struct isa_driver snd_es18xx_isa_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
- const struct pnp_device_id *id)
+static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
+ const struct pnp_device_id *id)
{
static int dev;
int err;
@@ -2302,7 +2302,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
return 0;
}
-static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev)
+static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
{
snd_card_free(pnp_get_drvdata(pdev));
pnp_set_drvdata(pdev, NULL);
@@ -2323,15 +2323,15 @@ static struct pnp_driver es18xx_pnp_driver = {
.name = "es18xx-pnpbios",
.id_table = snd_audiodrive_pnpbiosids,
.probe = snd_audiodrive_pnp_detect,
- .remove = __devexit_p(snd_audiodrive_pnp_remove),
+ .remove = snd_audiodrive_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_audiodrive_pnp_suspend,
.resume = snd_audiodrive_pnp_resume,
#endif
};
-static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -2363,7 +2363,7 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard)
+static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -2387,7 +2387,7 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
.name = "es18xx",
.id_table = snd_audiodrive_pnpids,
.probe = snd_audiodrive_pnpc_detect,
- .remove = __devexit_p(snd_audiodrive_pnpc_remove),
+ .remove = snd_audiodrive_pnpc_remove,
#ifdef CONFIG_PM
.suspend = snd_audiodrive_pnpc_suspend,
.resume = snd_audiodrive_pnpc_resume,
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index 55e20782858d..672184e3221a 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -84,7 +84,7 @@ MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
#define DSP_COMMAND_GET_VERSION 0xe1
-static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
+static int dsp_get_byte(void __iomem *port, u8 *val)
{
int loops = 1000;
@@ -97,7 +97,7 @@ static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
return 0;
}
-static int __devinit dsp_reset(void __iomem *port)
+static int dsp_reset(void __iomem *port)
{
u8 val;
@@ -111,7 +111,7 @@ static int __devinit dsp_reset(void __iomem *port)
return 0;
}
-static int __devinit dsp_command(void __iomem *port, u8 cmd)
+static int dsp_command(void __iomem *port, u8 cmd)
{
int loops = 1000;
@@ -124,7 +124,7 @@ static int __devinit dsp_command(void __iomem *port, u8 cmd)
return 0;
}
-static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
+static int dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
{
int err;
@@ -161,7 +161,7 @@ static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
#define WSS_SIGNATURE 4
-static int __devinit wss_detect(void __iomem *wss_port)
+static int wss_detect(void __iomem *wss_port)
{
if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
return -ENODEV;
@@ -204,7 +204,7 @@ struct snd_galaxy {
static u32 config[SNDRV_CARDS];
static u8 wss_config[SNDRV_CARDS];
-static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
+static int snd_galaxy_match(struct device *dev, unsigned int n)
{
if (!enable[n])
return 0;
@@ -379,7 +379,7 @@ fm:
return 1;
}
-static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
+static int galaxy_init(struct snd_galaxy *galaxy, u8 *type)
{
u8 major;
u8 minor;
@@ -411,7 +411,7 @@ static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
return 0;
}
-static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
+static int galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
{
int err;
@@ -449,7 +449,7 @@ static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
msleep(10);
}
-static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
+static void galaxy_config(struct snd_galaxy *galaxy, u32 config)
{
int i;
@@ -461,7 +461,7 @@ static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
galaxy_set_config(galaxy, config);
}
-static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
+static int galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
{
int err;
@@ -498,7 +498,7 @@ static void snd_galaxy_free(struct snd_card *card)
}
}
-static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
+static int snd_galaxy_probe(struct device *dev, unsigned int n)
{
struct snd_galaxy *galaxy;
struct snd_wss *chip;
@@ -620,7 +620,7 @@ error:
return err;
}
-static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
+static int snd_galaxy_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -630,7 +630,7 @@ static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
static struct isa_driver snd_galaxy_driver = {
.match = snd_galaxy_match,
.probe = snd_galaxy_probe,
- .remove = __devexit_p(snd_galaxy_remove),
+ .remove = snd_galaxy_remove,
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index bf6333671613..16bca4e96c08 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -73,13 +73,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
-static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n)
+static int snd_gusclassic_match(struct device *dev, unsigned int n)
{
return enable[n];
}
-static int __devinit snd_gusclassic_create(struct snd_card *card,
- struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+static int snd_gusclassic_create(struct snd_card *card,
+ struct device *dev, unsigned int n,
+ struct snd_gus_card **rgus)
{
static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
@@ -123,7 +124,7 @@ static int __devinit snd_gusclassic_create(struct snd_card *card,
return error;
}
-static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
+static int snd_gusclassic_detect(struct snd_gus_card *gus)
{
unsigned char d;
@@ -142,7 +143,7 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
return 0;
}
-static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
+static int snd_gusclassic_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_gus_card *gus;
@@ -211,7 +212,7 @@ out: snd_card_free(card);
return error;
}
-static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
+static int snd_gusclassic_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -221,7 +222,7 @@ static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
static struct isa_driver snd_gusclassic_driver = {
.match = snd_gusclassic_match,
.probe = snd_gusclassic_probe,
- .remove = __devexit_p(snd_gusclassic_remove),
+ .remove = snd_gusclassic_remove,
#if 0 /* FIXME */
.suspend = snd_gusclassic_suspend,
.remove = snd_gusclassic_remove,
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index bc10cc26e5f9..0b9c2426b49f 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -89,13 +89,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
-static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n)
+static int snd_gusextreme_match(struct device *dev, unsigned int n)
{
return enable[n];
}
-static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
- struct snd_es1688 *chip, struct device *dev, unsigned int n)
+static int snd_gusextreme_es1688_create(struct snd_card *card,
+ struct snd_es1688 *chip,
+ struct device *dev, unsigned int n)
{
static long possible_ports[] = {0x220, 0x240, 0x260};
static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -132,8 +133,9 @@ static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
return error;
}
-static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
- struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+static int snd_gusextreme_gus_card_create(struct snd_card *card,
+ struct device *dev, unsigned int n,
+ struct snd_gus_card **rgus)
{
static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
@@ -156,8 +158,8 @@ static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
0, channels[n], pcm_channels[n], 0, rgus);
}
-static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
- struct snd_es1688 *es1688)
+static int snd_gusextreme_detect(struct snd_gus_card *gus,
+ struct snd_es1688 *es1688)
{
unsigned long flags;
unsigned char d;
@@ -206,7 +208,7 @@ static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
return 0;
}
-static int __devinit snd_gusextreme_mixer(struct snd_card *card)
+static int snd_gusextreme_mixer(struct snd_card *card)
{
struct snd_ctl_elem_id id1, id2;
int error;
@@ -232,7 +234,7 @@ static int __devinit snd_gusextreme_mixer(struct snd_card *card)
return 0;
}
-static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
+static int snd_gusextreme_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_gus_card *gus;
@@ -339,7 +341,7 @@ out: snd_card_free(card);
return error;
}
-static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
+static int snd_gusextreme_remove(struct device *dev, unsigned int n)
{
snd_card_free(dev_get_drvdata(dev));
dev_set_drvdata(dev, NULL);
@@ -349,7 +351,7 @@ static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
static struct isa_driver snd_gusextreme_driver = {
.match = snd_gusextreme_match,
.probe = snd_gusextreme_probe,
- .remove = __devexit_p(snd_gusextreme_remove),
+ .remove = snd_gusextreme_remove,
#if 0 /* FIXME */
.suspend = snd_gusextreme_suspend,
.resume = snd_gusextreme_resume,
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 41c3f448745f..c309a5d0e7e1 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -82,7 +82,7 @@ struct snd_gusmax {
#define PFX "gusmax: "
-static int __devinit snd_gusmax_detect(struct snd_gus_card * gus)
+static int snd_gusmax_detect(struct snd_gus_card *gus)
{
unsigned char d;
@@ -124,8 +124,8 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
- struct snd_gus_card * gus)
+static void snd_gusmax_init(int dev, struct snd_card *card,
+ struct snd_gus_card *gus)
{
gus->equal_irq = 1;
gus->codec_flag = 1;
@@ -140,7 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
}
-static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
+static int snd_gusmax_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -199,12 +199,12 @@ static void snd_gusmax_free(struct snd_card *card)
free_irq(maxcard->irq, (void *)maxcard);
}
-static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev)
+static int snd_gusmax_match(struct device *pdev, unsigned int dev)
{
return enable[dev];
}
-static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
+static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
{
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
@@ -354,7 +354,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
return err;
}
-static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
+static int snd_gusmax_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -366,7 +366,7 @@ static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
static struct isa_driver snd_gusmax_driver = {
.match = snd_gusmax_match,
.probe = snd_gusmax_probe,
- .remove = __devexit_p(snd_gusmax_remove),
+ .remove = snd_gusmax_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 3fc8b66fd167..78bc5744e89a 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -207,9 +207,9 @@ static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = {
.getdata = snd_interwave_i2c_getdataline,
};
-static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
- struct snd_gus_card * gus, int dev,
- struct snd_i2c_bus **rbus)
+static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
+ struct snd_gus_card *gus, int dev,
+ struct snd_i2c_bus **rbus)
{
unsigned long port;
struct snd_i2c_bus *bus;
@@ -249,11 +249,11 @@ static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
}
#endif
-static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
- struct snd_gus_card * gus,
- int dev
+static int snd_interwave_detect(struct snd_interwave *iwcard,
+ struct snd_gus_card *gus,
+ int dev
#ifdef SNDRV_STB
- , struct snd_i2c_bus **rbus
+ , struct snd_i2c_bus **rbus
#endif
)
{
@@ -318,7 +318,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
+static void snd_interwave_reset(struct snd_gus_card *gus)
{
snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
udelay(160);
@@ -326,7 +326,7 @@ static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
udelay(160);
}
-static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes)
+static void snd_interwave_bank_sizes(struct snd_gus_card *gus, int *sizes)
{
unsigned int idx;
unsigned int local;
@@ -377,7 +377,7 @@ struct rom_hdr {
/* 511 */ unsigned char csum;
};
-static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
+static void snd_interwave_detect_memory(struct snd_gus_card *gus)
{
static unsigned int lmc[13] =
{
@@ -475,7 +475,7 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
snd_interwave_reset(gus);
}
-static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
+static void snd_interwave_init(int dev, struct snd_gus_card *gus)
{
unsigned long flags;
@@ -508,7 +508,7 @@ WSS_DOUBLE("Mic Playback Volume", 0,
CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
};
-static int __devinit snd_interwave_mixer(struct snd_wss *chip)
+static int snd_interwave_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -558,9 +558,9 @@ static int __devinit snd_interwave_mixer(struct snd_wss *chip)
#ifdef CONFIG_PNP
-static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -644,7 +644,7 @@ static int snd_interwave_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
+static int snd_interwave_probe(struct snd_card *card, int dev)
{
int xirq, xdma1, xdma2;
struct snd_interwave *iwcard = card->private_data;
@@ -775,7 +775,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
return 0;
}
-static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
+static int snd_interwave_isa_probe1(int dev, struct device *devptr)
{
struct snd_card *card;
int err;
@@ -793,8 +793,8 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
return 0;
}
-static int __devinit snd_interwave_isa_match(struct device *pdev,
- unsigned int dev)
+static int snd_interwave_isa_match(struct device *pdev,
+ unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -805,8 +805,8 @@ static int __devinit snd_interwave_isa_match(struct device *pdev,
return 1;
}
-static int __devinit snd_interwave_isa_probe(struct device *pdev,
- unsigned int dev)
+static int snd_interwave_isa_probe(struct device *pdev,
+ unsigned int dev)
{
int err;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
@@ -846,7 +846,7 @@ static int __devinit snd_interwave_isa_probe(struct device *pdev,
}
}
-static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
+static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -856,7 +856,7 @@ static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned in
static struct isa_driver snd_interwave_driver = {
.match = snd_interwave_isa_match,
.probe = snd_interwave_isa_probe,
- .remove = __devexit_p(snd_interwave_isa_remove),
+ .remove = snd_interwave_isa_remove,
/* FIXME: suspend,resume */
.driver = {
.name = INTERWAVE_DRIVER
@@ -864,8 +864,8 @@ static struct isa_driver snd_interwave_driver = {
};
#ifdef CONFIG_PNP
-static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -896,7 +896,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard)
+static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -907,7 +907,7 @@ static struct pnp_card_driver interwave_pnpc_driver = {
.name = INTERWAVE_PNP_DRIVER,
.id_table = snd_interwave_pnpids,
.probe = snd_interwave_pnp_detect,
- .remove = __devexit_p(snd_interwave_pnp_remove),
+ .remove = snd_interwave_pnp_remove,
/* FIXME: suspend,resume */
};
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
index a168ba3313ac..dbac3a42347b 100644
--- a/sound/isa/msnd/msnd.h
+++ b/sound/isa/msnd/msnd.h
@@ -303,6 +303,6 @@ int snd_msndmidi_new(struct snd_card *card, int device);
void snd_msndmidi_input_read(void *mpu);
void snd_msndmix_setup(struct snd_msnd *chip);
-int __devinit snd_msndmix_new(struct snd_card *card);
+int snd_msndmix_new(struct snd_card *card);
int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc);
#endif /* __MSND_H */
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 29cc8e162b02..ddabb406b14c 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -78,7 +78,7 @@
# define LOGNAME "snd_msnd_pinnacle"
#endif
-static void __devinit set_default_audio_parameters(struct snd_msnd *chip)
+static void set_default_audio_parameters(struct snd_msnd *chip)
{
chip->play_sample_size = DEFSAMPLESIZE;
chip->play_sample_rate = DEFSAMPLERATE;
@@ -213,7 +213,7 @@ static int snd_msnd_reset_dsp(long io, unsigned char *info)
return -EIO;
}
-static int __devinit snd_msnd_probe(struct snd_card *card)
+static int snd_msnd_probe(struct snd_card *card)
{
struct snd_msnd *chip = card->private_data;
unsigned char info;
@@ -497,7 +497,7 @@ static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
return snd_msnd_send_dsp_cmd(chip, cmd);
}
-static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
+static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
{
snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
writew(srate, chip->SMA + SMA_wCalFreqAtoD);
@@ -535,7 +535,7 @@ static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
-static int __devinit snd_msnd_attach(struct snd_card *card)
+static int snd_msnd_attach(struct snd_card *card)
{
struct snd_msnd *chip = card->private_data;
int err;
@@ -634,7 +634,7 @@ err_release_region:
}
-static void __devexit snd_msnd_unload(struct snd_card *card)
+static void snd_msnd_unload(struct snd_card *card)
{
struct snd_msnd *chip = card->private_data;
@@ -649,7 +649,7 @@ static void __devexit snd_msnd_unload(struct snd_card *card)
/* Pinnacle/Fiji Logical Device Configuration */
-static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
+static int snd_msnd_write_cfg(int cfg, int reg, int value)
{
outb(reg, cfg);
outb(value, cfg + 1);
@@ -660,7 +660,7 @@ static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
return 0;
}
-static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
+static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
{
if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
return -EIO;
@@ -671,7 +671,7 @@ static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
return 0;
}
-static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
+static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
{
if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
return -EIO;
@@ -682,7 +682,7 @@ static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
return 0;
}
-static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
+static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
{
if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
return -EIO;
@@ -693,7 +693,7 @@ static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
return 0;
}
-static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
+static int snd_msnd_write_cfg_mem(int cfg, int num, int mem)
{
u16 wmem;
@@ -711,7 +711,7 @@ static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
return 0;
}
-static int __devinit snd_msnd_activate_logical(int cfg, int num)
+static int snd_msnd_activate_logical(int cfg, int num)
{
if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
return -EIO;
@@ -720,8 +720,8 @@ static int __devinit snd_msnd_activate_logical(int cfg, int num)
return 0;
}
-static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
- u16 io1, u16 irq, int mem)
+static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
+ u16 io1, u16 irq, int mem)
{
if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
return -EIO;
@@ -738,7 +738,7 @@ static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
return 0;
}
-static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg)
+static int snd_msnd_pinnacle_cfg_reset(int cfg)
{
int i;
@@ -818,7 +818,7 @@ module_param_array(joystick_io, long, NULL, S_IRUGO);
#endif
-static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
+static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
{
if (io[i] == SNDRV_AUTO_PORT)
return 0;
@@ -888,7 +888,7 @@ static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
return 1;
}
-static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
+static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
{
int err;
struct snd_card *card;
@@ -1061,7 +1061,7 @@ cfg_error:
#endif
}
-static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
{
snd_msnd_unload(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
@@ -1073,7 +1073,7 @@ static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
static struct isa_driver snd_msnd_driver = {
.match = snd_msnd_isa_match,
.probe = snd_msnd_isa_probe,
- .remove = __devexit_p(snd_msnd_isa_remove),
+ .remove = snd_msnd_isa_remove,
/* FIXME: suspend, resume */
.driver = {
.name = DEV_NAME
@@ -1081,8 +1081,8 @@ static struct isa_driver snd_msnd_driver = {
};
#ifdef CONFIG_PNP
-static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int idx;
struct pnp_dev *pnp_dev;
@@ -1185,7 +1185,7 @@ _release_card:
return ret;
}
-static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard)
+static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
{
snd_msnd_unload(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -1207,7 +1207,7 @@ static struct pnp_card_driver msnd_pnpc_driver = {
.name = "msnd_pinnacle",
.id_table = msnd_pnpids,
.probe = snd_msnd_pnp_detect,
- .remove = __devexit_p(snd_msnd_pnp_remove),
+ .remove = snd_msnd_pnp_remove,
};
#endif /* CONFIG_PNP */
diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c
index 1de59d441426..031dc69b7470 100644
--- a/sound/isa/msnd/msnd_pinnacle_mixer.c
+++ b/sound/isa/msnd/msnd_pinnacle_mixer.c
@@ -302,7 +302,7 @@ DUMMY_VOLUME("Monitor", 0, MSND_MIXER_IMIX),
};
-int __devinit snd_msndmix_new(struct snd_card *card)
+int snd_msndmix_new(struct snd_card *card)
{
struct snd_msnd *chip = card->private_data;
unsigned int idx;
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index f6cc0b917ef0..075777a6cf0b 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static int __devinit snd_opl3sa2_detect(struct snd_card *card)
+static int snd_opl3sa2_detect(struct snd_card *card)
{
struct snd_opl3sa2 *chip = card->private_data;
unsigned long port;
@@ -496,7 +496,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
chip->master_volume = NULL;
}
-static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
+static int snd_opl3sa2_mixer(struct snd_card *card)
{
struct snd_opl3sa2 *chip = card->private_data;
struct snd_ctl_elem_id id1, id2;
@@ -596,8 +596,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
#endif /* CONFIG_PM */
#ifdef CONFIG_PNP
-static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
- struct pnp_dev *pdev)
+static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
+ struct pnp_dev *pdev)
{
if (pnp_activate_dev(pdev) < 0) {
snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n");
@@ -647,7 +647,7 @@ static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
+static int snd_opl3sa2_probe(struct snd_card *card, int dev)
{
int xirq, xdma1, xdma2;
struct snd_opl3sa2 *chip;
@@ -721,8 +721,8 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
}
#ifdef CONFIG_PNP
-static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
- const struct pnp_device_id *id)
+static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
+ const struct pnp_device_id *id)
{
static int dev;
int err;
@@ -754,7 +754,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
return 0;
}
-static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev)
+static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
{
snd_card_free(pnp_get_drvdata(pdev));
pnp_set_drvdata(pdev, NULL);
@@ -775,15 +775,15 @@ static struct pnp_driver opl3sa2_pnp_driver = {
.name = "snd-opl3sa2-pnpbios",
.id_table = snd_opl3sa2_pnpbiosids,
.probe = snd_opl3sa2_pnp_detect,
- .remove = __devexit_p(snd_opl3sa2_pnp_remove),
+ .remove = snd_opl3sa2_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_pnp_suspend,
.resume = snd_opl3sa2_pnp_resume,
#endif
};
-static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *id)
+static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *id)
{
static int dev;
struct pnp_dev *pdev;
@@ -820,7 +820,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard)
+static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -842,7 +842,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
.name = "snd-opl3sa2-cpnp",
.id_table = snd_opl3sa2_pnpids,
.probe = snd_opl3sa2_pnp_cdetect,
- .remove = __devexit_p(snd_opl3sa2_pnp_cremove),
+ .remove = snd_opl3sa2_pnp_cremove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_pnp_csuspend,
.resume = snd_opl3sa2_pnp_cresume,
@@ -850,8 +850,8 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
};
#endif /* CONFIG_PNP */
-static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
- unsigned int dev)
+static int snd_opl3sa2_isa_match(struct device *pdev,
+ unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -878,8 +878,8 @@ static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
return 1;
}
-static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
- unsigned int dev)
+static int snd_opl3sa2_isa_probe(struct device *pdev,
+ unsigned int dev)
{
struct snd_card *card;
int err;
@@ -896,8 +896,8 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
return 0;
}
-static int __devexit snd_opl3sa2_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_opl3sa2_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -922,7 +922,7 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_opl3sa2_isa_driver = {
.match = snd_opl3sa2_isa_match,
.probe = snd_opl3sa2_isa_probe,
- .remove = __devexit_p(snd_opl3sa2_isa_remove),
+ .remove = snd_opl3sa2_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_isa_suspend,
.resume = snd_opl3sa2_isa_resume,
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 4a7ff4e8985b..c3da1df9371d 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -587,7 +587,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_controls[] = {
MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
@@ -599,7 +599,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
/* Equalizer with seven bands (only PCM20)
from -12dB up to +12dB on each band */
-static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_eq_controls[] = {
MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
@@ -609,15 +609,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
};
-static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_radio_control[] = {
MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
};
-static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_line_control[] = {
MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
};
-static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_preamp_control[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost",
@@ -627,7 +627,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
.put = snd_miro_put_preamp,
}};
-static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_amp_control[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Boost",
@@ -637,7 +637,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
.put = snd_miro_put_amp,
}};
-static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_capture_control[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Capture Switch",
@@ -647,7 +647,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
.put = snd_miro_put_capture,
}};
-static unsigned char aci_init_values[][2] __devinitdata = {
+static unsigned char aci_init_values[][2] = {
{ ACI_SET_MUTE, 0x00 },
{ ACI_SET_POWERAMP, 0x00 },
{ ACI_SET_PREAMP, 0x00 },
@@ -670,7 +670,7 @@ static unsigned char aci_init_values[][2] __devinitdata = {
{ ACI_SET_MASTER + 1, 0x20 },
};
-static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
+static int snd_set_aci_init_values(struct snd_miro *miro)
{
int idx, error;
struct snd_miro_aci *aci = miro->aci;
@@ -713,8 +713,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
return 0;
}
-static int __devinit snd_miro_mixer(struct snd_card *card,
- struct snd_miro *miro)
+static int snd_miro_mixer(struct snd_card *card,
+ struct snd_miro *miro)
{
unsigned int idx;
int err;
@@ -771,8 +771,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
return 0;
}
-static int __devinit snd_miro_init(struct snd_miro *chip,
- unsigned short hardware)
+static int snd_miro_init(struct snd_miro *chip,
+ unsigned short hardware)
{
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
@@ -989,8 +989,8 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp);
}
-static void __devinit snd_miro_proc_init(struct snd_card *card,
- struct snd_miro *miro)
+static void snd_miro_proc_init(struct snd_card *card,
+ struct snd_miro *miro)
{
struct snd_info_entry *entry;
@@ -1002,7 +1002,7 @@ static void __devinit snd_miro_proc_init(struct snd_card *card,
* Init
*/
-static int __devinit snd_miro_configure(struct snd_miro *chip)
+static int snd_miro_configure(struct snd_miro *chip)
{
unsigned char wss_base_bits;
unsigned char irq_bits;
@@ -1162,7 +1162,7 @@ __skip_mpu:
return 0;
}
-static int __devinit snd_miro_opti_check(struct snd_miro *chip)
+static int snd_miro_opti_check(struct snd_miro *chip)
{
unsigned char value;
@@ -1182,8 +1182,8 @@ static int __devinit snd_miro_opti_check(struct snd_miro *chip)
return -ENODEV;
}
-static int __devinit snd_card_miro_detect(struct snd_card *card,
- struct snd_miro *chip)
+static int snd_card_miro_detect(struct snd_card *card,
+ struct snd_miro *chip)
{
int i, err;
@@ -1200,8 +1200,8 @@ static int __devinit snd_card_miro_detect(struct snd_card *card,
return -ENODEV;
}
-static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
- struct snd_miro *miro)
+static int snd_card_miro_aci_detect(struct snd_card *card,
+ struct snd_miro *miro)
{
unsigned char regval;
int i;
@@ -1265,7 +1265,7 @@ static void snd_card_miro_free(struct snd_card *card)
release_and_free_resource(miro->res_mc_base);
}
-static int __devinit snd_miro_probe(struct snd_card *card)
+static int snd_miro_probe(struct snd_card *card)
{
int error;
struct snd_miro *miro = card->private_data;
@@ -1386,7 +1386,7 @@ static int __devinit snd_miro_probe(struct snd_card *card)
return snd_card_register(card);
}
-static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
+static int snd_miro_isa_match(struct device *devptr, unsigned int n)
{
#ifdef CONFIG_PNP
if (snd_miro_pnp_is_probed)
@@ -1397,7 +1397,7 @@ static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
return 1;
}
-static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
+static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
@@ -1491,8 +1491,8 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
return 0;
}
-static int __devexit snd_miro_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_miro_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -1504,7 +1504,7 @@ static int __devexit snd_miro_isa_remove(struct device *devptr,
static struct isa_driver snd_miro_driver = {
.match = snd_miro_isa_match,
.probe = snd_miro_isa_probe,
- .remove = __devexit_p(snd_miro_isa_remove),
+ .remove = snd_miro_isa_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
@@ -1513,9 +1513,9 @@ static struct isa_driver snd_miro_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *pid)
+static int snd_card_miro_pnp(struct snd_miro *chip,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *pid)
{
struct pnp_dev *pdev;
int err;
@@ -1574,8 +1574,8 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
return 0;
}
-static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
struct snd_card *card;
int err;
@@ -1624,7 +1624,7 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard)
+static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -1636,7 +1636,7 @@ static struct pnp_card_driver miro_pnpc_driver = {
.name = "miro",
.id_table = snd_miro_pnpids,
.probe = snd_miro_pnp_probe,
- .remove = __devexit_p(snd_miro_pnp_remove),
+ .remove = snd_miro_pnp_remove,
};
#endif
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 2899c9fd1ceb..b41ed8661b23 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -186,8 +186,8 @@ static char * snd_opti9xx_names[] = {
"82C930", "82C931", "82C933"
};
-static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
- unsigned short hardware)
+static int snd_opti9xx_init(struct snd_opti9xx *chip,
+ unsigned short hardware)
{
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
@@ -593,7 +593,7 @@ WSS_DOUBLE_TLV("Aux Playback Volume", 0,
db_scale_4bit_12db_max),
};
-static int __devinit snd_opti93x_mixer(struct snd_wss *chip)
+static int snd_opti93x_mixer(struct snd_wss *chip)
{
struct snd_card *card;
unsigned int idx;
@@ -666,7 +666,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
#endif /* OPTi93X */
-static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
+static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
{
unsigned char value;
#ifdef OPTi93X
@@ -707,8 +707,8 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
return -ENODEV;
}
-static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
- struct snd_opti9xx *chip)
+static int snd_card_opti9xx_detect(struct snd_card *card,
+ struct snd_opti9xx *chip)
{
int i, err;
@@ -732,9 +732,9 @@ static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
}
#ifdef CONFIG_PNP
-static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *pid)
+static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *pid)
{
struct pnp_dev *pdev;
int err;
@@ -817,7 +817,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
}
}
-static int __devinit snd_opti9xx_probe(struct snd_card *card)
+static int snd_opti9xx_probe(struct snd_card *card)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
int error;
@@ -952,8 +952,8 @@ static int snd_opti9xx_card_new(struct snd_card **cardp)
return 0;
}
-static int __devinit snd_opti9xx_isa_match(struct device *devptr,
- unsigned int dev)
+static int snd_opti9xx_isa_match(struct device *devptr,
+ unsigned int dev)
{
#ifdef CONFIG_PNP
if (snd_opti9xx_pnp_is_probed)
@@ -964,8 +964,8 @@ static int __devinit snd_opti9xx_isa_match(struct device *devptr,
return 1;
}
-static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
- unsigned int dev)
+static int snd_opti9xx_isa_probe(struct device *devptr,
+ unsigned int dev)
{
struct snd_card *card;
int error;
@@ -1031,8 +1031,8 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
return 0;
}
-static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_opti9xx_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -1083,7 +1083,7 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_opti9xx_driver = {
.match = snd_opti9xx_isa_match,
.probe = snd_opti9xx_isa_probe,
- .remove = __devexit_p(snd_opti9xx_isa_remove),
+ .remove = snd_opti9xx_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_opti9xx_isa_suspend,
.resume = snd_opti9xx_isa_resume,
@@ -1094,8 +1094,8 @@ static struct isa_driver snd_opti9xx_driver = {
};
#ifdef CONFIG_PNP
-static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
struct snd_card *card;
int error, hw;
@@ -1146,7 +1146,7 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
+static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -1171,7 +1171,7 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
.name = "opti9xx",
.id_table = snd_opti9xx_pnpids,
.probe = snd_opti9xx_pnp_probe,
- .remove = __devexit_p(snd_opti9xx_pnp_remove),
+ .remove = snd_opti9xx_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_opti9xx_pnp_suspend,
.resume = snd_opti9xx_pnp_resume,
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 2aae6a0efbcd..45fcdff611f9 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
/*
*/
-static void __devinit
+static void
snd_emu8000_read_wait(struct snd_emu8000 *emu)
{
while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
@@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu)
/*
*/
-static void __devinit
+static void
snd_emu8000_write_wait(struct snd_emu8000 *emu)
{
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
@@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu)
/*
* detect a card at the given port
*/
-static int __devinit
+static int
snd_emu8000_detect(struct snd_emu8000 *emu)
{
/* Initialise */
@@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu)
/*
* intiailize audio channels
*/
-static void __devinit
+static void
init_audio(struct snd_emu8000 *emu)
{
int ch;
@@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu)
/*
* initialize DMA address
*/
-static void __devinit
+static void
init_dma(struct snd_emu8000 *emu)
{
EMU8000_SMALR_WRITE(emu, 0);
@@ -235,7 +235,7 @@ init_dma(struct snd_emu8000 *emu)
/*
* initialization arrays; from ADIP
*/
-static unsigned short init1[128] /*__devinitdata*/ = {
+static unsigned short init1[128] = {
0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730,
0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30,
@@ -257,7 +257,7 @@ static unsigned short init1[128] /*__devinitdata*/ = {
0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30,
};
-static unsigned short init2[128] /*__devinitdata*/ = {
+static unsigned short init2[128] = {
0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
@@ -279,7 +279,7 @@ static unsigned short init2[128] /*__devinitdata*/ = {
0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
};
-static unsigned short init3[128] /*__devinitdata*/ = {
+static unsigned short init3[128] = {
0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
@@ -301,7 +301,7 @@ static unsigned short init3[128] /*__devinitdata*/ = {
0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
};
-static unsigned short init4[128] /*__devinitdata*/ = {
+static unsigned short init4[128] = {
0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
@@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = {
* Taken from the oss driver, not obvious from the doc how this
* is meant to work
*/
-static void __devinit
+static void
send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
{
int i;
@@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
* Send initialization arrays to start up, this just follows the
* initialisation sequence in the adip.
*/
-static void __devinit
+static void
init_arrays(struct snd_emu8000 *emu)
{
send_array(emu, init1, ARRAY_SIZE(init1)/4);
@@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu)
* seems that the only way to do this is to use the one channel and keep
* reallocating between read and write.
*/
-static void __devinit
+static void
size_dram(struct snd_emu8000 *emu)
{
int i, size, detected_size;
@@ -512,7 +512,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu)
/*
* The main initialization routine.
*/
-static void __devinit
+static void
snd_emu8000_init_hw(struct snd_emu8000 *emu)
{
int i;
@@ -1031,7 +1031,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
/*
* create and attach mixer elements for WaveTable treble/bass controls
*/
-static int __devinit
+static int
snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
{
int i, err = 0;
@@ -1082,7 +1082,7 @@ static int snd_emu8000_dev_free(struct snd_device *device)
/*
* initialize and register emu8000 synth device.
*/
-int __devinit
+int
snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
struct snd_seq_device **awe_ret)
{
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 410758c68090..4961da4e627c 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -78,8 +78,8 @@ static irqreturn_t jazz16_interrupt(int irq, void *chip)
return snd_sb8dsp_interrupt(chip);
}
-static int __devinit jazz16_configure_ports(unsigned long port,
- unsigned long mpu_port, int idx)
+static int jazz16_configure_ports(unsigned long port,
+ unsigned long mpu_port, int idx)
{
unsigned char val;
@@ -99,8 +99,8 @@ static int __devinit jazz16_configure_ports(unsigned long port,
return 0;
}
-static int __devinit jazz16_detect_board(unsigned long port,
- unsigned long mpu_port)
+static int jazz16_detect_board(unsigned long port,
+ unsigned long mpu_port)
{
int err;
int val;
@@ -156,7 +156,7 @@ err_unmap:
return err;
}
-static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
+static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
{
static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
0, 2, 5, 0, 0, 0, 0, 6 };
@@ -183,7 +183,7 @@ static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
return 0;
}
-static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
+static int snd_jazz16_match(struct device *devptr, unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -218,7 +218,7 @@ static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
return 1;
}
-static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
+static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
{
struct snd_card *card;
struct snd_card_jazz16 *jazz16;
@@ -341,7 +341,7 @@ err_free:
return err;
}
-static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev)
+static int snd_jazz16_remove(struct device *devptr, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(devptr);
@@ -380,7 +380,7 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
static struct isa_driver snd_jazz16_driver = {
.match = snd_jazz16_match,
.probe = snd_jazz16_probe,
- .remove = __devexit_p(snd_jazz16_remove),
+ .remove = snd_jazz16_remove,
#ifdef CONFIG_PM
.suspend = snd_jazz16_suspend,
.resume = snd_jazz16_resume,
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 39b8eca15213..50dbec454f98 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -250,9 +250,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids);
#ifdef CONFIG_PNP
-static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
struct pnp_dev *pdev;
int err;
@@ -337,7 +337,7 @@ static int snd_sb16_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
+static int snd_sb16_probe(struct snd_card *card, int dev)
{
int xirq, xdma8, xdma16;
struct snd_sb *chip;
@@ -487,7 +487,7 @@ static int snd_sb16_resume(struct snd_card *card)
}
#endif
-static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
+static int snd_sb16_isa_probe1(int dev, struct device *pdev)
{
struct snd_card_sb16 *acard;
struct snd_card *card;
@@ -517,12 +517,12 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
}
-static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_match(struct device *pdev, unsigned int dev)
{
return enable[dev] && !is_isapnp_selected(dev);
}
-static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
{
int err;
static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -563,7 +563,7 @@ static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
@@ -592,7 +592,7 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_sb16_isa_driver = {
.match = snd_sb16_isa_match,
.probe = snd_sb16_isa_probe,
- .remove = __devexit_p(snd_sb16_isa_remove),
+ .remove = snd_sb16_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_sb16_isa_suspend,
.resume = snd_sb16_isa_resume,
@@ -604,8 +604,8 @@ static struct isa_driver snd_sb16_isa_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -631,7 +631,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
return -ENODEV;
}
-static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
+static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -657,7 +657,7 @@ static struct pnp_card_driver sb16_pnpc_driver = {
#endif
.id_table = snd_sb16_pnpids,
.probe = snd_sb16_pnp_detect,
- .remove = __devexit_p(snd_sb16_pnp_remove),
+ .remove = snd_sb16_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_sb16_pnp_suspend,
.resume = snd_sb16_pnp_resume,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index ab5cebea52e1..237d964ff8a6 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -79,7 +79,7 @@ static void snd_sb8_free(struct snd_card *card)
release_and_free_resource(acard->fm_res);
}
-static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
+static int snd_sb8_match(struct device *pdev, unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -94,7 +94,7 @@ static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
return 1;
}
-static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
+static int snd_sb8_probe(struct device *pdev, unsigned int dev)
{
struct snd_sb *chip;
struct snd_card *card;
@@ -205,7 +205,7 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
return err;
}
-static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev)
+static int snd_sb8_remove(struct device *pdev, unsigned int dev)
{
snd_card_free(dev_get_drvdata(pdev));
dev_set_drvdata(pdev, NULL);
@@ -244,7 +244,7 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_sb8_driver = {
.match = snd_sb8_match,
.probe = snd_sb8_probe,
- .remove = __devexit_p(snd_sb8_remove),
+ .remove = snd_sb8_remove,
#ifdef CONFIG_PM
.suspend = snd_sb8_suspend,
.resume = snd_sb8_resume,
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index d97d0f381817..5376ebff845e 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -121,7 +121,7 @@ MODULE_PARM_DESC(joystick, "Enable gameport.");
/*
* sc6000_irq_to_softcfg - Decode irq number into cfg code.
*/
-static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
+static unsigned char sc6000_irq_to_softcfg(int irq)
{
unsigned char val = 0;
@@ -150,7 +150,7 @@ static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
/*
* sc6000_dma_to_softcfg - Decode dma number into cfg code.
*/
-static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
+static unsigned char sc6000_dma_to_softcfg(int dma)
{
unsigned char val = 0;
@@ -173,7 +173,7 @@ static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
/*
* sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code.
*/
-static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
+static unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
{
unsigned char val = 0;
@@ -242,8 +242,8 @@ static int sc6000_write(char __iomem *vport, int cmd)
return -EIO;
}
-static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
- char *data, int data_len)
+static int sc6000_dsp_get_answer(char __iomem *vport, int command,
+ char *data, int data_len)
{
int len = 0;
@@ -269,7 +269,7 @@ static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
return len ? len : -EIO;
}
-static int __devinit sc6000_dsp_reset(char __iomem *vport)
+static int sc6000_dsp_reset(char __iomem *vport)
{
iowrite8(1, vport + DSP_RESET);
udelay(10);
@@ -281,7 +281,7 @@ static int __devinit sc6000_dsp_reset(char __iomem *vport)
}
/* detection and initialization */
-static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
+static int sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
{
if (sc6000_write(vport, COMMAND_6C) < 0) {
snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C);
@@ -345,8 +345,8 @@ static int sc6000_setup_board(char __iomem *vport, int config)
return 0;
}
-static int __devinit sc6000_init_mss(char __iomem *vport, int config,
- char __iomem *vmss_port, int mss_config)
+static int sc6000_init_mss(char __iomem *vport, int config,
+ char __iomem *vmss_port, int mss_config)
{
if (sc6000_write(vport, DSP_INIT_MSS)) {
snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n",
@@ -364,9 +364,9 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config,
return 0;
}
-static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
- long xport, long xmpu,
- long xmss_port, int joystick)
+static void sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
+ long xport, long xmpu,
+ long xmss_port, int joystick)
{
cfg[0] = 0;
cfg[1] = 0;
@@ -386,8 +386,8 @@ static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]);
}
-static int __devinit sc6000_init_board(char __iomem *vport,
- char __iomem *vmss_port, int dev)
+static int sc6000_init_board(char __iomem *vport,
+ char __iomem *vmss_port, int dev)
{
char answer[15];
char version[2];
@@ -467,7 +467,7 @@ static int __devinit sc6000_init_board(char __iomem *vport,
return 0;
}
-static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
+static int snd_sc6000_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -502,7 +502,7 @@ static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
return 0;
}
-static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
+static int snd_sc6000_match(struct device *devptr, unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -545,7 +545,7 @@ static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
return 1;
}
-static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
+static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
{
static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
static int possible_dmas[] = { 1, 3, 0, -1 };
@@ -687,7 +687,7 @@ err_exit:
return err;
}
-static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
+static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
{
struct snd_card *card = dev_get_drvdata(devptr);
char __iomem **vport = card->private_data;
@@ -706,7 +706,7 @@ static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
static struct isa_driver snd_sc6000_driver = {
.match = snd_sc6000_match,
.probe = snd_sc6000_probe,
- .remove = __devexit_p(snd_sc6000_remove),
+ .remove = snd_sc6000_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DRV_NAME,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 8490f59709bb..42a009720b29 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -683,7 +683,7 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
* These IRQs are encoded as bit patterns so that they can be
* written to the control registers.
*/
-static unsigned __devinit get_irq_config(int sscape_type, int irq)
+static unsigned get_irq_config(int sscape_type, int irq)
{
static const int valid_irq[] = { 9, 5, 7, 10 };
static const int old_irq[] = { 9, 7, 5, 15 };
@@ -706,7 +706,7 @@ static unsigned __devinit get_irq_config(int sscape_type, int irq)
* Perform certain arcane port-checks to see whether there
* is a SoundScape board lurking behind the given ports.
*/
-static int __devinit detect_sscape(struct soundscape *s, long wss_io)
+static int detect_sscape(struct soundscape *s, long wss_io)
{
unsigned long flags;
unsigned d;
@@ -817,8 +817,8 @@ static int mpu401_open(struct snd_mpu401 *mpu)
/*
* Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
*/
-static int __devinit create_mpu401(struct snd_card *card, int devnum,
- unsigned long port, int irq)
+static int create_mpu401(struct snd_card *card, int devnum,
+ unsigned long port, int irq)
{
struct soundscape *sscape = get_card_soundscape(card);
struct snd_rawmidi *rawmidi;
@@ -845,8 +845,8 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum,
* try to support at least some of the extra bits by overriding
* some of the CS4231 callback.
*/
-static int __devinit create_ad1845(struct snd_card *card, unsigned port,
- int irq, int dma1, int dma2)
+static int create_ad1845(struct snd_card *card, unsigned port,
+ int irq, int dma1, int dma2)
{
register struct soundscape *sscape = get_card_soundscape(card);
struct snd_wss *chip;
@@ -937,7 +937,7 @@ _error:
* Create an ALSA soundcard entry for the SoundScape, using
* the given list of port, IRQ and DMA resources.
*/
-static int __devinit create_sscape(int dev, struct snd_card *card)
+static int create_sscape(int dev, struct snd_card *card)
{
struct soundscape *sscape = get_card_soundscape(card);
unsigned dma_cfg;
@@ -1143,7 +1143,7 @@ _release_region:
}
-static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
+static int snd_sscape_match(struct device *pdev, unsigned int i)
{
/*
* Make sure we were given ALL of the other parameters.
@@ -1163,7 +1163,7 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
return 1;
}
-static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
+static int snd_sscape_probe(struct device *pdev, unsigned int dev)
{
struct snd_card *card;
struct soundscape *sscape;
@@ -1197,7 +1197,7 @@ _release_card:
return ret;
}
-static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
+static int snd_sscape_remove(struct device *devptr, unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -1209,7 +1209,7 @@ static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
static struct isa_driver snd_sscape_driver = {
.match = snd_sscape_match,
.probe = snd_sscape_probe,
- .remove = __devexit_p(snd_sscape_remove),
+ .remove = snd_sscape_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
@@ -1217,7 +1217,7 @@ static struct isa_driver snd_sscape_driver = {
};
#ifdef CONFIG_PNP
-static inline int __devinit get_next_autoindex(int i)
+static inline int get_next_autoindex(int i)
{
while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
++i;
@@ -1225,8 +1225,8 @@ static inline int __devinit get_next_autoindex(int i)
}
-static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int sscape_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int idx = 0;
struct pnp_dev *dev;
@@ -1310,7 +1310,7 @@ _release_card:
return ret;
}
-static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
+static void sscape_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -1321,7 +1321,7 @@ static struct pnp_card_driver sscape_pnpc_driver = {
.name = "sscape",
.id_table = sscape_pnpids,
.probe = sscape_pnp_detect,
- .remove = __devexit_p(sscape_pnp_remove),
+ .remove = sscape_pnp_remove,
};
#endif /* CONFIG_PNP */
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index e0a73271cb91..fe5dd982bd23 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -98,7 +98,7 @@ static struct pnp_card_device_id snd_wavefront_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids);
-static int __devinit
+static int
snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -231,10 +231,9 @@ static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static struct snd_hwdep * __devinit
-snd_wavefront_new_synth (struct snd_card *card,
- int hw_dev,
- snd_wavefront_card_t *acard)
+static struct snd_hwdep *snd_wavefront_new_synth(struct snd_card *card,
+ int hw_dev,
+ snd_wavefront_card_t *acard)
{
struct snd_hwdep *wavefront_synth;
@@ -257,11 +256,10 @@ snd_wavefront_new_synth (struct snd_card *card,
return wavefront_synth;
}
-static struct snd_hwdep * __devinit
-snd_wavefront_new_fx (struct snd_card *card,
- int hw_dev,
- snd_wavefront_card_t *acard,
- unsigned long port)
+static struct snd_hwdep *snd_wavefront_new_fx(struct snd_card *card,
+ int hw_dev,
+ snd_wavefront_card_t *acard,
+ unsigned long port)
{
struct snd_hwdep *fx_processor;
@@ -284,12 +282,11 @@ snd_wavefront_new_fx (struct snd_card *card,
static snd_wavefront_mpu_id internal_id = internal_mpu;
static snd_wavefront_mpu_id external_id = external_mpu;
-static struct snd_rawmidi *__devinit
-snd_wavefront_new_midi (struct snd_card *card,
- int midi_dev,
- snd_wavefront_card_t *acard,
- unsigned long port,
- snd_wavefront_mpu_id mpu)
+static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
+ int midi_dev,
+ snd_wavefront_card_t *acard,
+ unsigned long port,
+ snd_wavefront_mpu_id mpu)
{
struct snd_rawmidi *rmidi;
@@ -361,7 +358,7 @@ static int snd_wavefront_card_new(int dev, struct snd_card **cardp)
return 0;
}
-static int __devinit
+static int
snd_wavefront_probe (struct snd_card *card, int dev)
{
snd_wavefront_card_t *acard = card->private_data;
@@ -541,8 +538,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __devinit snd_wavefront_isa_match(struct device *pdev,
- unsigned int dev)
+static int snd_wavefront_isa_match(struct device *pdev,
+ unsigned int dev)
{
if (!enable[dev])
return 0;
@@ -561,8 +558,8 @@ static int __devinit snd_wavefront_isa_match(struct device *pdev,
return 1;
}
-static int __devinit snd_wavefront_isa_probe(struct device *pdev,
- unsigned int dev)
+static int snd_wavefront_isa_probe(struct device *pdev,
+ unsigned int dev)
{
struct snd_card *card;
int err;
@@ -580,8 +577,8 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev,
return 0;
}
-static int __devexit snd_wavefront_isa_remove(struct device *devptr,
- unsigned int dev)
+static int snd_wavefront_isa_remove(struct device *devptr,
+ unsigned int dev)
{
snd_card_free(dev_get_drvdata(devptr));
dev_set_drvdata(devptr, NULL);
@@ -593,7 +590,7 @@ static int __devexit snd_wavefront_isa_remove(struct device *devptr,
static struct isa_driver snd_wavefront_driver = {
.match = snd_wavefront_isa_match,
.probe = snd_wavefront_isa_probe,
- .remove = __devexit_p(snd_wavefront_isa_remove),
+ .remove = snd_wavefront_isa_remove,
/* FIXME: suspend, resume */
.driver = {
.name = DEV_NAME
@@ -602,8 +599,8 @@ static struct isa_driver snd_wavefront_driver = {
#ifdef CONFIG_PNP
-static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
@@ -637,7 +634,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
-static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
+static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
@@ -648,7 +645,7 @@ static struct pnp_card_driver wavefront_pnpc_driver = {
.name = "wavefront",
.id_table = snd_wavefront_pnpids,
.probe = snd_wavefront_pnp_detect,
- .remove = __devexit_p(snd_wavefront_pnp_remove),
+ .remove = snd_wavefront_pnp_remove,
/* FIXME: suspend,resume */
};
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index e51e0906050b..b77883c7ee76 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -240,7 +240,7 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
that outputs it.
*/
-int __devinit
+int
snd_wavefront_fx_start (snd_wavefront_t *dev)
{
unsigned int i;
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 65329f3abc30..7dc991682297 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -481,7 +481,7 @@ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
}
-int __devinit
+int
snd_wavefront_midi_start (snd_wavefront_card_t *card)
{
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index b1bf8d4e6494..a2f87f9488ee 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1739,7 +1739,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
7 Unused
*/
-static int __devinit
+static int
snd_wavefront_interrupt_bits (int irq)
{
@@ -1767,7 +1767,7 @@ snd_wavefront_interrupt_bits (int irq)
return bits;
}
-static void __devinit
+static void
wavefront_should_cause_interrupt (snd_wavefront_t *dev,
int val, int port, unsigned long timeout)
@@ -1786,7 +1786,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
}
}
-static int __devinit
+static int
wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
{
@@ -1937,7 +1937,7 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
return (1);
}
-static int __devinit
+static int
wavefront_download_firmware (snd_wavefront_t *dev, char *path)
{
@@ -2010,7 +2010,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
}
-static int __devinit
+static int
wavefront_do_reset (snd_wavefront_t *dev)
{
@@ -2099,7 +2099,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
return 1;
}
-int __devinit
+int
snd_wavefront_start (snd_wavefront_t *dev)
{
@@ -2141,7 +2141,7 @@ snd_wavefront_start (snd_wavefront_t *dev)
return (0);
}
-int __devinit
+int
snd_wavefront_detect (snd_wavefront_card_t *card)
{
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index 3f3ec0bec067..224f54be15a6 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -439,7 +439,7 @@ static struct snd_pcm_ops snd_card_au1000_capture_ops = {
.pointer = snd_au1000_pointer,
};
-static int __devinit
+static int
snd_au1000_pcm_new(struct snd_au1000 *au1000)
{
struct snd_pcm *pcm;
@@ -552,7 +552,7 @@ get the interrupt driven case to work efficiently */
spin_unlock(&au1000->ac97_lock);
}
-static int __devinit
+static int
snd_au1000_ac97_new(struct snd_au1000 *au1000)
{
int err;
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index 5f88d1f09ffe..7420c59444ab 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -260,7 +260,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
return old != new;
}
-static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
+static struct snd_kcontrol_new hal2_ctrl_headphone = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -270,7 +270,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
.put = hal2_gain_put,
};
-static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
+static struct snd_kcontrol_new hal2_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -280,7 +280,7 @@ static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
.put = hal2_gain_put,
};
-static int __devinit hal2_mixer_create(struct snd_hal2 *hal2)
+static int hal2_mixer_create(struct snd_hal2 *hal2)
{
int err;
@@ -733,7 +733,7 @@ static struct snd_pcm_ops hal2_capture_ops = {
.ack = hal2_capture_ack,
};
-static int __devinit hal2_pcm_create(struct snd_hal2 *hal2)
+static int hal2_pcm_create(struct snd_hal2 *hal2)
{
struct snd_pcm *pcm;
int err;
@@ -874,7 +874,7 @@ static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip)
return 0;
}
-static int __devinit hal2_probe(struct platform_device *pdev)
+static int hal2_probe(struct platform_device *pdev)
{
struct snd_card *card;
struct snd_hal2 *chip;
@@ -917,7 +917,7 @@ static int __devinit hal2_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit hal2_remove(struct platform_device *pdev)
+static int hal2_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
@@ -928,7 +928,7 @@ static int __devexit hal2_remove(struct platform_device *pdev)
static struct platform_driver hal2_driver = {
.probe = hal2_probe,
- .remove = __devexit_p(hal2_remove),
+ .remove = hal2_remove,
.driver = {
.name = "sgihal2",
.owner = THIS_MODULE,
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index ceaa593ea4ef..01a03efdc8b0 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -237,7 +237,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
}
/* dac1/pcm0 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -249,7 +249,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
};
/* dac2/pcm1 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 1,
@@ -261,7 +261,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
};
/* record level mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -272,7 +272,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
};
/* record level source control */
-static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -282,7 +282,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
};
/* line mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_line = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 0,
@@ -294,7 +294,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
};
/* cd mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 1,
@@ -306,7 +306,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
};
/* mic mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -317,7 +317,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
};
-static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
+static int snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
{
int err;
@@ -726,7 +726,7 @@ static struct snd_pcm_ops snd_sgio2audio_capture_ops = {
*/
/* create a pcm device */
-static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
+static int snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
{
struct snd_pcm *pcm;
int err;
@@ -834,8 +834,8 @@ static struct snd_device_ops ops = {
.dev_free = snd_sgio2audio_dev_free,
};
-static int __devinit snd_sgio2audio_create(struct snd_card *card,
- struct snd_sgio2audio **rchip)
+static int snd_sgio2audio_create(struct snd_card *card,
+ struct snd_sgio2audio **rchip)
{
struct snd_sgio2audio *chip;
int i, err;
@@ -914,7 +914,7 @@ static int __devinit snd_sgio2audio_create(struct snd_card *card,
return 0;
}
-static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
+static int snd_sgio2audio_probe(struct platform_device *pdev)
{
struct snd_card *card;
struct snd_sgio2audio *chip;
@@ -958,7 +958,7 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
+static int snd_sgio2audio_remove(struct platform_device *pdev)
{
struct snd_card *card = platform_get_drvdata(pdev);
@@ -969,7 +969,7 @@ static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
static struct platform_driver sgio2audio_driver = {
.probe = snd_sgio2audio_probe,
- .remove = __devexit_p(snd_sgio2audio_remove),
+ .remove = snd_sgio2audio_remove,
.driver = {
.name = "sgio2audio",
.owner = THIS_MODULE,
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 98d23bdcaf21..4918b7145b73 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -2864,7 +2864,7 @@ static struct {
{NULL}
};
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
{ ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c
index 52d06a334e8f..2a44cc106459 100644
--- a/sound/oss/kahlua.c
+++ b/sound/oss/kahlua.c
@@ -43,7 +43,7 @@
* not real hardware.
*/
-static u8 __devinit mixer_read(unsigned long io, u8 reg)
+static u8 mixer_read(unsigned long io, u8 reg)
{
outb(reg, io + 4);
udelay(20);
@@ -52,7 +52,7 @@ static u8 __devinit mixer_read(unsigned long io, u8 reg)
return reg;
}
-static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct address_info *hw_config;
unsigned long base;
@@ -183,7 +183,7 @@ err_out_free:
return 1;
}
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
{
struct address_info *hw_config = pci_get_drvdata(pdev);
sb_dsp_unload(hw_config, 0);
@@ -210,7 +210,7 @@ static struct pci_driver kahlua_driver = {
.name = "kahlua",
.id_table = id_tbl,
.probe = probe_one,
- .remove = __devexit_p(remove_one),
+ .remove = remove_one,
};
@@ -220,7 +220,7 @@ static int __init kahlua_init_module(void)
return pci_register_driver(&kahlua_driver);
}
-static void __devexit kahlua_cleanup_module(void)
+static void kahlua_cleanup_module(void)
{
pci_unregister_driver(&kahlua_driver);
}
diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c
index b2b3c014221a..048439a16000 100644
--- a/sound/oss/sb_audio.c
+++ b/sound/oss/sb_audio.c
@@ -442,7 +442,7 @@ static int sb201_audio_set_speed(int dev, int speed)
{
sb_devc *devc = audio_devs[dev]->devc;
int tmp;
- int s = speed * devc->channels;
+ int s;
if (speed > 0)
{
@@ -452,6 +452,7 @@ static int sb201_audio_set_speed(int dev, int speed)
speed = 44100;
if (devc->opened & OPEN_READ && speed > 15000)
speed = 15000;
+ s = speed * devc->channels;
devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
tmp = 256 - devc->tconst;
speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index f47f9e226b08..0e66ba48d453 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -856,7 +856,7 @@ static struct snd_kcontrol_new snd_harmony_controls[] = {
HARMONY_GAIN_HE_SHIFT, 1, 0),
};
-static void __devinit
+static void
snd_harmony_mixer_reset(struct snd_harmony *h)
{
harmony_mute(h);
@@ -865,7 +865,7 @@ snd_harmony_mixer_reset(struct snd_harmony *h)
harmony_unmute(h);
}
-static int __devinit
+static int
snd_harmony_mixer_init(struct snd_harmony *h)
{
struct snd_card *card;
@@ -915,7 +915,7 @@ snd_harmony_dev_free(struct snd_device *dev)
return snd_harmony_free(h);
}
-static int __devinit
+static int
snd_harmony_create(struct snd_card *card,
struct parisc_device *padev,
struct snd_harmony **rchip)
@@ -972,7 +972,7 @@ free_and_ret:
return err;
}
-static int __devinit
+static int
snd_harmony_probe(struct parisc_device *padev)
{
int err;
@@ -1012,7 +1012,7 @@ free_and_ret:
return err;
}
-static int __devexit
+static int
snd_harmony_remove(struct parisc_device *padev)
{
snd_card_free(parisc_get_drvdata(padev));
@@ -1024,7 +1024,7 @@ static struct parisc_driver snd_harmony_driver = {
.name = "harmony",
.id_table = snd_harmony_devtable,
.probe = snd_harmony_probe,
- .remove = __devexit_p(snd_harmony_remove),
+ .remove = snd_harmony_remove,
};
static int __init
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index f99fa2512286..947cfb4eb30c 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -572,6 +572,7 @@ source "sound/pci/hda/Kconfig"
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
+ select FW_LOADER
select SND_HWDEP
select SND_RAWMIDI
select SND_PCM
@@ -630,7 +631,7 @@ config SND_ICE1724
AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules
Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal
192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS,
- AV-710; Shuttle SN25P.
+ AV-710; Shuttle SN25P; Philips PSC724 Ultimate Edge.
To compile this driver as a module, choose M here: the module
will be called snd-ice1724.
@@ -707,6 +708,7 @@ config SND_MAESTRO3_INPUT
config SND_MIXART
tristate "Digigram miXart"
+ select FW_LOADER
select SND_HWDEP
select SND_PCM
help
@@ -727,6 +729,7 @@ config SND_NM256
config SND_PCXHR
tristate "Digigram PCXHR"
+ select FW_LOADER
select SND_PCM
select SND_HWDEP
help
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index e672ff4df2da..ad8a31173939 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -624,7 +624,7 @@ snd_ad1889_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit
+static int
snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm)
{
int err;
@@ -747,7 +747,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
}
-static void __devinit
+static void
snd_ad1889_proc_init(struct snd_ad1889 *chip)
{
struct snd_info_entry *entry;
@@ -767,7 +767,7 @@ static struct ac97_quirk ac97_quirks[] = {
{ } /* terminator */
};
-static void __devinit
+static void
snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
{
u16 reg;
@@ -805,7 +805,7 @@ snd_ad1889_ac97_free(struct snd_ac97 *ac97)
chip->ac97 = NULL;
}
-static int __devinit
+static int
snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
{
int err;
@@ -878,7 +878,7 @@ snd_ad1889_dev_free(struct snd_device *device)
return snd_ad1889_free(chip);
}
-static int __devinit
+static int
snd_ad1889_init(struct snd_ad1889 *chip)
{
ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
@@ -892,7 +892,7 @@ snd_ad1889_init(struct snd_ad1889 *chip)
return 0;
}
-static int __devinit
+static int
snd_ad1889_create(struct snd_card *card,
struct pci_dev *pci,
struct snd_ad1889 **rchip)
@@ -978,7 +978,7 @@ free_and_ret:
return err;
}
-static int __devinit
+static int
snd_ad1889_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -1042,7 +1042,7 @@ free_and_ret:
return err;
}
-static void __devexit
+static void
snd_ad1889_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
@@ -1059,7 +1059,7 @@ static struct pci_driver ad1889_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ad1889_ids,
.probe = snd_ad1889_probe,
- .remove = __devexit_p(snd_ad1889_remove),
+ .remove = snd_ad1889_remove,
};
module_pci_driver(ad1889_pci_driver);
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
index cadf7b962e30..3bf0dc53360a 100644
--- a/sound/pci/ak4531_codec.c
+++ b/sound/pci/ak4531_codec.c
@@ -274,7 +274,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
-static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ak4531_controls[] = {
AK4531_DOUBLE_TLV("Master Playback Switch", 0,
AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
@@ -383,9 +383,9 @@ static u8 snd_ak4531_initial_map[0x19 + 1] = {
0x01 /* 19: Mic Amp Setup */
};
-int __devinit snd_ak4531_mixer(struct snd_card *card,
- struct snd_ak4531 *_ak4531,
- struct snd_ak4531 **rak4531)
+int snd_ak4531_mixer(struct snd_card *card,
+ struct snd_ak4531 *_ak4531,
+ struct snd_ak4531 **rak4531)
{
unsigned int idx;
int err;
@@ -483,7 +483,7 @@ static void snd_ak4531_proc_read(struct snd_info_entry *entry,
ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
}
-static void __devinit
+static void
snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
{
struct snd_info_entry *entry;
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index c7e3c533316e..136a393b70ab 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1678,8 +1678,8 @@ static void snd_ali_pcm_free(struct snd_pcm *pcm)
}
-static int __devinit snd_ali_pcm(struct snd_ali * codec, int device,
- struct ali_pcm_description *desc)
+static int snd_ali_pcm(struct snd_ali *codec, int device,
+ struct ali_pcm_description *desc)
{
struct snd_pcm *pcm;
int err;
@@ -1727,7 +1727,7 @@ static struct ali_pcm_description ali_pcms[] = {
}
};
-static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
+static int snd_ali_build_pcms(struct snd_ali *codec)
{
int i, err;
for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {
@@ -1832,7 +1832,7 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
/* spdif aplayback switch */
/* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
@@ -1842,7 +1842,7 @@ static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
};
-static int __devinit snd_ali_mixer(struct snd_ali * codec)
+static int snd_ali_mixer(struct snd_ali *codec)
{
struct snd_ac97_template ac97;
unsigned int idx;
@@ -2079,14 +2079,14 @@ static void snd_ali_proc_read(struct snd_info_entry *entry,
snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
}
-static void __devinit snd_ali_proc_init(struct snd_ali *codec)
+static void snd_ali_proc_init(struct snd_ali *codec)
{
struct snd_info_entry *entry;
if (!snd_card_proc_new(codec->card, "ali5451", &entry))
snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
}
-static int __devinit snd_ali_resources(struct snd_ali *codec)
+static int snd_ali_resources(struct snd_ali *codec)
{
int err;
@@ -2112,11 +2112,11 @@ static int snd_ali_dev_free(struct snd_device *device)
return 0;
}
-static int __devinit snd_ali_create(struct snd_card *card,
- struct pci_dev *pci,
- int pcm_streams,
- int spdif_support,
- struct snd_ali ** r_ali)
+static int snd_ali_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int pcm_streams,
+ int spdif_support,
+ struct snd_ali **r_ali)
{
struct snd_ali *codec;
int i, err;
@@ -2246,8 +2246,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
return 0;
}
-static int __devinit snd_ali_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_ali_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct snd_ali *codec;
@@ -2295,7 +2295,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_ali_remove(struct pci_dev *pci)
+static void snd_ali_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2305,7 +2305,7 @@ static struct pci_driver ali5451_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
- .remove = __devexit_p(snd_ali_remove),
+ .remove = snd_ali_remove,
.driver = {
.pm = ALI_PM_OPS,
},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 5af3cb6b0c18..864c4310366b 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -278,7 +278,7 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void __devexit snd_als300_remove(struct pci_dev *pci)
+static void snd_als300_remove(struct pci_dev *pci)
{
snd_als300_dbgcallenter();
snd_card_free(pci_get_drvdata(pci));
@@ -622,7 +622,7 @@ static struct snd_pcm_ops snd_als300_capture_ops = {
.pointer = snd_als300_pointer,
};
-static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
+static int snd_als300_new_pcm(struct snd_als300 *chip)
{
struct snd_pcm *pcm;
int err;
@@ -683,9 +683,9 @@ static void snd_als300_init(struct snd_als300 *chip)
snd_als300_dbgcallleave();
}
-static int __devinit snd_als300_create(struct snd_card *card,
- struct pci_dev *pci, int chip_type,
- struct snd_als300 **rchip)
+static int snd_als300_create(struct snd_card *card,
+ struct pci_dev *pci, int chip_type,
+ struct snd_als300 **rchip)
{
struct snd_als300 *chip;
void *irq_handler;
@@ -815,7 +815,7 @@ static SIMPLE_DEV_PM_OPS(snd_als300_pm, snd_als300_suspend, snd_als300_resume);
#define SND_ALS300_PM_OPS NULL
#endif
-static int __devinit snd_als300_probe(struct pci_dev *pci,
+static int snd_als300_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
@@ -867,7 +867,7 @@ static struct pci_driver als300_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als300_ids,
.probe = snd_als300_probe,
- .remove = __devexit_p(snd_als300_remove),
+ .remove = snd_als300_remove,
.driver = {
.pm = SND_ALS300_PM_OPS,
},
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index feb2a1436830..61efda2a4d94 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -694,7 +694,7 @@ static struct snd_pcm_ops snd_als4000_capture_ops = {
.pointer = snd_als4000_capture_pointer
};
-static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device)
+static int snd_als4000_pcm(struct snd_sb *chip, int device)
{
struct snd_pcm *pcm;
int err;
@@ -770,7 +770,7 @@ static void snd_als4000_configure(struct snd_sb *chip)
}
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
+static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
{
struct gameport *gp;
struct resource *r;
@@ -847,8 +847,8 @@ static void snd_card_als4000_free( struct snd_card *card )
pci_disable_device(acard->pci);
}
-static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_card_als4000_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -981,7 +981,7 @@ out:
return err;
}
-static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
+static void snd_card_als4000_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1046,7 +1046,7 @@ static struct pci_driver als4000_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
- .remove = __devexit_p(snd_card_als4000_remove),
+ .remove = snd_card_als4000_remove,
.driver = {
.pm = SND_ALS4000_PM_OPS,
},
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index eedc017c1cd8..3536b076b529 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -1235,8 +1235,7 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
.pointer = snd_card_asihpi_capture_pointer,
};
-static int __devinit snd_card_asihpi_pcm_new(
- struct snd_card_asihpi *asihpi, int device)
+static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)
{
struct snd_pcm *pcm;
int err;
@@ -1497,8 +1496,8 @@ static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,
return change;
}
-static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -1593,8 +1592,8 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);
-static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -1715,8 +1714,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -1753,8 +1752,8 @@ static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
}
-static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -1996,8 +1995,8 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
}
/* Tuner control group initializer */
-static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -2100,8 +2099,8 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl, int subidx)
+static int snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl, int subidx)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -2214,8 +2213,8 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
}
-static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -2303,8 +2302,8 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
}
-static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -2471,8 +2470,8 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
- struct hpi_control *hpi_ctl)
+static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
+ struct hpi_control *hpi_ctl)
{
struct snd_card *card = asihpi->card;
struct snd_kcontrol_new snd_control;
@@ -2548,7 +2547,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
Mixer
------------------------------------------------------------*/
-static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
+static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
{
struct snd_card *card = asihpi->card;
unsigned int idx = 0;
@@ -2722,7 +2721,7 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
}
}
-static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
+static void snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
{
struct snd_info_entry *entry;
@@ -2764,8 +2763,8 @@ static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
/* results in /dev/snd/hwC#D0 file for each card with index #
also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
*/
-static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
- int device, struct snd_hwdep **rhwdep)
+static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
+ int device, struct snd_hwdep **rhwdep)
{
struct snd_hwdep *hw;
int err;
@@ -2789,8 +2788,8 @@ static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
/*------------------------------------------------------------
CARD
------------------------------------------------------------*/
-static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static int snd_asihpi_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
{
int err;
struct hpi_adapter *hpi;
@@ -2944,7 +2943,7 @@ __nodev:
}
-static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
+static void snd_asihpi_remove(struct pci_dev *pci_dev)
{
struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
snd_card_free(hpi->snd_card);
@@ -2967,7 +2966,7 @@ static struct pci_driver driver = {
.name = KBUILD_MODNAME,
.id_table = asihpi_pci_tbl,
.probe = snd_asihpi_probe,
- .remove = __devexit_p(snd_asihpi_remove),
+ .remove = snd_asihpi_remove,
#ifdef CONFIG_PM_SLEEP
/* .suspend = snd_asihpi_suspend,
.resume = snd_asihpi_resume, */
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index 456a758f04f6..ac9163770013 100644
--- a/sound/pci/asihpi/hpidspcd.c
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -49,14 +49,12 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
err = request_firmware(&firmware, fw_name, &dev->dev);
if (err || !firmware) {
- dev_printk(KERN_ERR, &dev->dev,
- "%d, request_firmware failed for %s\n", err,
- fw_name);
+ dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
+ err, fw_name);
goto error1;
}
if (firmware->size < sizeof(header)) {
- dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n",
- fw_name);
+ dev_err(&dev->dev, "Header size too small %s\n", fw_name);
goto error2;
}
memcpy(&header, firmware->data, sizeof(header));
@@ -64,7 +62,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
if ((header.type != 0x45444F43) || /* "CODE" */
(header.adapter != adapter)
|| (header.size != firmware->size)) {
- dev_printk(KERN_ERR, &dev->dev,
+ dev_err(&dev->dev,
"Invalid firmware header size %d != file %zd\n",
header.size, firmware->size);
goto error2;
@@ -72,17 +70,15 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
if ((header.version >> 9) != (HPI_VER >> 9)) {
/* Consider even and subsequent odd minor versions to be compatible */
- dev_printk(KERN_ERR, &dev->dev,
- "Incompatible firmware version "
- "DSP image %X != Driver %X\n", header.version,
- HPI_VER);
+ dev_err(&dev->dev, "Incompatible firmware version DSP image %X != Driver %X\n",
+ header.version, HPI_VER);
goto error2;
}
if (header.version != HPI_VER) {
- dev_printk(KERN_INFO, &dev->dev,
- "Firmware: release version mismatch DSP image %X != Driver %X\n",
- header.version, HPI_VER);
+ dev_info(&dev->dev,
+ "Firmware: release version mismatch DSP image %X != Driver %X\n",
+ header.version, HPI_VER);
}
HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 609156205562..ef5019fe5193 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -307,8 +307,8 @@ out:
return err;
}
-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+int asihpi_adapter_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
{
int idx, nm;
int adapter_index;
@@ -326,7 +326,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
pci_dev->subsystem_device, pci_dev->devfn);
if (pci_enable_device(pci_dev) < 0) {
- dev_printk(KERN_ERR, &pci_dev->dev,
+ dev_err(&pci_dev->dev,
"pci_enable_device failed, disabling device\n");
return -EIO;
}
@@ -398,9 +398,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
mutex_init(&adapters[adapter_index].mutex);
pci_set_drvdata(pci_dev, &adapters[adapter_index]);
- dev_printk(KERN_INFO, &pci_dev->dev,
- "probe succeeded for ASI%04X HPI index %d\n",
- adapter.adapter->type, adapter_index);
+ dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
+ adapter.adapter->type, adapter_index);
return 0;
@@ -421,7 +420,7 @@ err:
return -ENODEV;
}
-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
+void asihpi_adapter_remove(struct pci_dev *pci_dev)
{
int idx;
struct hpi_message hm;
@@ -448,11 +447,11 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
if (1)
- dev_printk(KERN_INFO, &pci_dev->dev,
- "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n",
- pci_dev->vendor, pci_dev->device,
- pci_dev->subsystem_vendor, pci_dev->subsystem_device,
- pci_dev->devfn, pa->adapter->index);
+ dev_info(&pci_dev->dev,
+ "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n",
+ pci_dev->vendor, pci_dev->device,
+ pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+ pci_dev->devfn, pa->adapter->index);
memset(pa, 0, sizeof(*pa));
}
diff --git a/sound/pci/asihpi/hpioctl.h b/sound/pci/asihpi/hpioctl.h
index 2614aff672e2..0d767e10ac48 100644
--- a/sound/pci/asihpi/hpioctl.h
+++ b/sound/pci/asihpi/hpioctl.h
@@ -19,9 +19,9 @@
Linux HPI ioctl, and shared module init functions
*******************************************************************************/
-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id);
-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev);
+int asihpi_adapter_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id);
+void asihpi_adapter_remove(struct pci_dev *pci_dev);
void __init asihpi_init(void);
void __exit asihpi_exit(void);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 368df8b0853e..a67743183aaf 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -296,7 +296,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = {
MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
-static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
+static struct snd_pci_quirk atiixp_quirks[] = {
SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
{ } /* terminator */
@@ -561,7 +561,7 @@ static int snd_atiixp_aclink_down(struct atiixp *chip)
ATI_REG_ISR_CODEC2_NOT_READY)
#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
-static int __devinit ac97_probing_bugs(struct pci_dev *pci)
+static int ac97_probing_bugs(struct pci_dev *pci)
{
const struct snd_pci_quirk *q;
@@ -575,7 +575,7 @@ static int __devinit ac97_probing_bugs(struct pci_dev *pci)
return -1;
}
-static int __devinit snd_atiixp_codec_detect(struct atiixp *chip)
+static int snd_atiixp_codec_detect(struct atiixp *chip)
{
int timeout;
@@ -1183,7 +1183,7 @@ static struct snd_pcm_ops snd_atiixp_spdif_ops = {
.pointer = snd_atiixp_pcm_pointer,
};
-static struct ac97_pcm atiixp_pcm_defs[] __devinitdata = {
+static struct ac97_pcm atiixp_pcm_defs[] = {
/* front PCM */
{
.exclusive = 1,
@@ -1247,7 +1247,7 @@ static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
};
-static int __devinit snd_atiixp_pcm_new(struct atiixp *chip)
+static int snd_atiixp_pcm_new(struct atiixp *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_chmap *chmap;
@@ -1390,7 +1390,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
* ac97 mixer section
*/
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
{
.subvendor = 0x103c,
.subdevice = 0x006b,
@@ -1412,8 +1412,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
{ } /* terminator */
};
-static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
- const char *quirk_override)
+static int snd_atiixp_mixer_new(struct atiixp *chip, int clock,
+ const char *quirk_override)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -1560,7 +1560,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
}
-static void __devinit snd_atiixp_proc_init(struct atiixp *chip)
+static void snd_atiixp_proc_init(struct atiixp *chip)
{
struct snd_info_entry *entry;
@@ -1602,9 +1602,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
/*
* constructor for chip instance
*/
-static int __devinit snd_atiixp_create(struct snd_card *card,
- struct pci_dev *pci,
- struct atiixp **r_chip)
+static int snd_atiixp_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct atiixp **r_chip)
{
static struct snd_device_ops ops = {
.dev_free = snd_atiixp_dev_free,
@@ -1661,8 +1661,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
}
-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_atiixp_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct atiixp *chip;
@@ -1710,7 +1710,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+static void snd_atiixp_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1720,7 +1720,7 @@ static struct pci_driver atiixp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
- .remove = __devexit_p(snd_atiixp_remove),
+ .remove = snd_atiixp_remove,
.driver = {
.pm = SND_ATIIXP_PM_OPS,
},
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 6fc03d9f2cff..d0bec7ba3b0d 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -988,7 +988,7 @@ static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.flush_dma = atiixp_in_flush_dma,
};
-static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip)
+static int snd_atiixp_pcm_new(struct atiixp_modem *chip)
{
struct snd_pcm *pcm;
int err;
@@ -1061,7 +1061,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
* ac97 mixer section
*/
-static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
+static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -1186,7 +1186,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
}
-static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
+static void snd_atiixp_proc_init(struct atiixp_modem *chip)
{
struct snd_info_entry *entry;
@@ -1228,9 +1228,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
/*
* constructor for chip instance
*/
-static int __devinit snd_atiixp_create(struct snd_card *card,
- struct pci_dev *pci,
- struct atiixp_modem **r_chip)
+static int snd_atiixp_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct atiixp_modem **r_chip)
{
static struct snd_device_ops ops = {
.dev_free = snd_atiixp_dev_free,
@@ -1287,8 +1287,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
}
-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_atiixp_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct atiixp_modem *chip;
@@ -1331,7 +1331,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+static void snd_atiixp_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1341,7 +1341,7 @@ static struct pci_driver atiixp_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
- .remove = __devexit_p(snd_atiixp_remove),
+ .remove = snd_atiixp_remove,
.driver = {
.pm = SND_ATIIXP_PM_OPS,
},
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index ffc376f9f4e4..b157e1fadd8f 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -78,7 +78,7 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
}
}
-static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
+static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
{
struct pci_dev *via = NULL;
@@ -137,7 +137,7 @@ static int snd_vortex_dev_free(struct snd_device *device)
// chip-specific constructor
// (see "Management of Cards and Components")
-static int __devinit
+static int
snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
{
vortex_t *chip;
@@ -234,7 +234,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
}
// constructor -- see "Constructor" sub-section
-static int __devinit
+static int
snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -368,7 +368,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
}
// destructor -- see "Destructor" sub-section
-static void __devexit snd_vortex_remove(struct pci_dev *pci)
+static void snd_vortex_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -379,7 +379,7 @@ static struct pci_driver vortex_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
- .remove = __devexit_p(snd_vortex_remove),
+ .remove = snd_vortex_remove,
};
module_pci_driver(vortex_driver);
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
index 9ae8b3b17651..aad831acbb17 100644
--- a/sound/pci/au88x0/au88x0_a3d.c
+++ b/sound/pci/au88x0/au88x0_a3d.c
@@ -594,7 +594,7 @@ static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
static int vortex_a3d_register_controls(vortex_t * vortex);
static void vortex_a3d_unregister_controls(vortex_t * vortex);
/* A3D base support init/shudown */
-static void __devinit vortex_Vort3D_enable(vortex_t * v)
+static void vortex_Vort3D_enable(vortex_t *v)
{
int i;
@@ -845,7 +845,7 @@ snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_a3d_kcontrol = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Playback PCM advanced processing",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -855,7 +855,7 @@ static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
};
/* Control (un)registration. */
-static int __devinit vortex_a3d_register_controls(vortex_t * vortex)
+static int vortex_a3d_register_controls(vortex_t *vortex)
{
struct snd_kcontrol *kcontrol;
int err, i;
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 525f881f0409..ae59dbaa53d9 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2461,7 +2461,12 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
#ifndef CHIP_AU8810
for (i = 0; i < NR_WT; i++) {
if (vortex->dma_wt[i].fifo_status == FIFO_START) {
- if (vortex_wtdma_bufshift(vortex, i)) ;
+ /* FIXME: we ignore the return value from
+ * vortex_wtdma_bufshift() below as the delta
+ * calculation seems not working for wavetable
+ * by some reason
+ */
+ vortex_wtdma_bufshift(vortex, i);
spin_unlock(&vortex->lock);
snd_pcm_period_elapsed(vortex->dma_wt[i].
substream);
@@ -2675,7 +2680,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
/* Initialization */
-static int __devinit vortex_core_init(vortex_t * vortex)
+static int vortex_core_init(vortex_t *vortex)
{
printk(KERN_INFO "Vortex: init.... ");
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 278ed8189fca..e7220533ecfc 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -757,7 +757,7 @@ snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
return 1; /* Allways changes */
}
-static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "EQ Enable",
.index = 0,
@@ -815,7 +815,7 @@ snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucon
return changed;
}
-static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eq_kcontrol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = " .",
.index = 0,
@@ -854,7 +854,7 @@ snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u
return 0;
}
-static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_levels_kcontrol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "EQ Peaks",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -863,7 +863,7 @@ static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
};
/* EQ band gain labels. */
-static char *EqBandLabels[10] __devinitdata = {
+static char *EqBandLabels[10] = {
"EQ0 31Hz\0",
"EQ1 63Hz\0",
"EQ2 125Hz\0",
@@ -877,7 +877,7 @@ static char *EqBandLabels[10] __devinitdata = {
};
/* ALSA driver entry points. Init and exit. */
-static int __devinit vortex_eq_init(vortex_t * vortex)
+static int vortex_eq_init(vortex_t *vortex)
{
struct snd_kcontrol *kcontrol;
int err, i;
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
index 30a456700d89..280f86de2230 100644
--- a/sound/pci/au88x0/au88x0_game.c
+++ b/sound/pci/au88x0/au88x0_game.c
@@ -92,7 +92,7 @@ static int vortex_game_open(struct gameport *gameport, int mode)
return 0;
}
-static int __devinit vortex_gameport_register(vortex_t * vortex)
+static int vortex_gameport_register(vortex_t *vortex)
{
struct gameport *gp;
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index fa13efbebdaf..a58298cfe7e0 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -19,7 +19,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
return snd_ctl_remove_id(card, &id);
}
-static int __devinit snd_vortex_mixer(vortex_t * vortex)
+static int snd_vortex_mixer(vortex_t *vortex)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index e6c6a0febb75..29e5945eef60 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -41,7 +41,7 @@
#define MPU401_ENTER_UART 0x3f
#define MPU401_ACK 0xfe
-static int __devinit snd_vortex_midi(vortex_t * vortex)
+static int snd_vortex_midi(vortex_t *vortex)
{
struct snd_rawmidi *rmidi;
int temp, mode;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index b2405020284c..a4184bb27761 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -516,7 +516,7 @@ static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
}
/* spdif controls */
-static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -598,7 +598,7 @@ static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
-static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+static struct snd_kcontrol_new snd_vortex_pcm_vol = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -611,7 +611,7 @@ static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
};
/* create a pcm device */
-static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
+static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
{
struct snd_pcm *pcm;
struct snd_kcontrol *kctl;
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 0f804741825f..08e9a4702cbc 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -113,11 +113,11 @@ struct aw2 {
* FUNCTION DECLARATIONS
********************************/
static int snd_aw2_dev_free(struct snd_device *device);
-static int __devinit snd_aw2_create(struct snd_card *card,
- struct pci_dev *pci, struct aw2 **rchip);
-static int __devinit snd_aw2_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id);
-static void __devexit snd_aw2_remove(struct pci_dev *pci);
+static int snd_aw2_create(struct snd_card *card,
+ struct pci_dev *pci, struct aw2 **rchip);
+static int snd_aw2_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id);
+static void snd_aw2_remove(struct pci_dev *pci);
static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
@@ -135,7 +135,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
*substream);
static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
*substream);
-static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
+static int snd_aw2_new_pcm(struct aw2 *chip);
static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
@@ -173,7 +173,7 @@ static struct pci_driver aw2_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_aw2_ids,
.probe = snd_aw2_probe,
- .remove = __devexit_p(snd_aw2_remove),
+ .remove = snd_aw2_remove,
};
module_pci_driver(aw2_driver);
@@ -202,7 +202,7 @@ static struct snd_pcm_ops snd_aw2_capture_ops = {
.pointer = snd_aw2_pcm_pointer_capture,
};
-static struct snd_kcontrol_new aw2_control __devinitdata = {
+static struct snd_kcontrol_new aw2_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Capture Route",
.index = 0,
@@ -242,8 +242,8 @@ static int snd_aw2_dev_free(struct snd_device *device)
}
/* chip-specific constructor */
-static int __devinit snd_aw2_create(struct snd_card *card,
- struct pci_dev *pci, struct aw2 **rchip)
+static int snd_aw2_create(struct snd_card *card,
+ struct pci_dev *pci, struct aw2 **rchip)
{
struct aw2 *chip;
int err;
@@ -332,8 +332,8 @@ static int __devinit snd_aw2_create(struct snd_card *card,
}
/* constructor */
-static int __devinit snd_aw2_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_aw2_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -389,7 +389,7 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci,
}
/* destructor */
-static void __devexit snd_aw2_remove(struct pci_dev *pci)
+static void snd_aw2_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -591,7 +591,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
}
/* create a pcm device */
-static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
+static int snd_aw2_new_pcm(struct aw2 *chip)
{
struct snd_pcm *pcm_playback_ana;
struct snd_pcm *pcm_playback_num;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index c03b66b784a3..1204a0fa3368 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -817,7 +817,7 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write");
}
-static int __devinit
+static int
snd_azf3328_mixer_new(struct snd_azf3328 *chip)
{
struct snd_ac97_bus *bus;
@@ -1171,7 +1171,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
return (nreg != oreg);
}
-static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
@@ -1229,7 +1229,7 @@ static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
#endif
};
-static u16 __devinitdata snd_azf3328_init_values[][2] = {
+static u16 snd_azf3328_init_values[][2] = {
{ IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_BASSTREBLE, 0x0000 },
@@ -1245,7 +1245,7 @@ static u16 __devinitdata snd_azf3328_init_values[][2] = {
{ IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 },
};
-static int __devinit
+static int
snd_azf3328_mixer_new(struct snd_azf3328 *chip)
{
struct snd_card *card;
@@ -1899,7 +1899,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
return 0;
}
-static int __devinit
+static int
snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
{
struct gameport *gp;
@@ -2212,7 +2212,7 @@ static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
.pointer = snd_azf3328_pcm_pointer
};
-static int __devinit
+static int
snd_azf3328_pcm(struct snd_azf3328 *chip)
{
enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
@@ -2344,7 +2344,7 @@ static struct snd_timer_hardware snd_azf3328_timer_hw = {
.precise_resolution = snd_azf3328_timer_precise_resolution,
};
-static int __devinit
+static int
snd_azf3328_timer(struct snd_azf3328 *chip, int device)
{
struct snd_timer *timer = NULL;
@@ -2489,7 +2489,7 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
#endif /* DEBUG_MISC */
}
-static int __devinit
+static int
snd_azf3328_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type,
@@ -2615,7 +2615,7 @@ out:
return err;
}
-static int __devinit
+static int
snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -2720,7 +2720,7 @@ out:
return err;
}
-static void __devexit
+static void
snd_azf3328_remove(struct pci_dev *pci)
{
snd_azf3328_dbgcallenter();
@@ -2872,7 +2872,7 @@ static struct pci_driver azf3328_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
- .remove = __devexit_p(snd_azf3328_remove),
+ .remove = snd_azf3328_remove,
.driver = {
.pm = SND_AZF3328_PM_OPS,
},
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index b6a95eeca095..cdd100dae855 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -164,7 +164,7 @@ struct snd_bt87x_board {
unsigned no_digital:1; /* No digital input */
};
-static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = {
+static struct snd_bt87x_board snd_bt87x_boards[] = {
[SND_BT87X_BOARD_UNKNOWN] = {
.dig_rate = 32000, /* just a guess */
},
@@ -696,7 +696,7 @@ static int snd_bt87x_dev_free(struct snd_device *device)
return snd_bt87x_free(chip);
}
-static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
+static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
{
int err;
struct snd_pcm *pcm;
@@ -714,9 +714,9 @@ static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *nam
ALIGN(255 * 4092, 1024));
}
-static int __devinit snd_bt87x_create(struct snd_card *card,
- struct pci_dev *pci,
- struct snd_bt87x **rchip)
+static int snd_bt87x_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct snd_bt87x **rchip)
{
struct snd_bt87x *chip;
int err;
@@ -822,7 +822,7 @@ MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
* (DVB cards use the audio function to transfer MPEG data) */
static struct {
unsigned short subvendor, subdevice;
-} blacklist[] __devinitdata = {
+} blacklist[] = {
{0x0071, 0x0101}, /* Nebula Electronics DigiTV */
{0x11bd, 0x001c}, /* Pinnacle PCTV Sat */
{0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */
@@ -837,7 +837,7 @@ static struct {
};
/* return the id of the card, or a negative value if it's blacklisted */
-static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
+static int snd_bt87x_detect_card(struct pci_dev *pci)
{
int i;
const struct pci_device_id *supported;
@@ -862,8 +862,8 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
return SND_BT87X_BOARD_UNKNOWN;
}
-static int __devinit snd_bt87x_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_bt87x_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -948,7 +948,7 @@ _error:
return err;
}
-static void __devexit snd_bt87x_remove(struct pci_dev *pci)
+static void snd_bt87x_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -966,7 +966,7 @@ static struct pci_driver bt87x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
- .remove = __devexit_p(snd_bt87x_remove),
+ .remove = snd_bt87x_remove,
};
module_pci_driver(bt87x_driver);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 65c55910566b..1610a5705970 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1352,7 +1352,7 @@ static const struct snd_pcm_chmap_elem side_map[] = {
{ }
};
-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
+static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -1650,7 +1650,7 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
*/
}
-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
+static int snd_ca0106_create(int dev, struct snd_card *card,
struct pci_dev *pci,
struct snd_ca0106 **rchip)
{
@@ -1777,7 +1777,7 @@ static int ca0106_dev_id_port(void *dev_id)
return ((struct snd_ca0106 *)dev_id)->port;
}
-static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
+static int snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
{
struct snd_ca_midi *midi;
char *name;
@@ -1828,7 +1828,7 @@ static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int chann
}
-static int __devinit snd_ca0106_probe(struct pci_dev *pci,
+static int snd_ca0106_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
@@ -1893,7 +1893,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_ca0106_remove(struct pci_dev *pci)
+static void snd_ca0106_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1971,7 +1971,7 @@ static struct pci_driver ca0106_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
- .remove = __devexit_p(snd_ca0106_remove),
+ .remove = snd_ca0106_remove,
.driver = {
.pm = SND_CA0106_PM_OPS,
},
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 68eacf7002d6..27de0de90018 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -325,7 +325,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
+static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Shared Mic/Line in Capture Switch",
@@ -334,7 +334,7 @@ static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
.put = snd_ca0106_capture_mic_line_in_put
};
-static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
+static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Shared Line in/Side out Capture Switch",
@@ -588,7 +588,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol,
.private_value = ((chid) << 8) | (reg) \
}
-static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
CA_VOLUME("Analog Front Playback Volume",
CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
CA_VOLUME("Analog Rear Playback Volume",
@@ -669,7 +669,7 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
.private_value = chid \
}
-static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
I2C_VOLUME("Phone Capture Volume", 0),
I2C_VOLUME("Mic Capture Volume", 1),
I2C_VOLUME("Line in Capture Volume", 2),
@@ -691,7 +691,7 @@ static const int spi_dmute_bit[] = {
SPI_DMUTE4_BIT,
};
-static struct snd_kcontrol_new __devinit
+static struct snd_kcontrol_new
snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
int channel_id)
{
@@ -735,7 +735,7 @@ snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
return spi_switch;
}
-static int __devinit remove_ctl(struct snd_card *card, const char *name)
+static int remove_ctl(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
@@ -744,7 +744,7 @@ static int __devinit remove_ctl(struct snd_card *card, const char *name)
return snd_ctl_remove_id(card, &id);
}
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
@@ -754,7 +754,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char
return snd_ctl_find_id(card, &sid);
}
-static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
+static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
{
struct snd_kcontrol *kctl = ctl_find(card, src);
if (kctl) {
@@ -774,10 +774,10 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
} \
} while (0)
-static __devinitdata
+static
DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
"Analog Front Playback Volume",
"Analog Rear Playback Volume",
"Analog Center/LFE Playback Volume",
@@ -790,7 +790,7 @@ static char *slave_vols[] __devinitdata = {
NULL
};
-static char *slave_sws[] __devinitdata = {
+static char *slave_sws[] = {
"Analog Front Playback Switch",
"Analog Rear Playback Switch",
"Analog Center/LFE Playback Switch",
@@ -799,7 +799,7 @@ static char *slave_sws[] __devinitdata = {
NULL
};
-static void __devinit add_slaves(struct snd_card *card,
+static void add_slaves(struct snd_card *card,
struct snd_kcontrol *master, char **list)
{
for (; *list; list++) {
@@ -809,7 +809,7 @@ static void __devinit add_slaves(struct snd_card *card,
}
}
-int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+int snd_ca0106_mixer(struct snd_ca0106 *emu)
{
int err;
struct snd_card *card = emu->card;
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index c694464b1168..4f9c2821bb31 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -424,7 +424,7 @@ static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry,
}
}
-int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
+int snd_ca0106_proc_init(struct snd_ca0106 *emu)
{
struct snd_info_entry *entry;
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
index c7885117da33..8bbdf265d11d 100644
--- a/sound/pci/ca0106/ca_midi.c
+++ b/sound/pci/ca0106/ca_midi.c
@@ -286,7 +286,7 @@ static void ca_rmidi_free(struct snd_rawmidi *rmidi)
ca_midi_free(rmidi->private_data);
}
-int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
+int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
{
struct snd_rawmidi *rmidi;
int err;
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 22122ff26e34..c617435db6e6 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -1045,7 +1045,7 @@ static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_default =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1072,7 +1072,7 @@ static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_mask =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1119,7 +1119,7 @@ static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_stream =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1897,7 +1897,7 @@ static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
/*
*/
-static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm_new(struct cmipci *cm, int device)
{
struct snd_pcm *pcm;
int err;
@@ -1920,7 +1920,7 @@ static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
return 0;
}
-static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm2_new(struct cmipci *cm, int device)
{
struct snd_pcm *pcm;
int err;
@@ -1942,7 +1942,7 @@ static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
return 0;
}
-static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
{
struct snd_pcm *pcm;
int err;
@@ -2290,7 +2290,7 @@ static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
}
-static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixers[] = {
CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31),
@@ -2601,7 +2601,7 @@ static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol,
}
/* both for CM8338/8738 */
-static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
{
.name = "Line-In Mode",
@@ -2613,11 +2613,11 @@ static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
};
/* for non-multichannel chips */
-static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_nomulti_switch =
DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac);
/* only for CM8738 */
-static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
#if 0 /* controlled in pcm device */
DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in),
DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out),
@@ -2639,14 +2639,14 @@ static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata =
};
/* only for model 033/037 */
-static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] = {
DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1),
};
/* only for model 039 or later */
-static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
{
@@ -2659,11 +2659,11 @@ static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata =
};
/* card control switches */
-static struct snd_kcontrol_new snd_cmipci_modem_switch __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_modem_switch =
DEFINE_CARD_SWITCH("Modem", modem);
-static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
+static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
{
struct snd_card *card;
struct snd_kcontrol_new *sw;
@@ -2791,7 +2791,7 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "\n");
}
-static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
+static void snd_cmipci_proc_init(struct cmipci *cm)
{
struct snd_info_entry *entry;
@@ -2817,7 +2817,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = {
* check chip version and capabilities
* driver name is modified according to the chip model
*/
-static void __devinit query_chip(struct cmipci *cm)
+static void query_chip(struct cmipci *cm)
{
unsigned int detect;
@@ -2866,7 +2866,7 @@ static void __devinit query_chip(struct cmipci *cm)
}
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev)
+static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
{
static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
struct gameport *gp;
@@ -2959,7 +2959,7 @@ static int snd_cmipci_dev_free(struct snd_device *device)
return snd_cmipci_free(cm);
}
-static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
+static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
{
long iosynth;
unsigned int val;
@@ -3012,8 +3012,8 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
return 0;
}
-static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
- int dev, struct cmipci **rcmipci)
+static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
+ int dev, struct cmipci **rcmipci)
{
struct cmipci *cm;
int err;
@@ -3265,8 +3265,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
MODULE_DEVICE_TABLE(pci, snd_cmipci_ids);
-static int __devinit snd_cmipci_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_cmipci_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -3314,7 +3314,7 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
}
-static void __devexit snd_cmipci_remove(struct pci_dev *pci)
+static void snd_cmipci_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -3415,7 +3415,7 @@ static struct pci_driver cmipci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
- .remove = __devexit_p(snd_cmipci_remove),
+ .remove = snd_cmipci_remove,
.driver = {
.pm = SND_CMIPCI_PM_OPS,
},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 8e86ec0031fc..6a8695069941 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -969,8 +969,8 @@ static struct snd_pcm_ops snd_cs4281_capture_ops = {
.pointer = snd_cs4281_pointer,
};
-static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device,
- struct snd_pcm ** rpcm)
+static int snd_cs4281_pcm(struct cs4281 *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1093,7 +1093,7 @@ static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97)
chip->ac97 = NULL;
}
-static int __devinit snd_cs4281_mixer(struct cs4281 * chip)
+static int snd_cs4281_mixer(struct cs4281 *chip)
{
struct snd_card *card = chip->card;
struct snd_ac97_template ac97;
@@ -1171,7 +1171,7 @@ static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
.read = snd_cs4281_BA1_read,
};
-static void __devinit snd_cs4281_proc_init(struct cs4281 * chip)
+static void snd_cs4281_proc_init(struct cs4281 *chip)
{
struct snd_info_entry *entry;
@@ -1259,7 +1259,7 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-static int __devinit snd_cs4281_create_gameport(struct cs4281 *chip)
+static int snd_cs4281_create_gameport(struct cs4281 *chip)
{
struct gameport *gp;
@@ -1335,10 +1335,10 @@ static int snd_cs4281_dev_free(struct snd_device *device)
static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
-static int __devinit snd_cs4281_create(struct snd_card *card,
- struct pci_dev *pci,
- struct cs4281 ** rchip,
- int dual_codec)
+static int snd_cs4281_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct cs4281 **rchip,
+ int dual_codec)
{
struct cs4281 *chip;
unsigned int tmp;
@@ -1779,8 +1779,8 @@ static struct snd_rawmidi_ops snd_cs4281_midi_input =
.trigger = snd_cs4281_midi_input_trigger,
};
-static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device,
- struct snd_rawmidi **rrawmidi)
+static int snd_cs4281_midi(struct cs4281 *chip, int device,
+ struct snd_rawmidi **rrawmidi)
{
struct snd_rawmidi *rmidi;
int err;
@@ -1901,8 +1901,8 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
spin_unlock_irqrestore(&opl3->reg_lock, flags);
}
-static int __devinit snd_cs4281_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_cs4281_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1968,7 +1968,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_cs4281_remove(struct pci_dev *pci)
+static void snd_cs4281_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2095,7 +2095,7 @@ static struct pci_driver cs4281_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
- .remove = __devexit_p(snd_cs4281_remove),
+ .remove = snd_cs4281_remove,
.driver = {
.pm = CS4281_PM_OPS,
},
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 575bed0836ff..6b0d8b50a305 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = {
MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids);
-static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_card_cs46xx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -155,7 +155,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
+static void snd_card_cs46xx_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -165,7 +165,7 @@ static struct pci_driver cs46xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
- .remove = __devexit_p(snd_card_cs46xx_remove),
+ .remove = snd_card_cs46xx_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_cs46xx_pm,
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index a2bb8c91ebe6..1b66efd9b728 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1590,7 +1590,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
#define MAX_PLAYBACK_CHANNELS 1
#endif
-int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1621,7 +1621,8 @@ int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1650,7 +1651,8 @@ int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct sn
return 0;
}
-int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1679,7 +1681,8 @@ int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, str
return 0;
}
-int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -2092,7 +2095,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
-static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cs46xx_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DAC Volume",
@@ -2278,7 +2281,7 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
}
#endif
-static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
+static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
{
int idx, err;
struct snd_ac97_template ac97;
@@ -2311,7 +2314,7 @@ static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
return -ENXIO;
}
-int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
+int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id;
@@ -2531,7 +2534,7 @@ static struct snd_rawmidi_ops snd_cs46xx_midi_input =
.trigger = snd_cs46xx_midi_input_trigger,
};
-int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
+int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
{
struct snd_rawmidi *rmidi;
int err;
@@ -2613,7 +2616,7 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
+int snd_cs46xx_gameport(struct snd_cs46xx *chip)
{
struct gameport *gp;
@@ -2649,7 +2652,7 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
}
}
#else
-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
+int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
#endif /* CONFIG_GAMEPORT */
@@ -2674,7 +2677,7 @@ static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
.read = snd_cs46xx_io_read,
};
-static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
+static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
{
struct snd_info_entry *entry;
int idx;
@@ -3061,7 +3064,7 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */
}
-int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
+int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
{
unsigned int tmp;
/*
@@ -3477,7 +3480,7 @@ struct cs_card_type
void (*mixer_init)(struct snd_cs46xx *);
};
-static struct cs_card_type __devinitdata cards[] = {
+static struct cs_card_type cards[] = {
{
.vendor = 0x1489,
.id = 0x7001,
@@ -3717,10 +3720,10 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
/*
*/
-int __devinit snd_cs46xx_create(struct snd_card *card,
- struct pci_dev * pci,
+int snd_cs46xx_create(struct snd_card *card,
+ struct pci_dev *pci,
int external_amp, int thinkpad,
- struct snd_cs46xx ** rchip)
+ struct snd_cs46xx **rchip)
{
struct snd_cs46xx *chip;
int err, idx;
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index d1cca2831575..dace827b45d1 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -88,13 +88,13 @@ static int snd_cs5530_dev_free(struct snd_device *device)
return snd_cs5530_free(chip);
}
-static void __devexit snd_cs5530_remove(struct pci_dev *pci)
+static void snd_cs5530_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
}
-static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
+static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
{
outb(reg, io + 4);
udelay(20);
@@ -103,9 +103,9 @@ static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
return reg;
}
-static int __devinit snd_cs5530_create(struct snd_card *card,
- struct pci_dev *pci,
- struct snd_cs5530 **rchip)
+static int snd_cs5530_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct snd_cs5530 **rchip)
{
struct snd_cs5530 *chip;
unsigned long sb_base;
@@ -250,8 +250,8 @@ static int __devinit snd_cs5530_create(struct snd_card *card,
return 0;
}
-static int __devinit snd_cs5530_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_cs5530_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -294,7 +294,7 @@ static struct pci_driver cs5530_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5530_ids,
.probe = snd_cs5530_probe,
- .remove = __devexit_p(snd_cs5530_remove),
+ .remove = snd_cs5530_remove,
};
module_pci_driver(cs5530_driver);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 4915efa551fc..7e4b13e2d12a 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -43,7 +43,7 @@ static char *ac97_quirk;
module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
#if 0 /* Not yet confirmed if all 5536 boards are HP only */
{
.subvendor = PCI_VENDOR_ID_AMD,
@@ -144,7 +144,7 @@ static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97,
return snd_cs5535audio_codec_read(cs5535au, reg);
}
-static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
+static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
{
struct snd_card *card = cs5535au->card;
struct snd_ac97_bus *pbus;
@@ -270,9 +270,9 @@ static int snd_cs5535audio_dev_free(struct snd_device *device)
return snd_cs5535audio_free(cs5535au);
}
-static int __devinit snd_cs5535audio_create(struct snd_card *card,
- struct pci_dev *pci,
- struct cs5535audio **rcs5535au)
+static int snd_cs5535audio_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct cs5535audio **rcs5535au)
{
struct cs5535audio *cs5535au;
@@ -338,8 +338,8 @@ pcifail:
return err;
}
-static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_cs5535audio_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -387,7 +387,7 @@ probefail_out:
return err;
}
-static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
+static void snd_cs5535audio_remove(struct pci_dev *pci)
{
olpc_quirks_cleanup();
snd_card_free(pci_get_drvdata(pci));
@@ -398,7 +398,7 @@ static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe,
- .remove = __devexit_p(snd_cs5535audio_remove),
+ .remove = snd_cs5535audio_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_cs5535audio_pm,
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
index bb3cc641130c..0579daa62215 100644
--- a/sound/pci/cs5535audio/cs5535audio.h
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -97,10 +97,10 @@ struct cs5535audio {
extern const struct dev_pm_ops snd_cs5535audio_pm;
#ifdef CONFIG_OLPC
-void __devinit olpc_prequirks(struct snd_card *card,
- struct snd_ac97_template *ac97);
-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
-void __devexit olpc_quirks_cleanup(void);
+void olpc_prequirks(struct snd_card *card,
+ struct snd_ac97_template *ac97);
+int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
+void olpc_quirks_cleanup(void);
void olpc_analog_input(struct snd_ac97 *ac97, int on);
void olpc_mic_bias(struct snd_ac97 *ac97, int on);
@@ -133,7 +133,7 @@ static inline void olpc_capture_open(struct snd_ac97 *ac97) { }
static inline void olpc_capture_close(struct snd_ac97 *ac97) { }
#endif
-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
+int snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
#endif /* __SOUND_CS5535AUDIO_H */
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index 50da49be9ae5..da1cb9c4c76c 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -114,7 +114,7 @@ static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
return 1;
}
-static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
+static struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DC Mode Enable",
@@ -133,8 +133,8 @@ static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
},
};
-void __devinit olpc_prequirks(struct snd_card *card,
- struct snd_ac97_template *ac97)
+void olpc_prequirks(struct snd_card *card,
+ struct snd_ac97_template *ac97)
{
if (!machine_is_olpc())
return;
@@ -144,7 +144,7 @@ void __devinit olpc_prequirks(struct snd_card *card,
ac97->scaps |= AC97_SCAP_INV_EAPD;
}
-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
{
struct snd_ctl_elem_id elem;
int i, err;
@@ -185,7 +185,7 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
return 0;
}
-void __devexit olpc_quirks_cleanup(void)
+void olpc_quirks_cleanup(void)
{
gpio_free(OLPC_GPIO_MIC_AC);
}
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index dbf94b189e75..9ab01a7047cf 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -422,7 +422,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
.read_dma_pntr = cs5535audio_capture_read_dma_pntr,
};
-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
+int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
{
struct snd_pcm *pcm;
int err;
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index a2f997a9977a..b5fa583a239a 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -38,7 +38,7 @@
| (0x10 << 16) \
| ((IEC958_AES3_CON_FS_48000) << 24))
-static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
+static struct snd_pci_quirk subsys_20k1_list[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
@@ -48,7 +48,7 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
{ } /* terminator */
};
-static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
+static struct snd_pci_quirk subsys_20k2_list[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
"SB0760", CTSB0760),
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,
@@ -1249,7 +1249,7 @@ static int atc_dev_free(struct snd_device *dev)
return ct_atc_destroy(atc);
}
-static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
+static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)
{
const struct snd_pci_quirk *p;
const struct snd_pci_quirk *list;
@@ -1296,7 +1296,7 @@ static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
return 0;
}
-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
+int ct_atc_create_alsa_devs(struct ct_atc *atc)
{
enum CTALSADEVS i;
int err;
@@ -1319,7 +1319,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
return 0;
}
-static int __devinit atc_create_hw_devs(struct ct_atc *atc)
+static int atc_create_hw_devs(struct ct_atc *atc)
{
struct hw *hw;
struct card_conf info = {0};
@@ -1614,7 +1614,7 @@ static int atc_resume(struct ct_atc *atc)
}
#endif
-static struct ct_atc atc_preset __devinitdata = {
+static struct ct_atc atc_preset = {
.map_audio_buffer = ct_map_audio_buffer,
.unmap_audio_buffer = ct_unmap_audio_buffer,
.pcm_playback_prepare = atc_pcm_playback_prepare,
@@ -1665,10 +1665,10 @@ static struct ct_atc atc_preset __devinitdata = {
* Returns 0 if succeeds, or negative error code if fails.
*/
-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
- unsigned int rsr, unsigned int msr,
- int chip_type, unsigned int ssid,
- struct ct_atc **ratc)
+int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+ unsigned int rsr, unsigned int msr,
+ int chip_type, unsigned int ssid,
+ struct ct_atc **ratc)
{
struct ct_atc *atc;
static struct snd_device_ops ops = {
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h
index 69b51f9d345e..5f11ca22fcde 100644
--- a/sound/pci/ctxfi/ctatc.h
+++ b/sound/pci/ctxfi/ctatc.h
@@ -152,9 +152,9 @@ struct ct_atc {
};
-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
- unsigned int rsr, unsigned int msr, int chip_type,
- unsigned int subsysid, struct ct_atc **ratc);
-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc);
+int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+ unsigned int rsr, unsigned int msr, int chip_type,
+ unsigned int subsysid, struct ct_atc **ratc);
+int ct_atc_create_alsa_devs(struct ct_atc *atc);
#endif /* CTATC_H */
diff --git a/sound/pci/ctxfi/cthardware.c b/sound/pci/ctxfi/cthardware.c
index 8e64f4862e85..110b8ace6d8a 100644
--- a/sound/pci/ctxfi/cthardware.c
+++ b/sound/pci/ctxfi/cthardware.c
@@ -20,8 +20,8 @@
#include "cthw20k2.h"
#include <linux/bug.h>
-int __devinit create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
- enum CTCARDS model, struct hw **rhw)
+int create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
+ enum CTCARDS model, struct hw **rhw)
{
int err;
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index 4507f7088b24..6ac40beb49da 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -2171,7 +2171,7 @@ static void hw_write_pci(struct hw *hw, u32 reg, u32 data)
&container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
}
-static struct hw ct20k1_preset __devinitdata = {
+static struct hw ct20k1_preset = {
.irq = -1,
.card_init = hw_card_init,
@@ -2275,7 +2275,7 @@ static struct hw ct20k1_preset __devinitdata = {
.get_wc = get_wc,
};
-int __devinit create_20k1_hw_obj(struct hw **rhw)
+int create_20k1_hw_obj(struct hw **rhw)
{
struct hw20k1 *hw20k1;
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index b9c9349058bc..b1438861d38a 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -2237,7 +2237,7 @@ static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
writel(data, (void *)(hw->mem_base + reg));
}
-static struct hw ct20k2_preset __devinitdata = {
+static struct hw ct20k2_preset = {
.irq = -1,
.card_init = hw_card_init,
@@ -2345,7 +2345,7 @@ static struct hw ct20k2_preset __devinitdata = {
.get_wc = get_wc,
};
-int __devinit create_20k2_hw_obj(struct hw **rhw)
+int create_20k2_hw_obj(struct hw **rhw)
{
struct hw20k2 *hw20k2;
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
index 07c07d752fd8..d01ffcb2b2f5 100644
--- a/sound/pci/ctxfi/xfi.c
+++ b/sound/pci/ctxfi/xfi.c
@@ -56,7 +56,7 @@ static DEFINE_PCI_DEVICE_TABLE(ct_pci_dev_ids) = {
};
MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids);
-static int __devinit
+static int
ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -119,7 +119,7 @@ error:
return err;
}
-static void __devexit ct_card_remove(struct pci_dev *pci)
+static void ct_card_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -152,7 +152,7 @@ static struct pci_driver ct_driver = {
.name = KBUILD_MODNAME,
.id_table = ct_pci_dev_ids,
.probe = ct_card_probe,
- .remove = __devexit_p(ct_card_remove),
+ .remove = ct_card_remove,
.driver = {
.pm = CT_CARD_PM_OPS,
},
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index abb0b86c41c9..760cbff53210 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -907,7 +907,7 @@ static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
/*<--snd_echo_probe() */
-static int __devinit snd_echo_new_pcm(struct echoaudio *chip)
+static int snd_echo_new_pcm(struct echoaudio *chip)
{
struct snd_pcm *pcm;
int err;
@@ -1050,7 +1050,7 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
/* On the Mia this one controls the line-out volume */
-static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_line_output_gain = {
.name = "Line Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1061,7 +1061,7 @@ static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
.tlv = {.p = db_scale_output_gain},
};
#else
-static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_pcm_output_gain = {
.name = "PCM Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1131,7 +1131,7 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
-static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_line_input_gain = {
.name = "Line Capture Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1195,7 +1195,7 @@ static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = {
+static struct snd_kcontrol_new snd_echo_output_nominal_level = {
.name = "Line Playback Switch (-10dBV)",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_echo_output_nominal_info,
@@ -1261,7 +1261,7 @@ static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = {
+static struct snd_kcontrol_new snd_echo_intput_nominal_level = {
.name = "Line Capture Switch (-10dBV)",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_echo_input_nominal_info,
@@ -1327,7 +1327,7 @@ static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
+static struct snd_kcontrol_new snd_echo_monitor_mixer = {
.name = "Monitor Mixer Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1395,7 +1395,7 @@ static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vmixer = {
.name = "VMixer Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1490,7 +1490,7 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_digital_mode_switch = {
.name = "Digital mode Switch",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = snd_echo_digital_mode_info,
@@ -1547,7 +1547,7 @@ static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_spdif_mode_switch = {
.name = "S/PDIF mode Switch",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = snd_echo_spdif_mode_info,
@@ -1626,7 +1626,7 @@ static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_clock_source_switch = {
.name = "Sample Clock Source",
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.info = snd_echo_clock_source_info,
@@ -1669,7 +1669,7 @@ static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_phantom_power_switch = {
.name = "Phantom power Switch",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = snd_echo_phantom_power_info,
@@ -1712,7 +1712,7 @@ static int snd_echo_automute_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_automute_switch = {
.name = "Digital Capture Switch (automute)",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = snd_echo_automute_info,
@@ -1739,7 +1739,7 @@ static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vumeters_switch = {
.name = "VU-meters Switch",
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
@@ -1780,7 +1780,7 @@ static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vumeters = {
.name = "VU-meters",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ |
@@ -1836,7 +1836,7 @@ static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = {
+static struct snd_kcontrol_new snd_echo_channels_info = {
.name = "Channels info",
.iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1940,9 +1940,9 @@ static int snd_echo_dev_free(struct snd_device *device)
/* <--snd_echo_probe() */
-static __devinit int snd_echo_create(struct snd_card *card,
- struct pci_dev *pci,
- struct echoaudio **rchip)
+static int snd_echo_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct echoaudio **rchip)
{
struct echoaudio *chip;
int err;
@@ -2040,8 +2040,8 @@ static __devinit int snd_echo_create(struct snd_card *card,
/* constructor */
-static int __devinit snd_echo_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_echo_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -2316,7 +2316,7 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
#endif /* CONFIG_PM_SLEEP */
-static void __devexit snd_echo_remove(struct pci_dev *pci)
+static void snd_echo_remove(struct pci_dev *pci)
{
struct echoaudio *chip;
@@ -2337,7 +2337,7 @@ static struct pci_driver echo_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_echo_ids,
.probe = snd_echo_probe,
- .remove = __devexit_p(snd_echo_remove),
+ .remove = snd_echo_remove,
.driver = {
.pm = SND_ECHO_PM_OPS,
},
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
index e158369f5faa..b86b88da81cd 100644
--- a/sound/pci/echoaudio/echoaudio.h
+++ b/sound/pci/echoaudio/echoaudio.h
@@ -475,8 +475,8 @@ static int enable_midi_input(struct echoaudio *chip, char enable);
static void snd_echo_midi_output_trigger(
struct snd_rawmidi_substream *substream, int up);
static int midi_service_irq(struct echoaudio *chip);
-static int __devinit snd_echo_midi_create(struct snd_card *card,
- struct echoaudio *chip);
+static int snd_echo_midi_create(struct snd_card *card,
+ struct echoaudio *chip);
#endif
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index a953d142cb4b..abfd51c2530e 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -307,8 +307,8 @@ static struct snd_rawmidi_ops snd_echo_midi_output = {
/* <--snd_echo_probe() */
-static int __devinit snd_echo_midi_create(struct snd_card *card,
- struct echoaudio *chip)
+static int snd_echo_midi_create(struct snd_card *card,
+ struct echoaudio *chip)
{
int err;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index b7c1875ba90e..8c5010f7889c 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -99,8 +99,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = {
MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids);
-static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_card_emu10k1_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -199,7 +199,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
+static void snd_card_emu10k1_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -215,6 +215,8 @@ static int snd_emu10k1_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ emu->suspend = 1;
+
snd_pcm_suspend_all(emu->pcm);
snd_pcm_suspend_all(emu->pcm_mic);
snd_pcm_suspend_all(emu->pcm_efx);
@@ -260,6 +262,8 @@ static int snd_emu10k1_resume(struct device *dev)
if (emu->card_capabilities->ca0151_chip)
snd_p16v_resume(emu);
+ emu->suspend = 0;
+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
@@ -274,7 +278,7 @@ static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
- .remove = __devexit_p(snd_card_emu10k1_remove),
+ .remove = snd_card_emu10k1_remove,
.driver = {
.pm = SND_EMU10K1_PM_OPS,
},
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index c21adb6ef1d5..a7c296a36a17 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -657,22 +657,17 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
return 0;
}
-static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu)
{
- int err;
int n, i;
int reg;
int value;
unsigned int write_post;
unsigned long flags;
- const struct firmware *fw_entry;
+ const struct firmware *fw_entry = emu->firmware;
- err = request_firmware(&fw_entry, filename, &emu->pci->dev);
- if (err != 0) {
- snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err);
- return err;
- }
- snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size);
+ if (!fw_entry)
+ return -EIO;
/* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* GPIO7 -> FPGA PGMN
@@ -705,7 +700,6 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena
write_post = inl(emu->port + A_IOCFG);
spin_unlock_irqrestore(&emu->emu_lock, flags);
- release_firmware(fw_entry);
return 0;
}
@@ -720,6 +714,10 @@ static int emu1010_firmware_thread(void *data)
msleep_interruptible(1000);
if (kthread_should_stop())
break;
+#ifdef CONFIG_PM_SLEEP
+ if (emu->suspend)
+ continue;
+#endif
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
@@ -727,22 +725,9 @@ static int emu1010_firmware_thread(void *data)
/* Return to Audio Dock programming mode */
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
- if (emu->card_capabilities->emu_model ==
- EMU_MODEL_EMU1010) {
- err = snd_emu1010_load_firmware(emu, DOCK_FILENAME);
- if (err != 0)
- continue;
- } else if (emu->card_capabilities->emu_model ==
- EMU_MODEL_EMU1010B) {
- err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
- if (err != 0)
- continue;
- } else if (emu->card_capabilities->emu_model ==
- EMU_MODEL_EMU1616) {
- err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
- if (err != 0)
- continue;
- }
+ err = snd_emu1010_load_firmware(emu);
+ if (err != 0)
+ continue;
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
@@ -807,7 +792,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
unsigned int i;
u32 tmp, tmp2, reg;
int err;
- const char *filename = NULL;
snd_printk(KERN_INFO "emu1010: Special config.\n");
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
@@ -849,31 +833,33 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
return -ENODEV;
}
snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg);
- switch (emu->card_capabilities->emu_model) {
- case EMU_MODEL_EMU1010:
- filename = HANA_FILENAME;
- break;
- case EMU_MODEL_EMU1010B:
- filename = EMU1010B_FILENAME;
- break;
- case EMU_MODEL_EMU1616:
- filename = EMU1010_NOTEBOOK_FILENAME;
- break;
- case EMU_MODEL_EMU0404:
- filename = EMU0404_FILENAME;
- break;
- default:
- filename = NULL;
- return -ENODEV;
- break;
- }
- snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename);
- err = snd_emu1010_load_firmware(emu, filename);
- if (err != 0) {
- snd_printk(
- KERN_INFO "emu1010: Loading Firmware file %s failed\n",
- filename);
- return err;
+
+ if (!emu->firmware) {
+ const char *filename;
+ switch (emu->card_capabilities->emu_model) {
+ case EMU_MODEL_EMU1010:
+ filename = HANA_FILENAME;
+ break;
+ case EMU_MODEL_EMU1010B:
+ filename = EMU1010B_FILENAME;
+ break;
+ case EMU_MODEL_EMU1616:
+ filename = EMU1010_NOTEBOOK_FILENAME;
+ break;
+ case EMU_MODEL_EMU0404:
+ filename = EMU0404_FILENAME;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ err = request_firmware(&emu->firmware, filename, &emu->pci->dev);
+ if (err != 0) {
+ snd_printk(KERN_ERR "emu1010: firmware: %s not found. Err = %d\n", filename, err);
+ return err;
+ }
+ snd_printk(KERN_INFO "emu1010: firmware file = %s, size = 0x%zx\n",
+ filename, emu->firmware->size);
}
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
@@ -1259,6 +1245,8 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
}
if (emu->emu1010.firmware_thread)
kthread_stop(emu->emu1010.firmware_thread);
+ if (emu->firmware)
+ release_firmware(emu->firmware);
if (emu->irq >= 0)
free_irq(emu->irq, emu);
/* remove reserved page */
@@ -1738,7 +1726,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
{ } /* terminator */
};
-int __devinit snd_emu10k1_create(struct snd_card *card,
+int snd_emu10k1_create(struct snd_card *card,
struct pci_dev *pci,
unsigned short extin_mask,
unsigned short extout_mask,
@@ -2025,7 +2013,7 @@ static unsigned char saved_regs_audigy[] = {
0xff /* end */
};
-static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
+static int alloc_pm_buffer(struct snd_emu10k1 *emu)
{
int size;
diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c
index e10f027bde03..662a45876a8b 100644
--- a/sound/pci/emu10k1/emu10k1_patch.c
+++ b/sound/pci/emu10k1/emu10k1_patch.c
@@ -123,7 +123,7 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
offset += size;
data += size;
-#if 0 /* not suppported yet */
+#if 0 /* not supported yet */
/* handle reverse (or bidirectional) loop */
if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
/* copy loop in reverse */
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 556fd6f456e3..cdff11d48ebd 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -842,7 +842,7 @@ static const struct snd_pcm_chmap_elem clfe_map[] = {
{ }
};
-static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
+static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
const struct snd_pcm_chmap_elem *map = NULL;
@@ -902,9 +902,9 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s
return 0;
}
-static int __devinit snd_emu10k1x_create(struct snd_card *card,
- struct pci_dev *pci,
- struct emu10k1x **rchip)
+static int snd_emu10k1x_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct emu10k1x **rchip)
{
struct emu10k1x *chip;
int err;
@@ -1066,7 +1066,7 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
}
}
-static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
+static int snd_emu10k1x_proc_init(struct emu10k1x *emu)
{
struct snd_info_entry *entry;
@@ -1115,7 +1115,7 @@ static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1x_shared_spdif =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog/Digital Output Jack",
@@ -1194,7 +1194,7 @@ static struct snd_kcontrol_new snd_emu10k1x_spdif_control =
.put = snd_emu10k1x_spdif_put
};
-static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu)
+static int snd_emu10k1x_mixer(struct emu10k1x *emu)
{
int err;
struct snd_kcontrol *kctl;
@@ -1507,8 +1507,9 @@ static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi)
midi->rmidi = NULL;
}
-static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
- struct emu10k1x_midi *midi, int device, char *name)
+static int emu10k1x_midi_init(struct emu10k1x *emu,
+ struct emu10k1x_midi *midi, int device,
+ char *name)
{
struct snd_rawmidi *rmidi;
int err;
@@ -1531,7 +1532,7 @@ static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
return 0;
}
-static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
+static int snd_emu10k1x_midi(struct emu10k1x *emu)
{
struct emu10k1x_midi *midi = &emu->midi;
int err;
@@ -1548,8 +1549,8 @@ static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
return 0;
}
-static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_emu10k1x_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1619,7 +1620,7 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
+static void snd_emu10k1x_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1637,7 +1638,7 @@ static struct pci_driver emu10k1x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
- .remove = __devexit_p(snd_emu10k1x_remove),
+ .remove = snd_emu10k1x_remove,
};
module_pci_driver(emu10k1x_driver);
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 52419959178c..0275209ca82e 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1073,7 +1073,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
#define SND_EMU10K1_PLAYBACK_CHANNELS 8
#define SND_EMU10K1_CAPTURE_CHANNELS 4
-static void __devinit
+static void
snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval)
{
@@ -1094,7 +1094,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
}
}
-static void __devinit
+static void
snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval)
{
@@ -1116,7 +1116,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
}
}
-static void __devinit
+static void
snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval)
{
@@ -1129,7 +1129,7 @@ snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
}
-static void __devinit
+static void
snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval)
{
@@ -1168,7 +1168,7 @@ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
* initial DSP configuration for Audigy
*/
-static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
+static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
{
int err, i, z, gpr, nctl;
int bit_shifter16;
@@ -1757,14 +1757,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* when volume = max, then copy only to avoid volume modification */
/* with iMAC0 (negative values) */
-static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
}
-static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1772,7 +1772,7 @@ static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *pt
OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
OP(icode, ptr, iMAC0, dst, dst, src, vol);
}
-static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1803,7 +1803,7 @@ static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *pt
_SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
-static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
{
int err, i, z, gpr, tmp, playback, capture;
u32 ptr;
@@ -2373,7 +2373,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
return err;
}
-int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+int snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
{
spin_lock_init(&emu->fx8010.irq_lock);
INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
@@ -2626,7 +2626,8 @@ static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
return 0;
}
-int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep)
+int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device,
+ struct snd_hwdep **rhwdep)
{
struct snd_hwdep *hw;
int err;
@@ -2647,7 +2648,7 @@ int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct
}
#ifdef CONFIG_PM_SLEEP
-int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
+int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
{
int len;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 9d890a5aec5a..f6c3da0d377d 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -510,7 +510,7 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
.private_value = chid \
}
-static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -539,7 +539,7 @@ static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
/* 1616(m) cardbus */
-static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -571,7 +571,7 @@ static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
.private_value = chid \
}
-static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
@@ -639,7 +639,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
.private_value = chid \
}
-static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
@@ -687,7 +687,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
.private_value = chid \
}
-static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
@@ -989,7 +989,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
}
-static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
I2C_VOLUME("Mic Capture Volume", 0),
I2C_VOLUME("Line Capture Volume", 0)
};
@@ -1621,7 +1621,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SB Live Analog/Digital Output Jack",
@@ -1630,7 +1630,7 @@ static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
.put = snd_emu10k1_shared_spdif_put
};
-static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_audigy_shared_spdif =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Audigy Analog/Digital Output Jack",
@@ -1668,7 +1668,7 @@ static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
}
-static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata =
+static struct snd_kcontrol_new snd_audigy_capture_boost =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Capture Boost",
@@ -1716,8 +1716,8 @@ static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
return -ENOENT;
}
-int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
- int pcm_device, int multi_device)
+int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
+ int pcm_device, int multi_device)
{
int err, pcm;
struct snd_kcontrol *kctl;
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index bab564824efe..1ec91246dfee 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -326,7 +326,7 @@ static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
midi->rmidi = NULL;
}
-static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
+static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
{
struct snd_rawmidi *rmidi;
int err;
@@ -349,7 +349,7 @@ static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10
return 0;
}
-int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
+int snd_emu10k1_midi(struct snd_emu10k1 *emu)
{
struct snd_emu10k1_midi *midi = &emu->midi;
int err;
@@ -366,7 +366,7 @@ int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
return 0;
}
-int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
+int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
{
struct snd_emu10k1_midi *midi;
int err;
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 0e6664fa6cd9..748a286277eb 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1391,7 +1391,7 @@ static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -1426,7 +1426,8 @@ int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_p
return 0;
}
-int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -1469,7 +1470,8 @@ static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
.pointer = snd_emu10k1_capture_pointer,
};
-int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1810,7 +1812,8 @@ static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
.ack = snd_emu10k1_fx8010_playback_transfer,
};
-int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_kcontrol *kctl;
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index bc38dd4d071f..2ca9f2e93139 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -577,7 +577,7 @@ static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
.read = snd_emu10k1_fx8010_read,
};
-int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
+int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
{
struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 88cec6b7dd41..7e2025cd6d9c 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -637,7 +637,7 @@ int snd_p16v_free(struct snd_emu10k1 *chip)
return 0;
}
-int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -854,7 +854,7 @@ static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
.private_value = ((xreg) | ((xhl) << 8)) \
}
-static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
+static struct snd_kcontrol_new p16v_mixer_controls[] = {
P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
@@ -880,7 +880,7 @@ static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
};
-int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
+int snd_p16v_mixer(struct snd_emu10k1 *emu)
{
int i, err;
struct snd_card *card = emu->card;
@@ -897,7 +897,7 @@ int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
#define NUM_CHS 1 /* up to 4, but only first channel is used */
-int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
+int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
{
emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
if (! emu->p16v_saved)
diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
index 72321e946ccc..b69a7f8a216c 100644
--- a/sound/pci/emu10k1/timer.c
+++ b/sound/pci/emu10k1/timer.c
@@ -75,7 +75,7 @@ static struct snd_timer_hardware snd_emu10k1_timer_hw = {
.precise_resolution = snd_emu10k1_timer_precise_resolution,
};
-int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
+int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
{
struct snd_timer *timer = NULL;
struct snd_timer_id tid;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 5674cc316530..db2dc835171d 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1268,8 +1268,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
{ }
};
-static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
- struct snd_pcm ** rpcm)
+static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1310,8 +1310,8 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
return 0;
}
-static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device,
- struct snd_pcm ** rpcm)
+static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1484,7 +1484,7 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
/* spdif controls */
-static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1546,7 +1546,7 @@ static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ens1373_rear __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 2ch->4ch Copy Switch",
@@ -1591,7 +1591,7 @@ static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new snd_ens1373_line __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_line =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line In->Rear Out Switch",
@@ -1625,7 +1625,7 @@ static int es1371_quirk_lookup(struct ensoniq *ensoniq,
return 0;
}
-static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
+static struct es1371_quirk es1371_spdif_present[] = {
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1634,14 +1634,14 @@ static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
};
-static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
+static struct snd_pci_quirk ens1373_line_quirk[] = {
SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
{ } /* end */
};
-static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
- int has_spdif, int has_line)
+static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+ int has_spdif, int has_line)
{
struct snd_card *card = ensoniq->card;
struct snd_ac97_bus *pbus;
@@ -1749,7 +1749,7 @@ static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol,
* ENS1370 mixer
*/
-static struct snd_kcontrol_new snd_es1370_controls[2] __devinitdata = {
+static struct snd_kcontrol_new snd_es1370_controls[2] = {
ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),
ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
};
@@ -1762,7 +1762,7 @@ static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531)
ensoniq->u.es1370.ak4531 = NULL;
}
-static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
+static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq)
{
struct snd_card *card = ensoniq->card;
struct snd_ak4531 ak4531;
@@ -1796,7 +1796,7 @@ static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
#ifdef SUPPORT_JOYSTICK
#ifdef CHIP1371
-static int __devinit snd_ensoniq_get_joystick_port(int dev)
+static int snd_ensoniq_get_joystick_port(int dev)
{
switch (joystick_port[dev]) {
case 0: /* disabled */
@@ -1819,7 +1819,7 @@ static inline int snd_ensoniq_get_joystick_port(int dev)
}
#endif
-static int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
+static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
{
struct gameport *gp;
int io_port;
@@ -1913,7 +1913,7 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry,
#endif
}
-static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq)
+static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
{
struct snd_info_entry *entry;
@@ -1960,7 +1960,7 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
}
#ifdef CHIP1371
-static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
+static struct snd_pci_quirk es1371_amplifier_hack[] = {
SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */
SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */
SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */
@@ -2106,9 +2106,9 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
#define SND_ENSONIQ_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-static int __devinit snd_ensoniq_create(struct snd_card *card,
- struct pci_dev *pci,
- struct ensoniq ** rensoniq)
+static int snd_ensoniq_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct ensoniq **rensoniq)
{
struct ensoniq *ensoniq;
int err;
@@ -2361,8 +2361,8 @@ static struct snd_rawmidi_ops snd_ensoniq_midi_input =
.trigger = snd_ensoniq_midi_input_trigger,
};
-static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device,
- struct snd_rawmidi **rrawmidi)
+static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device,
+ struct snd_rawmidi **rrawmidi)
{
struct snd_rawmidi *rmidi;
int err;
@@ -2422,8 +2422,8 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit snd_audiopci_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_audiopci_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -2494,7 +2494,7 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_audiopci_remove(struct pci_dev *pci)
+static void snd_audiopci_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2504,7 +2504,7 @@ static struct pci_driver ens137x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
- .remove = __devexit_p(snd_audiopci_remove),
+ .remove = snd_audiopci_remove,
.driver = {
.pm = SND_ENSONIQ_PM_OPS,
},
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 394c5d413530..8423403954ab 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1027,7 +1027,7 @@ static struct snd_pcm_ops snd_es1938_capture_ops = {
.copy = snd_es1938_capture_copy,
};
-static int __devinit snd_es1938_new_pcm(struct es1938 *chip, int device)
+static int snd_es1938_new_pcm(struct es1938 *chip, int device)
{
struct snd_pcm *pcm;
int err;
@@ -1539,7 +1539,7 @@ static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume);
#endif /* CONFIG_PM_SLEEP */
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_es1938_create_gameport(struct es1938 *chip)
+static int snd_es1938_create_gameport(struct es1938 *chip)
{
struct gameport *gp;
@@ -1594,9 +1594,9 @@ static int snd_es1938_dev_free(struct snd_device *device)
return snd_es1938_free(chip);
}
-static int __devinit snd_es1938_create(struct snd_card *card,
- struct pci_dev * pci,
- struct es1938 ** rchip)
+static int snd_es1938_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct es1938 **rchip)
{
struct es1938 *chip;
int err;
@@ -1754,7 +1754,7 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id)
#define ES1938_DMA_SIZE 64
-static int __devinit snd_es1938_mixer(struct es1938 *chip)
+static int snd_es1938_mixer(struct es1938 *chip)
{
struct snd_card *card;
unsigned int idx;
@@ -1792,8 +1792,8 @@ static int __devinit snd_es1938_mixer(struct es1938 *chip)
}
-static int __devinit snd_es1938_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_es1938_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1878,7 +1878,7 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_es1938_remove(struct pci_dev *pci)
+static void snd_es1938_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1888,7 +1888,7 @@ static struct pci_driver es1938_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
- .remove = __devexit_p(snd_es1938_remove),
+ .remove = snd_es1938_remove,
.driver = {
.pm = ES1938_PM_OPS,
},
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 7266020c16cb..a1f32b5ae0d1 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1429,7 +1429,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
}
}
-static int __devinit
+static int
snd_es1968_init_dmabuf(struct es1968 *chip)
{
int err;
@@ -1704,7 +1704,7 @@ static struct snd_pcm_ops snd_es1968_capture_ops = {
*/
#define CLOCK_MEASURE_BUFSIZE 16768 /* enough large for a single shot */
-static void __devinit es1968_measure_clock(struct es1968 *chip)
+static void es1968_measure_clock(struct es1968 *chip)
{
int i, apu;
unsigned int pa, offset, t;
@@ -1806,7 +1806,7 @@ static void snd_es1968_pcm_free(struct snd_pcm *pcm)
esm->pcm = NULL;
}
-static int __devinit
+static int
snd_es1968_pcm(struct es1968 *chip, int device)
{
struct snd_pcm *pcm;
@@ -2016,7 +2016,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
* Mixer stuff
*/
-static int __devinit
+static int
snd_es1968_mixer(struct es1968 *chip)
{
struct snd_ac97_bus *pbus;
@@ -2291,7 +2291,7 @@ static void snd_es1968_chip_init(struct es1968 *chip)
outb(0x88, iobase+0x1f);
/* it appears some maestros (dell 7500) only work if these are set,
- regardless of wether we use the assp or not. */
+ regardless of whether we use the assp or not. */
outb(0, iobase + ASSP_CONTROL_B);
outb(3, iobase + ASSP_CONTROL_A); /* M: Reserved bits... */
@@ -2465,7 +2465,7 @@ static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume);
#ifdef SUPPORT_JOYSTICK
#define JOYSTICK_ADDR 0x200
-static int __devinit snd_es1968_create_gameport(struct es1968 *chip, int dev)
+static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
{
struct gameport *gp;
struct resource *r;
@@ -2516,7 +2516,7 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
#endif
#ifdef CONFIG_SND_ES1968_INPUT
-static int __devinit snd_es1968_input_register(struct es1968 *chip)
+static int snd_es1968_input_register(struct es1968 *chip)
{
struct input_dev *input_dev;
int err;
@@ -2653,7 +2653,7 @@ struct ess_device_list {
unsigned short vendor; /* subsystem vendor id */
};
-static struct ess_device_list pm_whitelist[] __devinitdata = {
+static struct ess_device_list pm_whitelist[] = {
{ TYPE_MAESTRO2E, 0x0e11 }, /* Compaq Armada */
{ TYPE_MAESTRO2E, 0x1028 },
{ TYPE_MAESTRO2E, 0x103c },
@@ -2664,19 +2664,19 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
{ TYPE_MAESTRO2, 0x125d }, /* a PCI card, e.g. SF64-PCE2 */
};
-static struct ess_device_list mpu_blacklist[] __devinitdata = {
+static struct ess_device_list mpu_blacklist[] = {
{ TYPE_MAESTRO2, 0x125d },
};
-static int __devinit snd_es1968_create(struct snd_card *card,
- struct pci_dev *pci,
- int total_bufsize,
- int play_streams,
- int capt_streams,
- int chip_type,
- int do_pm,
- int radio_nr,
- struct es1968 **chip_ret)
+static int snd_es1968_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int total_bufsize,
+ int play_streams,
+ int capt_streams,
+ int chip_type,
+ int do_pm,
+ int radio_nr,
+ struct es1968 **chip_ret)
{
static struct snd_device_ops ops = {
.dev_free = snd_es1968_dev_free,
@@ -2795,8 +2795,8 @@ static int __devinit snd_es1968_create(struct snd_card *card,
/*
*/
-static int __devinit snd_es1968_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_es1968_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -2906,7 +2906,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_es1968_remove(struct pci_dev *pci)
+static void snd_es1968_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2916,7 +2916,7 @@ static struct pci_driver es1968_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
- .remove = __devexit_p(snd_es1968_remove),
+ .remove = snd_es1968_remove,
.driver = {
.pm = ES1968_PM_OPS,
},
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index c5806f89be1e..4f07fda5adf2 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -689,7 +689,7 @@ static struct snd_pcm_ops snd_fm801_capture_ops = {
.pointer = snd_fm801_capture_pointer,
};
-static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm ** rpcm)
+static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -984,7 +984,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
#define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
-static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_fm801_controls[] = {
FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1,
db_scale_dsp),
FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1),
@@ -1005,7 +1005,7 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
#define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi)
-static struct snd_kcontrol_new snd_fm801_controls_multi[] __devinitdata = {
+static struct snd_kcontrol_new snd_fm801_controls_multi[] = {
FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0),
FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0),
FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
@@ -1030,7 +1030,7 @@ static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
}
}
-static int __devinit snd_fm801_mixer(struct fm801 *chip)
+static int snd_fm801_mixer(struct fm801 *chip)
{
struct snd_ac97_template ac97;
unsigned int i;
@@ -1191,11 +1191,11 @@ static int snd_fm801_dev_free(struct snd_device *device)
return snd_fm801_free(chip);
}
-static int __devinit snd_fm801_create(struct snd_card *card,
- struct pci_dev * pci,
- int tea575x_tuner,
- int radio_nr,
- struct fm801 ** rchip)
+static int snd_fm801_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int tea575x_tuner,
+ int radio_nr,
+ struct fm801 **rchip)
{
struct fm801 *chip;
int err;
@@ -1296,8 +1296,8 @@ static int __devinit snd_fm801_create(struct snd_card *card,
return 0;
}
-static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_card_fm801_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1367,7 +1367,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
+static void snd_card_fm801_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1439,7 +1439,7 @@ static struct pci_driver fm801_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
- .remove = __devexit_p(snd_card_fm801_remove),
+ .remove = snd_card_fm801_remove,
.driver = {
.pm = SND_FM801_PM_OPS,
},
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 7105c3de1bca..6eeb8897624b 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -37,8 +37,8 @@ config SND_HDA_HWDEP
with codecs for debugging purposes.
config SND_HDA_RECONFIG
- bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
- depends on SND_HDA_HWDEP && EXPERIMENTAL
+ bool "Allow dynamic codec reconfiguration"
+ depends on SND_HDA_HWDEP
help
Say Y here to enable the HD-audio codec re-configuration feature.
This adds the sysfs interfaces to allow user to clear the whole
@@ -72,7 +72,6 @@ config SND_HDA_INPUT_JACK
config SND_HDA_PATCH_LOADER
bool "Support initialization patch loading for HD-audio"
- depends on EXPERIMENTAL
select FW_LOADER
select SND_HDA_HWDEP
select SND_HDA_RECONFIG
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index bd4149f1aaf4..24a251497a1f 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -8,6 +8,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
# for trace-points
CFLAGS_hda_codec.o := -I$(src)
+CFLAGS_hda_intel.o := -I$(src)
snd-hda-codec-realtek-objs := patch_realtek.o
snd-hda-codec-cmedia-objs := patch_cmedia.o
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 4ec6dc88b7f8..7da883a464e3 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/sort.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
@@ -30,29 +31,30 @@ static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
return 0;
}
+/* a pair of input pin and its sequence */
+struct auto_out_pin {
+ hda_nid_t pin;
+ short seq;
+};
+
+static int compare_seq(const void *ap, const void *bp)
+{
+ const struct auto_out_pin *a = ap;
+ const struct auto_out_pin *b = bp;
+ return (int)(a->seq - b->seq);
+}
/*
* Sort an associated group of pins according to their sequence numbers.
+ * then store it to a pin array.
*/
-static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
+static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,
int num_pins)
{
- int i, j;
- short seq;
- hda_nid_t nid;
-
- for (i = 0; i < num_pins; i++) {
- for (j = i + 1; j < num_pins; j++) {
- if (sequences[i] > sequences[j]) {
- seq = sequences[i];
- sequences[i] = sequences[j];
- sequences[j] = seq;
- nid = pins[i];
- pins[i] = pins[j];
- pins[j] = nid;
- }
- }
- }
+ int i;
+ sort(list, num_pins, sizeof(list[0]), compare_seq, NULL);
+ for (i = 0; i < num_pins; i++)
+ pins[i] = list[i].pin;
}
@@ -67,21 +69,11 @@ static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
}
}
-/* sort inputs in the order of AUTO_PIN_* type */
-static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
+static int compare_input_type(const void *ap, const void *bp)
{
- int i, j;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- for (j = i + 1; j < cfg->num_inputs; j++) {
- if (cfg->inputs[i].type > cfg->inputs[j].type) {
- struct auto_pin_cfg_item tmp;
- tmp = cfg->inputs[i];
- cfg->inputs[i] = cfg->inputs[j];
- cfg->inputs[j] = tmp;
- }
- }
- }
+ const struct auto_pin_cfg_item *a = ap;
+ const struct auto_pin_cfg_item *b = bp;
+ return (int)(a->type - b->type);
}
/* Reorder the surround channels
@@ -129,16 +121,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
{
hda_nid_t nid, end_nid;
short seq, assoc_line_out;
- short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
- short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
- short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
+ struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)];
+ struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)];
+ struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)];
int i;
memset(cfg, 0, sizeof(*cfg));
- memset(sequences_line_out, 0, sizeof(sequences_line_out));
- memset(sequences_speaker, 0, sizeof(sequences_speaker));
- memset(sequences_hp, 0, sizeof(sequences_hp));
+ memset(line_out, 0, sizeof(line_out));
+ memset(speaker_out, 0, sizeof(speaker_out));
+ memset(hp_out, 0, sizeof(hp_out));
assoc_line_out = 0;
end_nid = codec->start_nid + codec->num_nodes;
@@ -184,8 +176,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
continue;
if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
continue;
- cfg->line_out_pins[cfg->line_outs] = nid;
- sequences_line_out[cfg->line_outs] = seq;
+ line_out[cfg->line_outs].pin = nid;
+ line_out[cfg->line_outs].seq = seq;
cfg->line_outs++;
break;
case AC_JACK_SPEAKER:
@@ -193,8 +185,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
assoc = get_defcfg_association(def_conf);
if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
continue;
- cfg->speaker_pins[cfg->speaker_outs] = nid;
- sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;
+ speaker_out[cfg->speaker_outs].pin = nid;
+ speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq;
cfg->speaker_outs++;
break;
case AC_JACK_HP_OUT:
@@ -202,8 +194,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
assoc = get_defcfg_association(def_conf);
if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
continue;
- cfg->hp_pins[cfg->hp_outs] = nid;
- sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
+ hp_out[cfg->hp_outs].pin = nid;
+ hp_out[cfg->hp_outs].seq = (assoc << 4) | seq;
cfg->hp_outs++;
break;
case AC_JACK_MIC_IN:
@@ -248,34 +240,28 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
int i = 0;
while (i < cfg->hp_outs) {
/* The real HPs should have the sequence 0x0f */
- if ((sequences_hp[i] & 0x0f) == 0x0f) {
+ if ((hp_out[i].seq & 0x0f) == 0x0f) {
i++;
continue;
}
/* Move it to the line-out table */
- cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
- sequences_line_out[cfg->line_outs] = sequences_hp[i];
- cfg->line_outs++;
+ line_out[cfg->line_outs++] = hp_out[i];
cfg->hp_outs--;
- memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
- sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
- memmove(sequences_hp + i, sequences_hp + i + 1,
- sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
+ memmove(hp_out + i, hp_out + i + 1,
+ sizeof(hp_out[0]) * (cfg->hp_outs - i));
}
- memset(cfg->hp_pins + cfg->hp_outs, 0,
- sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
+ memset(hp_out + cfg->hp_outs, 0,
+ sizeof(hp_out[0]) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
if (!cfg->hp_outs)
cfg->line_out_type = AUTO_PIN_HP_OUT;
}
/* sort by sequence */
- sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
- cfg->line_outs);
- sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
+ sort_pins_by_sequence(cfg->line_out_pins, line_out, cfg->line_outs);
+ sort_pins_by_sequence(cfg->speaker_pins, speaker_out,
cfg->speaker_outs);
- sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
- cfg->hp_outs);
+ sort_pins_by_sequence(cfg->hp_pins, hp_out, cfg->hp_outs);
/*
* FIX-UP: if no line-outs are detected, try to use speaker or HP pin
@@ -304,7 +290,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
reorder_outputs(cfg->hp_outs, cfg->hp_pins);
reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
- sort_autocfg_input_pins(cfg);
+ /* sort inputs in the order of AUTO_PIN_* type */
+ sort(cfg->inputs, cfg->num_inputs, sizeof(cfg->inputs[0]),
+ compare_input_type, NULL);
/*
* debug prints of the parsed results
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d010de12335e..8353c77536ac 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -738,7 +738,7 @@ static int snd_hda_bus_dev_register(struct snd_device *device)
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
+int snd_hda_bus_new(struct snd_card *card,
const struct hda_bus_template *temp,
struct hda_bus **busp)
{
@@ -908,7 +908,7 @@ static int get_codec_name(struct hda_codec *codec)
/*
* look for an AFG and MFG nodes
*/
-static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
+static void setup_fg_nodes(struct hda_codec *codec)
{
int i, total_nodes, function_id;
hda_nid_t nid;
@@ -993,19 +993,6 @@ static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
return NULL;
}
-/* write a config value for the given NID */
-static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
- unsigned int cfg)
-{
- int i;
- for (i = 0; i < 4; i++) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
- cfg & 0xff);
- cfg >>= 8;
- }
-}
-
/* set the current pin config value for the given NID.
* the value is cached, and read via snd_hda_codec_get_pincfg()
*/
@@ -1013,12 +1000,10 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
hda_nid_t nid, unsigned int cfg)
{
struct hda_pincfg *pin;
- unsigned int oldcfg;
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
return -EINVAL;
- oldcfg = snd_hda_codec_get_pincfg(codec, nid);
pin = look_up_pincfg(codec, list, nid);
if (!pin) {
pin = snd_array_new(list);
@@ -1027,13 +1012,6 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
pin->nid = nid;
}
pin->cfg = cfg;
-
- /* change only when needed; e.g. if the pincfg is already present
- * in user_pins[], don't write it
- */
- cfg = snd_hda_codec_get_pincfg(codec, nid);
- if (oldcfg != cfg)
- set_pincfg(codec, nid, cfg);
return 0;
}
@@ -1082,17 +1060,6 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
}
EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
-/* restore all current pin configs */
-static void restore_pincfgs(struct hda_codec *codec)
-{
- int i;
- for (i = 0; i < codec->init_pins.used; i++) {
- struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
- set_pincfg(codec, pin->nid,
- snd_hda_codec_get_pincfg(codec, pin->nid));
- }
-}
-
/**
* snd_hda_shutup_pins - Shut up all pins
* @codec: the HDA codec
@@ -1137,21 +1104,30 @@ static void restore_shutup_pins(struct hda_codec *codec)
}
#endif
+static void hda_jackpoll_work(struct work_struct *work)
+{
+ struct hda_codec *codec =
+ container_of(work, struct hda_codec, jackpoll_work.work);
+ if (!codec->jackpoll_interval)
+ return;
+
+ snd_hda_jack_set_dirty_all(codec);
+ snd_hda_jack_poll_all(codec);
+ queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
+ codec->jackpoll_interval);
+}
+
static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size);
static void free_hda_cache(struct hda_cache_rec *cache);
-/* restore the initial pin cfgs and release all pincfg lists */
-static void restore_init_pincfgs(struct hda_codec *codec)
+/* release all pincfg lists */
+static void free_init_pincfgs(struct hda_codec *codec)
{
- /* first free driver_pins and user_pins, then call restore_pincfg
- * so that only the values in init_pins are restored
- */
snd_array_free(&codec->driver_pins);
#ifdef CONFIG_SND_HDA_HWDEP
snd_array_free(&codec->user_pins);
#endif
- restore_pincfgs(codec);
snd_array_free(&codec->init_pins);
}
@@ -1192,8 +1168,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)
{
if (!codec)
return;
+ cancel_delayed_work_sync(&codec->jackpoll_work);
snd_hda_jack_tbl_clear(codec);
- restore_init_pincfgs(codec);
+ free_init_pincfgs(codec);
#ifdef CONFIG_PM
cancel_delayed_work(&codec->power_work);
flush_workqueue(codec->bus->workq);
@@ -1235,7 +1212,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
+int snd_hda_codec_new(struct hda_bus *bus,
unsigned int codec_addr,
struct hda_codec **codecp)
{
@@ -1275,6 +1252,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
+ snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
+ INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
#ifdef CONFIG_PM
spin_lock_init(&codec->power_lock);
@@ -1588,7 +1567,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec)
#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
/* initialize the hash table */
-static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
+static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size)
{
memset(cache, 0, sizeof(*cache));
@@ -2153,12 +2132,12 @@ EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
/* find a mixer control element with the given name */
static struct snd_kcontrol *
-_snd_hda_find_mixer_ctl(struct hda_codec *codec,
- const char *name, int idx)
+find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ id.device = dev;
id.index = idx;
if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
return NULL;
@@ -2176,15 +2155,16 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name)
{
- return _snd_hda_find_mixer_ctl(codec, name, 0);
+ return find_mixer_ctl(codec, name, 0, 0);
}
EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
-static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
+static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
+ int dev)
{
int idx;
for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
- if (!_snd_hda_find_mixer_ctl(codec, name, idx))
+ if (!find_mixer_ctl(codec, name, dev, idx))
return idx;
}
return -EBUSY;
@@ -2351,7 +2331,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
return -EBUSY;
/* OK, let it free */
-
+ cancel_delayed_work_sync(&codec->jackpoll_work);
#ifdef CONFIG_PM
cancel_delayed_work_sync(&codec->power_work);
codec->power_on = 0;
@@ -2380,7 +2360,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
/* free only driver_pins so that init_pins + user_pins are restored */
snd_array_free(&codec->driver_pins);
- restore_pincfgs(codec);
snd_array_free(&codec->cvt_setups);
snd_array_free(&codec->spdif_out);
codec->num_pcms = 0;
@@ -3135,26 +3114,48 @@ static struct snd_kcontrol_new dig_mixes[] = {
};
/**
- * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
* @codec: the HDA codec
- * @nid: audio out widget NID
- *
- * Creates controls related with the SPDIF output.
- * Called from each patch supporting the SPDIF out.
+ * @associated_nid: NID that new ctls associated with
+ * @cvt_nid: converter NID
+ * @type: HDA_PCM_TYPE_*
+ * Creates controls related with the digital output.
+ * Called from each patch supporting the digital out.
*
* Returns 0 if successful, or a negative error code.
*/
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
- hda_nid_t associated_nid,
- hda_nid_t cvt_nid)
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+ hda_nid_t associated_nid,
+ hda_nid_t cvt_nid,
+ int type)
{
int err;
struct snd_kcontrol *kctl;
struct snd_kcontrol_new *dig_mix;
- int idx;
+ int idx, dev = 0;
+ const int spdif_pcm_dev = 1;
struct hda_spdif_out *spdif;
- idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
+ if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
+ type == HDA_PCM_TYPE_SPDIF) {
+ dev = spdif_pcm_dev;
+ } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
+ type == HDA_PCM_TYPE_HDMI) {
+ for (idx = 0; idx < codec->spdif_out.used; idx++) {
+ spdif = snd_array_elem(&codec->spdif_out, idx);
+ for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+ kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
+ if (!kctl)
+ break;
+ kctl->id.device = spdif_pcm_dev;
+ }
+ }
+ codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
+ }
+ if (!codec->primary_dig_out_type)
+ codec->primary_dig_out_type = type;
+
+ idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
if (idx < 0) {
printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
return -EBUSY;
@@ -3164,6 +3165,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
kctl = snd_ctl_new1(dig_mix, codec);
if (!kctl)
return -ENOMEM;
+ kctl->id.device = dev;
kctl->id.index = idx;
kctl->private_value = codec->spdif_out.used - 1;
err = snd_hda_ctl_add(codec, associated_nid, kctl);
@@ -3176,7 +3178,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
spdif->status = convert_to_spdif_status(spdif->ctls);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
+EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
/* get the hda_spdif_out entry from the given NID
* call within spdif_mutex lock
@@ -3351,7 +3353,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
struct snd_kcontrol_new *dig_mix;
int idx;
- idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
+ idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
if (idx < 0) {
printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
return -EBUSY;
@@ -3650,10 +3652,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
*/
hda_keep_power_on(codec);
hda_set_power_state(codec, AC_PWRST_D0);
- restore_pincfgs(codec); /* restore all current pin configs */
restore_shutup_pins(codec);
hda_exec_init_verbs(codec);
- snd_hda_jack_set_dirty_all(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
@@ -3662,7 +3662,13 @@ static void hda_call_codec_resume(struct hda_codec *codec)
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
}
- snd_hda_jack_report_sync(codec);
+
+ if (codec->jackpoll_interval)
+ hda_jackpoll_work(&codec->jackpoll_work.work);
+ else {
+ snd_hda_jack_set_dirty_all(codec);
+ snd_hda_jack_report_sync(codec);
+ }
codec->in_pm = 0;
snd_hda_power_down(codec); /* flag down before returning */
@@ -3678,7 +3684,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
*
* Returns 0 if successful, otherwise a negative error code.
*/
-int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
+int snd_hda_build_controls(struct hda_bus *bus)
{
struct hda_codec *codec;
@@ -3712,13 +3718,14 @@ static int add_std_chmaps(struct hda_codec *codec)
struct hda_pcm_stream *hinfo =
&codec->pcm_info[i].stream[str];
struct snd_pcm_chmap *chmap;
+ const struct snd_pcm_chmap_elem *elem;
if (codec->pcm_info[i].own_chmap)
continue;
if (!pcm || !hinfo->substreams)
continue;
- err = snd_pcm_add_chmap_ctls(pcm, str,
- snd_pcm_std_chmaps,
+ elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
+ err = snd_pcm_add_chmap_ctls(pcm, str, elem,
hinfo->channels_max,
0, &chmap);
if (err < 0)
@@ -3729,6 +3736,19 @@ static int add_std_chmaps(struct hda_codec *codec)
return 0;
}
+/* default channel maps for 2.1 speakers;
+ * since HD-audio supports only stereo, odd number channels are omitted
+ */
+const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+ { .channels = 4,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+ SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
+ { }
+};
+EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps);
+
int snd_hda_codec_build_controls(struct hda_codec *codec)
{
int err = 0;
@@ -3746,7 +3766,10 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
- snd_hda_jack_report_sync(codec); /* call at the last init point */
+ if (codec->jackpoll_interval)
+ hda_jackpoll_work(&codec->jackpoll_work.work);
+ else
+ snd_hda_jack_report_sync(codec); /* call at the last init point */
return 0;
}
@@ -4458,7 +4481,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
addr = codec->addr;
else if (!idx && !knew->index) {
idx = find_empty_mixer_ctl_idx(codec,
- knew->name);
+ knew->name, 0);
if (idx <= 0)
return err;
} else
@@ -4771,6 +4794,34 @@ EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
/*
+ * process kcontrol info callback of a simple string enum array
+ * when @num_items is 0 or @texts is NULL, assume a boolean enum array
+ */
+int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo,
+ int num_items, const char * const *texts)
+{
+ static const char * const texts_default[] = {
+ "Disabled", "Enabled"
+ };
+
+ if (!texts || !num_items) {
+ num_items = 2;
+ texts = texts_default;
+ }
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = num_items;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
+
+/*
* Multi-channel / digital-out PCM helper functions
*/
@@ -4778,10 +4829,20 @@ EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
unsigned int stream_tag, unsigned int format)
{
- struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid);
-
- /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
- if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
+ struct hda_spdif_out *spdif;
+ unsigned int curr_fmt;
+ bool reset;
+
+ spdif = snd_hda_spdif_out_of_nid(codec, nid);
+ curr_fmt = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_STREAM_FORMAT, 0);
+ reset = codec->spdif_status_reset &&
+ (spdif->ctls & AC_DIG1_ENABLE) &&
+ curr_fmt != format;
+
+ /* turn off SPDIF if needed; otherwise the IEC958 bits won't be
+ updated */
+ if (reset)
set_dig_out_convert(codec, nid,
spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
-1);
@@ -4793,7 +4854,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
format);
}
/* turn on again (if needed) */
- if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
+ if (reset)
set_dig_out_convert(codec, nid,
spdif->ctls & 0xff, -1);
}
@@ -5137,6 +5198,7 @@ int snd_hda_suspend(struct hda_bus *bus)
struct hda_codec *codec;
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);
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 4f4e545c0f4b..8665540e55aa 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -757,6 +757,7 @@ struct hda_pcm_stream {
u32 rates; /* supported rates */
u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */
unsigned int maxbps; /* supported max. bit per sample */
+ const struct snd_pcm_chmap_elem *chmap; /* chmap to override */
struct hda_pcm_ops ops;
};
@@ -836,6 +837,7 @@ struct hda_codec {
struct mutex hash_mutex;
struct snd_array spdif_out;
unsigned int spdif_in_enable; /* SPDIF input enable? */
+ int primary_dig_out_type; /* primary digital out PCM type */
const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
struct snd_array init_pins; /* initial (BIOS) pin configurations */
struct snd_array driver_pins; /* pin configs set by codec parser */
@@ -885,6 +887,8 @@ struct hda_codec {
/* jack detection */
struct snd_array jacktbl;
+ unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */
+ struct delayed_work jackpoll_work;
#ifdef CONFIG_SND_HDA_INPUT_JACK
/* jack detection */
@@ -1024,6 +1028,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);
+extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[];
+
/*
* Misc
*/
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 1af86d40eb23..a5c9411bb367 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -125,7 +125,7 @@ static void hwdep_free(struct snd_hwdep *hwdep)
clear_hwdep_elements(hwdep->private_data);
}
-int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
+int snd_hda_create_hwdep(struct hda_codec *codec)
{
char hwname[16];
struct snd_hwdep *hwdep;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index f9d870e554d9..0f3d3db0df71 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -47,6 +47,10 @@
#include <linux/reboot.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/completion.h>
+
#ifdef CONFIG_X86
/* for snoop control */
#include <asm/pgtable.h>
@@ -68,6 +72,7 @@ static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_only[SNDRV_CARDS];
+static int jackpoll_ms[SNDRV_CARDS];
static bool single_cmd;
static int enable_msi = -1;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
@@ -95,6 +100,8 @@ module_param_array(probe_mask, int, NULL, 0444);
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
module_param_array(probe_only, int, NULL, 0444);
MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
+module_param_array(jackpoll_ms, int, NULL, 0444);
+MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
module_param(single_cmd, bool, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only).");
@@ -185,7 +192,7 @@ MODULE_DESCRIPTION("Intel HDA driver");
#ifdef CONFIG_SND_VERBOSE_PRINTK
#define SFX /* nop */
#else
-#define SFX "hda-intel: "
+#define SFX "hda-intel "
#endif
#if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO)
@@ -416,6 +423,9 @@ struct azx_dev {
unsigned int insufficient :1;
unsigned int wc_marked:1;
unsigned int no_period_wakeup:1;
+
+ struct timecounter azx_tc;
+ struct cyclecounter azx_cc;
};
/* CORB/RIRB */
@@ -460,6 +470,7 @@ struct azx {
/* locks */
spinlock_t reg_lock;
struct mutex open_mutex;
+ struct completion probe_wait;
/* streams (x num_streams) */
struct azx_dev *azx_dev;
@@ -518,6 +529,9 @@ struct azx {
struct list_head list;
};
+#define CREATE_TRACE_POINTS
+#include "hda_intel_trace.h"
+
/* driver types */
enum {
AZX_DRIVER_ICH,
@@ -589,15 +603,7 @@ enum {
#define use_vga_switcheroo(chip) 0
#endif
-#if defined(SUPPORT_VGA_SWITCHEROO) || defined(CONFIG_SND_HDA_PATCH_LOADER)
-#define DELAYED_INIT_MARK
-#define DELAYED_INITDATA_MARK
-#else
-#define DELAYED_INIT_MARK __devinit
-#define DELAYED_INITDATA_MARK __devinitdata
-#endif
-
-static char *driver_short_names[] DELAYED_INITDATA_MARK = {
+static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
[AZX_DRIVER_SCH] = "HDA Intel MID",
@@ -703,7 +709,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
snd_dma_pci_data(chip->pci),
PAGE_SIZE, &chip->rb);
if (err < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
+ snd_printk(KERN_ERR SFX "%s: cannot allocate CORB/RIRB\n", pci_name(chip->pci));
return err;
}
mark_pages_wc(chip, &chip->rb, true);
@@ -793,7 +799,12 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
spin_lock_irq(&chip->reg_lock);
/* add command to corb */
- wp = azx_readb(chip, CORBWP);
+ wp = azx_readw(chip, CORBWP);
+ if (wp == 0xffff) {
+ /* something wrong, controller likely turned to D3 */
+ spin_unlock_irq(&chip->reg_lock);
+ return -1;
+ }
wp++;
wp %= ICH6_MAX_CORB_ENTRIES;
@@ -815,7 +826,12 @@ static void azx_update_rirb(struct azx *chip)
unsigned int addr;
u32 res, res_ex;
- wp = azx_readb(chip, RIRBWP);
+ wp = azx_readw(chip, RIRBWP);
+ if (wp == 0xffff) {
+ /* something wrong, controller likely turned to D3 */
+ return;
+ }
+
if (wp == chip->rirb.wp)
return;
chip->rirb.wp = wp;
@@ -835,8 +851,9 @@ static void azx_update_rirb(struct azx *chip)
smp_wmb();
chip->rirb.cmds[addr]--;
} else
- snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+ snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, "
"last cmd=%#08x\n",
+ pci_name(chip->pci),
res, res_ex,
chip->last_cmd[addr]);
}
@@ -879,9 +896,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
if (!chip->polling_mode && chip->poll_count < 2) {
- snd_printdd(SFX "azx_get_response timeout, "
+ snd_printdd(SFX "%s: azx_get_response timeout, "
"polling the codec once: last cmd=0x%08x\n",
- chip->last_cmd[addr]);
+ pci_name(chip->pci), chip->last_cmd[addr]);
do_poll = 1;
chip->poll_count++;
goto again;
@@ -889,17 +906,17 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
if (!chip->polling_mode) {
- snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
+ snd_printk(KERN_WARNING SFX "%s: azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n",
- chip->last_cmd[addr]);
+ pci_name(chip->pci), chip->last_cmd[addr]);
chip->polling_mode = 1;
goto again;
}
if (chip->msi) {
- snd_printk(KERN_WARNING SFX "No response from codec, "
+ snd_printk(KERN_WARNING SFX "%s: No response from codec, "
"disabling MSI: last cmd=0x%08x\n",
- chip->last_cmd[addr]);
+ pci_name(chip->pci), chip->last_cmd[addr]);
free_irq(chip->irq, chip);
chip->irq = -1;
pci_disable_msi(chip->pci);
@@ -965,8 +982,8 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
udelay(1);
}
if (printk_ratelimit())
- snd_printd(SFX "get_response timeout: IRS=0x%x\n",
- azx_readw(chip, IRS));
+ snd_printd(SFX "%s: get_response timeout: IRS=0x%x\n",
+ pci_name(chip->pci), azx_readw(chip, IRS));
chip->rirb.res[addr] = -1;
return -EIO;
}
@@ -993,8 +1010,8 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
udelay(1);
}
if (printk_ratelimit())
- snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n",
- azx_readw(chip, IRS), val);
+ snd_printd(SFX "%s: send_cmd timeout: IRS=0x%x, val=0x%x\n",
+ pci_name(chip->pci), azx_readw(chip, IRS), val);
return -EIO;
}
@@ -1047,7 +1064,7 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up);
/* reset codec link */
static int azx_reset(struct azx *chip, int full_reset)
{
- int count;
+ unsigned long timeout;
if (!full_reset)
goto __skip;
@@ -1058,29 +1075,31 @@ static int azx_reset(struct azx *chip, int full_reset)
/* reset controller */
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
- count = 50;
- while (azx_readb(chip, GCTL) && --count)
- msleep(1);
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (azx_readb(chip, GCTL) &&
+ time_before(jiffies, timeout))
+ usleep_range(500, 1000);
/* delay for >= 100us for codec PLL to settle per spec
* Rev 0.9 section 5.5.1
*/
- msleep(1);
+ usleep_range(500, 1000);
/* Bring controller out of reset */
azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
- count = 50;
- while (!azx_readb(chip, GCTL) && --count)
- msleep(1);
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (!azx_readb(chip, GCTL) &&
+ time_before(jiffies, timeout))
+ usleep_range(500, 1000);
/* Brent Chartrand said to wait >= 540us for codecs to initialize */
- msleep(1);
+ usleep_range(1000, 1200);
__skip:
/* check to see if controller is ready */
if (!azx_readb(chip, GCTL)) {
- snd_printd(SFX "azx_reset: controller not ready!\n");
+ snd_printd(SFX "%s: azx_reset: controller not ready!\n", pci_name(chip->pci));
return -EBUSY;
}
@@ -1092,7 +1111,7 @@ static int azx_reset(struct azx *chip, int full_reset)
/* detect codecs */
if (!chip->codec_mask) {
chip->codec_mask = azx_readw(chip, STATESTS);
- snd_printdd(SFX "codec_mask = 0x%x\n", chip->codec_mask);
+ snd_printdd(SFX "%s: codec_mask = 0x%x\n", pci_name(chip->pci), chip->codec_mask);
}
return 0;
@@ -1236,7 +1255,7 @@ static void azx_init_pci(struct azx *chip)
* The PCI register TCSEL is defined in the Intel manuals.
*/
if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
- snd_printdd(SFX "Clearing TCSEL\n");
+ snd_printdd(SFX "%s: Clearing TCSEL\n", pci_name(chip->pci));
update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
}
@@ -1244,7 +1263,7 @@ static void azx_init_pci(struct azx *chip)
* we need to enable snoop.
*/
if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
- snd_printdd(SFX "Setting ATI snoop: %d\n", azx_snoop(chip));
+ snd_printdd(SFX "%s: Setting ATI snoop: %d\n", pci_name(chip->pci), azx_snoop(chip));
update_pci_byte(chip->pci,
ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
@@ -1252,7 +1271,7 @@ static void azx_init_pci(struct azx *chip)
/* For NVIDIA HDA, enable snoop */
if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) {
- snd_printdd(SFX "Setting Nvidia snoop: %d\n", azx_snoop(chip));
+ snd_printdd(SFX "%s: Setting Nvidia snoop: %d\n", pci_name(chip->pci), azx_snoop(chip));
update_pci_byte(chip->pci,
NVIDIA_HDA_TRANSREG_ADDR,
0x0f, NVIDIA_HDA_ENABLE_COHBITS);
@@ -1277,8 +1296,8 @@ static void azx_init_pci(struct azx *chip)
pci_read_config_word(chip->pci,
INTEL_SCH_HDA_DEVC, &snoop);
}
- snd_printdd(SFX "SCH snoop: %s\n",
- (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
+ snd_printdd(SFX "%s: SCH snoop: %s\n",
+ pci_name(chip->pci), (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
? "Disabled" : "Enabled");
}
}
@@ -1438,8 +1457,8 @@ static int azx_setup_periods(struct azx *chip,
pos_align;
pos_adj = frames_to_bytes(runtime, pos_adj);
if (pos_adj >= period_bytes) {
- snd_printk(KERN_WARNING SFX "Too big adjustment %d\n",
- bdl_pos_adj[chip->dev_index]);
+ snd_printk(KERN_WARNING SFX "%s: Too big adjustment %d\n",
+ pci_name(chip->pci), bdl_pos_adj[chip->dev_index]);
pos_adj = 0;
} else {
ofs = setup_bdle(chip, substream, azx_dev,
@@ -1463,8 +1482,8 @@ static int azx_setup_periods(struct azx *chip,
return 0;
error:
- snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n",
- azx_dev->bufsize, period_bytes);
+ snd_printk(KERN_ERR SFX "%s: Too many BDL entries: buffer=%d, period=%d\n",
+ pci_name(chip->pci), azx_dev->bufsize, period_bytes);
return -EINVAL;
}
@@ -1561,7 +1580,7 @@ static int probe_codec(struct azx *chip, int addr)
mutex_unlock(&chip->bus->cmd_mutex);
if (res == -1)
return -EIO;
- snd_printdd(SFX "codec #%d probed OK\n", addr);
+ snd_printdd(SFX "%s: codec #%d probed OK\n", pci_name(chip->pci), addr);
return 0;
}
@@ -1588,17 +1607,33 @@ static void azx_bus_reset(struct hda_bus *bus)
bus->in_reset = 0;
}
+static int get_jackpoll_interval(struct azx *chip)
+{
+ int i = jackpoll_ms[chip->dev_index];
+ unsigned int j;
+ if (i == 0)
+ return 0;
+ if (i < 50 || i > 60000)
+ j = 0;
+ else
+ j = msecs_to_jiffies(i);
+ if (j == 0)
+ snd_printk(KERN_WARNING SFX
+ "jackpoll_ms value out of range: %d\n", i);
+ return j;
+}
+
/*
* Codec initialization
*/
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
-static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] DELAYED_INITDATA_MARK = {
+static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
[AZX_DRIVER_NVIDIA] = 8,
[AZX_DRIVER_TERA] = 1,
};
-static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *model)
+static int azx_codec_create(struct azx *chip, const char *model)
{
struct hda_bus_template bus_temp;
int c, codecs, err;
@@ -1622,7 +1657,7 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
return err;
if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
- snd_printd(SFX "Enable delay in RIRB handling\n");
+ snd_printd(SFX "%s: Enable delay in RIRB handling\n", pci_name(chip->pci));
chip->bus->needs_damn_long_delay = 1;
}
@@ -1639,8 +1674,8 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
* that don't exist
*/
snd_printk(KERN_WARNING SFX
- "Codec #%d probe error; "
- "disabling it...\n", c);
+ "%s: Codec #%d probe error; "
+ "disabling it...\n", pci_name(chip->pci), c);
chip->codec_mask &= ~(1 << c);
/* More badly, accessing to a non-existing
* codec often screws up the controller chip,
@@ -1660,7 +1695,8 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
* access works around the stall. Grrr...
*/
if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) {
- snd_printd(SFX "Enable sync_write for stable communication\n");
+ snd_printd(SFX "%s: Enable sync_write for stable communication\n",
+ pci_name(chip->pci));
chip->bus->sync_write = 1;
chip->bus->allow_bus_reset = 1;
}
@@ -1672,19 +1708,20 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
err = snd_hda_codec_new(chip->bus, c, &codec);
if (err < 0)
continue;
+ codec->jackpoll_interval = get_jackpoll_interval(chip);
codec->beep_mode = chip->beep_mode;
codecs++;
}
}
if (!codecs) {
- snd_printk(KERN_ERR SFX "no codecs initialized\n");
+ snd_printk(KERN_ERR SFX "%s: no codecs initialized\n", pci_name(chip->pci));
return -ENXIO;
}
return 0;
}
/* configure each codec instance */
-static int __devinit azx_codec_configure(struct azx *chip)
+static int azx_codec_configure(struct azx *chip)
{
struct hda_codec *codec;
list_for_each_entry(codec, &chip->bus->codec_list, list) {
@@ -1734,6 +1771,64 @@ static inline void azx_release_device(struct azx_dev *azx_dev)
azx_dev->opened = 0;
}
+static cycle_t azx_cc_read(const struct cyclecounter *cc)
+{
+ struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc);
+ struct snd_pcm_substream *substream = azx_dev->substream;
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ struct azx *chip = apcm->chip;
+
+ return azx_readl(chip, WALLCLK);
+}
+
+static void azx_timecounter_init(struct snd_pcm_substream *substream,
+ bool force, cycle_t last)
+{
+ struct azx_dev *azx_dev = get_azx_dev(substream);
+ struct timecounter *tc = &azx_dev->azx_tc;
+ struct cyclecounter *cc = &azx_dev->azx_cc;
+ u64 nsec;
+
+ cc->read = azx_cc_read;
+ cc->mask = CLOCKSOURCE_MASK(32);
+
+ /*
+ * Converting from 24 MHz to ns means applying a 125/3 factor.
+ * To avoid any saturation issues in intermediate operations,
+ * the 125 factor is applied first. The division is applied
+ * last after reading the timecounter value.
+ * Applying the 1/3 factor as part of the multiplication
+ * requires at least 20 bits for a decent precision, however
+ * overflows occur after about 4 hours or less, not a option.
+ */
+
+ cc->mult = 125; /* saturation after 195 years */
+ cc->shift = 0;
+
+ nsec = 0; /* audio time is elapsed time since trigger */
+ timecounter_init(tc, cc, nsec);
+ if (force)
+ /*
+ * force timecounter to use predefined value,
+ * used for synchronized starts
+ */
+ tc->cycle_last = last;
+}
+
+static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
+ struct timespec *ts)
+{
+ struct azx_dev *azx_dev = get_azx_dev(substream);
+ u64 nsec;
+
+ nsec = timecounter_read(&azx_dev->azx_tc);
+ nsec = div_u64(nsec, 3); /* can be optimized */
+
+ *ts = ns_to_timespec(nsec);
+
+ return 0;
+}
+
static struct snd_pcm_hardware azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1743,6 +1838,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
/* SNDRV_PCM_INFO_RESUME |*/
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_SYNC_START |
+ SNDRV_PCM_INFO_HAS_WALL_CLOCK |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
@@ -1782,6 +1878,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
runtime->hw.rates = hinfo->rates;
snd_pcm_limit_hw_rates(runtime);
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+ /* avoid wrap-around with wall-clock */
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
+ 20,
+ 178000000);
+
if (chip->align_buffer_size)
/* constrain buffer sizes to be multiple of 128
bytes. This is more efficient in terms of memory
@@ -1821,6 +1923,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock(&chip->open_mutex);
return -EINVAL;
}
+
+ /* disable WALLCLOCK timestamps for capture streams
+ until we figure out how to handle digital inputs */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK;
+
spin_lock_irqsave(&chip->reg_lock, flags);
azx_dev->substream = substream;
azx_dev->running = 0;
@@ -1916,16 +2024,16 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
ctls);
if (!format_val) {
snd_printk(KERN_ERR SFX
- "invalid format_val, rate=%d, ch=%d, format=%d\n",
- runtime->rate, runtime->channels, runtime->format);
+ "%s: invalid format_val, rate=%d, ch=%d, format=%d\n",
+ pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format);
return -EINVAL;
}
bufsize = snd_pcm_lib_buffer_bytes(substream);
period_bytes = snd_pcm_lib_period_bytes(substream);
- snd_printdd(SFX "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
- bufsize, format_val);
+ snd_printdd(SFX "%s: azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+ pci_name(chip->pci), bufsize, format_val);
if (bufsize != azx_dev->bufsize ||
period_bytes != azx_dev->period_bytes ||
@@ -1967,6 +2075,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
int rstart = 0, start, nsync = 0, sbits = 0;
int nwait, timeout;
+ azx_dev = get_azx_dev(substream);
+ trace_azx_pcm_trigger(chip, azx_dev, cmd);
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
rstart = 1;
@@ -2057,6 +2168,22 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
azx_readl(chip, OLD_SSYNC) & ~sbits);
else
azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits);
+ if (start) {
+ azx_timecounter_init(substream, 0, 0);
+ if (nsync > 1) {
+ cycle_t cycle_last;
+
+ /* same start cycle for master and group */
+ azx_dev = get_azx_dev(substream);
+ cycle_last = azx_dev->azx_tc.cycle_last;
+
+ snd_pcm_group_for_each_entry(s, substream) {
+ if (s->pcm->card != substream->pcm->card)
+ continue;
+ azx_timecounter_init(s, 1, cycle_last);
+ }
+ }
+ }
spin_unlock(&chip->reg_lock);
return 0;
}
@@ -2123,6 +2250,7 @@ static unsigned int azx_get_position(struct azx *chip,
{
unsigned int pos;
int stream = azx_dev->substream->stream;
+ int delay = 0;
switch (chip->position_fix[stream]) {
case POS_FIX_LPIB:
@@ -2156,7 +2284,6 @@ static unsigned int azx_get_position(struct azx *chip,
chip->position_fix[stream] == POS_FIX_POSBUF &&
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
- int delay;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
delay = pos - lpib_pos;
else
@@ -2165,15 +2292,16 @@ static unsigned int azx_get_position(struct azx *chip,
delay += azx_dev->bufsize;
if (delay >= azx_dev->period_bytes) {
snd_printk(KERN_WARNING SFX
- "Unstable LPIB (%d >= %d); "
+ "%s: Unstable LPIB (%d >= %d); "
"disabling LPIB delay counting\n",
- delay, azx_dev->period_bytes);
+ pci_name(chip->pci), delay, azx_dev->period_bytes);
delay = 0;
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
}
azx_dev->substream->runtime->delay =
bytes_to_frames(azx_dev->substream->runtime, delay);
}
+ trace_azx_get_position(chip, azx_dev, pos, delay);
return pos;
}
@@ -2199,13 +2327,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
{
u32 wallclk;
unsigned int pos;
- int stream;
wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk;
if (wallclk < (azx_dev->period_wallclk * 2) / 3)
return -1; /* bogus (too early) interrupt */
- stream = azx_dev->substream->stream;
pos = azx_get_position(chip, azx_dev, true);
if (WARN_ONCE(!azx_dev->period_bytes,
@@ -2296,6 +2422,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
.prepare = azx_pcm_prepare,
.trigger = azx_pcm_trigger,
.pointer = azx_pcm_pointer,
+ .wall_clock = azx_get_wallclock_tstamp,
.mmap = azx_pcm_mmap,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -2324,7 +2451,8 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
list_for_each_entry(apcm, &chip->pcm_list, list) {
if (apcm->pcm->device == pcm_dev) {
- snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
+ snd_printk(KERN_ERR SFX "%s: PCM %d already exists\n",
+ pci_name(chip->pci), pcm_dev);
return -EBUSY;
}
}
@@ -2365,7 +2493,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
/*
* mixer creation - all stuff is implemented in hda module
*/
-static int __devinit azx_mixer_create(struct azx *chip)
+static int azx_mixer_create(struct azx *chip)
{
return snd_hda_build_controls(chip->bus);
}
@@ -2374,7 +2502,7 @@ static int __devinit azx_mixer_create(struct azx *chip)
/*
* initialize SD streams
*/
-static int __devinit azx_init_stream(struct azx *chip)
+static int azx_init_stream(struct azx *chip)
{
int i;
@@ -2502,6 +2630,9 @@ static int azx_suspend(struct device *dev)
struct azx *chip = card->private_data;
struct azx_pcm *p;
+ if (chip->disabled)
+ return 0;
+
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
azx_clear_irq_pending(chip);
list_for_each_entry(p, &chip->pcm_list, list)
@@ -2527,6 +2658,9 @@ static int azx_resume(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
+ if (chip->disabled)
+ return 0;
+
pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci);
if (pci_enable_device(pci) < 0) {
@@ -2557,10 +2691,6 @@ static int azx_runtime_suspend(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
- if (!power_save_controller ||
- !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
- return -EAGAIN;
-
azx_stop_chip(chip);
azx_clear_irq_pending(chip);
return 0;
@@ -2575,12 +2705,25 @@ static int azx_runtime_resume(struct device *dev)
azx_init_chip(chip, 1);
return 0;
}
+
+static int azx_runtime_idle(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip = card->private_data;
+
+ if (!power_save_controller ||
+ !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+ return -EBUSY;
+
+ return 0;
+}
+
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM
static const struct dev_pm_ops azx_pm = {
SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
- SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, NULL)
+ SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
};
#define AZX_PM_OPS &azx_pm
@@ -2612,11 +2755,11 @@ static void azx_notifier_unregister(struct azx *chip)
unregister_reboot_notifier(&chip->reboot_notifier);
}
-static int DELAYED_INIT_MARK azx_first_init(struct azx *chip);
-static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip);
+static int azx_first_init(struct azx *chip);
+static int azx_probe_continue(struct azx *chip);
#ifdef SUPPORT_VGA_SWITCHEROO
-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci);
+static struct pci_dev *get_bound_vga(struct pci_dev *pci);
static void azx_vs_set_state(struct pci_dev *pci,
enum vga_switcheroo_state state)
@@ -2625,6 +2768,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
struct azx *chip = card->private_data;
bool disabled;
+ wait_for_completion(&chip->probe_wait);
if (chip->init_failed)
return;
@@ -2648,15 +2792,14 @@ static void azx_vs_set_state(struct pci_dev *pci,
}
} else {
snd_printk(KERN_INFO SFX
- "%s %s via VGA-switcheroo\n",
- disabled ? "Disabling" : "Enabling",
- pci_name(chip->pci));
+ "%s: %s via VGA-switcheroo\n", pci_name(chip->pci),
+ disabled ? "Disabling" : "Enabling");
if (disabled) {
azx_suspend(&pci->dev);
chip->disabled = true;
if (snd_hda_lock_devices(chip->bus))
- snd_printk(KERN_WARNING SFX
- "Cannot lock devices!\n");
+ snd_printk(KERN_WARNING SFX "%s: Cannot lock devices!\n",
+ pci_name(chip->pci));
} else {
snd_hda_unlock_devices(chip->bus);
chip->disabled = false;
@@ -2670,6 +2813,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
+ wait_for_completion(&chip->probe_wait);
if (chip->init_failed)
return false;
if (chip->disabled || !chip->bus)
@@ -2680,7 +2824,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
return true;
}
-static void __devinit init_vga_switcheroo(struct azx *chip)
+static void init_vga_switcheroo(struct azx *chip)
{
struct pci_dev *p = get_bound_vga(chip->pci);
if (p) {
@@ -2697,7 +2841,7 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
.can_switch = azx_vs_can_switch,
};
-static int __devinit register_vga_switcheroo(struct azx *chip)
+static int register_vga_switcheroo(struct azx *chip)
{
int err;
@@ -2731,6 +2875,9 @@ static int azx_free(struct azx *chip)
azx_notifier_unregister(chip);
+ chip->init_failed = 1; /* to be sure */
+ complete(&chip->probe_wait);
+
if (use_vga_switcheroo(chip)) {
if (chip->disabled && chip->bus)
snd_hda_unlock_devices(chip->bus);
@@ -2789,7 +2936,7 @@ static int azx_dev_free(struct snd_device *device)
/*
* Check of disabled HDMI controller by vga-switcheroo
*/
-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
+static struct pci_dev *get_bound_vga(struct pci_dev *pci)
{
struct pci_dev *p;
@@ -2812,7 +2959,7 @@ static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
return NULL;
}
-static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
+static bool check_hdmi_disabled(struct pci_dev *pci)
{
bool vga_inactive = false;
struct pci_dev *p = get_bound_vga(pci);
@@ -2829,7 +2976,7 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
/*
* white/black-listing for position_fix
*/
-static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+static struct snd_pci_quirk position_fix_list[] = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
@@ -2847,7 +2994,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
{}
};
-static int __devinit check_position_fix(struct azx *chip, int fix)
+static int check_position_fix(struct azx *chip, int fix)
{
const struct snd_pci_quirk *q;
@@ -2871,11 +3018,11 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
/* Check VIA/ATI HD Audio Controller exist */
if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
- snd_printd(SFX "Using VIACOMBO position fix\n");
+ snd_printd(SFX "%s: Using VIACOMBO position fix\n", pci_name(chip->pci));
return POS_FIX_VIACOMBO;
}
if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
- snd_printd(SFX "Using LPIB position fix\n");
+ snd_printd(SFX "%s: Using LPIB position fix\n", pci_name(chip->pci));
return POS_FIX_LPIB;
}
return POS_FIX_AUTO;
@@ -2884,7 +3031,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
/*
* black-lists for probe_mask
*/
-static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
+static struct snd_pci_quirk probe_mask_list[] = {
/* Thinkpad often breaks the controller communication when accessing
* to the non-working (or non-existing) modem codec slot.
*/
@@ -2905,7 +3052,7 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
#define AZX_FORCE_CODEC_MASK 0x100
-static void __devinit check_probe_mask(struct azx *chip, int dev)
+static void check_probe_mask(struct azx *chip, int dev)
{
const struct snd_pci_quirk *q;
@@ -2933,7 +3080,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
/*
* white/black-list for enable_msi
*/
-static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+static struct snd_pci_quirk msi_black_list[] = {
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
@@ -2942,7 +3089,7 @@ static struct snd_pci_quirk msi_black_list[] __devinitdata = {
{}
};
-static void __devinit check_msi(struct azx *chip)
+static void check_msi(struct azx *chip)
{
const struct snd_pci_quirk *q;
@@ -2968,7 +3115,7 @@ static void __devinit check_msi(struct azx *chip)
}
/* check the snoop mode availability */
-static void __devinit azx_check_snoop_available(struct azx *chip)
+static void azx_check_snoop_available(struct azx *chip)
{
bool snoop = chip->snoop;
@@ -2991,8 +3138,8 @@ static void __devinit azx_check_snoop_available(struct azx *chip)
}
if (snoop != chip->snoop) {
- snd_printk(KERN_INFO SFX "Force to %s mode\n",
- snoop ? "snoop" : "non-snoop");
+ snd_printk(KERN_INFO SFX "%s: Force to %s mode\n",
+ pci_name(chip->pci), snoop ? "snoop" : "non-snoop");
chip->snoop = snoop;
}
}
@@ -3000,9 +3147,9 @@ static void __devinit azx_check_snoop_available(struct azx *chip)
/*
* constructor
*/
-static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
- int dev, unsigned int driver_caps,
- struct azx **rchip)
+static int azx_create(struct snd_card *card, struct pci_dev *pci,
+ int dev, unsigned int driver_caps,
+ struct azx **rchip)
{
static struct snd_device_ops ops = {
.dev_free = azx_dev_free,
@@ -3018,7 +3165,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) {
- snd_printk(KERN_ERR SFX "cannot allocate chip\n");
+ snd_printk(KERN_ERR SFX "%s: Cannot allocate chip\n", pci_name(pci));
pci_disable_device(pci);
return -ENOMEM;
}
@@ -3036,6 +3183,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->list);
init_vga_switcheroo(chip);
+ init_completion(&chip->probe_wait);
chip->position_fix[0] = chip->position_fix[1] =
check_position_fix(chip, position_fix[dev]);
@@ -3063,29 +3211,10 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
}
}
- if (check_hdmi_disabled(pci)) {
- snd_printk(KERN_INFO SFX "VGA controller for %s is disabled\n",
- pci_name(pci));
- if (use_vga_switcheroo(chip)) {
- snd_printk(KERN_INFO SFX "Delaying initialization\n");
- chip->disabled = true;
- goto ok;
- }
- kfree(chip);
- pci_disable_device(pci);
- return -ENXIO;
- }
-
- err = azx_first_init(chip);
- if (err < 0) {
- azx_free(chip);
- return err;
- }
-
- ok:
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
- snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
+ snd_printk(KERN_ERR SFX "%s: Error creating device [card]!\n",
+ pci_name(chip->pci));
azx_free(chip);
return err;
}
@@ -3094,7 +3223,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
return 0;
}
-static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
+static int azx_first_init(struct azx *chip)
{
int dev = chip->dev_index;
struct pci_dev *pci = chip->pci;
@@ -3120,7 +3249,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
chip->addr = pci_resource_start(pci, 0);
chip->remap_addr = pci_ioremap_bar(pci, 0);
if (chip->remap_addr == NULL) {
- snd_printk(KERN_ERR SFX "ioremap error\n");
+ snd_printk(KERN_ERR SFX "%s: ioremap error\n", pci_name(chip->pci));
return -ENXIO;
}
@@ -3135,7 +3264,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
synchronize_irq(chip->irq);
gcap = azx_readw(chip, GCAP);
- snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
+ snd_printdd(SFX "%s: chipset global capabilities = 0x%x\n", pci_name(chip->pci), gcap);
/* disable SB600 64bit support for safety */
if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
@@ -3152,7 +3281,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
/* disable 64bit DMA address on some devices */
if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
- snd_printd(SFX "Disabling 64bit DMA\n");
+ snd_printd(SFX "%s: Disabling 64bit DMA\n", pci_name(chip->pci));
gcap &= ~ICH6_GCAP_64OK;
}
@@ -3207,7 +3336,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
GFP_KERNEL);
if (!chip->azx_dev) {
- snd_printk(KERN_ERR SFX "cannot malloc azx_dev\n");
+ snd_printk(KERN_ERR SFX "%s: cannot malloc azx_dev\n", pci_name(chip->pci));
return -ENOMEM;
}
@@ -3217,7 +3346,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
snd_dma_pci_data(chip->pci),
BDL_SIZE, &chip->azx_dev[i].bdl);
if (err < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+ snd_printk(KERN_ERR SFX "%s: cannot allocate BDL\n", pci_name(chip->pci));
return -ENOMEM;
}
mark_pages_wc(chip, &chip->azx_dev[i].bdl, true);
@@ -3227,7 +3356,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
snd_dma_pci_data(chip->pci),
chip->num_streams * 8, &chip->posbuf);
if (err < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ snd_printk(KERN_ERR SFX "%s: cannot allocate posbuf\n", pci_name(chip->pci));
return -ENOMEM;
}
mark_pages_wc(chip, &chip->posbuf, true);
@@ -3245,7 +3374,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
/* codec detection */
if (!chip->codec_mask) {
- snd_printk(KERN_ERR SFX "no codecs found!\n");
+ snd_printk(KERN_ERR SFX "%s: no codecs found!\n", pci_name(chip->pci));
return -ENODEV;
}
@@ -3281,7 +3410,8 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
struct pci_dev *pci = chip->pci;
if (!fw) {
- snd_printk(KERN_ERR SFX "Cannot load firmware, aborting\n");
+ snd_printk(KERN_ERR SFX "%s: Cannot load firmware, aborting\n",
+ pci_name(chip->pci));
goto error;
}
@@ -3299,8 +3429,8 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
}
#endif
-static int __devinit azx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int azx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -3317,7 +3447,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
if (err < 0) {
- snd_printk(KERN_ERR SFX "Error creating card!\n");
+ snd_printk(KERN_ERR "hda-intel: Error creating card!\n");
return err;
}
@@ -3327,12 +3457,34 @@ static int __devinit azx_probe(struct pci_dev *pci,
if (err < 0)
goto out_free;
card->private_data = chip;
+
+ pci_set_drvdata(pci, card);
+
+ err = register_vga_switcheroo(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR SFX
+ "%s: Error registering VGA-switcheroo client\n", pci_name(pci));
+ goto out_free;
+ }
+
+ if (check_hdmi_disabled(pci)) {
+ snd_printk(KERN_INFO SFX "%s: VGA controller is disabled\n",
+ pci_name(pci));
+ snd_printk(KERN_INFO SFX "%s: Delaying initialization\n", pci_name(pci));
+ chip->disabled = true;
+ }
+
probe_now = !chip->disabled;
+ if (probe_now) {
+ err = azx_first_init(chip);
+ if (err < 0)
+ goto out_free;
+ }
#ifdef CONFIG_SND_HDA_PATCH_LOADER
if (patch[dev] && *patch[dev]) {
- snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n",
- patch[dev]);
+ snd_printk(KERN_ERR SFX "%s: Applying patch firmware '%s'\n",
+ pci_name(pci), patch[dev]);
err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
&pci->dev, GFP_KERNEL, card,
azx_firmware_cb);
@@ -3348,27 +3500,20 @@ static int __devinit azx_probe(struct pci_dev *pci,
goto out_free;
}
- pci_set_drvdata(pci, card);
-
if (pci_dev_run_wake(pci))
pm_runtime_put_noidle(&pci->dev);
- err = register_vga_switcheroo(chip);
- if (err < 0) {
- snd_printk(KERN_ERR SFX
- "Error registering VGA-switcheroo client\n");
- goto out_free;
- }
-
dev++;
+ complete(&chip->probe_wait);
return 0;
out_free:
snd_card_free(card);
+ pci_set_drvdata(pci, NULL);
return err;
}
-static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
+static int azx_probe_continue(struct azx *chip)
{
int dev = chip->dev_index;
int err;
@@ -3387,8 +3532,10 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
chip->fw->data);
if (err < 0)
goto out_free;
+#ifndef CONFIG_PM
release_firmware(chip->fw); /* no longer needed */
chip->fw = NULL;
+#endif
}
#endif
if ((probe_only[dev] & 1) == 0) {
@@ -3423,7 +3570,7 @@ out_free:
return err;
}
-static void __devexit azx_remove(struct pci_dev *pci)
+static void azx_remove(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
@@ -3610,7 +3757,7 @@ static struct pci_driver azx_driver = {
.name = KBUILD_MODNAME,
.id_table = azx_ids,
.probe = azx_probe,
- .remove = __devexit_p(azx_remove),
+ .remove = azx_remove,
.driver = {
.pm = AZX_PM_OPS,
},
diff --git a/sound/pci/hda/hda_intel_trace.h b/sound/pci/hda/hda_intel_trace.h
new file mode 100644
index 000000000000..7b5e4c2cf9d5
--- /dev/null
+++ b/sound/pci/hda/hda_intel_trace.h
@@ -0,0 +1,62 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hda_intel
+#define TRACE_INCLUDE_FILE hda_intel_trace
+
+#if !defined(_TRACE_HDA_INTEL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HDA_INTEL_H
+
+#include <linux/tracepoint.h>
+
+struct azx;
+struct azx_dev;
+
+TRACE_EVENT(azx_pcm_trigger,
+
+ TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd),
+
+ TP_ARGS(chip, dev, cmd),
+
+ TP_STRUCT__entry(
+ __field( int, card )
+ __field( int, idx )
+ __field( int, cmd )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (chip)->card->number;
+ __entry->idx = (dev)->index;
+ __entry->cmd = cmd;
+ ),
+
+ TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd)
+);
+
+TRACE_EVENT(azx_get_position,
+
+ TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay),
+
+ TP_ARGS(chip, dev, pos, delay),
+
+ TP_STRUCT__entry(
+ __field( int, card )
+ __field( int, idx )
+ __field( unsigned int, pos )
+ __field( unsigned int, delay )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (chip)->card->number;
+ __entry->idx = (dev)->index;
+ __entry->pos = pos;
+ __entry->delay = delay;
+ ),
+
+ TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay)
+);
+
+#endif /* _TRACE_HDA_INTEL_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 5c690cb873d4..6e9f57bbe667 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -95,7 +95,6 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack)
return jack;
- snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
jack = snd_array_new(&codec->jacktbl);
if (!jack)
return NULL;
@@ -122,6 +121,8 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
snd_array_free(&codec->jacktbl);
}
+#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
+
/* update the cached value and notification flag if needed */
static void jack_detect_update(struct hda_codec *codec,
struct hda_jack_tbl *jack)
@@ -134,7 +135,21 @@ static void jack_detect_update(struct hda_codec *codec,
else
jack->pin_sense = read_pin_sense(codec, jack->nid);
+ /* A gating jack indicates the jack is invalid if gating is unplugged */
+ if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack))
+ jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
+
jack->jack_dirty = 0;
+
+ /* If a jack is gated by this one update it. */
+ if (jack->gated_jack) {
+ struct hda_jack_tbl *gated =
+ snd_hda_jack_tbl_get(codec, jack->gated_jack);
+ if (gated) {
+ gated->jack_dirty = 1;
+ jack_detect_update(codec, gated);
+ }
+ }
}
/**
@@ -173,8 +188,6 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
}
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
-#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
-
/**
* snd_hda_jack_detect - query pin Presence Detect status
* @codec: the CODEC to sense
@@ -206,6 +219,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
jack->action = action;
if (cb)
jack->callback = cb;
+ if (codec->jackpoll_interval > 0)
+ return 0; /* No unsol if we're polling instead */
return snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | jack->tag);
@@ -220,16 +235,46 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
/**
+ * snd_hda_jack_set_gating_jack - Set gating jack.
+ *
+ * Indicates the gated jack is only valid when the gating jack is plugged.
+ */
+int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
+ hda_nid_t gating_nid)
+{
+ struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid);
+ struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid);
+
+ if (!gated || !gating)
+ return -EINVAL;
+
+ gated->gating_jack = gating_nid;
+ gating->gated_jack = gated_nid;
+
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack);
+
+/**
* snd_hda_jack_report_sync - sync the states of all jacks and report if changed
*/
void snd_hda_jack_report_sync(struct hda_codec *codec)
{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
+ struct hda_jack_tbl *jack;
int i, state;
+ /* update all jacks at first */
+ jack = codec->jacktbl.list;
for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid) {
+ if (jack->nid)
jack_detect_update(codec, jack);
+
+ /* report the updated jacks; it's done after updating all jacks
+ * to make sure that all gating jacks properly have been set
+ */
+ jack = codec->jacktbl.list;
+ for (i = 0; i < codec->jacktbl.used; i++, jack++)
+ if (jack->nid) {
if (!jack->kctl)
continue;
state = get_jack_plug_state(jack->pin_sense);
@@ -422,6 +467,19 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
+static void call_jack_callback(struct hda_codec *codec,
+ struct hda_jack_tbl *jack)
+{
+ if (jack->callback)
+ jack->callback(codec, jack);
+ if (jack->gated_jack) {
+ struct hda_jack_tbl *gated =
+ snd_hda_jack_tbl_get(codec, jack->gated_jack);
+ if (gated && gated->callback)
+ gated->callback(codec, gated);
+ }
+}
+
void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
{
struct hda_jack_tbl *event;
@@ -432,10 +490,29 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
return;
event->jack_dirty = 1;
- if (event->callback)
- event->callback(codec, event);
-
+ call_jack_callback(codec, event);
snd_hda_jack_report_sync(codec);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event);
+void snd_hda_jack_poll_all(struct hda_codec *codec)
+{
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i, changes = 0;
+
+ for (i = 0; i < codec->jacktbl.used; i++, jack++) {
+ unsigned int old_sense;
+ if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
+ continue;
+ old_sense = get_jack_plug_state(jack->pin_sense);
+ jack_detect_update(codec, jack);
+ if (old_sense == get_jack_plug_state(jack->pin_sense))
+ continue;
+ changes = 1;
+ call_jack_callback(codec, jack);
+ }
+ if (changes)
+ snd_hda_jack_report_sync(codec);
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all);
+
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index af8dd4724da5..ec12abd45263 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -28,6 +28,8 @@ struct hda_jack_tbl {
unsigned int jack_detect:1; /* capable of jack-detection? */
unsigned int jack_dirty:1; /* needs to update? */
unsigned int phantom_jack:1; /* a fixed, always present port? */
+ hda_nid_t gating_jack; /* valid when gating jack plugged */
+ hda_nid_t gated_jack; /* gated is dependent on this jack */
struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
#ifdef CONFIG_SND_HDA_INPUT_JACK
int type;
@@ -69,6 +71,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
unsigned char action,
hda_jack_callback cb);
+int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
+ hda_nid_t gating_nid);
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
@@ -84,4 +88,6 @@ void snd_hda_jack_report_sync(struct hda_codec *codec);
void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
+void snd_hda_jack_poll_all(struct hda_codec *codec);
+
#endif /* __SOUND_HDA_JACK_H */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 09dbdc37f781..4b40a5e7a8f5 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -240,9 +240,11 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
/*
* SPDIF I/O
*/
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
- hda_nid_t associated_nid,
- hda_nid_t cvt_nid);
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+ hda_nid_t associated_nid,
+ hda_nid_t cvt_nid, int type);
+#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
+ snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF)
int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
/*
@@ -599,6 +601,15 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
/*
+ * enum control helper
+ */
+int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo,
+ int num_entries, const char * const *texts);
+#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
+ snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)
+
+/*
* CEA Short Audio Descriptor data
*/
struct cea_sad {
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 1eeba7386666..89fc5030ec79 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -636,7 +636,6 @@ static void ad198x_free(struct hda_codec *codec)
if (!spec)
return;
- ad198x_shutup(codec);
ad198x_free_kctls(codec);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -1247,16 +1246,27 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
}
-static int patch_ad1986a(struct hda_codec *codec)
+static int alloc_ad_spec(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
+ if (!spec)
return -ENOMEM;
-
codec->spec = spec;
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+ return 0;
+}
+
+static int patch_ad1986a(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec;
+ int err, board_config;
+
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x19);
if (err < 0) {
@@ -1549,11 +1559,10 @@ static int patch_ad1983(struct hda_codec *codec)
struct ad198x_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) {
@@ -1955,11 +1964,10 @@ static int patch_ad1981(struct hda_codec *codec)
struct ad198x_spec *spec;
int err, board_config;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
+ err = alloc_ad_spec(codec);
+ if (err < 0)
return -ENOMEM;
-
- codec->spec = spec;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) {
@@ -2837,7 +2845,6 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls);
if (!knew)
return -ENOMEM;
@@ -3255,11 +3262,10 @@ static int patch_ad1988(struct hda_codec *codec)
struct ad198x_spec *spec;
int err, board_config;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
if (is_rev2(codec))
snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
@@ -3575,11 +3581,10 @@ static int patch_ad1884(struct hda_codec *codec)
struct ad198x_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) {
@@ -4575,11 +4580,10 @@ static int patch_ad1884a(struct hda_codec *codec)
struct ad198x_spec *spec;
int err, board_config;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) {
@@ -4988,11 +4992,10 @@ static int patch_ad1882(struct hda_codec *codec)
struct ad198x_spec *spec;
int err, board_config;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alloc_ad_spec(codec);
+ if (err < 0)
+ return err;
+ spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) {
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 3bcb67172358..a2537b2f8724 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -68,6 +68,7 @@ struct cs_spec {
unsigned int hp_detect:1;
unsigned int mic_detect:1;
+ unsigned int speaker_2_1:1;
/* CS421x */
unsigned int spdif_detect:1;
unsigned int sense_b:1;
@@ -84,7 +85,7 @@ enum {
CS420X_GPIO_13,
CS420X_GPIO_23,
CS420X_MBP101,
- CS420X_MBP101_COEF,
+ CS420X_MBP81,
CS420X_AUTO,
/* aliases */
CS420X_IMAC27_122 = CS420X_GPIO_23,
@@ -343,6 +344,9 @@ static int cs_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dac_nid[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
spec->multiout.max_channels;
+ if (spec->speaker_2_1)
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+ snd_pcm_2_1_chmaps;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = cs_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
spec->adc_nid[spec->cur_input];
@@ -443,6 +447,9 @@ static int parse_output(struct hda_codec *codec)
spec->multiout.dac_nids = spec->dac_nid;
spec->multiout.max_channels = i * 2;
+ if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && i == 2)
+ spec->speaker_2_1 = 1; /* assume 2.1 speakers */
+
/* add HP and speakers */
extra_nids = 0;
for (i = 0; i < cfg->hp_outs; i++) {
@@ -633,7 +640,9 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
index = idx;
break;
case AUTO_PIN_SPEAKER_OUT:
- if (num_ctls > 1)
+ if (spec->speaker_2_1)
+ name = idx ? "Bass Speaker" : "Speaker";
+ else if (num_ctls > 1)
name = speakers[idx];
else
name = "Speaker";
@@ -874,8 +883,9 @@ static int build_digital_output(struct hda_codec *codec)
if (!spec->multiout.dig_out_nid)
return 0;
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid,
- spec->multiout.dig_out_nid);
+ err = snd_hda_create_dig_out_ctls(codec, spec->multiout.dig_out_nid,
+ spec->multiout.dig_out_nid,
+ spec->pcm_rec[1].pcm_type);
if (err < 0)
return err;
err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
@@ -1079,9 +1089,6 @@ static void init_input(struct hda_codec *codec)
if (spec->mic_detect)
cs_automic(codec, NULL);
- coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
- cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
-
coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
if (is_active_pin(codec, CS_DMIC2_PIN_NID))
coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
@@ -1111,6 +1118,9 @@ static const struct hda_verb cs_coef_init_verbs[] = {
| 0x1000 /* Enable DACs High Pass Filter */
| 0x0400 /* Disable Coefficient Auto increment */
)},
+ /* ADC1/2 - Digital and Analog Soft Ramp */
+ {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
+ {0x11, AC_VERB_SET_PROC_COEF, 0x000a},
/* Beep */
{0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
{0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
@@ -1167,14 +1177,6 @@ static const struct hda_verb cs_errata_init_verbs[] = {
{} /* terminator */
};
-static const struct hda_verb mbp101_init_verbs[] = {
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0002},
- {0x11, AC_VERB_SET_PROC_COEF, 0x100a},
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0004},
- {0x11, AC_VERB_SET_PROC_COEF, 0x000f},
- {}
-};
-
/* SPDIF setup */
static void init_digital(struct hda_codec *codec)
{
@@ -1199,6 +1201,8 @@ static int cs_init(struct hda_codec *codec)
snd_hda_sequence_write(codec, cs_coef_init_verbs);
+ snd_hda_gen_apply_verbs(codec);
+
if (spec->gpio_mask) {
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
spec->gpio_mask);
@@ -1291,6 +1295,7 @@ static const struct hda_model_fixup cs420x_models[] = {
{ .id = CS420X_IMAC27_122, .name = "imac27_122" },
{ .id = CS420X_APPLE, .name = "apple" },
{ .id = CS420X_MBP101, .name = "mbp101" },
+ { .id = CS420X_MBP81, .name = "mbp81" },
{}
};
@@ -1303,6 +1308,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
/*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
/* codec SSID */
+ SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
@@ -1413,11 +1419,16 @@ static const struct hda_fixup cs420x_fixups[] = {
.type = HDA_FIXUP_PINS,
.v.pins = mbp101_pincfgs,
.chained = true,
- .chain_id = CS420X_MBP101_COEF,
+ .chain_id = CS420X_GPIO_13,
},
- [CS420X_MBP101_COEF] = {
+ [CS420X_MBP81] = {
.type = HDA_FIXUP_VERBS,
- .v.verbs = mbp101_init_verbs,
+ .v.verbs = (const struct hda_verb[]) {
+ /* internal mic ADC2: right only, single ended */
+ {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
+ {0x11, AC_VERB_SET_PROC_COEF, 0x102a},
+ {}
+ },
.chained = true,
.chain_id = CS420X_GPIO_13,
},
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 03b1dc317ff0..60890bfecc19 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -337,6 +337,8 @@ static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
},
};
+static bool is_2_1_speaker(struct conexant_spec *spec);
+
static int conexant_build_pcms(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -351,6 +353,9 @@ static int conexant_build_pcms(struct hda_codec *codec)
spec->multiout.max_channels;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
spec->multiout.dac_nids[0];
+ if (is_2_1_speaker(spec))
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+ snd_pcm_2_1_chmaps;
if (spec->capture_stream)
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
else {
@@ -472,7 +477,7 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = {
#endif
static const char * const slave_pfxs[] = {
- "Headphone", "Speaker", "Front", "Surround", "CLFE",
+ "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE",
NULL
};
@@ -3430,28 +3435,13 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct conexant_spec *spec = codec->spec;
- static const char * const texts2[] = {
- "Disabled", "Enabled"
- };
static const char * const texts3[] = {
"Disabled", "Speaker Only", "Line Out+Speaker"
};
- const char * const *texts;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- if (spec->automute_hp_lo) {
- uinfo->value.enumerated.items = 3;
- texts = texts3;
- } else {
- uinfo->value.enumerated.items = 2;
- texts = texts2;
- }
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
+ if (spec->automute_hp_lo)
+ return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
+ return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
}
static int cx_automute_mode_get(struct snd_kcontrol *kcontrol,
@@ -4116,11 +4106,26 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
return 0;
}
+static bool is_2_1_speaker(struct conexant_spec *spec)
+{
+ int i, type, num_spk = 0;
+
+ for (i = 0; i < spec->dac_info_filled; i++) {
+ type = spec->dac_info[i].type;
+ if (type == AUTO_PIN_LINE_OUT)
+ type = spec->autocfg.line_out_type;
+ if (type == AUTO_PIN_SPEAKER_OUT)
+ num_spk++;
+ }
+ return (num_spk == 2 && spec->autocfg.line_out_type != AUTO_PIN_LINE_OUT);
+}
+
static int cx_auto_build_output_controls(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
int i, err;
int num_line = 0, num_hp = 0, num_spk = 0;
+ bool speaker_2_1;
static const char * const texts[3] = { "Front", "Surround", "CLFE" };
if (spec->dac_info_filled == 1)
@@ -4128,6 +4133,8 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
spec->dac_info[0].pin,
"Master", 0);
+ speaker_2_1 = is_2_1_speaker(spec);
+
for (i = 0; i < spec->dac_info_filled; i++) {
const char *label;
int idx, type;
@@ -4146,8 +4153,13 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
idx = num_hp++;
break;
case AUTO_PIN_SPEAKER_OUT:
- label = "Speaker";
- idx = num_spk++;
+ if (speaker_2_1) {
+ label = num_spk++ ? "Bass Speaker" : "Speaker";
+ idx = 0;
+ } else {
+ label = "Speaker";
+ idx = num_spk++;
+ }
break;
}
err = try_add_pb_volume(codec, dac,
@@ -4405,7 +4417,10 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
enum {
CXT_PINCFG_LENOVO_X200,
CXT_PINCFG_LENOVO_TP410,
+ CXT_PINCFG_LEMOTE_A1004,
+ CXT_PINCFG_LEMOTE_A1205,
CXT_FIXUP_STEREO_DMIC,
+ CXT_FIXUP_INC_MIC_BOOST,
};
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
@@ -4415,6 +4430,19 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
spec->fixup_stereo_dmic = 1;
}
+static void cxt5066_increase_mic_boost(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action != HDA_FIXUP_ACT_PRE_PROBE)
+ return;
+
+ snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT,
+ (0x3 << AC_AMPCAP_OFFSET_SHIFT) |
+ (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+ (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+ (0 << AC_AMPCAP_MUTE_SHIFT));
+}
+
/* ThinkPad X200 & co with cxt5051 */
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -4432,6 +4460,18 @@ static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
{}
};
+/* Lemote A1004/A1205 with cxt5066 */
+static const struct hda_pintbl cxt_pincfg_lemote[] = {
+ { 0x1a, 0x90a10020 }, /* Internal mic */
+ { 0x1b, 0x03a11020 }, /* External mic */
+ { 0x1d, 0x400101f0 }, /* Not used */
+ { 0x1e, 0x40a701f0 }, /* Not used */
+ { 0x20, 0x404501f0 }, /* Not used */
+ { 0x22, 0x404401f0 }, /* Not used */
+ { 0x23, 0x40a701f0 }, /* Not used */
+ {}
+};
+
static const struct hda_fixup cxt_fixups[] = {
[CXT_PINCFG_LENOVO_X200] = {
.type = HDA_FIXUP_PINS,
@@ -4441,10 +4481,24 @@ static const struct hda_fixup cxt_fixups[] = {
.type = HDA_FIXUP_PINS,
.v.pins = cxt_pincfg_lenovo_tp410,
},
+ [CXT_PINCFG_LEMOTE_A1004] = {
+ .type = HDA_FIXUP_PINS,
+ .chained = true,
+ .chain_id = CXT_FIXUP_INC_MIC_BOOST,
+ .v.pins = cxt_pincfg_lemote,
+ },
+ [CXT_PINCFG_LEMOTE_A1205] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cxt_pincfg_lemote,
+ },
[CXT_FIXUP_STEREO_DMIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_stereo_dmic,
},
+ [CXT_FIXUP_INC_MIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cxt5066_increase_mic_boost,
+ },
};
static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4453,6 +4507,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
};
static const struct snd_pci_quirk cxt5066_fixups[] = {
+ SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
@@ -4461,6 +4516,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
+ SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
{}
};
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 71555cc54db1..0fcfa6f406b8 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1193,12 +1193,11 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
struct hdmi_spec_per_pin *per_pin;
int err;
- caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP);
+ caps = snd_hda_query_pin_caps(codec, pin_nid);
if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
return 0;
- config = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ config = snd_hda_codec_get_pincfg(codec, pin_nid);
if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
return 0;
@@ -1272,7 +1271,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
unsigned int caps;
unsigned int type;
- caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ caps = get_wcaps(codec, nid);
type = get_wcaps_type(caps);
if (!(caps & AC_WCAP_DIGITAL))
@@ -1288,13 +1287,17 @@ 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.
*/
-#ifdef CONFIG_PM
- if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+ else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
AC_PWRST_EPSS))
codec->bus->power_keep_link_on = 1;
#endif
@@ -1589,9 +1592,10 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
- err = snd_hda_create_spdif_out_ctls(codec,
- per_pin->pin_nid,
- per_pin->mux_nids[0]);
+ err = snd_hda_create_dig_out_ctls(codec,
+ per_pin->pin_nid,
+ per_pin->mux_nids[0],
+ HDA_PCM_TYPE_HDMI);
if (err < 0)
return err;
snd_hda_spdif_ctls_unassign(codec, pin_idx);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ad68d223f8af..7743775f6abb 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -153,8 +153,8 @@ struct alc_spec {
const struct hda_channel_mode *channel_mode;
int num_channel_mode;
int need_dac_fix;
- int const_channel_count;
- int ext_channel_count;
+ int const_channel_count; /* min. channel count (for speakers) */
+ int ext_channel_count; /* current channel count for multi-io */
/* PCM information */
struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
@@ -815,28 +815,13 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- static const char * const texts2[] = {
- "Disabled", "Enabled"
- };
static const char * const texts3[] = {
"Disabled", "Speaker Only", "Line Out+Speaker"
};
- const char * const *texts;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- if (spec->automute_speaker_possible && spec->automute_lo_possible) {
- uinfo->value.enumerated.items = 3;
- texts = texts3;
- } else {
- uinfo->value.enumerated.items = 2;
- texts = texts2;
- }
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
+ if (spec->automute_speaker_possible && spec->automute_lo_possible)
+ return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
+ return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
}
static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
@@ -903,23 +888,25 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = {
.put = alc_automute_mode_put,
};
-static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+static struct snd_kcontrol_new *
+alc_kcontrol_new(struct alc_spec *spec, const char *name,
+ const struct snd_kcontrol_new *temp)
{
- snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
- return snd_array_new(&spec->kctls);
+ struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return NULL;
+ *knew = *temp;
+ knew->name = kstrdup(name, GFP_KERNEL);
+ if (!knew->name)
+ return NULL;
+ return knew;
}
static int alc_add_automute_mode_enum(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- struct snd_kcontrol_new *knew;
- knew = alc_kcontrol_new(spec);
- if (!knew)
- return -ENOMEM;
- *knew = alc_automute_mode_enum;
- knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
- if (!knew->name)
+ if (!alc_kcontrol_new(spec, "Auto-Mute Mode", &alc_automute_mode_enum))
return -ENOMEM;
return 0;
}
@@ -928,12 +915,12 @@ static int alc_add_automute_mode_enum(struct hda_codec *codec)
* Check the availability of HP/line-out auto-mute;
* Set up appropriately if really supported
*/
-static void alc_init_automute(struct hda_codec *codec)
+static int alc_init_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
int present = 0;
- int i;
+ int i, err;
if (cfg->hp_pins[0])
present++;
@@ -942,7 +929,7 @@ static void alc_init_automute(struct hda_codec *codec)
if (cfg->speaker_pins[0])
present++;
if (present < 2) /* need two different output types */
- return;
+ return 0;
if (!cfg->speaker_pins[0] &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
@@ -992,9 +979,13 @@ static void alc_init_automute(struct hda_codec *codec)
spec->automute_lo = spec->automute_lo_possible;
spec->automute_speaker = spec->automute_speaker_possible;
- if (spec->automute_speaker_possible || spec->automute_lo_possible)
+ if (spec->automute_speaker_possible || spec->automute_lo_possible) {
/* create a control for automute mode */
- alc_add_automute_mode_enum(codec);
+ err = alc_add_automute_mode_enum(codec);
+ if (err < 0)
+ return err;
+ }
+ return 0;
}
/* return the position of NID in the list, or -1 if not found */
@@ -1094,7 +1085,7 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec)
* Check the availability of auto-mic switch;
* Set up if really supported
*/
-static void alc_init_auto_mic(struct hda_codec *codec)
+static int alc_init_auto_mic(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -1102,7 +1093,7 @@ static void alc_init_auto_mic(struct hda_codec *codec)
int i;
if (spec->shared_mic_hp)
- return; /* no auto-mic for the shared I/O */
+ return 0; /* no auto-mic for the shared I/O */
spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
@@ -1114,25 +1105,25 @@ static void alc_init_auto_mic(struct hda_codec *codec)
switch (snd_hda_get_input_pin_attr(defcfg)) {
case INPUT_PIN_ATTR_INT:
if (fixed)
- return; /* already occupied */
+ return 0; /* already occupied */
if (cfg->inputs[i].type != AUTO_PIN_MIC)
- return; /* invalid type */
+ return 0; /* invalid type */
fixed = nid;
break;
case INPUT_PIN_ATTR_UNUSED:
- return; /* invalid entry */
+ return 0; /* invalid entry */
case INPUT_PIN_ATTR_DOCK:
if (dock)
- return; /* already occupied */
+ return 0; /* already occupied */
if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
- return; /* invalid type */
+ return 0; /* invalid type */
dock = nid;
break;
default:
if (ext)
- return; /* already occupied */
+ return 0; /* already occupied */
if (cfg->inputs[i].type != AUTO_PIN_MIC)
- return; /* invalid type */
+ return 0; /* invalid type */
ext = nid;
break;
}
@@ -1142,11 +1133,11 @@ static void alc_init_auto_mic(struct hda_codec *codec)
dock = 0;
}
if (!ext || !fixed)
- return;
+ return 0;
if (!is_jack_detectable(codec, ext))
- return; /* no unsol support */
+ return 0; /* no unsol support */
if (dock && !is_jack_detectable(codec, dock))
- return; /* no unsol support */
+ return 0; /* no unsol support */
/* check imux indices */
spec->ext_mic_pin = ext;
@@ -1155,17 +1146,26 @@ static void alc_init_auto_mic(struct hda_codec *codec)
spec->auto_mic = 1;
if (!alc_auto_mic_check_imux(codec))
- return;
+ return 0;
snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
ext, fixed, dock);
+
+ return 0;
}
/* check the availabilities of auto-mute and auto-mic switches */
-static void alc_auto_check_switches(struct hda_codec *codec)
+static int alc_auto_check_switches(struct hda_codec *codec)
{
- alc_init_automute(codec);
- alc_init_auto_mic(codec);
+ int err;
+
+ err = alc_init_automute(codec);
+ if (err < 0)
+ return err;
+ err = alc_init_auto_mic(codec);
+ if (err < 0)
+ return err;
+ return 0;
}
/*
@@ -1757,12 +1757,9 @@ static const struct snd_kcontrol_new alc_inv_dmic_sw = {
static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid)
{
struct alc_spec *spec = codec->spec;
- struct snd_kcontrol_new *knew = alc_kcontrol_new(spec);
- if (!knew)
- return -ENOMEM;
- *knew = alc_inv_dmic_sw;
- knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL);
- if (!knew->name)
+
+ if (!alc_kcontrol_new(spec, "Inverted Internal Mic Capture Switch",
+ &alc_inv_dmic_sw))
return -ENOMEM;
spec->inv_dmic_fixup = 1;
spec->inv_dmic_muted = 0;
@@ -1836,9 +1833,10 @@ static int __alc_build_controls(struct hda_codec *codec)
return err;
}
if (spec->multiout.dig_out_nid) {
- err = snd_hda_create_spdif_out_ctls(codec,
- spec->multiout.dig_out_nid,
- spec->multiout.dig_out_nid);
+ err = snd_hda_create_dig_out_ctls(codec,
+ spec->multiout.dig_out_nid,
+ spec->multiout.dig_out_nid,
+ spec->pcm_rec[1].pcm_type);
if (err < 0)
return err;
if (!spec->no_analog) {
@@ -2259,6 +2257,10 @@ static int alc_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
spec->multiout.max_channels;
+ if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
+ spec->autocfg.line_outs == 2)
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+ snd_pcm_2_1_chmaps;
}
if (spec->adc_nids) {
p = spec->stream_analog_capture;
@@ -2399,7 +2401,6 @@ static void alc_free(struct hda_codec *codec)
if (!spec)
return;
- alc_shutup(codec);
alc_free_kctls(codec);
alc_free_bind_ctls(codec);
snd_hda_gen_free(&spec->gen);
@@ -2534,13 +2535,9 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- knew = alc_kcontrol_new(spec);
+ knew = alc_kcontrol_new(spec, name, &alc_control_templates[type]);
if (!knew)
return -ENOMEM;
- *knew = alc_control_templates[type];
- knew->name = kstrdup(name, GFP_KERNEL);
- if (!knew->name)
- return -ENOMEM;
knew->index = cidx;
if (get_amp_nid_(val))
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
@@ -3601,7 +3598,6 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
{
struct alc_spec *spec = codec->spec;
struct hda_bind_ctls **ctlp, *ctl;
- snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
ctlp = snd_array_new(&spec->bind_ctls);
if (!ctlp)
return NULL;
@@ -3965,8 +3961,9 @@ static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
spec->ext_channel_count = (ch + 1) * 2;
for (i = 0; i < spec->multi_ios; i++)
alc_set_multi_io(codec, i, i < ch);
- spec->multiout.max_channels = spec->ext_channel_count;
- if (spec->need_dac_fix && !spec->const_channel_count)
+ spec->multiout.max_channels = max(spec->ext_channel_count,
+ spec->const_channel_count);
+ if (spec->need_dac_fix)
spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return 1;
}
@@ -3984,14 +3981,8 @@ static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
if (spec->multi_ios > 0) {
- struct snd_kcontrol_new *knew;
-
- knew = alc_kcontrol_new(spec);
- if (!knew)
- return -ENOMEM;
- *knew = alc_auto_channel_mode_enum;
- knew->name = kstrdup("Channel Mode", GFP_KERNEL);
- if (!knew->name)
+ if (!alc_kcontrol_new(spec, "Channel Mode",
+ &alc_auto_channel_mode_enum))
return -ENOMEM;
}
return 0;
@@ -4334,7 +4325,17 @@ static int alc_parse_auto_config(struct hda_codec *codec,
if (err < 0)
return err;
- spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+ /* check the multiple speaker pins */
+ if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+ spec->const_channel_count = cfg->line_outs * 2;
+ else
+ spec->const_channel_count = cfg->speaker_outs * 2;
+
+ if (spec->multi_ios > 0)
+ spec->multiout.max_channels = max(spec->ext_channel_count,
+ spec->const_channel_count);
+ else
+ spec->multiout.max_channels = spec->multiout.num_dacs * 2;
dig_only:
alc_auto_parse_digital(codec);
@@ -4346,7 +4347,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
alc_ssid_check(codec, ssid_nids);
if (!spec->no_analog) {
- alc_auto_check_switches(codec);
+ err = alc_auto_check_switches(codec);
+ if (err < 0)
+ return err;
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
@@ -4372,6 +4375,8 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
codec->spec = spec;
spec->mixer_nid = mixer_nid;
snd_hda_gen_init(&spec->gen);
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+ snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8);
err = alc_codec_rename_from_preset(codec);
if (err < 0) {
@@ -6009,6 +6014,16 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec,
}
}
+static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
+ const struct alc_fixup *fix,
+ int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (action == ALC_FIXUP_ACT_PROBE)
+ snd_hda_jack_set_gating_jack(codec, spec->ext_mic_pin,
+ spec->autocfg.hp_pins[0]);
+}
enum {
ALC269_FIXUP_SONY_VAIO,
@@ -6031,6 +6046,8 @@ enum {
ALC269_FIXUP_INV_DMIC,
ALC269_FIXUP_LENOVO_DOCK,
ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
+ ALC271_FIXUP_AMIC_MIC2,
+ ALC271_FIXUP_HP_GATE_MIC_JACK,
};
static const struct alc_fixup alc269_fixups[] = {
@@ -6175,6 +6192,22 @@ static const struct alc_fixup alc269_fixups[] = {
.type = ALC_FIXUP_FUNC,
.v.func = alc269_fixup_pincfg_no_hp_to_lineout,
},
+ [ALC271_FIXUP_AMIC_MIC2] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x19, 0x01a19c20 }, /* mic */
+ { 0x1b, 0x99a7012f }, /* int-mic */
+ { 0x21, 0x0121401f }, /* HP out */
+ { }
+ },
+ },
+ [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc271_hp_gate_mic_jack,
+ .chained = true,
+ .chain_id = ALC271_FIXUP_AMIC_MIC2,
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6195,6 +6228,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+ 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(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9ba8af056170..df13c0f84899 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1081,7 +1081,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {
static const char * const slave_pfxs[] = {
"Front", "Surround", "Center", "LFE", "Side",
- "Headphone", "Speaker", "IEC958", "PCM",
+ "Headphone", "Speaker", "Bass Speaker", "IEC958", "PCM",
NULL
};
@@ -1136,9 +1136,10 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
if (spec->multiout.dig_out_nid) {
- err = snd_hda_create_spdif_out_ctls(codec,
- spec->multiout.dig_out_nid,
- spec->multiout.dig_out_nid);
+ err = snd_hda_create_dig_out_ctls(codec,
+ spec->multiout.dig_out_nid,
+ spec->multiout.dig_out_nid,
+ spec->autocfg.dig_out_type[0]);
if (err < 0)
return err;
err = snd_hda_create_spdif_share_sw(codec,
@@ -2515,6 +2516,11 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
spec->multiout.dac_nids[0];
+ if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
+ spec->autocfg.line_outs == 2)
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+ snd_pcm_2_1_chmaps;
+
info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs;
@@ -2805,7 +2811,6 @@ stac_control_new(struct sigmatel_spec *spec,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls);
if (!knew)
return NULL;
@@ -3268,9 +3273,9 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
idx = i;
break;
case AUTO_PIN_SPEAKER_OUT:
- if (num_outs <= 1) {
- name = "Speaker";
- idx = i;
+ if (num_outs <= 2) {
+ name = i ? "Bass Speaker" : "Speaker";
+ idx = 0;
break;
}
/* Fall through in case of multi speaker outs */
@@ -4569,8 +4574,6 @@ static void stac92xx_free(struct hda_codec *codec)
if (! spec)
return;
- stac92xx_shutup(codec);
-
kfree(spec);
snd_hda_detach_beep_device(codec);
}
@@ -5155,20 +5158,34 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
.reboot_notify = stac92xx_shutup,
};
+static int alloc_stac_spec(struct hda_codec *codec, int num_pins,
+ const hda_nid_t *pin_nids)
+{
+ struct sigmatel_spec *spec;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return -ENOMEM;
+ codec->spec = spec;
+ codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
+ spec->num_pins = num_pins;
+ spec->pin_nids = pin_nids;
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+ return 0;
+}
+
static int patch_stac9200(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids),
+ stac9200_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 1;
- spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
- spec->pin_nids = stac9200_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models,
stac9200_cfg_tbl);
@@ -5224,15 +5241,13 @@ static int patch_stac925x(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids),
+ stac925x_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 1;
- spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
- spec->pin_nids = stac925x_pin_nids;
/* Check first for codec ID */
spec->board_config = snd_hda_check_board_codec_sid_config(codec,
@@ -5307,19 +5322,17 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
hda_nid_t conn[STAC92HD73_DAC_COUNT + 2];
- int err = 0;
+ int err;
int num_dacs;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids),
+ stac92hd73xx_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 0;
codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
- spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
- spec->pin_nids = stac92hd73xx_pin_nids;
spec->board_config = snd_hda_check_board_config(codec,
STAC_92HD73XX_MODELS,
stac92hd73xx_models,
@@ -5596,9 +5609,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
int default_polarity = -1; /* no default cfg */
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */
+ if (err < 0)
+ return err;
if (hp_bnb2011_with_dock(codec)) {
snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f);
@@ -5606,11 +5619,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
}
codec->epss = 0; /* longer delay needed for D3 */
- codec->no_trigger_sense = 1;
- codec->spec = spec;
-
stac92hd8x_fill_auto_spec(codec);
+ spec = codec->spec;
spec->linear_tone_beep = 0;
codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
spec->digbeep_nid = 0x21;
@@ -5779,21 +5790,19 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
struct sigmatel_spec *spec;
const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
unsigned int pin_cfg;
- int err = 0;
+ int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS,
+ stac92hd71bxx_pin_nids_4port);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 0;
codec->patch_ops = stac92xx_patch_ops;
- spec->num_pins = STAC92HD71BXX_NUM_PINS;
switch (codec->vendor_id) {
case 0x111d76b6:
case 0x111d76b7:
- spec->pin_nids = stac92hd71bxx_pin_nids_4port;
break;
case 0x111d7603:
case 0x111d7608:
@@ -6024,15 +6033,13 @@ static int patch_stac922x(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids),
+ stac922x_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 1;
- spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
- spec->pin_nids = stac922x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
stac922x_models,
stac922x_cfg_tbl);
@@ -6129,16 +6136,14 @@ static int patch_stac927x(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids),
+ stac927x_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 1;
codec->slave_dig_outs = stac927x_slave_dig_outs;
- spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
- spec->pin_nids = stac927x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
stac927x_models,
stac927x_cfg_tbl);
@@ -6265,15 +6270,13 @@ static int patch_stac9205(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids),
+ stac9205_pin_nids);
+ if (err < 0)
+ return err;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ spec = codec->spec;
spec->linear_tone_beep = 1;
- spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
- spec->pin_nids = stac9205_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
stac9205_models,
stac9205_cfg_tbl);
@@ -6421,14 +6424,13 @@ static int patch_stac9872(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
- codec->no_trigger_sense = 1;
- codec->spec = spec;
+ err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids),
+ stac9872_pin_nids);
+ if (err < 0)
+ return err;
+
+ spec = codec->spec;
spec->linear_tone_beep = 1;
- spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
- spec->pin_nids = stac9872_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
stac9872_models,
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 019e1a00414a..09bb64996d72 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -76,6 +76,8 @@ enum VIA_HDA_CODEC {
VT2002P,
VT1812,
VT1802,
+ VT1705CF,
+ VT1808,
CODEC_TYPES,
};
@@ -220,6 +222,7 @@ struct via_spec {
int vt1708_hp_present;
void (*set_widgets_power_state)(struct hda_codec *codec);
+ unsigned int dac_stream_tag[4];
struct hda_loopback_check loopback;
int num_loopbacks;
@@ -241,6 +244,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
if (spec == NULL)
return NULL;
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
mutex_init(&spec->config_mutex);
codec->spec = spec;
spec->codec = codec;
@@ -295,6 +299,10 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
codec_type = VT1708S;
else if ((dev_id & 0xfff) == 0x446)
codec_type = VT1802;
+ else if (dev_id == 0x4760)
+ codec_type = VT1705CF;
+ else if (dev_id == 0x4761 || dev_id == 0x4762)
+ codec_type = VT1808;
else
codec_type = UNKNOWN;
return codec_type;
@@ -387,7 +395,6 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls);
if (!knew)
return NULL;
@@ -711,6 +718,28 @@ static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
}
+static void update_conv_power_state(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int parm, unsigned int index)
+{
+ struct via_spec *spec = codec->spec;
+ unsigned int format;
+ if (snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_POWER_STATE, 0) == parm)
+ return;
+ format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+ if (format && (spec->dac_stream_tag[index] != format))
+ spec->dac_stream_tag[index] = format;
+
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (parm == AC_PWRST_D0) {
+ format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+ if (!format && (spec->dac_stream_tag[index] != format))
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CHANNEL_STREAMID,
+ spec->dac_stream_tag[index]);
+ }
+}
+
static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int *affected_parm)
{
@@ -739,18 +768,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static const char * const texts[] = {
- "Disabled", "Enabled"
- };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
+ return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
}
static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
@@ -1096,6 +1114,11 @@ static void __analog_low_current_mode(struct hda_codec *codec, bool force)
verb = 0xf93;
parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
break;
+ case VT1705CF:
+ case VT1808:
+ verb = 0xf82;
+ parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
+ break;
default:
return; /* other codecs are not supported */
}
@@ -1454,7 +1477,7 @@ static const struct hda_pcm_stream via_pcm_digital_capture = {
*/
static const char * const via_slave_pfxs[] = {
"Front", "Surround", "Center", "LFE", "Side",
- "Headphone", "Speaker",
+ "Headphone", "Speaker", "Bass Speaker",
NULL,
};
@@ -1555,6 +1578,10 @@ static int via_build_pcms(struct hda_codec *codec)
spec->multiout.dac_nids[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
spec->multiout.max_channels;
+ if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT
+ && spec->autocfg.line_outs == 2)
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+ snd_pcm_2_1_chmaps;
}
if (!spec->stream_analog_capture) {
@@ -1934,7 +1961,7 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg;
struct nid_path *path;
static const char * const chname[4] = {
- "Front", "Surround", "C/LFE", "Side"
+ "Front", "Surround", NULL /* "CLFE" */, "Side"
};
int i, idx, err;
int old_line_outs;
@@ -1969,8 +1996,8 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
} else {
const char *pfx = chname[i];
if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
- cfg->line_outs == 1)
- pfx = "Speaker";
+ cfg->line_outs <= 2)
+ pfx = i ? "Bass Speaker" : "Speaker";
err = create_ch_ctls(codec, pfx, 3, true, path);
if (err < 0)
return err;
@@ -3824,6 +3851,125 @@ static int patch_vt1812(struct hda_codec *codec)
return 0;
}
+/* patch for vt3476 */
+
+static const struct hda_verb vt3476_init_verbs[] = {
+ /* Enable DMic 8/16/32K */
+ {0x1, 0xF7B, 0x30},
+ /* Enable Boost Volume backdoor */
+ {0x1, 0xFB9, 0x20},
+ /* Enable AOW-MW9 path */
+ {0x1, 0xFB8, 0x10},
+ { }
+};
+
+static void set_widgets_power_state_vt3476(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm, parm2;
+ /* MUX10 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
+
+ /* outputs */
+ /* PW3 (27h), MW3(37h), AOW3 (bh) */
+ if (spec->codec_type == VT1705CF) {
+ parm = AC_PWRST_D3;
+ update_power_state(codec, 0x27, parm);
+ update_power_state(codec, 0x37, parm);
+ } else {
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x27, &parm);
+ update_power_state(codec, 0x37, parm);
+ }
+
+ /* PW2 (26h), MW2(36h), AOW2 (ah) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x26, &parm);
+ update_power_state(codec, 0x36, parm);
+ if (spec->smart51_enabled) {
+ /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
+ set_pin_power_state(codec, 0x2b, &parm);
+ update_power_state(codec, 0x3b, parm);
+ update_power_state(codec, 0x1b, parm);
+ }
+ update_conv_power_state(codec, 0xa, parm, 2);
+
+ /* PW1 (25h), MW1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ update_power_state(codec, 0x35, parm);
+ if (spec->smart51_enabled) {
+ /* PW6(2ah), MW6(3ah), MUX6(1ah) */
+ set_pin_power_state(codec, 0x2a, &parm);
+ update_power_state(codec, 0x3a, parm);
+ update_power_state(codec, 0x1a, parm);
+ }
+ update_conv_power_state(codec, 0x9, parm, 1);
+
+ /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ update_power_state(codec, 0x38, parm);
+ update_power_state(codec, 0x18, parm);
+ if (spec->hp_independent_mode)
+ update_conv_power_state(codec, 0xb, parm, 3);
+ parm2 = parm; /* for pin 0x0b */
+
+ /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ update_power_state(codec, 0x34, parm);
+ if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3)
+ parm = parm2;
+ update_conv_power_state(codec, 0x8, parm, 0);
+ /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
+ update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
+}
+
+static int patch_vt3476(struct hda_codec *codec)
+{
+ struct via_spec *spec;
+ int err;
+
+ /* create a codec specific record */
+ spec = via_new_spec(codec);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ spec->aa_mix_nid = 0x3f;
+ add_secret_dac_path(codec);
+
+ /* automatic parse from the BIOS config */
+ err = via_parse_auto_config(codec);
+ if (err < 0) {
+ via_free(codec);
+ return err;
+ }
+
+ spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
+
+ codec->patch_ops = via_patch_ops;
+
+ spec->set_widgets_power_state = set_widgets_power_state_vt3476;
+
+ return 0;
+}
+
/*
* patch entries
*/
@@ -3917,6 +4063,12 @@ static const struct hda_codec_preset snd_hda_preset_via[] = {
.patch = patch_vt2002P},
{ .id = 0x11068446, .name = "VT1802",
.patch = patch_vt2002P},
+ { .id = 0x11064760, .name = "VT1705CF",
+ .patch = patch_vt3476},
+ { .id = 0x11064761, .name = "VT1708SCE",
+ .patch = patch_vt3476},
+ { .id = 0x11064762, .name = "VT1808",
+ .patch = patch_vt3476},
{} /* terminator */
};
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index f7ce33f00ea5..7e50c1324556 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
snd-ice17xx-ak4xxx-objs := ak4xxx.o
snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o psc724.o wm8766.o wm8776.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index e525da2673be..2f9b93467867 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -21,7 +21,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -38,7 +37,7 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
}
-static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
+static int snd_vt1724_amp_init(struct snd_ice1712 *ice)
{
static const unsigned short wm_inits[] = {
WM_ATTEN_L, 0x0000, /* 0 db */
@@ -66,7 +65,7 @@ static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
{
if (ice->ac97)
/* we use pins 39 and 41 of the VT1616 for left and right
@@ -78,7 +77,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_amp_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_AV710,
.name = "Chaintech AV-710",
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 20bcddea2eab..55902ec40344 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -46,7 +46,6 @@
* on mixer switch and other coll stuff.
*/
-#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -203,7 +202,8 @@ static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+ static const char * const texts[3] =
+ {"Internal Aux", "Wavetable", "Rear Line-In"};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1433,7 +1433,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
* mixers
*/
-static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new aureon_dac_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -1548,7 +1548,7 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
}
};
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
@@ -1614,7 +1614,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
}
};
-static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new ac97_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 Playback Switch",
@@ -1719,7 +1719,7 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
}
};
-static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new universe_ac97_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 Playback Switch",
@@ -1851,7 +1851,7 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
};
-static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
+static struct snd_kcontrol_new cs8415_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
@@ -1896,7 +1896,7 @@ static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
}
};
-static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
+static int aureon_add_controls(struct snd_ice1712 *ice)
{
unsigned int i, counts;
int err;
@@ -2124,7 +2124,7 @@ static int aureon_resume(struct snd_ice1712 *ice)
/*
* initialize the chip
*/
-static int __devinit aureon_init(struct snd_ice1712 *ice)
+static int aureon_init(struct snd_ice1712 *ice)
{
struct aureon_spec *spec;
int i, err;
@@ -2174,7 +2174,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
* hence the driver needs to sets up it properly.
*/
-static unsigned char aureon51_eeprom[] __devinitdata = {
+static unsigned char aureon51_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
@@ -2190,7 +2190,7 @@ static unsigned char aureon51_eeprom[] __devinitdata = {
[ICE_EEP2_GPIO_STATE2] = 0x00,
};
-static unsigned char aureon71_eeprom[] __devinitdata = {
+static unsigned char aureon71_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
@@ -2207,7 +2207,7 @@ static unsigned char aureon71_eeprom[] __devinitdata = {
};
#define prodigy71_eeprom aureon71_eeprom
-static unsigned char aureon71_universe_eeprom[] __devinitdata = {
+static unsigned char aureon71_universe_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC,
* 4DACs
*/
@@ -2225,7 +2225,7 @@ static unsigned char aureon71_universe_eeprom[] __devinitdata = {
[ICE_EEP2_GPIO_STATE2] = 0x00,
};
-static unsigned char prodigy71lt_eeprom[] __devinitdata = {
+static unsigned char prodigy71lt_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
@@ -2243,7 +2243,7 @@ static unsigned char prodigy71lt_eeprom[] __devinitdata = {
#define prodigy71xt_eeprom prodigy71lt_eeprom
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
.name = "Terratec Aureon 5.1-Sky",
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index 20c6b079d0df..9e28cc12969b 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -22,7 +22,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -432,7 +431,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status =
{
.access = (SNDRV_CTL_ELEM_ACCESS_READ),
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -445,7 +444,7 @@ static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devini
* initialize the chips on M-Audio cards
*/
-static struct snd_akm4xxx akm_audiophile __devinitdata = {
+static struct snd_akm4xxx akm_audiophile = {
.type = SND_AK4528,
.num_adcs = 2,
.num_dacs = 2,
@@ -454,7 +453,7 @@ static struct snd_akm4xxx akm_audiophile __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_audiophile_priv = {
.caddr = 2,
.cif = 0,
.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -466,7 +465,7 @@ static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_delta410 __devinitdata = {
+static struct snd_akm4xxx akm_delta410 = {
.type = SND_AK4529,
.num_adcs = 2,
.num_dacs = 8,
@@ -475,7 +474,7 @@ static struct snd_akm4xxx akm_delta410 __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta410_priv = {
.caddr = 0,
.cif = 0,
.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -487,7 +486,7 @@ static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
+static struct snd_akm4xxx akm_delta1010lt = {
.type = SND_AK4524,
.num_adcs = 8,
.num_dacs = 8,
@@ -497,7 +496,7 @@ static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta1010lt_priv = {
.caddr = 2,
.cif = 0, /* the default level of the CIF pin from AK4524 */
.data_mask = ICE1712_DELTA_1010LT_DOUT,
@@ -509,7 +508,7 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_delta66e __devinitdata = {
+static struct snd_akm4xxx akm_delta66e = {
.type = SND_AK4524,
.num_adcs = 4,
.num_dacs = 4,
@@ -519,7 +518,7 @@ static struct snd_akm4xxx akm_delta66e __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta66e_priv = {
.caddr = 2,
.cif = 0, /* the default level of the CIF pin from AK4524 */
.data_mask = ICE1712_DELTA_66E_DOUT,
@@ -532,7 +531,7 @@ static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
};
-static struct snd_akm4xxx akm_delta44 __devinitdata = {
+static struct snd_akm4xxx akm_delta44 = {
.type = SND_AK4524,
.num_adcs = 4,
.num_dacs = 4,
@@ -542,7 +541,7 @@ static struct snd_akm4xxx akm_delta44 __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta44_priv = {
.caddr = 2,
.cif = 0, /* the default level of the CIF pin from AK4524 */
.data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
@@ -554,7 +553,7 @@ static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_vx442 __devinitdata = {
+static struct snd_akm4xxx akm_vx442 = {
.type = SND_AK4524,
.num_adcs = 4,
.num_dacs = 4,
@@ -564,7 +563,7 @@ static struct snd_akm4xxx akm_vx442 __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_vx442_priv = {
.caddr = 2,
.cif = 0,
.data_mask = ICE1712_VX442_DOUT,
@@ -576,7 +575,7 @@ static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
.mask_flags = 0,
};
-static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+static int snd_ice1712_delta_init(struct snd_ice1712 *ice)
{
int err;
struct snd_akm4xxx *ak;
@@ -617,7 +616,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
ice->num_total_dacs = 4; /* two AK4324 codecs */
break;
case ICE1712_SUBDEVICE_VX442:
- case ICE1712_SUBDEVICE_DELTA66E: /* omni not suported yet */
+ case ICE1712_SUBDEVICE_DELTA66E: /* omni not supported yet */
ice->num_total_dacs = 4;
ice->num_total_adcs = 4;
break;
@@ -714,19 +713,19 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
* additional controls for M-Audio cards
*/
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
{
int err;
@@ -802,7 +801,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
/* entry point */
-struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_delta_cards[] = {
{
.subvendor = ICE1712_SUBDEVICE_DELTA1010,
.name = "M Audio Delta 1010",
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 6fe35b812040..bc2e7011c55d 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -22,7 +22,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -344,7 +343,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
/*
*/
-static struct snd_akm4xxx akm_ews88mt __devinitdata = {
+static struct snd_akm4xxx akm_ews88mt = {
.num_adcs = 8,
.num_dacs = 8,
.type = SND_AK4524,
@@ -354,7 +353,7 @@ static struct snd_akm4xxx akm_ews88mt __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ews88mt_priv = {
.caddr = 2,
.cif = 1, /* CIF high */
.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -366,7 +365,7 @@ static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
+static struct snd_akm4xxx akm_ewx2496 = {
.num_adcs = 2,
.num_dacs = 2,
.type = SND_AK4524,
@@ -375,7 +374,7 @@ static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ewx2496_priv = {
.caddr = 2,
.cif = 1, /* CIF high */
.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -387,7 +386,7 @@ static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_6fire __devinitdata = {
+static struct snd_akm4xxx akm_6fire = {
.num_adcs = 6,
.num_dacs = 6,
.type = SND_AK4524,
@@ -396,7 +395,7 @@ static struct snd_akm4xxx akm_6fire __devinitdata = {
}
};
-static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_6fire_priv = {
.caddr = 2,
.cif = 1, /* CIF high */
.data_mask = ICE1712_6FIRE_SERIAL_DATA,
@@ -420,7 +419,7 @@ static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data);
-static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+static int snd_ice1712_ews_init(struct snd_ice1712 *ice)
{
int err;
struct snd_akm4xxx *ak;
@@ -576,7 +575,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
/* i/o sensitivity - this callback is shared among other devices, too */
static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){
- static char *texts[2] = {
+ static const char * const texts[2] = {
"+4dBu", "-10dBV",
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -616,7 +615,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
return val != nval;
}
-static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Sensitivity Switch",
@@ -724,7 +723,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st
return ndata != data;
}
-static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Sensitivity Switch",
.info = snd_ice1712_ewx_io_sense_info,
@@ -733,7 +732,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
.count = 8,
};
-static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Output Sensitivity Switch",
.info = snd_ice1712_ewx_io_sense_info,
@@ -811,7 +810,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
.private_value = xshift | (xinvert << 8),\
}
-static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] = {
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -899,7 +898,7 @@ static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct s
static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- static char *texts[4] = {
+ static const char * const texts[4] = {
"Internal", "Front Input", "Rear Input", "Wave Table"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -948,7 +947,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
.private_value = xshift | (xinvert << 8),\
}
-static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_6fire_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Input Select",
@@ -964,7 +963,7 @@ static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
};
-static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
{
unsigned int idx;
int err;
@@ -1030,7 +1029,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
/* entry point */
-struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_ews_cards[] = {
{
.subvendor = ICE1712_SUBDEVICE_EWX2496,
.name = "TerraTec EWX24/96",
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index 6914189073a4..59e37c581691 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -21,7 +21,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -40,7 +39,7 @@ struct hoontech_spec {
unsigned short boxconfig[4];
};
-static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
+static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
{
byte |= ICE1712_STDSP24_CLOCK_BIT;
udelay(100);
@@ -53,7 +52,7 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
}
-static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
{
struct hoontech_spec *spec = ice->spec;
mutex_lock(&ice->gpio_mutex);
@@ -62,7 +61,7 @@ static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int ac
mutex_unlock(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
{
struct hoontech_spec *spec = ice->spec;
mutex_lock(&ice->gpio_mutex);
@@ -71,7 +70,7 @@ static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int acti
mutex_unlock(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
{
struct hoontech_spec *spec = ice->spec;
mutex_lock(&ice->gpio_mutex);
@@ -80,7 +79,7 @@ static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int act
mutex_unlock(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
+static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
{
struct hoontech_spec *spec = ice->spec;
@@ -130,7 +129,7 @@ static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, i
mutex_unlock(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
+static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
{
struct hoontech_spec *spec = ice->spec;
@@ -158,7 +157,7 @@ static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int
mutex_unlock(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
{
struct hoontech_spec *spec = ice->spec;
mutex_lock(&ice->gpio_mutex);
@@ -167,7 +166,7 @@ static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int act
mutex_unlock(&ice->gpio_mutex);
}
-static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+static int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
{
struct hoontech_spec *spec;
int box, chn;
@@ -267,10 +266,10 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
}
-static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
+static int snd_ice1712_value_init(struct snd_ice1712 *ice)
{
/* Hoontech STDSP24 with modified hardware */
- static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
+ static struct snd_akm4xxx akm_stdsp24_mv = {
.num_adcs = 2,
.num_dacs = 2,
.type = SND_AK4524,
@@ -279,7 +278,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
}
};
- static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
+ static struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
.caddr = 2,
.cif = 1, /* CIF high */
.data_mask = ICE1712_STDSP24_SERIAL_DATA,
@@ -317,7 +316,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
+static int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
{
ice->gpio.write_mask = ice->eeprom.gpiomask;
ice->gpio.direction = ice->eeprom.gpiodir;
@@ -329,7 +328,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
/* entry point */
-struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
{
.subvendor = ICE1712_SUBDEVICE_STDSP24,
.name = "Hoontech SoundTrack Audio DSP24",
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 5be2e120a14e..2ffdc35d5ffd 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -47,7 +47,6 @@
*/
-#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -280,7 +279,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru
return val != nval;
}
-static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Digital Mixer To AC97",
.info = snd_ice1712_digmix_route_ac97_info,
@@ -388,7 +387,7 @@ static void setup_cs8427(struct snd_ice1712 *ice, int rate)
/*
* create and initialize callbacks for cs8427 interface
*/
-int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
+int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
{
int err;
@@ -879,7 +878,7 @@ static struct snd_pcm_ops snd_ice1712_capture_ops = {
.pointer = snd_ice1712_capture_pointer,
};
-static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -909,7 +908,7 @@ static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct
return 0;
}
-static int __devinit snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1254,7 +1253,7 @@ static struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
.pointer = snd_ice1712_capture_pro_pointer,
};
-static int __devinit snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1388,7 +1387,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
-static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Playback Switch",
@@ -1412,7 +1411,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata
},
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Multi Capture Switch",
.info = snd_ice1712_pro_mixer_switch_info,
@@ -1421,7 +1420,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinit
.private_value = 10,
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, SWITCH),
.info = snd_ice1712_pro_mixer_switch_info,
@@ -1431,7 +1430,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd
.count = 2,
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -1443,7 +1442,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinit
.tlv = { .p = db_scale_playback }
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, VOLUME),
.info = snd_ice1712_pro_mixer_volume_info,
@@ -1453,7 +1452,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitd
.count = 2,
};
-static int __devinit snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
+static int snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
{
struct snd_card *card = ice->card;
unsigned int idx;
@@ -1512,7 +1511,7 @@ static void snd_ice1712_mixer_free_ac97(struct snd_ac97 *ac97)
ice->ac97 = NULL;
}
-static int __devinit snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
+static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
{
int err, bus_num = 0;
struct snd_ac97_template ac97;
@@ -1611,7 +1610,7 @@ static void snd_ice1712_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, " GPIO_DIRECTION : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION));
}
-static void __devinit snd_ice1712_proc_init(struct snd_ice1712 *ice)
+static void snd_ice1712_proc_init(struct snd_ice1712 *ice)
{
struct snd_info_entry *entry;
@@ -1640,7 +1639,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_eeprom = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "ICE1712 EEPROM",
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1676,7 +1675,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_default =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1727,7 +1726,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskc =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1736,7 +1735,7 @@ static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
.get = snd_ice1712_spdif_maskc_get,
};
-static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskp =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1763,7 +1762,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_stream =
{
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_INACTIVE),
@@ -1894,7 +1893,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock",
.info = snd_ice1712_pro_internal_clock_info,
@@ -1965,7 +1964,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont
return change;
}
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock Default",
.info = snd_ice1712_pro_internal_clock_default_info,
@@ -1996,7 +1995,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_locking = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Locking",
.info = snd_ice1712_pro_rate_locking_info,
@@ -2027,7 +2026,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_reset = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Reset",
.info = snd_ice1712_pro_rate_reset_info,
@@ -2194,7 +2193,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
.info = snd_ice1712_pro_route_info,
@@ -2202,7 +2201,7 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata
.put = snd_ice1712_pro_route_analog_put,
};
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
.info = snd_ice1712_pro_route_info,
@@ -2244,7 +2243,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Volume Rate",
.info = snd_ice1712_pro_volume_rate_info,
@@ -2277,7 +2276,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Multi Track Peak",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2292,16 +2291,16 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
/*
* list of available boards
*/
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] = {
snd_ice1712_hoontech_cards,
snd_ice1712_delta_cards,
snd_ice1712_ews_cards,
NULL,
};
-static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
- unsigned char dev,
- unsigned char addr)
+static unsigned char snd_ice1712_read_i2c(struct snd_ice1712 *ice,
+ unsigned char dev,
+ unsigned char addr)
{
long t = 0x10000;
@@ -2311,8 +2310,8 @@ static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
return inb(ICEREG(ice, I2C_DATA));
}
-static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
- const char *modelname)
+static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
+ const char *modelname)
{
int dev = 0xa0; /* EEPROM device address */
unsigned int i, size;
@@ -2386,7 +2385,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
-static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
+static int snd_ice1712_chip_init(struct snd_ice1712 *ice)
{
outb(ICE1712_RESET | ICE1712_NATIVE, ICEREG(ice, CONTROL));
udelay(200);
@@ -2433,7 +2432,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
return 0;
}
-int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
+int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
{
int err;
struct snd_kcontrol *kctl;
@@ -2461,7 +2460,7 @@ int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
}
-static int __devinit snd_ice1712_build_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
{
int err;
@@ -2531,13 +2530,13 @@ static int snd_ice1712_dev_free(struct snd_device *device)
return snd_ice1712_free(ice);
}
-static int __devinit snd_ice1712_create(struct snd_card *card,
- struct pci_dev *pci,
- const char *modelname,
- int omni,
- int cs8427_timeout,
- int dxr_enable,
- struct snd_ice1712 **r_ice1712)
+static int snd_ice1712_create(struct snd_card *card,
+ struct pci_dev *pci,
+ const char *modelname,
+ int omni,
+ int cs8427_timeout,
+ int dxr_enable,
+ struct snd_ice1712 **r_ice1712)
{
struct snd_ice1712 *ice;
int err;
@@ -2651,10 +2650,10 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
*
*/
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched;
-static int __devinit snd_ice1712_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_ice1712_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -2686,6 +2685,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
for (tbl = card_tables; *tbl; tbl++) {
for (c = *tbl; c->subvendor; c++) {
if (c->subvendor == ice->eeprom.subvendor) {
+ ice->card_info = c;
strcpy(card->shortname, c->name);
if (c->driver) /* specific driver? */
strcpy(card->driver, c->driver);
@@ -2797,9 +2797,14 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_ice1712_remove(struct pci_dev *pci)
+static void snd_ice1712_remove(struct pci_dev *pci)
{
- snd_card_free(pci_get_drvdata(pci));
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ice1712 *ice = card->private_data;
+
+ if (ice->card_info && ice->card_info->chip_exit)
+ ice->card_info->chip_exit(ice);
+ snd_card_free(card);
pci_set_drvdata(pci, NULL);
}
@@ -2807,7 +2812,7 @@ static struct pci_driver ice1712_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ice1712_ids,
.probe = snd_ice1712_probe,
- .remove = __devexit_p(snd_ice1712_remove),
+ .remove = snd_ice1712_remove,
};
module_pci_driver(ice1712_driver);
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index d0e7d87f09f0..b209fc30b334 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -22,6 +22,7 @@
*
*/
+#include <linux/io.h>
#include <sound/control.h>
#include <sound/ac97_codec.h>
#include <sound/rawmidi.h>
@@ -288,6 +289,7 @@ struct snd_ice1712_spdif {
} ops;
};
+struct snd_ice1712_card_info;
struct snd_ice1712 {
unsigned long conp_dma_size;
@@ -324,6 +326,7 @@ struct snd_ice1712 {
struct snd_info_entry *proc_entry;
struct snd_ice1712_eeprom eeprom;
+ struct snd_ice1712_card_info *card_info;
unsigned int pro_volumes[20];
unsigned int omni:1; /* Delta Omni I/O */
@@ -381,7 +384,7 @@ struct snd_ice1712 {
unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
int (*get_spdif_master_type)(struct snd_ice1712 *ice);
- char **ext_clock_names;
+ const char * const *ext_clock_names;
int ext_clock_count;
void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
#ifdef CONFIG_PM_SLEEP
@@ -513,10 +516,11 @@ static inline u8 snd_ice1712_read(struct snd_ice1712 *ice, u8 addr)
struct snd_ice1712_card_info {
unsigned int subvendor;
- char *name;
- char *model;
- char *driver;
+ const char *name;
+ const char *model;
+ const char *driver;
int (*chip_init)(struct snd_ice1712 *);
+ void (*chip_exit)(struct snd_ice1712 *);
int (*build_controls)(struct snd_ice1712 *);
unsigned int no_mpu401:1;
unsigned int mpu401_1_info_flags;
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 245d874891ba..ce70e7f113e0 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -22,7 +22,6 @@
*
*/
-#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -54,6 +53,7 @@
#include "wtm.h"
#include "se.h"
#include "quartet.h"
+#include "psc724.h"
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -106,7 +106,7 @@ static int PRO_RATE_LOCKED;
static int PRO_RATE_RESET = 1;
static unsigned int PRO_RATE_DEFAULT = 44100;
-static char *ext_clock_names[1] = { "IEC958 In" };
+static const char * const ext_clock_names[1] = { "IEC958 In" };
/*
* Basic I/O
@@ -1135,7 +1135,7 @@ static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
.pointer = snd_vt1724_pcm_pointer,
};
-static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
{
struct snd_pcm *pcm;
int capt, err;
@@ -1315,7 +1315,7 @@ static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
};
-static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
{
char *name;
struct snd_pcm *pcm;
@@ -1449,7 +1449,7 @@ static struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
};
-static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
{
struct snd_pcm *pcm;
int play;
@@ -1484,7 +1484,7 @@ static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
* Mixer section
*/
-static int __devinit snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
+static int snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
{
int err;
@@ -1570,7 +1570,7 @@ static void snd_vt1724_proc_read(struct snd_info_entry *entry,
idx, inb(ice->profi_port+idx));
}
-static void __devinit snd_vt1724_proc_init(struct snd_ice1712 *ice)
+static void snd_vt1724_proc_init(struct snd_ice1712 *ice)
{
struct snd_info_entry *entry;
@@ -1599,7 +1599,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_eeprom = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "ICE1724 EEPROM",
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1712,7 +1712,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
return val != old;
}
-static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_default =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1744,7 +1744,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskc =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1753,7 +1753,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
.get = snd_vt1724_spdif_maskc_get,
};
-static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskp =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1790,7 +1790,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
return old != val;
}
-static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_switch =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* FIXME: the following conflict with IEC958 Playback Route */
@@ -1965,7 +1965,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
return old_rate != new_rate;
}
-static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_internal_clock = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock",
.info = snd_vt1724_pro_internal_clock_info,
@@ -1996,7 +1996,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_locking = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Locking",
.info = snd_vt1724_pro_rate_locking_info,
@@ -2027,7 +2027,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_reset = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Reset",
.info = snd_vt1724_pro_rate_reset_info,
@@ -2042,7 +2042,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = {
+ static const char * const texts[] = {
"PCM Out", /* 0 */
"H/W In 0", "H/W In 1", /* 1-2 */
"IEC958 In L", "IEC958 In R", /* 3-4 */
@@ -2149,7 +2149,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
digital_route_shift(idx));
}
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
@@ -2158,7 +2158,7 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
.put = snd_vt1724_pro_route_analog_put,
};
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
.info = snd_vt1724_pro_route_info,
@@ -2194,7 +2194,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Multi Track Peak",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2206,13 +2206,13 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
*
*/
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched;
/*
ooAoo cards with no controls
*/
-static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
+static unsigned char ooaoo_sq210_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x4c, /* 49MHz crystal, no mpu401, no ADC,
1xDACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
@@ -2232,7 +2232,7 @@ static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
};
-struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
+static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
{
.name = "ooAoo SQ210a",
.model = "sq210a",
@@ -2242,7 +2242,7 @@ struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
{ } /* terminator */
};
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] = {
snd_vt1724_revo_cards,
snd_vt1724_amp_cards,
snd_vt1724_aureon_cards,
@@ -2257,6 +2257,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
snd_vt1724_se_cards,
snd_vt1724_qtet_cards,
snd_vt1724_ooaoo_cards,
+ snd_vt1724_psc724_cards,
NULL,
};
@@ -2306,8 +2307,8 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice,
mutex_unlock(&ice->i2c_mutex);
}
-static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
- const char *modelname)
+static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+ const char *modelname)
{
const int dev = 0xa0; /* EEPROM device address */
unsigned int i, size;
@@ -2348,6 +2349,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
ice->eeprom.subvendor = c->subvendor;
} else if (c->subvendor != ice->eeprom.subvendor)
continue;
+ ice->card_info = c;
if (!c->eeprom_size || !c->eeprom_data)
goto found;
/* if the EEPROM is given by the driver, use it */
@@ -2360,6 +2362,10 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
}
printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n",
ice->eeprom.subvendor);
+#ifdef CONFIG_PM_SLEEP
+ /* assume AC97-only card which can suspend without additional code */
+ ice->pm_suspend_enabled = 1;
+#endif
found:
ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04);
@@ -2371,7 +2377,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
return -EIO;
}
ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05);
- if (ice->eeprom.version != 2)
+ if (ice->eeprom.version != 1 && ice->eeprom.version != 2)
printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n",
ice->eeprom.version);
size = ice->eeprom.size - 6;
@@ -2424,7 +2430,7 @@ static int snd_vt1724_chip_init(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
{
int err;
struct snd_kcontrol *kctl;
@@ -2466,7 +2472,7 @@ static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
}
-static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
{
int err;
@@ -2526,10 +2532,10 @@ static int snd_vt1724_dev_free(struct snd_device *device)
return snd_vt1724_free(ice);
}
-static int __devinit snd_vt1724_create(struct snd_card *card,
- struct pci_dev *pci,
- const char *modelname,
- struct snd_ice1712 **r_ice1712)
+static int snd_vt1724_create(struct snd_card *card,
+ struct pci_dev *pci,
+ const char *modelname,
+ struct snd_ice1712 **r_ice1712)
{
struct snd_ice1712 *ice;
int err;
@@ -2616,8 +2622,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
*
*/
-static int __devinit snd_vt1724_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_vt1724_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -2786,9 +2792,14 @@ __found:
return 0;
}
-static void __devexit snd_vt1724_remove(struct pci_dev *pci)
+static void snd_vt1724_remove(struct pci_dev *pci)
{
- snd_card_free(pci_get_drvdata(pci));
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ice1712 *ice = card->private_data;
+
+ if (ice->card_info && ice->card_info->chip_exit)
+ ice->card_info->chip_exit(ice);
+ snd_card_free(card);
pci_set_drvdata(pci, NULL);
}
@@ -2889,7 +2900,7 @@ static struct pci_driver vt1724_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vt1724_ids,
.probe = snd_vt1724_probe,
- .remove = __devexit_p(snd_vt1724_remove),
+ .remove = snd_vt1724_remove,
.driver = {
.pm = SND_VT1724_PM_OPS,
},
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 14fd536b6452..8855933e710d 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -23,7 +23,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -283,7 +282,7 @@ static const struct snd_akm4xxx_dac_channel juli_dac[] = {
};
-static struct snd_akm4xxx akm_juli_dac __devinitdata = {
+static struct snd_akm4xxx akm_juli_dac = {
.type = SND_AK4358,
.num_dacs = 8, /* DAC1 - analog out
DAC2 - analog in monitor
@@ -358,7 +357,7 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+static struct snd_kcontrol_new juli_mute_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -412,7 +411,7 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
},
};
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
PCM_VOLUME,
MONITOR_AN_IN_VOLUME,
MONITOR_DIG_IN_VOLUME,
@@ -420,11 +419,11 @@ static char *slave_vols[] __devinitdata = {
NULL
};
-static __devinitdata
+static
DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
- const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card,
+ const char *name)
{
struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
@@ -434,8 +433,9 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
return snd_ctl_find_id(card, &sid);
}
-static void __devinit add_slaves(struct snd_card *card,
- struct snd_kcontrol *master, char **list)
+static void add_slaves(struct snd_card *card,
+ struct snd_kcontrol *master,
+ char * const *list)
{
for (; *list; list++) {
struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -447,7 +447,7 @@ static void __devinit add_slaves(struct snd_card *card,
}
}
-static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+static int juli_add_controls(struct snd_ice1712 *ice)
{
struct juli_spec *spec = ice->spec;
int err;
@@ -579,7 +579,7 @@ static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
}
}
-static int __devinit juli_init(struct snd_ice1712 *ice)
+static int juli_init(struct snd_ice1712 *ice)
{
static const unsigned char ak4114_init_vals[] = {
/* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN |
@@ -667,7 +667,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
* hence the driver needs to sets up it properly.
*/
-static unsigned char juli_eeprom[] __devinitdata = {
+static unsigned char juli_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, 1xADC, 1xDACs,
SPDIF in */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
@@ -686,7 +686,7 @@ static unsigned char juli_eeprom[] __devinitdata = {
};
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_JULI,
.name = "ESI Juli@",
diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c
index 726fd4b92e19..63aa39f06f02 100644
--- a/sound/pci/ice1712/maya44.c
+++ b/sound/pci/ice1712/maya44.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/io.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -358,7 +357,7 @@ static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = { "Line", "Mic" };
+ static const char * const texts[] = { "Line", "Mic" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -407,7 +406,7 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = {
+ static const char * const texts[] = {
"PCM Out", /* 0 */
"Input 1", "Input 2", "Input 3", "Input 4"
};
@@ -455,7 +454,7 @@ static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
* controls to be added
*/
-static struct snd_kcontrol_new maya_controls[] __devinitdata = {
+static struct snd_kcontrol_new maya_controls[] = {
{
.name = "Crossmix Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -545,7 +544,7 @@ static struct snd_kcontrol_new maya_controls[] __devinitdata = {
},
};
-static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
+static int maya44_add_controls(struct snd_ice1712 *ice)
{
int err, i;
@@ -562,8 +561,8 @@ static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
/*
* initialize a wm8776 chip
*/
-static void __devinit wm8776_init(struct snd_ice1712 *ice,
- struct snd_wm8776 *wm, unsigned int addr)
+static void wm8776_init(struct snd_ice1712 *ice,
+ struct snd_wm8776 *wm, unsigned int addr)
{
static const unsigned short inits_wm8776[] = {
0x02, 0x100, /* R2: headphone L+R muted + update */
@@ -693,14 +692,14 @@ static struct snd_pcm_hw_constraint_list dac_rates = {
/*
* chip addresses on I2C bus
*/
-static unsigned char wm8776_addr[2] __devinitdata = {
+static unsigned char wm8776_addr[2] = {
0x34, 0x36, /* codec 0 & 1 */
};
/*
* initialize the chip
*/
-static int __devinit maya44_init(struct snd_ice1712 *ice)
+static int maya44_init(struct snd_ice1712 *ice)
{
int i;
struct snd_maya44 *chip;
@@ -743,7 +742,7 @@ static int __devinit maya44_init(struct snd_ice1712 *ice)
* hence the driver needs to sets up it properly.
*/
-static unsigned char maya44_eeprom[] __devinitdata = {
+static unsigned char maya44_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x45,
/* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
[ICE_EEP2_ACLINK] = 0x80,
@@ -765,7 +764,7 @@ static unsigned char maya44_eeprom[] __devinitdata = {
};
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_maya44_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_MAYA44,
.name = "ESI Maya44",
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index de29be8c9657..0011e04f36a2 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -42,7 +42,6 @@
* Digital receiver: CS8414-CS (supported in this release)
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -103,13 +102,13 @@ static const unsigned char wm_vol[256] = {
#define WM_VOL_MAX (sizeof(wm_vol) - 1)
#define WM_VOL_MUTE 0x8000
-static struct snd_akm4xxx akm_phase22 __devinitdata = {
+static struct snd_akm4xxx akm_phase22 = {
.type = SND_AK4524,
.num_dacs = 2,
.num_adcs = 2,
};
-static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_phase22_priv = {
.caddr = 2,
.cif = 1,
.data_mask = 1 << 4,
@@ -121,7 +120,7 @@ static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
.mask_flags = 0,
};
-static int __devinit phase22_init(struct snd_ice1712 *ice)
+static int phase22_init(struct snd_ice1712 *ice)
{
struct snd_akm4xxx *ak;
int err;
@@ -158,7 +157,7 @@ static int __devinit phase22_init(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
+static int phase22_add_controls(struct snd_ice1712 *ice)
{
int err = 0;
@@ -172,7 +171,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
return 0;
}
-static unsigned char phase22_eeprom[] __devinitdata = {
+static unsigned char phase22_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x28, /* clock 512, mpu 401,
spdif-in/1xADC, 1xDACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
@@ -189,7 +188,7 @@ static unsigned char phase22_eeprom[] __devinitdata = {
[ICE_EEP2_GPIO_STATE2] = 0x00,
};
-static unsigned char phase28_eeprom[] __devinitdata = {
+static unsigned char phase28_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401,
spdif-in/1xADC, 4xDACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
@@ -379,7 +378,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
return change;
}
-static int __devinit phase28_init(struct snd_ice1712 *ice)
+static int phase28_init(struct snd_ice1712 *ice)
{
static const unsigned short wm_inits_phase28[] = {
/* These come first to reduce init pop noise */
@@ -722,7 +721,7 @@ static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
static int phase28_oversampling_info(struct snd_kcontrol *k,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[2] = { "128x", "64x" };
+ static const char * const texts[2] = { "128x", "64x" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -770,7 +769,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
-static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new phase28_dac_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -885,7 +884,7 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
}
};
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
@@ -919,7 +918,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
}
};
-static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
+static int phase28_add_controls(struct snd_ice1712 *ice)
{
unsigned int i, counts;
int err;
@@ -943,7 +942,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
return 0;
}
-struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_phase_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_PHASE22,
.name = "Terratec PHASE 22",
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 92c1160d7ab5..5555eb4b2400 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -21,7 +21,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -550,7 +549,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
* mixers
*/
-static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
+static struct snd_kcontrol_new pontis_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -697,7 +696,7 @@ static void cs_proc_init(struct snd_ice1712 *ice)
}
-static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
+static int pontis_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -718,7 +717,7 @@ static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
/*
* initialize the chip
*/
-static int __devinit pontis_init(struct snd_ice1712 *ice)
+static int pontis_init(struct snd_ice1712 *ice)
{
static const unsigned short wm_inits[] = {
/* These come first to reduce init pop noise */
@@ -805,7 +804,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
* hence the driver needs to sets up it properly.
*/
-static unsigned char pontis_eeprom[] __devinitdata = {
+static unsigned char pontis_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x08, /* clock 256, mpu401, spdif-in/ADC, 1DAC */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
@@ -822,7 +821,7 @@ static unsigned char pontis_eeprom[] __devinitdata = {
};
/* entry point */
-struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_pontis_cards[] = {
{
.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
.name = "Pontis MS300",
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index e36ddb94c382..e610339f7601 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -54,7 +54,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -283,7 +282,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[2] = { "Line In", "Mic" };
+ static const char * const texts[2] = { "Line In", "Mic" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -369,7 +368,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
* mixers
*/
-static struct snd_kcontrol_new stac_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -562,7 +561,7 @@ static unsigned char prodigy192_ak4114_read(void *private_data,
static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[2] = { "Toslink", "Coax" };
+ static const char * const texts[2] = { "Toslink", "Coax" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -607,7 +606,7 @@ static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
}
-static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
+static struct snd_kcontrol_new ak4114_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "MIODIO IEC958 Capture Input",
@@ -672,7 +671,7 @@ static void stac9460_proc_init(struct snd_ice1712 *ice)
}
-static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
+static int prodigy192_add_controls(struct snd_ice1712 *ice)
{
struct prodigy192_spec *spec = ice->spec;
unsigned int i;
@@ -728,7 +727,7 @@ static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
/*
* initialize the chip
*/
-static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+static int prodigy192_init(struct snd_ice1712 *ice)
{
static const unsigned short stac_inits_prodigy[] = {
STAC946X_RESET, 0,
@@ -784,7 +783,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
* hence the driver needs to sets up it properly.
*/
-static unsigned char prodigy71_eeprom[] __devinitdata = {
+static unsigned char prodigy71_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401,
* spdif-in+ 1 stereo ADC,
* 3 stereo DACs
@@ -808,7 +807,7 @@ static unsigned char prodigy71_eeprom[] __devinitdata = {
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
.name = "Audiotrak Prodigy 192",
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c
index 7bf093c51ce5..2261d1e49150 100644
--- a/sound/pci/ice1712/prodigy_hifi.c
+++ b/sound/pci/ice1712/prodigy_hifi.c
@@ -25,7 +25,6 @@
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -299,7 +298,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
-static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
+static struct snd_kcontrol_new prodigy_hd2_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -782,7 +781,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol,
* mixers
*/
-static struct snd_kcontrol_new prodigy_hifi_controls[] __devinitdata = {
+static struct snd_kcontrol_new prodigy_hifi_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -939,7 +938,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
}
}
-static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
+static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -956,7 +955,7 @@ static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
+static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -977,7 +976,7 @@ static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
/*
* initialize the chip
*/
-static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice)
+static int prodigy_hifi_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits[] = {
/* These come first to reduce init pop noise */
@@ -1115,7 +1114,7 @@ static int prodigy_hd2_resume(struct snd_ice1712 *ice)
}
#endif
-static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
+static int prodigy_hd2_init(struct snd_ice1712 *ice)
{
struct prodigy_hifi_spec *spec;
@@ -1152,7 +1151,7 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
}
-static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
+static unsigned char prodigy71hifi_eeprom[] = {
0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
0x80, /* ACLINK: I2S */
0xfc, /* I2S: vol, 96k, 24bit, 192k */
@@ -1168,7 +1167,7 @@ static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
0x00, /* GPIO_STATE2 */
};
-static unsigned char prodigyhd2_eeprom[] __devinitdata = {
+static unsigned char prodigyhd2_eeprom[] = {
0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
0x80, /* ACLINK: I2S */
0xfc, /* I2S: vol, 96k, 24bit, 192k */
@@ -1184,7 +1183,7 @@ static unsigned char prodigyhd2_eeprom[] __devinitdata = {
0x00, /* GPIO_STATE2 */
};
-static unsigned char fortissimo4_eeprom[] __devinitdata = {
+static unsigned char fortissimo4_eeprom[] = {
0x43, /* SYSCONF: clock 512, ADC, 4DACs */
0x80, /* ACLINK: I2S */
0xfc, /* I2S: vol, 96k, 24bit, 192k */
@@ -1201,7 +1200,7 @@ static unsigned char fortissimo4_eeprom[] __devinitdata = {
};
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
.name = "Audiotrak Prodigy 7.1 HiFi",
diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
new file mode 100644
index 000000000000..302ac6ddd545
--- /dev/null
+++ b/sound/pci/ice1712/psc724.c
@@ -0,0 +1,464 @@
+/*
+ * ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ * Lowlevel functions for Philips PSC724 Ultimate Edge
+ *
+ * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "psc724.h"
+#include "wm8766.h"
+#include "wm8776.h"
+
+struct psc724_spec {
+ struct snd_wm8766 wm8766;
+ struct snd_wm8776 wm8776;
+ bool mute_all, jack_detect;
+ struct snd_ice1712 *ice;
+ struct delayed_work hp_work;
+ bool hp_connected;
+};
+
+/****************************************************************************/
+/* PHILIPS PSC724 ULTIMATE EDGE */
+/****************************************************************************/
+/*
+ * VT1722 (Envy24GT) - 6 outputs, 4 inputs (only 2 used), 24-bit/96kHz
+ *
+ * system configuration ICE_EEP2_SYSCONF=0x42
+ * XIN1 49.152MHz
+ * no MPU401
+ * one stereo ADC, no S/PDIF receiver
+ * three stereo DACs (FRONT, REAR, CENTER+LFE)
+ *
+ * AC-Link configuration ICE_EEP2_ACLINK=0x80
+ * use I2S, not AC97
+ *
+ * I2S converters feature ICE_EEP2_I2S=0x30
+ * I2S codec has no volume/mute control feature (bug!)
+ * I2S codec does not support 96KHz or 192KHz (bug!)
+ * I2S codec 24bits
+ *
+ * S/PDIF configuration ICE_EEP2_SPDIF=0xc1
+ * Enable integrated S/PDIF transmitter
+ * internal S/PDIF out implemented
+ * No S/PDIF input
+ * External S/PDIF out implemented
+ *
+ *
+ * ** connected chips **
+ *
+ * WM8776
+ * 2-channel DAC used for main output and stereo ADC (with 10-channel MUX)
+ * AIN1: LINE IN, AIN2: CD/VIDEO, AIN3: AUX, AIN4: Front MIC, AIN5: Rear MIC
+ * Controlled by I2C using VT1722 I2C interface:
+ * MODE (pin16) -- GND
+ * CE (pin17) -- GND I2C mode (address=0x34)
+ * DI (pin18) -- SDA (VT1722 pin70)
+ * CL (pin19) -- SCLK (VT1722 pin71)
+ *
+ * WM8766
+ * 6-channel DAC used for rear & center/LFE outputs (only 4 channels used)
+ * Controlled by SPI using VT1722 GPIO pins:
+ * MODE (pin 1) -- GPIO19 (VT1722 pin99)
+ * ML/I2S (pin11) -- GPIO18 (VT1722 pin98)
+ * MC/IWL (pin12) -- GPIO17 (VT1722 pin97)
+ * MD/DM (pin13) -- GPIO16 (VT1722 pin96)
+ * MUTE (pin14) -- GPIO20 (VT1722 pin101)
+ *
+ * GPIO14 is used as input for headphone jack detection (1 = connected)
+ * GPIO22 is used as MUTE ALL output, grounding all 6 channels
+ *
+ * ** output pins and device names **
+ *
+ * 5.1ch name -- output connector color -- device (-D option)
+ *
+ * FRONT 2ch -- green -- plughw:0,0
+ * CENTER(Lch) SUBWOOFER(Rch) -- orange -- plughw:0,2,0
+ * REAR 2ch -- black -- plughw:0,2,1
+ */
+
+/* codec access low-level functions */
+
+#define GPIO_HP_JACK (1 << 14)
+#define GPIO_MUTE_SUR (1 << 20)
+#define GPIO_MUTE_ALL (1 << 22)
+
+#define JACK_INTERVAL 1000
+
+#define PSC724_SPI_DELAY 1
+
+#define PSC724_SPI_DATA (1 << 16)
+#define PSC724_SPI_CLK (1 << 17)
+#define PSC724_SPI_LOAD (1 << 18)
+#define PSC724_SPI_MASK (PSC724_SPI_DATA | PSC724_SPI_CLK | PSC724_SPI_LOAD)
+
+static void psc724_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+ struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8766);
+ struct snd_ice1712 *ice = spec->ice;
+ u32 st, bits;
+ int i;
+
+ snd_ice1712_save_gpio_status(ice);
+
+ st = ((addr & 0x7f) << 9) | (data & 0x1ff);
+ snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | PSC724_SPI_MASK);
+ snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~PSC724_SPI_MASK);
+ bits = snd_ice1712_gpio_read(ice) & ~PSC724_SPI_MASK;
+ snd_ice1712_gpio_write(ice, bits);
+
+ for (i = 0; i < 16; i++) {
+ udelay(PSC724_SPI_DELAY);
+ bits &= ~PSC724_SPI_CLK;
+ /* MSB first */
+ st <<= 1;
+ if (st & 0x10000)
+ bits |= PSC724_SPI_DATA;
+ else
+ bits &= ~PSC724_SPI_DATA;
+ snd_ice1712_gpio_write(ice, bits);
+ /* CLOCK high */
+ udelay(PSC724_SPI_DELAY);
+ bits |= PSC724_SPI_CLK;
+ snd_ice1712_gpio_write(ice, bits);
+ }
+ /* LOAD high */
+ udelay(PSC724_SPI_DELAY);
+ bits |= PSC724_SPI_LOAD;
+ snd_ice1712_gpio_write(ice, bits);
+ /* LOAD low, DATA and CLOCK high */
+ udelay(PSC724_SPI_DELAY);
+ bits |= (PSC724_SPI_DATA | PSC724_SPI_CLK);
+ snd_ice1712_gpio_write(ice, bits);
+
+ snd_ice1712_restore_gpio_status(ice);
+}
+
+static void psc724_wm8776_write(struct snd_wm8776 *wm, u8 addr, u8 data)
+{
+ struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8776);
+
+ snd_vt1724_write_i2c(spec->ice, 0x34, addr, data);
+}
+
+/* mute all */
+
+static void psc724_set_master_switch(struct snd_ice1712 *ice, bool on)
+{
+ unsigned int bits = snd_ice1712_gpio_read(ice);
+ struct psc724_spec *spec = ice->spec;
+
+ spec->mute_all = !on;
+ if (on)
+ bits &= ~(GPIO_MUTE_ALL | GPIO_MUTE_SUR);
+ else
+ bits |= GPIO_MUTE_ALL | GPIO_MUTE_SUR;
+ snd_ice1712_gpio_write(ice, bits);
+}
+
+static bool psc724_get_master_switch(struct snd_ice1712 *ice)
+{
+ struct psc724_spec *spec = ice->spec;
+
+ return !spec->mute_all;
+}
+
+/* jack detection */
+
+static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected)
+{
+ struct psc724_spec *spec = ice->spec;
+ struct snd_ctl_elem_id elem_id;
+ struct snd_kcontrol *kctl;
+ u16 power = spec->wm8776.regs[WM8776_REG_PWRDOWN] & ~WM8776_PWR_HPPD;
+
+ psc724_set_master_switch(ice, !hp_connected);
+ if (!hp_connected)
+ power |= WM8776_PWR_HPPD;
+ snd_wm8776_set_power(&spec->wm8776, power);
+ spec->hp_connected = hp_connected;
+ /* notify about master speaker mute change */
+ memset(&elem_id, 0, sizeof(elem_id));
+ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strncpy(elem_id.name, "Master Speakers Playback Switch",
+ sizeof(elem_id.name));
+ kctl = snd_ctl_find_id(ice->card, &elem_id);
+ snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+ /* and headphone mute change */
+ strncpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+ sizeof(elem_id.name));
+ kctl = snd_ctl_find_id(ice->card, &elem_id);
+ snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+}
+
+static void psc724_update_hp_jack_state(struct work_struct *work)
+{
+ struct psc724_spec *spec = container_of(work, struct psc724_spec,
+ hp_work.work);
+ struct snd_ice1712 *ice = spec->ice;
+ bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+
+ schedule_delayed_work(&spec->hp_work, msecs_to_jiffies(JACK_INTERVAL));
+ if (hp_connected == spec->hp_connected)
+ return;
+ psc724_set_jack_state(ice, hp_connected);
+}
+
+static void psc724_set_jack_detection(struct snd_ice1712 *ice, bool on)
+{
+ struct psc724_spec *spec = ice->spec;
+
+ if (spec->jack_detect == on)
+ return;
+
+ spec->jack_detect = on;
+ if (on) {
+ bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+ psc724_set_jack_state(ice, hp_connected);
+ schedule_delayed_work(&spec->hp_work,
+ msecs_to_jiffies(JACK_INTERVAL));
+ } else
+ cancel_delayed_work_sync(&spec->hp_work);
+}
+
+static bool psc724_get_jack_detection(struct snd_ice1712 *ice)
+{
+ struct psc724_spec *spec = ice->spec;
+
+ return spec->jack_detect;
+}
+
+/* mixer controls */
+
+struct psc724_control {
+ const char *name;
+ void (*set)(struct snd_ice1712 *ice, bool on);
+ bool (*get)(struct snd_ice1712 *ice);
+};
+
+static const struct psc724_control psc724_cont[] = {
+ {
+ .name = "Master Speakers Playback Switch",
+ .set = psc724_set_master_switch,
+ .get = psc724_get_master_switch,
+ },
+ {
+ .name = "Headphone Jack Detection Playback Switch",
+ .set = psc724_set_jack_detection,
+ .get = psc724_get_jack_detection,
+ },
+};
+
+static int psc724_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = psc724_cont[n].get(ice);
+
+ return 0;
+}
+
+static int psc724_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ psc724_cont[n].set(ice, ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static const char *front_volume = "Front Playback Volume";
+static const char *front_switch = "Front Playback Switch";
+static const char *front_zc = "Front Zero Cross Detect Playback Switch";
+static const char *front_izd = "Front Infinite Zero Detect Playback Switch";
+static const char *front_phase = "Front Phase Invert Playback Switch";
+static const char *front_deemph = "Front Deemphasis Playback Switch";
+static const char *ain1_switch = "Line Capture Switch";
+static const char *ain2_switch = "CD Capture Switch";
+static const char *ain3_switch = "AUX Capture Switch";
+static const char *ain4_switch = "Front Mic Capture Switch";
+static const char *ain5_switch = "Rear Mic Capture Switch";
+static const char *rear_volume = "Surround Playback Volume";
+static const char *clfe_volume = "CLFE Playback Volume";
+static const char *rear_switch = "Surround Playback Switch";
+static const char *clfe_switch = "CLFE Playback Switch";
+static const char *rear_phase = "Surround Phase Invert Playback Switch";
+static const char *clfe_phase = "CLFE Phase Invert Playback Switch";
+static const char *rear_deemph = "Surround Deemphasis Playback Switch";
+static const char *clfe_deemph = "CLFE Deemphasis Playback Switch";
+static const char *rear_clfe_izd = "Rear Infinite Zero Detect Playback Switch";
+static const char *rear_clfe_zc = "Rear Zero Cross Detect Playback Switch";
+
+static int psc724_add_controls(struct snd_ice1712 *ice)
+{
+ struct snd_kcontrol_new cont;
+ struct snd_kcontrol *ctl;
+ int err, i;
+ struct psc724_spec *spec = ice->spec;
+
+ spec->wm8776.ctl[WM8776_CTL_DAC_VOL].name = front_volume;
+ spec->wm8776.ctl[WM8776_CTL_DAC_SW].name = front_switch;
+ spec->wm8776.ctl[WM8776_CTL_DAC_ZC_SW].name = front_zc;
+ spec->wm8776.ctl[WM8776_CTL_AUX_SW].name = NULL;
+ spec->wm8776.ctl[WM8776_CTL_DAC_IZD_SW].name = front_izd;
+ spec->wm8776.ctl[WM8776_CTL_PHASE_SW].name = front_phase;
+ spec->wm8776.ctl[WM8776_CTL_DEEMPH_SW].name = front_deemph;
+ spec->wm8776.ctl[WM8776_CTL_INPUT1_SW].name = ain1_switch;
+ spec->wm8776.ctl[WM8776_CTL_INPUT2_SW].name = ain2_switch;
+ spec->wm8776.ctl[WM8776_CTL_INPUT3_SW].name = ain3_switch;
+ spec->wm8776.ctl[WM8776_CTL_INPUT4_SW].name = ain4_switch;
+ spec->wm8776.ctl[WM8776_CTL_INPUT5_SW].name = ain5_switch;
+ snd_wm8776_build_controls(&spec->wm8776);
+ spec->wm8766.ctl[WM8766_CTL_CH1_VOL].name = rear_volume;
+ spec->wm8766.ctl[WM8766_CTL_CH2_VOL].name = clfe_volume;
+ spec->wm8766.ctl[WM8766_CTL_CH3_VOL].name = NULL;
+ spec->wm8766.ctl[WM8766_CTL_CH1_SW].name = rear_switch;
+ spec->wm8766.ctl[WM8766_CTL_CH2_SW].name = clfe_switch;
+ spec->wm8766.ctl[WM8766_CTL_CH3_SW].name = NULL;
+ spec->wm8766.ctl[WM8766_CTL_PHASE1_SW].name = rear_phase;
+ spec->wm8766.ctl[WM8766_CTL_PHASE2_SW].name = clfe_phase;
+ spec->wm8766.ctl[WM8766_CTL_PHASE3_SW].name = NULL;
+ spec->wm8766.ctl[WM8766_CTL_DEEMPH1_SW].name = rear_deemph;
+ spec->wm8766.ctl[WM8766_CTL_DEEMPH2_SW].name = clfe_deemph;
+ spec->wm8766.ctl[WM8766_CTL_DEEMPH3_SW].name = NULL;
+ spec->wm8766.ctl[WM8766_CTL_IZD_SW].name = rear_clfe_izd;
+ spec->wm8766.ctl[WM8766_CTL_ZC_SW].name = rear_clfe_zc;
+ snd_wm8766_build_controls(&spec->wm8766);
+
+ memset(&cont, 0, sizeof(cont));
+ cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ for (i = 0; i < ARRAY_SIZE(psc724_cont); i++) {
+ cont.private_value = i;
+ cont.name = psc724_cont[i].name;
+ cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ cont.info = snd_ctl_boolean_mono_info;
+ cont.get = psc724_ctl_get;
+ cont.put = psc724_ctl_put;
+ ctl = snd_ctl_new1(&cont, ice);
+ if (!ctl)
+ return -ENOMEM;
+ err = snd_ctl_add(ice->card, ctl);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static void psc724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+ struct psc724_spec *spec = ice->spec;
+ /* restore codec volume settings after rate change (PMCLK stop) */
+ snd_wm8776_volume_restore(&spec->wm8776);
+ snd_wm8766_volume_restore(&spec->wm8766);
+}
+
+/* power management */
+
+#ifdef CONFIG_PM_SLEEP
+static int psc724_resume(struct snd_ice1712 *ice)
+{
+ struct psc724_spec *spec = ice->spec;
+
+ snd_wm8776_resume(&spec->wm8776);
+ snd_wm8766_resume(&spec->wm8766);
+
+ return 0;
+}
+#endif
+
+/* init */
+
+static int psc724_init(struct snd_ice1712 *ice)
+{
+ struct psc724_spec *spec;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return -ENOMEM;
+ ice->spec = spec;
+ spec->ice = ice;
+
+ ice->num_total_dacs = 6;
+ ice->num_total_adcs = 2;
+ spec->wm8776.ops.write = psc724_wm8776_write;
+ spec->wm8776.card = ice->card;
+ snd_wm8776_init(&spec->wm8776);
+ spec->wm8766.ops.write = psc724_wm8766_write;
+ spec->wm8766.card = ice->card;
+#ifdef CONFIG_PM_SLEEP
+ ice->pm_resume = psc724_resume;
+ ice->pm_suspend_enabled = 1;
+#endif
+ snd_wm8766_init(&spec->wm8766);
+ snd_wm8766_set_if(&spec->wm8766,
+ WM8766_IF_FMT_I2S | WM8766_IF_IWL_24BIT);
+ ice->gpio.set_pro_rate = psc724_set_pro_rate;
+ INIT_DELAYED_WORK(&spec->hp_work, psc724_update_hp_jack_state);
+ psc724_set_jack_detection(ice, true);
+ return 0;
+}
+
+static void psc724_exit(struct snd_ice1712 *ice)
+{
+ struct psc724_spec *spec = ice->spec;
+
+ cancel_delayed_work_sync(&spec->hp_work);
+}
+
+/* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */
+static unsigned char psc724_eeprom[] = {
+ [ICE_EEP2_SYSCONF] = 0x42, /* 49.152MHz, 1 ADC, 3 DACs */
+ [ICE_EEP2_ACLINK] = 0x80, /* I2S */
+ [ICE_EEP2_I2S] = 0xf0, /* I2S volume, 96kHz, 24bit */
+ [ICE_EEP2_SPDIF] = 0xc1, /* spdif out-en, out-int, no input */
+ /* GPIO outputs */
+ [ICE_EEP2_GPIO_DIR2] = 0x5f, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+ /* GPIO write enable */
+ [ICE_EEP2_GPIO_MASK] = 0xff, /* read-only */
+ [ICE_EEP2_GPIO_MASK1] = 0xff, /* read-only */
+ [ICE_EEP2_GPIO_MASK2] = 0xa0, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+ /* GPIO initial state */
+ [ICE_EEP2_GPIO_STATE2] = 0x20, /* unmuted, all WM8766 pins low */
+};
+
+struct snd_ice1712_card_info snd_vt1724_psc724_cards[] = {
+ {
+ .subvendor = VT1724_SUBDEVICE_PSC724,
+ .name = "Philips PSC724 Ultimate Edge",
+ .model = "psc724",
+ .chip_init = psc724_init,
+ .chip_exit = psc724_exit,
+ .build_controls = psc724_add_controls,
+ .eeprom_size = sizeof(psc724_eeprom),
+ .eeprom_data = psc724_eeprom,
+ },
+ {} /*terminator*/
+};
diff --git a/sound/pci/ice1712/psc724.h b/sound/pci/ice1712/psc724.h
new file mode 100644
index 000000000000..858e5fd0eebb
--- /dev/null
+++ b/sound/pci/ice1712/psc724.h
@@ -0,0 +1,13 @@
+#ifndef __SOUND_PSC724_H
+#define __SOUND_PSC724_H
+
+/* ID */
+#define PSC724_DEVICE_DESC \
+ "{Philips,PSC724 Ultimate Edge},"
+
+#define VT1724_SUBDEVICE_PSC724 0xab170619
+
+/* entry struct */
+extern struct snd_ice1712_card_info snd_vt1724_psc724_cards[];
+
+#endif /* __SOUND_PSC724_H */
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
index 1948632787e6..975e0357bd5a 100644
--- a/sound/pci/ice1712/quartet.c
+++ b/sound/pci/ice1712/quartet.c
@@ -22,7 +22,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -47,7 +46,7 @@ struct qtet_kcontrol_private {
unsigned int bit;
void (*set_register)(struct snd_ice1712 *ice, unsigned int val);
unsigned int (*get_register)(struct snd_ice1712 *ice);
- unsigned char *texts[2];
+ unsigned char * const texts[2];
};
enum {
@@ -63,7 +62,7 @@ enum {
OUT34_MON12,
};
-static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
+static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
"Word Clock 256xFS"};
/* chip address on I2C bus */
@@ -387,7 +386,7 @@ static const struct snd_akm4xxx_adc_channel qtet_adc[] = {
AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2),
};
-static struct snd_akm4xxx akm_qtet_dac __devinitdata = {
+static struct snd_akm4xxx akm_qtet_dac = {
.type = SND_AK4620,
.num_dacs = 4, /* DAC1 - Output 12
*/
@@ -551,7 +550,8 @@ static int qtet_mute_put(struct snd_kcontrol *kcontrol,
static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"};
+ static const char * const texts[3] =
+ {"Line In 1/2", "Mic", "Mic + Low-cut"};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = ARRAY_SIZE(texts);
@@ -758,7 +758,7 @@ static int qtet_sw_put(struct snd_kcontrol *kcontrol,
.put = qtet_sw_put,\
.private_value = xpriv }
-static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
+static struct snd_kcontrol_new qtet_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -795,17 +795,17 @@ static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12),
};
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
PCM_12_PLAYBACK_VOLUME,
PCM_34_PLAYBACK_VOLUME,
NULL
};
-static __devinitdata
+static
DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1);
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
- const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card,
+ const char *name)
{
struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
@@ -815,8 +815,8 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
return snd_ctl_find_id(card, &sid);
}
-static void __devinit add_slaves(struct snd_card *card,
- struct snd_kcontrol *master, char **list)
+static void add_slaves(struct snd_card *card,
+ struct snd_kcontrol *master, char * const *list)
{
for (; *list; list++) {
struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -825,7 +825,7 @@ static void __devinit add_slaves(struct snd_card *card,
}
}
-static int __devinit qtet_add_controls(struct snd_ice1712 *ice)
+static int qtet_add_controls(struct snd_ice1712 *ice)
{
struct qtet_spec *spec = ice->spec;
int err, i;
@@ -1007,7 +1007,7 @@ static void qtet_spdif_in_open(struct snd_ice1712 *ice,
/*
* initialize the chip
*/
-static int __devinit qtet_init(struct snd_ice1712 *ice)
+static int qtet_init(struct snd_ice1712 *ice)
{
static const unsigned char ak4113_init_vals[] = {
/* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN |
@@ -1095,7 +1095,7 @@ static int __devinit qtet_init(struct snd_ice1712 *ice)
return 0;
}
-static unsigned char qtet_eeprom[] __devinitdata = {
+static unsigned char qtet_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC,
1xDACs, SPDIF in */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
@@ -1116,7 +1116,7 @@ static unsigned char qtet_eeprom[] __devinitdata = {
};
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_qtet_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_QTET,
.name = "Infrasonic Quartet",
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index b508bb360b97..7641080a9b5d 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -21,7 +21,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -235,7 +234,7 @@ static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
},
};
-static struct snd_akm4xxx akm_revo_front __devinitdata = {
+static struct snd_akm4xxx akm_revo_front = {
.type = SND_AK4381,
.num_dacs = 2,
.ops = {
@@ -244,7 +243,7 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = {
.dac_info = revo71_front,
};
-static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_front_priv = {
.caddr = 1,
.cif = 0,
.data_mask = VT1724_REVO_CDOUT,
@@ -256,7 +255,7 @@ static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_revo_surround __devinitdata = {
+static struct snd_akm4xxx akm_revo_surround = {
.type = SND_AK4355,
.idx_offset = 1,
.num_dacs = 6,
@@ -266,7 +265,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
.dac_info = revo71_surround,
};
-static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_surround_priv = {
.caddr = 3,
.cif = 0,
.data_mask = VT1724_REVO_CDOUT,
@@ -278,7 +277,7 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_revo51 __devinitdata = {
+static struct snd_akm4xxx akm_revo51 = {
.type = SND_AK4358,
.num_dacs = 8,
.ops = {
@@ -287,7 +286,7 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
.dac_info = revo51_dac,
};
-static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_priv = {
.caddr = 2,
.cif = 0,
.data_mask = VT1724_REVO_CDOUT,
@@ -299,13 +298,13 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
.mask_flags = 0,
};
-static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
+static struct snd_akm4xxx akm_revo51_adc = {
.type = SND_AK5365,
.num_adcs = 2,
.adc_info = revo51_adc,
};
-static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_adc_priv = {
.caddr = 2,
.cif = 0,
.data_mask = VT1724_REVO_CDOUT,
@@ -346,7 +345,7 @@ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
AK_DAC("PCM Playback Volume", 2)
};
-static struct snd_akm4xxx akm_ap192 __devinitdata = {
+static struct snd_akm4xxx akm_ap192 = {
.type = SND_AK4358,
.num_dacs = 2,
.ops = {
@@ -355,7 +354,7 @@ static struct snd_akm4xxx akm_ap192 __devinitdata = {
.dac_info = ap192_dac,
};
-static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ap192_priv = {
.caddr = 2,
.cif = 0,
.data_mask = VT1724_REVO_CDOUT,
@@ -468,7 +467,7 @@ static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
return data;
}
-static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
+static int ap192_ak4114_init(struct snd_ice1712 *ice)
{
static const unsigned char ak4114_init_vals[] = {
AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
@@ -496,7 +495,7 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
return 0; /* error ignored; it's no fatal error */
}
-static int __devinit revo_init(struct snd_ice1712 *ice)
+static int revo_init(struct snd_ice1712 *ice)
{
struct snd_akm4xxx *ak;
int err;
@@ -574,7 +573,7 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
}
-static int __devinit revo_add_controls(struct snd_ice1712 *ice)
+static int revo_add_controls(struct snd_ice1712 *ice)
{
struct revo51_spec *spec;
int err;
@@ -607,7 +606,7 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
}
/* entry point */
-struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_revo_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_REVOLUTION71,
.name = "M Audio Revolution-7.1",
diff --git a/sound/pci/ice1712/se.c b/sound/pci/ice1712/se.c
index 69673b95869d..ffd894bb4507 100644
--- a/sound/pci/ice1712/se.c
+++ b/sound/pci/ice1712/se.c
@@ -22,7 +22,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -114,7 +113,7 @@ struct se_spec {
/* WM8740 interface */
/****************************************************************************/
-static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
+static void se200pci_WM8740_init(struct snd_ice1712 *ice)
{
/* nothing to do */
}
@@ -196,7 +195,7 @@ static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
}
}
-static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
+static void se200pci_WM8766_init(struct snd_ice1712 *ice)
{
se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
udelay(10);
@@ -253,7 +252,7 @@ static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
}
-static const char *se200pci_sel[] = {
+static const char * const se200pci_sel[] = {
"LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
};
@@ -278,7 +277,7 @@ static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
se200pci_WM8776_write(ice, 0x16, 0x001);
}
-static const char *se200pci_agc[] = {
+static const char * const se200pci_agc[] = {
"Off", "LimiterMode", "ALCMode", NULL
};
@@ -300,10 +299,10 @@ static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
}
}
-static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
+static void se200pci_WM8776_init(struct snd_ice1712 *ice)
{
int i;
- static unsigned short __devinitdata default_values[] = {
+ static unsigned short default_values[] = {
0x100, 0x100, 0x100,
0x100, 0x100, 0x100,
0x000, 0x090, 0x000, 0x000,
@@ -352,7 +351,7 @@ static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
}
struct se200pci_control {
- char *name;
+ const char *name;
enum {
WM8766,
WM8776in,
@@ -363,7 +362,7 @@ struct se200pci_control {
} target;
enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
int ch;
- const char **member;
+ const char * const *member;
const char *comment;
};
@@ -421,7 +420,7 @@ static const struct se200pci_control se200pci_cont[] = {
static int se200pci_get_enum_count(int n)
{
- const char **member;
+ const char * const *member;
int c;
member = se200pci_cont[n].member;
@@ -600,7 +599,7 @@ static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
-static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
+static int se200pci_add_controls(struct snd_ice1712 *ice)
{
int i;
struct snd_kcontrol_new cont;
@@ -678,7 +677,7 @@ static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
/* probe/initialize/setup */
/****************************************************************************/
-static int __devinit se_init(struct snd_ice1712 *ice)
+static int se_init(struct snd_ice1712 *ice)
{
struct se_spec *spec;
@@ -706,7 +705,7 @@ static int __devinit se_init(struct snd_ice1712 *ice)
return -ENOENT;
}
-static int __devinit se_add_controls(struct snd_ice1712 *ice)
+static int se_add_controls(struct snd_ice1712 *ice)
{
int err;
@@ -723,7 +722,7 @@ static int __devinit se_add_controls(struct snd_ice1712 *ice)
/* entry point */
/****************************************************************************/
-static unsigned char se200pci_eeprom[] __devinitdata = {
+static unsigned char se200pci_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
@@ -742,7 +741,7 @@ static unsigned char se200pci_eeprom[] __devinitdata = {
[ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */
};
-static unsigned char se90pci_eeprom[] __devinitdata = {
+static unsigned char se90pci_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
@@ -751,7 +750,7 @@ static unsigned char se90pci_eeprom[] __devinitdata = {
/* ALL GPIO bits are in input mode */
};
-struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_SE200PCI,
.name = "ONKYO SE200PCI",
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 4c551e147c08..5dbb867e642c 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -21,7 +21,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -32,7 +31,7 @@
#include "vt1720_mobo.h"
-static int __devinit k8x800_init(struct snd_ice1712 *ice)
+static int k8x800_init(struct snd_ice1712 *ice)
{
ice->vt1720 = 1;
@@ -46,7 +45,7 @@ static int __devinit k8x800_init(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
+static int k8x800_add_controls(struct snd_ice1712 *ice)
{
/* FIXME: needs some quirks for VT1616? */
return 0;
@@ -54,7 +53,7 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
/* EEPROM image */
-static unsigned char k8x800_eeprom[] __devinitdata = {
+static unsigned char k8x800_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */
[ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */
[ICE_EEP2_I2S] = 0x00, /* - */
@@ -70,7 +69,7 @@ static unsigned char k8x800_eeprom[] __devinitdata = {
[ICE_EEP2_GPIO_STATE2] = 0x00, /* - */
};
-static unsigned char sn25p_eeprom[] __devinitdata = {
+static unsigned char sn25p_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */
[ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */
[ICE_EEP2_I2S] = 0x00, /* - */
@@ -88,7 +87,7 @@ static unsigned char sn25p_eeprom[] __devinitdata = {
/* entry point */
-struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] = {
{
.subvendor = VT1720_SUBDEVICE_K8X800,
.name = "Albatron K8X800 Pro II",
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c
new file mode 100644
index 000000000000..8072adeecf68
--- /dev/null
+++ b/sound/pci/ice1712/wm8766.c
@@ -0,0 +1,361 @@
+/*
+ * ALSA driver for ICEnsemble VT17xx
+ *
+ * Lowlevel functions for WM8766 codec
+ *
+ * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8766.h"
+
+/* low-level access */
+
+static void snd_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+ if (addr < WM8766_REG_RESET)
+ wm->regs[addr] = data;
+ wm->ops.write(wm, addr, data);
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8766_tlv, -12750, 50, 1);
+
+static struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = {
+ [WM8766_CTL_CH1_VOL] = {
+ .name = "Channel 1 Playback Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8766_tlv,
+ .reg1 = WM8766_REG_DACL1,
+ .reg2 = WM8766_REG_DACR1,
+ .mask1 = WM8766_VOL_MASK,
+ .mask2 = WM8766_VOL_MASK,
+ .max = 0xff,
+ .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+ },
+ [WM8766_CTL_CH2_VOL] = {
+ .name = "Channel 2 Playback Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8766_tlv,
+ .reg1 = WM8766_REG_DACL2,
+ .reg2 = WM8766_REG_DACR2,
+ .mask1 = WM8766_VOL_MASK,
+ .mask2 = WM8766_VOL_MASK,
+ .max = 0xff,
+ .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+ },
+ [WM8766_CTL_CH3_VOL] = {
+ .name = "Channel 3 Playback Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8766_tlv,
+ .reg1 = WM8766_REG_DACL3,
+ .reg2 = WM8766_REG_DACR3,
+ .mask1 = WM8766_VOL_MASK,
+ .mask2 = WM8766_VOL_MASK,
+ .max = 0xff,
+ .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+ },
+ [WM8766_CTL_CH1_SW] = {
+ .name = "Channel 1 Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_MUTE1,
+ .flags = WM8766_FLAG_INVERT,
+ },
+ [WM8766_CTL_CH2_SW] = {
+ .name = "Channel 2 Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_MUTE2,
+ .flags = WM8766_FLAG_INVERT,
+ },
+ [WM8766_CTL_CH3_SW] = {
+ .name = "Channel 3 Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_MUTE3,
+ .flags = WM8766_FLAG_INVERT,
+ },
+ [WM8766_CTL_PHASE1_SW] = {
+ .name = "Channel 1 Phase Invert Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_IFCTRL,
+ .mask1 = WM8766_PHASE_INVERT1,
+ },
+ [WM8766_CTL_PHASE2_SW] = {
+ .name = "Channel 2 Phase Invert Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_IFCTRL,
+ .mask1 = WM8766_PHASE_INVERT2,
+ },
+ [WM8766_CTL_PHASE3_SW] = {
+ .name = "Channel 3 Phase Invert Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_IFCTRL,
+ .mask1 = WM8766_PHASE_INVERT3,
+ },
+ [WM8766_CTL_DEEMPH1_SW] = {
+ .name = "Channel 1 Deemphasis Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_DEEMP1,
+ },
+ [WM8766_CTL_DEEMPH2_SW] = {
+ .name = "Channel 2 Deemphasis Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_DEEMP2,
+ },
+ [WM8766_CTL_DEEMPH3_SW] = {
+ .name = "Channel 3 Deemphasis Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_DEEMP3,
+ },
+ [WM8766_CTL_IZD_SW] = {
+ .name = "Infinite Zero Detect Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL1,
+ .mask1 = WM8766_DAC_IZD,
+ },
+ [WM8766_CTL_ZC_SW] = {
+ .name = "Zero Cross Detect Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8766_REG_DACCTRL2,
+ .mask1 = WM8766_DAC2_ZCD,
+ .flags = WM8766_FLAG_INVERT,
+ },
+};
+
+/* exported functions */
+
+void snd_wm8766_init(struct snd_wm8766 *wm)
+{
+ int i;
+ static const u16 default_values[] = {
+ 0x000, 0x100,
+ 0x120, 0x000,
+ 0x000, 0x100, 0x000, 0x100, 0x000,
+ 0x000, 0x080,
+ };
+
+ memcpy(wm->ctl, snd_wm8766_default_ctl, sizeof(wm->ctl));
+
+ snd_wm8766_write(wm, WM8766_REG_RESET, 0x00); /* reset */
+ udelay(10);
+ /* load defaults */
+ for (i = 0; i < ARRAY_SIZE(default_values); i++)
+ snd_wm8766_write(wm, i, default_values[i]);
+}
+
+void snd_wm8766_resume(struct snd_wm8766 *wm)
+{
+ int i;
+
+ for (i = 0; i < WM8766_REG_COUNT; i++)
+ snd_wm8766_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac)
+{
+ u16 val = wm->regs[WM8766_REG_IFCTRL] & ~WM8766_IF_MASK;
+
+ dac &= WM8766_IF_MASK;
+ snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac);
+}
+
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode)
+{
+ u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK;
+
+ mode &= WM8766_DAC3_MSTR_MASK;
+ snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode);
+}
+
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power)
+{
+ u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK;
+
+ power &= WM8766_DAC3_POWER_MASK;
+ snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power);
+}
+
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm)
+{
+ u16 val = wm->regs[WM8766_REG_DACR1];
+ /* restore volume after MCLK stopped */
+ snd_wm8766_write(wm, WM8766_REG_DACR1, val | WM8766_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8766_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = (wm->ctl[n].flags & WM8766_FLAG_STEREO) ? 2 : 1;
+ uinfo->value.integer.min = wm->ctl[n].min;
+ uinfo->value.integer.max = wm->ctl[n].max;
+
+ return 0;
+}
+
+static int snd_wm8766_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+ wm->ctl[n].enum_names);
+}
+
+static int snd_wm8766_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+ u16 val1, val2;
+
+ if (wm->ctl[n].get)
+ wm->ctl[n].get(wm, &val1, &val2);
+ else {
+ val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+ val1 >>= __ffs(wm->ctl[n].mask1);
+ if (wm->ctl[n].flags & WM8766_FLAG_STEREO) {
+ val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+ val2 >>= __ffs(wm->ctl[n].mask2);
+ if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+ val2 &= ~WM8766_VOL_UPDATE;
+ }
+ }
+ if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+ val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+ val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+ }
+ ucontrol->value.integer.value[0] = val1;
+ if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
+ ucontrol->value.integer.value[1] = val2;
+
+ return 0;
+}
+
+static int snd_wm8766_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+ u16 val, regval1, regval2;
+
+ /* this also works for enum because value is an union */
+ regval1 = ucontrol->value.integer.value[0];
+ regval2 = ucontrol->value.integer.value[1];
+ if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+ regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+ regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+ }
+ if (wm->ctl[n].set)
+ wm->ctl[n].set(wm, regval1, regval2);
+ else {
+ val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+ val |= regval1 << __ffs(wm->ctl[n].mask1);
+ /* both stereo controls in one register */
+ if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+ wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+ val &= ~wm->ctl[n].mask2;
+ val |= regval2 << __ffs(wm->ctl[n].mask2);
+ }
+ snd_wm8766_write(wm, wm->ctl[n].reg1, val);
+ /* stereo controls in different registers */
+ if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+ wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+ val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+ val |= regval2 << __ffs(wm->ctl[n].mask2);
+ if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+ val |= WM8766_VOL_UPDATE;
+ snd_wm8766_write(wm, wm->ctl[n].reg2, val);
+ }
+ }
+
+ return 0;
+}
+
+static int snd_wm8766_add_control(struct snd_wm8766 *wm, int num)
+{
+ struct snd_kcontrol_new cont;
+ struct snd_kcontrol *ctl;
+
+ memset(&cont, 0, sizeof(cont));
+ cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ cont.private_value = num;
+ cont.name = wm->ctl[num].name;
+ cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ if (wm->ctl[num].flags & WM8766_FLAG_LIM ||
+ wm->ctl[num].flags & WM8766_FLAG_ALC)
+ cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ cont.tlv.p = NULL;
+ cont.get = snd_wm8766_ctl_get;
+ cont.put = snd_wm8766_ctl_put;
+
+ switch (wm->ctl[num].type) {
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ cont.info = snd_wm8766_volume_info;
+ cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+ cont.tlv.p = wm->ctl[num].tlv;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ wm->ctl[num].max = 1;
+ if (wm->ctl[num].flags & WM8766_FLAG_STEREO)
+ cont.info = snd_ctl_boolean_stereo_info;
+ else
+ cont.info = snd_ctl_boolean_mono_info;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ cont.info = snd_wm8766_enum_info;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ctl = snd_ctl_new1(&cont, wm);
+ if (!ctl)
+ return -ENOMEM;
+ wm->ctl[num].kctl = ctl;
+
+ return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8766_build_controls(struct snd_wm8766 *wm)
+{
+ int err, i;
+
+ for (i = 0; i < WM8766_CTL_COUNT; i++)
+ if (wm->ctl[i].name) {
+ err = snd_wm8766_add_control(wm, i);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/sound/pci/ice1712/wm8766.h b/sound/pci/ice1712/wm8766.h
new file mode 100644
index 000000000000..c119f84bd2c2
--- /dev/null
+++ b/sound/pci/ice1712/wm8766.h
@@ -0,0 +1,163 @@
+#ifndef __SOUND_WM8766_H
+#define __SOUND_WM8766_H
+
+/*
+ * ALSA driver for ICEnsemble VT17xx
+ *
+ * Lowlevel functions for WM8766 codec
+ *
+ * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define WM8766_REG_DACL1 0x00
+#define WM8766_REG_DACR1 0x01
+#define WM8766_VOL_MASK 0x1ff /* incl. update bit */
+#define WM8766_VOL_UPDATE (1 << 8) /* update volume */
+#define WM8766_REG_DACCTRL1 0x02
+#define WM8766_DAC_MUTEALL (1 << 0)
+#define WM8766_DAC_DEEMPALL (1 << 1)
+#define WM8766_DAC_PDWN (1 << 2)
+#define WM8766_DAC_ATC (1 << 3)
+#define WM8766_DAC_IZD (1 << 4)
+#define WM8766_DAC_PL_MASK 0x1e0
+#define WM8766_DAC_PL_LL (1 << 5) /* L chan: L signal */
+#define WM8766_DAC_PL_LR (2 << 5) /* L chan: R signal */
+#define WM8766_DAC_PL_LB (3 << 5) /* L chan: both */
+#define WM8766_DAC_PL_RL (1 << 7) /* R chan: L signal */
+#define WM8766_DAC_PL_RR (2 << 7) /* R chan: R signal */
+#define WM8766_DAC_PL_RB (3 << 7) /* R chan: both */
+#define WM8766_REG_IFCTRL 0x03
+#define WM8766_IF_FMT_RIGHTJ (0 << 0)
+#define WM8766_IF_FMT_LEFTJ (1 << 0)
+#define WM8766_IF_FMT_I2S (2 << 0)
+#define WM8766_IF_FMT_DSP (3 << 0)
+#define WM8766_IF_DSP_LATE (1 << 2) /* in DSP mode */
+#define WM8766_IF_LRC_INVERTED (1 << 2) /* in other modes */
+#define WM8766_IF_BCLK_INVERTED (1 << 3)
+#define WM8766_IF_IWL_16BIT (0 << 4)
+#define WM8766_IF_IWL_20BIT (1 << 4)
+#define WM8766_IF_IWL_24BIT (2 << 4)
+#define WM8766_IF_IWL_32BIT (3 << 4)
+#define WM8766_IF_MASK 0x3f
+#define WM8766_PHASE_INVERT1 (1 << 6)
+#define WM8766_PHASE_INVERT2 (1 << 7)
+#define WM8766_PHASE_INVERT3 (1 << 8)
+#define WM8766_REG_DACL2 0x04
+#define WM8766_REG_DACR2 0x05
+#define WM8766_REG_DACL3 0x06
+#define WM8766_REG_DACR3 0x07
+#define WM8766_REG_MASTDA 0x08
+#define WM8766_REG_DACCTRL2 0x09
+#define WM8766_DAC2_ZCD (1 << 0)
+#define WM8766_DAC2_ZFLAG_ALL (0 << 1)
+#define WM8766_DAC2_ZFLAG_1 (1 << 1)
+#define WM8766_DAC2_ZFLAG_2 (2 << 1)
+#define WM8766_DAC2_ZFLAG_3 (3 << 1)
+#define WM8766_DAC2_MUTE1 (1 << 3)
+#define WM8766_DAC2_MUTE2 (1 << 4)
+#define WM8766_DAC2_MUTE3 (1 << 5)
+#define WM8766_DAC2_DEEMP1 (1 << 6)
+#define WM8766_DAC2_DEEMP2 (1 << 7)
+#define WM8766_DAC2_DEEMP3 (1 << 8)
+#define WM8766_REG_DACCTRL3 0x0a
+#define WM8766_DAC3_DACPD1 (1 << 1)
+#define WM8766_DAC3_DACPD2 (1 << 2)
+#define WM8766_DAC3_DACPD3 (1 << 3)
+#define WM8766_DAC3_PWRDNALL (1 << 4)
+#define WM8766_DAC3_POWER_MASK 0x1e
+#define WM8766_DAC3_MASTER (1 << 5)
+#define WM8766_DAC3_DAC128FS (0 << 6)
+#define WM8766_DAC3_DAC192FS (1 << 6)
+#define WM8766_DAC3_DAC256FS (2 << 6)
+#define WM8766_DAC3_DAC384FS (3 << 6)
+#define WM8766_DAC3_DAC512FS (4 << 6)
+#define WM8766_DAC3_DAC768FS (5 << 6)
+#define WM8766_DAC3_MSTR_MASK 0x1e0
+#define WM8766_REG_MUTE1 0x0c
+#define WM8766_MUTE1_MPD (1 << 6)
+#define WM8766_REG_MUTE2 0x0f
+#define WM8766_MUTE2_MPD (1 << 5)
+#define WM8766_REG_RESET 0x1f
+
+#define WM8766_REG_COUNT 0x10 /* don't cache the RESET register */
+
+struct snd_wm8766;
+
+struct snd_wm8766_ops {
+ void (*write)(struct snd_wm8766 *wm, u16 addr, u16 data);
+};
+
+enum snd_wm8766_ctl_id {
+ WM8766_CTL_CH1_VOL,
+ WM8766_CTL_CH2_VOL,
+ WM8766_CTL_CH3_VOL,
+ WM8766_CTL_CH1_SW,
+ WM8766_CTL_CH2_SW,
+ WM8766_CTL_CH3_SW,
+ WM8766_CTL_PHASE1_SW,
+ WM8766_CTL_PHASE2_SW,
+ WM8766_CTL_PHASE3_SW,
+ WM8766_CTL_DEEMPH1_SW,
+ WM8766_CTL_DEEMPH2_SW,
+ WM8766_CTL_DEEMPH3_SW,
+ WM8766_CTL_IZD_SW,
+ WM8766_CTL_ZC_SW,
+
+ WM8766_CTL_COUNT,
+};
+
+#define WM8766_ENUM_MAX 16
+
+#define WM8766_FLAG_STEREO (1 << 0)
+#define WM8766_FLAG_VOL_UPDATE (1 << 1)
+#define WM8766_FLAG_INVERT (1 << 2)
+#define WM8766_FLAG_LIM (1 << 3)
+#define WM8766_FLAG_ALC (1 << 4)
+
+struct snd_wm8766_ctl {
+ struct snd_kcontrol *kctl;
+ const char *name;
+ snd_ctl_elem_type_t type;
+ const char *const enum_names[WM8766_ENUM_MAX];
+ const unsigned int *tlv;
+ u16 reg1, reg2, mask1, mask2, min, max, flags;
+ void (*set)(struct snd_wm8766 *wm, u16 ch1, u16 ch2);
+ void (*get)(struct snd_wm8766 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8766_agc_mode { WM8766_AGC_OFF, WM8766_AGC_LIM, WM8766_AGC_ALC };
+
+struct snd_wm8766 {
+ struct snd_card *card;
+ struct snd_wm8766_ctl ctl[WM8766_CTL_COUNT];
+ enum snd_wm8766_agc_mode agc_mode;
+ struct snd_wm8766_ops ops;
+ u16 regs[WM8766_REG_COUNT]; /* 9-bit registers */
+};
+
+
+
+void snd_wm8766_init(struct snd_wm8766 *wm);
+void snd_wm8766_resume(struct snd_wm8766 *wm);
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac);
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode);
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power);
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm);
+int snd_wm8766_build_controls(struct snd_wm8766 *wm);
+
+#endif /* __SOUND_WM8766_H */
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
new file mode 100644
index 000000000000..a3c05fe5daf9
--- /dev/null
+++ b/sound/pci/ice1712/wm8776.c
@@ -0,0 +1,633 @@
+/*
+ * ALSA driver for ICEnsemble VT17xx
+ *
+ * Lowlevel functions for WM8776 codec
+ *
+ * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8776.h"
+
+/* low-level access */
+
+static void snd_wm8776_write(struct snd_wm8776 *wm, u16 addr, u16 data)
+{
+ u8 bus_addr = addr << 1 | data >> 8; /* addr + 9th data bit */
+ u8 bus_data = data & 0xff; /* remaining 8 data bits */
+
+ if (addr < WM8776_REG_RESET)
+ wm->regs[addr] = data;
+ wm->ops.write(wm, bus_addr, bus_data);
+}
+
+/* register-level functions */
+
+static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm,
+ const char *ctl_name,
+ bool active)
+{
+ struct snd_card *card = wm->card;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
+ struct snd_ctl_elem_id elem_id;
+ unsigned int index_offset;
+
+ memset(&elem_id, 0, sizeof(elem_id));
+ strncpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ kctl = snd_ctl_find_id(card, &elem_id);
+ if (!kctl)
+ return;
+ index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
+ vd = &kctl->vd[index_offset];
+ if (active)
+ vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ else
+ vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
+}
+
+static void snd_wm8776_update_agc_ctl(struct snd_wm8776 *wm)
+{
+ int i, flags_on = 0, flags_off = 0;
+
+ switch (wm->agc_mode) {
+ case WM8776_AGC_OFF:
+ flags_off = WM8776_FLAG_LIM | WM8776_FLAG_ALC;
+ break;
+ case WM8776_AGC_LIM:
+ flags_off = WM8776_FLAG_ALC;
+ flags_on = WM8776_FLAG_LIM;
+ break;
+ case WM8776_AGC_ALC_R:
+ case WM8776_AGC_ALC_L:
+ case WM8776_AGC_ALC_STEREO:
+ flags_off = WM8776_FLAG_LIM;
+ flags_on = WM8776_FLAG_ALC;
+ break;
+ }
+
+ for (i = 0; i < WM8776_CTL_COUNT; i++)
+ if (wm->ctl[i].flags & flags_off)
+ snd_wm8776_activate_ctl(wm, wm->ctl[i].name, false);
+ else if (wm->ctl[i].flags & flags_on)
+ snd_wm8776_activate_ctl(wm, wm->ctl[i].name, true);
+}
+
+static void snd_wm8776_set_agc(struct snd_wm8776 *wm, u16 agc, u16 nothing)
+{
+ u16 alc1 = wm->regs[WM8776_REG_ALCCTRL1] & ~WM8776_ALC1_LCT_MASK;
+ u16 alc2 = wm->regs[WM8776_REG_ALCCTRL2] & ~WM8776_ALC2_LCEN;
+
+ switch (agc) {
+ case 0: /* Off */
+ wm->agc_mode = WM8776_AGC_OFF;
+ break;
+ case 1: /* Limiter */
+ alc2 |= WM8776_ALC2_LCEN;
+ wm->agc_mode = WM8776_AGC_LIM;
+ break;
+ case 2: /* ALC Right */
+ alc1 |= WM8776_ALC1_LCSEL_ALCR;
+ alc2 |= WM8776_ALC2_LCEN;
+ wm->agc_mode = WM8776_AGC_ALC_R;
+ break;
+ case 3: /* ALC Left */
+ alc1 |= WM8776_ALC1_LCSEL_ALCL;
+ alc2 |= WM8776_ALC2_LCEN;
+ wm->agc_mode = WM8776_AGC_ALC_L;
+ break;
+ case 4: /* ALC Stereo */
+ alc1 |= WM8776_ALC1_LCSEL_ALCSTEREO;
+ alc2 |= WM8776_ALC2_LCEN;
+ wm->agc_mode = WM8776_AGC_ALC_STEREO;
+ break;
+ }
+ snd_wm8776_write(wm, WM8776_REG_ALCCTRL1, alc1);
+ snd_wm8776_write(wm, WM8776_REG_ALCCTRL2, alc2);
+ snd_wm8776_update_agc_ctl(wm);
+}
+
+static void snd_wm8776_get_agc(struct snd_wm8776 *wm, u16 *mode, u16 *nothing)
+{
+ *mode = wm->agc_mode;
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8776_hp_tlv, -7400, 100, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_dac_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_adc_tlv, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_lct_tlv, -1600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_tlv, 0, 400, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_ngth_tlv, -7800, 600, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_tlv, -2100, 400, 0);
+
+static struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = {
+ [WM8776_CTL_DAC_VOL] = {
+ .name = "Master Playback Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_dac_tlv,
+ .reg1 = WM8776_REG_DACLVOL,
+ .reg2 = WM8776_REG_DACRVOL,
+ .mask1 = WM8776_DACVOL_MASK,
+ .mask2 = WM8776_DACVOL_MASK,
+ .max = 0xff,
+ .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+ },
+ [WM8776_CTL_DAC_SW] = {
+ .name = "Master Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_DACCTRL1,
+ .reg2 = WM8776_REG_DACCTRL1,
+ .mask1 = WM8776_DAC_PL_LL,
+ .mask2 = WM8776_DAC_PL_RR,
+ .flags = WM8776_FLAG_STEREO,
+ },
+ [WM8776_CTL_DAC_ZC_SW] = {
+ .name = "Master Zero Cross Detect Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_DACCTRL1,
+ .mask1 = WM8776_DAC_DZCEN,
+ },
+ [WM8776_CTL_HP_VOL] = {
+ .name = "Headphone Playback Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_hp_tlv,
+ .reg1 = WM8776_REG_HPLVOL,
+ .reg2 = WM8776_REG_HPRVOL,
+ .mask1 = WM8776_HPVOL_MASK,
+ .mask2 = WM8776_HPVOL_MASK,
+ .min = 0x2f,
+ .max = 0x7f,
+ .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+ },
+ [WM8776_CTL_HP_SW] = {
+ .name = "Headphone Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_PWRDOWN,
+ .mask1 = WM8776_PWR_HPPD,
+ .flags = WM8776_FLAG_INVERT,
+ },
+ [WM8776_CTL_HP_ZC_SW] = {
+ .name = "Headphone Zero Cross Detect Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_HPLVOL,
+ .reg2 = WM8776_REG_HPRVOL,
+ .mask1 = WM8776_VOL_HPZCEN,
+ .mask2 = WM8776_VOL_HPZCEN,
+ .flags = WM8776_FLAG_STEREO,
+ },
+ [WM8776_CTL_AUX_SW] = {
+ .name = "AUX Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_OUTMUX,
+ .mask1 = WM8776_OUTMUX_AUX,
+ },
+ [WM8776_CTL_BYPASS_SW] = {
+ .name = "Bypass Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_OUTMUX,
+ .mask1 = WM8776_OUTMUX_BYPASS,
+ },
+ [WM8776_CTL_DAC_IZD_SW] = {
+ .name = "Infinite Zero Detect Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_DACCTRL1,
+ .mask1 = WM8776_DAC_IZD,
+ },
+ [WM8776_CTL_PHASE_SW] = {
+ .name = "Phase Invert Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_PHASESWAP,
+ .reg2 = WM8776_REG_PHASESWAP,
+ .mask1 = WM8776_PHASE_INVERTL,
+ .mask2 = WM8776_PHASE_INVERTR,
+ .flags = WM8776_FLAG_STEREO,
+ },
+ [WM8776_CTL_DEEMPH_SW] = {
+ .name = "Deemphasis Playback Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_DACCTRL2,
+ .mask1 = WM8776_DAC2_DEEMPH,
+ },
+ [WM8776_CTL_ADC_VOL] = {
+ .name = "Input Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_adc_tlv,
+ .reg1 = WM8776_REG_ADCLVOL,
+ .reg2 = WM8776_REG_ADCRVOL,
+ .mask1 = WM8776_ADC_GAIN_MASK,
+ .mask2 = WM8776_ADC_GAIN_MASK,
+ .max = 0xff,
+ .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+ },
+ [WM8776_CTL_ADC_SW] = {
+ .name = "Input Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .reg2 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUTEL,
+ .mask2 = WM8776_ADC_MUTER,
+ .flags = WM8776_FLAG_STEREO | WM8776_FLAG_INVERT,
+ },
+ [WM8776_CTL_INPUT1_SW] = {
+ .name = "AIN1 Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUX_AIN1,
+ },
+ [WM8776_CTL_INPUT2_SW] = {
+ .name = "AIN2 Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUX_AIN2,
+ },
+ [WM8776_CTL_INPUT3_SW] = {
+ .name = "AIN3 Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUX_AIN3,
+ },
+ [WM8776_CTL_INPUT4_SW] = {
+ .name = "AIN4 Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUX_AIN4,
+ },
+ [WM8776_CTL_INPUT5_SW] = {
+ .name = "AIN5 Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_ADCMUX,
+ .mask1 = WM8776_ADC_MUX_AIN5,
+ },
+ [WM8776_CTL_AGC_SEL] = {
+ .name = "AGC Select Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "Off", "Limiter", "ALC Right", "ALC Left",
+ "ALC Stereo" },
+ .max = 5, /* .enum_names item count */
+ .set = snd_wm8776_set_agc,
+ .get = snd_wm8776_get_agc,
+ },
+ [WM8776_CTL_LIM_THR] = {
+ .name = "Limiter Threshold Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_lct_tlv,
+ .reg1 = WM8776_REG_ALCCTRL1,
+ .mask1 = WM8776_ALC1_LCT_MASK,
+ .max = 15,
+ .flags = WM8776_FLAG_LIM,
+ },
+ [WM8776_CTL_LIM_ATK] = {
+ .name = "Limiter Attack Time Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "0.25 ms", "0.5 ms", "1 ms", "2 ms", "4 ms",
+ "8 ms", "16 ms", "32 ms", "64 ms", "128 ms", "256 ms" },
+ .max = 11, /* .enum_names item count */
+ .reg1 = WM8776_REG_ALCCTRL3,
+ .mask1 = WM8776_ALC3_ATK_MASK,
+ .flags = WM8776_FLAG_LIM,
+ },
+ [WM8776_CTL_LIM_DCY] = {
+ .name = "Limiter Decay Time Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
+ "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", "307 ms",
+ "614 ms", "1.23 s" },
+ .max = 11, /* .enum_names item count */
+ .reg1 = WM8776_REG_ALCCTRL3,
+ .mask1 = WM8776_ALC3_DCY_MASK,
+ .flags = WM8776_FLAG_LIM,
+ },
+ [WM8776_CTL_LIM_TRANWIN] = {
+ .name = "Limiter Transient Window Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "0 us", "62.5 us", "125 us", "250 us", "500 us",
+ "1 ms", "2 ms", "4 ms" },
+ .max = 8, /* .enum_names item count */
+ .reg1 = WM8776_REG_LIMITER,
+ .mask1 = WM8776_LIM_TRANWIN_MASK,
+ .flags = WM8776_FLAG_LIM,
+ },
+ [WM8776_CTL_LIM_MAXATTN] = {
+ .name = "Limiter Maximum Attenuation Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_maxatten_lim_tlv,
+ .reg1 = WM8776_REG_LIMITER,
+ .mask1 = WM8776_LIM_MAXATTEN_MASK,
+ .min = 3,
+ .max = 12,
+ .flags = WM8776_FLAG_LIM | WM8776_FLAG_INVERT,
+ },
+ [WM8776_CTL_ALC_TGT] = {
+ .name = "ALC Target Level Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_lct_tlv,
+ .reg1 = WM8776_REG_ALCCTRL1,
+ .mask1 = WM8776_ALC1_LCT_MASK,
+ .max = 15,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_ALC_ATK] = {
+ .name = "ALC Attack Time Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
+ "134 ms", "269 ms", "538 ms", "1.08 s", "2.15 s",
+ "4.3 s", "8.6 s" },
+ .max = 11, /* .enum_names item count */
+ .reg1 = WM8776_REG_ALCCTRL3,
+ .mask1 = WM8776_ALC3_ATK_MASK,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_ALC_DCY] = {
+ .name = "ALC Decay Time Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "33.5 ms", "67.0 ms", "134 ms", "268 ms",
+ "536 ms", "1.07 s", "2.14 s", "4.29 s", "8.58 s",
+ "17.2 s", "34.3 s" },
+ .max = 11, /* .enum_names item count */
+ .reg1 = WM8776_REG_ALCCTRL3,
+ .mask1 = WM8776_ALC3_DCY_MASK,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_ALC_MAXGAIN] = {
+ .name = "ALC Maximum Gain Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_maxgain_tlv,
+ .reg1 = WM8776_REG_ALCCTRL1,
+ .mask1 = WM8776_ALC1_MAXGAIN_MASK,
+ .min = 1,
+ .max = 7,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_ALC_MAXATTN] = {
+ .name = "ALC Maximum Attenuation Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_maxatten_alc_tlv,
+ .reg1 = WM8776_REG_LIMITER,
+ .mask1 = WM8776_LIM_MAXATTEN_MASK,
+ .min = 10,
+ .max = 15,
+ .flags = WM8776_FLAG_ALC | WM8776_FLAG_INVERT,
+ },
+ [WM8776_CTL_ALC_HLD] = {
+ .name = "ALC Hold Time Capture Enum",
+ .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+ .enum_names = { "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
+ "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", "341 ms",
+ "683 ms", "1.37 s", "2.73 s", "5.46 s", "10.9 s",
+ "21.8 s", "43.7 s" },
+ .max = 16, /* .enum_names item count */
+ .reg1 = WM8776_REG_ALCCTRL2,
+ .mask1 = WM8776_ALC2_HOLD_MASK,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_NGT_SW] = {
+ .name = "Noise Gate Capture Switch",
+ .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+ .reg1 = WM8776_REG_NOISEGATE,
+ .mask1 = WM8776_NGAT_ENABLE,
+ .flags = WM8776_FLAG_ALC,
+ },
+ [WM8776_CTL_NGT_THR] = {
+ .name = "Noise Gate Threshold Capture Volume",
+ .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+ .tlv = wm8776_ngth_tlv,
+ .reg1 = WM8776_REG_NOISEGATE,
+ .mask1 = WM8776_NGAT_THR_MASK,
+ .max = 7,
+ .flags = WM8776_FLAG_ALC,
+ },
+};
+
+/* exported functions */
+
+void snd_wm8776_init(struct snd_wm8776 *wm)
+{
+ int i;
+ static const u16 default_values[] = {
+ 0x000, 0x100, 0x000,
+ 0x000, 0x100, 0x000,
+ 0x000, 0x090, 0x000, 0x000,
+ 0x022, 0x022, 0x022,
+ 0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
+ 0x032, 0x000, 0x0a6, 0x001, 0x001
+ };
+
+ memcpy(wm->ctl, snd_wm8776_default_ctl, sizeof(wm->ctl));
+
+ snd_wm8776_write(wm, WM8776_REG_RESET, 0x00); /* reset */
+ udelay(10);
+ /* load defaults */
+ for (i = 0; i < ARRAY_SIZE(default_values); i++)
+ snd_wm8776_write(wm, i, default_values[i]);
+}
+
+void snd_wm8776_resume(struct snd_wm8776 *wm)
+{
+ int i;
+
+ for (i = 0; i < WM8776_REG_COUNT; i++)
+ snd_wm8776_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac)
+{
+ snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac);
+}
+
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc)
+{
+ snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc);
+}
+
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode)
+{
+ snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode);
+}
+
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power)
+{
+ snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power);
+}
+
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm)
+{
+ u16 val = wm->regs[WM8776_REG_DACRVOL];
+ /* restore volume after MCLK stopped */
+ snd_wm8776_write(wm, WM8776_REG_DACRVOL, val | WM8776_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8776_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = (wm->ctl[n].flags & WM8776_FLAG_STEREO) ? 2 : 1;
+ uinfo->value.integer.min = wm->ctl[n].min;
+ uinfo->value.integer.max = wm->ctl[n].max;
+
+ return 0;
+}
+
+static int snd_wm8776_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+
+ return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+ wm->ctl[n].enum_names);
+}
+
+static int snd_wm8776_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+ u16 val1, val2;
+
+ if (wm->ctl[n].get)
+ wm->ctl[n].get(wm, &val1, &val2);
+ else {
+ val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+ val1 >>= __ffs(wm->ctl[n].mask1);
+ if (wm->ctl[n].flags & WM8776_FLAG_STEREO) {
+ val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+ val2 >>= __ffs(wm->ctl[n].mask2);
+ if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+ val2 &= ~WM8776_VOL_UPDATE;
+ }
+ }
+ if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+ val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+ val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+ }
+ ucontrol->value.integer.value[0] = val1;
+ if (wm->ctl[n].flags & WM8776_FLAG_STEREO)
+ ucontrol->value.integer.value[1] = val2;
+
+ return 0;
+}
+
+static int snd_wm8776_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+ int n = kcontrol->private_value;
+ u16 val, regval1, regval2;
+
+ /* this also works for enum because value is an union */
+ regval1 = ucontrol->value.integer.value[0];
+ regval2 = ucontrol->value.integer.value[1];
+ if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+ regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+ regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+ }
+ if (wm->ctl[n].set)
+ wm->ctl[n].set(wm, regval1, regval2);
+ else {
+ val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+ val |= regval1 << __ffs(wm->ctl[n].mask1);
+ /* both stereo controls in one register */
+ if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+ wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+ val &= ~wm->ctl[n].mask2;
+ val |= regval2 << __ffs(wm->ctl[n].mask2);
+ }
+ snd_wm8776_write(wm, wm->ctl[n].reg1, val);
+ /* stereo controls in different registers */
+ if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+ wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+ val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+ val |= regval2 << __ffs(wm->ctl[n].mask2);
+ if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+ val |= WM8776_VOL_UPDATE;
+ snd_wm8776_write(wm, wm->ctl[n].reg2, val);
+ }
+ }
+
+ return 0;
+}
+
+static int snd_wm8776_add_control(struct snd_wm8776 *wm, int num)
+{
+ struct snd_kcontrol_new cont;
+ struct snd_kcontrol *ctl;
+
+ memset(&cont, 0, sizeof(cont));
+ cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ cont.private_value = num;
+ cont.name = wm->ctl[num].name;
+ cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ if (wm->ctl[num].flags & WM8776_FLAG_LIM ||
+ wm->ctl[num].flags & WM8776_FLAG_ALC)
+ cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ cont.tlv.p = NULL;
+ cont.get = snd_wm8776_ctl_get;
+ cont.put = snd_wm8776_ctl_put;
+
+ switch (wm->ctl[num].type) {
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ cont.info = snd_wm8776_volume_info;
+ cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+ cont.tlv.p = wm->ctl[num].tlv;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ wm->ctl[num].max = 1;
+ if (wm->ctl[num].flags & WM8776_FLAG_STEREO)
+ cont.info = snd_ctl_boolean_stereo_info;
+ else
+ cont.info = snd_ctl_boolean_mono_info;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ cont.info = snd_wm8776_enum_info;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ctl = snd_ctl_new1(&cont, wm);
+ if (!ctl)
+ return -ENOMEM;
+
+ return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8776_build_controls(struct snd_wm8776 *wm)
+{
+ int err, i;
+
+ for (i = 0; i < WM8776_CTL_COUNT; i++)
+ if (wm->ctl[i].name) {
+ err = snd_wm8776_add_control(wm, i);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/sound/pci/ice1712/wm8776.h b/sound/pci/ice1712/wm8776.h
new file mode 100644
index 000000000000..93a2d6971154
--- /dev/null
+++ b/sound/pci/ice1712/wm8776.h
@@ -0,0 +1,226 @@
+#ifndef __SOUND_WM8776_H
+#define __SOUND_WM8776_H
+
+/*
+ * ALSA driver for ICEnsemble VT17xx
+ *
+ * Lowlevel functions for WM8776 codec
+ *
+ * Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define WM8776_REG_HPLVOL 0x00
+#define WM8776_REG_HPRVOL 0x01
+#define WM8776_REG_HPMASTER 0x02
+#define WM8776_HPVOL_MASK 0x17f /* incl. update bit */
+#define WM8776_VOL_HPZCEN (1 << 7) /* zero cross detect */
+#define WM8776_VOL_UPDATE (1 << 8) /* update volume */
+#define WM8776_REG_DACLVOL 0x03
+#define WM8776_REG_DACRVOL 0x04
+#define WM8776_REG_DACMASTER 0x05
+#define WM8776_DACVOL_MASK 0x1ff /* incl. update bit */
+#define WM8776_REG_PHASESWAP 0x06
+#define WM8776_PHASE_INVERTL (1 << 0)
+#define WM8776_PHASE_INVERTR (1 << 1)
+#define WM8776_REG_DACCTRL1 0x07
+#define WM8776_DAC_DZCEN (1 << 0)
+#define WM8776_DAC_ATC (1 << 1)
+#define WM8776_DAC_IZD (1 << 2)
+#define WM8776_DAC_TOD (1 << 3)
+#define WM8776_DAC_PL_MASK 0xf0
+#define WM8776_DAC_PL_LL (1 << 4) /* L chan: L signal */
+#define WM8776_DAC_PL_LR (2 << 4) /* L chan: R signal */
+#define WM8776_DAC_PL_LB (3 << 4) /* L chan: both */
+#define WM8776_DAC_PL_RL (1 << 6) /* R chan: L signal */
+#define WM8776_DAC_PL_RR (2 << 6) /* R chan: R signal */
+#define WM8776_DAC_PL_RB (3 << 6) /* R chan: both */
+#define WM8776_REG_DACMUTE 0x08
+#define WM8776_DACMUTE (1 << 0)
+#define WM8776_REG_DACCTRL2 0x09
+#define WM8776_DAC2_DEEMPH (1 << 0)
+#define WM8776_DAC2_ZFLAG_DISABLE (0 << 1)
+#define WM8776_DAC2_ZFLAG_OWN (1 << 1)
+#define WM8776_DAC2_ZFLAG_BOTH (2 << 1)
+#define WM8776_DAC2_ZFLAG_EITHER (3 << 1)
+#define WM8776_REG_DACIFCTRL 0x0a
+#define WM8776_FMT_RIGHTJ (0 << 0)
+#define WM8776_FMT_LEFTJ (1 << 0)
+#define WM8776_FMT_I2S (2 << 0)
+#define WM8776_FMT_DSP (3 << 0)
+#define WM8776_FMT_DSP_LATE (1 << 2) /* in DSP mode */
+#define WM8776_FMT_LRC_INVERTED (1 << 2) /* in other modes */
+#define WM8776_FMT_BCLK_INVERTED (1 << 3)
+#define WM8776_FMT_16BIT (0 << 4)
+#define WM8776_FMT_20BIT (1 << 4)
+#define WM8776_FMT_24BIT (2 << 4)
+#define WM8776_FMT_32BIT (3 << 4)
+#define WM8776_REG_ADCIFCTRL 0x0b
+#define WM8776_FMT_ADCMCLK_INVERTED (1 << 6)
+#define WM8776_FMT_ADCHPD (1 << 8)
+#define WM8776_REG_MSTRCTRL 0x0c
+#define WM8776_IF_ADC256FS (2 << 0)
+#define WM8776_IF_ADC384FS (3 << 0)
+#define WM8776_IF_ADC512FS (4 << 0)
+#define WM8776_IF_ADC768FS (5 << 0)
+#define WM8776_IF_OVERSAMP64 (1 << 3)
+#define WM8776_IF_DAC128FS (0 << 4)
+#define WM8776_IF_DAC192FS (1 << 4)
+#define WM8776_IF_DAC256FS (2 << 4)
+#define WM8776_IF_DAC384FS (3 << 4)
+#define WM8776_IF_DAC512FS (4 << 4)
+#define WM8776_IF_DAC768FS (5 << 4)
+#define WM8776_IF_DAC_MASTER (1 << 7)
+#define WM8776_IF_ADC_MASTER (1 << 8)
+#define WM8776_REG_PWRDOWN 0x0d
+#define WM8776_PWR_PDWN (1 << 0)
+#define WM8776_PWR_ADCPD (1 << 1)
+#define WM8776_PWR_DACPD (1 << 2)
+#define WM8776_PWR_HPPD (1 << 3)
+#define WM8776_PWR_AINPD (1 << 6)
+#define WM8776_REG_ADCLVOL 0x0e
+#define WM8776_REG_ADCRVOL 0x0f
+#define WM8776_ADC_GAIN_MASK 0xff
+#define WM8776_ADC_ZCEN (1 << 8)
+#define WM8776_REG_ALCCTRL1 0x10
+#define WM8776_ALC1_LCT_MASK 0x0f /* 0=-16dB, 1=-15dB..15=-1dB */
+#define WM8776_ALC1_MAXGAIN_MASK 0x70 /* 0,1=0dB, 2=+4dB...7=+24dB */
+#define WM8776_ALC1_LCSEL_MASK 0x180
+#define WM8776_ALC1_LCSEL_LIMITER (0 << 7)
+#define WM8776_ALC1_LCSEL_ALCR (1 << 7)
+#define WM8776_ALC1_LCSEL_ALCL (2 << 7)
+#define WM8776_ALC1_LCSEL_ALCSTEREO (3 << 7)
+#define WM8776_REG_ALCCTRL2 0x11
+#define WM8776_ALC2_HOLD_MASK 0x0f /*0=0ms, 1=2.67ms, 2=5.33ms.. */
+#define WM8776_ALC2_ZCEN (1 << 7)
+#define WM8776_ALC2_LCEN (1 << 8)
+#define WM8776_REG_ALCCTRL3 0x12
+#define WM8776_ALC3_ATK_MASK 0x0f
+#define WM8776_ALC3_DCY_MASK 0xf0
+#define WM8776_ALC3_FDECAY (1 << 8)
+#define WM8776_REG_NOISEGATE 0x13
+#define WM8776_NGAT_ENABLE (1 << 0)
+#define WM8776_NGAT_THR_MASK 0x1c /*0=-78dB, 1=-72dB...7=-36dB */
+#define WM8776_REG_LIMITER 0x14
+#define WM8776_LIM_MAXATTEN_MASK 0x0f
+#define WM8776_LIM_TRANWIN_MASK 0x70 /*0=0us, 1=62.5us, 2=125us.. */
+#define WM8776_REG_ADCMUX 0x15
+#define WM8776_ADC_MUX_AIN1 (1 << 0)
+#define WM8776_ADC_MUX_AIN2 (1 << 1)
+#define WM8776_ADC_MUX_AIN3 (1 << 2)
+#define WM8776_ADC_MUX_AIN4 (1 << 3)
+#define WM8776_ADC_MUX_AIN5 (1 << 4)
+#define WM8776_ADC_MUTER (1 << 6)
+#define WM8776_ADC_MUTEL (1 << 7)
+#define WM8776_ADC_LRBOTH (1 << 8)
+#define WM8776_REG_OUTMUX 0x16
+#define WM8776_OUTMUX_DAC (1 << 0)
+#define WM8776_OUTMUX_AUX (1 << 1)
+#define WM8776_OUTMUX_BYPASS (1 << 2)
+#define WM8776_REG_RESET 0x17
+
+#define WM8776_REG_COUNT 0x17 /* don't cache the RESET register */
+
+struct snd_wm8776;
+
+struct snd_wm8776_ops {
+ void (*write)(struct snd_wm8776 *wm, u8 addr, u8 data);
+};
+
+enum snd_wm8776_ctl_id {
+ WM8776_CTL_DAC_VOL,
+ WM8776_CTL_DAC_SW,
+ WM8776_CTL_DAC_ZC_SW,
+ WM8776_CTL_HP_VOL,
+ WM8776_CTL_HP_SW,
+ WM8776_CTL_HP_ZC_SW,
+ WM8776_CTL_AUX_SW,
+ WM8776_CTL_BYPASS_SW,
+ WM8776_CTL_DAC_IZD_SW,
+ WM8776_CTL_PHASE_SW,
+ WM8776_CTL_DEEMPH_SW,
+ WM8776_CTL_ADC_VOL,
+ WM8776_CTL_ADC_SW,
+ WM8776_CTL_INPUT1_SW,
+ WM8776_CTL_INPUT2_SW,
+ WM8776_CTL_INPUT3_SW,
+ WM8776_CTL_INPUT4_SW,
+ WM8776_CTL_INPUT5_SW,
+ WM8776_CTL_AGC_SEL,
+ WM8776_CTL_LIM_THR,
+ WM8776_CTL_LIM_ATK,
+ WM8776_CTL_LIM_DCY,
+ WM8776_CTL_LIM_TRANWIN,
+ WM8776_CTL_LIM_MAXATTN,
+ WM8776_CTL_ALC_TGT,
+ WM8776_CTL_ALC_ATK,
+ WM8776_CTL_ALC_DCY,
+ WM8776_CTL_ALC_MAXGAIN,
+ WM8776_CTL_ALC_MAXATTN,
+ WM8776_CTL_ALC_HLD,
+ WM8776_CTL_NGT_SW,
+ WM8776_CTL_NGT_THR,
+
+ WM8776_CTL_COUNT,
+};
+
+#define WM8776_ENUM_MAX 16
+
+#define WM8776_FLAG_STEREO (1 << 0)
+#define WM8776_FLAG_VOL_UPDATE (1 << 1)
+#define WM8776_FLAG_INVERT (1 << 2)
+#define WM8776_FLAG_LIM (1 << 3)
+#define WM8776_FLAG_ALC (1 << 4)
+
+struct snd_wm8776_ctl {
+ const char *name;
+ snd_ctl_elem_type_t type;
+ const char *const enum_names[WM8776_ENUM_MAX];
+ const unsigned int *tlv;
+ u16 reg1, reg2, mask1, mask2, min, max, flags;
+ void (*set)(struct snd_wm8776 *wm, u16 ch1, u16 ch2);
+ void (*get)(struct snd_wm8776 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8776_agc_mode {
+ WM8776_AGC_OFF,
+ WM8776_AGC_LIM,
+ WM8776_AGC_ALC_R,
+ WM8776_AGC_ALC_L,
+ WM8776_AGC_ALC_STEREO
+};
+
+struct snd_wm8776 {
+ struct snd_card *card;
+ struct snd_wm8776_ctl ctl[WM8776_CTL_COUNT];
+ enum snd_wm8776_agc_mode agc_mode;
+ struct snd_wm8776_ops ops;
+ u16 regs[WM8776_REG_COUNT]; /* 9-bit registers */
+};
+
+
+
+void snd_wm8776_init(struct snd_wm8776 *wm);
+void snd_wm8776_resume(struct snd_wm8776 *wm);
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac);
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc);
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode);
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power);
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm);
+int snd_wm8776_build_controls(struct snd_wm8776 *wm);
+
+#endif /* __SOUND_WM8776_H */
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
index e618f789026e..bcf30a387b87 100644
--- a/sound/pci/ice1712/wtm.c
+++ b/sound/pci/ice1712/wtm.c
@@ -25,7 +25,6 @@
-#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -384,7 +383,7 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
/*
* Control tabs
*/
-static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac9640_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -448,7 +447,7 @@ static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
/*INIT*/
-static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
+static int wtm_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -462,7 +461,7 @@ static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
return 0;
}
-static int __devinit wtm_init(struct snd_ice1712 *ice)
+static int wtm_init(struct snd_ice1712 *ice)
{
static unsigned short stac_inits_prodigy[] = {
STAC946X_RESET, 0,
@@ -485,7 +484,7 @@ static int __devinit wtm_init(struct snd_ice1712 *ice)
}
-static unsigned char wtm_eeprom[] __devinitdata = {
+static unsigned char wtm_eeprom[] = {
0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
0x80, /* ACLINK : I2S */
0xf8, /* I2S: vol; 96k, 24bit, 192k */
@@ -503,7 +502,7 @@ static unsigned char wtm_eeprom[] __devinitdata = {
/*entry point*/
-struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
{
.subvendor = VT1724_SUBDEVICE_WTM,
.name = "ESI Waveterminal 192M",
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index ea4b706c8d63..3b9be752f3e2 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -592,8 +592,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
return res;
}
-static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip,
- unsigned int codec)
+static void snd_intel8x0_codec_read_test(struct intel8x0 *chip,
+ unsigned int codec)
{
unsigned int tmp;
@@ -1507,8 +1507,8 @@ struct ich_pcm_table {
int ac97_idx;
};
-static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
- struct ich_pcm_table *rec)
+static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
+ struct ich_pcm_table *rec)
{
struct snd_pcm *pcm;
int err;
@@ -1564,7 +1564,7 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
return 0;
}
-static struct ich_pcm_table intel_pcms[] __devinitdata = {
+static struct ich_pcm_table intel_pcms[] = {
{
.playback_ops = &snd_intel8x0_playback_ops,
.capture_ops = &snd_intel8x0_capture_ops,
@@ -1601,7 +1601,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
},
};
-static struct ich_pcm_table nforce_pcms[] __devinitdata = {
+static struct ich_pcm_table nforce_pcms[] = {
{
.playback_ops = &snd_intel8x0_playback_ops,
.capture_ops = &snd_intel8x0_capture_ops,
@@ -1624,7 +1624,7 @@ static struct ich_pcm_table nforce_pcms[] __devinitdata = {
},
};
-static struct ich_pcm_table ali_pcms[] __devinitdata = {
+static struct ich_pcm_table ali_pcms[] = {
{
.playback_ops = &snd_intel8x0_ali_playback_ops,
.capture_ops = &snd_intel8x0_ali_capture_ops,
@@ -1656,7 +1656,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
#endif
};
-static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
+static int snd_intel8x0_pcm(struct intel8x0 *chip)
{
int i, tblsize, device, err;
struct ich_pcm_table *tbl, *rec;
@@ -1719,7 +1719,7 @@ static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
chip->ac97[ac97->num] = NULL;
}
-static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
+static struct ac97_pcm ac97_pcm_defs[] = {
/* front PCM */
{
.exclusive = 1,
@@ -1789,7 +1789,7 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
},
};
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
{
.subvendor = 0x0e11,
.subdevice = 0x000e,
@@ -2196,8 +2196,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
{ } /* terminator */
};
-static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
- const char *quirk_override)
+static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+ const char *quirk_override)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -2765,7 +2765,7 @@ static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume);
#define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */
-static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
{
struct snd_pcm_substream *subs;
struct ichdev *ichdev;
@@ -2883,7 +2883,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
}
-static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
+static struct snd_pci_quirk intel8x0_clock_list[] = {
SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
@@ -2892,7 +2892,7 @@ static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
{ } /* terminator */
};
-static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip)
+static int intel8x0_in_clock_list(struct intel8x0 *chip)
{
struct pci_dev *pci = chip->pci;
const struct snd_pci_quirk *wl;
@@ -2941,7 +2941,7 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
chip->ac97_sdin[2]);
}
-static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip)
+static void snd_intel8x0_proc_init(struct intel8x0 *chip)
{
struct snd_info_entry *entry;
@@ -2970,7 +2970,7 @@ static unsigned int sis_codec_bits[3] = {
ICH_PCR, ICH_SCR, ICH_SIS_TCR
};
-static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
+static int snd_intel8x0_inside_vm(struct pci_dev *pci)
{
int result = inside_vm;
char *msg = NULL;
@@ -3009,10 +3009,10 @@ fini:
return result;
}
-static int __devinit snd_intel8x0_create(struct snd_card *card,
- struct pci_dev *pci,
- unsigned long device_type,
- struct intel8x0 ** r_intel8x0)
+static int snd_intel8x0_create(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned long device_type,
+ struct intel8x0 **r_intel8x0)
{
struct intel8x0 *chip;
int err;
@@ -3227,7 +3227,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
static struct shortname_table {
unsigned int id;
const char *s;
-} shortnames[] __devinitdata = {
+} shortnames[] = {
{ PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
{ PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
{ PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
@@ -3253,13 +3253,13 @@ static struct shortname_table {
{ 0, NULL },
};
-static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
+static struct snd_pci_quirk spdif_aclink_defaults[] = {
SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
{ } /* end */
};
/* look up white/black list for SPDIF over ac-link */
-static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
+static int check_default_spdif_aclink(struct pci_dev *pci)
{
const struct snd_pci_quirk *w;
@@ -3276,8 +3276,8 @@ static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
return 0;
}
-static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_intel8x0_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct intel8x0 *chip;
@@ -3359,7 +3359,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
+static void snd_intel8x0_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -3369,7 +3369,7 @@ static struct pci_driver intel8x0_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
- .remove = __devexit_p(snd_intel8x0_remove),
+ .remove = snd_intel8x0_remove,
.driver = {
.pm = INTEL8X0_PM_OPS,
},
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 4d551736531e..fea09e8ea608 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -710,8 +710,8 @@ struct ich_pcm_table {
int ac97_idx;
};
-static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
- struct ich_pcm_table *rec)
+static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
+ struct ich_pcm_table *rec)
{
struct snd_pcm *pcm;
int err;
@@ -749,7 +749,7 @@ static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
return 0;
}
-static struct ich_pcm_table intel_pcms[] __devinitdata = {
+static struct ich_pcm_table intel_pcms[] = {
{
.suffix = "Modem",
.playback_ops = &snd_intel8x0m_playback_ops,
@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
},
};
-static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip)
+static int snd_intel8x0m_pcm(struct intel8x0m *chip)
{
int i, tblsize, device, err;
struct ich_pcm_table *tbl, *rec;
@@ -819,7 +819,7 @@ static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97)
}
-static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
+static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -1090,7 +1090,7 @@ static void snd_intel8x0m_proc_read(struct snd_info_entry * entry,
(tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : "");
}
-static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
+static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
{
struct snd_info_entry *entry;
@@ -1113,10 +1113,10 @@ struct ich_reg_info {
unsigned int offset;
};
-static int __devinit snd_intel8x0m_create(struct snd_card *card,
- struct pci_dev *pci,
- unsigned long device_type,
- struct intel8x0m **r_intel8x0m)
+static int snd_intel8x0m_create(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned long device_type,
+ struct intel8x0m **r_intel8x0m)
{
struct intel8x0m *chip;
int err;
@@ -1252,7 +1252,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
static struct shortname_table {
unsigned int id;
const char *s;
-} shortnames[] __devinitdata = {
+} shortnames[] = {
{ PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
{ PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
@@ -1275,8 +1275,8 @@ static struct shortname_table {
{ 0 },
};
-static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_intel8x0m_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct intel8x0m *chip;
@@ -1325,7 +1325,7 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
+static void snd_intel8x0m_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1335,7 +1335,7 @@ static struct pci_driver intel8x0m_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
- .remove = __devexit_p(snd_intel8x0m_remove),
+ .remove = snd_intel8x0m_remove,
.driver = {
.pm = INTEL8X0M_PM_OPS,
},
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 8a67ce95f246..43b4228d9afe 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2083,7 +2083,7 @@ static void snd_korg1212_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt);
}
-static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
+static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
{
struct snd_info_entry *entry;
@@ -2154,8 +2154,8 @@ static int snd_korg1212_dev_free(struct snd_device *device)
return snd_korg1212_free(korg1212);
}
-static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
- struct snd_korg1212 ** rchip)
+static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
+ struct snd_korg1212 **rchip)
{
int err, rc;
@@ -2429,7 +2429,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
* Card initialisation
*/
-static int __devinit
+static int
snd_korg1212_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -2470,7 +2470,7 @@ snd_korg1212_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_korg1212_remove(struct pci_dev *pci)
+static void snd_korg1212_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2480,7 +2480,7 @@ static struct pci_driver korg1212_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_korg1212_ids,
.probe = snd_korg1212_probe,
- .remove = __devexit_p(snd_korg1212_remove),
+ .remove = snd_korg1212_remove,
};
module_pci_driver(korg1212_driver);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index ac15166bee68..322b638e8ec4 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip)
lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
}
-static int __devinit lola_parse_tree(struct lola *chip)
+static int lola_parse_tree(struct lola *chip)
{
unsigned int val;
int nid, err;
@@ -568,8 +568,8 @@ static int lola_dev_free(struct snd_device *device)
return 0;
}
-static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
- int dev, struct lola **rchip)
+static int lola_create(struct snd_card *card, struct pci_dev *pci,
+ int dev, struct lola **rchip)
{
struct lola *chip;
int err;
@@ -702,8 +702,8 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
-static int __devinit lola_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int lola_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -756,7 +756,7 @@ out_free:
return err;
}
-static void __devexit lola_remove(struct pci_dev *pci)
+static void lola_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -774,7 +774,7 @@ static struct pci_driver lola_driver = {
.name = KBUILD_MODNAME,
.id_table = lola_ids,
.probe = lola_probe,
- .remove = __devexit_p(lola_remove),
+ .remove = lola_remove,
};
module_pci_driver(lola_driver);
diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c
index 72f8ef0ac865..eb1d6b97df16 100644
--- a/sound/pci/lola/lola_clock.c
+++ b/sound/pci/lola/lola_clock.c
@@ -120,7 +120,7 @@ int lola_set_granularity(struct lola *chip, unsigned int val, bool force)
* Clock widget handling
*/
-int __devinit lola_init_clock_widget(struct lola *chip, int nid)
+int lola_init_clock_widget(struct lola *chip, int nid)
{
unsigned int val;
int i, j, nitems, nb_verbs, idx, idx_list;
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
index 6b8d64812951..52c8d6b0f39b 100644
--- a/sound/pci/lola/lola_mixer.c
+++ b/sound/pci/lola/lola_mixer.c
@@ -28,8 +28,8 @@
#include <sound/tlv.h>
#include "lola.h"
-static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
- int dir, int nid)
+static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
+ int dir, int nid)
{
unsigned int val;
int err;
@@ -91,7 +91,7 @@ static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
return 0;
}
-int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp)
+int lola_init_pins(struct lola *chip, int dir, int *nidp)
{
int i, err, nid;
nid = *nidp;
@@ -112,7 +112,7 @@ void lola_free_mixer(struct lola *chip)
vfree(chip->mixer.array_saved);
}
-int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
+int lola_init_mixer_widget(struct lola *chip, int nid)
{
unsigned int val;
int err;
@@ -579,7 +579,7 @@ static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return 0;
}
-static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_analog_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -590,7 +590,7 @@ static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
.tlv.c = lola_analog_vol_tlv,
};
-static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name)
+static int create_analog_mixer(struct lola *chip, int dir, char *name)
{
if (!chip->pin[dir].num_pins)
return 0;
@@ -644,7 +644,7 @@ static int lola_input_src_put(struct snd_kcontrol *kcontrol,
return lola_set_src_config(chip, mask, true);
}
-static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_input_src_mixer = {
.name = "Digital SRC Capture Switch",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = lola_input_src_info,
@@ -656,7 +656,7 @@ static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
* Lola16161 or Lola881 can have Hardware sample rate converters
* on its digital input pins
*/
-static int __devinit create_input_src_mixer(struct lola *chip)
+static int create_input_src_mixer(struct lola *chip)
{
if (!chip->input_src_caps_mask)
return 0;
@@ -726,7 +726,7 @@ static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
/* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
-static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_src_gain_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -736,8 +736,8 @@ static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
.tlv.p = lola_src_gain_tlv,
};
-static int __devinit create_src_gain_mixer(struct lola *chip,
- int num, int ofs, char *name)
+static int create_src_gain_mixer(struct lola *chip,
+ int num, int ofs, char *name)
{
lola_src_gain_mixer.name = name;
lola_src_gain_mixer.private_value = ofs + (num << 8);
@@ -813,7 +813,7 @@ static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
-static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_dest_gain_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -823,9 +823,9 @@ static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
.tlv.p = lola_dest_gain_tlv,
};
-static int __devinit create_dest_gain_mixer(struct lola *chip,
- int src_num, int src_ofs,
- int num, int ofs, char *name)
+static int create_dest_gain_mixer(struct lola *chip,
+ int src_num, int src_ofs,
+ int num, int ofs, char *name)
{
lola_dest_gain_mixer.count = num;
lola_dest_gain_mixer.name = name;
@@ -838,7 +838,7 @@ static int __devinit create_dest_gain_mixer(struct lola *chip,
/*
*/
-int __devinit lola_create_mixer(struct lola *chip)
+int lola_create_mixer(struct lola *chip)
{
int err;
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index c44db68eecb5..5ea85e8b83ab 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -597,7 +597,7 @@ static struct snd_pcm_ops lola_pcm_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-int __devinit lola_create_pcm(struct lola *chip)
+int lola_create_pcm(struct lola *chip)
{
struct snd_pcm *pcm;
int i, err;
@@ -690,7 +690,7 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str,
return 0;
}
-int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp)
+int lola_init_pcm(struct lola *chip, int dir, int *nidp)
{
struct lola_pcm *pcm = &chip->pcm[dir];
int i, nid, err;
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c
index 9d7daf897c9d..04df83defc09 100644
--- a/sound/pci/lola/lola_proc.c
+++ b/sound/pci/lola/lola_proc.c
@@ -206,7 +206,7 @@ static void lola_proc_regs_read(struct snd_info_entry *entry,
}
}
-void __devinit lola_proc_debug_new(struct lola *chip)
+void lola_proc_debug_new(struct lola *chip)
{
struct snd_info_entry *entry;
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 5579b08bb35b..298bc9b72991 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -578,7 +578,7 @@ static int snd_lx6464es_dev_free(struct snd_device *device)
}
/* reset the dsp during initialization */
-static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
+static int lx_init_xilinx_reset(struct lx6464es *chip)
{
int i;
u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC);
@@ -620,7 +620,7 @@ static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
return 0;
}
-static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
+static int lx_init_xilinx_test(struct lx6464es *chip)
{
u32 reg;
@@ -650,7 +650,7 @@ static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
}
/* initialize ethersound */
-static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
+static int lx_init_ethersound_config(struct lx6464es *chip)
{
int i;
u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES);
@@ -690,7 +690,7 @@ static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
return 0;
}
-static int __devinit lx_init_get_version_features(struct lx6464es *chip)
+static int lx_init_get_version_features(struct lx6464es *chip)
{
u32 dsp_version;
@@ -759,7 +759,7 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran)
}
/* initialize and test the xilinx dsp chip */
-static int __devinit lx_init_dsp(struct lx6464es *chip)
+static int lx_init_dsp(struct lx6464es *chip)
{
int err;
int i;
@@ -835,7 +835,7 @@ static struct snd_pcm_ops lx_ops_capture = {
.pointer = lx_pcm_stream_pointer,
};
-static int __devinit lx_pcm_create(struct lx6464es *chip)
+static int lx_pcm_create(struct lx6464es *chip)
{
int err;
struct snd_pcm *pcm;
@@ -907,7 +907,7 @@ static int lx_control_playback_put(struct snd_kcontrol *kcontrol,
return changed;
}
-static struct snd_kcontrol_new lx_control_playback_switch __devinitdata = {
+static struct snd_kcontrol_new lx_control_playback_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -954,7 +954,7 @@ static void lx_proc_levels_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "\n");
}
-static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip)
+static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
{
struct snd_info_entry *entry;
int err = snd_card_proc_new(card, "levels", &entry);
@@ -966,9 +966,9 @@ static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip
}
-static int __devinit snd_lx6464es_create(struct snd_card *card,
- struct pci_dev *pci,
- struct lx6464es **rchip)
+static int snd_lx6464es_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct lx6464es **rchip)
{
struct lx6464es *chip;
int err;
@@ -1082,8 +1082,8 @@ alloc_failed:
return err;
}
-static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_lx6464es_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1136,7 +1136,7 @@ out_free:
}
-static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
+static void snd_lx6464es_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1147,7 +1147,7 @@ static struct pci_driver lx6464es_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_lx6464es_ids,
.probe = snd_lx6464es_probe,
- .remove = __devexit_p(snd_lx6464es_remove),
+ .remove = snd_lx6464es_remove,
};
module_pci_driver(lx6464es_driver);
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index 8c3e7fcefd99..633c8607d053 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -385,7 +385,7 @@ polling_successful:
/* low-level dsp access */
-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
+int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
{
u16 ret;
unsigned long flags;
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
index 4d7ff797a646..5ec5e04da1a5 100644
--- a/sound/pci/lx6464es/lx_core.h
+++ b/sound/pci/lx6464es/lx_core.h
@@ -109,7 +109,7 @@ struct lx_rmh {
/* low-level dsp access */
-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
+int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq);
int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran);
int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index eb3cd3a4315e..9387533f70dc 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -822,7 +822,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = {
MODULE_DEVICE_TABLE(pci, snd_m3_ids);
-static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_amp_quirk_list[] = {
SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c),
SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
@@ -831,7 +831,7 @@ static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
{ } /* END */
};
-static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_irda_quirk_list[] = {
SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
@@ -839,7 +839,7 @@ static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
};
/* hardware volume quirks */
-static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_hv_quirk_list[] = {
/* Allegro chips */
SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
@@ -917,7 +917,7 @@ static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
};
/* HP Omnibook quirks */
-static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_omnibook_quirk_list[] = {
SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
{ } /* END */
@@ -1856,7 +1856,7 @@ static struct snd_pcm_ops snd_m3_capture_ops = {
.pointer = snd_m3_pcm_pointer,
};
-static int __devinit
+static int
snd_m3_pcm(struct snd_m3 * chip, int device)
{
struct snd_pcm *pcm;
@@ -2031,7 +2031,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip)
#endif
}
-static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+static int snd_m3_mixer(struct snd_m3 *chip)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -2173,7 +2173,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip)
}
-static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
+static int snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
{
int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 +
MINISRC_IN_BUFFER_SIZE / 2 +
@@ -2488,7 +2488,7 @@ static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume);
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_SND_MAESTRO3_INPUT
-static int __devinit snd_m3_input_register(struct snd_m3 *chip)
+static int snd_m3_input_register(struct snd_m3 *chip)
{
struct input_dev *input_dev;
int err;
@@ -2532,7 +2532,7 @@ static int snd_m3_dev_free(struct snd_device *device)
return snd_m3_free(chip);
}
-static int __devinit
+static int
snd_m3_create(struct snd_card *card, struct pci_dev *pci,
int enable_amp,
int amp_gpio,
@@ -2700,7 +2700,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
/*
*/
-static int __devinit
+static int
snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -2770,7 +2770,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return 0;
}
-static void __devexit snd_m3_remove(struct pci_dev *pci)
+static void snd_m3_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2780,7 +2780,7 @@ static struct pci_driver m3_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
- .remove = __devexit_p(snd_m3_remove),
+ .remove = snd_m3_remove,
.driver = {
.pm = M3_PM_OPS,
},
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 0762610c99c0..01f7f37a8410 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1004,7 +1004,7 @@ static int snd_mixart_chip_dev_free(struct snd_device *device)
/*
*/
-static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
+static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
{
int err;
struct snd_mixart *chip;
@@ -1180,7 +1180,7 @@ static void snd_mixart_proc_read(struct snd_info_entry *entry,
} /* endif elf loaded */
}
-static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
+static void snd_mixart_proc_init(struct snd_mixart *chip)
{
struct snd_info_entry *entry;
@@ -1209,8 +1209,8 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
/*
* probe function - creates the card manager
*/
-static int __devinit snd_mixart_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_mixart_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct mixart_mgr *mgr;
@@ -1374,7 +1374,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_mixart_remove(struct pci_dev *pci)
+static void snd_mixart_remove(struct pci_dev *pci)
{
snd_mixart_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1384,7 +1384,7 @@ static struct pci_driver mixart_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_mixart_ids,
.probe = snd_mixart_probe,
- .remove = __devexit_p(snd_mixart_remove),
+ .remove = snd_mixart_remove,
};
module_pci_driver(mixart_driver);
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index e0f4d87555a0..ece1f831c16a 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -546,14 +546,6 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw
}
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */
-#define SND_MIXART_FW_LOADER /* use the standard firmware loader */
-#endif
-#endif
-
-#ifdef SND_MIXART_FW_LOADER
-
int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
{
static char *fw_files[3] = {
@@ -583,71 +575,3 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
MODULE_FIRMWARE("mixart/miXart8.xlx");
MODULE_FIRMWARE("mixart/miXart8.elf");
MODULE_FIRMWARE("mixart/miXart8AES.xlx");
-
-#else /* old style firmware loading */
-
-/* miXart hwdep interface id string */
-#define SND_MIXART_HWDEP_ID "miXart Loader"
-
-static int mixart_hwdep_dsp_status(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_status *info)
-{
- struct mixart_mgr *mgr = hw->private_data;
-
- strcpy(info->id, "miXart");
- info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
-
- if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX))
- info->chip_ready = 1;
-
- info->version = MIXART_DRIVER_VERSION;
- return 0;
-}
-
-static int mixart_hwdep_dsp_load(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_image *dsp)
-{
- struct mixart_mgr* mgr = hw->private_data;
- struct firmware fw;
- int err;
-
- fw.size = dsp->length;
- fw.data = vmalloc(dsp->length);
- if (! fw.data) {
- snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n",
- (int)dsp->length);
- return -ENOMEM;
- }
- if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) {
- vfree(fw.data);
- return -EFAULT;
- }
- err = mixart_dsp_load(mgr, dsp->index, &fw);
- vfree(fw.data);
- if (err < 0)
- return err;
- mgr->dsp_loaded |= 1 << dsp->index;
- return err;
-}
-
-int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
-{
- int err;
- struct snd_hwdep *hw;
-
- /* only create hwdep interface for first cardX (see "index" module parameter)*/
- if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0)
- return err;
-
- hw->iface = SNDRV_HWDEP_IFACE_MIXART;
- hw->private_data = mgr;
- hw->ops.dsp_status = mixart_hwdep_dsp_status;
- hw->ops.dsp_load = mixart_hwdep_dsp_load;
- hw->exclusive = 1;
- sprintf(hw->name, SND_MIXART_HWDEP_ID);
- mgr->dsp_loaded = 0;
-
- return snd_card_register(mgr->chip[0]->card);
-}
-
-#endif /* SND_MIXART_FW_LOADER */
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index e80e9a1e84aa..563a193e36a3 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -928,7 +928,7 @@ static struct snd_pcm_ops snd_nm256_capture_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static int __devinit
+static int
snd_nm256_pcm(struct nm256 *chip, int device)
{
struct snd_pcm *pcm;
@@ -1295,7 +1295,7 @@ snd_nm256_ac97_reset(struct snd_ac97 *ac97)
}
/* create an ac97 mixer interface */
-static int __devinit
+static int
snd_nm256_mixer(struct nm256 *chip)
{
struct snd_ac97_bus *pbus;
@@ -1336,7 +1336,7 @@ snd_nm256_mixer(struct nm256 *chip)
* RAM.
*/
-static int __devinit
+static int
snd_nm256_peek_for_sig(struct nm256 *chip)
{
/* The signature is located 1K below the end of video RAM. */
@@ -1472,7 +1472,7 @@ static int snd_nm256_dev_free(struct snd_device *device)
return snd_nm256_free(chip);
}
-static int __devinit
+static int
snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
struct nm256 **chip_ret)
{
@@ -1639,7 +1639,7 @@ __error:
enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
-static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
+static struct snd_pci_quirk nm256_quirks[] = {
/* HP omnibook 4150 has cs4232 codec internally */
SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
/* Reset workarounds to avoid lock-ups */
@@ -1650,8 +1650,8 @@ static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
};
-static int __devinit snd_nm256_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_nm256_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct nm256 *chip;
@@ -1742,7 +1742,7 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_nm256_remove(struct pci_dev *pci)
+static void snd_nm256_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1753,7 +1753,7 @@ static struct pci_driver nm256_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
- .remove = __devexit_p(snd_nm256_remove),
+ .remove = snd_nm256_remove,
.driver = {
.pm = NM256_PM_OPS,
},
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 2becae155a48..ada6c256378e 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -756,8 +756,8 @@ static const struct oxygen_model model_generic = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
-static int __devinit get_oxygen_model(struct oxygen *chip,
- const struct pci_device_id *id)
+static int get_oxygen_model(struct oxygen *chip,
+ const struct pci_device_id *id)
{
static const char *const names[] = {
[MODEL_MERIDIAN] = "AuzenTech X-Meridian",
@@ -848,8 +848,8 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
return 0;
}
-static int __devinit generic_oxygen_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int generic_oxygen_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
int err;
@@ -871,7 +871,7 @@ static struct pci_driver oxygen_driver = {
.name = KBUILD_MODNAME,
.id_table = oxygen_ids,
.probe = generic_oxygen_probe,
- .remove = __devexit_p(oxygen_pci_remove),
+ .remove = oxygen_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &oxygen_pci_pm,
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 3d71423b23bc..64b9fda5f04a 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -52,13 +52,14 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
{ OXYGEN_PCI_SUBID(0x1043, 0x835d) },
{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
+ { OXYGEN_PCI_SUBID(0x1043, 0x8522) },
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
{ }
};
MODULE_DEVICE_TABLE(pci, xonar_ids);
-static int __devinit get_xonar_model(struct oxygen *chip,
- const struct pci_device_id *id)
+static int get_xonar_model(struct oxygen *chip,
+ const struct pci_device_id *id)
{
if (get_xonar_pcm179x_model(chip, id) >= 0)
return 0;
@@ -69,8 +70,8 @@ static int __devinit get_xonar_model(struct oxygen *chip,
return -EINVAL;
}
-static int __devinit xonar_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int xonar_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
int err;
@@ -92,7 +93,7 @@ static struct pci_driver xonar_driver = {
.name = KBUILD_MODNAME,
.id_table = xonar_ids,
.probe = xonar_probe,
- .remove = __devexit_p(oxygen_pci_remove),
+ .remove = oxygen_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &oxygen_pci_pm,
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index c8febf4b9bd6..d231b93d6ab5 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -431,8 +431,8 @@ static const struct oxygen_model model_xonar_d1 = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
-int __devinit get_xonar_cs43xx_model(struct oxygen *chip,
- const struct pci_device_id *id)
+int get_xonar_cs43xx_model(struct oxygen *chip,
+ const struct pci_device_id *id)
{
switch (id->subdevice) {
case 0x834f:
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 8433aa7c3d75..c8c7f2c9b355 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -1087,8 +1087,8 @@ static const struct oxygen_model model_xonar_st = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
-int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
- const struct pci_device_id *id)
+int get_xonar_pcm179x_model(struct oxygen *chip,
+ const struct pci_device_id *id)
{
switch (id->subdevice) {
case 0x8269:
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 63cff90706bf..6ce68604c25e 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -1255,7 +1255,6 @@ static void dump_wm87x6_registers(struct oxygen *chip,
}
static const struct oxygen_model model_xonar_ds = {
- .shortname = "Xonar DS",
.longname = "Asus Virtuoso 66",
.chip = "AV200",
.init = xonar_ds_init,
@@ -1321,12 +1320,17 @@ static const struct oxygen_model model_xonar_hdav_slim = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
-int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
- const struct pci_device_id *id)
+int get_xonar_wm87x6_model(struct oxygen *chip,
+ const struct pci_device_id *id)
{
switch (id->subdevice) {
case 0x838e:
chip->model = model_xonar_ds;
+ chip->model.shortname = "Xonar DS";
+ break;
+ case 0x8522:
+ chip->model = model_xonar_ds;
+ chip->model.shortname = "Xonar DSX";
break;
case 0x835e:
chip->model = model_xonar_hdav_slim;
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index be4f1456009a..b97384ad946d 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1203,8 +1203,8 @@ static int pcxhr_chip_dev_free(struct snd_device *device)
/*
*/
-static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
- struct snd_card *card, int idx)
+static int pcxhr_create(struct pcxhr_mgr *mgr,
+ struct snd_card *card, int idx)
{
int err;
struct snd_pcxhr *chip;
@@ -1453,7 +1453,7 @@ static void pcxhr_proc_ltc(struct snd_info_entry *entry,
}
}
-static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
+static void pcxhr_proc_init(struct snd_pcxhr *chip)
{
struct snd_info_entry *entry;
@@ -1513,8 +1513,8 @@ static int pcxhr_free(struct pcxhr_mgr *mgr)
/*
* probe function - creates the card manager
*/
-static int __devinit pcxhr_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int pcxhr_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct pcxhr_mgr *mgr;
@@ -1688,7 +1688,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit pcxhr_remove(struct pci_dev *pci)
+static void pcxhr_remove(struct pci_dev *pci)
{
pcxhr_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1698,7 +1698,7 @@ static struct pci_driver pcxhr_driver = {
.name = KBUILD_MODNAME,
.id_table = pcxhr_ids,
.probe = pcxhr_probe,
- .remove = __devexit_p(pcxhr_remove),
+ .remove = pcxhr_remove,
};
module_pci_driver(pcxhr_driver);
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index bf207e317f71..d995175c1c48 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -35,13 +35,6 @@
#include "pcxhr_mix22.h"
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */
-#define SND_PCXHR_FW_LOADER /* use the standard firmware loader */
-#endif
-#endif
-
-
static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
/*
* get basic information and init pcxhr card
@@ -362,8 +355,6 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
/*
* fw loader entry
*/
-#ifdef SND_PCXHR_FW_LOADER
-
int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
{
static char *fw_files[][5] = {
@@ -424,80 +415,3 @@ MODULE_FIRMWARE("pcxhr/xlxc924.dat");
MODULE_FIRMWARE("pcxhr/dspe924.e56");
MODULE_FIRMWARE("pcxhr/dspb924.b56");
MODULE_FIRMWARE("pcxhr/dspd222.d56");
-
-
-#else /* old style firmware loading */
-
-/* pcxhr hwdep interface id string */
-#define PCXHR_HWDEP_ID "pcxhr loader"
-
-
-static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_status *info)
-{
- struct pcxhr_mgr *mgr = hw->private_data;
- sprintf(info->id, "pcxhr%d", mgr->fw_file_set);
- info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
-
- if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
- info->chip_ready = 1;
-
- info->version = PCXHR_DRIVER_VERSION;
- return 0;
-}
-
-static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
- struct snd_hwdep_dsp_image *dsp)
-{
- struct pcxhr_mgr *mgr = hw->private_data;
- int err;
- struct firmware fw;
-
- fw.size = dsp->length;
- fw.data = vmalloc(fw.size);
- if (! fw.data) {
- snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image "
- "(%lu bytes)\n", (unsigned long)fw.size);
- return -ENOMEM;
- }
- if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) {
- vfree(fw.data);
- return -EFAULT;
- }
- err = pcxhr_dsp_load(mgr, dsp->index, &fw);
- vfree(fw.data);
- if (err < 0)
- return err;
- mgr->dsp_loaded |= 1 << dsp->index;
- return 0;
-}
-
-int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
-{
- int err;
- struct snd_hwdep *hw;
-
- /* only create hwdep interface for first cardX
- * (see "index" module parameter)
- */
- err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw);
- if (err < 0)
- return err;
-
- hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
- hw->private_data = mgr;
- hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
- hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
- hw->exclusive = 1;
- /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */
- hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0;
- mgr->dsp_loaded = 0;
- sprintf(hw->name, PCXHR_HWDEP_ID);
-
- err = snd_card_register(mgr->chip[0]->card);
- if (err < 0)
- return err;
- return 0;
-}
-
-#endif /* SND_PCXHR_FW_LOADER */
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 7d291542c5ba..63c1c8041554 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1706,7 +1706,7 @@ static struct snd_pcm_ops snd_riptide_capture_ops = {
.pointer = snd_riptide_pointer,
};
-static int __devinit
+static int
snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
@@ -1857,7 +1857,7 @@ static int snd_riptide_dev_free(struct snd_device *device)
return snd_riptide_free(chip);
}
-static int __devinit
+static int
snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
struct snd_riptide **rchip)
{
@@ -1993,7 +1993,7 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "\n");
}
-static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+static void snd_riptide_proc_init(struct snd_riptide *chip)
{
struct snd_info_entry *entry;
@@ -2001,7 +2001,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
}
-static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+static int snd_riptide_mixer(struct snd_riptide *chip)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
@@ -2027,7 +2027,7 @@ static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
#ifdef SUPPORT_JOYSTICK
-static int __devinit
+static int
snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
static int dev;
@@ -2060,7 +2060,7 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
return 0;
}
-static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+static void snd_riptide_joystick_remove(struct pci_dev *pci)
{
struct gameport *gameport = pci_get_drvdata(pci);
if (gameport) {
@@ -2071,7 +2071,7 @@ static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
}
#endif
-static int __devinit
+static int
snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -2176,7 +2176,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return err;
}
-static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
+static void snd_card_riptide_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2186,7 +2186,7 @@ static struct pci_driver driver = {
.name = KBUILD_MODNAME,
.id_table = snd_riptide_ids,
.probe = snd_card_riptide_probe,
- .remove = __devexit_p(snd_card_riptide_remove),
+ .remove = snd_card_riptide_remove,
.driver = {
.pm = RIPTIDE_PM_OPS,
},
@@ -2197,7 +2197,7 @@ static struct pci_driver joystick_driver = {
.name = KBUILD_MODNAME "-joystick",
.id_table = snd_riptide_joystick_ids,
.probe = snd_riptide_joystick_probe,
- .remove = __devexit_p(snd_riptide_joystick_remove),
+ .remove = snd_riptide_joystick_remove,
};
#endif
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 46b3629dda22..2450663e1a18 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1332,7 +1332,7 @@ snd_rme32_free_adat_pcm(struct snd_pcm *pcm)
rme32->adat_pcm = NULL;
}
-static int __devinit snd_rme32_create(struct rme32 * rme32)
+static int snd_rme32_create(struct rme32 *rme32)
{
struct pci_dev *pci = rme32->pci;
int err;
@@ -1554,7 +1554,7 @@ snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
}
}
-static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
+static void snd_rme32_proc_init(struct rme32 *rme32)
{
struct snd_info_entry *entry;
@@ -1922,7 +1922,7 @@ static void snd_rme32_card_free(struct snd_card *card)
snd_rme32_free(card->private_data);
}
-static int __devinit
+static int
snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
@@ -1978,7 +1978,7 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return 0;
}
-static void __devexit snd_rme32_remove(struct pci_dev *pci)
+static void snd_rme32_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1988,7 +1988,7 @@ static struct pci_driver rme32_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme32_ids,
.probe = snd_rme32_probe,
- .remove = __devexit_p(snd_rme32_remove),
+ .remove = snd_rme32_remove,
};
module_pci_driver(rme32_driver);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 9b98dc406988..5fb88ac82aa9 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -270,8 +270,7 @@ snd_rme96_playback_pointer(struct snd_pcm_substream *substream);
static snd_pcm_uframes_t
snd_rme96_capture_pointer(struct snd_pcm_substream *substream);
-static void __devinit
-snd_rme96_proc_init(struct rme96 *rme96);
+static void snd_rme96_proc_init(struct rme96 *rme96);
static int
snd_rme96_create_switches(struct snd_card *card,
@@ -1538,7 +1537,7 @@ snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
rme96->adat_pcm = NULL;
}
-static int __devinit
+static int
snd_rme96_create(struct rme96 *rme96)
{
struct pci_dev *pci = rme96->pci;
@@ -1786,8 +1785,7 @@ snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer
}
}
-static void __devinit
-snd_rme96_proc_init(struct rme96 *rme96)
+static void snd_rme96_proc_init(struct rme96 *rme96)
{
struct snd_info_entry *entry;
@@ -2326,7 +2324,7 @@ static void snd_rme96_card_free(struct snd_card *card)
snd_rme96_free(card->private_data);
}
-static int __devinit
+static int
snd_rme96_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -2389,7 +2387,7 @@ snd_rme96_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_rme96_remove(struct pci_dev *pci)
+static void snd_rme96_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2399,7 +2397,7 @@ static struct pci_driver rme96_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme96_ids,
.probe = snd_rme96_probe,
- .remove = __devexit_p(snd_rme96_remove),
+ .remove = snd_rme96_remove,
};
module_pci_driver(rme96_driver);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 0d6930c4f4b7..4fae81f21efb 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -28,6 +28,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/math64.h>
+#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -59,13 +60,11 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
"{RME HDSP-9652},"
"{RME HDSP-9632}}");
-#ifdef HDSP_FW_LOADER
MODULE_FIRMWARE("rpm_firmware.bin");
MODULE_FIRMWARE("multiface_firmware.bin");
MODULE_FIRMWARE("multiface_firmware_rev11.bin");
MODULE_FIRMWARE("digiface_firmware.bin");
MODULE_FIRMWARE("digiface_firmware_rev11.bin");
-#endif
#define HDSP_MAX_CHANNELS 26
#define HDSP_MAX_DS_CHANNELS 14
@@ -423,12 +422,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
-/* use hotplug firmware loader? */
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(HDSP_USE_HWDEP_LOADER)
-#define HDSP_FW_LOADER
-#endif
-#endif
+#define HDSP_FIRMWARE_SIZE (24413 * 4)
struct hdsp_9632_meters {
u32 input_peak[16];
@@ -475,7 +469,8 @@ struct hdsp {
enum HDSP_IO_Type io_type; /* ditto, but for code use */
unsigned short firmware_rev;
unsigned short state; /* stores state bits */
- u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
+ const struct firmware *firmware;
+ u32 *fw_uploaded;
size_t period_bytes; /* guess what this is */
unsigned char max_channels;
unsigned char qs_in_channels; /* quad speed mode for H9632 */
@@ -712,6 +707,17 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
int i;
unsigned long flags;
+ const u32 *cache;
+
+ if (hdsp->fw_uploaded)
+ cache = hdsp->fw_uploaded;
+ else {
+ if (!hdsp->firmware)
+ return -ENODEV;
+ cache = (u32 *)hdsp->firmware->data;
+ if (!cache)
+ return -ENODEV;
+ }
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
@@ -727,8 +733,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
- for (i = 0; i < 24413; ++i) {
- hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
+ for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) {
+ hdsp_write(hdsp, HDSP_fifoData, cache[i]);
if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
return -EIO;
@@ -798,9 +804,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp)
}
-#ifdef HDSP_FW_LOADER
static int hdsp_request_fw_loader(struct hdsp *hdsp);
-#endif
static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
{
@@ -813,10 +817,8 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
/* try to load firmware */
if (! (hdsp->state & HDSP_FirmwareCached)) {
-#ifdef HDSP_FW_LOADER
if (! hdsp_request_fw_loader(hdsp))
return 0;
-#endif
snd_printk(KERN_ERR
"Hammerfall-DSP: No firmware loaded nor "
"cached, please upload firmware.\n");
@@ -3673,9 +3675,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
}
} else {
int err = -EINVAL;
-#ifdef HDSP_FW_LOADER
err = hdsp_request_fw_loader(hdsp);
-#endif
if (err < 0) {
snd_iprintf(buffer,
"No firmware loaded nor cached, "
@@ -4020,7 +4020,7 @@ static void snd_hdsp_free_buffers(struct hdsp *hdsp)
snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
}
-static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
+static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
{
unsigned long pb_bus, cb_bus;
@@ -5100,8 +5100,18 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
if (hdsp_check_for_iobox (hdsp))
return -EIO;
- if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
+ if (!hdsp->fw_uploaded) {
+ hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE);
+ if (!hdsp->fw_uploaded)
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(hdsp->fw_uploaded, firmware_data,
+ HDSP_FIRMWARE_SIZE)) {
+ vfree(hdsp->fw_uploaded);
+ hdsp->fw_uploaded = NULL;
return -EFAULT;
+ }
hdsp->state |= HDSP_FirmwareCached;
@@ -5330,7 +5340,6 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp
return 0;
}
-#ifdef HDSP_FW_LOADER
/* load firmware via hotplug fw loader */
static int hdsp_request_fw_loader(struct hdsp *hdsp)
{
@@ -5373,16 +5382,13 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp)
snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
return -ENOENT;
}
- if (fw->size < sizeof(hdsp->firmware_cache)) {
+ if (fw->size < HDSP_FIRMWARE_SIZE) {
snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
- (int)fw->size, (int)sizeof(hdsp->firmware_cache));
- release_firmware(fw);
+ (int)fw->size, HDSP_FIRMWARE_SIZE);
return -EINVAL;
}
- memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-
- release_firmware(fw);
+ hdsp->firmware = fw;
hdsp->state |= HDSP_FirmwareCached;
@@ -5406,10 +5412,9 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp)
}
return 0;
}
-#endif
-static int __devinit snd_hdsp_create(struct snd_card *card,
- struct hdsp *hdsp)
+static int snd_hdsp_create(struct snd_card *card,
+ struct hdsp *hdsp)
{
struct pci_dev *pci = hdsp->pci;
int err;
@@ -5504,7 +5509,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
return err;
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-#ifdef HDSP_FW_LOADER
if ((err = hdsp_request_fw_loader(hdsp)) < 0)
/* we don't fail as this can happen
if userspace is not ready for
@@ -5514,7 +5518,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
else
/* init is complete, we return */
return 0;
-#endif
/* we defer initialization */
snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
@@ -5568,6 +5571,10 @@ static int snd_hdsp_free(struct hdsp *hdsp)
snd_hdsp_free_buffers(hdsp);
+ if (hdsp->firmware)
+ release_firmware(hdsp->firmware);
+ vfree(hdsp->fw_uploaded);
+
if (hdsp->iobase)
iounmap(hdsp->iobase);
@@ -5586,8 +5593,8 @@ static void snd_hdsp_card_free(struct snd_card *card)
snd_hdsp_free(hdsp);
}
-static int __devinit snd_hdsp_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_hdsp_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct hdsp *hdsp;
@@ -5630,7 +5637,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_hdsp_remove(struct pci_dev *pci)
+static void snd_hdsp_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -5640,7 +5647,7 @@ static struct pci_driver hdsp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdsp_ids,
.probe = snd_hdsp_probe,
- .remove = __devexit_p(snd_hdsp_remove),
+ .remove = snd_hdsp_remove,
};
module_pci_driver(hdsp_driver);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 748e36c66603..6e02e064d7b4 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -962,10 +962,10 @@ static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
/* prototypes */
-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
- struct hdspm * hdspm);
-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
- struct hdspm * hdspm);
+static int snd_hdspm_create_alsa_devices(struct snd_card *card,
+ struct hdspm *hdspm);
+static int snd_hdspm_create_pcm(struct snd_card *card,
+ struct hdspm *hdspm);
static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
@@ -1845,8 +1845,8 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input =
.trigger = snd_hdspm_midi_input_trigger,
};
-static int __devinit snd_hdspm_create_midi (struct snd_card *card,
- struct hdspm *hdspm, int id)
+static int snd_hdspm_create_midi(struct snd_card *card,
+ struct hdspm *hdspm, int id)
{
int err;
char buf[32];
@@ -2887,330 +2887,50 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
return 0;
}
-
-#define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_line_out, \
- .get = snd_hdspm_get_line_out, \
- .put = snd_hdspm_put_line_out \
-}
-
-static int hdspm_line_out(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
-}
-
-
-static int hdspm_set_line_output(struct hdspm * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_LineOut;
- else
- hdspm->control_register &= ~HDSPM_LineOut;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_line_out(hdspm);
- hdspm_set_line_output(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_tx_64, \
- .get = snd_hdspm_get_tx_64, \
- .put = snd_hdspm_put_tx_64 \
-}
-
-static int hdspm_tx_64(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
-}
-
-static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_TX_64ch;
- else
- hdspm->control_register &= ~HDSPM_TX_64ch;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_tx_64(hdspm);
- hdspm_set_tx_64(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_c_tms, \
- .get = snd_hdspm_get_c_tms, \
- .put = snd_hdspm_put_c_tms \
-}
-
-static int hdspm_c_tms(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
-}
-
-static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_clr_tms;
- else
- hdspm->control_register &= ~HDSPM_clr_tms;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_c_tms(hdspm);
- hdspm_set_c_tms(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_SAFE_MODE(xname, xindex) \
+#define HDSPM_TOGGLE_SETTING(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_safe_mode, \
- .get = snd_hdspm_get_safe_mode, \
- .put = snd_hdspm_put_safe_mode \
+ .private_value = xindex, \
+ .info = snd_hdspm_info_toggle_setting, \
+ .get = snd_hdspm_get_toggle_setting, \
+ .put = snd_hdspm_put_toggle_setting \
}
-static int hdspm_safe_mode(struct hdspm * hdspm)
+static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
{
- return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
+ return (hdspm->control_register & regmask) ? 1 : 0;
}
-static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
+static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
{
if (out)
- hdspm->control_register |= HDSPM_AutoInp;
- else
- hdspm->control_register &= ~HDSPM_AutoInp;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_safe_mode(hdspm);
- hdspm_set_safe_mode(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_emphasis, \
- .get = snd_hdspm_get_emphasis, \
- .put = snd_hdspm_put_emphasis \
-}
-
-static int hdspm_emphasis(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
-}
-
-static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
-{
- if (emp)
- hdspm->control_register |= HDSPM_Emphasis;
+ hdspm->control_register |= regmask;
else
- hdspm->control_register &= ~HDSPM_Emphasis;
+ hdspm->control_register &= ~regmask;
hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
return 0;
}
-#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_emphasis(hdspm);
- hdspm_set_emphasis(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_DOLBY(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_dolby, \
- .get = snd_hdspm_get_dolby, \
- .put = snd_hdspm_put_dolby \
-}
-
-static int hdspm_dolby(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
-}
-
-static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
-{
- if (dol)
- hdspm->control_register |= HDSPM_Dolby;
- else
- hdspm->control_register &= ~HDSPM_Dolby;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
+static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+ u32 regmask = kcontrol->private_value;
spin_lock_irq(&hdspm->lock);
- ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
+ ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
spin_unlock_irq(&hdspm->lock);
return 0;
}
-static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
+static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+ u32 regmask = kcontrol->private_value;
int change;
unsigned int val;
@@ -3218,64 +2938,8 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_dolby(hdspm);
- hdspm_set_dolby(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-
-#define HDSPM_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_professional, \
- .get = snd_hdspm_get_professional, \
- .put = snd_hdspm_put_professional \
-}
-
-static int hdspm_professional(struct hdspm * hdspm)
-{
- return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
-}
-
-static int hdspm_set_professional(struct hdspm * hdspm, int dol)
-{
- if (dol)
- hdspm->control_register |= HDSPM_Professional;
- else
- hdspm->control_register &= ~HDSPM_Professional;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_professional(hdspm);
- hdspm_set_professional(hdspm, val);
+ change = (int) val != hdspm_toggle_setting(hdspm, regmask);
+ hdspm_set_toggle_setting(hdspm, regmask, val);
spin_unlock_irq(&hdspm->lock);
return change;
}
@@ -4476,10 +4140,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
- HDSPM_LINE_OUT("Line Out", 0),
- HDSPM_TX_64("TX 64 channels mode", 0),
- HDSPM_C_TMS("Clear Track Marker", 0),
- HDSPM_SAFE_MODE("Safe Mode", 0),
+ HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
+ HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
+ HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
+ HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
HDSPM_INPUT_SELECT("Input Select", 0),
HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
};
@@ -4492,9 +4156,9 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
- HDSPM_TX_64("TX 64 channels mode", 0),
- HDSPM_C_TMS("Clear Track Marker", 0),
- HDSPM_SAFE_MODE("Safe Mode", 0),
+ HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
+ HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
+ HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
};
@@ -4587,11 +4251,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
- HDSPM_LINE_OUT("Line Out", 0),
- HDSPM_EMPHASIS("Emphasis", 0),
- HDSPM_DOLBY("Non Audio", 0),
- HDSPM_PROFESSIONAL("Professional", 0),
- HDSPM_C_TMS("Clear Track Marker", 0),
+ HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
+ HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
+ HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
+ HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
+ HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
};
@@ -5233,7 +4897,7 @@ static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
}
-static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
+static void snd_hdspm_proc_init(struct hdspm *hdspm)
{
struct snd_info_entry *entry;
@@ -6266,7 +5930,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
info.system_clock_mode = hdspm_system_clock_mode(hdspm);
info.clock_source = hdspm_clock_source(hdspm);
info.autosync_ref = hdspm_autosync_ref(hdspm);
- info.line_out = hdspm_line_out(hdspm);
+ info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
info.passthru = 0;
spin_unlock_irq(&hdspm->lock);
if (copy_to_user(argp, &info, sizeof(info)))
@@ -6369,8 +6033,8 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
- struct hdspm * hdspm)
+static int snd_hdspm_create_hwdep(struct snd_card *card,
+ struct hdspm *hdspm)
{
struct snd_hwdep *hw;
int err;
@@ -6395,7 +6059,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
/*------------------------------------------------------------
memory interface
------------------------------------------------------------*/
-static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
+static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
{
int err;
struct snd_pcm *pcm;
@@ -6436,8 +6100,8 @@ static void hdspm_set_sgbuf(struct hdspm *hdspm,
/* ------------- ALSA Devices ---------------------------- */
-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
- struct hdspm *hdspm)
+static int snd_hdspm_create_pcm(struct snd_card *card,
+ struct hdspm *hdspm)
{
struct snd_pcm *pcm;
int err;
@@ -6472,8 +6136,8 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
snd_hdspm_flush_midi_input(hdspm, i);
}
-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
- struct hdspm * hdspm)
+static int snd_hdspm_create_alsa_devices(struct snd_card *card,
+ struct hdspm *hdspm)
{
int err, i;
@@ -6531,8 +6195,9 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
return 0;
}
-static int __devinit snd_hdspm_create(struct snd_card *card,
- struct hdspm *hdspm) {
+static int snd_hdspm_create(struct snd_card *card,
+ struct hdspm *hdspm)
+{
struct pci_dev *pci = hdspm->pci;
int err;
@@ -6905,8 +6570,8 @@ static void snd_hdspm_card_free(struct snd_card *card)
}
-static int __devinit snd_hdspm_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_hdspm_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct hdspm *hdspm;
@@ -6964,7 +6629,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_hdspm_remove(struct pci_dev *pci)
+static void snd_hdspm_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -6974,7 +6639,7 @@ static struct pci_driver hdspm_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdspm_ids,
.probe = snd_hdspm_probe,
- .remove = __devexit_p(snd_hdspm_remove),
+ .remove = snd_hdspm_remove,
};
module_pci_driver(hdspm_driver);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index a15fc100ab0c..773a67fff4cd 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1757,7 +1757,7 @@ snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buff
snd_iprintf(buffer, "\n");
}
-static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
+static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
{
struct snd_info_entry *entry;
@@ -1788,7 +1788,7 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
return 0;
}
-static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
+static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
{
unsigned long pb_bus, cb_bus;
@@ -2414,8 +2414,8 @@ static struct snd_pcm_ops snd_rme9652_capture_ops = {
.copy = snd_rme9652_capture_copy,
};
-static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
- struct snd_rme9652 *rme9652)
+static int snd_rme9652_create_pcm(struct snd_card *card,
+ struct snd_rme9652 *rme9652)
{
struct snd_pcm *pcm;
int err;
@@ -2438,9 +2438,9 @@ static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
return 0;
}
-static int __devinit snd_rme9652_create(struct snd_card *card,
- struct snd_rme9652 *rme9652,
- int precise_ptr)
+static int snd_rme9652_create(struct snd_card *card,
+ struct snd_rme9652 *rme9652,
+ int precise_ptr)
{
struct pci_dev *pci = rme9652->pci;
int err;
@@ -2578,8 +2578,8 @@ static void snd_rme9652_card_free(struct snd_card *card)
snd_rme9652_free(rme9652);
}
-static int __devinit snd_rme9652_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_rme9652_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_rme9652 *rme9652;
@@ -2625,7 +2625,7 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_rme9652_remove(struct pci_dev *pci)
+static void snd_rme9652_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2635,7 +2635,7 @@ static struct pci_driver rme9652_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme9652_ids,
.probe = snd_rme9652_probe,
- .remove = __devexit_p(snd_rme9652_remove),
+ .remove = snd_rme9652_remove,
};
module_pci_driver(rme9652_driver);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 51e43407ebc5..d59abe1682c5 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -894,7 +894,7 @@ static struct snd_pcm_ops sis_capture_ops = {
.pointer = sis_pcm_pointer,
};
-static int __devinit sis_pcm_create(struct sis7019 *sis)
+static int sis_pcm_create(struct sis7019 *sis)
{
struct snd_pcm *pcm;
int rc;
@@ -1013,7 +1013,7 @@ static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
(reg << 8) | cmd[ac97->num]);
}
-static int __devinit sis_mixer_create(struct sis7019 *sis)
+static int sis_mixer_create(struct sis7019 *sis)
{
struct snd_ac97_bus *bus;
struct snd_ac97_template ac97;
@@ -1171,7 +1171,7 @@ static int sis_chip_init(struct sis7019 *sis)
outl(SIS_DMA_CSR_PCI_SETTINGS, io + SIS_DMA_CSR);
/* Reset the synchronization groups for all of the channels
- * to be asyncronous. If we start doing SPDIF or 5.1 sound, etc.
+ * to be asynchronous. If we start doing SPDIF or 5.1 sound, etc.
* we'll need to change how we handle these. Until then, we just
* assign sub-mixer 0 to all playback channels, and avoid any
* attenuation on the audio.
@@ -1326,8 +1326,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
return 0;
}
-static int __devinit sis_chip_create(struct snd_card *card,
- struct pci_dev *pci)
+static int sis_chip_create(struct snd_card *card,
+ struct pci_dev *pci)
{
struct sis7019 *sis = card->private_data;
struct voice *voice;
@@ -1417,8 +1417,8 @@ error_out:
return rc;
}
-static int __devinit snd_sis7019_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_sis7019_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct sis7019 *sis;
@@ -1478,7 +1478,7 @@ error_out:
return rc;
}
-static void __devexit snd_sis7019_remove(struct pci_dev *pci)
+static void snd_sis7019_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1488,7 +1488,7 @@ static struct pci_driver sis7019_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_sis7019_ids,
.probe = snd_sis7019_probe,
- .remove = __devexit_p(snd_sis7019_remove),
+ .remove = snd_sis7019_remove,
.driver = {
.pm = SIS_PM_OPS,
},
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index baa9946bedf0..a2e7686e7ae3 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -877,7 +877,8 @@ static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
.pointer = snd_sonicvibes_capture_pointer,
};
-static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
+static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1087,7 +1088,7 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c
return change;
}
-static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_controls[] = {
SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
@@ -1118,7 +1119,7 @@ static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
sonic->master_volume = NULL;
}
-static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
+static int snd_sonicvibes_mixer(struct sonicvibes *sonic)
{
struct snd_card *card;
struct snd_kcontrol *kctl;
@@ -1175,7 +1176,7 @@ static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "MIDI to ext. Tx : %s\n", tmp & 0x04 ? "on" : "off");
}
-static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
+static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
{
struct snd_info_entry *entry;
@@ -1188,10 +1189,10 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
*/
#ifdef SUPPORT_JOYSTICK
-static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
+static struct snd_kcontrol_new snd_sonicvibes_game_control =
SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
-static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
+static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
{
struct gameport *gp;
@@ -1246,11 +1247,11 @@ static int snd_sonicvibes_dev_free(struct snd_device *device)
return snd_sonicvibes_free(sonic);
}
-static int __devinit snd_sonicvibes_create(struct snd_card *card,
- struct pci_dev *pci,
- int reverb,
- int mge,
- struct sonicvibes ** rsonic)
+static int snd_sonicvibes_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int reverb,
+ int mge,
+ struct sonicvibes **rsonic)
{
struct sonicvibes *sonic;
unsigned int dmaa, dmac;
@@ -1401,7 +1402,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
* MIDI section
*/
-static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = {
SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
@@ -1422,8 +1423,8 @@ static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
}
-static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
- struct snd_rawmidi *rmidi)
+static int snd_sonicvibes_midi(struct sonicvibes *sonic,
+ struct snd_rawmidi *rmidi)
{
struct snd_mpu401 * mpu = rmidi->private_data;
struct snd_card *card = sonic->card;
@@ -1441,8 +1442,8 @@ static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
return 0;
}
-static int __devinit snd_sonic_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_sonic_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -1524,7 +1525,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_sonic_remove(struct pci_dev *pci)
+static void snd_sonic_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1534,7 +1535,7 @@ static struct pci_driver sonicvibes_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_sonic_ids,
.probe = snd_sonic_probe,
- .remove = __devexit_p(snd_sonic_remove),
+ .remove = snd_sonic_remove,
};
module_pci_driver(sonicvibes_driver);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 8a6f1f76e870..1aefd6204a63 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_trident_ids) = {
MODULE_DEVICE_TABLE(pci, snd_trident_ids);
-static int __devinit snd_trident_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_trident_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -166,7 +166,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_trident_remove(struct pci_dev *pci)
+static void snd_trident_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -176,7 +176,7 @@ static struct pci_driver trident_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
- .remove = __devexit_p(snd_trident_remove),
+ .remove = snd_trident_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_trident_pm,
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 06b10d1a76e5..fb0e1586a6f8 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2171,8 +2171,8 @@ static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
---------------------------------------------------------------------------*/
-int __devinit snd_trident_pcm(struct snd_trident * trident,
- int device, struct snd_pcm ** rpcm)
+int snd_trident_pcm(struct snd_trident *trident,
+ int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -2229,8 +2229,8 @@ int __devinit snd_trident_pcm(struct snd_trident * trident,
---------------------------------------------------------------------------*/
-int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
- int device, struct snd_pcm ** rpcm)
+int snd_trident_foldback_pcm(struct snd_trident *trident,
+ int device, struct snd_pcm **rpcm)
{
struct snd_pcm *foldback;
int err;
@@ -2286,8 +2286,8 @@ int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
---------------------------------------------------------------------------*/
-int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
- int device, struct snd_pcm ** rpcm)
+int snd_trident_spdif_pcm(struct snd_trident *trident,
+ int device, struct snd_pcm **rpcm)
{
struct snd_pcm *spdif;
int err;
@@ -2371,7 +2371,7 @@ static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
@@ -2434,7 +2434,7 @@ static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_default =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -2467,7 +2467,7 @@ static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_mask =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2529,7 +2529,7 @@ static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_stream =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2579,7 +2579,7 @@ static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_ac97_rear_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Rear Path",
@@ -2637,7 +2637,7 @@ static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_music_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Music Playback Volume",
@@ -2648,7 +2648,7 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
.tlv = { .p = db_scale_gvol },
};
-static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_wave_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Wave Playback Volume",
@@ -2715,7 +2715,7 @@ static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_vol_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Front Playback Volume",
@@ -2779,7 +2779,7 @@ static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_pan_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Pan Playback Control",
@@ -2836,7 +2836,7 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
-static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_rvol_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Reverb Playback Volume",
@@ -2892,7 +2892,7 @@ static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_cvol_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Chorus Playback Volume",
@@ -2972,7 +2972,7 @@ static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_tr
---------------------------------------------------------------------------*/
-static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device)
+static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
{
struct snd_ac97_template _ac97;
struct snd_card *card = trident->card;
@@ -3191,7 +3191,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
}
}
-int __devinit snd_trident_create_gameport(struct snd_trident *chip)
+int snd_trident_create_gameport(struct snd_trident *chip)
{
struct gameport *gp;
@@ -3225,7 +3225,7 @@ static inline void snd_trident_free_gameport(struct snd_trident *chip)
}
}
#else
-int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
+int snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
#endif /* CONFIG_GAMEPORT */
@@ -3329,7 +3329,7 @@ static void snd_trident_proc_read(struct snd_info_entry *entry,
}
}
-static void __devinit snd_trident_proc_init(struct snd_trident * trident)
+static void snd_trident_proc_init(struct snd_trident *trident)
{
struct snd_info_entry *entry;
const char *s = "trident";
@@ -3358,7 +3358,7 @@ static int snd_trident_dev_free(struct snd_device *device)
---------------------------------------------------------------------------*/
-static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
+static int snd_trident_tlb_alloc(struct snd_trident *trident)
{
int i;
@@ -3539,7 +3539,7 @@ static int snd_trident_sis_init(struct snd_trident *trident)
---------------------------------------------------------------------------*/
-int __devinit snd_trident_create(struct snd_card *card,
+int snd_trident_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index f0b4efdb483c..6442f611a07b 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1437,7 +1437,7 @@ static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,
/*
* create pcm instances for VIA8233, 8233C and 8235 (not 8233A)
*/
-static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
+static int snd_via8233_pcm_new(struct via82xx *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_chmap *chmap;
@@ -1505,7 +1505,7 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
/*
* create pcm instances for VIA8233A
*/
-static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
+static int snd_via8233a_pcm_new(struct via82xx *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_chmap *chmap;
@@ -1566,7 +1566,7 @@ static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
/*
* create a pcm instance for via686a/b
*/
-static int __devinit snd_via686_pcm_new(struct via82xx *chip)
+static int snd_via686_pcm_new(struct via82xx *chip)
{
struct snd_pcm *pcm;
int err;
@@ -1643,7 +1643,7 @@ static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,
return val != oval;
}
-static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_capture_source = {
.name = "Input Source Select",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_capture_source_info,
@@ -1683,7 +1683,7 @@ static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control = {
.name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_dxs3_spdif_info,
@@ -1772,7 +1772,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1);
-static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control = {
.name = "PCM Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1783,7 +1783,7 @@ static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata =
.tlv = { .p = db_scale_dxs }
};
-static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs_volume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.device = 0,
/* .subdevice set later */
@@ -1895,7 +1895,7 @@ static struct ac97_quirk ac97_quirks[] = {
{ } /* terminator */
};
-static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
+static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
{
struct snd_ac97_template ac97;
int err;
@@ -1930,7 +1930,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui
#ifdef SUPPORT_JOYSTICK
#define JOYSTICK_ADDR 0x200
-static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
+static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{
struct gameport *gp;
struct resource *r;
@@ -1990,7 +1990,7 @@ static inline void snd_via686_free_gameport(struct via82xx *chip) { }
*
*/
-static int __devinit snd_via8233_init_misc(struct via82xx *chip)
+static int snd_via8233_init_misc(struct via82xx *chip)
{
int i, err, caps;
unsigned char val;
@@ -2047,7 +2047,7 @@ static int __devinit snd_via8233_init_misc(struct via82xx *chip)
return 0;
}
-static int __devinit snd_via686_init_misc(struct via82xx *chip)
+static int snd_via686_init_misc(struct via82xx *chip)
{
unsigned char legacy, legacy_cfg;
int rev_h = 0;
@@ -2137,7 +2137,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry,
}
}
-static void __devinit snd_via82xx_proc_init(struct via82xx *chip)
+static void snd_via82xx_proc_init(struct via82xx *chip)
{
struct snd_info_entry *entry;
@@ -2370,12 +2370,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
return snd_via82xx_free(chip);
}
-static int __devinit snd_via82xx_create(struct snd_card *card,
- struct pci_dev *pci,
- int chip_type,
- int revision,
- unsigned int ac97_clock,
- struct via82xx ** r_via)
+static int snd_via82xx_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int chip_type,
+ int revision,
+ unsigned int ac97_clock,
+ struct via82xx **r_via)
{
struct via82xx *chip;
int err;
@@ -2452,7 +2452,7 @@ struct via823x_info {
char *name;
int type;
};
-static struct via823x_info via823x_cards[] __devinitdata = {
+static struct via823x_info via823x_cards[] = {
{ VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 },
{ VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 },
{ VIA_REV_8233, "VIA 8233", TYPE_VIA8233 },
@@ -2466,7 +2466,7 @@ static struct via823x_info via823x_cards[] __devinitdata = {
* auto detection of DXS channel supports.
*/
-static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
+static struct snd_pci_quirk dxs_whitelist[] = {
SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
@@ -2510,7 +2510,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
{ } /* terminator */
};
-static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
+static int check_dxs_list(struct pci_dev *pci, int revision)
{
const struct snd_pci_quirk *w;
@@ -2535,8 +2535,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
return VIA_DXS_48K;
};
-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_via82xx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct via82xx *chip;
@@ -2643,7 +2643,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
+static void snd_via82xx_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -2653,7 +2653,7 @@ static struct pci_driver via82xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
- .remove = __devexit_p(snd_via82xx_remove),
+ .remove = snd_via82xx_remove,
.driver = {
.pm = SND_VIA82XX_PM_OPS,
},
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 8e0efc416f22..4f5fd80b7e56 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -836,7 +836,7 @@ static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_of
/*
* create a pcm instance for via686a/b
*/
-static int __devinit snd_via686_pcm_new(struct via82xx_modem *chip)
+static int snd_via686_pcm_new(struct via82xx_modem *chip)
{
struct snd_pcm *pcm;
int err;
@@ -885,7 +885,7 @@ static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
}
-static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
+static int snd_via82xx_mixer_new(struct via82xx_modem *chip)
{
struct snd_ac97_template ac97;
int err;
@@ -928,7 +928,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_
}
}
-static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip)
+static void snd_via82xx_proc_init(struct via82xx_modem *chip)
{
struct snd_info_entry *entry;
@@ -1103,12 +1103,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
return snd_via82xx_free(chip);
}
-static int __devinit snd_via82xx_create(struct snd_card *card,
- struct pci_dev *pci,
- int chip_type,
- int revision,
- unsigned int ac97_clock,
- struct via82xx_modem ** r_via)
+static int snd_via82xx_create(struct snd_card *card,
+ struct pci_dev *pci,
+ int chip_type,
+ int revision,
+ unsigned int ac97_clock,
+ struct via82xx_modem **r_via)
{
struct via82xx_modem *chip;
int err;
@@ -1168,8 +1168,8 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
}
-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_via82xx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct via82xx_modem *chip;
@@ -1224,7 +1224,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
return err;
}
-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
+static void snd_via82xx_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -1234,7 +1234,7 @@ static struct pci_driver via82xx_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
- .remove = __devexit_p(snd_via82xx_remove),
+ .remove = snd_via82xx_remove,
.driver = {
.pm = SND_VIA82XX_PM_OPS,
},
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index fdfbaf857233..e2f1ab37e154 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -134,9 +134,9 @@ static int snd_vx222_dev_free(struct snd_device *device)
}
-static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
- struct snd_vx_hardware *hw,
- struct snd_vx222 **rchip)
+static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
+ struct snd_vx_hardware *hw,
+ struct snd_vx222 **rchip)
{
struct vx_core *chip;
struct snd_vx222 *vx;
@@ -188,8 +188,8 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci
}
-static int __devinit snd_vx222_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_vx222_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -251,7 +251,7 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_vx222_remove(struct pci_dev *pci)
+static void snd_vx222_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -300,7 +300,7 @@ static struct pci_driver vx222_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
- .remove = __devexit_p(snd_vx222_remove),
+ .remove = snd_vx222_remove,
.driver = {
.pm = SND_VX222_PM_OPS,
},
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index e01fe34db9ec..01c49655a3c1 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -79,8 +79,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = {
MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
- int legacy_ctrl, int legacy_ctrl2)
+static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
+ int legacy_ctrl, int legacy_ctrl2)
{
struct gameport *gp;
struct resource *r = NULL;
@@ -167,8 +167,8 @@ static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, i
void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
#endif /* SUPPORT_JOYSTICK */
-static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int snd_card_ymfpci_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -344,7 +344,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
return 0;
}
-static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
+static void snd_card_ymfpci_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
@@ -354,7 +354,7 @@ static struct pci_driver ymfpci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
- .remove = __devexit_p(snd_card_ymfpci_remove),
+ .remove = snd_card_ymfpci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_ymfpci_pm,
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 3a6f03f9b02f..22056c50fe39 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -25,7 +25,6 @@
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/module.h>
@@ -598,7 +597,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
}
}
-static int __devinit snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
+static int snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
{
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
4096, &chip->ac3_tmp_base) < 0)
@@ -1144,7 +1143,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
.pointer = snd_ymfpci_capture_pointer,
};
-int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1187,7 +1186,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
.pointer = snd_ymfpci_capture_pointer,
};
-int __devinit snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1225,7 +1224,8 @@ static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
.pointer = snd_ymfpci_playback_pointer,
};
-int __devinit snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1270,7 +1270,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
{ }
};
-int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1339,7 +1340,7 @@ static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ymfpci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_default =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1367,7 +1368,7 @@ static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ymfpci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_mask =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1414,7 +1415,7 @@ static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_stream =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1462,7 +1463,7 @@ static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_
return reg != old_reg;
}
-static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_drec_source = {
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Direct Recording Source",
@@ -1632,7 +1633,7 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return change;
}
-static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_dup4ch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "4ch Duplication",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -1641,7 +1642,7 @@ static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
.put = snd_ymfpci_put_dup4ch,
};
-static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Wave Playback Volume",
@@ -1735,7 +1736,7 @@ static int snd_ymfpci_gpio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
return 0;
}
-static struct snd_kcontrol_new snd_ymfpci_rear_shared __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_rear_shared = {
.name = "Shared Rear/Line-In Switch",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ymfpci_gpio_sw_info,
@@ -1799,7 +1800,7 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new snd_ymfpci_pcm_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_pcm_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1826,7 +1827,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97)
chip->ac97 = NULL;
}
-int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
+int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
{
struct snd_ac97_template ac97;
struct snd_kcontrol *kctl;
@@ -1970,7 +1971,7 @@ static struct snd_timer_hardware snd_ymfpci_timer_hw = {
.precise_resolution = snd_ymfpci_timer_precise_resolution,
};
-int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
+int snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
{
struct snd_timer *timer = NULL;
struct snd_timer_id tid;
@@ -2006,7 +2007,7 @@ static void snd_ymfpci_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i));
}
-static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
+static int snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
{
struct snd_info_entry *entry;
@@ -2128,7 +2129,7 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
snd_ymfpci_enable_dsp(chip);
}
-static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
+static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
{
long size, playback_ctrl_size;
int voice, bank, reg;
@@ -2261,7 +2262,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
#endif
#ifdef CONFIG_PM_SLEEP
- vfree(chip->saved_regs);
+ kfree(chip->saved_regs);
#endif
if (chip->irq >= 0)
free_irq(chip->irq, chip);
@@ -2394,10 +2395,10 @@ static int snd_ymfpci_resume(struct device *dev)
SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
#endif /* CONFIG_PM_SLEEP */
-int __devinit snd_ymfpci_create(struct snd_card *card,
- struct pci_dev * pci,
- unsigned short old_legacy_ctrl,
- struct snd_ymfpci ** rchip)
+int snd_ymfpci_create(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned short old_legacy_ctrl,
+ struct snd_ymfpci **rchip)
{
struct snd_ymfpci *chip;
int err;
@@ -2471,7 +2472,8 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
}
#ifdef CONFIG_PM_SLEEP
- chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32));
+ chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32),
+ GFP_KERNEL);
if (chip->saved_regs == NULL) {
snd_ymfpci_free(chip);
return -ENOMEM;
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index b36679384b27..5fbf5db2543d 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -477,7 +477,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
#define AMP_CH_SPK 0
#define AMP_CH_HD 1
-static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Volume",
.info = snd_pmac_awacs_info_volume_amp,
@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
},
};
-static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
.private_value = AMP_CH_HD,
};
-static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -595,46 +595,46 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
/*
* lists of mixer elements
*/
-static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {
AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
/* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
};
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {
AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {
AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
};
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
};
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {
AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
};
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
};
@@ -642,34 +642,34 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
/* FIXME: is this correct order?
* screamer (powerbook G3 pismo) seems to have different bits...
*/
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
};
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
};
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw =
AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =
AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =
AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {
AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost Capture Volume",
.info = snd_pmac_screamer_mic_boost_info,
@@ -678,34 +678,34 @@ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
},
};
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =
{
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =
{
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
};
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =
{
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
};
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {
AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
};
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
@@ -872,7 +872,7 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
/*
* initialize chip
*/
-int __devinit
+int
snd_pmac_awacs_init(struct snd_pmac *chip)
{
int pm7500 = IS_PM7500;
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index a9d350789f55..0040f048221f 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -215,7 +215,7 @@ static struct snd_kcontrol_new snd_pmac_beep_mixer = {
};
/* Initialize beep stuff */
-int __devinit snd_pmac_attach_beep(struct snd_pmac *chip)
+int snd_pmac_attach_beep(struct snd_pmac *chip)
{
struct pmac_beep *beep;
struct input_dev *input_dev;
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index 00e2d5166d0a..cb4f0a5e984e 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -467,7 +467,7 @@ static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
/*
* Burgundy mixers
*/
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
BURGUNDY_VOLUME_W("Master Playback Volume", 0,
MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
BURGUNDY_VOLUME_W("CD Capture Volume", 0,
@@ -495,7 +495,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
*/ BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
};
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
MASK_ADDR_BURGUNDY_VOLLINE, 16),
BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
@@ -521,7 +521,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
};
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
MASK_ADDR_BURGUNDY_VOLMIC, 16),
BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
@@ -537,33 +537,33 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
/* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
* MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
};
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
BURGUNDY_SWITCH_B("Master Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
BURGUNDY_SWITCH_B("Master Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_OUTPUT_INTERN
| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_OUTPUT_INTERN, 0, 0);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
@@ -617,7 +617,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
/*
* initialize burgundy
*/
-int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip)
+int snd_pmac_burgundy_init(struct snd_pmac *chip)
{
int imac = of_machine_is_compatible("iMac");
int i, err;
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 24200b7bdace..b86526223e4e 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -244,7 +244,7 @@ static void daca_cleanup(struct snd_pmac *chip)
}
/* exported */
-int __devinit snd_pmac_daca_init(struct snd_pmac *chip)
+int snd_pmac_daca_init(struct snd_pmac *chip)
{
int i, err;
struct pmac_daca *mix;
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index 4080becf4cef..01aecc2b5073 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -115,7 +115,7 @@ void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
}
}
-int __devinit snd_pmac_tumbler_post_init(void)
+int snd_pmac_tumbler_post_init(void)
{
int err;
@@ -130,7 +130,7 @@ int __devinit snd_pmac_tumbler_post_init(void)
}
/* exported */
-int __devinit snd_pmac_keywest_init(struct pmac_keywest *i2c)
+int snd_pmac_keywest_init(struct pmac_keywest *i2c)
{
int err;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index ab96cde7417b..c93fbbb201fe 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_pmac_capture_ops = {
.pointer = snd_pmac_capture_pointer,
};
-int __devinit snd_pmac_pcm_new(struct snd_pmac *chip)
+int snd_pmac_pcm_new(struct snd_pmac *chip)
{
struct snd_pcm *pcm;
int err;
@@ -907,7 +907,7 @@ static int snd_pmac_dev_free(struct snd_device *device)
* check the machine support byteswap (little-endian)
*/
-static void __devinit detect_byte_swap(struct snd_pmac *chip)
+static void detect_byte_swap(struct snd_pmac *chip)
{
struct device_node *mio;
@@ -933,7 +933,7 @@ static void __devinit detect_byte_swap(struct snd_pmac *chip)
/*
* detect a sound chip
*/
-static int __devinit snd_pmac_detect(struct snd_pmac *chip)
+static int snd_pmac_detect(struct snd_pmac *chip)
{
struct device_node *sound;
struct device_node *dn;
@@ -1146,7 +1146,7 @@ static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
+static struct snd_kcontrol_new auto_mute_controls[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Auto Mute Switch",
.info = snd_pmac_boolean_mono_info,
@@ -1161,7 +1161,7 @@ static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
},
};
-int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
+int snd_pmac_add_automute(struct snd_pmac *chip)
{
int err;
chip->auto_mute = 1;
@@ -1178,7 +1178,7 @@ int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
/*
* create and detect a pmac chip record
*/
-int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
+int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
{
struct snd_pmac *chip;
struct device_node *np;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 210cafe04890..09fc848d32ec 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -51,7 +51,7 @@ static struct platform_device *device;
/*
*/
-static int __devinit snd_pmac_probe(struct platform_device *devptr)
+static int snd_pmac_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct snd_pmac *chip;
@@ -136,7 +136,7 @@ __error:
}
-static int __devexit snd_pmac_remove(struct platform_device *devptr)
+static int snd_pmac_remove(struct platform_device *devptr)
{
snd_card_free(platform_get_drvdata(devptr));
platform_set_drvdata(devptr, NULL);
@@ -168,7 +168,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r
static struct platform_driver snd_pmac_driver = {
.probe = snd_pmac_probe,
- .remove = __devexit_p(snd_pmac_remove),
+ .remove = snd_pmac_remove,
.driver = {
.name = SND_PMAC_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index 9b18b5243a56..8c7dcbe0118d 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -786,7 +786,7 @@ static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = {
};
-static int __devinit snd_ps3_map_mmio(void)
+static int snd_ps3_map_mmio(void)
{
the_card.mapped_mmio_vaddr =
ioremap(the_card.ps3_dev->m_region->bus_addr,
@@ -808,7 +808,7 @@ static void snd_ps3_unmap_mmio(void)
the_card.mapped_mmio_vaddr = NULL;
}
-static int __devinit snd_ps3_allocate_irq(void)
+static int snd_ps3_allocate_irq(void)
{
int ret;
u64 lpar_addr, lpar_size;
@@ -866,7 +866,7 @@ static void snd_ps3_free_irq(void)
ps3_irq_plug_destroy(the_card.irq_no);
}
-static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
+static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
{
uint64_t val;
int ret;
@@ -882,7 +882,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
ret);
}
-static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
+static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
{
/*
* avsetting driver seems to never change the followings
@@ -906,7 +906,7 @@ static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT);
}
-static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
+static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
{
int ret;
pr_debug("%s: start\n", __func__);
@@ -928,7 +928,7 @@ static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
return ret;
}
-static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
+static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
{
int i, ret;
u64 lpar_addr, lpar_size;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 9cea84c3e0c6..b23354a4ceca 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -844,7 +844,7 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
/*
*/
-static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
+static struct snd_kcontrol_new tumbler_mixers[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.info = tumbler_info_master_volume,
@@ -868,7 +868,7 @@ static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
},
};
-static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snapper_mixers[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.info = tumbler_info_master_volume,
@@ -901,7 +901,7 @@ static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
},
};
-static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -909,7 +909,7 @@ static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_HP,
};
-static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_speaker_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -917,7 +917,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_AMP,
};
-static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_lineout_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Out Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -925,7 +925,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_LINE,
};
-static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_drc_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Switch",
.info = snd_pmac_boolean_mono_info,
@@ -1276,7 +1276,7 @@ static void tumbler_resume(struct snd_pmac *chip)
#endif
/* initialize tumbler */
-static int __devinit tumbler_init(struct snd_pmac *chip)
+static int tumbler_init(struct snd_pmac *chip)
{
int irq;
struct pmac_tumbler *mix = chip->mixer_data;
@@ -1349,7 +1349,7 @@ static void tumbler_cleanup(struct snd_pmac *chip)
}
/* exported */
-int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip)
+int snd_pmac_tumbler_init(struct snd_pmac *chip)
{
int i, err;
struct pmac_tumbler *mix;
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index d48b523207eb..e59a73a9bc42 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -540,7 +540,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
+static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -549,7 +549,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
.put = aica_pcmswitch_put
};
-static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = {
+static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -574,8 +574,7 @@ static int load_aica_firmware(void)
return err;
}
-static int __devinit add_aicamixer_controls(struct snd_card_aica
- *dreamcastcard)
+static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard)
{
int err;
err = snd_ctl_add
@@ -591,7 +590,7 @@ static int __devinit add_aicamixer_controls(struct snd_card_aica
return 0;
}
-static int __devexit snd_aica_remove(struct platform_device *devptr)
+static int snd_aica_remove(struct platform_device *devptr)
{
struct snd_card_aica *dreamcastcard;
dreamcastcard = platform_get_drvdata(devptr);
@@ -603,7 +602,7 @@ static int __devexit snd_aica_remove(struct platform_device *devptr)
return 0;
}
-static int __devinit snd_aica_probe(struct platform_device *devptr)
+static int snd_aica_probe(struct platform_device *devptr)
{
int err;
struct snd_card_aica *dreamcastcard;
@@ -652,7 +651,7 @@ static int __devinit snd_aica_probe(struct platform_device *devptr)
static struct platform_driver snd_aica_driver = {
.probe = snd_aica_probe,
- .remove = __devexit_p(snd_aica_remove),
+ .remove = snd_aica_remove,
.driver = {
.name = SND_AICA_DRIVER,
.owner = THIS_MODULE,
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 0a3394751ed2..e68c4fc91a03 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -261,7 +261,7 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
+static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
{
int err;
struct snd_pcm *pcm;
@@ -346,9 +346,9 @@ static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
}
/* create -- chip-specific constructor for the cards components */
-static int __devinit snd_sh_dac_create(struct snd_card *card,
- struct platform_device *devptr,
- struct snd_sh_dac **rchip)
+static int snd_sh_dac_create(struct snd_card *card,
+ struct platform_device *devptr,
+ struct snd_sh_dac **rchip)
{
struct snd_sh_dac *chip;
int err;
@@ -392,7 +392,7 @@ static int __devinit snd_sh_dac_create(struct snd_card *card,
}
/* driver .probe -- constructor */
-static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
+static int snd_sh_dac_probe(struct platform_device *devptr)
{
struct snd_sh_dac *chip;
struct snd_card *card;
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 72b09cfd3dc3..d1b691bf8e2d 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -6,6 +6,14 @@ config SND_ATMEL_SOC
the ATMEL SSC interface. You will also need
to select the audio interfaces to support below.
+config SND_ATMEL_SOC_PDC
+ tristate
+ depends on SND_ATMEL_SOC
+
+config SND_ATMEL_SOC_DMA
+ tristate
+ depends on SND_ATMEL_SOC
+
config SND_ATMEL_SOC_SSC
tristate
depends on SND_ATMEL_SOC
@@ -16,8 +24,8 @@ config SND_ATMEL_SOC_SSC
config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
- depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
- AT91_PROGRAMMABLE_CLOCKS
+ depends on ATMEL_SSC && SND_ATMEL_SOC && AT91_PROGRAMMABLE_CLOCKS
+ select SND_ATMEL_SOC_PDC
select SND_ATMEL_SOC_SSC
select SND_SOC_WM8731
help
@@ -27,6 +35,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
config SND_AT91_SOC_AFEB9260
tristate "SoC Audio support for AFEB9260 board"
depends on ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
+ select SND_ATMEL_SOC_PDC
select SND_ATMEL_SOC_SSC
select SND_SOC_TLV320AIC23
help
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index a5c0bf19da78..41967ccb6f41 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -1,8 +1,12 @@
# AT91 Platform Support
snd-soc-atmel-pcm-objs := atmel-pcm.o
+snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
+snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
+obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
+obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
# AT91 Machine Support
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
new file mode 100644
index 000000000000..30184a4a147a
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -0,0 +1,240 @@
+/*
+ * atmel-pcm-dma.c -- ALSA PCM DMA support for the Atmel SoC.
+ *
+ * Copyright (C) 2012 Atmel
+ *
+ * Author: Bo Shen <voice.shen@atmel.com>
+ *
+ * Based on atmel-pcm by:
+ * Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * Copyright 2008 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/atmel-ssc.h>
+#include <linux/platform_data/dma-atmel.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "atmel-pcm.h"
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .period_bytes_min = 256, /* lighting DMA overhead */
+ .period_bytes_max = 2 * 0xffff, /* if 2 bytes format */
+ .periods_min = 8,
+ .periods_max = 1024, /* no limit */
+ .buffer_bytes_max = ATMEL_SSC_DMABUF_SIZE,
+};
+
+/**
+ * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC
+ *
+ * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to
+ * check if any overrun occured.
+ */
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+ struct snd_pcm_substream *substream)
+{
+ struct atmel_pcm_dma_params *prtd;
+
+ prtd = snd_dmaengine_pcm_get_data(substream);
+
+ if (ssc_sr & prtd->mask->ssc_error) {
+ if (snd_pcm_running(substream))
+ pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? "underrun" : "overrun", prtd->name,
+ ssc_sr);
+
+ /* stop RX and capture: will be enabled again at restart */
+ ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+
+ /* now drain RHR and read status to remove xrun condition */
+ ssc_readx(prtd->ssc->regs, SSC_RHR);
+ ssc_readx(prtd->ssc->regs, SSC_SR);
+ }
+}
+
+/*--------------------------------------------------------------------------*\
+ * DMAENGINE operations
+\*--------------------------------------------------------------------------*/
+static bool filter(struct dma_chan *chan, void *slave)
+{
+ struct at_dma_slave *sl = slave;
+
+ if (sl->dma_dev == chan->device->dev) {
+ chan->private = sl;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct atmel_pcm_dma_params *prtd;
+ struct ssc_device *ssc;
+ struct dma_chan *dma_chan;
+ struct dma_slave_config slave_config;
+ int ret;
+
+ prtd = snd_dmaengine_pcm_get_data(substream);
+ ssc = prtd->ssc;
+
+ ret = snd_hwparams_to_dma_slave_config(substream, params,
+ &slave_config);
+ if (ret) {
+ pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
+ return ret;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
+ slave_config.dst_maxburst = 1;
+ } else {
+ slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
+ slave_config.src_maxburst = 1;
+ }
+
+ slave_config.device_fc = false;
+
+ dma_chan = snd_dmaengine_pcm_get_chan(substream);
+ if (dmaengine_slave_config(dma_chan, &slave_config)) {
+ pr_err("atmel-pcm: failed to configure dma channel\n");
+ ret = -EBUSY;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pcm_dma_params *prtd;
+ struct ssc_device *ssc;
+ struct at_dma_slave *sdata = NULL;
+ int ret;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+ prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ ssc = prtd->ssc;
+ if (ssc->pdev)
+ sdata = ssc->pdev->dev.platform_data;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, sdata);
+ if (ret) {
+ pr_err("atmel-pcm: dmaengine pcm open failed\n");
+ return -EINVAL;
+ }
+
+ snd_dmaengine_pcm_set_data(substream, prtd);
+
+ ret = atmel_pcm_configure_dma(substream, params);
+ if (ret) {
+ pr_err("atmel-pcm: failed to configure dmai\n");
+ goto err;
+ }
+
+ prtd->dma_intr_handler = atmel_pcm_dma_irq;
+
+ return 0;
+err:
+ snd_dmaengine_pcm_close(substream);
+ return ret;
+}
+
+static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
+{
+ struct atmel_pcm_dma_params *prtd;
+
+ prtd = snd_dmaengine_pcm_get_data(substream);
+
+ ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
+ ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
+
+ return 0;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+ snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
+
+ return 0;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+ snd_dmaengine_pcm_close(substream);
+
+ return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+ .open = atmel_pcm_open,
+ .close = atmel_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = atmel_pcm_hw_params,
+ .prepare = atmel_pcm_dma_prepare,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer_no_residue,
+ .mmap = atmel_pcm_mmap,
+};
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+ .ops = &atmel_pcm_ops,
+ .pcm_new = atmel_pcm_new,
+ .pcm_free = atmel_pcm_free,
+};
+
+int atmel_pcm_dma_platform_register(struct device *dev)
+{
+ return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
+
+void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+ snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Atmel DMA based PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c
new file mode 100644
index 000000000000..6a293c713a38
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm-pdc.c
@@ -0,0 +1,401 @@
+/*
+ * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "atmel-pcm.h"
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ * them against real values for AT32
+ */
+static const struct snd_pcm_hardware atmel_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .periods_min = 2,
+ .periods_max = 1024,
+ .buffer_bytes_max = ATMEL_SSC_DMABUF_SIZE,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct atmel_runtime_data {
+ struct atmel_pcm_dma_params *params;
+ dma_addr_t dma_buffer; /* physical address of dma buffer */
+ dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+ size_t period_size;
+
+ dma_addr_t period_ptr; /* physical address of next period */
+
+ /* PDC register save */
+ u32 pdc_xpr_save;
+ u32 pdc_xcr_save;
+ u32 pdc_xnpr_save;
+ u32 pdc_xncr_save;
+};
+
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+ struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ static int count;
+
+ count++;
+
+ if (ssc_sr & params->mask->ssc_endbuf) {
+ pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? "underrun" : "overrun",
+ params->name, ssc_sr, count);
+
+ /* re-start the PDC */
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ }
+
+ if (ssc_sr & params->mask->ssc_endx) {
+ /* Load the PDC next pointer and counter registers */
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+ }
+
+ snd_pcm_period_elapsed(substream);
+}
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* this may get called several times by oss emulation
+ * with different params */
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
+
+ prtd->dma_buffer = runtime->dma_addr;
+ prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+ prtd->period_size = params_period_bytes(params);
+
+ pr_debug("atmel-pcm: "
+ "hw_params: DMA for %s initialized "
+ "(dma_bytes=%u, period_size=%u)\n",
+ prtd->params->name,
+ runtime->dma_bytes,
+ prtd->period_size);
+ return 0;
+}
+
+static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ if (params != NULL) {
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->params->dma_intr_handler = NULL;
+ }
+
+ return 0;
+}
+
+static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ ssc_writex(params->ssc->regs, SSC_IDR,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ return 0;
+}
+
+static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_pcm_runtime *rtd = substream->runtime;
+ struct atmel_runtime_data *prtd = rtd->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ int ret = 0;
+
+ pr_debug("atmel-pcm:buffer_size = %ld,"
+ "dma_area = %p, dma_bytes = %u\n",
+ rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ prtd->period_ptr += prtd->period_size;
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ pr_debug("atmel-pcm: trigger: "
+ "period_ptr=%lx, xpr=%u, "
+ "xcr=%u, xnpr=%u, xncr=%u\n",
+ (unsigned long)prtd->period_ptr,
+ ssc_readx(params->ssc->regs, params->pdc->xpr),
+ ssc_readx(params->ssc->regs, params->pdc->xcr),
+ ssc_readx(params->ssc->regs, params->pdc->xnpr),
+ ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+ ssc_writex(params->ssc->regs, SSC_IER,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_enable);
+
+ pr_debug("sr=%u imr=%u\n",
+ ssc_readx(params->ssc->regs, SSC_SR),
+ ssc_readx(params->ssc->regs, SSC_IER));
+ break; /* SNDRV_PCM_TRIGGER_START */
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static snd_pcm_uframes_t atmel_pcm_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ dma_addr_t ptr;
+ snd_pcm_uframes_t x;
+
+ ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+ x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+
+ return x;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd;
+ int ret = 0;
+
+ snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
+ if (prtd == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ runtime->private_data = prtd;
+
+ out:
+ return ret;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+
+ kfree(prtd);
+ return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+ .open = atmel_pcm_open,
+ .close = atmel_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = atmel_pcm_hw_params,
+ .hw_free = atmel_pcm_hw_free,
+ .prepare = atmel_pcm_prepare,
+ .trigger = atmel_pcm_trigger,
+ .pointer = atmel_pcm_pointer,
+ .mmap = atmel_pcm_mmap,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+#ifdef CONFIG_PM
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* disable the PDC and save the PDC registers */
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+ prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+ prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+ prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+ prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+ return 0;
+}
+
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* restore the PDC registers and enable the PDC */
+ ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+ return 0;
+}
+#else
+#define atmel_pcm_suspend NULL
+#define atmel_pcm_resume NULL
+#endif
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+ .ops = &atmel_pcm_ops,
+ .pcm_new = atmel_pcm_new,
+ .pcm_free = atmel_pcm_free,
+ .suspend = atmel_pcm_suspend,
+ .resume = atmel_pcm_resume,
+};
+
+int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+ return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_register);
+
+void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+ snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_unregister);
+
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("Atmel PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 9b84f985770e..e99f1811300a 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -32,80 +32,25 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
#include <sound/pcm.h>
-#include <sound/pcm_params.h>
#include <sound/soc.h>
-
#include "atmel-pcm.h"
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- * them against real values for AT32
- */
-static const struct snd_pcm_hardware atmel_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct atmel_runtime_data {
- struct atmel_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of dma buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
-
- dma_addr_t period_ptr; /* physical address of next period */
-
- /* PDC register save */
- u32 pdc_xpr_save;
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
static int atmel_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 = atmel_pcm_hardware.buffer_bytes_max;
+ size_t size = ATMEL_SSC_DMABUF_SIZE;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_coherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- pr_debug("atmel-pcm:"
- "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area,
- (void *) buf->addr,
- size);
+ &buf->addr, GFP_KERNEL);
+ pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%d\n",
+ (void *)buf->area, (void *)buf->addr, size);
if (!buf->area)
return -ENOMEM;
@@ -113,258 +58,19 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
buf->bytes = size;
return 0;
}
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void atmel_pcm_dma_irq(u32 ssc_sr,
- struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- static int count;
-
- count++;
-
- if (ssc_sr & params->mask->ssc_endbuf) {
- pr_warning("atmel-pcm: buffer %s on %s"
- " (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "underrun" : "overrun",
- params->name, ssc_sr, count);
-
- /* re-start the PDC */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- }
-
- if (ssc_sr & params->mask->ssc_endx) {
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
- snd_pcm_period_elapsed(substream);
-}
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params */
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- pr_debug("atmel-pcm: "
- "hw_params: DMA for %s initialized "
- "(dma_bytes=%u, period_size=%u)\n",
- prtd->params->name,
- runtime->dma_bytes,
- prtd->period_size);
- return 0;
-}
-
-static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
-
- ssc_writex(params->ssc->regs, SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- return 0;
-}
-
-static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct atmel_runtime_data *prtd = rtd->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- pr_debug("atmel-pcm:buffer_size = %ld,"
- "dma_area = %p, dma_bytes = %u\n",
- rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- pr_debug("atmel-pcm: trigger: "
- "period_ptr=%lx, xpr=%u, "
- "xcr=%u, xnpr=%u, xncr=%u\n",
- (unsigned long)prtd->period_ptr,
- ssc_readx(params->ssc->regs, params->pdc->xpr),
- ssc_readx(params->ssc->regs, params->pdc->xcr),
- ssc_readx(params->ssc->regs, params->pdc->xnpr),
- ssc_readx(params->ssc->regs, params->pdc->xncr));
-
- ssc_writex(params->ssc->regs, SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_enable);
-
- pr_debug("sr=%u imr=%u\n",
- ssc_readx(params->ssc->regs, SSC_SR),
- ssc_readx(params->ssc->regs, SSC_IER));
- break; /* SNDRV_PCM_TRIGGER_START */
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-static snd_pcm_uframes_t atmel_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd = runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
-
- return x;
-}
-
-static int atmel_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
- out:
- return ret;
-}
-
-static int atmel_pcm_close(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+int atmel_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);
}
+EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
-static struct snd_pcm_ops atmel_pcm_ops = {
- .open = atmel_pcm_open,
- .close = atmel_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = atmel_pcm_hw_params,
- .hw_free = atmel_pcm_hw_free,
- .prepare = atmel_pcm_prepare,
- .trigger = atmel_pcm_trigger,
- .pointer = atmel_pcm_pointer,
- .mmap = atmel_pcm_mmap,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
-static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@@ -376,6 +82,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
@@ -383,8 +90,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- pr_debug("atmel-pcm:"
- "Allocating PCM capture DMA buffer\n");
+ pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -393,8 +99,9 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
out:
return ret;
}
+EXPORT_SYMBOL_GPL(atmel_pcm_new);
-static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
+void atmel_pcm_free(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@@ -413,89 +120,5 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
buf->area = NULL;
}
}
+EXPORT_SYMBOL_GPL(atmel_pcm_free);
-#ifdef CONFIG_PM
-static int atmel_pcm_suspend(struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct atmel_runtime_data *prtd;
- struct atmel_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* disable the PDC and save the PDC registers */
-
- ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
- prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
- prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
- prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
- return 0;
-}
-
-static int atmel_pcm_resume(struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct atmel_runtime_data *prtd;
- struct atmel_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* restore the PDC registers and enable the PDC */
- ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
- ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
- ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else
-#define atmel_pcm_suspend NULL
-#define atmel_pcm_resume NULL
-#endif
-
-static struct snd_soc_platform_driver atmel_soc_platform = {
- .ops = &atmel_pcm_ops,
- .pcm_new = atmel_pcm_new,
- .pcm_free = atmel_pcm_free_dma_buffers,
- .suspend = atmel_pcm_suspend,
- .resume = atmel_pcm_resume,
-};
-
-static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
-{
- return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
-}
-
-static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
-}
-
-static struct platform_driver atmel_pcm_driver = {
- .driver = {
- .name = "atmel-pcm-audio",
- .owner = THIS_MODULE,
- },
-
- .probe = atmel_soc_platform_probe,
- .remove = __devexit_p(atmel_soc_platform_remove),
-};
-
-module_platform_driver(atmel_pcm_driver);
-
-MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
-MODULE_DESCRIPTION("Atmel PCM module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
index 5e0a95e64329..bb45d20e7250 100644
--- a/sound/soc/atmel/atmel-pcm.h
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -36,6 +36,8 @@
#include <linux/atmel-ssc.h>
+#define ATMEL_SSC_DMABUF_SIZE (64 * 1024)
+
/*
* Registers and status bits that are required by the PCM driver.
*/
@@ -50,6 +52,7 @@ struct atmel_pdc_regs {
struct atmel_ssc_mask {
u32 ssc_enable; /* SSC recv/trans enable */
u32 ssc_disable; /* SSC recv/trans disable */
+ u32 ssc_error; /* SSC error conditions */
u32 ssc_endx; /* SSC ENDTX or ENDRX */
u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
u32 pdc_enable; /* PDC recv/trans enable */
@@ -80,4 +83,35 @@ struct atmel_pcm_dma_params {
#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void atmel_pcm_free(struct snd_pcm *pcm);
+int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma);
+
+#ifdef CONFIG_SND_ATMEL_SOC_PDC
+int atmel_pcm_pdc_platform_register(struct device *dev);
+void atmel_pcm_pdc_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+ return 0;
+}
+static inline void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+}
+#endif
+
+#ifdef CONFIG_SND_ATMEL_SOC_DMA
+int atmel_pcm_dma_platform_register(struct device *dev);
+void atmel_pcm_dma_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_dma_platform_register(struct device *dev)
+{
+ return 0;
+}
+static inline void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+}
+#endif
+
#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 354341ec0f42..1c7663422054 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -48,11 +48,7 @@
#include "atmel_ssc_dai.h"
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
#define NUM_SSC_DEVICES 3
-#endif
/*
* SSC PDC registers required by the PCM DMA engine.
@@ -107,7 +103,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
.pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask,
} },
-#if NUM_SSC_DEVICES == 3
{{
.name = "SSC1 PCM out",
.pdc = &pdc_tx_reg,
@@ -128,7 +123,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
.pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask,
} },
-#endif
};
@@ -139,7 +133,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
.dir_mask = SSC_DIR_MASK_UNUSED,
.initialized = 0,
},
-#if NUM_SSC_DEVICES == 3
{
.name = "ssc1",
.lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
@@ -152,7 +145,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
.dir_mask = SSC_DIR_MASK_UNUSED,
.initialized = 0,
},
-#endif
};
@@ -690,27 +682,9 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
static int atmel_ssc_probe(struct snd_soc_dai *dai)
{
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
- int ret = 0;
snd_soc_dai_set_drvdata(dai, ssc_p);
- /*
- * Request SSC device
- */
- ssc_p->ssc = ssc_request(dai->id);
- if (IS_ERR(ssc_p->ssc)) {
- printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
- ret = PTR_ERR(ssc_p->ssc);
- }
-
- return ret;
-}
-
-static int atmel_ssc_remove(struct snd_soc_dai *dai)
-{
- struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
-
- ssc_free(ssc_p->ssc);
return 0;
}
@@ -728,30 +702,8 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
.set_clkdiv = atmel_ssc_set_dai_clkdiv,
};
-static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
- {
- .name = "atmel-ssc-dai.0",
- .probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = &atmel_ssc_dai_ops,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "atmel-ssc-dai.1",
+static struct snd_soc_dai_driver atmel_ssc_dai = {
.probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume,
.playback = {
@@ -765,50 +717,50 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops,
- },
- {
- .name = "atmel-ssc-dai.2",
- .probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = &atmel_ssc_dai_ops,
- },
-#endif
};
-static __devinit int asoc_ssc_probe(struct platform_device *pdev)
+static int asoc_ssc_init(struct device *dev)
{
- BUG_ON(pdev->id < 0);
- BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
- return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
-}
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ssc_device *ssc = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
+ if (ret) {
+ dev_err(dev, "Could not register DAI: %d\n", ret);
+ goto err;
+ }
+
+ if (ssc->pdata->use_dma)
+ ret = atmel_pcm_dma_platform_register(dev);
+ else
+ ret = atmel_pcm_pdc_platform_register(dev);
+
+ if (ret) {
+ dev_err(dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ };
-static int __devexit asoc_ssc_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_dai(&pdev->dev);
return 0;
+
+err_unregister_dai:
+ snd_soc_unregister_dai(dev);
+err:
+ return ret;
}
-static struct platform_driver asoc_ssc_driver = {
- .driver = {
- .name = "atmel-ssc-dai",
- .owner = THIS_MODULE,
- },
+static void asoc_ssc_exit(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ssc_device *ssc = platform_get_drvdata(pdev);
- .probe = asoc_ssc_probe,
- .remove = __devexit_p(asoc_ssc_remove),
-};
+ if (ssc->pdata->use_dma)
+ atmel_pcm_dma_platform_unregister(dev);
+ else
+ atmel_pcm_pdc_platform_unregister(dev);
+
+ snd_soc_unregister_dai(dev);
+}
/**
* atmel_ssc_set_audio - Allocate the specified SSC for audio use.
@@ -816,50 +768,32 @@ static struct platform_driver asoc_ssc_driver = {
int atmel_ssc_set_audio(int ssc_id)
{
struct ssc_device *ssc;
- static struct platform_device *dma_pdev;
- struct platform_device *ssc_pdev;
int ret;
- if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
- return -EINVAL;
-
- /* Allocate a dummy device for DMA if we don't have one already */
- if (!dma_pdev) {
- dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
- if (!dma_pdev)
- return -ENOMEM;
-
- ret = platform_device_add(dma_pdev);
- if (ret < 0) {
- platform_device_put(dma_pdev);
- dma_pdev = NULL;
- return ret;
- }
- }
-
- ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
- if (!ssc_pdev)
- return -ENOMEM;
-
/* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id);
- if (IS_ERR(ssc))
- pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
+ if (IS_ERR(ssc)) {
+ pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
PTR_ERR(ssc));
- else {
- ssc_pdev->dev.parent = &(ssc->pdev->dev);
- ssc_free(ssc);
+ return PTR_ERR(ssc);
+ } else {
+ ssc_info[ssc_id].ssc = ssc;
}
- ret = platform_device_add(ssc_pdev);
- if (ret < 0)
- platform_device_put(ssc_pdev);
+ ret = asoc_ssc_init(&ssc->pdev->dev);
return ret;
}
EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
-module_platform_driver(asoc_ssc_driver);
+void atmel_ssc_put_audio(int ssc_id)
+{
+ struct ssc_device *ssc = ssc_info[ssc_id].ssc;
+
+ ssc_free(ssc);
+ asoc_ssc_exit(&ssc->pdev->dev);
+}
+EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);
/* Module information */
MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
index 5d4f0f9b4d9a..b1f08d511495 100644
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -117,6 +117,7 @@ struct atmel_ssc_info {
struct atmel_ssc_state ssc_state;
};
-int atmel_ssc_set_audio(int ssc);
+int atmel_ssc_set_audio(int ssc_id);
+void atmel_ssc_put_audio(int ssc_id);
#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index c88351488f45..da976291da9e 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -38,6 +38,8 @@
#include <linux/platform_device.h>
#include <linux/i2c.h>
+#include <linux/pinctrl/consumer.h>
+
#include <linux/atmel-ssc.h>
#include <sound/core.h>
@@ -179,10 +181,10 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link at91sam9g20ek_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
- .cpu_dai_name = "atmel-ssc-dai.0",
+ .cpu_dai_name = "at91rm9200_ssc.0",
.codec_dai_name = "wm8731-hifi",
.init = at91sam9g20ek_wm8731_init,
- .platform_name = "atmel-pcm-audio",
+ .platform_name = "at91rm9200_ssc.0",
.codec_name = "wm8731.0-001b",
.ops = &at91sam9g20ek_ops,
};
@@ -195,20 +197,31 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
.set_bias_level = at91sam9g20ek_set_bias_level,
};
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
+static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *codec_np, *cpu_np;
struct clk *pllb;
+ struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
+ struct pinctrl *pinctrl;
int ret;
- if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
- return -ENODEV;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "Failed to request pinctrl for mck\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ if (!np) {
+ if (!(machine_is_at91sam9g20ek() ||
+ machine_is_at91sam9g20ek_2mmc()))
+ return -ENODEV;
+ }
ret = atmel_ssc_set_audio(0);
- if (ret != 0) {
- pr_err("Failed to set SSC 0 for audio: %d\n", ret);
- return ret;
+ if (ret) {
+ dev_err(&pdev->dev, "ssc channel is not valid\n");
+ return -EINVAL;
}
/*
@@ -236,45 +249,92 @@ static int __init at91sam9g20ek_init(void)
clk_set_rate(mclk, MCLK_RATE);
- at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
- if (!at91sam9g20ek_snd_device) {
- printk(KERN_ERR "ASoC: Platform device allocation failed\n");
- ret = -ENOMEM;
- goto err_mclk;
+ card->dev = &pdev->dev;
+
+ /* Parse device node info */
+ if (np) {
+ ret = snd_soc_of_parse_card_name(card, "atmel,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card,
+ "atmel,audio-routing");
+ if (ret)
+ goto err;
+
+ /* Parse codec info */
+ at91sam9g20ek_dai.codec_name = NULL;
+ codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "codec info missing\n");
+ return -EINVAL;
+ }
+ at91sam9g20ek_dai.codec_of_node = codec_np;
+
+ /* Parse dai and platform info */
+ at91sam9g20ek_dai.cpu_dai_name = NULL;
+ at91sam9g20ek_dai.platform_name = NULL;
+ cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "dai and pcm info missing\n");
+ return -EINVAL;
+ }
+ at91sam9g20ek_dai.cpu_of_node = cpu_np;
+ at91sam9g20ek_dai.platform_of_node = cpu_np;
+
+ of_node_put(codec_np);
+ of_node_put(cpu_np);
}
- platform_set_drvdata(at91sam9g20ek_snd_device,
- &snd_soc_at91sam9g20ek);
-
- ret = platform_device_add(at91sam9g20ek_snd_device);
+ ret = snd_soc_register_card(card);
if (ret) {
- printk(KERN_ERR "ASoC: Platform device allocation failed\n");
- goto err_device_add;
+ printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
}
return ret;
-err_device_add:
- platform_device_put(at91sam9g20ek_snd_device);
err_mclk:
clk_put(mclk);
mclk = NULL;
err:
+ atmel_ssc_put_audio(0);
return ret;
}
-static void __exit at91sam9g20ek_exit(void)
+static int at91sam9g20ek_audio_remove(struct platform_device *pdev)
{
- platform_device_unregister(at91sam9g20ek_snd_device);
- at91sam9g20ek_snd_device = NULL;
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ atmel_ssc_put_audio(0);
+ snd_soc_unregister_card(card);
clk_put(mclk);
mclk = NULL;
+
+ return 0;
}
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
+#ifdef CONFIG_OF
+static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = {
+ { .compatible = "atmel,at91sam9g20ek-wm8731-audio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids);
+#endif
+
+static struct platform_driver at91sam9g20ek_audio_driver = {
+ .driver = {
+ .name = "at91sam9g20ek-audio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
+ },
+ .probe = at91sam9g20ek_audio_probe,
+ .remove = at91sam9g20ek_audio_remove,
+};
+
+module_platform_driver(at91sam9g20ek_audio_driver);
/* Module information */
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_ALIAS("platform:at91sam9g20ek-audio");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index c5ac2449563a..ea7d9d157022 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -223,7 +223,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
.ops = &alchemy_ac97c_ops,
};
-static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
+static int au1xac97c_drvprobe(struct platform_device *pdev)
{
int ret;
struct resource *iores, *dmares;
@@ -276,7 +276,7 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
return 0;
}
-static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
+static int au1xac97c_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
@@ -330,7 +330,7 @@ static struct platform_driver au1xac97c_driver = {
.pm = AU1XPSCAC97_PMOPS,
},
.probe = au1xac97c_drvprobe,
- .remove = __devexit_p(au1xac97c_drvremove),
+ .remove = au1xac97c_drvremove,
};
static int __init au1xac97c_load(void)
diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c
index 511d83c11a9a..376d976bcc2d 100644
--- a/sound/soc/au1x/db1000.c
+++ b/sound/soc/au1x/db1000.c
@@ -34,14 +34,14 @@ static struct snd_soc_card db1000_ac97 = {
.num_links = 1,
};
-static int __devinit db1000_audio_probe(struct platform_device *pdev)
+static int db1000_audio_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &db1000_ac97;
card->dev = &pdev->dev;
return snd_soc_register_card(card);
}
-static int __devexit db1000_audio_remove(struct platform_device *pdev)
+static int db1000_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
@@ -55,7 +55,7 @@ static struct platform_driver db1000_audio_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = db1000_audio_probe,
- .remove = __devexit_p(db1000_audio_remove),
+ .remove = db1000_audio_remove,
};
module_platform_driver(db1000_audio_driver);
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index 30ea513d81d7..a497a0cfeba1 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -167,7 +167,7 @@ static struct snd_soc_card db1550_i2s_machine = {
/*------------------------- COMMON PART ---------------------------*/
-static struct snd_soc_card *db1200_cards[] __devinitdata = {
+static struct snd_soc_card *db1200_cards[] = {
&db1200_ac97_machine,
&db1200_i2s_machine,
&db1300_ac97_machine,
@@ -176,7 +176,7 @@ static struct snd_soc_card *db1200_cards[] __devinitdata = {
&db1550_i2s_machine,
};
-static int __devinit db1200_audio_probe(struct platform_device *pdev)
+static int db1200_audio_probe(struct platform_device *pdev)
{
const struct platform_device_id *pid = platform_get_device_id(pdev);
struct snd_soc_card *card;
@@ -186,7 +186,7 @@ static int __devinit db1200_audio_probe(struct platform_device *pdev)
return snd_soc_register_card(card);
}
-static int __devexit db1200_audio_remove(struct platform_device *pdev)
+static int db1200_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
@@ -201,7 +201,7 @@ static struct platform_driver db1200_audio_driver = {
},
.id_table = db1200_pids,
.probe = db1200_audio_probe,
- .remove = __devexit_p(db1200_audio_remove),
+ .remove = db1200_audio_remove,
};
module_platform_driver(db1200_audio_driver);
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 8372cd35f0d6..3b4eafaf30d3 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -347,7 +347,7 @@ static struct snd_soc_platform_driver au1xpsc_soc_platform = {
.pcm_free = au1xpsc_pcm_free_dma_buffers,
};
-static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
+static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)
{
struct au1xpsc_audio_dmadata *dmadata;
@@ -362,7 +362,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
}
-static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
+static int au1xpsc_pcm_drvremove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
@@ -375,7 +375,7 @@ static struct platform_driver au1xpsc_pcm_driver = {
.owner = THIS_MODULE,
},
.probe = au1xpsc_pcm_drvprobe,
- .remove = __devexit_p(au1xpsc_pcm_drvremove),
+ .remove = au1xpsc_pcm_drvremove,
};
module_platform_driver(au1xpsc_pcm_driver);
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
index 0a91b186a86f..befd1074f9bd 100644
--- a/sound/soc/au1x/dma.c
+++ b/sound/soc/au1x/dma.c
@@ -322,7 +322,7 @@ static struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
.pcm_free = alchemy_pcm_free_dma_buffers,
};
-static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
+static int alchemy_pcm_drvprobe(struct platform_device *pdev)
{
struct alchemy_pcm_ctx *ctx;
@@ -335,7 +335,7 @@ static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform);
}
-static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev)
+static int alchemy_pcm_drvremove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
@@ -348,7 +348,7 @@ static struct platform_driver alchemy_pcmdma_driver = {
.owner = THIS_MODULE,
},
.probe = alchemy_pcm_drvprobe,
- .remove = __devexit_p(alchemy_pcm_drvremove),
+ .remove = alchemy_pcm_drvremove,
};
module_platform_driver(alchemy_pcmdma_driver);
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index d4b9e364a47a..072448afc219 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -225,7 +225,7 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
.ops = &au1xi2s_dai_ops,
};
-static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
+static int au1xi2s_drvprobe(struct platform_device *pdev)
{
struct resource *iores, *dmares;
struct au1xpsc_audio_data *ctx;
@@ -263,7 +263,7 @@ static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
}
-static int __devexit au1xi2s_drvremove(struct platform_device *pdev)
+static int au1xi2s_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
@@ -309,7 +309,7 @@ static struct platform_driver au1xi2s_driver = {
.pm = AU1XI2SC_PMOPS,
},
.probe = au1xi2s_drvprobe,
- .remove = __devexit_p(au1xi2s_drvremove),
+ .remove = au1xi2s_drvremove,
};
module_platform_driver(au1xi2s_driver);
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 476b79a1c11a..6ba07e365967 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -361,7 +361,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
.ops = &au1xpsc_ac97_dai_ops,
};
-static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
+static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
{
int ret;
struct resource *iores, *dmares;
@@ -427,7 +427,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
return 0;
}
-static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
+static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
@@ -495,7 +495,7 @@ static struct platform_driver au1xpsc_ac97_driver = {
.pm = AU1XPSCAC97_PMOPS,
},
.probe = au1xpsc_ac97_drvprobe,
- .remove = __devexit_p(au1xpsc_ac97_drvremove),
+ .remove = au1xpsc_ac97_drvremove,
};
static int __init au1xpsc_ac97_load(void)
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 0607ba3d9258..360b4e50d7c8 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -288,7 +288,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
.ops = &au1xpsc_i2s_dai_ops,
};
-static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
+static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
{
struct resource *iores, *dmares;
unsigned long sel;
@@ -353,7 +353,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
}
-static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
+static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
@@ -418,7 +418,7 @@ static struct platform_driver au1xpsc_i2s_driver = {
.pm = AU1XPSCI2S_PMOPS,
},
.probe = au1xpsc_i2s_drvprobe,
- .remove = __devexit_p(au1xpsc_i2s_drvremove),
+ .remove = au1xpsc_i2s_drvremove,
};
module_platform_driver(au1xpsc_i2s_driver);
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index d7dc9bde0976..7e2f36004a5a 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -453,12 +453,12 @@ static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
.pcm_free = bf5xx_pcm_free_dma_buffers,
};
-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
+static int bf5xx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
}
-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
+static int bf5xx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -471,7 +471,7 @@ static struct platform_driver bf5xx_pcm_driver = {
},
.probe = bf5xx_soc_platform_probe,
- .remove = __devexit_p(bf5xx_soc_platform_remove),
+ .remove = bf5xx_soc_platform_remove,
};
module_platform_driver(bf5xx_pcm_driver);
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index f4e9dc4e262e..8e41bcb020eb 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -282,7 +282,7 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
};
-static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
+static int asoc_bfin_ac97_probe(struct platform_device *pdev)
{
struct sport_device *sport_handle;
int ret;
@@ -352,7 +352,7 @@ gpio_err:
return ret;
}
-static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
+static int asoc_bfin_ac97_remove(struct platform_device *pdev)
{
struct sport_device *sport_handle = platform_get_drvdata(pdev);
@@ -372,7 +372,7 @@ static struct platform_driver asoc_bfin_ac97_driver = {
},
.probe = asoc_bfin_ac97_probe,
- .remove = __devexit_p(asoc_bfin_ac97_remove),
+ .remove = asoc_bfin_ac97_remove,
};
module_platform_driver(asoc_bfin_ac97_driver);
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 16b9c9efd19a..d23f4b0ea54f 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -75,7 +75,7 @@ static struct snd_soc_card bf5xx_ad1836 = {
.num_links = 1,
};
-static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
+static int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &bf5xx_ad1836;
const char **link_name;
@@ -98,7 +98,7 @@ static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev)
+static int bf5xx_ad1836_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -113,7 +113,7 @@ static struct platform_driver bf5xx_ad1836_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = bf5xx_ad1836_driver_probe,
- .remove = __devexit_p(bf5xx_ad1836_driver_remove),
+ .remove = bf5xx_ad1836_driver_remove,
};
module_platform_driver(bf5xx_ad1836_driver);
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 63205d723eab..262c1de364d8 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -292,12 +292,12 @@ static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
.pcm_free = bf5xx_pcm_free_dma_buffers,
};
-static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
+static int bfin_i2s_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
}
-static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
+static int bfin_i2s_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -310,7 +310,7 @@ static struct platform_driver bfin_i2s_pcm_driver = {
},
.probe = bfin_i2s_soc_platform_probe,
- .remove = __devexit_p(bfin_i2s_soc_platform_remove),
+ .remove = bfin_i2s_soc_platform_remove,
};
module_platform_driver(bfin_i2s_pcm_driver);
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 4dccf0374fe7..168d88bccb41 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -245,7 +245,7 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
.ops = &bf5xx_i2s_dai_ops,
};
-static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
+static int bf5xx_i2s_probe(struct platform_device *pdev)
{
struct sport_device *sport_handle;
int ret;
@@ -267,7 +267,7 @@ static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
+static int bf5xx_i2s_remove(struct platform_device *pdev)
{
struct sport_device *sport_handle = platform_get_drvdata(pdev);
@@ -281,7 +281,7 @@ static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
static struct platform_driver bfin_i2s_driver = {
.probe = bf5xx_i2s_probe,
- .remove = __devexit_p(bf5xx_i2s_remove),
+ .remove = bf5xx_i2s_remove,
.driver = {
.name = "bfin-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index 254490cf1876..0e6b888bb4cc 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -317,12 +317,12 @@ static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
.pcm_free = bf5xx_pcm_free_dma_buffers,
};
-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
+static int bf5xx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
}
-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
+static int bf5xx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -335,7 +335,7 @@ static struct platform_driver bfin_tdm_driver = {
},
.probe = bf5xx_soc_platform_probe,
- .remove = __devexit_p(bf5xx_soc_platform_remove),
+ .remove = bf5xx_soc_platform_remove,
};
module_platform_driver(bfin_tdm_driver);
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index 594f88217c74..c1e516ec53ad 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -249,7 +249,7 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
.ops = &bf5xx_tdm_dai_ops,
};
-static int __devinit bfin_tdm_probe(struct platform_device *pdev)
+static int bfin_tdm_probe(struct platform_device *pdev)
{
struct sport_device *sport_handle;
int ret;
@@ -295,7 +295,7 @@ sport_config_err:
return ret;
}
-static int __devexit bfin_tdm_remove(struct platform_device *pdev)
+static int bfin_tdm_remove(struct platform_device *pdev)
{
struct sport_device *sport_handle = platform_get_drvdata(pdev);
@@ -307,7 +307,7 @@ static int __devexit bfin_tdm_remove(struct platform_device *pdev)
static struct platform_driver bfin_tdm_driver = {
.probe = bfin_tdm_probe,
- .remove = __devexit_p(bfin_tdm_remove),
+ .remove = bfin_tdm_remove,
.driver = {
.name = "bfin-tdm",
.owner = THIS_MODULE,
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
index c3c2466d3a42..8f337972f438 100644
--- a/sound/soc/blackfin/bf6xx-i2s.c
+++ b/sound/soc/blackfin/bf6xx-i2s.c
@@ -186,7 +186,7 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
.ops = &bfin_i2s_dai_ops,
};
-static int __devinit bfin_i2s_probe(struct platform_device *pdev)
+static int bfin_i2s_probe(struct platform_device *pdev)
{
struct sport_device *sport;
struct device *dev = &pdev->dev;
@@ -208,7 +208,7 @@ static int __devinit bfin_i2s_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bfin_i2s_remove(struct platform_device *pdev)
+static int bfin_i2s_remove(struct platform_device *pdev)
{
struct sport_device *sport = platform_get_drvdata(pdev);
@@ -220,7 +220,7 @@ static int __devexit bfin_i2s_remove(struct platform_device *pdev)
static struct platform_driver bfin_i2s_driver = {
.probe = bfin_i2s_probe,
- .remove = __devexit_p(bfin_i2s_remove),
+ .remove = bfin_i2s_remove,
.driver = {
.name = "bfin-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
index f3adbdbdd5e1..4ef9683bcad8 100644
--- a/sound/soc/blackfin/bfin-eval-adau1373.c
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -157,7 +157,7 @@ static int bfin_eval_adau1373_probe(struct platform_device *pdev)
return snd_soc_register_card(&bfin_eval_adau1373);
}
-static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev)
+static int bfin_eval_adau1373_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -173,7 +173,7 @@ static struct platform_driver bfin_eval_adau1373_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = bfin_eval_adau1373_probe,
- .remove = __devexit_p(bfin_eval_adau1373_remove),
+ .remove = bfin_eval_adau1373_remove,
};
module_platform_driver(bfin_eval_adau1373_driver);
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index b0531fc9d814..3b55081a96c0 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -97,7 +97,7 @@ static int bfin_eval_adau1701_probe(struct platform_device *pdev)
return snd_soc_register_card(&bfin_eval_adau1701);
}
-static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev)
+static int bfin_eval_adau1701_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -113,7 +113,7 @@ static struct platform_driver bfin_eval_adau1701_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = bfin_eval_adau1701_probe,
- .remove = __devexit_p(bfin_eval_adau1701_remove),
+ .remove = bfin_eval_adau1701_remove,
};
module_platform_driver(bfin_eval_adau1701_driver);
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 84b09987b7f3..3b1b61a44815 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -122,7 +122,7 @@ static int bfin_eval_adav80x_probe(struct platform_device *pdev)
return snd_soc_register_card(&bfin_eval_adav80x);
}
-static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev)
+static int bfin_eval_adav80x_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -145,7 +145,7 @@ static struct platform_driver bfin_eval_adav80x_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = bfin_eval_adav80x_probe,
- .remove = __devexit_p(bfin_eval_adav80x_remove),
+ .remove = bfin_eval_adav80x_remove,
.id_table = bfin_eval_adav80x_ids,
};
diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c
index e01cb02abd3a..5db68cf7b281 100644
--- a/sound/soc/cirrus/edb93xx.c
+++ b/sound/soc/cirrus/edb93xx.c
@@ -80,7 +80,7 @@ static struct snd_soc_card snd_soc_edb93xx = {
.num_links = 1,
};
-static int __devinit edb93xx_probe(struct platform_device *pdev)
+static int edb93xx_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_edb93xx;
int ret;
@@ -101,7 +101,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit edb93xx_remove(struct platform_device *pdev)
+static int edb93xx_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -117,7 +117,7 @@ static struct platform_driver edb93xx_driver = {
.owner = THIS_MODULE,
},
.probe = edb93xx_probe,
- .remove = __devexit_p(edb93xx_remove),
+ .remove = edb93xx_remove,
};
module_platform_driver(edb93xx_driver);
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index c3521653cfd3..f3f50e6fd6eb 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -352,7 +352,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
.ops = &ep93xx_ac97_dai_ops,
};
-static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
+static int ep93xx_ac97_probe(struct platform_device *pdev)
{
struct ep93xx_ac97_info *info;
struct resource *res;
@@ -402,7 +402,7 @@ fail:
return ret;
}
-static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
+static int ep93xx_ac97_remove(struct platform_device *pdev)
{
struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
@@ -420,7 +420,7 @@ static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
static struct platform_driver ep93xx_ac97_driver = {
.probe = ep93xx_ac97_probe,
- .remove = __devexit_p(ep93xx_ac97_remove),
+ .remove = ep93xx_ac97_remove,
.driver = {
.name = "ep93xx-ac97",
.owner = THIS_MODULE,
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index ac4a7515e7be..3365d4e843b7 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -422,7 +422,7 @@ fail:
return err;
}
-static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
+static int ep93xx_i2s_remove(struct platform_device *pdev)
{
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
@@ -436,7 +436,7 @@ static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
static struct platform_driver ep93xx_i2s_driver = {
.probe = ep93xx_i2s_probe,
- .remove = __devexit_p(ep93xx_i2s_remove),
+ .remove = ep93xx_i2s_remove,
.driver = {
.name = "ep93xx-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 665d9c94cc17..72eb7a49e16a 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -213,12 +213,12 @@ static struct snd_soc_platform_driver ep93xx_soc_platform = {
.pcm_free = &ep93xx_pcm_free_dma_buffers,
};
-static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
+static int ep93xx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
}
-static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
+static int ep93xx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -231,7 +231,7 @@ static struct platform_driver ep93xx_pcm_driver = {
},
.probe = ep93xx_soc_platform_probe,
- .remove = __devexit_p(ep93xx_soc_platform_remove),
+ .remove = ep93xx_soc_platform_remove,
};
module_platform_driver(ep93xx_pcm_driver);
diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c
index dd997094eb30..a397bb0d8179 100644
--- a/sound/soc/cirrus/simone.c
+++ b/sound/soc/cirrus/simone.c
@@ -41,7 +41,7 @@ static struct snd_soc_card snd_soc_simone = {
static struct platform_device *simone_snd_ac97_device;
-static int __devinit simone_probe(struct platform_device *pdev)
+static int simone_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_simone;
int ret;
@@ -63,7 +63,7 @@ static int __devinit simone_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit simone_remove(struct platform_device *pdev)
+static int simone_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -79,7 +79,7 @@ static struct platform_driver simone_driver = {
.owner = THIS_MODULE,
},
.probe = simone_probe,
- .remove = __devexit_p(simone_remove),
+ .remove = simone_remove,
};
module_platform_driver(simone_driver);
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c
index a193cea3cf3c..9d77fe28dfcc 100644
--- a/sound/soc/cirrus/snappercl15.c
+++ b/sound/soc/cirrus/snappercl15.c
@@ -98,7 +98,7 @@ static struct snd_soc_card snd_soc_snappercl15 = {
.num_links = 1,
};
-static int __devinit snappercl15_probe(struct platform_device *pdev)
+static int snappercl15_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_snappercl15;
int ret;
@@ -119,7 +119,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit snappercl15_remove(struct platform_device *pdev)
+static int snappercl15_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -135,7 +135,7 @@ static struct platform_driver snappercl15_driver = {
.owner = THIS_MODULE,
},
.probe = snappercl15_probe,
- .remove = __devexit_p(snappercl15_remove),
+ .remove = snappercl15_remove,
};
module_platform_driver(snappercl15_driver);
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 9fd3b6827bba..60159c07448d 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1423,7 +1423,7 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes),
};
-static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+static int pm860x_codec_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_priv *pm860x;
@@ -1463,7 +1463,7 @@ out:
return -EINVAL;
}
-static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+static int pm860x_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
platform_set_drvdata(pdev, NULL);
@@ -1476,7 +1476,7 @@ static struct platform_driver pm860x_codec_driver = {
.owner = THIS_MODULE,
},
.probe = pm860x_codec_probe,
- .remove = __devexit_p(pm860x_codec_remove),
+ .remove = pm860x_codec_remove,
};
module_platform_driver(pm860x_codec_driver);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b92759a39361..3a847828932a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_LM4857 if I2C
select SND_SOC_LM49453 if I2C
select SND_SOC_MAX98088 if I2C
+ select SND_SOC_MAX98090 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9768 if I2C
@@ -54,6 +55,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
+ select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -146,6 +148,13 @@ config SND_SOC_WM_HUBS
default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
+config SND_SOC_WM_ADSP
+ tristate
+ default y if SND_SOC_WM5102=y
+ default y if SND_SOC_WM2200=y
+ default m if SND_SOC_WM5102=m
+ default m if SND_SOC_WM2200=m
+
config SND_SOC_AB8500_CODEC
tristate
@@ -229,6 +238,7 @@ config SND_SOC_CX20442
tristate
config SND_SOC_JZ4740_CODEC
+ select REGMAP_MMIO
tristate
config SND_SOC_L3
@@ -258,6 +268,9 @@ config SND_SOC_LM49453
config SND_SOC_MAX98088
tristate
+config SND_SOC_MAX98090
+ tristate
+
config SND_SOC_MAX98095
tristate
@@ -277,6 +290,9 @@ config SND_SOC_RT5631
config SND_SOC_SGTL5000
tristate
+config SND_SOC_SI476X
+ tristate
+
config SND_SOC_SIGMADSP
tristate
select CRC32
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 9bd4d95aab4f..f6e8e36cceb7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -34,6 +34,7 @@ snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
+snd-soc-max98090-objs := max98090.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
snd-soc-mc13783-objs := mc13783.o
@@ -45,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-tx-objs := spdif_transciever.o
snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -62,6 +64,7 @@ snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
+snd-soc-wm-adsp-objs := wm_adsp.o
snd-soc-wm0010-objs := wm0010.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
@@ -155,6 +158,7 @@ obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
+obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
@@ -164,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -229,6 +234,7 @@ obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
# Amp
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index af547490b4f7..6c12ac206ee9 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2356,7 +2356,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
return 0;
}
-struct snd_soc_dai_driver ab8500_codec_dai[] = {
+static struct snd_soc_dai_driver ab8500_codec_dai[] = {
{
.name = "ab8500-codec-dai.0",
.id = 0,
@@ -2554,7 +2554,7 @@ static struct snd_soc_codec_driver ab8500_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes),
};
-static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
+static int ab8500_codec_driver_probe(struct platform_device *pdev)
{
int status;
struct ab8500_codec_drvdata *drvdata;
@@ -2580,7 +2580,7 @@ static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
return status;
}
-static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
+static int ab8500_codec_driver_remove(struct platform_device *pdev)
{
dev_info(&pdev->dev, "%s Enter.\n", __func__);
@@ -2595,7 +2595,7 @@ static struct platform_driver ab8500_codec_platform_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_codec_driver_probe,
- .remove = __devexit_p(ab8500_codec_driver_remove),
+ .remove = ab8500_codec_driver_remove,
.suspend = NULL,
.resume = NULL,
};
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index ea06b834a7de..ef2ae32ffc66 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -118,13 +118,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
.resume = ac97_soc_resume,
};
-static __devinit int ac97_probe(struct platform_device *pdev)
+static int ac97_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ac97, &ac97_dai, 1);
}
-static int __devexit ac97_remove(struct platform_device *pdev)
+static int ac97_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -137,7 +137,7 @@ static struct platform_driver ac97_codec_driver = {
},
.probe = ac97_probe,
- .remove = __devexit_p(ac97_remove),
+ .remove = ac97_remove,
};
module_platform_driver(ac97_codec_driver);
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index dce6ebeef452..9a92b7962f41 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -360,7 +360,7 @@ static const struct regmap_config ad1836_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit ad1836_spi_probe(struct spi_device *spi)
+static int ad1836_spi_probe(struct spi_device *spi)
{
struct ad1836_priv *ad1836;
int ret;
@@ -383,7 +383,7 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit ad1836_spi_remove(struct spi_device *spi)
+static int ad1836_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -405,7 +405,7 @@ static struct spi_driver ad1836_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad1836_spi_probe,
- .remove = __devexit_p(ad1836_spi_remove),
+ .remove = ad1836_spi_remove,
.id_table = ad1836_ids,
};
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 2f752660f678..aea7e52cf714 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -378,7 +378,7 @@ static const struct regmap_config ad193x_spi_regmap_config = {
.volatile_reg = adau193x_reg_volatile,
};
-static int __devinit ad193x_spi_probe(struct spi_device *spi)
+static int ad193x_spi_probe(struct spi_device *spi)
{
struct ad193x_priv *ad193x;
@@ -397,7 +397,7 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi)
&ad193x_dai, 1);
}
-static int __devexit ad193x_spi_remove(struct spi_device *spi)
+static int ad193x_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -409,7 +409,7 @@ static struct spi_driver ad193x_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad193x_spi_probe,
- .remove = __devexit_p(ad193x_spi_remove),
+ .remove = ad193x_spi_remove,
};
#endif
@@ -430,8 +430,8 @@ static const struct i2c_device_id ad193x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ad193x_id);
-static int __devinit ad193x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ad193x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ad193x_priv *ad193x;
@@ -450,7 +450,7 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
&ad193x_dai, 1);
}
-static int __devexit ad193x_i2c_remove(struct i2c_client *client)
+static int ad193x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -461,7 +461,7 @@ static struct i2c_driver ad193x_i2c_driver = {
.name = "ad193x",
},
.probe = ad193x_i2c_probe,
- .remove = __devexit_p(ad193x_i2c_remove),
+ .remove = ad193x_i2c_remove,
.id_table = ad193x_id,
};
#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 8c39dddd7d00..f385342947d3 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -255,13 +255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
.read = ac97_read,
};
-static __devinit int ad1980_probe(struct platform_device *pdev)
+static int ad1980_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ad1980, &ad1980_dai, 1);
}
-static int __devexit ad1980_remove(struct platform_device *pdev)
+static int ad1980_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -274,7 +274,7 @@ static struct platform_driver ad1980_codec_driver = {
},
.probe = ad1980_probe,
- .remove = __devexit_p(ad1980_remove),
+ .remove = ad1980_remove,
};
module_platform_driver(ad1980_codec_driver);
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index ee7a68dcefd2..b1f2baf42b48 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -47,7 +47,7 @@ static int ad73311_probe(struct platform_device *pdev)
&soc_codec_dev_ad73311, &ad73311_dai, 1);
}
-static int __devexit ad73311_remove(struct platform_device *pdev)
+static int ad73311_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -60,7 +60,7 @@ static struct platform_driver ad73311_codec_driver = {
},
.probe = ad73311_probe,
- .remove = __devexit_p(ad73311_remove),
+ .remove = ad73311_remove,
};
module_platform_driver(ad73311_codec_driver);
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 704544bfc90d..068b3ae56a17 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1353,8 +1353,8 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
};
-static int __devinit adau1373_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adau1373_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct adau1373 *adau1373;
int ret;
@@ -1370,7 +1370,7 @@ static int __devinit adau1373_i2c_probe(struct i2c_client *client,
return ret;
}
-static int __devexit adau1373_i2c_remove(struct i2c_client *client)
+static int adau1373_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1388,7 +1388,7 @@ static struct i2c_driver adau1373_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adau1373_i2c_probe,
- .remove = __devexit_p(adau1373_i2c_remove),
+ .remove = adau1373_i2c_remove,
.id_table = adau1373_i2c_id,
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 51f2f3cd8136..dafdbe87edeb 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -489,8 +489,8 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
.set_sysclk = adau1701_set_sysclk,
};
-static __devinit int adau1701_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adau1701_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct adau1701 *adau1701;
int ret;
@@ -505,7 +505,7 @@ static __devinit int adau1701_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int adau1701_i2c_remove(struct i2c_client *client)
+static int adau1701_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -523,7 +523,7 @@ static struct i2c_driver adau1701_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adau1701_i2c_probe,
- .remove = __devexit_p(adau1701_i2c_remove),
+ .remove = adau1701_i2c_remove,
.id_table = adau1701_i2c_id,
};
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index ebd7b37b902b..3c839cc4e00e 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -839,8 +839,8 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
};
-static int __devinit adav80x_bus_probe(struct device *dev,
- enum snd_soc_control_type control_type)
+static int adav80x_bus_probe(struct device *dev,
+ enum snd_soc_control_type control_type)
{
struct adav80x *adav80x;
int ret;
@@ -860,7 +860,7 @@ static int __devinit adav80x_bus_probe(struct device *dev,
return ret;
}
-static int __devexit adav80x_bus_remove(struct device *dev)
+static int adav80x_bus_remove(struct device *dev)
{
snd_soc_unregister_codec(dev);
kfree(dev_get_drvdata(dev));
@@ -868,12 +868,12 @@ static int __devexit adav80x_bus_remove(struct device *dev)
}
#if defined(CONFIG_SPI_MASTER)
-static int __devinit adav80x_spi_probe(struct spi_device *spi)
+static int adav80x_spi_probe(struct spi_device *spi)
{
return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
}
-static int __devexit adav80x_spi_remove(struct spi_device *spi)
+static int adav80x_spi_remove(struct spi_device *spi)
{
return adav80x_bus_remove(&spi->dev);
}
@@ -884,7 +884,7 @@ static struct spi_driver adav80x_spi_driver = {
.owner = THIS_MODULE,
},
.probe = adav80x_spi_probe,
- .remove = __devexit_p(adav80x_spi_remove),
+ .remove = adav80x_spi_remove,
};
#endif
@@ -895,13 +895,13 @@ static const struct i2c_device_id adav80x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, adav80x_id);
-static int __devinit adav80x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adav80x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
}
-static int __devexit adav80x_i2c_remove(struct i2c_client *client)
+static int adav80x_i2c_remove(struct i2c_client *client)
{
return adav80x_bus_remove(&client->dev);
}
@@ -912,7 +912,7 @@ static struct i2c_driver adav80x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adav80x_i2c_probe,
- .remove = __devexit_p(adav80x_i2c_remove),
+ .remove = adav80x_i2c_remove,
.id_table = adav80x_id,
};
#endif
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 8103b938b8c0..506d474c4d22 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -36,13 +36,13 @@ static struct snd_soc_dai_driver ads117x_dai = {
static struct snd_soc_codec_driver soc_codec_dev_ads117x;
-static __devinit int ads117x_probe(struct platform_device *pdev)
+static int ads117x_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ads117x, &ads117x_dai, 1);
}
-static int __devexit ads117x_remove(struct platform_device *pdev)
+static int ads117x_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -55,7 +55,7 @@ static struct platform_driver ads117x_codec_driver = {
},
.probe = ads117x_probe,
- .remove = __devexit_p(ads117x_remove),
+ .remove = ads117x_remove,
};
module_platform_driver(ads117x_codec_driver);
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 31d4483245d0..6f6c335a5baa 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -15,6 +15,8 @@
#include <sound/soc.h>
#include <sound/initval.h>
#include <linux/spi/spi.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <sound/asoundef.h>
/* AK4104 registers addresses */
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
val = 0;
switch (params_rate(params)) {
+ case 22050:
+ val |= IEC958_AES3_CON_FS_22050;
+ break;
+ case 24000:
+ val |= IEC958_AES3_CON_FS_24000;
+ break;
+ case 32000:
+ val |= IEC958_AES3_CON_FS_32000;
+ break;
case 44100:
val |= IEC958_AES3_CON_FS_44100;
break;
case 48000:
val |= IEC958_AES3_CON_FS_48000;
break;
- case 32000:
- val |= IEC958_AES3_CON_FS_32000;
+ case 88200:
+ val |= IEC958_AES3_CON_FS_88200;
+ break;
+ case 96000:
+ val |= IEC958_AES3_CON_FS_96000;
+ break;
+ case 176400:
+ val |= IEC958_AES3_CON_FS_176400;
+ break;
+ case 192000:
+ val |= IEC958_AES3_CON_FS_192000;
break;
default:
dev_err(codec->dev, "unsupported sampling rate\n");
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = {
static int ak4104_spi_probe(struct spi_device *spi)
{
+ struct device_node *np = spi->dev.of_node;
struct ak4104_private *ak4104;
unsigned int val;
int ret;
@@ -201,52 +222,62 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ak4104 == NULL)
return -ENOMEM;
- ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+ ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
if (IS_ERR(ak4104->regmap)) {
ret = PTR_ERR(ak4104->regmap);
return ret;
}
+ if (np) {
+ enum of_gpio_flags flags;
+ int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
+
+ if (gpio_is_valid(gpio)) {
+ ret = devm_gpio_request_one(&spi->dev, gpio,
+ flags & OF_GPIO_ACTIVE_LOW ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+ "ak4104 reset");
+ if (ret < 0)
+ return ret;
+ }
+ }
+
/* read the 'reserved' register - according to the datasheet, it
* should contain 0x5b. Not a good way to verify the presence of
* the device, but there is no hardware ID register. */
ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
if (ret != 0)
- goto err;
- if (val != AK4104_RESERVED_VAL) {
- ret = -ENODEV;
- goto err;
- }
+ return ret;
+ if (val != AK4104_RESERVED_VAL)
+ return -ENODEV;
spi_set_drvdata(spi, ak4104);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_device_ak4104, &ak4104_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(ak4104->regmap);
return ret;
}
-static int __devexit ak4104_spi_remove(struct spi_device *spi)
+static int ak4104_spi_remove(struct spi_device *spi)
{
- struct ak4104_private *ak4101 = spi_get_drvdata(spi);
- regmap_exit(ak4101->regmap);
snd_soc_unregister_codec(&spi->dev);
return 0;
}
+static const struct of_device_id ak4104_of_match[] = {
+ { .compatible = "asahi-kasei,ak4104", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
static struct spi_driver ak4104_spi_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = ak4104_of_match,
},
.probe = ak4104_spi_probe,
- .remove = __devexit_p(ak4104_spi_remove),
+ .remove = ak4104_spi_remove,
};
module_spi_driver(ak4104_spi_driver);
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 618fdc30f73e..684fe910669f 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -436,8 +436,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
};
-static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4535_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ak4535_priv *ak4535;
int ret;
@@ -447,7 +447,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
if (ak4535 == NULL)
return -ENOMEM;
- ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+ ak4535->regmap = devm_regmap_init_i2c(i2c, &ak4535_regmap);
if (IS_ERR(ak4535->regmap)) {
ret = PTR_ERR(ak4535->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -458,18 +458,13 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ak4535, &ak4535_dai, 1);
- if (ret != 0)
- regmap_exit(ak4535->regmap);
return ret;
}
-static __devexit int ak4535_i2c_remove(struct i2c_client *client)
+static int ak4535_i2c_remove(struct i2c_client *client)
{
- struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(ak4535->regmap);
return 0;
}
@@ -485,7 +480,7 @@ static struct i2c_driver ak4535_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
- .remove = __devexit_p(ak4535_i2c_remove),
+ .remove = ak4535_i2c_remove,
.id_table = ak4535_i2c_id,
};
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 543a12f471be..5f9af1fb76e8 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -557,8 +557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
};
-static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4641_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ak4641_platform_data *pdata = i2c->dev.platform_data;
struct ak4641_priv *ak4641;
@@ -610,7 +610,7 @@ err_out:
return ret;
}
-static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
+static int ak4641_i2c_remove(struct i2c_client *i2c)
{
struct ak4641_platform_data *pdata = i2c->dev.platform_data;
@@ -640,7 +640,7 @@ static struct i2c_driver ak4641_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4641_i2c_probe,
- .remove = __devexit_p(ak4641_i2c_remove),
+ .remove = ak4641_i2c_remove,
.id_table = ak4641_i2c_id,
};
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index b3e24f289421..1f0cdab03294 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -194,12 +194,6 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
{"LINEOUT Mixer", "DACL", "DAC"},
};
-/* codec private data */
-struct ak4642_priv {
- unsigned int sysclk;
- enum snd_soc_control_type control_type;
-};
-
/*
* ak4642 register cache
*/
@@ -468,10 +462,9 @@ static int ak4642_resume(struct snd_soc_codec *codec)
static int ak4642_probe(struct snd_soc_codec *codec)
{
- struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -520,27 +513,15 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4642_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct ak4642_priv *ak4642;
- int ret;
-
- ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv),
- GFP_KERNEL);
- if (!ak4642)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, ak4642);
- ak4642->control_type = SND_SOC_I2C;
-
- ret = snd_soc_register_codec(&i2c->dev,
+ return snd_soc_register_codec(&i2c->dev,
(struct snd_soc_codec_driver *)id->driver_data,
&ak4642_dai, 1);
- return ret;
}
-static __devexit int ak4642_i2c_remove(struct i2c_client *client)
+static int ak4642_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -560,7 +541,7 @@ static struct i2c_driver ak4642_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4642_i2c_probe,
- .remove = __devexit_p(ak4642_i2c_remove),
+ .remove = ak4642_i2c_remove,
.id_table = ak4642_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 2b457976a7bf..25bdf6ad4a54 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -655,8 +655,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
};
-static int __devinit ak4671_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ak4671_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ak4671_priv *ak4671;
int ret;
@@ -674,7 +674,7 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int ak4671_i2c_remove(struct i2c_client *client)
+static int ak4671_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -692,7 +692,7 @@ static struct i2c_driver ak4671_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4671_i2c_probe,
- .remove = __devexit_p(ak4671_i2c_remove),
+ .remove = ak4671_i2c_remove,
.id_table = ak4671_i2c_id,
};
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 1960478ce6bb..256c364193a5 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -991,8 +991,8 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
* low = 0x1a
* high = 0x1b
*/
-static __devinit int alc5623_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int alc5623_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct alc5623_platform_data *pdata;
struct alc5623_priv *alc5623;
@@ -1058,7 +1058,7 @@ static __devinit int alc5623_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int alc5623_i2c_remove(struct i2c_client *client)
+static int alc5623_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1079,7 +1079,7 @@ static struct i2c_driver alc5623_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = alc5623_i2c_probe,
- .remove = __devexit_p(alc5623_i2c_remove),
+ .remove = alc5623_i2c_remove,
.id_table = alc5623_i2c_table,
};
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 7dd02420b36d..f2e62e45f912 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -1116,8 +1116,8 @@ static struct regmap_config alc5632_regmap = {
* low = 0x1a
* high = 0x1b
*/
-static __devinit int alc5632_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int alc5632_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct alc5632_priv *alc5632;
int ret, ret1, ret2;
@@ -1179,7 +1179,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int alc5632_i2c_remove(struct i2c_client *client)
+static int alc5632_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1198,7 +1198,7 @@ static struct i2c_driver alc5632_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = alc5632_i2c_probe,
- .remove = __devexit_p(alc5632_i2c_remove),
+ .remove = alc5632_i2c_remove,
.id_table = alc5632_i2c_table,
};
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 054967d8bac2..adf397b9d0e6 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
+static const char *arizona_vol_ramp_text[] = {
+ "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+ "15ms/6dB", "30ms/6dB",
+};
+
+const struct soc_enum arizona_in_vd_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
+
+const struct soc_enum arizona_in_vi_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
+
+const struct soc_enum arizona_out_vd_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
+
+const struct soc_enum arizona_out_vi_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
+
static const char *arizona_lhpf_mode_text[] = {
"Low-pass", "High-pass"
};
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
case 49152000:
val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
+ case 67737600:
+ case 73728000:
+ val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
+ case 90316800:
+ case 98304000:
+ val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
+ case 135475200:
+ case 147456000:
+ val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
default:
return -EINVAL;
}
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
return -EBUSY;
}
+ dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
+ arizona_dai_clk_str(clk_id));
+
memset(&routes, 0, sizeof(routes));
routes[0].sink = dai->driver->capture.stream_name;
routes[1].sink = dai->driver->playback.stream_name;
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
routes[1].source = arizona_dai_clk_str(clk_id);
snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
+ dai_priv->clk = clk_id;
+
return snd_soc_dapm_sync(&codec->dapm);
}
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
bool ena;
int ret;
+ if (fll->fref == Fref && fll->fout == Fout)
+ return 0;
+
ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
if (ret != 0) {
arizona_fll_err(fll, "Failed to read current state: %d\n",
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
if (ena)
pm_runtime_put_autosuspend(arizona->dev);
+ fll->fref = Fref;
+ fll->fout = Fout;
+
return 0;
}
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
ARIZONA_FLL1_SYNC_ENA);
ret = wait_for_completion_timeout(&fll->ok,
- msecs_to_jiffies(25));
+ msecs_to_jiffies(250));
if (ret == 0)
arizona_fll_warn(fll, "Timed out waiting for lock\n");
+ fll->fref = Fref;
+ fll->fout = Fout;
+
return 0;
}
EXPORT_SYMBOL_GPL(arizona_set_fll);
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 36ec64946120..41dae1ed3b71 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -17,6 +17,8 @@
#include <sound/soc.h>
+#include "wm_adsp.h"
+
#define ARIZONA_CLK_SYSCLK 1
#define ARIZONA_CLK_ASYNCCLK 2
#define ARIZONA_CLK_OPCLK 3
@@ -46,15 +48,18 @@
#define ARIZONA_MIXER_VOL_SHIFT 1
#define ARIZONA_MIXER_VOL_WIDTH 7
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI 4
+#define ARIZONA_MAX_ADSP 4
struct arizona;
+struct wm_adsp;
struct arizona_dai_priv {
int clk;
};
struct arizona_priv {
+ struct wm_adsp adsp[ARIZONA_MAX_ADSP];
struct arizona *arizona;
int sysclk;
int asyncclk;
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
const struct snd_kcontrol_new name##_mux = \
SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+#define ARIZONA_MUX_ENUMS(name, base_reg) \
+ static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg); \
+ static ARIZONA_MUX_CTL_DECL(name)
+
#define ARIZONA_MIXER_ENUMS(name, base_reg) \
- static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
- static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
- static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
- static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
- static ARIZONA_MUX_CTL_DECL(name##_in1); \
- static ARIZONA_MUX_CTL_DECL(name##_in2); \
- static ARIZONA_MUX_CTL_DECL(name##_in3); \
- static ARIZONA_MUX_CTL_DECL(name##_in4)
+ ARIZONA_MUX_ENUMS(name##_in1, base_reg); \
+ ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
+ ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
+ ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
+
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+ ARIZONA_MUX_ENUMS(name##_aux1, base_reg); \
+ ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8); \
+ ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16); \
+ ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24); \
+ ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32); \
+ ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define ARIZONA_MUX(name, ctrl) \
SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+#define ARIZONA_MUX_WIDGETS(name, name_str) \
+ ARIZONA_MUX(name_str " Input", &name##_mux)
+
#define ARIZONA_MIXER_WIDGETS(name, name_str) \
ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+ ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+ ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+ ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+ ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+ ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+ ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+ ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+ ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
+#define ARIZONA_MUX_ROUTES(name) \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Input")
+
#define ARIZONA_MIXER_ROUTES(widget, name) \
{ widget, NULL, name " Mixer" }, \
{ name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
+#define ARIZONA_DSP_ROUTES(name) \
+ { name, NULL, name " Aux 1" }, \
+ { name, NULL, name " Aux 2" }, \
+ { name, NULL, name " Aux 3" }, \
+ { name, NULL, name " Aux 4" }, \
+ { name, NULL, name " Aux 5" }, \
+ { name, NULL, name " Aux 6" }, \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+ ARIZONA_MIXER_ROUTES(name, name "L"), \
+ ARIZONA_MIXER_ROUTES(name, name "R")
+
+extern const struct soc_enum arizona_in_vi_ramp;
+extern const struct soc_enum arizona_in_vd_ramp;
+
+extern const struct soc_enum arizona_out_vi_ramp;
+extern const struct soc_enum arizona_out_vd_ramp;
+
extern const struct soc_enum arizona_lhpf1_mode;
extern const struct soc_enum arizona_lhpf2_mode;
extern const struct soc_enum arizona_lhpf3_mode;
@@ -146,6 +197,8 @@ struct arizona_fll {
unsigned int vco_mult;
struct completion lock;
struct completion ok;
+ unsigned int fref;
+ unsigned int fout;
char lock_name[ARIZONA_FLL_NAME_LEN];
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 064cd6a93516..23316c887b19 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -201,7 +201,7 @@ static struct platform_driver cq93vc_codec_driver = {
},
.probe = cq93vc_platform_probe,
- .remove = __devexit_p(cq93vc_platform_remove),
+ .remove = cq93vc_platform_remove,
};
module_platform_driver(cq93vc_codec_driver);
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index e3f0a7f3131e..4f1127935fdf 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec)
struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
int ret;
int gpio_nreset = -EINVAL;
+ int amutec_eq_bmutec = 0;
#ifdef CONFIG_OF
- if (of_match_device(cs4271_dt_ids, codec->dev))
+ if (of_match_device(cs4271_dt_ids, codec->dev)) {
gpio_nreset = of_get_named_gpio(codec->dev->of_node,
"reset-gpio", 0);
+
+ if (!of_get_property(codec->dev->of_node,
+ "cirrus,amutec-eq-bmutec", NULL))
+ amutec_eq_bmutec = 1;
+ }
#endif
- if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
- gpio_nreset = cs4271plat->gpio_nreset;
+ if (cs4271plat) {
+ if (gpio_is_valid(cs4271plat->gpio_nreset))
+ gpio_nreset = cs4271plat->gpio_nreset;
+
+ amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+ }
if (gpio_nreset >= 0)
if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
/* Power-up sequence requires 85 uS */
udelay(85);
+ if (amutec_eq_bmutec)
+ snd_soc_update_bits(codec, CS4271_MODE2,
+ CS4271_MODE2_MUTECAEQUB,
+ CS4271_MODE2_MUTECAEQUB);
+
return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
@@ -555,7 +570,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit cs4271_spi_probe(struct spi_device *spi)
+static int cs4271_spi_probe(struct spi_device *spi)
{
struct cs4271_private *cs4271;
@@ -570,7 +585,7 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
&cs4271_dai, 1);
}
-static int __devexit cs4271_spi_remove(struct spi_device *spi)
+static int cs4271_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -583,7 +598,7 @@ static struct spi_driver cs4271_spi_driver = {
.of_match_table = of_match_ptr(cs4271_dt_ids),
},
.probe = cs4271_spi_probe,
- .remove = __devexit_p(cs4271_spi_remove),
+ .remove = cs4271_spi_remove,
};
#endif /* defined(CONFIG_SPI_MASTER) */
@@ -594,8 +609,8 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
-static int __devinit cs4271_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int cs4271_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct cs4271_private *cs4271;
@@ -610,7 +625,7 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
&cs4271_dai, 1);
}
-static int __devexit cs4271_i2c_remove(struct i2c_client *client)
+static int cs4271_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -624,7 +639,7 @@ static struct i2c_driver cs4271_i2c_driver = {
},
.id_table = cs4271_i2c_id,
.probe = cs4271_i2c_probe,
- .remove = __devexit_p(cs4271_i2c_remove),
+ .remove = cs4271_i2c_remove,
};
#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 97a81051e88d..99bb1c69499e 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -1271,7 +1271,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
},
.id_table = cs42l52_id,
.probe = cs42l52_i2c_probe,
- .remove = __devexit_p(cs42l52_i2c_remove),
+ .remove = cs42l52_i2c_remove,
};
module_i2c_driver(cs42l52_i2c_driver);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 2c08c4cb465a..a0791ecf6d95 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1345,8 +1345,8 @@ static struct regmap_config cs42l73_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
+static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
{
struct cs42l73_private *cs42l73;
int ret;
@@ -1406,7 +1406,7 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
return 0;
}
-static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+static int cs42l73_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1426,7 +1426,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
},
.id_table = cs42l73_id,
.probe = cs42l73_i2c_probe,
- .remove = __devexit_p(cs42l73_i2c_remove),
+ .remove = cs42l73_i2c_remove,
};
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index af5db7080519..9c1231456502 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1218,8 +1218,8 @@ static const struct regmap_config da7210_regmap_config_i2c = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da7210_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da7210_priv *da7210;
int ret;
@@ -1231,7 +1231,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, da7210);
- da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
+ da7210->regmap = devm_regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
if (IS_ERR(da7210->regmap)) {
ret = PTR_ERR(da7210->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -1245,24 +1245,15 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- goto err_regmap;
- }
- return ret;
-
-err_regmap:
- regmap_exit(da7210->regmap);
return ret;
}
-static int __devexit da7210_i2c_remove(struct i2c_client *client)
+static int da7210_i2c_remove(struct i2c_client *client)
{
- struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(da7210->regmap);
return 0;
}
@@ -1279,7 +1270,7 @@ static struct i2c_driver da7210_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da7210_i2c_probe,
- .remove = __devexit_p(da7210_i2c_remove),
+ .remove = da7210_i2c_remove,
.id_table = da7210_i2c_id,
};
#endif
@@ -1323,7 +1314,7 @@ static const struct regmap_config da7210_regmap_config_spi = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da7210_spi_probe(struct spi_device *spi)
+static int da7210_spi_probe(struct spi_device *spi)
{
struct da7210_priv *da7210;
int ret;
@@ -1346,24 +1337,15 @@ static int __devinit da7210_spi_probe(struct spi_device *spi)
if (ret != 0)
dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
- ret = snd_soc_register_codec(&spi->dev,
+ ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
- if (ret < 0)
- goto err_regmap;
-
- return ret;
-
-err_regmap:
- regmap_exit(da7210->regmap);
return ret;
}
-static int __devexit da7210_spi_remove(struct spi_device *spi)
+static int da7210_spi_remove(struct spi_device *spi)
{
- struct da7210_priv *da7210 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(da7210->regmap);
return 0;
}
@@ -1373,7 +1355,7 @@ static struct spi_driver da7210_spi_driver = {
.owner = THIS_MODULE,
},
.probe = da7210_spi_probe,
- .remove = __devexit_p(da7210_spi_remove)
+ .remove = da7210_spi_remove
};
#endif
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index 01be2a320e21..dc0284dc9e6f 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1557,8 +1557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
.reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
};
-static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da732x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da732x_priv *da732x;
unsigned int reg;
@@ -1596,7 +1596,7 @@ err:
return ret;
}
-static __devexit int da732x_i2c_remove(struct i2c_client *client)
+static int da732x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1615,7 +1615,7 @@ static struct i2c_driver da732x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da732x_i2c_probe,
- .remove = __devexit_p(da732x_i2c_remove),
+ .remove = da732x_i2c_remove,
.id_table = da732x_i2c_id,
};
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index f379b085c392..fc9802d1281d 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -173,6 +173,7 @@
#define DA9055_AIF_FORMAT_I2S_MODE (0 << 0)
#define DA9055_AIF_FORMAT_LEFT_J (1 << 0)
#define DA9055_AIF_FORMAT_RIGHT_J (2 << 0)
+#define DA9055_AIF_FORMAT_DSP (3 << 0)
#define DA9055_AIF_WORD_S16_LE (0 << 2)
#define DA9055_AIF_WORD_S20_3LE (1 << 2)
#define DA9055_AIF_WORD_S24_LE (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
6, 1, 0),
};
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
/* DAPM widgets */
static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
/* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
&da9055_dapm_mixoutr_controls[0],
ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
+ /* Output Enable Switches */
+ SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_hp_l_control),
+ SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_hp_r_control),
+ SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_lineout_control),
+
/* Output PGAs */
SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
{"Out Mixer Right", "DAC Right Switch", "DAC Right"},
{"MIXOUT Left", NULL, "Out Mixer Left"},
- {"Headphone Left", NULL, "MIXOUT Left"},
+ {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+ {"Headphone Left", NULL, "Headphone Left Enable"},
{"Headphone Left", NULL, "Charge Pump"},
{"HPL", NULL, "Headphone Left"},
{"MIXOUT Right", NULL, "Out Mixer Right"},
- {"Headphone Right", NULL, "MIXOUT Right"},
+ {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+ {"Headphone Right", NULL, "Headphone Right Enable"},
{"Headphone Right", NULL, "Charge Pump"},
{"HPR", NULL, "Headphone Right"},
{"MIXOUT Right", NULL, "Out Mixer Right"},
- {"Lineout", NULL, "MIXOUT Right"},
+ {"Lineout Enable", "Switch", "MIXOUT Right"},
+ {"Lineout", NULL, "Lineout Enable"},
{"LINE", NULL, "Lineout"},
};
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
case SND_SOC_DAIFMT_RIGHT_J:
aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ aif_ctrl = DA9055_AIF_FORMAT_DSP;
+ break;
default:
return -EINVAL;
}
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
/*
- * There are two separate control bits for input and output mixers as
- * well as headphone and line outs.
+ * There are two separate control bits for input and output mixers.
* One to enable corresponding amplifier and other to enable its
* output. As amplifier bits are related to power control, they are
* being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
- snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
- DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
- snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
- DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
- snd_soc_update_bits(codec, DA9055_LINE_CTRL,
- DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
/* Set this as per your system configuration */
snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
@@ -1467,8 +1484,8 @@ static const struct regmap_config da9055_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da9055_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da9055_priv *da9055;
struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev);
@@ -1500,7 +1517,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit da9055_remove(struct i2c_client *client)
+static int da9055_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1519,7 +1536,7 @@ static struct i2c_driver da9055_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da9055_i2c_probe,
- .remove = __devexit_p(da9055_remove),
+ .remove = da9055_remove,
.id_table = da9055_i2c_id,
};
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
index bfe46aa90362..4f4f7f41a7d1 100644
--- a/sound/soc/codecs/dfbmcs320.c
+++ b/sound/soc/codecs/dfbmcs320.c
@@ -33,13 +33,13 @@ static struct snd_soc_dai_driver dfbmcs320_dai = {
static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
-static int __devinit dfbmcs320_probe(struct platform_device *pdev)
+static int dfbmcs320_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
&dfbmcs320_dai, 1);
}
-static int __devexit dfbmcs320_remove(struct platform_device *pdev)
+static int dfbmcs320_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
@@ -52,7 +52,7 @@ static struct platform_driver dfmcs320_driver = {
.owner = THIS_MODULE,
},
.probe = dfbmcs320_probe,
- .remove = __devexit_p(dfbmcs320_remove),
+ .remove = dfbmcs320_remove,
};
module_platform_driver(dfmcs320_driver);
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index 3e929f079a1f..66967ba6f757 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -66,13 +66,13 @@ static struct snd_soc_codec_driver soc_dmic = {
.probe = dmic_probe,
};
-static int __devinit dmic_dev_probe(struct platform_device *pdev)
+static int dmic_dev_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_dmic, &dmic_dai, 1);
}
-static int __devexit dmic_dev_remove(struct platform_device *pdev)
+static int dmic_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -86,7 +86,7 @@ static struct platform_driver dmic_driver = {
.owner = THIS_MODULE,
},
.probe = dmic_dev_probe,
- .remove = __devexit_p(dmic_dev_remove),
+ .remove = dmic_dev_remove,
};
module_platform_driver(dmic_driver);
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index 1bf55602c9eb..53b455b8c07a 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -1119,8 +1119,8 @@ static const struct regmap_config isabelle_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int isabelle_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct regmap *isabelle_regmap;
int ret = 0;
@@ -1145,7 +1145,7 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit isabelle_i2c_remove(struct i2c_client *client)
+static int isabelle_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1163,7 +1163,7 @@ static struct i2c_driver isabelle_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = isabelle_i2c_probe,
- .remove = __devexit_p(isabelle_i2c_remove),
+ .remove = isabelle_i2c_remove,
.id_table = isabelle_i2c_id,
};
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 85d9cabe6d55..d991529e1aff 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/regmap.h>
#include <linux/delay.h>
@@ -24,9 +25,10 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#define JZ4740_REG_CODEC_1 0x0
-#define JZ4740_REG_CODEC_2 0x1
+#define JZ4740_REG_CODEC_2 0x4
#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
@@ -67,43 +69,36 @@
#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4
#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0
-static const uint32_t jz4740_codec_regs[] = {
- 0x021b2302, 0x00170803,
+static const struct reg_default jz4740_codec_reg_defaults[] = {
+ { JZ4740_REG_CODEC_1, 0x021b2302 },
+ { JZ4740_REG_CODEC_2, 0x00170803 },
};
struct jz4740_codec {
- void __iomem *base;
- struct resource *mem;
+ struct regmap *regmap;
};
-static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
- return readl(jz4740_codec->base + (reg << 2));
-}
-
-static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int val)
-{
- struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
- u32 *cache = codec->reg_cache;
-
- cache[reg] = val;
- writel(val, jz4740_codec->base + (reg << 2));
+static const unsigned int jz4740_mic_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
+};
- return 0;
-}
+static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0);
+static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0);
static const struct snd_kcontrol_new jz4740_codec_controls[] = {
- SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
- SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
+ SOC_SINGLE_TLV("Master Playback Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0,
+ jz4740_out_tlv),
+ SOC_SINGLE_TLV("Master Capture Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0,
+ jz4740_in_tlv),
SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
- SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
+ SOC_SINGLE_TLV("Mic Capture Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0,
+ jz4740_mic_tlv),
};
static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
@@ -163,8 +158,8 @@ static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(dai->codec);
uint32_t val;
- struct snd_soc_codec *codec = dai->codec;
switch (params_rate(params)) {
case 8000:
@@ -200,7 +195,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
+ regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
return 0;
@@ -230,25 +225,23 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
.symmetric_rates = 1,
};
-static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
+static void jz4740_codec_wakeup(struct regmap *regmap)
{
- int i;
- uint32_t *cache = codec->reg_cache;
-
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
udelay(2);
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
- for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i)
- jz4740_codec_write(codec, i, cache[i]);
+ regcache_sync(regmap);
}
static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+ struct regmap *regmap = jz4740_codec->regmap;
unsigned int mask;
unsigned int value;
@@ -261,12 +254,12 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
value = 0;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_STANDBY:
/* The only way to clear the suspend flag is to reset the codec */
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
- jz4740_codec_wakeup(codec);
+ jz4740_codec_wakeup(regmap);
mask = JZ4740_CODEC_1_VREF_DISABLE |
JZ4740_CODEC_1_VREF_AMP_DISABLE |
@@ -275,13 +268,14 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
JZ4740_CODEC_1_VREF_AMP_DISABLE |
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_OFF:
mask = JZ4740_CODEC_1_SUSPEND;
value = JZ4740_CODEC_1_SUSPEND;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
+ regcache_mark_dirty(regmap);
break;
default:
break;
@@ -294,7 +288,9 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
{
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -331,12 +327,7 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume,
- .read = jz4740_codec_read,
- .write = jz4740_codec_write,
.set_bias_level = jz4740_codec_set_bias_level,
- .reg_cache_default = jz4740_codec_regs,
- .reg_word_size = sizeof(u32),
- .reg_cache_size = 2,
.controls = jz4740_codec_controls,
.num_controls = ARRAY_SIZE(jz4740_codec_controls),
@@ -346,11 +337,23 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes),
};
-static int __devinit jz4740_codec_probe(struct platform_device *pdev)
+static const struct regmap_config jz4740_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = JZ4740_REG_CODEC_2,
+
+ .reg_defaults = jz4740_codec_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(jz4740_codec_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int jz4740_codec_probe(struct platform_device *pdev)
{
int ret;
struct jz4740_codec *jz4740_codec;
struct resource *mem;
+ void __iomem *base;
jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
GFP_KERNEL);
@@ -358,56 +361,29 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
- ret = -ENOENT;
- goto err_out;
- }
-
- mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
- if (!mem) {
- dev_err(&pdev->dev, "Failed to request mmio memory region\n");
- ret = -EBUSY;
- goto err_out;
- }
+ base = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!base)
+ return -EBUSY;
- jz4740_codec->base = ioremap(mem->start, resource_size(mem));
- if (!jz4740_codec->base) {
- dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
- ret = -EBUSY;
- goto err_release_mem_region;
- }
- jz4740_codec->mem = mem;
+ jz4740_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &jz4740_codec_regmap_config);
+ if (IS_ERR(jz4740_codec->regmap))
+ return PTR_ERR(jz4740_codec->regmap);
platform_set_drvdata(pdev, jz4740_codec);
ret = snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "Failed to register codec\n");
- goto err_iounmap;
- }
- return 0;
-
-err_iounmap:
- iounmap(jz4740_codec->base);
-err_release_mem_region:
- release_mem_region(mem->start, resource_size(mem));
-err_out:
return ret;
}
-static int __devexit jz4740_codec_remove(struct platform_device *pdev)
+static int jz4740_codec_remove(struct platform_device *pdev)
{
- struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
- struct resource *mem = jz4740_codec->mem;
-
snd_soc_unregister_codec(&pdev->dev);
- iounmap(jz4740_codec->base);
- release_mem_region(mem->start, resource_size(mem));
-
platform_set_drvdata(pdev, NULL);
return 0;
@@ -415,7 +391,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
static struct platform_driver jz4740_codec_driver = {
.probe = jz4740_codec_probe,
- .remove = __devexit_p(jz4740_codec_remove),
+ .remove = jz4740_codec_remove,
.driver = {
.name = "jz4740-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 81a328c78838..9f9f59573f72 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -209,8 +209,8 @@ static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
.set_bias_level = lm4857_set_bias_level,
};
-static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int lm4857_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct lm4857 *lm4857;
int ret;
@@ -228,7 +228,7 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
+static int lm4857_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
@@ -246,7 +246,7 @@ static struct i2c_driver lm4857_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lm4857_i2c_probe,
- .remove = __devexit_p(lm4857_i2c_remove),
+ .remove = lm4857_i2c_remove,
.id_table = lm4857_i2c_id,
};
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 99b0a9dcff34..d75257d40a49 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1483,8 +1483,8 @@ static const struct regmap_config lm49453_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int lm49453_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct lm49453_priv *lm49453;
int ret = 0;
@@ -1497,7 +1497,7 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, lm49453);
- lm49453->regmap = regmap_init_i2c(i2c, &lm49453_regmap_config);
+ lm49453->regmap = devm_regmap_init_i2c(i2c, &lm49453_regmap_config);
if (IS_ERR(lm49453->regmap)) {
ret = PTR_ERR(lm49453->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1508,21 +1508,15 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_lm49453,
lm49453_dai, ARRAY_SIZE(lm49453_dai));
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- regmap_exit(lm49453->regmap);
- return ret;
- }
return ret;
}
-static int __devexit lm49453_i2c_remove(struct i2c_client *client)
+static int lm49453_i2c_remove(struct i2c_client *client)
{
- struct lm49453_priv *lm49453 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(lm49453->regmap);
return 0;
}
@@ -1538,7 +1532,7 @@ static struct i2c_driver lm49453_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lm49453_i2c_probe,
- .remove = __devexit_p(lm49453_i2c_remove),
+ .remove = lm49453_i2c_remove,
.id_table = lm49453_i2c_id,
};
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index 17b3ec2d05cb..a6ac2313047d 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -159,8 +159,8 @@ static const struct regmap_config max9768_i2c_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit max9768_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max9768_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct max9768 *max9768;
struct max9768_pdata *pdata = client->dev.platform_data;
@@ -187,7 +187,7 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, max9768);
- max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+ max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config);
if (IS_ERR(max9768->regmap)) {
err = PTR_ERR(max9768->regmap);
goto err_gpio_free;
@@ -195,12 +195,10 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
if (err)
- goto err_regmap_free;
+ goto err_gpio_free;
return 0;
- err_regmap_free:
- regmap_exit(max9768->regmap);
err_gpio_free:
if (gpio_is_valid(max9768->shdn_gpio))
gpio_free(max9768->shdn_gpio);
@@ -210,12 +208,11 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
return err;
}
-static int __devexit max9768_i2c_remove(struct i2c_client *client)
+static int max9768_i2c_remove(struct i2c_client *client)
{
struct max9768 *max9768 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(max9768->regmap);
if (gpio_is_valid(max9768->shdn_gpio))
gpio_free(max9768->shdn_gpio);
@@ -237,7 +234,7 @@ static struct i2c_driver max9768_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9768_i2c_probe,
- .remove = __devexit_p(max9768_i2c_remove),
+ .remove = max9768_i2c_remove,
.id_table = max9768_i2c_id,
};
module_i2c_driver(max9768_i2c_driver);
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 3264a5169306..a4c16fd70f77 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -2084,7 +2084,7 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit max98088_i2c_remove(struct i2c_client *client)
+static int max98088_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2098,13 +2098,13 @@ static const struct i2c_device_id max98088_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
static struct i2c_driver max98088_i2c_driver = {
- .driver = {
- .name = "max98088",
- .owner = THIS_MODULE,
- },
- .probe = max98088_i2c_probe,
- .remove = __devexit_p(max98088_i2c_remove),
- .id_table = max98088_i2c_id,
+ .driver = {
+ .name = "max98088",
+ .owner = THIS_MODULE,
+ },
+ .probe = max98088_i2c_probe,
+ .remove = max98088_i2c_remove,
+ .id_table = max98088_i2c_id,
};
module_i2c_driver(max98088_i2c_driver);
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
new file mode 100644
index 000000000000..c9772ca3da4f
--- /dev/null
+++ b/sound/soc/codecs/max98090.c
@@ -0,0 +1,577 @@
+/*
+ * max98090.c -- MAX98090 ALSA SoC Audio driver
+ * based on Rev0p8 datasheet
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on
+ *
+ * max98095.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * https://github.com/hardkernel/linux/commit/\
+ * 3417d7166b17113b3b33b0a337c74d1c7cc313df#sound/soc/codecs/max98090.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * 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/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+/*
+ *
+ * MAX98090 Registers Definition
+ *
+ */
+
+/* RESET / STATUS / INTERRUPT REGISTERS */
+#define MAX98090_0x00_SW_RESET 0x00
+#define MAX98090_0x01_INT_STS 0x01
+#define MAX98090_0x02_JACK_STS 0x02
+#define MAX98090_0x03_INT_MASK 0x03
+
+/* QUICK SETUP REGISTERS */
+#define MAX98090_0x04_SYS_CLK 0x04
+#define MAX98090_0x05_SAMPLE_RATE 0x05
+#define MAX98090_0x06_DAI_IF 0x06
+#define MAX98090_0x07_DAC_PATH 0x07
+#define MAX98090_0x08_MIC_TO_ADC 0x08
+#define MAX98090_0x09_LINE_TO_ADC 0x09
+#define MAX98090_0x0A_ANALOG_MIC_LOOP 0x0A
+#define MAX98090_0x0B_ANALOG_LINE_LOOP 0x0B
+
+/* ANALOG INPUT CONFIGURATION REGISTERS */
+#define MAX98090_0x0D_INPUT_CONFIG 0x0D
+#define MAX98090_0x0E_LINE_IN_LVL 0x0E
+#define MAX98090_0x0F_LINI_IN_CFG 0x0F
+#define MAX98090_0x10_MIC1_IN_LVL 0x10
+#define MAX98090_0x11_MIC2_IN_LVL 0x11
+
+/* MICROPHONE CONFIGURATION REGISTERS */
+#define MAX98090_0x12_MIC_BIAS_VOL 0x12
+#define MAX98090_0x13_DIGITAL_MIC_CFG 0x13
+#define MAX98090_0x14_DIGITAL_MIC_MODE 0x14
+
+/* ADC PATH AND CONFIGURATION REGISTERS */
+#define MAX98090_0x15_L_ADC_MIX 0x15
+#define MAX98090_0x16_R_ADC_MIX 0x16
+#define MAX98090_0x17_L_ADC_LVL 0x17
+#define MAX98090_0x18_R_ADC_LVL 0x18
+#define MAX98090_0x19_ADC_BIQUAD_LVL 0x19
+#define MAX98090_0x1A_ADC_SIDETONE 0x1A
+
+/* CLOCK CONFIGURATION REGISTERS */
+#define MAX98090_0x1B_SYS_CLK 0x1B
+#define MAX98090_0x1C_CLK_MODE 0x1C
+#define MAX98090_0x1D_ANY_CLK1 0x1D
+#define MAX98090_0x1E_ANY_CLK2 0x1E
+#define MAX98090_0x1F_ANY_CLK3 0x1F
+#define MAX98090_0x20_ANY_CLK4 0x20
+#define MAX98090_0x21_MASTER_MODE 0x21
+
+/* INTERFACE CONTROL REGISTERS */
+#define MAX98090_0x22_DAI_IF_FMT 0x22
+#define MAX98090_0x23_DAI_TDM_FMT1 0x23
+#define MAX98090_0x24_DAI_TDM_FMT2 0x24
+#define MAX98090_0x25_DAI_IO_CFG 0x25
+#define MAX98090_0x26_FILTER_CFG 0x26
+#define MAX98090_0x27_DAI_PLAYBACK_LVL 0x27
+#define MAX98090_0x28_EQ_PLAYBACK_LVL 0x28
+
+/* HEADPHONE CONTROL REGISTERS */
+#define MAX98090_0x29_L_HP_MIX 0x29
+#define MAX98090_0x2A_R_HP_MIX 0x2A
+#define MAX98090_0x2B_HP_CTR 0x2B
+#define MAX98090_0x2C_L_HP_VOL 0x2C
+#define MAX98090_0x2D_R_HP_VOL 0x2D
+
+/* SPEAKER CONFIGURATION REGISTERS */
+#define MAX98090_0x2E_L_SPK_MIX 0x2E
+#define MAX98090_0x2F_R_SPK_MIX 0x2F
+#define MAX98090_0x30_SPK_CTR 0x30
+#define MAX98090_0x31_L_SPK_VOL 0x31
+#define MAX98090_0x32_R_SPK_VOL 0x32
+
+/* ALC CONFIGURATION REGISTERS */
+#define MAX98090_0x33_ALC_TIMING 0x33
+#define MAX98090_0x34_ALC_COMPRESSOR 0x34
+#define MAX98090_0x35_ALC_EXPANDER 0x35
+#define MAX98090_0x36_ALC_GAIN 0x36
+
+/* RECEIVER AND LINE_OUTPUT REGISTERS */
+#define MAX98090_0x37_RCV_LOUT_L_MIX 0x37
+#define MAX98090_0x38_RCV_LOUT_L_CNTL 0x38
+#define MAX98090_0x39_RCV_LOUT_L_VOL 0x39
+#define MAX98090_0x3A_LOUT_R_MIX 0x3A
+#define MAX98090_0x3B_LOUT_R_CNTL 0x3B
+#define MAX98090_0x3C_LOUT_R_VOL 0x3C
+
+/* JACK DETECT AND ENABLE REGISTERS */
+#define MAX98090_0x3D_JACK_DETECT 0x3D
+#define MAX98090_0x3E_IN_ENABLE 0x3E
+#define MAX98090_0x3F_OUT_ENABLE 0x3F
+#define MAX98090_0x40_LVL_CTR 0x40
+#define MAX98090_0x41_DSP_FILTER_ENABLE 0x41
+
+/* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+#define MAX98090_0x42_BIAS_CTR 0x42
+#define MAX98090_0x43_DAC_CTR 0x43
+#define MAX98090_0x44_ADC_CTR 0x44
+#define MAX98090_0x45_DEV_SHUTDOWN 0x45
+
+/* REVISION ID REGISTER */
+#define MAX98090_0xFF_REV_ID 0xFF
+
+#define MAX98090_REG_MAX_CACHED 0x45
+#define MAX98090_REG_END 0xFF
+
+/*
+ *
+ * MAX98090 Registers Bit Fields
+ *
+ */
+
+/* MAX98090_0x06_DAI_IF */
+#define MAX98090_DAI_IF_MASK 0x3F
+#define MAX98090_RJ_M (1 << 5)
+#define MAX98090_RJ_S (1 << 4)
+#define MAX98090_LJ_M (1 << 3)
+#define MAX98090_LJ_S (1 << 2)
+#define MAX98090_I2S_M (1 << 1)
+#define MAX98090_I2S_S (1 << 0)
+
+/* MAX98090_0x45_DEV_SHUTDOWN */
+#define MAX98090_SHDNRUN (1 << 7)
+
+/* codec private data */
+struct max98090_priv {
+ struct regmap *regmap;
+};
+
+static const struct reg_default max98090_reg_defaults[] = {
+ /* RESET / STATUS / INTERRUPT REGISTERS */
+ {MAX98090_0x00_SW_RESET, 0x00},
+ {MAX98090_0x01_INT_STS, 0x00},
+ {MAX98090_0x02_JACK_STS, 0x00},
+ {MAX98090_0x03_INT_MASK, 0x04},
+
+ /* QUICK SETUP REGISTERS */
+ {MAX98090_0x04_SYS_CLK, 0x00},
+ {MAX98090_0x05_SAMPLE_RATE, 0x00},
+ {MAX98090_0x06_DAI_IF, 0x00},
+ {MAX98090_0x07_DAC_PATH, 0x00},
+ {MAX98090_0x08_MIC_TO_ADC, 0x00},
+ {MAX98090_0x09_LINE_TO_ADC, 0x00},
+ {MAX98090_0x0A_ANALOG_MIC_LOOP, 0x00},
+ {MAX98090_0x0B_ANALOG_LINE_LOOP, 0x00},
+
+ /* ANALOG INPUT CONFIGURATION REGISTERS */
+ {MAX98090_0x0D_INPUT_CONFIG, 0x00},
+ {MAX98090_0x0E_LINE_IN_LVL, 0x1B},
+ {MAX98090_0x0F_LINI_IN_CFG, 0x00},
+ {MAX98090_0x10_MIC1_IN_LVL, 0x11},
+ {MAX98090_0x11_MIC2_IN_LVL, 0x11},
+
+ /* MICROPHONE CONFIGURATION REGISTERS */
+ {MAX98090_0x12_MIC_BIAS_VOL, 0x00},
+ {MAX98090_0x13_DIGITAL_MIC_CFG, 0x00},
+ {MAX98090_0x14_DIGITAL_MIC_MODE, 0x00},
+
+ /* ADC PATH AND CONFIGURATION REGISTERS */
+ {MAX98090_0x15_L_ADC_MIX, 0x00},
+ {MAX98090_0x16_R_ADC_MIX, 0x00},
+ {MAX98090_0x17_L_ADC_LVL, 0x03},
+ {MAX98090_0x18_R_ADC_LVL, 0x03},
+ {MAX98090_0x19_ADC_BIQUAD_LVL, 0x00},
+ {MAX98090_0x1A_ADC_SIDETONE, 0x00},
+
+ /* CLOCK CONFIGURATION REGISTERS */
+ {MAX98090_0x1B_SYS_CLK, 0x00},
+ {MAX98090_0x1C_CLK_MODE, 0x00},
+ {MAX98090_0x1D_ANY_CLK1, 0x00},
+ {MAX98090_0x1E_ANY_CLK2, 0x00},
+ {MAX98090_0x1F_ANY_CLK3, 0x00},
+ {MAX98090_0x20_ANY_CLK4, 0x00},
+ {MAX98090_0x21_MASTER_MODE, 0x00},
+
+ /* INTERFACE CONTROL REGISTERS */
+ {MAX98090_0x22_DAI_IF_FMT, 0x00},
+ {MAX98090_0x23_DAI_TDM_FMT1, 0x00},
+ {MAX98090_0x24_DAI_TDM_FMT2, 0x00},
+ {MAX98090_0x25_DAI_IO_CFG, 0x00},
+ {MAX98090_0x26_FILTER_CFG, 0x80},
+ {MAX98090_0x27_DAI_PLAYBACK_LVL, 0x00},
+ {MAX98090_0x28_EQ_PLAYBACK_LVL, 0x00},
+
+ /* HEADPHONE CONTROL REGISTERS */
+ {MAX98090_0x29_L_HP_MIX, 0x00},
+ {MAX98090_0x2A_R_HP_MIX, 0x00},
+ {MAX98090_0x2B_HP_CTR, 0x00},
+ {MAX98090_0x2C_L_HP_VOL, 0x1A},
+ {MAX98090_0x2D_R_HP_VOL, 0x1A},
+
+ /* SPEAKER CONFIGURATION REGISTERS */
+ {MAX98090_0x2E_L_SPK_MIX, 0x00},
+ {MAX98090_0x2F_R_SPK_MIX, 0x00},
+ {MAX98090_0x30_SPK_CTR, 0x00},
+ {MAX98090_0x31_L_SPK_VOL, 0x2C},
+ {MAX98090_0x32_R_SPK_VOL, 0x2C},
+
+ /* ALC CONFIGURATION REGISTERS */
+ {MAX98090_0x33_ALC_TIMING, 0x00},
+ {MAX98090_0x34_ALC_COMPRESSOR, 0x00},
+ {MAX98090_0x35_ALC_EXPANDER, 0x00},
+ {MAX98090_0x36_ALC_GAIN, 0x00},
+
+ /* RECEIVER AND LINE_OUTPUT REGISTERS */
+ {MAX98090_0x37_RCV_LOUT_L_MIX, 0x00},
+ {MAX98090_0x38_RCV_LOUT_L_CNTL, 0x00},
+ {MAX98090_0x39_RCV_LOUT_L_VOL, 0x15},
+ {MAX98090_0x3A_LOUT_R_MIX, 0x00},
+ {MAX98090_0x3B_LOUT_R_CNTL, 0x00},
+ {MAX98090_0x3C_LOUT_R_VOL, 0x15},
+
+ /* JACK DETECT AND ENABLE REGISTERS */
+ {MAX98090_0x3D_JACK_DETECT, 0x00},
+ {MAX98090_0x3E_IN_ENABLE, 0x00},
+ {MAX98090_0x3F_OUT_ENABLE, 0x00},
+ {MAX98090_0x40_LVL_CTR, 0x00},
+ {MAX98090_0x41_DSP_FILTER_ENABLE, 0x00},
+
+ /* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+ {MAX98090_0x42_BIAS_CTR, 0x00},
+ {MAX98090_0x43_DAC_CTR, 0x00},
+ {MAX98090_0x44_ADC_CTR, 0x06},
+ {MAX98090_0x45_DEV_SHUTDOWN, 0x00},
+};
+
+static const unsigned int max98090_hp_tlv[] = {
+ TLV_DB_RANGE_HEAD(5),
+ 0x0, 0x6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
+ 0x7, 0xE, TLV_DB_SCALE_ITEM(-4000, 300, 0),
+ 0xF, 0x15, TLV_DB_SCALE_ITEM(-1700, 200, 0),
+ 0x16, 0x1B, TLV_DB_SCALE_ITEM(-400, 100, 0),
+ 0x1C, 0x1F, TLV_DB_SCALE_ITEM(150, 50, 0),
+};
+
+static struct snd_kcontrol_new max98090_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Headphone Volume", MAX98090_0x2C_L_HP_VOL,
+ MAX98090_0x2D_R_HP_VOL, 0, 31, 0, max98090_hp_tlv),
+};
+
+/* Left HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_left_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x29_L_HP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x29_L_HP_MIX, 0, 1, 0),
+};
+
+/* Right HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_right_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x2A_R_HP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x2A_R_HP_MIX, 0, 1, 0),
+};
+
+static struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
+ /* Output */
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+
+ /* PGA */
+ SND_SOC_DAPM_PGA("HPL Out", MAX98090_0x3F_OUT_ENABLE, 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPR Out", MAX98090_0x3F_OUT_ENABLE, 6, 0, NULL, 0),
+
+ /* Mixer */
+ SND_SOC_DAPM_MIXER("HPL Mixer", SND_SOC_NOPM, 0, 0,
+ max98090_left_hp_mixer_controls,
+ ARRAY_SIZE(max98090_left_hp_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("HPR Mixer", SND_SOC_NOPM, 0, 0,
+ max98090_right_hp_mixer_controls,
+ ARRAY_SIZE(max98090_right_hp_mixer_controls)),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("DACL", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 0, 0),
+ SND_SOC_DAPM_DAC("DACR", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 1, 0),
+};
+
+static struct snd_soc_dapm_route max98090_audio_map[] = {
+ /* Output */
+ {"HPL", NULL, "HPL Out"},
+ {"HPR", NULL, "HPR Out"},
+
+ /* PGA */
+ {"HPL Out", NULL, "HPL Mixer"},
+ {"HPR Out", NULL, "HPR Mixer"},
+
+ /* Mixer*/
+ {"HPL Mixer", "DACR Switch", "DACR"},
+ {"HPL Mixer", "DACL Switch", "DACL"},
+
+ {"HPR Mixer", "DACR Switch", "DACR"},
+ {"HPR Mixer", "DACL Switch", "DACL"},
+};
+
+static bool max98090_volatile(struct device *dev, unsigned int reg)
+{
+ if ((reg == MAX98090_0x01_INT_STS) ||
+ (reg == MAX98090_0x02_JACK_STS) ||
+ (reg > MAX98090_REG_MAX_CACHED))
+ return true;
+
+ return false;
+}
+
+static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val;
+
+ switch (params_rate(params)) {
+ case 96000:
+ val = 1 << 5;
+ break;
+ case 32000:
+ val = 1 << 4;
+ break;
+ case 48000:
+ val = 1 << 3;
+ break;
+ case 44100:
+ val = 1 << 2;
+ break;
+ case 16000:
+ val = 1 << 1;
+ break;
+ case 8000:
+ val = 1 << 0;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported rate\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x05_SAMPLE_RATE, 0x03F, val);
+
+ return 0;
+}
+
+static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val;
+
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, 0);
+
+ switch (freq) {
+ case 26000000:
+ val = 1 << 7;
+ break;
+ case 19200000:
+ val = 1 << 6;
+ break;
+ case 13000000:
+ val = 1 << 5;
+ break;
+ case 12288000:
+ val = 1 << 4;
+ break;
+ case 12000000:
+ val = 1 << 3;
+ break;
+ case 11289600:
+ val = 1 << 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid master clock frequency\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x04_SYS_CLK, 0xFD, val);
+
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+ dev_dbg(dai->dev, "sysclk is %uHz\n", freq);
+
+ return 0;
+}
+
+static int max98090_dai_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int is_master;
+ u8 val;
+
+ /* master/slave mode */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ is_master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ is_master = 0;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported clock\n");
+ return -EINVAL;
+ }
+
+ /* format */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ val = (is_master) ? MAX98090_I2S_M : MAX98090_I2S_S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val = (is_master) ? MAX98090_RJ_M : MAX98090_RJ_S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ val = (is_master) ? MAX98090_LJ_M : MAX98090_LJ_S;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported format\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x06_DAI_IF,
+ MAX98090_DAI_IF_MASK, val);
+
+ return 0;
+}
+
+#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
+#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max98090_dai_ops = {
+ .set_sysclk = max98090_dai_set_sysclk,
+ .set_fmt = max98090_dai_set_fmt,
+ .hw_params = max98090_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver max98090_dai = {
+ .name = "max98090-Hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98090_RATES,
+ .formats = MAX98090_FORMATS,
+ },
+ .ops = &max98090_dai_ops,
+};
+
+static int max98090_probe(struct snd_soc_codec *codec)
+{
+ struct max98090_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct device *dev = codec->dev;
+ int ret;
+
+ codec->control_data = priv->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* Device active */
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+ return 0;
+}
+
+static int max98090_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98090 = {
+ .probe = max98090_probe,
+ .remove = max98090_remove,
+ .controls = max98090_snd_controls,
+ .num_controls = ARRAY_SIZE(max98090_snd_controls),
+ .dapm_widgets = max98090_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(max98090_dapm_widgets),
+ .dapm_routes = max98090_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(max98090_audio_map),
+};
+
+static const struct regmap_config max98090_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX98090_REG_END,
+ .volatile_reg = max98090_volatile,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = max98090_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(max98090_reg_defaults),
+};
+
+static int max98090_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct max98090_priv *priv;
+ struct device *dev = &i2c->dev;
+ unsigned int val;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(struct max98090_priv),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
+ if (IS_ERR(priv->regmap)) {
+ ret = PTR_ERR(priv->regmap);
+ dev_err(dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, priv);
+
+ ret = regmap_read(priv->regmap, MAX98090_0xFF_REV_ID, &val);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read device revision: %d\n", ret);
+ return ret;
+ }
+ dev_info(dev, "revision 0x%02x\n", val);
+
+ ret = snd_soc_register_codec(dev,
+ &soc_codec_dev_max98090,
+ &max98090_dai, 1);
+
+ return ret;
+}
+
+static int max98090_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id max98090_i2c_id[] = {
+ { "max98090", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
+
+static struct i2c_driver max98090_i2c_driver = {
+ .driver = {
+ .name = "max98090",
+ .owner = THIS_MODULE,
+ },
+ .probe = max98090_i2c_probe,
+ .remove = max98090_i2c_remove,
+ .id_table = max98090_i2c_id,
+};
+module_i2c_driver(max98090_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98090 driver");
+MODULE_AUTHOR("Peter Hsiang, Kuninori Morimoto");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 38d43c59d3f4..41cdd1642970 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2511,7 +2511,7 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit max98095_i2c_remove(struct i2c_client *client)
+static int max98095_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2529,7 +2529,7 @@ static struct i2c_driver max98095_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max98095_i2c_probe,
- .remove = __devexit_p(max98095_i2c_remove),
+ .remove = max98095_i2c_remove,
.id_table = max98095_i2c_id,
};
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index efe535c37b39..58c38a5b481c 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -329,8 +329,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes),
};
-static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int max9850_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct max9850_priv *max9850;
int ret;
@@ -347,7 +347,7 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int max9850_i2c_remove(struct i2c_client *client)
+static int max9850_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -365,7 +365,7 @@ static struct i2c_driver max9850_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9850_i2c_probe,
- .remove = __devexit_p(max9850_i2c_remove),
+ .remove = max9850_i2c_remove,
.id_table = max9850_i2c_id,
};
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index d15e5943c85e..6b6c74cd83e2 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -258,8 +258,8 @@ int max9877_add_controls(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(max9877_add_controls);
-static int __devinit max9877_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max9877_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
i2c = client;
@@ -268,7 +268,7 @@ static int __devinit max9877_i2c_probe(struct i2c_client *client,
return 0;
}
-static __devexit int max9877_i2c_remove(struct i2c_client *client)
+static int max9877_i2c_remove(struct i2c_client *client)
{
i2c = NULL;
@@ -287,7 +287,7 @@ static struct i2c_driver max9877_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9877_i2c_probe,
- .remove = __devexit_p(max9877_i2c_remove),
+ .remove = max9877_i2c_remove,
.id_table = max9877_i2c_id,
};
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index bc955999c8aa..5402dfbbb716 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -779,7 +779,7 @@ static struct platform_driver mc13783_codec_driver = {
.owner = THIS_MODULE,
},
.probe = mc13783_codec_probe,
- .remove = __devexit_p(mc13783_codec_remove),
+ .remove = mc13783_codec_remove,
};
module_platform_driver(mc13783_codec_driver);
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 96aa5fa05160..26118828782b 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -626,8 +626,8 @@ static const struct regmap_config ml26124_i2c_regmap = {
.write_flag_mask = 0x01,
};
-static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ml26124_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ml26124_priv *priv;
int ret;
@@ -649,7 +649,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
&soc_codec_dev_ml26124, &ml26124_dai, 1);
}
-static __devexit int ml26124_i2c_remove(struct i2c_client *client)
+static int ml26124_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -667,7 +667,7 @@ static struct i2c_driver ml26124_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ml26124_i2c_probe,
- .remove = __devexit_p(ml26124_i2c_remove),
+ .remove = ml26124_i2c_remove,
.id_table = ml26124_i2c_id,
};
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/omap-hdmi.c
index 1bf5c74f5f96..529d06444c54 100644
--- a/sound/soc/codecs/omap-hdmi.c
+++ b/sound/soc/codecs/omap-hdmi.c
@@ -39,13 +39,13 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
},
};
-static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
+static int omap_hdmi_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
&omap_hdmi_codec_dai, 1);
}
-static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
+static int omap_hdmi_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -58,7 +58,7 @@ static struct platform_driver omap_hdmi_codec_driver = {
},
.probe = omap_hdmi_codec_probe,
- .remove = __devexit_p(omap_hdmi_codec_remove),
+ .remove = omap_hdmi_codec_remove,
};
module_platform_driver(omap_hdmi_codec_driver);
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index edcaa7ea5487..f2a6282b41f4 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -149,13 +149,13 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
.resume = pcm3008_soc_resume,
};
-static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
+static int pcm3008_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
}
-static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
+static int pcm3008_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -165,7 +165,7 @@ MODULE_ALIAS("platform:pcm3008-codec");
static struct platform_driver pcm3008_codec_driver = {
.probe = pcm3008_codec_probe,
- .remove = __devexit_p(pcm3008_codec_remove),
+ .remove = pcm3008_codec_remove,
.driver = {
.name = "pcm3008-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 960d0e93cce9..912c9cbc2724 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1382,7 +1382,7 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
timesofbclk);
if (coeff < 0) {
dev_err(codec->dev, "Fail to get coeff\n");
- return -EINVAL;
+ return coeff;
}
switch (params_format(params)) {
@@ -1748,7 +1748,7 @@ static int rt5631_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+static int rt5631_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1760,7 +1760,7 @@ static struct i2c_driver rt5631_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = rt5631_i2c_probe,
- .remove = __devexit_p(rt5631_i2c_remove),
+ .remove = rt5631_i2c_remove,
.id_table = rt5631_i2c_id,
};
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index df2f99d1d428..cb1675cd8e1c 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1404,8 +1404,8 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
.num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
};
-static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sgtl5000_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct sgtl5000_priv *sgtl5000;
int ret;
@@ -1422,7 +1422,7 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
+static int sgtl5000_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1449,7 +1449,7 @@ static struct i2c_driver sgtl5000_i2c_driver = {
.of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
- .remove = __devexit_p(sgtl5000_i2c_remove),
+ .remove = sgtl5000_i2c_remove,
.id_table = sgtl5000_id,
};
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644
index 000000000000..f2d61a187830
--- /dev/null
+++ b/sound/soc/codecs/si476x.c
@@ -0,0 +1,255 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include <linux/i2c.h>
+
+#include <linux/mfd/si476x-core.h>
+
+enum si476x_audio_registers {
+ SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
+ SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+ SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11,
+ SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+ (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b1111110)
+
+enum si476x_daudio_formats {
+ SI476X_DAUDIO_MODE_I2S = (0x0 << 1),
+ SI476X_DAUDIO_MODE_DSP_A = (0x6 << 1),
+ SI476X_DAUDIO_MODE_DSP_B = (0x7 << 1),
+ SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1),
+ SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1),
+
+ SI476X_DAUDIO_MODE_IB = (1 << 5),
+ SI476X_DAUDIO_MODE_IF = (1 << 6),
+};
+
+enum si476x_pcm_format {
+ SI476X_PCM_FORMAT_S8 = 2,
+ SI476X_PCM_FORMAT_S16_LE = 4,
+ SI476X_PCM_FORMAT_S20_3LE = 5,
+ SI476X_PCM_FORMAT_S24_LE = 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_get_property(core, reg);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int val)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_set_property(core, reg, val);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ int err;
+ u16 format = 0;
+
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+ return -EINVAL;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ format |= SI476X_DAUDIO_MODE_DSP_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ format |= SI476X_DAUDIO_MODE_DSP_B;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ format |= SI476X_DAUDIO_MODE_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ format |= SI476X_DAUDIO_MODE_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format |= SI476X_DAUDIO_MODE_LEFT_J;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ format |= SI476X_DAUDIO_MODE_IB;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ format |= SI476X_DAUDIO_MODE_IB |
+ SI476X_DAUDIO_MODE_IF;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ format |= SI476X_DAUDIO_MODE_IB;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ format |= SI476X_DAUDIO_MODE_IF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+ SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
+ format);
+ if (err < 0) {
+ dev_err(codec_dai->codec->dev, "Failed to set output format\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int rate, width, err;
+
+ rate = params_rate(params);
+ if (rate < 32000 || rate > 48000) {
+ dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate);
+ return -EINVAL;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ width = SI476X_PCM_FORMAT_S8;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ width = SI476X_PCM_FORMAT_S16_LE;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ width = SI476X_PCM_FORMAT_S20_3LE;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ width = SI476X_PCM_FORMAT_S24_LE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
+ rate);
+ if (err < 0) {
+ dev_err(dai->codec->dev, "Failed to set sample rate\n");
+ return err;
+ }
+
+ err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+ SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
+ (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) |
+ (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
+ if (err < 0) {
+ dev_err(dai->codec->dev, "Failed to set output width\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int si476x_codec_probe(struct snd_soc_codec *codec)
+{
+ codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+ return 0;
+}
+
+static struct snd_soc_dai_ops si476x_dai_ops = {
+ .hw_params = si476x_codec_hw_params,
+ .set_fmt = si476x_codec_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver si476x_dai = {
+ .name = "si476x-codec",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE
+ },
+ .ops = &si476x_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+ .probe = si476x_codec_probe,
+ .read = si476x_codec_read,
+ .write = si476x_codec_write,
+};
+
+static int si476x_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+ &si476x_dai, 1);
+}
+
+static int si476x_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+MODULE_ALIAS("platform:si476x-codec");
+
+static struct platform_driver si476x_platform_driver = {
+ .driver = {
+ .name = "si476x-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = si476x_platform_probe,
+ .remove = si476x_platform_remove,
+};
+module_platform_driver(si476x_platform_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 50dbdb9357ea..d1ae869d3181 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -896,14 +896,14 @@ struct snd_soc_codec_driver sn95031_codec = {
.num_dapm_routes = ARRAY_SIZE(sn95031_audio_map),
};
-static int __devinit sn95031_device_probe(struct platform_device *pdev)
+static int sn95031_device_probe(struct platform_device *pdev)
{
pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
sn95031_dais, ARRAY_SIZE(sn95031_dais));
}
-static int __devexit sn95031_device_remove(struct platform_device *pdev)
+static int sn95031_device_remove(struct platform_device *pdev)
{
pr_debug("codec device remove called\n");
snd_soc_unregister_codec(&pdev->dev);
@@ -916,7 +916,7 @@ static struct platform_driver sn95031_codec_driver = {
.owner = THIS_MODULE,
},
.probe = sn95031_device_probe,
- .remove = __devexit_p(sn95031_device_remove),
+ .remove = sn95031_device_remove,
};
module_platform_driver(sn95031_codec_driver);
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 079066fef425..f8d30e5f6371 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -691,7 +691,7 @@ static const struct regmap_config ssm2602_regmap_config = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit ssm2602_spi_probe(struct spi_device *spi)
+static int ssm2602_spi_probe(struct spi_device *spi)
{
struct ssm2602_priv *ssm2602;
int ret;
@@ -713,7 +713,7 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit ssm2602_spi_remove(struct spi_device *spi)
+static int ssm2602_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -725,7 +725,7 @@ static struct spi_driver ssm2602_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ssm2602_spi_probe,
- .remove = __devexit_p(ssm2602_spi_remove),
+ .remove = ssm2602_spi_remove,
};
#endif
@@ -736,7 +736,7 @@ static struct spi_driver ssm2602_spi_driver = {
* low = 0x1a
* high = 0x1b
*/
-static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
+static int ssm2602_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct ssm2602_priv *ssm2602;
@@ -759,7 +759,7 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
+static int ssm2602_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -780,7 +780,7 @@ static struct i2c_driver ssm2602_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ssm2602_i2c_probe,
- .remove = __devexit_p(ssm2602_i2c_remove),
+ .remove = ssm2602_i2c_remove,
.id_table = ssm2602_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 0935bfe62471..cfb55fe35e98 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -995,8 +995,8 @@ static const struct regmap_config sta32x_regmap = {
.volatile_reg = sta32x_reg_is_volatile,
};
-static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int sta32x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct sta32x_priv *sta32x;
int ret, i;
@@ -1033,7 +1033,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int sta32x_i2c_remove(struct i2c_client *client)
+static int sta32x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1053,7 +1053,7 @@ static struct i2c_driver sta32x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = sta32x_i2c_probe,
- .remove = __devexit_p(sta32x_i2c_remove),
+ .remove = sta32x_i2c_remove,
.id_table = sta32x_i2c_id,
};
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index 9e3144862386..ab355c4f0b2d 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -380,8 +380,8 @@ static const struct regmap_config sta529_regmap = {
.num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
};
-static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int sta529_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct sta529 *sta529;
int ret;
@@ -412,7 +412,7 @@ static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit sta529_i2c_remove(struct i2c_client *client)
+static int sta529_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -431,7 +431,7 @@ static struct i2c_driver sta529_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = sta529_i2c_probe,
- .remove = __devexit_p(sta529_i2c_remove),
+ .remove = sta529_i2c_remove,
.id_table = sta529_i2c_id,
};
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 982e437799a8..2eda85ba79ac 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -385,13 +385,13 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
.reg_cache_default = stac9766_reg,
};
-static __devinit int stac9766_probe(struct platform_device *pdev)
+static int stac9766_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
}
-static int __devexit stac9766_remove(struct platform_device *pdev)
+static int stac9766_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -404,7 +404,7 @@ static struct platform_driver stac9766_codec_driver = {
},
.probe = stac9766_probe,
- .remove = __devexit_p(stac9766_remove),
+ .remove = stac9766_remove,
};
module_platform_driver(stac9766_codec_driver);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index f230292ba96b..17df4e32feac 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/slab.h>
@@ -65,6 +66,7 @@ struct aic32x4_priv {
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
+ int rstn_gpio;
};
/* 0dB min, 1dB steps */
@@ -627,10 +629,20 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
{
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u32 tmp_reg;
+ int ret;
codec->hw_write = (hw_write_t) i2c_master_send;
codec->control_data = aic32x4->control_data;
+ if (aic32x4->rstn_gpio >= 0) {
+ ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
+ GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+ if (ret != 0)
+ return ret;
+ ndelay(10);
+ gpio_set_value(aic32x4->rstn_gpio, 1);
+ }
+
snd_soc_write(codec, AIC32X4_RESET, 0x01);
/* Power platform configuration */
@@ -675,6 +687,16 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(aic32x4_snd_controls));
aic32x4_add_widgets(codec);
+ /*
+ * Workaround: for an unknown reason, the ADC needs to be powered up
+ * and down for the first capture to work properly. It seems related to
+ * a HW BUG or some kind of behavior not documented in the datasheet.
+ */
+ tmp_reg = snd_soc_read(codec, AIC32X4_ADCSETUP);
+ snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg |
+ AIC32X4_LADC_EN | AIC32X4_RADC_EN);
+ snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg);
+
return 0;
}
@@ -694,8 +716,8 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
.set_bias_level = aic32x4_set_bias_level,
};
-static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int aic32x4_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct aic32x4_pdata *pdata = i2c->dev.platform_data;
struct aic32x4_priv *aic32x4;
@@ -713,10 +735,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
aic32x4->power_cfg = pdata->power_cfg;
aic32x4->swapdacs = pdata->swapdacs;
aic32x4->micpga_routing = pdata->micpga_routing;
+ aic32x4->rstn_gpio = pdata->rstn_gpio;
} else {
aic32x4->power_cfg = 0;
aic32x4->swapdacs = false;
aic32x4->micpga_routing = 0;
+ aic32x4->rstn_gpio = -1;
}
ret = snd_soc_register_codec(&i2c->dev,
@@ -724,7 +748,7 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
+static int aic32x4_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -742,7 +766,7 @@ static struct i2c_driver aic32x4_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = aic32x4_i2c_probe,
- .remove = __devexit_p(aic32x4_i2c_remove),
+ .remove = aic32x4_i2c_remove,
.id_table = aic32x4_i2c_id,
};
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h
index aae2b2440398..35774223fd91 100644
--- a/sound/soc/codecs/tlv320aic32x4.h
+++ b/sound/soc/codecs/tlv320aic32x4.h
@@ -94,6 +94,9 @@
#define AIC32X4_WORD_LEN_24BITS 0x02
#define AIC32X4_WORD_LEN_32BITS 0x03
+#define AIC32X4_LADC_EN (1 << 7)
+#define AIC32X4_RADC_EN (1 << 6)
+
#define AIC32X4_I2S_MODE 0x00
#define AIC32X4_DSP_MODE 0x01
#define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index d2e16c5d7d1f..782b0cded2e6 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1514,8 +1514,8 @@ static struct snd_soc_dai_driver dac33_dai = {
.ops = &dac33_dai_ops,
};
-static int __devinit dac33_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int dac33_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tlv320dac33_platform_data *pdata;
struct tlv320dac33_priv *dac33;
@@ -1586,7 +1586,7 @@ err_gpio:
return ret;
}
-static int __devexit dac33_i2c_remove(struct i2c_client *client)
+static int dac33_i2c_remove(struct i2c_client *client)
{
struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
@@ -1617,7 +1617,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = dac33_i2c_probe,
- .remove = __devexit_p(dac33_i2c_remove),
+ .remove = dac33_i2c_remove,
.id_table = tlv320dac33_i2c_id,
};
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 565ff39ad3a3..8d75aa152c8c 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -359,8 +359,8 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
-static int __devinit tpa6130a2_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int tpa6130a2_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct device *dev;
struct tpa6130a2_data *data;
@@ -455,7 +455,7 @@ err_gpio:
return ret;
}
-static int __devexit tpa6130a2_remove(struct i2c_client *client)
+static int tpa6130a2_remove(struct i2c_client *client)
{
struct tpa6130a2_data *data = i2c_get_clientdata(client);
@@ -483,7 +483,7 @@ static struct i2c_driver tpa6130a2_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = tpa6130a2_probe,
- .remove = __devexit_p(tpa6130a2_remove),
+ .remove = tpa6130a2_remove,
.id_table = tpa6130a2_id,
};
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index e7f608996c41..63b280b06035 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2334,13 +2334,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.num_dapm_routes = ARRAY_SIZE(intercon),
};
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
+static int twl4030_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
twl4030_dai, ARRAY_SIZE(twl4030_dai));
}
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
+static int twl4030_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -2350,7 +2350,7 @@ MODULE_ALIAS("platform:twl4030-codec");
static struct platform_driver twl4030_codec_driver = {
.probe = twl4030_codec_probe,
- .remove = __devexit_p(twl4030_codec_remove),
+ .remove = twl4030_codec_remove,
.driver = {
.name = "twl4030-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 00b85cc1b9a3..3fc3fc64dd8b 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1229,13 +1229,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.num_dapm_routes = ARRAY_SIZE(intercon),
};
-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+static int twl6040_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
twl6040_dai, ARRAY_SIZE(twl6040_dai));
}
-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+static int twl6040_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1247,7 +1247,7 @@ static struct platform_driver twl6040_codec_driver = {
.owner = THIS_MODULE,
},
.probe = twl6040_codec_probe,
- .remove = __devexit_p(twl6040_codec_remove),
+ .remove = twl6040_codec_remove,
};
module_platform_driver(twl6040_codec_driver);
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 6c3d43b8ee85..6d0aa44c3757 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -601,13 +601,13 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.set_bias_level = uda134x_set_bias_level,
};
-static int __devinit uda134x_codec_probe(struct platform_device *pdev)
+static int uda134x_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_uda134x, &uda134x_dai, 1);
}
-static int __devexit uda134x_codec_remove(struct platform_device *pdev)
+static int uda134x_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -619,7 +619,7 @@ static struct platform_driver uda134x_codec_driver = {
.owner = THIS_MODULE,
},
.probe = uda134x_codec_probe,
- .remove = __devexit_p(uda134x_codec_remove),
+ .remove = uda134x_codec_remove,
};
module_platform_driver(uda134x_codec_driver);
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 2502214b84ab..fd0a314bc209 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -795,8 +795,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int uda1380_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct uda1380_priv *uda1380;
int ret;
@@ -814,7 +814,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
+static int uda1380_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
@@ -832,7 +832,7 @@ static struct i2c_driver uda1380_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = uda1380_i2c_probe,
- .remove = __devexit_p(uda1380_i2c_remove),
+ .remove = uda1380_i2c_remove,
.id_table = uda1380_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 7b24d6d192e1..54cd3da09abd 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -485,13 +485,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
.remove = wl1273_remove,
};
-static int __devinit wl1273_platform_probe(struct platform_device *pdev)
+static int wl1273_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
&wl1273_dai, 1);
}
-static int __devexit wl1273_platform_remove(struct platform_device *pdev)
+static int wl1273_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -505,7 +505,7 @@ static struct platform_driver wl1273_platform_driver = {
.owner = THIS_MODULE,
},
.probe = wl1273_platform_probe,
- .remove = __devexit_p(wl1273_platform_remove),
+ .remove = wl1273_platform_remove,
};
module_platform_driver(wl1273_platform_driver);
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 99afc003a084..ad2fee4bb4cd 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -31,6 +31,9 @@
#define DEVICE_ID_WM0010 10
+/* We only support v1 of the .dfw INFO record */
+#define INFO_VERSION 1
+
enum dfw_cmd {
DFW_CMD_FUSE = 0x01,
DFW_CMD_CODE_HDR,
@@ -46,6 +49,13 @@ struct dfw_binrec {
uint8_t data[0];
} __packed;
+struct dfw_inforec {
+ u8 info_version;
+ u8 tool_major_version;
+ u8 tool_minor_version;
+ u8 dsp_target;
+};
+
struct dfw_pllrec {
u8 command;
u32 length:24;
@@ -97,7 +107,6 @@ struct wm0010_priv {
enum wm0010_state state;
bool boot_failed;
- int boot_done;
bool ready;
bool pll_running;
int max_spi_freq;
@@ -234,7 +243,7 @@ static void wm0010_boot_xfer_complete(void *data)
break;
case 0x55555555:
- if (wm0010->boot_done == 0)
+ if (wm0010->state < WM0010_STAGE2)
break;
dev_err(codec->dev,
"%d: ROM bootloader running in stage 2\n", i);
@@ -321,7 +330,6 @@ static void wm0010_boot_xfer_complete(void *data)
break;
}
- wm0010->boot_done++;
if (xfer->done)
complete(xfer->done);
}
@@ -334,94 +342,198 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
}
-static int wm0010_boot(struct snd_soc_codec *codec)
+static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
{
struct spi_device *spi = to_spi_device(codec->dev);
struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
- unsigned long flags;
struct list_head xfer_list;
struct wm0010_boot_xfer *xfer;
int ret;
struct completion done;
const struct firmware *fw;
const struct dfw_binrec *rec;
- struct spi_message m;
- struct spi_transfer t;
- struct dfw_pllrec pll_rec;
- u32 *img, *p;
- u64 *img_swap;
- u8 *out;
+ const struct dfw_inforec *inforec;
+ u64 *img;
+ u8 *out, dsp;
u32 len, offset;
- int i;
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- if (wm0010->state != WM0010_POWER_OFF)
- dev_warn(wm0010->dev, "DSP already powered up!\n");
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+ INIT_LIST_HEAD(&xfer_list);
- if (wm0010->sysclk > 26000000) {
- dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
- ret = -ECANCELED;
- goto err;
+ ret = request_firmware(&fw, name, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request application: %d\n",
+ ret);
+ return ret;
}
- INIT_LIST_HEAD(&xfer_list);
+ rec = (const struct dfw_binrec *)fw->data;
+ inforec = (const struct dfw_inforec *)rec->data;
+ offset = 0;
+ dsp = inforec->dsp_target;
+ wm0010->boot_failed = false;
+ BUG_ON(!list_empty(&xfer_list));
+ init_completion(&done);
- mutex_lock(&wm0010->lock);
- wm0010->pll_running = false;
+ /* First record should be INFO */
+ if (rec->command != DFW_CMD_INFO) {
+ dev_err(codec->dev, "First record not INFO\r\n");
+ ret = -EINVAL;
+ goto abort;
+ }
- dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+ if (inforec->info_version != INFO_VERSION) {
+ dev_err(codec->dev,
+ "Unsupported version (%02d) of INFO record\r\n",
+ inforec->info_version);
+ ret = -EINVAL;
+ goto abort;
+ }
- ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
- wm0010->core_supplies);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
- ret);
- mutex_unlock(&wm0010->lock);
- goto err;
+ dev_dbg(codec->dev, "Version v%02d INFO record found\r\n",
+ inforec->info_version);
+
+ /* Check it's a DSP file */
+ if (dsp != DEVICE_ID_WM0010) {
+ dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+ ret = -EINVAL;
+ goto abort;
}
- ret = regulator_enable(wm0010->dbvdd);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
- goto err_core;
+ /* Skip the info record as we don't need to send it */
+ offset += ((rec->length) + 8);
+ rec = (void *)&rec->data[rec->length];
+
+ while (offset < fw->size) {
+ dev_dbg(codec->dev,
+ "Packet: command %d, data length = 0x%x\r\n",
+ rec->command, rec->length);
+ len = rec->length + 8;
+
+ out = kzalloc(len, GFP_KERNEL);
+ if (!out) {
+ dev_err(codec->dev,
+ "Failed to allocate RX buffer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ img = kzalloc(len, GFP_KERNEL);
+ if (!img) {
+ dev_err(codec->dev,
+ "Failed to allocate image buffer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ byte_swap_64((u64 *)&rec->command, img, len);
+
+ xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
+ if (!xfer) {
+ dev_err(codec->dev, "Failed to allocate xfer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ xfer->codec = codec;
+ list_add_tail(&xfer->list, &xfer_list);
+
+ spi_message_init(&xfer->m);
+ xfer->m.complete = wm0010_boot_xfer_complete;
+ xfer->m.context = xfer;
+ xfer->t.tx_buf = img;
+ xfer->t.rx_buf = out;
+ xfer->t.len = len;
+ xfer->t.bits_per_word = 8;
+
+ if (!wm0010->pll_running) {
+ xfer->t.speed_hz = wm0010->sysclk / 6;
+ } else {
+ xfer->t.speed_hz = wm0010->max_spi_freq;
+
+ if (wm0010->board_max_spi_speed &&
+ (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
+ xfer->t.speed_hz = wm0010->board_max_spi_speed;
+ }
+
+ /* Store max usable spi frequency for later use */
+ wm0010->max_spi_freq = xfer->t.speed_hz;
+
+ spi_message_add_tail(&xfer->t, &xfer->m);
+
+ offset += ((rec->length) + 8);
+ rec = (void *)&rec->data[rec->length];
+
+ if (offset >= fw->size) {
+ dev_dbg(codec->dev, "All transfers scheduled\n");
+ xfer->done = &done;
+ }
+
+ ret = spi_async(spi, &xfer->m);
+ if (ret != 0) {
+ dev_err(codec->dev, "Write failed: %d\n", ret);
+ goto abort1;
+ }
+
+ if (wm0010->boot_failed) {
+ dev_dbg(codec->dev, "Boot fail!\n");
+ ret = -EINVAL;
+ goto abort1;
+ }
}
- /* Release reset */
- gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- wm0010->state = WM0010_OUT_OF_RESET;
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+ wait_for_completion(&done);
+
+ ret = 0;
+
+abort1:
+ while (!list_empty(&xfer_list)) {
+ xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
+ list);
+ kfree(xfer->t.rx_buf);
+ kfree(xfer->t.tx_buf);
+ list_del(&xfer->list);
+ kfree(xfer);
+ }
+
+abort:
+ release_firmware(fw);
+ return ret;
+}
+
+static int wm0010_stage2_load(struct snd_soc_codec *codec)
+{
+ struct spi_device *spi = to_spi_device(codec->dev);
+ struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+ const struct firmware *fw;
+ struct spi_message m;
+ struct spi_transfer t;
+ u32 *img;
+ u8 *out;
+ int i;
+ int ret = 0;
- /* First the bootloader */
ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
if (ret != 0) {
dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
ret);
- goto abort;
+ return ret;
}
- if (!wait_for_completion_timeout(&wm0010->boot_completion,
- msecs_to_jiffies(10)))
- dev_err(codec->dev, "Failed to get interrupt from DSP\n");
-
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- wm0010->state = WM0010_BOOTROM;
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
-
dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
/* Copy to local buffer first as vmalloc causes problems for dma */
img = kzalloc(fw->size, GFP_KERNEL);
if (!img) {
dev_err(codec->dev, "Failed to allocate image buffer\n");
- goto abort;
+ ret = -ENOMEM;
+ goto abort2;
}
out = kzalloc(fw->size, GFP_KERNEL);
if (!out) {
dev_err(codec->dev, "Failed to allocate output buffer\n");
- goto abort;
+ ret = -ENOMEM;
+ goto abort1;
}
memcpy(img, &fw->data[0], fw->size);
@@ -447,20 +559,97 @@ static int wm0010_boot(struct snd_soc_codec *codec)
/* Look for errors from the boot ROM */
for (i = 0; i < fw->size; i++) {
if (out[i] != 0x55) {
- ret = -EBUSY;
dev_err(codec->dev, "Boot ROM error: %x in %d\n",
out[i], i);
wm0010_mark_boot_failure(wm0010);
+ ret = -EBUSY;
goto abort;
}
}
-
- release_firmware(fw);
- kfree(img);
+abort:
kfree(out);
+abort1:
+ kfree(img);
+abort2:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int wm0010_boot(struct snd_soc_codec *codec)
+{
+ struct spi_device *spi = to_spi_device(codec->dev);
+ struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+ unsigned long flags;
+ int ret;
+ const struct firmware *fw;
+ struct spi_message m;
+ struct spi_transfer t;
+ struct dfw_pllrec pll_rec;
+ u32 *p, len;
+ u64 *img_swap;
+ u8 *out;
+ int i;
+
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ if (wm0010->state != WM0010_POWER_OFF)
+ dev_warn(wm0010->dev, "DSP already powered up!\n");
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ if (wm0010->sysclk > 26000000) {
+ dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
+ ret = -ECANCELED;
+ goto err;
+ }
+
+ mutex_lock(&wm0010->lock);
+ wm0010->pll_running = false;
+
+ dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
+ wm0010->core_supplies);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ mutex_unlock(&wm0010->lock);
+ goto err;
+ }
+
+ ret = regulator_enable(wm0010->dbvdd);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
+ goto err_core;
+ }
+
+ /* Release reset */
+ gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ wm0010->state = WM0010_OUT_OF_RESET;
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ /* First the bootloader */
+ ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
+ ret);
+ goto abort;
+ }
+
+ if (!wait_for_completion_timeout(&wm0010->boot_completion,
+ msecs_to_jiffies(20)))
+ dev_err(codec->dev, "Failed to get interrupt from DSP\n");
+
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ wm0010->state = WM0010_BOOTROM;
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ ret = wm0010_stage2_load(codec);
+ if (ret)
+ goto abort;
if (!wait_for_completion_timeout(&wm0010->boot_completion,
- msecs_to_jiffies(10)))
+ msecs_to_jiffies(20)))
dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n");
spin_lock_irqsave(&wm0010->irq_lock, flags);
@@ -535,110 +724,10 @@ static int wm0010_boot(struct snd_soc_codec *codec)
} else
dev_dbg(codec->dev, "Not enabling DSP PLL.");
- ret = request_firmware(&fw, "wm0010.dfw", codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request application: %d\n",
- ret);
- goto abort;
- }
-
- rec = (const struct dfw_binrec *)fw->data;
- offset = 0;
- wm0010->boot_done = 0;
- wm0010->boot_failed = false;
- BUG_ON(!list_empty(&xfer_list));
- init_completion(&done);
+ ret = wm0010_firmware_load("wm0010.dfw", codec);
- /* First record should be INFO */
- if (rec->command != DFW_CMD_INFO) {
- dev_err(codec->dev, "First record not INFO\r\n");
- goto abort;
- }
-
- /* Check it's a 0010 file */
- if (rec->data[0] != DEVICE_ID_WM0010) {
- dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+ if (ret != 0)
goto abort;
- }
-
- /* Skip the info record as we don't need to send it */
- offset += ((rec->length) + 8);
- rec = (void *)&rec->data[rec->length];
-
- while (offset < fw->size) {
- dev_dbg(codec->dev,
- "Packet: command %d, data length = 0x%x\r\n",
- rec->command, rec->length);
- len = rec->length + 8;
-
- out = kzalloc(len, GFP_KERNEL);
- if (!out) {
- dev_err(codec->dev,
- "Failed to allocate RX buffer\n");
- goto abort;
- }
-
- img_swap = kzalloc(len, GFP_KERNEL);
- if (!img_swap) {
- dev_err(codec->dev,
- "Failed to allocate image buffer\n");
- goto abort;
- }
-
- /* We need to re-order for 0010 */
- byte_swap_64((u64 *)&rec->command, img_swap, len);
-
- xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
- if (!xfer) {
- dev_err(codec->dev, "Failed to allocate xfer\n");
- goto abort;
- }
-
- xfer->codec = codec;
- list_add_tail(&xfer->list, &xfer_list);
-
- spi_message_init(&xfer->m);
- xfer->m.complete = wm0010_boot_xfer_complete;
- xfer->m.context = xfer;
- xfer->t.tx_buf = img_swap;
- xfer->t.rx_buf = out;
- xfer->t.len = len;
- xfer->t.bits_per_word = 8;
-
- if (!wm0010->pll_running) {
- xfer->t.speed_hz = wm0010->sysclk / 6;
- } else {
- xfer->t.speed_hz = wm0010->max_spi_freq;
-
- if (wm0010->board_max_spi_speed &&
- (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
- xfer->t.speed_hz = wm0010->board_max_spi_speed;
- }
-
- /* Store max usable spi frequency for later use */
- wm0010->max_spi_freq = xfer->t.speed_hz;
-
- spi_message_add_tail(&xfer->t, &xfer->m);
-
- offset += ((rec->length) + 8);
- rec = (void *)&rec->data[rec->length];
-
- if (offset >= fw->size) {
- dev_dbg(codec->dev, "All transfers scheduled\n");
- xfer->done = &done;
- }
-
- ret = spi_async(spi, &xfer->m);
- if (ret != 0) {
- dev_err(codec->dev, "Write failed: %d\n", ret);
- goto abort;
- }
-
- if (wm0010->boot_failed)
- goto abort;
- }
-
- wait_for_completion(&done);
spin_lock_irqsave(&wm0010->irq_lock, flags);
wm0010->state = WM0010_FIRMWARE;
@@ -646,17 +735,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
mutex_unlock(&wm0010->lock);
- release_firmware(fw);
-
- while (!list_empty(&xfer_list)) {
- xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
- list);
- kfree(xfer->t.rx_buf);
- kfree(xfer->t.tx_buf);
- list_del(&xfer->list);
- kfree(xfer);
- }
-
return 0;
abort:
@@ -784,7 +862,6 @@ static irqreturn_t wm0010_irq(int irq, void *data)
struct wm0010_priv *wm0010 = data;
switch (wm0010->state) {
- case WM0010_POWER_OFF:
case WM0010_OUT_OF_RESET:
case WM0010_BOOTROM:
case WM0010_STAGE2:
@@ -808,7 +885,7 @@ static int wm0010_probe(struct snd_soc_codec *codec)
return 0;
}
-static int __devinit wm0010_spi_probe(struct spi_device *spi)
+static int wm0010_spi_probe(struct spi_device *spi)
{
unsigned long gpio_flags;
int ret;
@@ -908,7 +985,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
return 0;
}
-static int __devexit wm0010_spi_remove(struct spi_device *spi)
+static int wm0010_spi_remove(struct spi_device *spi)
{
struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
@@ -930,7 +1007,7 @@ static struct spi_driver wm0010_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm0010_spi_probe,
- .remove = __devexit_p(wm0010_spi_remove),
+ .remove = wm0010_spi_remove,
};
module_spi_driver(wm0010_spi_driver);
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 951d7b49476a..6e6b93d4696e 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -153,7 +153,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
.idle_bias_off = true,
};
-static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+static int wm1250_ev1_pdata(struct i2c_client *i2c)
{
struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm1250_priv *wm1250;
@@ -199,8 +199,8 @@ static void wm1250_ev1_free(struct i2c_client *i2c)
gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
}
-static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+static int wm1250_ev1_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
{
int id, board, rev, ret;
@@ -237,7 +237,7 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
return 0;
}
-static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
+static int wm1250_ev1_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
wm1250_ev1_free(i2c);
@@ -257,7 +257,7 @@ static struct i2c_driver wm1250_ev1_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm1250_ev1_probe,
- .remove = __devexit_p(wm1250_ev1_remove),
+ .remove = wm1250_ev1_remove,
.id_table = wm1250_ev1_i2c_id,
};
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 683dc43b1d87..1cbe88f01d63 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -646,7 +646,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = w->codec;
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -764,8 +764,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
.num_controls = ARRAY_SIZE(wm2000_controls),
};
-static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+static int wm2000_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
{
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
@@ -871,7 +871,7 @@ out:
return ret;
}
-static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
+static int wm2000_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
@@ -890,7 +890,7 @@ static struct i2c_driver wm2000_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm2000_i2c_probe,
- .remove = __devexit_p(wm2000_i2c_remove),
+ .remove = wm2000_i2c_remove,
.id_table = wm2000_i2c_id,
};
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index eab64a193989..afcf31df77e0 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/firmware.h>
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
@@ -32,6 +33,40 @@
#include <sound/wm2200.h>
#include "wm2200.h"
+#include "wmfw.h"
+#include "wm_adsp.h"
+
+#define WM2200_DSP_CONTROL_1 0x00
+#define WM2200_DSP_CONTROL_2 0x02
+#define WM2200_DSP_CONTROL_3 0x03
+#define WM2200_DSP_CONTROL_4 0x04
+#define WM2200_DSP_CONTROL_5 0x06
+#define WM2200_DSP_CONTROL_6 0x07
+#define WM2200_DSP_CONTROL_7 0x08
+#define WM2200_DSP_CONTROL_8 0x09
+#define WM2200_DSP_CONTROL_9 0x0A
+#define WM2200_DSP_CONTROL_10 0x0B
+#define WM2200_DSP_CONTROL_11 0x0C
+#define WM2200_DSP_CONTROL_12 0x0D
+#define WM2200_DSP_CONTROL_13 0x0F
+#define WM2200_DSP_CONTROL_14 0x10
+#define WM2200_DSP_CONTROL_15 0x11
+#define WM2200_DSP_CONTROL_16 0x12
+#define WM2200_DSP_CONTROL_17 0x13
+#define WM2200_DSP_CONTROL_18 0x14
+#define WM2200_DSP_CONTROL_19 0x16
+#define WM2200_DSP_CONTROL_20 0x17
+#define WM2200_DSP_CONTROL_21 0x18
+#define WM2200_DSP_CONTROL_22 0x1A
+#define WM2200_DSP_CONTROL_23 0x1B
+#define WM2200_DSP_CONTROL_24 0x1C
+#define WM2200_DSP_CONTROL_25 0x1E
+#define WM2200_DSP_CONTROL_26 0x20
+#define WM2200_DSP_CONTROL_27 0x21
+#define WM2200_DSP_CONTROL_28 0x22
+#define WM2200_DSP_CONTROL_29 0x23
+#define WM2200_DSP_CONTROL_30 0x24
+#define WM2200_DSP_CONTROL_31 0x26
/* The code assumes DCVDD is generated internally */
#define WM2200_NUM_CORE_SUPPLIES 2
@@ -49,6 +84,7 @@ struct wm2200_fll {
/* codec private data */
struct wm2200_priv {
+ struct wm_adsp dsp[2];
struct regmap *regmap;
struct device *dev;
struct snd_soc_codec *codec;
@@ -64,6 +100,72 @@ struct wm2200_priv {
int sysclk;
};
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+ { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE,
+ .range_max = WM2200_DSP1_DM_BASE + 12287,
+ .selector_reg = WM2200_DSP1_CONTROL_3,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+ .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+ { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE,
+ .range_max = WM2200_DSP1_PM_BASE + 12287,
+ .selector_reg = WM2200_DSP1_CONTROL_2,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+ .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+ { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE,
+ .range_max = WM2200_DSP1_ZM_BASE + 2047,
+ .selector_reg = WM2200_DSP1_CONTROL_4,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+ .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+ { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE,
+ .range_max = WM2200_DSP2_DM_BASE + 4095,
+ .selector_reg = WM2200_DSP2_CONTROL_3,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+ .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+ { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE,
+ .range_max = WM2200_DSP2_PM_BASE + 11287,
+ .selector_reg = WM2200_DSP2_CONTROL_2,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+ .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+ { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE,
+ .range_max = WM2200_DSP2_ZM_BASE + 2047,
+ .selector_reg = WM2200_DSP2_CONTROL_4,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+ .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
+static const struct wm_adsp_region wm2200_dsp1_regions[] = {
+ { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE },
+ { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE },
+ { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE },
+};
+
+static const struct wm_adsp_region wm2200_dsp2_regions[] = {
+ { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE },
+ { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE },
+ { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE },
+};
+
static struct reg_default wm2200_reg_defaults[] = {
{ 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
{ 0x0102, 0x0000 }, /* R258 - Clocking 3 */
@@ -407,6 +509,16 @@ static struct reg_default wm2200_reg_defaults[] = {
static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+ if ((reg >= wm2200_ranges[i].window_start &&
+ reg <= wm2200_ranges[i].window_start +
+ wm2200_ranges[i].window_len) ||
+ (reg >= wm2200_ranges[i].range_min &&
+ reg <= wm2200_ranges[i].range_max))
+ return true;
+
switch (reg) {
case WM2200_SOFTWARE_RESET:
case WM2200_DEVICE_REVISION:
@@ -423,6 +535,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
static bool wm2200_readable_register(struct device *dev, unsigned int reg)
{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+ if ((reg >= wm2200_ranges[i].window_start &&
+ reg <= wm2200_ranges[i].window_start +
+ wm2200_ranges[i].window_len) ||
+ (reg >= wm2200_ranges[i].range_min &&
+ reg <= wm2200_ranges[i].range_max))
+ return true;
+
switch (reg) {
case WM2200_SOFTWARE_RESET:
case WM2200_DEVICE_REVISION:
@@ -880,7 +1002,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
static const char *wm2200_mixer_texts[] = {
"None",
"Tone Generator",
- "AEC loopback",
+ "AEC Loopback",
"IN1L",
"IN1R",
"IN2L",
@@ -976,6 +1098,20 @@ static int wm2200_mixer_values[] = {
static WM2200_MUX_CTL_DECL(name##_in3); \
static WM2200_MUX_CTL_DECL(name##_in4)
+#define WM2200_DSP_ENUMS(name, base_reg) \
+ static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg); \
+ static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+ static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+ static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+ static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+ static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+ static WM2200_MUX_CTL_DECL(name##_aux1); \
+ static WM2200_MUX_CTL_DECL(name##_aux2); \
+ static WM2200_MUX_CTL_DECL(name##_aux3); \
+ static WM2200_MUX_CTL_DECL(name##_aux4); \
+ static WM2200_MUX_CTL_DECL(name##_aux5); \
+ static WM2200_MUX_CTL_DECL(name##_aux6);
+
static const struct snd_kcontrol_new wm2200_snd_controls[] = {
SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1187,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
@@ -1064,8 +1203,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+#define WM2200_DSP_WIDGETS(name, name_str) \
+ WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+ WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+ WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+ WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+ WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+ WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+ WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+ WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
#define WM2200_MIXER_INPUT_ROUTES(name) \
{ name, "Tone Generator", "Tone Generator" }, \
+ { name, "AEC Loopback", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
{ name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1256,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+#define WM2200_DSP_AUX_ROUTES(name) \
+ { name, NULL, name " Aux 1" }, \
+ { name, NULL, name " Aux 2" }, \
+ { name, NULL, name " Aux 3" }, \
+ { name, NULL, name " Aux 4" }, \
+ { name, NULL, name " Aux 5" }, \
+ { name, NULL, name " Aux 6" }, \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+ "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+ SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+ WM2200_AEC_LOOPBACK_SRC_SHIFT,
+ ARRAY_SIZE(wm2200_aec_loopback_texts),
+ wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+ SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
NULL, 0),
@@ -1165,8 +1342,8 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+WM_ADSP1("DSP1", 0),
+WM_ADSP1("DSP2", 1),
SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1358,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+ WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1411,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1504,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
{ "SPK", NULL, "OUT2L" },
{ "SPK", NULL, "OUT2R" },
+ { "AEC Loopback", "OUT1L", "OUT1L" },
+ { "AEC Loopback", "OUT1R", "OUT1R" },
+ { "AEC Loopback", "OUT2L", "OUT2L" },
+ { "AEC Loopback", "OUT2R", "OUT2R" },
+
WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+ WM2200_DSP_AUX_ROUTES("DSP1"),
+ WM2200_DSP_AUX_ROUTES("DSP2"),
+
WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2154,15 @@ static const struct regmap_config wm2200_regmap = {
.reg_bits = 16,
.val_bits = 16,
- .max_register = WM2200_MAX_REGISTER,
+ .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+ WM2200_DSP_SPACING),
.reg_defaults = wm2200_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
.volatile_reg = wm2200_volatile_register,
.readable_reg = wm2200_readable_register,
.cache_type = REGCACHE_RBTREE,
+ .ranges = wm2200_ranges,
+ .num_ranges = ARRAY_SIZE(wm2200_ranges),
};
static const unsigned int wm2200_dig_vu[] = {
@@ -1995,8 +2184,8 @@ static const unsigned int wm2200_mic_ctrl_reg[] = {
WM2200_IN3L_CONTROL,
};
-static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm2200_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm2200_priv *wm2200;
@@ -2011,14 +2200,30 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
wm2200->dev = &i2c->dev;
init_completion(&wm2200->fll_lock);
- wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+ wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
if (IS_ERR(wm2200->regmap)) {
ret = PTR_ERR(wm2200->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
+ }
+
+ for (i = 0; i < 2; i++) {
+ wm2200->dsp[i].type = WMFW_ADSP1;
+ wm2200->dsp[i].part = "wm2200";
+ wm2200->dsp[i].num = i + 1;
+ wm2200->dsp[i].dev = &i2c->dev;
+ wm2200->dsp[i].regmap = wm2200->regmap;
}
+ wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1;
+ wm2200->dsp[0].mem = wm2200_dsp1_regions;
+ wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions);
+
+ wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1;
+ wm2200->dsp[1].mem = wm2200_dsp2_regions;
+ wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions);
+
if (pdata)
wm2200->pdata = *pdata;
@@ -2027,12 +2232,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
ret);
- goto err_regmap;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
@@ -2040,12 +2246,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_core;
+ return ret;
}
if (wm2200->pdata.ldo_ena) {
- ret = gpio_request_one(wm2200->pdata.ldo_ena,
- GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+ ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH,
+ "WM2200 LDOENA");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2262,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
}
if (wm2200->pdata.reset) {
- ret = gpio_request_one(wm2200->pdata.reset,
- GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+ ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+ GPIOF_OUT_INIT_HIGH,
+ "WM2200 /RESET");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
wm2200->pdata.reset, ret);
@@ -2166,45 +2374,28 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
err_pm_runtime:
pm_runtime_disable(&i2c->dev);
err_reset:
- if (wm2200->pdata.reset) {
+ if (wm2200->pdata.reset)
gpio_set_value_cansleep(wm2200->pdata.reset, 0);
- gpio_free(wm2200->pdata.reset);
- }
err_ldo:
- if (wm2200->pdata.ldo_ena) {
+ if (wm2200->pdata.ldo_ena)
gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
- gpio_free(wm2200->pdata.ldo_ena);
- }
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
wm2200->core_supplies);
-err_core:
- regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
-err_regmap:
- regmap_exit(wm2200->regmap);
-err:
return ret;
}
-static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+static int wm2200_i2c_remove(struct i2c_client *i2c)
{
struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
if (i2c->irq)
free_irq(i2c->irq, wm2200);
- if (wm2200->pdata.reset) {
+ if (wm2200->pdata.reset)
gpio_set_value_cansleep(wm2200->pdata.reset, 0);
- gpio_free(wm2200->pdata.reset);
- }
- if (wm2200->pdata.ldo_ena) {
+ if (wm2200->pdata.ldo_ena)
gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
- gpio_free(wm2200->pdata.ldo_ena);
- }
- regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
- regmap_exit(wm2200->regmap);
return 0;
}
@@ -2267,7 +2458,7 @@ static struct i2c_driver wm2200_i2c_driver = {
.pm = &wm2200_pm,
},
.probe = wm2200_i2c_probe,
- .remove = __devexit_p(wm2200_i2c_remove),
+ .remove = wm2200_i2c_remove,
.id_table = wm2200_i2c_id,
};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 7f567585832e..5a5f36936235 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
{ "PWM2", NULL, "PWM2 Driver" },
};
-static const __devinitconst struct reg_default wm5100_reva_patches[] = {
+static const struct reg_default wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_1_10, 0 },
{ WM5100_AUDIO_IF_1_11, 1 },
{ WM5100_AUDIO_IF_1_12, 2 },
@@ -2414,8 +2414,8 @@ static const unsigned int wm5100_mic_ctrl_reg[] = {
WM5100_IN4L_CONTROL,
};
-static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm5100_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm5100_priv *wm5100;
@@ -2639,7 +2639,7 @@ err:
return ret;
}
-static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
+static int wm5100_i2c_remove(struct i2c_client *i2c)
{
struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
@@ -2717,7 +2717,7 @@ static struct i2c_driver wm5100_i2c_driver = {
.pm = &wm5100_pm,
},
.probe = wm5100_i2c_probe,
- .remove = __devexit_p(wm5100_i2c_remove),
+ .remove = wm5100_i2c_remove,
.id_table = wm5100_i2c_id,
};
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 7394e73fa43c..688ade080589 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -31,6 +31,7 @@
#include "arizona.h"
#include "wm5102.h"
+#include "wm_adsp.h"
struct wm5102_priv {
struct arizona_priv core;
@@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
+static const struct wm_adsp_region wm5102_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 reg_default wm5102_sysclk_reva_patch[] = {
{ 0x3000, 0x2225 },
{ 0x3001, 0x3a03 },
@@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+ ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+ ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+ ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+ ARIZONA_EQ4_ENA_MASK),
+
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -687,6 +707,14 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
+ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
- ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
- ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("EPOUT 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),
@@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_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("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
- ARIZONA_OUTPUT_PATH_CONFIG_2R,
- ARIZONA_OUT2L_PGA_VOL_SHIFT,
- 0x34, 0x40, 0, ana_tlv),
-SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
- ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+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_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);
static const char *wm5102_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
- ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+ ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
- ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+ ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
@@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+WM_ADSP2("DSP1", 0),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "ASRC1L", "ASRC1L" }, \
{ name, "ASRC1R", "ASRC1R" }, \
{ name, "ASRC2L", "ASRC2L" }, \
- { name, "ASRC2R", "ASRC2R" }
+ { name, "ASRC2R", "ASRC2R" }, \
+ { name, "DSP1.1", "DSP1" }, \
+ { name, "DSP1.2", "DSP1" }, \
+ { name, "DSP1.3", "DSP1" }, \
+ { name, "DSP1.4", "DSP1" }, \
+ { name, "DSP1.5", "DSP1" }, \
+ { name, "DSP1.6", "DSP1" }
static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "AIF2 Capture", NULL, "DBVDD2" },
@@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "IN3L PGA", NULL, "IN3L" },
{ "IN3R PGA", NULL, "IN3R" },
+ { "ASRC1L", NULL, "ASRC1L Input" },
+ { "ASRC1R", NULL, "ASRC1R Input" },
+ { "ASRC2L", NULL, "ASRC2L Input" },
+ { "ASRC2R", NULL, "ASRC2R Input" },
+
ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
- ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
- ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
- ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
- ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+ ARIZONA_MUX_ROUTES("ASRC1L"),
+ ARIZONA_MUX_ROUTES("ASRC1R"),
+ ARIZONA_MUX_ROUTES("ASRC2L"),
+ ARIZONA_MUX_ROUTES("ASRC2R"),
+
+ ARIZONA_DSP_ROUTES("DSP1"),
{ "AEC Loopback", "HPOUT1L", "OUT1L" },
{ "AEC Loopback", "HPOUT1R", "OUT1R" },
@@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
static int wm5102_codec_probe(struct snd_soc_codec *codec)
{
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
codec->control_data = priv->core.arizona->regmap;
- return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+
+ ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ if (ret != 0)
+ return ret;
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+ priv->core.arizona->dapm = &codec->dapm;
+
+ return 0;
+}
+
+static int wm5102_codec_remove(struct snd_soc_codec *codec)
+{
+ struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->core.arizona->dapm = NULL;
+
+ return 0;
}
#define WM5102_DIG_VU 0x0200
@@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.probe = wm5102_codec_probe,
+ .remove = wm5102_codec_remove,
.idle_bias_off = true,
@@ -1420,11 +1475,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
};
-static int __devinit wm5102_probe(struct platform_device *pdev)
+static int wm5102_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct wm5102_priv *wm5102;
- int i;
+ int i, ret;
wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
GFP_KERNEL);
@@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
wm5102->core.arizona = arizona;
+ wm5102->core.adsp[0].part = "wm5102";
+ wm5102->core.adsp[0].num = 1;
+ wm5102->core.adsp[0].type = WMFW_ADSP2;
+ wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+ wm5102->core.adsp[0].dev = arizona->dev;
+ wm5102->core.adsp[0].regmap = arizona->regmap;
+ wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+ wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
+ ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+ if (ret != 0)
+ return ret;
+
for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
wm5102->fll[i].vco_mult = 1;
@@ -1459,7 +1527,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
wm5102_dai, ARRAY_SIZE(wm5102_dai));
}
-static int __devexit wm5102_remove(struct platform_device *pdev)
+static int wm5102_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -1473,7 +1541,7 @@ static struct platform_driver wm5102_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm5102_probe,
- .remove = __devexit_p(wm5102_remove),
+ .remove = wm5102_remove,
};
module_platform_driver(wm5102_codec_driver);
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 9211e4192f71..ae80c8c28536 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+ ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+ ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+ ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+ ARIZONA_EQ4_ENA_MASK),
+
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
24, 0, eq_tlv),
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -148,6 +160,11 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+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);
static const char *wm5110_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
- ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
- ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
- ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
- ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+ ARIZONA_MUX_ROUTES("ASRC1L"),
+ ARIZONA_MUX_ROUTES("ASRC1R"),
+ ARIZONA_MUX_ROUTES("ASRC2L"),
+ ARIZONA_MUX_ROUTES("ASRC2R"),
{ "HPOUT1L", NULL, "OUT1L" },
{ "HPOUT1R", NULL, "OUT1R" },
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
static int wm5110_codec_probe(struct snd_soc_codec *codec)
{
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
codec->control_data = priv->core.arizona->regmap;
- return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ priv->core.arizona->dapm = &codec->dapm;
+
+ ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ if (ret != 0)
+ return ret;
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+ priv->core.arizona->dapm = &codec->dapm;
+
+ return 0;
+}
+
+static int wm5110_codec_remove(struct snd_soc_codec *codec)
+{
+ struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->core.arizona->dapm = NULL;
+
+ return 0;
}
#define WM5110_DIG_VU 0x0200
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.probe = wm5110_codec_probe,
+ .remove = wm5110_codec_remove,
.idle_bias_off = true,
@@ -949,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
};
-static int __devinit wm5110_probe(struct platform_device *pdev)
+static int wm5110_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct wm5110_priv *wm5110;
@@ -988,7 +1031,7 @@ static int __devinit wm5110_probe(struct platform_device *pdev)
wm5110_dai, ARRAY_SIZE(wm5110_dai));
}
-static int __devexit wm5110_remove(struct platform_device *pdev)
+static int wm5110_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -1002,7 +1045,7 @@ static struct platform_driver wm5110_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm5110_probe,
- .remove = __devexit_p(wm5110_remove),
+ .remove = wm5110_remove,
};
module_platform_driver(wm5110_codec_driver);
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index a4cae060bf26..fb92fb47d636 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1500,7 +1500,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
priv->supplies[i].supply = supply_names[i];
- ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+ ret = devm_regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
priv->supplies);
if (ret != 0)
return ret;
@@ -1607,8 +1607,6 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
- regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-
return 0;
}
@@ -1627,13 +1625,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
.num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
};
-static int __devinit wm8350_probe(struct platform_device *pdev)
+static int wm8350_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
&wm8350_dai, 1);
}
-static int __devexit wm8350_remove(struct platform_device *pdev)
+static int wm8350_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1645,7 +1643,7 @@ static struct platform_driver wm8350_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8350_probe,
- .remove = __devexit_p(wm8350_remove),
+ .remove = wm8350_remove,
};
module_platform_driver(wm8350_codec_driver);
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 5d277a915f81..af6d227e67be 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1373,7 +1373,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
codec->control_data = priv->wm8400 = wm8400;
priv->codec = codec;
- ret = regulator_bulk_get(wm8400->dev,
+ ret = devm_regulator_bulk_get(wm8400->dev,
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
@@ -1398,15 +1398,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- if (!schedule_work(&priv->work)) {
- ret = -EINVAL;
- goto err_regulator;
- }
+ if (!schedule_work(&priv->work))
+ return -EINVAL;
return 0;
-
-err_regulator:
- regulator_bulk_free(ARRAY_SIZE(power), power);
- return ret;
}
static int wm8400_codec_remove(struct snd_soc_codec *codec)
@@ -1417,8 +1411,6 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1,
reg & (~WM8400_CODEC_ENA));
- regulator_bulk_free(ARRAY_SIZE(power), power);
-
return 0;
}
@@ -1439,13 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
};
-static int __devinit wm8400_probe(struct platform_device *pdev)
+static int wm8400_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
&wm8400_dai, 1);
}
-static int __devexit wm8400_remove(struct platform_device *pdev)
+static int wm8400_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1457,7 +1449,7 @@ static struct platform_driver wm8400_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8400_probe,
- .remove = __devexit_p(wm8400_remove),
+ .remove = wm8400_remove,
};
module_platform_driver(wm8400_codec_driver);
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index c12a54e72e89..6ed5433943ea 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -608,10 +608,7 @@ static int wm8510_probe(struct snd_soc_codec *codec)
/* power down chip */
static int wm8510_remove(struct snd_soc_codec *codec)
{
- struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
-
wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
- kfree(wm8510);
return 0;
}
@@ -648,7 +645,7 @@ static const struct regmap_config wm8510_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8510_spi_probe(struct spi_device *spi)
+static int wm8510_spi_probe(struct spi_device *spi)
{
struct wm8510_priv *wm8510;
int ret;
@@ -670,7 +667,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8510_spi_remove(struct spi_device *spi)
+static int wm8510_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -683,13 +680,13 @@ static struct spi_driver wm8510_spi_driver = {
.of_match_table = wm8510_of_match,
},
.probe = wm8510_spi_probe,
- .remove = __devexit_p(wm8510_spi_remove),
+ .remove = wm8510_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8510_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8510_priv *wm8510;
int ret;
@@ -711,7 +708,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8510_i2c_remove(struct i2c_client *client)
+static int wm8510_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -730,7 +727,7 @@ static struct i2c_driver wm8510_i2c_driver = {
.of_match_table = wm8510_of_match,
},
.probe = wm8510_i2c_probe,
- .remove = __devexit_p(wm8510_i2c_remove),
+ .remove = wm8510_i2c_remove,
.id_table = wm8510_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 8d5c27673501..139bf9ac9407 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -453,8 +453,8 @@ static const struct regmap_config wm8523_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8523_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8523_priv *wm8523;
unsigned int val;
@@ -528,7 +528,7 @@ err_enable:
return ret;
}
-static __devexit int wm8523_i2c_remove(struct i2c_client *client)
+static int wm8523_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -547,7 +547,7 @@ static struct i2c_driver wm8523_i2c_driver = {
.of_match_table = wm8523_of_match,
},
.probe = wm8523_i2c_probe,
- .remove = __devexit_p(wm8523_i2c_remove),
+ .remove = wm8523_i2c_remove,
.id_table = wm8523_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 8b8bb70f1eb9..5b428b060d41 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -429,7 +429,7 @@ static const struct regmap_config wm8711_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8711_spi_probe(struct spi_device *spi)
+static int wm8711_spi_probe(struct spi_device *spi)
{
struct wm8711_priv *wm8711;
int ret;
@@ -451,7 +451,7 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8711_spi_remove(struct spi_device *spi)
+static int wm8711_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -465,13 +465,13 @@ static struct spi_driver wm8711_spi_driver = {
.of_match_table = wm8711_of_match,
},
.probe = wm8711_spi_probe,
- .remove = __devexit_p(wm8711_spi_remove),
+ .remove = wm8711_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8711_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int wm8711_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8711_priv *wm8711;
int ret;
@@ -493,7 +493,7 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int wm8711_i2c_remove(struct i2c_client *client)
+static int wm8711_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -512,7 +512,7 @@ static struct i2c_driver wm8711_i2c_driver = {
.of_match_table = wm8711_of_match,
},
.probe = wm8711_i2c_probe,
- .remove = __devexit_p(wm8711_i2c_remove),
+ .remove = wm8711_i2c_remove,
.id_table = wm8711_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index e81705620718..462f5e4d5c05 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -45,13 +45,13 @@ static struct snd_soc_dai_driver wm8727_dai = {
static struct snd_soc_codec_driver soc_codec_dev_wm8727;
-static __devinit int wm8727_probe(struct platform_device *pdev)
+static int wm8727_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm8727, &wm8727_dai, 1);
}
-static int __devexit wm8727_remove(struct platform_device *pdev)
+static int wm8727_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -64,7 +64,7 @@ static struct platform_driver wm8727_codec_driver = {
},
.probe = wm8727_probe,
- .remove = __devexit_p(wm8727_remove),
+ .remove = wm8727_remove,
};
module_platform_driver(wm8727_codec_driver);
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 00a12a0c3919..c6a292dcded0 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -280,7 +280,7 @@ static const struct regmap_config wm8728_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
+static int wm8728_spi_probe(struct spi_device *spi)
{
struct wm8728_priv *wm8728;
int ret;
@@ -302,7 +302,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
+static int wm8728_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -316,13 +316,13 @@ static struct spi_driver wm8728_spi_driver = {
.of_match_table = wm8728_of_match,
},
.probe = wm8728_spi_probe,
- .remove = __devexit_p(wm8728_spi_remove),
+ .remove = wm8728_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8728_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8728_priv *wm8728;
int ret;
@@ -344,7 +344,7 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8728_i2c_remove(struct i2c_client *client)
+static int wm8728_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -363,7 +363,7 @@ static struct i2c_driver wm8728_i2c_driver = {
.of_match_table = wm8728_of_match,
},
.probe = wm8728_i2c_probe,
- .remove = __devexit_p(wm8728_i2c_remove),
+ .remove = wm8728_i2c_remove,
.id_table = wm8728_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index bb1d26919b10..5276062d6c79 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -631,7 +631,7 @@ static const struct regmap_config wm8731_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8731_spi_probe(struct spi_device *spi)
+static int wm8731_spi_probe(struct spi_device *spi)
{
struct wm8731_priv *wm8731;
int ret;
@@ -661,7 +661,7 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
return 0;
}
-static int __devexit wm8731_spi_remove(struct spi_device *spi)
+static int wm8731_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -674,13 +674,13 @@ static struct spi_driver wm8731_spi_driver = {
.of_match_table = wm8731_of_match,
},
.probe = wm8731_spi_probe,
- .remove = __devexit_p(wm8731_spi_remove),
+ .remove = wm8731_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8731_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8731_priv *wm8731;
int ret;
@@ -710,7 +710,7 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
return 0;
}
-static __devexit int wm8731_i2c_remove(struct i2c_client *client)
+static int wm8731_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -729,7 +729,7 @@ static struct i2c_driver wm8731_i2c_driver = {
.of_match_table = wm8731_of_match,
},
.probe = wm8731_i2c_probe,
- .remove = __devexit_p(wm8731_i2c_remove),
+ .remove = wm8731_i2c_remove,
.id_table = wm8731_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 5c9634f4c1f0..2f167a8ca01b 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -645,8 +645,8 @@ static const struct regmap_config wm8737_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8737_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8737_priv *wm8737;
int ret, i;
@@ -679,7 +679,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
}
-static __devexit int wm8737_i2c_remove(struct i2c_client *client)
+static int wm8737_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -699,13 +699,13 @@ static struct i2c_driver wm8737_i2c_driver = {
.of_match_table = wm8737_of_match,
},
.probe = wm8737_i2c_probe,
- .remove = __devexit_p(wm8737_i2c_remove),
+ .remove = wm8737_i2c_remove,
.id_table = wm8737_i2c_id,
};
#endif
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8737_spi_probe(struct spi_device *spi)
+static int wm8737_spi_probe(struct spi_device *spi)
{
struct wm8737_priv *wm8737;
int ret, i;
@@ -737,7 +737,7 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8737_spi_remove(struct spi_device *spi)
+static int wm8737_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -751,7 +751,7 @@ static struct spi_driver wm8737_spi_driver = {
.of_match_table = wm8737_of_match,
},
.probe = wm8737_spi_probe,
- .remove = __devexit_p(wm8737_spi_remove),
+ .remove = wm8737_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 4281a0802138..b18813cc7ba9 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -522,7 +522,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c,
return ret;
}
- wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap);
+ wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap);
if (IS_ERR(wm8741->regmap)) {
ret = PTR_ERR(wm8741->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -562,7 +562,7 @@ static struct i2c_driver wm8741_i2c_driver = {
#endif
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8741_spi_probe(struct spi_device *spi)
+static int wm8741_spi_probe(struct spi_device *spi)
{
struct wm8741_priv *wm8741;
int ret, i;
@@ -582,7 +582,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
return ret;
}
- wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap);
+ wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap);
if (IS_ERR(wm8741->regmap)) {
ret = PTR_ERR(wm8741->regmap);
dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -596,7 +596,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8741_spi_remove(struct spi_device *spi)
+static int wm8741_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -609,7 +609,7 @@ static struct spi_driver wm8741_spi_driver = {
.of_match_table = wm8741_of_match,
},
.probe = wm8741_spi_probe,
- .remove = __devexit_p(wm8741_spi_remove),
+ .remove = wm8741_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 89151ca5e776..50d5ff616232 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/of_device.h>
@@ -34,24 +35,55 @@
* We can't read the WM8750 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8750_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8750_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x0000 },
+ { 5, 0x0008 },
+ { 6, 0x0000 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 14, 0x0000 },
+ { 15, 0x0000 },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 38, 0x0050 },
+ { 39, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
/* codec private data */
struct wm8750_priv {
unsigned int sysclk;
- enum snd_soc_control_type control_type;
};
#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec)
static int wm8750_probe(struct snd_soc_codec *codec)
{
- struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
return ret;
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
.suspend = wm8750_suspend,
.resume = wm8750_resume,
.set_bias_level = wm8750_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8750_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8750_reg,
.controls = wm8750_snd_controls,
.num_controls = ARRAY_SIZE(wm8750_snd_controls),
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8750_of_match);
+static const struct regmap_config wm8750_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8750_MOUTV,
+
+ .reg_defaults = wm8750_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8750_spi_probe(struct spi_device *spi)
+static int wm8750_spi_probe(struct spi_device *spi)
{
struct wm8750_priv *wm8750;
+ struct regmap *regmap;
int ret;
wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
if (wm8750 == NULL)
return -ENOMEM;
- wm8750->control_type = SND_SOC_SPI;
+ regmap = devm_regmap_init_spi(spi, &wm8750_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
spi_set_drvdata(spi, wm8750);
ret = snd_soc_register_codec(&spi->dev,
@@ -749,7 +791,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8750_spi_remove(struct spi_device *spi)
+static int wm8750_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -770,15 +812,16 @@ static struct spi_driver wm8750_spi_driver = {
},
.id_table = wm8750_spi_ids,
.probe = wm8750_spi_probe,
- .remove = __devexit_p(wm8750_spi_remove),
+ .remove = wm8750_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8750_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8750_priv *wm8750;
+ struct regmap *regmap;
int ret;
wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
@@ -787,14 +830,17 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm8750);
- wm8750->control_type = SND_SOC_I2C;
+
+ regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8750, &wm8750_dai, 1);
return ret;
}
-static __devexit int wm8750_i2c_remove(struct i2c_client *client)
+static int wm8750_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -814,7 +860,7 @@ static struct i2c_driver wm8750_i2c_driver = {
.of_match_table = wm8750_of_match,
},
.probe = wm8750_i2c_probe,
- .remove = __devexit_p(wm8750_i2c_remove),
+ .remove = wm8750_i2c_remove,
.id_table = wm8750_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 2e4a775ae560..0a4ab4c423d1 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1550,7 +1550,7 @@ static const struct regmap_config wm8753_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8753_spi_probe(struct spi_device *spi)
+static int wm8753_spi_probe(struct spi_device *spi)
{
struct wm8753_priv *wm8753;
int ret;
@@ -1562,36 +1562,25 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, wm8753);
- wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+ wm8753->regmap = devm_regmap_init_spi(spi, &wm8753_regmap);
if (IS_ERR(wm8753->regmap)) {
ret = PTR_ERR(wm8753->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret != 0) {
+ if (ret != 0)
dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
- return 0;
-
-err_regmap:
- regmap_exit(wm8753->regmap);
-err:
return ret;
}
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
+static int wm8753_spi_remove(struct spi_device *spi)
{
- struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
-
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8753->regmap);
- kfree(wm8753);
return 0;
}
@@ -1602,13 +1591,13 @@ static struct spi_driver wm8753_spi_driver = {
.of_match_table = wm8753_of_match,
},
.probe = wm8753_spi_probe,
- .remove = __devexit_p(wm8753_spi_remove),
+ .remove = wm8753_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8753_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8753_priv *wm8753;
int ret;
@@ -1620,35 +1609,25 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8753);
- wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+ wm8753->regmap = devm_regmap_init_i2c(i2c, &wm8753_regmap);
if (IS_ERR(wm8753->regmap)) {
ret = PTR_ERR(wm8753->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret != 0) {
+ if (ret != 0)
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
- return 0;
-
-err_regmap:
- regmap_exit(wm8753->regmap);
-err:
return ret;
}
-static __devexit int wm8753_i2c_remove(struct i2c_client *client)
+static int wm8753_i2c_remove(struct i2c_client *client)
{
- struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8753->regmap);
return 0;
}
@@ -1665,7 +1644,7 @@ static struct i2c_driver wm8753_i2c_driver = {
.of_match_table = wm8753_of_match,
},
.probe = wm8753_i2c_probe,
- .remove = __devexit_p(wm8753_i2c_remove),
+ .remove = wm8753_i2c_remove,
.id_table = wm8753_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index c7c0034d3966..89a18d82f303 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -17,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
"DVDD"
};
-static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
- 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0, 0x90, 0,
- 0, 0x22, 0x22, 0x3e,
- 0xc, 0xc, 0x100, 0x189,
- 0x189, 0x8770
+static const struct reg_default wm8770_reg_defaults[] = {
+ { 0, 0x7f },
+ { 1, 0x7f },
+ { 2, 0x7f },
+ { 3, 0x7f },
+ { 4, 0x7f },
+ { 5, 0x7f },
+ { 6, 0x7f },
+ { 7, 0x7f },
+ { 8, 0x7f },
+ { 9, 0xff },
+ { 10, 0xff },
+ { 11, 0xff },
+ { 12, 0xff },
+ { 13, 0xff },
+ { 14, 0xff },
+ { 15, 0xff },
+ { 16, 0xff },
+ { 17, 0xff },
+ { 18, 0 },
+ { 19, 0x90 },
+ { 20, 0 },
+ { 21, 0 },
+ { 22, 0x22 },
+ { 23, 0x22 },
+ { 24, 0x3e },
+ { 25, 0xc },
+ { 26, 0xc },
+ { 27, 0x100 },
+ { 28, 0x189 },
+ { 29, 0x189 },
+ { 30, 0x8770 },
};
+static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8770_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct wm8770_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
struct snd_soc_codec *codec;
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8770->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8770->regmap); \
} \
return 0; \
}
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
return 0;
}
-static void wm8770_sync_cache(struct snd_soc_codec *codec)
-{
- int i;
- u16 *cache;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_sync = 0;
-}
-
static int wm8770_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
ret);
return ret;
}
- wm8770_sync_cache(codec);
+
+ regcache_sync(wm8770->regmap);
+
/* global powerup */
snd_soc_write(codec, WM8770_PWDNCTRL, 0);
}
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
.symmetric_rates = 1
};
-#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec)
-{
- wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return 0;
-}
-
-static int wm8770_resume(struct snd_soc_codec *codec)
-{
- wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return 0;
-}
-#else
-#define wm8770_suspend NULL
-#define wm8770_resume NULL
-#endif
-
static int wm8770_probe(struct snd_soc_codec *codec)
{
struct wm8770_priv *wm8770;
int ret;
- int i;
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
- wm8770->supplies[i].supply = wm8770_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
- wm8770->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
- wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
- wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
-
- /* This should really be moved into the regulator core */
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
- ret = regulator_register_notifier(wm8770->supplies[i].consumer,
- &wm8770->disable_nb[i]);
- if (ret) {
- dev_err(codec->dev,
- "Failed to register regulator notifier: %d\n",
- ret);
- }
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
wm8770->supplies);
if (ret) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_reg_get;
+ return ret;
}
ret = wm8770_reset(codec);
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
goto err_reg_enable;
}
- wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
/* latch the volume update bits */
snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
- snd_soc_add_codec_controls(codec, wm8770_snd_controls,
- ARRAY_SIZE(wm8770_snd_controls));
- snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
- ARRAY_SIZE(wm8770_dapm_widgets));
- snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
- ARRAY_SIZE(wm8770_intercon));
- return 0;
-
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-err_reg_get:
- regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
return ret;
}
-static int wm8770_remove(struct snd_soc_codec *codec)
-{
- struct wm8770_priv *wm8770;
- int i;
-
- wm8770 = snd_soc_codec_get_drvdata(codec);
- wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
- regulator_unregister_notifier(wm8770->supplies[i].consumer,
- &wm8770->disable_nb[i]);
- regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
- return 0;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
.probe = wm8770_probe,
- .remove = wm8770_remove,
- .suspend = wm8770_suspend,
- .resume = wm8770_resume,
.set_bias_level = wm8770_set_bias_level,
.idle_bias_off = true,
- .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
- .reg_word_size = sizeof (u16),
- .reg_cache_default = wm8770_reg_defs
+
+ .controls = wm8770_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8770_snd_controls),
+ .dapm_widgets = wm8770_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
+ .dapm_routes = wm8770_intercon,
+ .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
};
static const struct of_device_id wm8770_of_match[] = {
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8770_of_match);
-static int __devinit wm8770_spi_probe(struct spi_device *spi)
+static const struct regmap_config wm8770_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8770_RESET,
+
+ .reg_defaults = wm8770_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+
+ .volatile_reg = wm8770_volatile_reg,
+};
+
+static int wm8770_spi_probe(struct spi_device *spi)
{
struct wm8770_priv *wm8770;
- int ret;
+ int ret, i;
wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
GFP_KERNEL);
if (!wm8770)
return -ENOMEM;
- wm8770->control_type = SND_SOC_SPI;
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
+ wm8770->supplies[i].supply = wm8770_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
+ wm8770->supplies);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
+ wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
+ wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
+
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
+ ret = regulator_register_notifier(wm8770->supplies[i].consumer,
+ &wm8770->disable_nb[i]);
+ if (ret) {
+ dev_err(&spi->dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
+
+ wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
+ if (IS_ERR(wm8770->regmap))
+ return PTR_ERR(wm8770->regmap);
+
spi_set_drvdata(spi, wm8770);
ret = snd_soc_register_codec(&spi->dev,
@@ -708,9 +697,17 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8770_spi_remove(struct spi_device *spi)
+static int wm8770_spi_remove(struct spi_device *spi)
{
+ struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
+ regulator_unregister_notifier(wm8770->supplies[i].consumer,
+ &wm8770->disable_nb[i]);
+
snd_soc_unregister_codec(&spi->dev);
+
return 0;
}
@@ -721,7 +718,7 @@ static struct spi_driver wm8770_spi_driver = {
.of_match_table = wm8770_of_match,
},
.probe = wm8770_spi_probe,
- .remove = __devexit_p(wm8770_spi_remove)
+ .remove = wm8770_spi_remove
};
module_spi_driver(wm8770_spi_driver);
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index c32249ddb2e0..f31017ed1381 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -492,7 +492,7 @@ static const struct regmap_config wm8776_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8776_spi_probe(struct spi_device *spi)
+static int wm8776_spi_probe(struct spi_device *spi)
{
struct wm8776_priv *wm8776;
int ret;
@@ -514,7 +514,7 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8776_spi_remove(struct spi_device *spi)
+static int wm8776_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -527,13 +527,13 @@ static struct spi_driver wm8776_spi_driver = {
.of_match_table = wm8776_of_match,
},
.probe = wm8776_spi_probe,
- .remove = __devexit_p(wm8776_spi_remove),
+ .remove = wm8776_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8776_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8776_priv *wm8776;
int ret;
@@ -555,7 +555,7 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8776_i2c_remove(struct i2c_client *client)
+static int wm8776_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -575,7 +575,7 @@ static struct i2c_driver wm8776_i2c_driver = {
.of_match_table = wm8776_of_match,
},
.probe = wm8776_i2c_probe,
- .remove = __devexit_p(wm8776_i2c_remove),
+ .remove = wm8776_i2c_remove,
.id_table = wm8776_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index 3fdea98f732e..f1fdbf63abb4 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -42,13 +42,13 @@ static struct snd_soc_dai_driver wm8782_dai = {
static struct snd_soc_codec_driver soc_codec_dev_wm8782;
-static __devinit int wm8782_probe(struct platform_device *pdev)
+static int wm8782_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm8782, &wm8782_dai, 1);
}
-static int __devexit wm8782_remove(struct platform_device *pdev)
+static int wm8782_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8782_probe,
- .remove = __devexit_p(wm8782_remove),
+ .remove = wm8782_remove,
};
module_platform_driver(wm8782_codec_driver);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index c088020172ab..d321a875b029 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -702,7 +702,7 @@ static struct regmap_config wm8804_regmap_config = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8804_spi_probe(struct spi_device *spi)
+static int wm8804_spi_probe(struct spi_device *spi)
{
struct wm8804_priv *wm8804;
int ret;
@@ -711,7 +711,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
if (!wm8804)
return -ENOMEM;
- wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+ wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap);
return ret;
@@ -725,11 +725,9 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8804_spi_remove(struct spi_device *spi)
+static int wm8804_spi_remove(struct spi_device *spi)
{
- struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8804->regmap);
return 0;
}
@@ -740,13 +738,13 @@ static struct spi_driver wm8804_spi_driver = {
.of_match_table = wm8804_of_match,
},
.probe = wm8804_spi_probe,
- .remove = __devexit_p(wm8804_spi_remove)
+ .remove = wm8804_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8804_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8804_priv *wm8804;
int ret;
@@ -755,7 +753,7 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
if (!wm8804)
return -ENOMEM;
- wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+ wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap);
return ret;
@@ -765,23 +763,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8804, &wm8804_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8804->regmap);
return ret;
}
-static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
+static int wm8804_i2c_remove(struct i2c_client *i2c)
{
- struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm8804->regmap);
-
return 0;
}
@@ -798,7 +785,7 @@ static struct i2c_driver wm8804_i2c_driver = {
.of_match_table = wm8804_of_match,
},
.probe = wm8804_i2c_probe,
- .remove = __devexit_p(wm8804_i2c_remove),
+ .remove = wm8804_i2c_remove,
.id_table = wm8804_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index e781f865e5d7..7c8257c5a17b 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1247,7 +1247,7 @@ static const struct regmap_config wm8900_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8900_spi_probe(struct spi_device *spi)
+static int wm8900_spi_probe(struct spi_device *spi)
{
struct wm8900_priv *wm8900;
int ret;
@@ -1269,7 +1269,7 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8900_spi_remove(struct spi_device *spi)
+static int wm8900_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -1281,13 +1281,13 @@ static struct spi_driver wm8900_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8900_spi_probe,
- .remove = __devexit_p(wm8900_spi_remove),
+ .remove = wm8900_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8900_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8900_priv *wm8900;
int ret;
@@ -1309,7 +1309,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+static int wm8900_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1327,7 +1327,7 @@ static struct i2c_driver wm8900_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8900_i2c_probe,
- .remove = __devexit_p(wm8900_i2c_remove),
+ .remove = wm8900_i2c_remove,
.id_table = wm8900_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 839414f9e2ed..134e41c870b9 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2020,8 +2020,8 @@ static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
return 0;
}
-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8903_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8903_priv *wm8903;
@@ -2206,7 +2206,7 @@ err:
return ret;
}
-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+static int wm8903_i2c_remove(struct i2c_client *client)
{
struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
@@ -2237,7 +2237,7 @@ static struct i2c_driver wm8903_i2c_driver = {
.of_match_table = wm8903_of_match,
},
.probe = wm8903_i2c_probe,
- .remove = __devexit_p(wm8903_i2c_remove),
+ .remove = wm8903_i2c_remove,
.id_table = wm8903_i2c_id,
};
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 7c8df52a8d9d..3ff195c541db 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2111,8 +2111,8 @@ static const struct regmap_config wm8904_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
-static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8904_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8904_priv *wm8904;
unsigned int val;
@@ -2247,7 +2247,7 @@ err_enable:
return ret;
}
-static __devexit int wm8904_i2c_remove(struct i2c_client *client)
+static int wm8904_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2267,7 +2267,7 @@ static struct i2c_driver wm8904_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8904_i2c_probe,
- .remove = __devexit_p(wm8904_i2c_remove),
+ .remove = wm8904_i2c_remove,
.id_table = wm8904_i2c_id,
};
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index b20aa4e7c3f9..b1591c61c254 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -742,8 +742,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
.volatile_register = wm8940_volatile_register,
};
-static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8940_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8940_priv *wm8940;
int ret;
@@ -762,7 +762,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8940_i2c_remove(struct i2c_client *client)
+static int wm8940_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -781,7 +781,7 @@ static struct i2c_driver wm8940_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8940_i2c_probe,
- .remove = __devexit_p(wm8940_i2c_remove),
+ .remove = wm8940_i2c_remove,
.id_table = wm8940_i2c_id,
};
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 2f1c075755b1..82c8ba975720 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -1012,8 +1012,8 @@ static const struct regmap_config wm8955_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
};
-static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8955_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8955_priv *wm8955;
int ret;
@@ -1023,7 +1023,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
if (wm8955 == NULL)
return -ENOMEM;
- wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+ wm8955->regmap = devm_regmap_init_i2c(i2c, &wm8955_regmap);
if (IS_ERR(wm8955->regmap)) {
ret = PTR_ERR(wm8955->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1035,22 +1035,13 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1);
- if (ret != 0)
- goto err;
return ret;
-
-err:
- regmap_exit(wm8955->regmap);
- return ret;
}
-static __devexit int wm8955_i2c_remove(struct i2c_client *client)
+static int wm8955_i2c_remove(struct i2c_client *client)
{
- struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8955->regmap);
return 0;
}
@@ -1067,7 +1058,7 @@ static struct i2c_driver wm8955_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8955_i2c_probe,
- .remove = __devexit_p(wm8955_i2c_remove),
+ .remove = wm8955_i2c_remove,
.id_table = wm8955_i2c_id,
};
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 00121ba36597..b0710d817a65 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -195,7 +195,7 @@ ok:
static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i;
/* If the DSP is already running then noop */
@@ -210,9 +210,9 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied MBC settings use them */
- if (pdata && pdata->num_mbc_cfgs) {
+ if (control->pdata.num_mbc_cfgs) {
struct wm8958_mbc_cfg *cfg
- = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+ = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1,
@@ -239,7 +239,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i, ena;
if (wm8994->mbc_vss)
@@ -249,26 +249,26 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied settings use them */
- if (pdata && pdata->num_mbc_cfgs) {
+ if (control->pdata.num_mbc_cfgs) {
struct wm8958_mbc_cfg *cfg
- = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+ = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
snd_soc_write(codec, i + 0x2800,
cfg->combined_regs[i]);
}
- if (pdata && pdata->num_vss_cfgs) {
+ if (control->pdata.num_vss_cfgs) {
struct wm8958_vss_cfg *cfg
- = &pdata->vss_cfgs[wm8994->vss_cfg];
+ = &control->pdata.vss_cfgs[wm8994->vss_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2600, cfg->regs[i]);
}
- if (pdata && pdata->num_vss_hpf_cfgs) {
+ if (control->pdata.num_vss_hpf_cfgs) {
struct wm8958_vss_hpf_cfg *cfg
- = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg];
+ = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2400, cfg->regs[i]);
@@ -300,7 +300,7 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i;
wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false);
@@ -309,9 +309,9 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied settings use them */
- if (pdata && pdata->num_enh_eq_cfgs) {
+ if (control->pdata.num_enh_eq_cfgs) {
struct wm8958_enh_eq_cfg *cfg
- = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg];
+ = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2200,
@@ -458,7 +458,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -467,7 +467,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_mbc_cfgs)
+ if (value >= control->pdata.num_mbc_cfgs)
return -EINVAL;
wm8994->mbc_cfg = value;
@@ -548,7 +548,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -557,7 +557,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_vss_cfgs)
+ if (value >= control->pdata.num_vss_cfgs)
return -EINVAL;
wm8994->vss_cfg = value;
@@ -581,7 +581,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -590,7 +590,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_vss_hpf_cfgs)
+ if (value >= control->pdata.num_vss_hpf_cfgs)
return -EINVAL;
wm8994->vss_hpf_cfg = value;
@@ -748,7 +748,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -757,7 +757,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_enh_eq_cfgs)
+ if (value >= control->pdata.num_enh_eq_cfgs)
return -EINVAL;
wm8994->enh_eq_cfg = value;
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
wm8994->mbc_vss = fw;
mutex_unlock(&codec->mutex);
}
-
- /* We can't have more than one request outstanding at once so
- * we daisy chain.
- */
- request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
- "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
- codec, wm8958_enh_eq_loaded);
}
static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
@@ -897,25 +890,18 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
struct snd_soc_codec *codec = context;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0)
- return;
-
- mutex_lock(&codec->mutex);
- wm8994->mbc = fw;
- mutex_unlock(&codec->mutex);
-
- /* We can't have more than one request outstanding at once so
- * we daisy chain.
- */
- request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
- "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
- codec, wm8958_mbc_vss_loaded);
+ if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) {
+ mutex_lock(&codec->mutex);
+ wm8994->mbc = fw;
+ mutex_unlock(&codec->mutex);
+ }
}
void wm8958_dsp2_init(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int ret, i;
wm8994->dsp_active = -1;
@@ -932,9 +918,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
"wm8958_mbc.wfw", codec->dev, GFP_KERNEL,
codec, wm8958_mbc_loaded);
-
- if (!pdata)
- return;
+ request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
+ codec, wm8958_mbc_vss_loaded);
+ request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
+ codec, wm8958_enh_eq_loaded);
if (pdata->num_mbc_cfgs) {
struct snd_kcontrol_new control[] = {
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f0f6f6601785..9bb927325993 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1028,8 +1028,8 @@ static const struct regmap_config wm8960_regmap = {
.volatile_reg = wm8960_volatile,
};
-static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8960_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960;
@@ -1040,7 +1040,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
if (wm8960 == NULL)
return -ENOMEM;
- wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap);
+ wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);
@@ -1062,7 +1062,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8960_i2c_remove(struct i2c_client *client)
+static int wm8960_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1080,7 +1080,7 @@ static struct i2c_driver wm8960_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8960_i2c_probe,
- .remove = __devexit_p(wm8960_i2c_remove),
+ .remove = wm8960_i2c_remove,
.id_table = wm8960_i2c_id,
};
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index f387670d0d75..900328e28a15 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -937,8 +937,8 @@ static const struct regmap_config wm8961_regmap = {
.readable_reg = wm8961_readable,
};
-static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8961_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8961_priv *wm8961;
unsigned int val;
@@ -993,7 +993,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8961_i2c_remove(struct i2c_client *client)
+static int wm8961_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1012,7 +1012,7 @@ static struct i2c_driver wm8961_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8961_i2c_probe,
- .remove = __devexit_p(wm8961_i2c_remove),
+ .remove = wm8961_i2c_remove,
.id_table = wm8961_i2c_id,
};
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index ce6720073798..bd4b0db4cdaa 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3588,8 +3588,8 @@ static const struct regmap_config wm8962_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8962_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm8962_priv *wm8962;
@@ -3610,7 +3610,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
wm8962->supplies[i].supply = wm8962_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
wm8962->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
@@ -3621,10 +3621,10 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
wm8962->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
+ return ret;
}
- wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+ wm8962->regmap = devm_regmap_init_i2c(i2c, &wm8962_regmap);
if (IS_ERR(wm8962->regmap)) {
ret = PTR_ERR(wm8962->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -3641,20 +3641,20 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read ID register\n");
- goto err_regmap;
+ goto err_enable;
}
if (reg != 0x6243) {
dev_err(&i2c->dev,
"Device is not a WM8962, ID %x != 0x6243\n", reg);
ret = -EINVAL;
- goto err_regmap;
+ goto err_enable;
}
ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read device revision: %d\n",
ret);
- goto err_regmap;
+ goto err_enable;
}
dev_info(&i2c->dev, "customer id %x revision %c\n",
@@ -3667,7 +3667,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = wm8962_reset(wm8962);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
- goto err_regmap;
+ goto err_enable;
}
if (pdata && pdata->in4_dc_measure) {
@@ -3686,30 +3686,22 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
if (ret < 0)
- goto err_regmap;
+ goto err_enable;
/* The drivers should power up as needed */
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
-err_regmap:
- regmap_exit(wm8962->regmap);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
err:
return ret;
}
-static __devexit int wm8962_i2c_remove(struct i2c_client *client)
+static int wm8962_i2c_remove(struct i2c_client *client)
{
- struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8962->regmap);
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
}
@@ -3773,7 +3765,7 @@ static struct i2c_driver wm8962_i2c_driver = {
.pm = &wm8962_pm,
},
.probe = wm8962_i2c_probe,
- .remove = __devexit_p(wm8962_i2c_remove),
+ .remove = wm8962_i2c_remove,
.id_table = wm8962_i2c_id,
};
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 5ce647758443..67aba78a7ca5 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -19,6 +19,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>
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL;
/* codec private data */
struct wm8971_priv {
- enum snd_soc_control_type control_type;
unsigned int sysclk;
};
@@ -43,18 +43,50 @@ struct wm8971_priv {
* We can't read the WM8971 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8971_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8971_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x0000 },
+ { 5, 0x0008 },
+ { 6, 0x0000 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 14, 0x0000 },
+ { 15, 0x0000 },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 38, 0x0050 },
+ { 39, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec)
static int wm8971_probe(struct snd_soc_codec *codec)
{
- struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
return ret;
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.suspend = wm8971_suspend,
.resume = wm8971_resume,
.set_bias_level = wm8971_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8971_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8971_reg,
.controls = wm8971_snd_controls,
.num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
};
-static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static const struct regmap_config wm8971_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8971_MOUTV,
+
+ .reg_defaults = wm8971_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int wm8971_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8971_priv *wm8971;
+ struct regmap *regmap;
int ret;
wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
if (wm8971 == NULL)
return -ENOMEM;
- wm8971->control_type = SND_SOC_I2C;
+ regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
i2c_set_clientdata(i2c, wm8971);
ret = snd_soc_register_codec(&i2c->dev,
@@ -699,7 +741,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8971_i2c_remove(struct i2c_client *client)
+static int wm8971_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -717,7 +759,7 @@ static struct i2c_driver wm8971_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8971_i2c_probe,
- .remove = __devexit_p(wm8971_i2c_remove),
+ .remove = wm8971_i2c_remove,
.id_table = wm8971_i2c_id,
};
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 9a39511af52a..ea58b73e86b2 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -625,8 +625,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
};
-static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8974_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
int ret;
@@ -636,7 +636,7 @@ static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8974_i2c_remove(struct i2c_client *client)
+static int wm8974_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -655,7 +655,7 @@ static struct i2c_driver wm8974_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8974_i2c_probe,
- .remove = __devexit_p(wm8974_i2c_remove),
+ .remove = wm8974_i2c_remove,
.id_table = wm8974_i2c_id,
};
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 4c0a8e496131..f347af3a67c2 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -527,9 +527,6 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
return idx;
wm8978->mclk_idx = idx;
-
- /* GPIO1 into default mode as input - before configuring PLL */
- snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0);
} else {
return -EINVAL;
}
@@ -1038,8 +1035,8 @@ static const struct regmap_config wm8978_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
};
-static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8978_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8978_priv *wm8978;
int ret;
@@ -1049,7 +1046,7 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
if (wm8978 == NULL)
return -ENOMEM;
- wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+ wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config);
if (IS_ERR(wm8978->regmap)) {
ret = PTR_ERR(wm8978->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1062,29 +1059,22 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8978, &wm8978_dai, 1);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err;
+ return ret;
}
return 0;
-
-err:
- regmap_exit(wm8978->regmap);
- return ret;
}
-static __devexit int wm8978_i2c_remove(struct i2c_client *client)
+static int wm8978_i2c_remove(struct i2c_client *client)
{
- struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8978->regmap);
return 0;
}
@@ -1101,7 +1091,7 @@ static struct i2c_driver wm8978_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8978_i2c_probe,
- .remove = __devexit_p(wm8978_i2c_remove),
+ .remove = wm8978_i2c_remove,
.id_table = wm8978_i2c_id,
};
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index d8879f262d27..9fe1e041da49 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -1087,7 +1087,7 @@ static const struct regmap_config wm8983_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8983_spi_probe(struct spi_device *spi)
+static int wm8983_spi_probe(struct spi_device *spi)
{
struct wm8983_priv *wm8983;
int ret;
@@ -1110,7 +1110,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8983_spi_remove(struct spi_device *spi)
+static int wm8983_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -1122,13 +1122,13 @@ static struct spi_driver wm8983_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8983_spi_probe,
- .remove = __devexit_p(wm8983_spi_remove)
+ .remove = wm8983_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8983_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8983_priv *wm8983;
int ret;
@@ -1152,7 +1152,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8983_i2c_remove(struct i2c_client *client)
+static int wm8983_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1170,7 +1170,7 @@ static struct i2c_driver wm8983_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8983_i2c_probe,
- .remove = __devexit_p(wm8983_i2c_remove),
+ .remove = wm8983_i2c_remove,
.id_table = wm8983_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 14f666398d0c..ab3782657ac8 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1111,7 +1111,7 @@ static const struct regmap_config wm8985_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8985_spi_probe(struct spi_device *spi)
+static int wm8985_spi_probe(struct spi_device *spi)
{
struct wm8985_priv *wm8985;
int ret;
@@ -1122,33 +1122,22 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, wm8985);
- wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+ wm8985->regmap = devm_regmap_init_spi(spi, &wm8985_regmap);
if (IS_ERR(wm8985->regmap)) {
ret = PTR_ERR(wm8985->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8985->regmap);
return ret;
}
-static int __devexit wm8985_spi_remove(struct spi_device *spi)
+static int wm8985_spi_remove(struct spi_device *spi)
{
- struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
-
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8985->regmap);
-
return 0;
}
@@ -1158,13 +1147,13 @@ static struct spi_driver wm8985_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8985_spi_probe,
- .remove = __devexit_p(wm8985_spi_remove)
+ .remove = wm8985_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8985_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8985_priv *wm8985;
int ret;
@@ -1175,33 +1164,22 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8985);
- wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+ wm8985->regmap = devm_regmap_init_i2c(i2c, &wm8985_regmap);
if (IS_ERR(wm8985->regmap)) {
ret = PTR_ERR(wm8985->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8985->regmap);
return ret;
}
-static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
+static int wm8985_i2c_remove(struct i2c_client *i2c)
{
- struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm8985->regmap);
-
return 0;
}
@@ -1217,7 +1195,7 @@ static struct i2c_driver wm8985_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8985_i2c_probe,
- .remove = __devexit_p(wm8985_i2c_remove),
+ .remove = wm8985_i2c_remove,
.id_table = wm8985_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 1d4c5cf47b06..39b9acceb595 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -872,7 +872,7 @@ static struct regmap_config wm8988_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8988_spi_probe(struct spi_device *spi)
+static int wm8988_spi_probe(struct spi_device *spi)
{
struct wm8988_priv *wm8988;
int ret;
@@ -882,7 +882,7 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
if (wm8988 == NULL)
return -ENOMEM;
- wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+ wm8988->regmap = devm_regmap_init_spi(spi, &wm8988_regmap);
if (IS_ERR(wm8988->regmap)) {
ret = PTR_ERR(wm8988->regmap);
dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -893,17 +893,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret != 0)
- regmap_exit(wm8988->regmap);
-
return ret;
}
-static int __devexit wm8988_spi_remove(struct spi_device *spi)
+static int wm8988_spi_remove(struct spi_device *spi)
{
- struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8988->regmap);
return 0;
}
@@ -913,13 +908,13 @@ static struct spi_driver wm8988_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8988_spi_probe,
- .remove = __devexit_p(wm8988_spi_remove),
+ .remove = wm8988_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8988_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8988_priv *wm8988;
int ret;
@@ -931,7 +926,7 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8988);
- wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+ wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);
if (IS_ERR(wm8988->regmap)) {
ret = PTR_ERR(wm8988->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -940,17 +935,12 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret != 0)
- regmap_exit(wm8988->regmap);
-
return ret;
}
-static __devexit int wm8988_i2c_remove(struct i2c_client *client)
+static int wm8988_i2c_remove(struct i2c_client *client)
{
- struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8988->regmap);
return 0;
}
@@ -966,7 +956,7 @@ static struct i2c_driver wm8988_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
- .remove = __devexit_p(wm8988_i2c_remove),
+ .remove = wm8988_i2c_remove,
.id_table = wm8988_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c28c83e5395d..837978e16e9d 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1382,8 +1382,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8990_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8990_priv *wm8990;
int ret;
@@ -1401,7 +1401,7 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8990_i2c_remove(struct i2c_client *client)
+static int wm8990_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1420,7 +1420,7 @@ static struct i2c_driver wm8990_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8990_i2c_probe,
- .remove = __devexit_p(wm8990_i2c_remove),
+ .remove = wm8990_i2c_remove,
.id_table = wm8990_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index fe439f027e10..3a39df7a3829 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1357,8 +1357,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
.reg_cache_default = wm8991_reg_defs
};
-static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8991_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8991_priv *wm8991;
int ret;
@@ -1376,7 +1376,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8991_i2c_remove(struct i2c_client *client)
+static int wm8991_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1395,7 +1395,7 @@ static struct i2c_driver wm8991_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8991_i2c_probe,
- .remove = __devexit_p(wm8991_i2c_remove),
+ .remove = wm8991_i2c_remove,
.id_table = wm8991_i2c_id,
};
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 94737a30716b..433d59a0f3ef 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1645,8 +1645,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
.set_bias_level = wm8993_set_bias_level,
};
-static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8993_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8993_priv *wm8993;
unsigned int reg;
@@ -1660,7 +1660,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
wm8993->dev = &i2c->dev;
init_completion(&wm8993->fll_lock);
- wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+ wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap);
if (IS_ERR(wm8993->regmap)) {
ret = PTR_ERR(wm8993->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1672,18 +1672,18 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
wm8993->supplies[i].supply = wm8993_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
+ return ret;
}
ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
@@ -1742,23 +1742,17 @@ err_irq:
free_irq(i2c->irq, wm8993);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err:
- regmap_exit(wm8993->regmap);
return ret;
}
-static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
+static int wm8993_i2c_remove(struct i2c_client *i2c)
{
struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
if (i2c->irq)
free_irq(i2c->irq, wm8993);
- regmap_exit(wm8993->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
return 0;
}
@@ -1775,7 +1769,7 @@ static struct i2c_driver wm8993_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8993_i2c_probe,
- .remove = __devexit_p(wm8993_i2c_remove),
+ .remove = wm8993_i2c_remove,
.id_table = wm8993_i2c_id,
};
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b2b2b37131bd..3b269fa226bd 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = {
WM8994_AIF2_EQ_GAINS_1,
};
-static void wm8958_default_micdet(u16 status, void *data);
-
static const struct wm8958_micd_rate micdet_rates[] = {
{ 32768, true, 1, 4 },
{ 32768, false, 1, 1 },
@@ -110,15 +108,12 @@ static const struct wm8958_micd_rate jackdet_rates[] = {
static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int best, i, sysclk, val;
bool idle;
const struct wm8958_micd_rate *rates;
int num_rates;
- if (!(wm8994->pdata && wm8994->pdata->micd_rates) &&
- wm8994->jack_cb != wm8958_default_micdet)
- return;
-
idle = !wm8994->jack_mic;
sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
@@ -127,9 +122,9 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
else
sysclk = wm8994->aifclk[0];
- if (wm8994->pdata && wm8994->pdata->micd_rates) {
- rates = wm8994->pdata->micd_rates;
- num_rates = wm8994->pdata->num_micd_rates;
+ if (control->pdata.micd_rates) {
+ rates = control->pdata.micd_rates;
+ num_rates = control->pdata.num_micd_rates;
} else if (wm8994->jackdet) {
rates = jackdet_rates;
num_rates = ARRAY_SIZE(jackdet_rates);
@@ -326,7 +321,8 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int base = wm8994_drc_base[drc];
int cfg = wm8994->drc_cfg[drc];
int save, i;
@@ -362,7 +358,8 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int drc = wm8994_get_drc(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -394,7 +391,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int base = wm8994_retune_mobile_base[block];
int iface, best, best_val, save, i, cfg;
@@ -465,7 +463,8 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -736,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- if (!wm8994->jackdet || !wm8994->jack_cb)
+ if (!wm8994->jackdet || !wm8994->micdet[0].jack)
return;
if (wm8994->active_refcount)
@@ -862,7 +861,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
- (0x3 << WM8994_VMID_RAMP_SHIFT));
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -870,7 +869,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_VMID_SEL_MASK,
WM8994_BIAS_ENA | 0x2);
- msleep(50);
+ msleep(300);
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_VMID_RAMP_MASK |
@@ -939,16 +938,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_BIAS_SRC |
WM8994_VMID_DISCH);
- switch (wm8994->vmid_mode) {
- case WM8994_VMID_FORCE:
- msleep(350);
- break;
- default:
- break;
- }
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0);
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
- WM8994_VROI, WM8994_VROI);
+ msleep(400);
/* Active discharge */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -957,17 +950,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH);
- msleep(150);
-
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
WM8994_LINEOUT1N_ENA |
WM8994_LINEOUT1P_ENA |
WM8994_LINEOUT2N_ENA |
WM8994_LINEOUT2P_ENA, 0);
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
- WM8994_VROI, 0);
-
/* Switch off startup biases */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_BIAS_SRC |
@@ -976,10 +964,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_VMID_RAMP_MASK, 0);
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
-
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM8994_VMID_RAMP_MASK, 0);
+ WM8994_VMID_SEL_MASK, 0);
}
pm_runtime_put(codec->dev);
@@ -2277,6 +2262,18 @@ out:
configure_clock(codec);
+ /*
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+ * for detection.
+ */
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
+ }
+
return 0;
}
@@ -2365,6 +2362,18 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
configure_clock(codec);
+ /*
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+ * for detection.
+ */
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
+ }
+
return 0;
}
@@ -3082,7 +3091,8 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
{
struct snd_soc_codec *codec = wm8994->hubs.codec;
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
struct snd_kcontrol_new controls[] = {
SOC_ENUM_EXT("AIF1.1 EQ Mode",
wm8994->retune_mobile_enum,
@@ -3149,7 +3159,8 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
{
struct snd_soc_codec *codec = wm8994->hubs.codec;
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int ret, i;
if (!pdata)
@@ -3389,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
return IRQ_HANDLED;
}
-/* Default microphone detection handler for WM8958 - the user can
- * override this if they wish.
- */
-static void wm8958_default_micdet(u16 status, void *data)
+static void wm1811_micd_stop(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ if (!wm8994->jackdet)
+ return;
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0);
+
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ if (wm8994->wm8994->pdata.jd_ext_cap)
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS2");
+}
+
+static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
{
- struct snd_soc_codec *codec = data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int report;
- dev_dbg(codec->dev, "MICDET %x\n", status);
+ report = 0;
+ if (status & 0x4)
+ report |= SND_JACK_BTN_0;
+
+ if (status & 0x8)
+ report |= SND_JACK_BTN_1;
+
+ if (status & 0x10)
+ report |= SND_JACK_BTN_2;
+
+ if (status & 0x20)
+ report |= SND_JACK_BTN_3;
+
+ if (status & 0x40)
+ report |= SND_JACK_BTN_4;
+
+ if (status & 0x80)
+ report |= SND_JACK_BTN_5;
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, report,
+ wm8994->btn_mask);
+}
+
+static void wm8958_mic_id(void *data, u16 status)
+{
+ struct snd_soc_codec *codec = data;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
/* Either nothing present or just starting detection */
if (!(status & WM8958_MICD_STS)) {
- if (!wm8994->jackdet) {
- /* If nothing present then clear our statuses */
- dev_dbg(codec->dev, "Detected open circuit\n");
- wm8994->jack_mic = false;
- wm8994->mic_detecting = true;
+ /* If nothing present then clear our statuses */
+ dev_dbg(codec->dev, "Detected open circuit\n");
+ wm8994->jack_mic = false;
+ wm8994->mic_detecting = true;
- wm8958_micd_set_rate(codec);
+ wm1811_micd_stop(codec);
- snd_soc_jack_report(wm8994->micdet[0].jack, 0,
- wm8994->btn_mask |
- SND_JACK_HEADSET);
- }
+ wm8958_micd_set_rate(codec);
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+ wm8994->btn_mask |
+ SND_JACK_HEADSET);
return;
}
/* If the measurement is showing a high impedence we've got a
* microphone.
*/
- if (wm8994->mic_detecting && (status & 0x600)) {
+ if (status & 0x600) {
dev_dbg(codec->dev, "Detected microphone\n");
wm8994->mic_detecting = false;
@@ -3433,64 +3486,67 @@ static void wm8958_default_micdet(u16 status, void *data)
}
- if (wm8994->mic_detecting && status & 0xfc) {
+ if (status & 0xfc) {
dev_dbg(codec->dev, "Detected headphone\n");
wm8994->mic_detecting = false;
wm8958_micd_set_rate(codec);
/* If we have jackdet that will detect removal */
- if (wm8994->jackdet) {
- mutex_lock(&wm8994->accdet_lock);
-
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, 0);
-
- wm1811_jackdet_set_mode(codec,
- WM1811_JACKDET_MODE_JACK);
-
- mutex_unlock(&wm8994->accdet_lock);
-
- if (wm8994->pdata->jd_ext_cap)
- snd_soc_dapm_disable_pin(&codec->dapm,
- "MICBIAS2");
- }
+ wm1811_micd_stop(codec);
snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
SND_JACK_HEADSET);
}
+}
- /* Report short circuit as a button */
- if (wm8994->jack_mic) {
- report = 0;
- if (status & 0x4)
- report |= SND_JACK_BTN_0;
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+ struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+ mic_work.work);
+ struct wm8994 *control = wm8994->wm8994;
+ struct snd_soc_codec *codec = wm8994->hubs.codec;
- if (status & 0x8)
- report |= SND_JACK_BTN_1;
+ pm_runtime_get_sync(codec->dev);
- if (status & 0x10)
- report |= SND_JACK_BTN_2;
+ /* If required for an external cap force MICBIAS on */
+ if (control->pdata.jd_ext_cap) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ }
- if (status & 0x20)
- report |= SND_JACK_BTN_3;
+ mutex_lock(&wm8994->accdet_lock);
- if (status & 0x40)
- report |= SND_JACK_BTN_4;
+ dev_dbg(codec->dev, "Starting mic detection\n");
- if (status & 0x80)
- report |= SND_JACK_BTN_5;
+ /* Use a user-supplied callback if we have one */
+ if (wm8994->micd_cb) {
+ wm8994->micd_cb(wm8994->micd_cb_data);
+ } else {
+ /*
+ * Start off measument of microphone impedence to find out
+ * what's actually there.
+ */
+ wm8994->mic_detecting = true;
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
- snd_soc_jack_report(wm8994->micdet[0].jack, report,
- wm8994->btn_mask);
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
}
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ pm_runtime_put(codec->dev);
}
static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
{
struct wm8994_priv *wm8994 = data;
+ struct wm8994 *control = wm8994->wm8994;
struct snd_soc_codec *codec = wm8994->hubs.codec;
- int reg;
+ int reg, delay;
bool present;
pm_runtime_get_sync(codec->dev);
@@ -3521,18 +3577,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
WM1811_JACKDET_DB, 0);
- /*
- * Start off measument of microphone impedence to find
- * out what's actually there.
- */
- wm8994->mic_detecting = true;
- wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, WM8958_MICD_ENA);
+ delay = control->pdata.micdet_delay;
+ schedule_delayed_work(&wm8994->mic_work,
+ msecs_to_jiffies(delay));
} else {
dev_dbg(codec->dev, "Jack not detected\n");
+ cancel_delayed_work_sync(&wm8994->mic_work);
+
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
@@ -3549,14 +3601,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
mutex_unlock(&wm8994->accdet_lock);
- /* If required for an external cap force MICBIAS on */
- if (wm8994->pdata->jd_ext_cap) {
- if (present)
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "MICBIAS2");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
- }
+ /* Turn off MICBIAS if it was on for an external cap */
+ if (control->pdata.jd_ext_cap && !present)
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
if (present)
snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3599,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work)
* detection algorithm.
*/
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data)
+ wm1811_micdet_cb det_cb, void *det_cb_data,
+ wm1811_mic_id_cb id_cb, void *id_cb_data)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
@@ -3614,27 +3662,32 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
}
if (jack) {
- if (!cb) {
- dev_dbg(codec->dev, "Using default micdet callback\n");
- cb = wm8958_default_micdet;
- cb_data = codec;
- }
-
snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
snd_soc_dapm_sync(&codec->dapm);
wm8994->micdet[0].jack = jack;
- wm8994->jack_cb = cb;
- wm8994->jack_cb_data = cb_data;
- wm8994->mic_detecting = true;
- wm8994->jack_mic = false;
+ if (det_cb) {
+ wm8994->micd_cb = det_cb;
+ wm8994->micd_cb_data = det_cb_data;
+ } else {
+ wm8994->mic_detecting = true;
+ wm8994->jack_mic = false;
+ }
+
+ if (id_cb) {
+ wm8994->mic_id_cb = id_cb;
+ wm8994->mic_id_cb_data = id_cb_data;
+ } else {
+ wm8994->mic_id_cb = wm8958_mic_id;
+ wm8994->mic_id_cb_data = codec;
+ }
wm8958_micd_set_rate(codec);
/* Detect microphones and short circuits by default */
- if (wm8994->pdata->micd_lvl_sel)
- micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+ if (control->pdata.micd_lvl_sel)
+ micd_lvl_sel = control->pdata.micd_lvl_sel;
else
micd_lvl_sel = 0x41;
@@ -3728,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
trace_snd_soc_jack_irq(dev_name(codec->dev));
#endif
- if (wm8994->jack_cb)
- wm8994->jack_cb(reg, wm8994->jack_cb_data);
+ /* Avoid a transient report when the accessory is being removed */
+ if (wm8994->jackdet) {
+ reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+ if (reg < 0) {
+ dev_err(codec->dev, "Failed to read jack status: %d\n",
+ reg);
+ } else if (!(reg & WM1811_JACKDET_LVL)) {
+ dev_dbg(codec->dev, "Ignoring removed jack\n");
+ return IRQ_HANDLED;
+ }
+ }
+
+ if (wm8994->mic_detecting)
+ wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg);
else
- dev_warn(codec->dev, "Accessory detection with no callback\n");
+ wm8958_button_det(codec, reg);
out:
pm_runtime_put(codec->dev);
@@ -3779,15 +3844,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
mutex_init(&wm8994->accdet_lock);
- INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
wm1811_jackdet_bootstrap);
+ switch (control->type) {
+ case WM8994:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+ break;
+ case WM1811:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+ break;
+ default:
+ break;
+ }
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
init_completion(&wm8994->fll_locked[i]);
- if (wm8994->pdata && wm8994->pdata->micdet_irq)
- wm8994->micdet_irq = wm8994->pdata->micdet_irq;
+ wm8994->micdet_irq = control->pdata.micdet_irq;
pm_runtime_enable(codec->dev);
pm_runtime_idle(codec->dev);
@@ -3800,8 +3874,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
switch (control->type) {
case WM8994:
/* Single ended line outputs should have VMID on. */
- if (!wm8994->pdata->lineout1_diff ||
- !wm8994->pdata->lineout2_diff)
+ if (!control->pdata.lineout1_diff ||
+ !control->pdata.lineout2_diff)
codec->dapm.idle_bias_off = 0;
switch (wm8994->revision) {
@@ -3839,20 +3913,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->hubs.no_cache_dac_hp_direct = true;
wm8994->fll_byp = true;
- switch (control->cust_id) {
- case 0:
- case 2:
- wm8994->hubs.dcs_codes_l = -9;
- wm8994->hubs.dcs_codes_r = -7;
- break;
- case 1:
- case 3:
- wm8994->hubs.dcs_codes_l = -8;
- wm8994->hubs.dcs_codes_r = -7;
- break;
- default:
- break;
- }
+ wm8994->hubs.dcs_codes_l = -9;
+ wm8994->hubs.dcs_codes_r = -7;
snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
@@ -4225,7 +4287,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.set_bias_level = wm8994_set_bias_level,
};
-static int __devinit wm8994_probe(struct platform_device *pdev)
+static int wm8994_probe(struct platform_device *pdev)
{
struct wm8994_priv *wm8994;
@@ -4236,13 +4298,12 @@ static int __devinit wm8994_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, wm8994);
wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
- wm8994->pdata = dev_get_platdata(pdev->dev.parent);
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
-static int __devexit wm8994_remove(struct platform_device *pdev)
+static int wm8994_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -4266,7 +4327,7 @@ static int wm8994_resume(struct device *dev)
{
struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
- if (wm8994->jackdet && wm8994->jack_cb)
+ if (wm8994->jackdet && wm8994->jackdet_mode)
regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK,
WM1811_JACKDET_MODE_AUDIO);
@@ -4286,7 +4347,7 @@ static struct platform_driver wm8994_codec_driver = {
.pm = &wm8994_pm_ops,
},
.probe = wm8994_probe,
- .remove = __devexit_p(wm8994_remove),
+ .remove = wm8994_remove,
};
module_platform_driver(wm8994_codec_driver);
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index ccbce5791e95..45f192702024 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -39,12 +39,14 @@ enum wm8994_vmid_mode {
WM8994_VMID_FORCE,
};
-typedef void (*wm8958_micdet_cb)(u16 status, void *data);
+typedef void (*wm1811_micdet_cb)(void *data);
+typedef void (*wm1811_mic_id_cb)(void *data, u16 status);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
int micbias);
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data);
+ wm1811_micdet_cb cb, void *det_cb_data,
+ wm1811_mic_id_cb id_cb, void *id_cb_data);
int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
@@ -138,12 +140,13 @@ struct wm8994_priv {
int jackdet_mode;
struct delayed_work jackdet_bootstrap;
- wm8958_micdet_cb jack_cb;
- void *jack_cb_data;
int micdet_irq;
+ wm1811_micdet_cb micd_cb;
+ void *micd_cb_data;
+ wm1811_mic_id_cb mic_id_cb;
+ void *mic_id_cb_data;
int revision;
- struct wm8994_pdata *pdata;
unsigned int aif1clk_enable:1;
unsigned int aif2clk_enable:1;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 28c89b094c6e..90a65c427541 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2256,46 +2256,33 @@ static struct regmap_config wm8995_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8995_spi_probe(struct spi_device *spi)
+static int wm8995_spi_probe(struct spi_device *spi)
{
struct wm8995_priv *wm8995;
int ret;
- wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+ wm8995 = devm_kzalloc(&spi->dev, sizeof(*wm8995), GFP_KERNEL);
if (!wm8995)
return -ENOMEM;
spi_set_drvdata(spi, wm8995);
- wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+ wm8995->regmap = devm_regmap_init_spi(spi, &wm8995_regmap);
if (IS_ERR(wm8995->regmap)) {
ret = PTR_ERR(wm8995->regmap);
dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
- goto err_alloc;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
- if (ret < 0)
- goto err_regmap;
-
- return ret;
-
-err_regmap:
- regmap_exit(wm8995->regmap);
-err_alloc:
- kfree(wm8995);
-
return ret;
}
-static int __devexit wm8995_spi_remove(struct spi_device *spi)
+static int wm8995_spi_remove(struct spi_device *spi)
{
- struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8995->regmap);
- kfree(wm8995);
return 0;
}
@@ -2305,55 +2292,42 @@ static struct spi_driver wm8995_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8995_spi_probe,
- .remove = __devexit_p(wm8995_spi_remove)
+ .remove = wm8995_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8995_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8995_priv *wm8995;
int ret;
- wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+ wm8995 = devm_kzalloc(&i2c->dev, sizeof(*wm8995), GFP_KERNEL);
if (!wm8995)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8995);
- wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+ wm8995->regmap = devm_regmap_init_i2c(i2c, &wm8995_regmap);
if (IS_ERR(wm8995->regmap)) {
ret = PTR_ERR(wm8995->regmap);
dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
- goto err_alloc;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
-
- return ret;
-
-err_regmap:
- regmap_exit(wm8995->regmap);
-err_alloc:
- kfree(wm8995);
return ret;
}
-static __devexit int wm8995_i2c_remove(struct i2c_client *client)
+static int wm8995_i2c_remove(struct i2c_client *client)
{
- struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8995->regmap);
- kfree(wm8995);
return 0;
}
@@ -2370,7 +2344,7 @@ static struct i2c_driver wm8995_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8995_i2c_probe,
- .remove = __devexit_p(wm8995_i2c_remove),
+ .remove = wm8995_i2c_remove,
.id_table = wm8995_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 6dcb02c3666f..46fe83d2b224 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -2765,8 +2765,8 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
},
};
-static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8996_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8996_priv *wm8996;
int ret, i;
@@ -3077,7 +3077,7 @@ err:
return ret;
}
-static __devexit int wm8996_i2c_remove(struct i2c_client *client)
+static int wm8996_i2c_remove(struct i2c_client *client)
{
struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
int i;
@@ -3107,7 +3107,7 @@ static struct i2c_driver wm8996_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8996_i2c_probe,
- .remove = __devexit_p(wm8996_i2c_remove),
+ .remove = wm8996_i2c_remove,
.id_table = wm8996_i2c_id,
};
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 2de74e1ea225..630b3d776ec2 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1327,8 +1327,8 @@ static const struct regmap_config wm9081_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm9081_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm9081_priv *wm9081;
unsigned int reg;
@@ -1341,28 +1341,27 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm9081);
- wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+ wm9081->regmap = devm_regmap_init_i2c(i2c, &wm9081_regmap);
if (IS_ERR(wm9081->regmap)) {
ret = PTR_ERR(wm9081->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
- goto err;
+ return ret;
}
ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
- goto err_regmap;
+ return ret;
}
if (reg != 0x9081) {
dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
- ret = -EINVAL;
- goto err_regmap;
+ return -EINVAL;
}
ret = wm9081_reset(wm9081->regmap);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
- goto err_regmap;
+ return ret;
}
if (dev_get_platdata(&i2c->dev))
@@ -1382,23 +1381,14 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9081, &wm9081_dai, 1);
if (ret < 0)
- goto err_regmap;
+ return ret;
return 0;
-
-err_regmap:
- regmap_exit(wm9081->regmap);
-err:
-
- return ret;
}
-static __devexit int wm9081_i2c_remove(struct i2c_client *client)
+static int wm9081_i2c_remove(struct i2c_client *client)
{
- struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm9081->regmap);
return 0;
}
@@ -1414,7 +1404,7 @@ static struct i2c_driver wm9081_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm9081_i2c_probe,
- .remove = __devexit_p(wm9081_i2c_remove),
+ .remove = wm9081_i2c_remove,
.id_table = wm9081_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index c7ddc56175d1..a07fe1618eec 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -628,7 +628,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
- wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+ wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap);
if (IS_ERR(wm9090->regmap)) {
ret = PTR_ERR(wm9090->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -637,16 +637,16 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
if (ret < 0)
- goto err;
+ return ret;
+
if (reg != 0x9093) {
dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
- ret = -ENODEV;
- goto err;
+ return -ENODEV;
}
ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
if (ret < 0)
- goto err;
+ return ret;
if (i2c->dev.platform_data)
memcpy(&wm9090->pdata, i2c->dev.platform_data,
@@ -658,23 +658,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
&soc_codec_dev_wm9090, NULL, 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err;
+ return ret;
}
return 0;
-
-err:
- regmap_exit(wm9090->regmap);
- return ret;
}
-static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
+static int wm9090_i2c_remove(struct i2c_client *i2c)
{
- struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm9090->regmap);
-
return 0;
}
@@ -691,7 +683,7 @@ static struct i2c_driver wm9090_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm9090_i2c_probe,
- .remove = __devexit_p(wm9090_i2c_remove),
+ .remove = wm9090_i2c_remove,
.id_table = wm9090_id,
};
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index e8e782a0c78d..05b1f346695b 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -382,13 +382,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
.num_dapm_routes = ARRAY_SIZE(wm9705_audio_map),
};
-static __devinit int wm9705_probe(struct platform_device *pdev)
+static int wm9705_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
}
-static int __devexit wm9705_remove(struct platform_device *pdev)
+static int wm9705_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -401,7 +401,7 @@ static struct platform_driver wm9705_codec_driver = {
},
.probe = wm9705_probe,
- .remove = __devexit_p(wm9705_remove),
+ .remove = wm9705_remove,
};
module_platform_driver(wm9705_codec_driver);
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 4dd73ea08d0b..8e9a6a3eeb1a 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -685,13 +685,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
.num_dapm_routes = ARRAY_SIZE(wm9712_audio_map),
};
-static __devinit int wm9712_probe(struct platform_device *pdev)
+static int wm9712_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
}
-static int __devexit wm9712_remove(struct platform_device *pdev)
+static int wm9712_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -704,7 +704,7 @@ static struct platform_driver wm9712_codec_driver = {
},
.probe = wm9712_probe,
- .remove = __devexit_p(wm9712_remove),
+ .remove = wm9712_remove,
};
module_platform_driver(wm9712_codec_driver);
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 3eb19fb71d17..f7afa68d8c7f 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1254,13 +1254,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
.num_dapm_routes = ARRAY_SIZE(wm9713_audio_map),
};
-static __devinit int wm9713_probe(struct platform_device *pdev)
+static int wm9713_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
}
-static int __devexit wm9713_remove(struct platform_device *pdev)
+static int wm9713_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1273,7 +1273,7 @@ static struct platform_driver wm9713_codec_driver = {
},
.probe = wm9713_probe,
- .remove = __devexit_p(wm9713_remove),
+ .remove = wm9713_remove,
};
module_platform_driver(wm9713_codec_driver);
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
new file mode 100644
index 000000000000..ffc89fab96fb
--- /dev/null
+++ b/sound/soc/codecs/wm_adsp.c
@@ -0,0 +1,699 @@
+/*
+ * wm_adsp.c -- Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/registers.h>
+
+#include "wm_adsp.h"
+
+#define adsp_crit(_dsp, fmt, ...) \
+ dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_err(_dsp, fmt, ...) \
+ dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_warn(_dsp, fmt, ...) \
+ dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_info(_dsp, fmt, ...) \
+ dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_dbg(_dsp, fmt, ...) \
+ dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+
+#define ADSP1_CONTROL_1 0x00
+#define ADSP1_CONTROL_2 0x02
+#define ADSP1_CONTROL_3 0x03
+#define ADSP1_CONTROL_4 0x04
+#define ADSP1_CONTROL_5 0x06
+#define ADSP1_CONTROL_6 0x07
+#define ADSP1_CONTROL_7 0x08
+#define ADSP1_CONTROL_8 0x09
+#define ADSP1_CONTROL_9 0x0A
+#define ADSP1_CONTROL_10 0x0B
+#define ADSP1_CONTROL_11 0x0C
+#define ADSP1_CONTROL_12 0x0D
+#define ADSP1_CONTROL_13 0x0F
+#define ADSP1_CONTROL_14 0x10
+#define ADSP1_CONTROL_15 0x11
+#define ADSP1_CONTROL_16 0x12
+#define ADSP1_CONTROL_17 0x13
+#define ADSP1_CONTROL_18 0x14
+#define ADSP1_CONTROL_19 0x16
+#define ADSP1_CONTROL_20 0x17
+#define ADSP1_CONTROL_21 0x18
+#define ADSP1_CONTROL_22 0x1A
+#define ADSP1_CONTROL_23 0x1B
+#define ADSP1_CONTROL_24 0x1C
+#define ADSP1_CONTROL_25 0x1E
+#define ADSP1_CONTROL_26 0x20
+#define ADSP1_CONTROL_27 0x21
+#define ADSP1_CONTROL_28 0x22
+#define ADSP1_CONTROL_29 0x23
+#define ADSP1_CONTROL_30 0x24
+#define ADSP1_CONTROL_31 0x26
+
+/*
+ * ADSP1 Control 19
+ */
+#define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+
+/*
+ * ADSP1 Control 30
+ */
+#define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define ADSP1_START 0x0001 /* DSP1_START */
+#define ADSP1_START_MASK 0x0001 /* DSP1_START */
+#define ADSP1_START_SHIFT 0 /* DSP1_START */
+#define ADSP1_START_WIDTH 1 /* DSP1_START */
+
+#define ADSP2_CONTROL 0
+#define ADSP2_CLOCKING 1
+#define ADSP2_STATUS1 4
+
+/*
+ * ADSP2 Control
+ */
+
+#define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */
+#define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define ADSP2_START 0x0001 /* DSP1_START */
+#define ADSP2_START_MASK 0x0001 /* DSP1_START */
+#define ADSP2_START_SHIFT 0 /* DSP1_START */
+#define ADSP2_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * ADSP2 clocking
+ */
+#define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */
+
+/*
+ * ADSP2 Status 1
+ */
+#define ADSP2_RAM_RDY 0x0001
+#define ADSP2_RAM_RDY_MASK 0x0001
+#define ADSP2_RAM_RDY_SHIFT 0
+#define ADSP2_RAM_RDY_WIDTH 1
+
+
+static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
+ int type)
+{
+ int i;
+
+ for (i = 0; i < dsp->num_mems; i++)
+ if (dsp->mem[i].type == type)
+ return &dsp->mem[i];
+
+ return NULL;
+}
+
+static int wm_adsp_load(struct wm_adsp *dsp)
+{
+ const struct firmware *firmware;
+ struct regmap *regmap = dsp->regmap;
+ unsigned int pos = 0;
+ const struct wmfw_header *header;
+ const struct wmfw_adsp1_sizes *adsp1_sizes;
+ const struct wmfw_adsp2_sizes *adsp2_sizes;
+ const struct wmfw_footer *footer;
+ const struct wmfw_region *region;
+ const struct wm_adsp_region *mem;
+ const char *region_name;
+ char *file, *text;
+ unsigned int reg;
+ int regions = 0;
+ int ret, offset, type, sizes;
+
+ file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (file == NULL)
+ return -ENOMEM;
+
+ snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+ file[PAGE_SIZE - 1] = '\0';
+
+ ret = request_firmware(&firmware, file, dsp->dev);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to request '%s'\n", file);
+ goto out;
+ }
+ ret = -EINVAL;
+
+ pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+ if (pos >= firmware->size) {
+ adsp_err(dsp, "%s: file too short, %zu bytes\n",
+ file, firmware->size);
+ goto out_fw;
+ }
+
+ header = (void*)&firmware->data[0];
+
+ if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+ adsp_err(dsp, "%s: invalid magic\n", file);
+ goto out_fw;
+ }
+
+ if (header->ver != 0) {
+ adsp_err(dsp, "%s: unknown file format %d\n",
+ file, header->ver);
+ goto out_fw;
+ }
+
+ if (header->core != dsp->type) {
+ adsp_err(dsp, "%s: invalid core %d != %d\n",
+ file, header->core, dsp->type);
+ goto out_fw;
+ }
+
+ switch (dsp->type) {
+ case WMFW_ADSP1:
+ pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+ adsp1_sizes = (void *)&(header[1]);
+ footer = (void *)&(adsp1_sizes[1]);
+ sizes = sizeof(*adsp1_sizes);
+
+ adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
+ file, le32_to_cpu(adsp1_sizes->dm),
+ le32_to_cpu(adsp1_sizes->pm),
+ le32_to_cpu(adsp1_sizes->zm));
+ break;
+
+ case WMFW_ADSP2:
+ pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
+ adsp2_sizes = (void *)&(header[1]);
+ footer = (void *)&(adsp2_sizes[1]);
+ sizes = sizeof(*adsp2_sizes);
+
+ adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
+ file, le32_to_cpu(adsp2_sizes->xm),
+ le32_to_cpu(adsp2_sizes->ym),
+ le32_to_cpu(adsp2_sizes->pm),
+ le32_to_cpu(adsp2_sizes->zm));
+ break;
+
+ default:
+ BUG_ON(NULL == "Unknown DSP type");
+ goto out_fw;
+ }
+
+ if (le32_to_cpu(header->len) != sizeof(*header) +
+ sizes + sizeof(*footer)) {
+ adsp_err(dsp, "%s: unexpected header length %d\n",
+ file, le32_to_cpu(header->len));
+ goto out_fw;
+ }
+
+ adsp_dbg(dsp, "%s: timestamp %llu\n", file,
+ le64_to_cpu(footer->timestamp));
+
+ while (pos < firmware->size &&
+ pos - firmware->size > sizeof(*region)) {
+ region = (void *)&(firmware->data[pos]);
+ region_name = "Unknown";
+ reg = 0;
+ text = NULL;
+ offset = le32_to_cpu(region->offset) & 0xffffff;
+ type = be32_to_cpu(region->type) & 0xff;
+ mem = wm_adsp_find_region(dsp, type);
+
+ switch (type) {
+ case WMFW_NAME_TEXT:
+ region_name = "Firmware name";
+ text = kzalloc(le32_to_cpu(region->len) + 1,
+ GFP_KERNEL);
+ break;
+ case WMFW_INFO_TEXT:
+ region_name = "Information";
+ text = kzalloc(le32_to_cpu(region->len) + 1,
+ GFP_KERNEL);
+ break;
+ case WMFW_ABSOLUTE:
+ region_name = "Absolute";
+ reg = offset;
+ break;
+ case WMFW_ADSP1_PM:
+ BUG_ON(!mem);
+ region_name = "PM";
+ reg = mem->base + (offset * 3);
+ break;
+ case WMFW_ADSP1_DM:
+ BUG_ON(!mem);
+ region_name = "DM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP2_XM:
+ BUG_ON(!mem);
+ region_name = "XM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP2_YM:
+ BUG_ON(!mem);
+ region_name = "YM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP1_ZM:
+ BUG_ON(!mem);
+ region_name = "ZM";
+ reg = mem->base + (offset * 2);
+ break;
+ default:
+ adsp_warn(dsp,
+ "%s.%d: Unknown region type %x at %d(%x)\n",
+ file, regions, type, pos, pos);
+ break;
+ }
+
+ adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
+ regions, le32_to_cpu(region->len), offset,
+ region_name);
+
+ if (text) {
+ memcpy(text, region->data, le32_to_cpu(region->len));
+ adsp_info(dsp, "%s: %s\n", file, text);
+ kfree(text);
+ }
+
+ if (reg) {
+ ret = regmap_raw_write(regmap, reg, region->data,
+ le32_to_cpu(region->len));
+ if (ret != 0) {
+ adsp_err(dsp,
+ "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+ file, regions,
+ le32_to_cpu(region->len), offset,
+ region_name, ret);
+ goto out_fw;
+ }
+ }
+
+ pos += le32_to_cpu(region->len) + sizeof(*region);
+ regions++;
+ }
+
+ if (pos > firmware->size)
+ adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+ file, regions, pos - firmware->size);
+
+out_fw:
+ release_firmware(firmware);
+out:
+ kfree(file);
+
+ return ret;
+}
+
+static int wm_adsp_load_coeff(struct wm_adsp *dsp)
+{
+ struct regmap *regmap = dsp->regmap;
+ struct wmfw_coeff_hdr *hdr;
+ struct wmfw_coeff_item *blk;
+ const struct firmware *firmware;
+ const char *region_name;
+ int ret, pos, blocks, type, offset, reg;
+ char *file;
+
+ file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (file == NULL)
+ return -ENOMEM;
+
+ snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+ file[PAGE_SIZE - 1] = '\0';
+
+ ret = request_firmware(&firmware, file, dsp->dev);
+ if (ret != 0) {
+ adsp_warn(dsp, "Failed to request '%s'\n", file);
+ ret = 0;
+ goto out;
+ }
+ ret = -EINVAL;
+
+ if (sizeof(*hdr) >= firmware->size) {
+ adsp_err(dsp, "%s: file too short, %zu bytes\n",
+ file, firmware->size);
+ goto out_fw;
+ }
+
+ hdr = (void*)&firmware->data[0];
+ if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+ adsp_err(dsp, "%s: invalid magic\n", file);
+ return -EINVAL;
+ }
+
+ adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
+ (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+ (le32_to_cpu(hdr->ver) >> 8) & 0xff,
+ le32_to_cpu(hdr->ver) & 0xff);
+
+ pos = le32_to_cpu(hdr->len);
+
+ blocks = 0;
+ while (pos < firmware->size &&
+ pos - firmware->size > sizeof(*blk)) {
+ blk = (void*)(&firmware->data[pos]);
+
+ type = be32_to_cpu(blk->type) & 0xff;
+ offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+ adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
+ file, blocks, le32_to_cpu(blk->id),
+ (le32_to_cpu(blk->ver) >> 16) & 0xff,
+ (le32_to_cpu(blk->ver) >> 8) & 0xff,
+ le32_to_cpu(blk->ver) & 0xff);
+ adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
+ file, blocks, le32_to_cpu(blk->len), offset, type);
+
+ reg = 0;
+ region_name = "Unknown";
+ switch (type) {
+ case WMFW_NAME_TEXT:
+ case WMFW_INFO_TEXT:
+ break;
+ case WMFW_ABSOLUTE:
+ region_name = "register";
+ reg = offset;
+ break;
+ default:
+ adsp_err(dsp, "Unknown region type %x\n", type);
+ break;
+ }
+
+ if (reg) {
+ ret = regmap_raw_write(regmap, reg, blk->data,
+ le32_to_cpu(blk->len));
+ if (ret != 0) {
+ adsp_err(dsp,
+ "%s.%d: Failed to write to %x in %s\n",
+ file, blocks, reg, region_name);
+ }
+ }
+
+ pos += le32_to_cpu(blk->len) + sizeof(*blk);
+ blocks++;
+ }
+
+ if (pos > firmware->size)
+ adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+ file, blocks, pos - firmware->size);
+
+out_fw:
+ release_firmware(firmware);
+out:
+ kfree(file);
+ return 0;
+}
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ struct wm_adsp *dsp = &dsps[w->shift];
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, ADSP1_SYS_ENA);
+
+ ret = wm_adsp_load(dsp);
+ if (ret != 0)
+ goto err;
+
+ ret = wm_adsp_load_coeff(dsp);
+ if (ret != 0)
+ goto err;
+
+ /* Start the core running */
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_CORE_ENA | ADSP1_START,
+ ADSP1_CORE_ENA | ADSP1_START);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Halt the core */
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_CORE_ENA | ADSP1_START, 0);
+
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
+ ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+
+err:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_event);
+
+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);
+ if (ret != 0)
+ return ret;
+
+ /* Wait for the RAM to start, should be near instantaneous */
+ count = 0;
+ do {
+ ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
+ &val);
+ if (ret != 0)
+ return ret;
+ } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+ if (!(val & ADSP2_RAM_RDY)) {
+ adsp_err(dsp, "Failed to start DSP RAM\n");
+ return -EBUSY;
+ }
+
+ adsp_dbg(dsp, "RAM ready after %d polls\n", count);
+ adsp_info(dsp, "RAM ready after %d polls\n", count);
+
+ return 0;
+}
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ struct wm_adsp *dsp = &dsps[w->shift];
+ unsigned int val;
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * For simplicity set the DSP clock rate to be the
+ * SYSCLK rate rather than making it configurable.
+ */
+ ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+ ret);
+ return ret;
+ }
+ 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);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to set clock rate: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (dsp->dvfs) {
+ ret = regmap_read(dsp->regmap,
+ dsp->base + ADSP2_CLOCKING, &val);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to read clocking: %d\n", ret);
+ return ret;
+ }
+
+ if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+ ret = regulator_enable(dsp->dvfs);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to enable supply: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(dsp->dvfs,
+ 1800000,
+ 1800000);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to raise supply: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ ret = wm_adsp2_ena(dsp);
+ if (ret != 0)
+ return ret;
+
+ ret = wm_adsp_load(dsp);
+ if (ret != 0)
+ goto err;
+
+ ret = wm_adsp_load_coeff(dsp);
+ 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);
+ if (ret != 0)
+ goto err;
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA | ADSP2_CORE_ENA |
+ ADSP2_START, 0);
+
+ if (dsp->dvfs) {
+ ret = regulator_set_voltage(dsp->dvfs, 1200000,
+ 1800000);
+ if (ret != 0)
+ dev_warn(dsp->dev,
+ "Failed to lower supply: %d\n",
+ ret);
+
+ ret = regulator_disable(dsp->dvfs);
+ if (ret != 0)
+ dev_err(dsp->dev,
+ "Failed to enable supply: %d\n",
+ ret);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+err:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_event);
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
+{
+ int ret;
+
+ /*
+ * Disable the DSP memory by default when in reset for a small
+ * power saving.
+ */
+ ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
+ ADSP2_MEM_ENA, 0);
+ if (ret != 0) {
+ adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
+ return ret;
+ }
+
+ if (dvfs) {
+ adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
+ if (IS_ERR(adsp->dvfs)) {
+ ret = PTR_ERR(adsp->dvfs);
+ dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_enable(adsp->dvfs);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_disable(adsp->dvfs);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
new file mode 100644
index 000000000000..ffd29a4609e2
--- /dev/null
+++ b/sound/soc/codecs/wm_adsp.h
@@ -0,0 +1,59 @@
+/*
+ * wm_adsp.h -- Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WM_ADSP_H
+#define __WM_ADSP_H
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wmfw.h"
+
+struct regulator;
+
+struct wm_adsp_region {
+ int type;
+ unsigned int base;
+};
+
+struct wm_adsp {
+ const char *part;
+ int num;
+ int type;
+ struct device *dev;
+ struct regmap *regmap;
+
+ int base;
+
+ const struct wm_adsp_region *mem;
+ int num_mems;
+
+ struct regulator *dvfs;
+};
+
+#define WM_ADSP1(wname, num) \
+ { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+ .shift = num, .event = wm_adsp1_event, \
+ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+#define WM_ADSP2(wname, num) \
+{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+ .shift = num, .event = wm_adsp2_event, \
+ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+
+#endif
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644
index 000000000000..5632ded67fdd
--- /dev/null
+++ b/sound/soc/codecs/wmfw.h
@@ -0,0 +1,128 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+ char magic[4];
+ __le32 len;
+ __le16 rev;
+ u8 core;
+ u8 ver;
+} __packed;
+
+struct wmfw_footer {
+ __le64 timestamp;
+ __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+ __le32 dm;
+ __le32 pm;
+ __le32 zm;
+} __packed;
+
+struct wmfw_adsp2_sizes {
+ __le32 xm;
+ __le32 ym;
+ __le32 pm;
+ __le32 zm;
+} __packed;
+
+struct wmfw_region {
+ union {
+ __be32 type;
+ __le32 offset;
+ };
+ __le32 len;
+ u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+ __be32 core_id;
+ __be32 core_rev;
+ __be32 id;
+ __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+ struct wmfw_id_hdr fw;
+ __be32 zm;
+ __be32 dm;
+ __be32 algs;
+} __packed;
+
+struct wmfw_adsp2_id_hdr {
+ struct wmfw_id_hdr fw;
+ __be32 zm;
+ __be32 xm;
+ __be32 ym;
+ __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+ __be32 id;
+ __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+ struct wmfw_alg_hdr alg;
+ __be32 zm;
+ __be32 dm;
+} __packed;
+
+struct wmfw_adsp2_alg_hdr {
+ struct wmfw_alg_hdr alg;
+ __be32 zm;
+ __be32 xm;
+ __be32 ym;
+} __packed;
+
+struct wmfw_coeff_hdr {
+ u8 magic[4];
+ __le32 len;
+ __le32 ver;
+ u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+ union {
+ __be32 type;
+ __le32 offset;
+ };
+ __le32 id;
+ __le32 ver;
+ __le32 sr;
+ __le32 len;
+ u8 data[];
+} __packed;
+
+#define WMFW_ADSP1 1
+#define WMFW_ADSP2 2
+
+#define WMFW_ABSOLUTE 0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#define WMFW_ADSP2_PM 2
+#define WMFW_ADSP2_ZM 4
+#define WMFW_ADSP2_XM 5
+#define WMFW_ADSP2_YM 6
+
+#endif
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 6fac5af13298..d55e6477bff0 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
+ /* set the CPU system clock */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
return 0;
}
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 714e51e5be5b..55e2bf652bef 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -199,6 +199,7 @@
#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
@@ -207,6 +208,7 @@
#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
@@ -215,6 +217,7 @@
#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
@@ -223,6 +226,7 @@
#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
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
void __iomem *base = dev->base;
+ 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);
+ 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);
+
+ /* 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));
+ break;
+ }
+
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
- mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
- ACLKX | AHCLKX | AFSX);
+ mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
break;
case SND_SOC_DAIFMT_CBM_CFS:
/* codec is clock master and frame slave */
@@ -554,59 +574,75 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return 0;
}
-static int davinci_config_channel_size(struct davinci_audio_dev *dev,
- int channel_size)
+static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
{
- u32 fmt = 0;
- u32 mask, rotate;
-
- switch (channel_size) {
- case DAVINCI_AUDIO_WORD_8:
- fmt = 0x03;
- rotate = 6;
- mask = 0x000000ff;
- break;
+ struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
- case DAVINCI_AUDIO_WORD_12:
- fmt = 0x05;
- rotate = 5;
- mask = 0x00000fff;
+ switch (div_id) {
+ case 0: /* MCLK divider */
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
break;
- case DAVINCI_AUDIO_WORD_16:
- fmt = 0x07;
- rotate = 4;
- mask = 0x0000ffff;
+ case 1: /* BCLK divider */
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+ ACLKXDIV(div - 1), ACLKXDIV_MASK);
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+ ACLKRDIV(div - 1), ACLKRDIV_MASK);
break;
- case DAVINCI_AUDIO_WORD_20:
- fmt = 0x09;
- rotate = 3;
- mask = 0x000fffff;
+ case 2: /* BCLK/LRCLK ratio */
+ dev->bclk_lrclk_ratio = div;
break;
- case DAVINCI_AUDIO_WORD_24:
- fmt = 0x0B;
- rotate = 2;
- mask = 0x00ffffff;
- break;
+ default:
+ return -EINVAL;
+ }
- case DAVINCI_AUDIO_WORD_28:
- fmt = 0x0D;
- rotate = 1;
- mask = 0x0fffffff;
- break;
+ return 0;
+}
- case DAVINCI_AUDIO_WORD_32:
- fmt = 0x0F;
- rotate = 0;
- mask = 0xffffffff;
- break;
+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);
- default:
- return -EINVAL;
+ 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);
+ } 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);
}
+ return 0;
+}
+
+static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+ int word_length)
+{
+ u32 fmt;
+ u32 rotate = (32 - word_length) / 4;
+ u32 mask = (1ULL << word_length) - 1;
+
+ /*
+ * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
+ * callback, take it into account here. That allows us to for example
+ * send 32 bits per channel to the codec, while only 16 of them carry
+ * audio payload.
+ * The clock ratio is given for a full period of data (both left and
+ * right channels), so it has to be divided by 2.
+ */
+ if (dev->bclk_lrclk_ratio)
+ word_length = dev->bclk_lrclk_ratio / 2;
+
+ /* mapping of the XSSZ bit-field as described in the datasheet */
+ fmt = (word_length >> 1) - 1;
+
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
RXSSZ(fmt), RXSSZ(0x0F));
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -709,8 +745,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* bit stream is MSB first with no delay */
/* DSP_B mode */
- mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
- AHCLKXE);
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
@@ -720,14 +754,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
else
printk(KERN_ERR "playback tdm slot %d not supported\n",
dev->tdm_slots);
-
- mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
} else {
/* bit stream is MSB first with no delay */
/* DSP_B mode */
mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
- AHCLKRE);
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +766,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
else
printk(KERN_ERR "capture tdm slot %d not supported\n",
dev->tdm_slots);
-
- mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
}
}
@@ -800,19 +828,27 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8:
dma_params->data_type = 1;
- word_length = DAVINCI_AUDIO_WORD_8;
+ word_length = 8;
break;
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
dma_params->data_type = 2;
- word_length = DAVINCI_AUDIO_WORD_16;
+ word_length = 16;
+ break;
+
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ dma_params->data_type = 3;
+ word_length = 24;
break;
+ case SNDRV_PCM_FORMAT_U24_LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE:
dma_params->data_type = 4;
- word_length = DAVINCI_AUDIO_WORD_32;
+ word_length = 32;
break;
default:
@@ -880,13 +916,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.trigger = davinci_mcasp_trigger,
.hw_params = davinci_mcasp_hw_params,
.set_fmt = davinci_mcasp_set_dai_fmt,
-
+ .set_clkdiv = davinci_mcasp_set_clkdiv,
+ .set_sysclk = davinci_mcasp_set_sysclk,
};
#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_U8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_U24_LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | \
+ SNDRV_PCM_FMTBIT_U24_3LE | \
SNDRV_PCM_FMTBIT_S32_LE | \
SNDRV_PCM_FMTBIT_U32_LE)
@@ -1089,7 +1130,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dev->tdm_slots = pdata->tdm_slots;
dev->num_serializer = pdata->num_serializer;
dev->serial_dir = pdata->serial_dir;
- dev->codec_fmt = pdata->codec_fmt;
dev->version = pdata->version;
dev->txnumevt = pdata->txnumevt;
dev->rxnumevt = pdata->rxnumevt;
@@ -1098,6 +1138,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dma_data = &dev->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 = (dma_addr_t) (pdata->tx_dma_offset +
mem->start);
@@ -1115,6 +1156,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dma_data = &dev->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 = (dma_addr_t)(pdata->rx_dma_offset +
mem->start);
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 0de9ed6ce038..0edd3b5a37fd 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -23,26 +23,14 @@
#include "davinci-pcm.h"
-#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_I2S_DAI 0
#define DAVINCI_MCASP_DIT_DAI 1
-enum {
- DAVINCI_AUDIO_WORD_8 = 0,
- DAVINCI_AUDIO_WORD_12,
- DAVINCI_AUDIO_WORD_16,
- DAVINCI_AUDIO_WORD_20,
- DAVINCI_AUDIO_WORD_24,
- DAVINCI_AUDIO_WORD_32,
- DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */
-};
-
struct davinci_audio_dev {
struct davinci_pcm_dma_params dma_params[2];
void __iomem *base;
- int sample_rate;
struct device *dev;
- unsigned int codec_fmt;
/* McASP specific data */
int tdm_slots;
@@ -50,6 +38,7 @@ struct davinci_audio_dev {
u8 num_serializer;
u8 *serial_dir;
u8 version;
+ u8 bclk_lrclk_ratio;
/* McASP FIFO related */
u8 txnumevt;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 93ea3bf567e1..afab81f844ae 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
+#include <linux/genalloc.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -23,7 +24,6 @@
#include <sound/soc.h>
#include <asm/dma.h>
-#include <mach/sram.h>
#include "davinci-pcm.h"
@@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
SNDRV_PCM_INFO_BATCH),
.formats = DAVINCI_PCM_FMTBITS,
- .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_KNOT),
+ .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
.channels_min = 2,
.channels_max = 384,
.buffer_bytes_max = 128 * 1024,
@@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_BATCH),
.formats = DAVINCI_PCM_FMTBITS,
- .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_KNOT),
+ .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
.channels_min = 2,
.channels_max = 384,
.buffer_bytes_max = 128 * 1024,
@@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
}
}
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+ struct gen_pool *sram_pool, unsigned size,
struct snd_pcm_hardware *ppcm)
{
struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
return 0;
ppcm->period_bytes_max = size;
- iram_virt = sram_alloc(size, &iram_phys);
+ iram_virt = (void *)gen_pool_alloc(sram_pool, size);
if (!iram_virt)
goto exit1;
+ iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
if (!iram_dma)
goto exit2;
@@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
return 0;
exit2:
if (iram_virt)
- sram_free(iram_virt, size);
+ gen_pool_free(sram_pool, (unsigned)iram_virt, size);
exit1:
return -ENOMEM;
}
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+ struct snd_dma_buffer *iram_dma)
+{
+ struct davinci_runtime_data *prtd = substream->runtime->private_data;
+ struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+ gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+ struct gen_pool *sram_pool, unsigned size,
+ struct snd_pcm_hardware *ppcm)
+{
+ return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+ struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
/*
* Only used with ping/pong.
* This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
&pcm_hardware_playback : &pcm_hardware_capture;
- allocate_sram(substream, params->sram_size, ppcm);
+ allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
snd_soc_set_runtime_hwparams(substream, ppcm);
/* ensure that buffer size is a multiple of period size */
ret = snd_pcm_hw_constraint_integer(runtime,
@@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
buf->area = NULL;
iram_dma = buf->private_data;
if (iram_dma) {
- sram_free(iram_dma->area, iram_dma->bytes);
+ davinci_free_sram(substream, iram_dma);
kfree(iram_dma);
}
}
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index fc4d01cdd8c9..b6ef7039dd09 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -12,6 +12,7 @@
#ifndef _DAVINCI_PCM_H
#define _DAVINCI_PCM_H
+#include <linux/genalloc.h>
#include <linux/platform_data/davinci_asp.h>
#include <mach/edma.h>
@@ -20,6 +21,7 @@ struct davinci_pcm_dma_params {
unsigned short acnt;
dma_addr_t dma_addr; /* device physical address for DMA */
unsigned sram_size;
+ struct gen_pool *sram_pool; /* SRAM gen_pool for ping pong */
enum dma_event_q asp_chan_q; /* event queue number for ASP channel */
enum dma_event_q ram_chan_q; /* event queue number for RAM channel */
unsigned char data_type; /* xfer data type */
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 4563b28bd625..3b98159d9645 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -46,6 +46,20 @@ config SND_SOC_P1022_DS
This will also include the Wolfson Microelectronics WM8776 codec
driver.
+config SND_SOC_P1022_RDK
+ tristate "ALSA SoC support for the Freescale / iVeia P1022 RDK board"
+ # I2C is necessary for the WM8960 driver
+ depends on P1022_RDK && I2C
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_POWERPC_DMA
+ select SND_SOC_WM8960
+ default y if P1022_RDK
+ help
+ Say Y if you want to enable audio on the Freescale / iVeia
+ P1022 RDK board. This will also include the Wolfson
+ Microelectronics WM8960 codec driver.
+
config SND_SOC_MPC5200_I2S
tristate "Freescale MPC5200 PSC in I2S mode driver"
depends on PPC_MPC52xx && PPC_BESTCOMM
@@ -98,12 +112,12 @@ config SND_SOC_IMX_PCM
tristate
config SND_SOC_IMX_PCM_FIQ
- tristate
+ bool
select FIQ
select SND_SOC_IMX_PCM
config SND_SOC_IMX_PCM_DMA
- tristate
+ bool
select SND_SOC_DMAENGINE_PCM
select SND_SOC_IMX_PCM
@@ -112,7 +126,7 @@ config SND_SOC_IMX_AUDMUX
config SND_MXC_SOC_WM1133_EV1
tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
- depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+ depends on MACH_MX31ADS_WM1133_EV1
select SND_SOC_WM8350
select SND_SOC_IMX_PCM_FIQ
select SND_SOC_IMX_AUDMUX
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 5f3cf3f52ea0..afd34794db53 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -6,6 +6,10 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
snd-soc-p1022-ds-objs := p1022_ds.o
obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
+# P1022 RDK Machine Support
+snd-soc-p1022-rdk-objs := p1022_rdk.o
+obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
+
# Freescale PowerPC SSI/DMA Platform Support
snd-soc-fsl-ssi-objs := fsl_ssi.o
snd-soc-fsl-utils-objs := fsl_utils.o
@@ -26,14 +30,18 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
# i.MX Platform Support
snd-soc-imx-ssi-objs := imx-ssi.o
snd-soc-imx-audmux-objs := imx-audmux.o
+snd-soc-imx-pcm-objs := imx-pcm.o
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),)
+ snd-soc-imx-pcm-objs += imx-pcm-fiq.o
+endif
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),)
+ snd-soc-imx-pcm-objs += imx-pcm-dma.o
+endif
obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
-snd-soc-imx-pcm-y := imx-pcm.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
# i.MX Machine Support
snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 267d5b4b63ce..75ffdf0e2aad 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -93,7 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = {
.num_links = 1,
};
-static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
+static int eukrea_tlv320_probe(struct platform_device *pdev)
{
int ret;
int int_port = 0, ext_port;
@@ -142,7 +142,7 @@ static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit eukrea_tlv320_remove(struct platform_device *pdev)
+static int eukrea_tlv320_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&eukrea_tlv320);
@@ -155,7 +155,7 @@ static struct platform_driver eukrea_tlv320_driver = {
.owner = THIS_MODULE,
},
.probe = eukrea_tlv320_probe,
- .remove = __devexit_p(eukrea_tlv320_remove),};
+ .remove = eukrea_tlv320_remove,};
module_platform_driver(eukrea_tlv320_driver);
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 6feb26500580..9cc5c1f82f09 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -894,7 +894,7 @@ static struct snd_pcm_ops fsl_dma_ops = {
.pointer = fsl_dma_pointer,
};
-static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
+static int fsl_soc_dma_probe(struct platform_device *pdev)
{
struct dma_object *dma;
struct device_node *np = pdev->dev.of_node;
@@ -958,7 +958,7 @@ static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
+static int fsl_soc_dma_remove(struct platform_device *pdev)
{
struct dma_object *dma = dev_get_drvdata(&pdev->dev);
@@ -983,7 +983,7 @@ static struct platform_driver fsl_soc_dma_driver = {
.of_match_table = fsl_soc_dma_ids,
},
.probe = fsl_soc_dma_probe,
- .remove = __devexit_p(fsl_soc_dma_remove),
+ .remove = fsl_soc_dma_remove,
};
module_platform_driver(fsl_soc_dma_driver);
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 4ed2afd47782..7decbd9b2340 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -639,7 +639,7 @@ static void make_lowercase(char *s)
}
}
-static int __devinit fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe(struct platform_device *pdev)
{
struct fsl_ssi_private *ssi_private;
int ret = 0;
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 524ce6210cee..251f4d981e0c 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -162,7 +162,7 @@ static void __init audmux_debugfs_init(void)
}
}
-static void __devexit audmux_debugfs_remove(void)
+static void audmux_debugfs_remove(void)
{
debugfs_remove_recursive(audmux_debugfs_root);
}
@@ -244,7 +244,7 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
}
EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
-static int __devinit imx_audmux_probe(struct platform_device *pdev)
+static int imx_audmux_probe(struct platform_device *pdev)
{
struct resource *res;
struct pinctrl *pinctrl;
@@ -278,7 +278,7 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit imx_audmux_remove(struct platform_device *pdev)
+static int imx_audmux_remove(struct platform_device *pdev)
{
if (audmux_type == IMX31_AUDMUX)
audmux_debugfs_remove();
@@ -289,7 +289,7 @@ static int __devexit imx_audmux_remove(struct platform_device *pdev)
static struct platform_driver imx_audmux_driver = {
.probe = imx_audmux_probe,
- .remove = __devexit_p(imx_audmux_remove),
+ .remove = imx_audmux_remove,
.id_table = imx_audmux_ids,
.driver = {
.name = DRIVER_NAME,
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index 549b31fdc9dd..4ae30f21fdb5 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -98,7 +98,7 @@ static struct snd_soc_card imx_mc13783 = {
.num_dapm_routes = ARRAY_SIZE(imx_mc13783_routes),
};
-static int __devinit imx_mc13783_probe(struct platform_device *pdev)
+static int imx_mc13783_probe(struct platform_device *pdev)
{
int ret;
@@ -148,7 +148,7 @@ static int __devinit imx_mc13783_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit imx_mc13783_remove(struct platform_device *pdev)
+static int imx_mc13783_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&imx_mc13783);
@@ -161,7 +161,7 @@ static struct platform_driver imx_mc13783_audio_driver = {
.owner = THIS_MODULE,
},
.probe = imx_mc13783_probe,
- .remove = __devexit_p(imx_mc13783_remove)
+ .remove = imx_mc13783_remove
};
module_platform_driver(imx_mc13783_audio_driver);
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index d85929b79c35..bf363d8d044a 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -154,12 +154,12 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
.pcm_free = imx_pcm_free,
};
-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
+static int imx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
}
-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
+static int imx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -171,7 +171,7 @@ static struct platform_driver imx_pcm_driver = {
.owner = THIS_MODULE,
},
.probe = imx_soc_platform_probe,
- .remove = __devexit_p(imx_soc_platform_remove),
+ .remove = imx_soc_platform_remove,
};
module_platform_driver(imx_pcm_driver);
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 9ffc9e66308f..5ec362ae4d01 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
.pcm_free = imx_pcm_fiq_free,
};
-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
+static int imx_soc_platform_probe(struct platform_device *pdev)
{
struct imx_ssi *ssi = platform_get_drvdata(pdev);
int ret;
@@ -315,7 +315,7 @@ failed_register:
return ret;
}
-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
+static int imx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -328,7 +328,7 @@ static struct platform_driver imx_pcm_driver = {
},
.probe = imx_soc_platform_probe,
- .remove = __devexit_p(imx_soc_platform_remove),
+ .remove = imx_soc_platform_remove,
};
module_platform_driver(imx_pcm_driver);
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c
index 93dc360b1777..d5cd9eff3b48 100644
--- a/sound/soc/fsl/imx-pcm.c
+++ b/sound/soc/fsl/imx-pcm.c
@@ -103,3 +103,7 @@ void imx_pcm_free(struct snd_pcm *pcm)
}
}
EXPORT_SYMBOL_GPL(imx_pcm_free);
+
+MODULE_DESCRIPTION("Freescale i.MX PCM driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 199408ec4261..424347e9b2d7 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -56,7 +56,7 @@ static const struct snd_soc_dapm_widget imx_sgtl5000_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Ext Spk", NULL),
};
-static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
+static int imx_sgtl5000_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *ssi_np, *codec_np;
@@ -162,6 +162,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
if (ret)
goto clk_fail;
data->card.num_links = 1;
+ data->card.owner = THIS_MODULE;
data->card.dai_link = &data->dai;
data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
@@ -184,7 +185,7 @@ fail:
return ret;
}
-static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
+static int imx_sgtl5000_remove(struct platform_device *pdev)
{
struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
@@ -210,7 +211,7 @@ static struct platform_driver imx_sgtl5000_driver = {
.of_match_table = imx_sgtl5000_dt_ids,
},
.probe = imx_sgtl5000_probe,
- .remove = __devexit_p(imx_sgtl5000_remove),
+ .remove = imx_sgtl5000_remove,
};
module_platform_driver(imx_sgtl5000_driver);
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index dd566444e3c3..3b480423747f 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -638,7 +638,7 @@ failed_clk:
return ret;
}
-static int __devexit imx_ssi_remove(struct platform_device *pdev)
+static int imx_ssi_remove(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct imx_ssi *ssi = platform_get_drvdata(pdev);
@@ -659,7 +659,7 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
static struct platform_driver imx_ssi_driver = {
.probe = imx_ssi_probe,
- .remove = __devexit_p(imx_ssi_remove),
+ .remove = imx_ssi_remove,
.driver = {
.name = "imx-ssi",
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index a313c0ae36db..a4aec0488dd3 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -277,7 +277,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
* - Probe/remove operations
* - OF device match table
*/
-static int __devinit psc_ac97_of_probe(struct platform_device *op)
+static int psc_ac97_of_probe(struct platform_device *op)
{
int rc;
struct snd_ac97 ac97;
@@ -310,7 +310,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op)
return 0;
}
-static int __devexit psc_ac97_of_remove(struct platform_device *op)
+static int psc_ac97_of_remove(struct platform_device *op)
{
mpc5200_audio_dma_destroy(op);
snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
@@ -318,7 +318,7 @@ static int __devexit psc_ac97_of_remove(struct platform_device *op)
}
/* Match table for of_platform binding */
-static struct of_device_id psc_ac97_match[] __devinitdata = {
+static struct of_device_id psc_ac97_match[] = {
{ .compatible = "fsl,mpc5200-psc-ac97", },
{ .compatible = "fsl,mpc5200b-psc-ac97", },
{}
@@ -327,7 +327,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match);
static struct platform_driver psc_ac97_driver = {
.probe = psc_ac97_of_probe,
- .remove = __devexit_p(psc_ac97_of_remove),
+ .remove = psc_ac97_of_remove,
.driver = {
.name = "mpc5200-psc-ac97",
.owner = THIS_MODULE,
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index ba1f0a66358f..b95b966f25a0 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -153,7 +153,7 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
* - Probe/remove operations
* - OF device match table
*/
-static int __devinit psc_i2s_of_probe(struct platform_device *op)
+static int psc_i2s_of_probe(struct platform_device *op)
{
int rc;
struct psc_dma *psc_dma;
@@ -205,7 +205,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op)
}
-static int __devexit psc_i2s_of_remove(struct platform_device *op)
+static int psc_i2s_of_remove(struct platform_device *op)
{
mpc5200_audio_dma_destroy(op);
snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
@@ -213,7 +213,7 @@ static int __devexit psc_i2s_of_remove(struct platform_device *op)
}
/* Match table for of_platform binding */
-static struct of_device_id psc_i2s_match[] __devinitdata = {
+static struct of_device_id psc_i2s_match[] = {
{ .compatible = "fsl,mpc5200-psc-i2s", },
{ .compatible = "fsl,mpc5200b-psc-i2s", },
{}
@@ -222,7 +222,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match);
static struct platform_driver psc_i2s_driver = {
.probe = psc_i2s_of_probe,
- .remove = __devexit_p(psc_i2s_of_remove),
+ .remove = psc_i2s_of_remove,
.driver = {
.name = "mpc5200-psc-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 9ff9318c52b9..228c52e71440 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -368,7 +368,7 @@ error_alloc:
*
* This function is called when the platform device is removed.
*/
-static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
+static int mpc8610_hpcd_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct mpc8610_hpcd_data *machine_data =
@@ -382,7 +382,7 @@ static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
static struct platform_driver mpc8610_hpcd_driver = {
.probe = mpc8610_hpcd_probe,
- .remove = __devexit_p(mpc8610_hpcd_remove),
+ .remove = mpc8610_hpcd_remove,
.driver = {
/* The name must match 'compatible' property in the device tree,
* in lowercase letters.
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c
index 2b76877b1789..3d1074179057 100644
--- a/sound/soc/fsl/mx27vis-aic32x4.c
+++ b/sound/soc/fsl/mx27vis-aic32x4.c
@@ -180,7 +180,7 @@ static struct snd_soc_card mx27vis_aic32x4 = {
.num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
-static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
+static int mx27vis_aic32x4_probe(struct platform_device *pdev)
{
struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data;
int ret;
@@ -219,7 +219,7 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
+static int mx27vis_aic32x4_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&mx27vis_aic32x4);
@@ -232,7 +232,7 @@ static struct platform_driver mx27vis_aic32x4_audio_driver = {
.owner = THIS_MODULE,
},
.probe = mx27vis_aic32x4_probe,
- .remove = __devexit_p(mx27vis_aic32x4_remove),
+ .remove = mx27vis_aic32x4_remove,
};
module_platform_driver(mx27vis_aic32x4_audio_driver);
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 144d49603637..ba59c23a137b 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -376,7 +376,7 @@ error_put:
*
* This function is called when the platform device is removed.
*/
-static int __devexit p1022_ds_remove(struct platform_device *pdev)
+static int p1022_ds_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct machine_data *mdata =
@@ -390,7 +390,7 @@ static int __devexit p1022_ds_remove(struct platform_device *pdev)
static struct platform_driver p1022_ds_driver = {
.probe = p1022_ds_probe,
- .remove = __devexit_p(p1022_ds_remove),
+ .remove = p1022_ds_remove,
.driver = {
/*
* The name must match 'compatible' property in the device tree,
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
new file mode 100644
index 000000000000..f21551911533
--- /dev/null
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -0,0 +1,392 @@
+/**
+ * Freescale P1022RDK ALSA SoC Machine driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * Note: in order for audio to work correctly, the output controls need
+ * to be enabled, because they control the clock. So for playback, for
+ * example:
+ *
+ * amixer sset 'Left Output Mixer PCM' on
+ * amixer sset 'Right Output Mixer PCM' on
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <asm/fsl_guts.h>
+
+#include "fsl_dma.h"
+#include "fsl_ssi.h"
+#include "fsl_utils.h"
+
+/* P1022-specific PMUXCR and DMUXCR bit definitions */
+
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK 0x0001c000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI 0x00010000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI 0x00018000
+
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK 0x00000c00
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI 0x00000000
+
+#define CCSR_GUTS_DMUXCR_PAD 1 /* DMA controller/channel set to pad */
+#define CCSR_GUTS_DMUXCR_SSI 2 /* DMA controller/channel set to SSI */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller. Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
+ */
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
+ unsigned int co, unsigned int ch, unsigned int device)
+{
+ unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+ clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
+}
+
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+/**
+ * machine_data: machine-specific ASoC device data
+ *
+ * This structure contains data for a single sound platform device on an
+ * P1022 RDK. Some of the data is taken from the device tree.
+ */
+struct machine_data {
+ struct snd_soc_dai_link dai[2];
+ struct snd_soc_card card;
+ unsigned int dai_format;
+ unsigned int codec_clk_direction;
+ unsigned int cpu_clk_direction;
+ unsigned int clk_frequency;
+ unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
+ unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+ char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
+};
+
+/**
+ * p1022_rdk_machine_probe: initialize the board
+ *
+ * This function is used to initialize the board-specific hardware.
+ *
+ * Here we program the DMACR and PMUXCR registers.
+ */
+static int p1022_rdk_machine_probe(struct snd_soc_card *card)
+{
+ struct machine_data *mdata =
+ container_of(card, struct machine_data, card);
+ struct ccsr_guts __iomem *guts;
+
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+ if (!guts) {
+ dev_err(card->dev, "could not map global utilities\n");
+ return -ENOMEM;
+ }
+
+ /* Enable SSI Tx signal */
+ clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
+ CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
+
+ /* Enable SSI Rx signal */
+ clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
+ CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
+
+ /* Enable DMA Channel for SSI */
+ guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
+ CCSR_GUTS_DMUXCR_SSI);
+
+ guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
+ CCSR_GUTS_DMUXCR_SSI);
+
+ iounmap(guts);
+
+ return 0;
+}
+
+/**
+ * p1022_rdk_startup: program the board with various hardware parameters
+ *
+ * This function takes board-specific information, like clock frequencies
+ * and serial data formats, and passes that information to the codec and
+ * transport drivers.
+ */
+static int p1022_rdk_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct machine_data *mdata =
+ container_of(rtd->card, struct machine_data, card);
+ struct device *dev = rtd->card->dev;
+ int ret = 0;
+
+ /* Tell the codec driver what the serial protocol is. */
+ ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
+ if (ret < 0) {
+ dev_err(dev, "could not set codec driver audio format (ret=%i)\n",
+ ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, mdata->clk_frequency,
+ mdata->clk_frequency);
+ if (ret < 0) {
+ dev_err(dev, "could not set codec PLL frequency (ret=%i)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * p1022_rdk_machine_remove: Remove the sound device
+ *
+ * This function is called to remove the sound device for one SSI. We
+ * de-program the DMACR and PMUXCR register.
+ */
+static int p1022_rdk_machine_remove(struct snd_soc_card *card)
+{
+ struct machine_data *mdata =
+ container_of(card, struct machine_data, card);
+ struct ccsr_guts __iomem *guts;
+
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+ if (!guts) {
+ dev_err(card->dev, "could not map global utilities\n");
+ return -ENOMEM;
+ }
+
+ /* Restore the signal routing */
+ clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
+ clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
+ guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
+ guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
+
+ iounmap(guts);
+
+ return 0;
+}
+
+/**
+ * p1022_rdk_ops: ASoC machine driver operations
+ */
+static struct snd_soc_ops p1022_rdk_ops = {
+ .startup = p1022_rdk_startup,
+};
+
+/**
+ * p1022_rdk_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections. Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int p1022_rdk_probe(struct platform_device *pdev)
+{
+ struct device *dev = pdev->dev.parent;
+ /* ssi_pdev is the platform device for the SSI node that probed us */
+ struct platform_device *ssi_pdev =
+ container_of(dev, struct platform_device, dev);
+ struct device_node *np = ssi_pdev->dev.of_node;
+ struct device_node *codec_np = NULL;
+ struct machine_data *mdata;
+ const u32 *iprop;
+ int ret;
+
+ /* Find the codec node for this SSI. */
+ codec_np = of_parse_phandle(np, "codec-handle", 0);
+ if (!codec_np) {
+ dev_err(dev, "could not find codec node\n");
+ return -EINVAL;
+ }
+
+ mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
+ if (!mdata) {
+ ret = -ENOMEM;
+ goto error_put;
+ }
+
+ mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+ mdata->dai[0].ops = &p1022_rdk_ops;
+
+ /* ASoC core can match codec with device node */
+ mdata->dai[0].codec_of_node = codec_np;
+
+ /*
+ * We register two DAIs per SSI, one for playback and the other for
+ * capture. We support codecs that have separate DAIs for both playback
+ * and capture.
+ */
+ memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
+
+ /* The DAI names from the codec (snd_soc_dai_driver.name) */
+ mdata->dai[0].codec_dai_name = "wm8960-hifi";
+ mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name;
+
+ /*
+ * Configure the SSI for I2S slave mode. Older device trees have
+ * an fsl,mode property, but we ignore that since there's really
+ * only one way to configure the SSI.
+ */
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
+ mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+ mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+
+ /*
+ * In i2s-slave mode, the codec has its own clock source, so we
+ * need to get the frequency from the device tree and pass it to
+ * the codec driver.
+ */
+ iprop = of_get_property(codec_np, "clock-frequency", NULL);
+ if (!iprop || !*iprop) {
+ dev_err(&pdev->dev, "codec bus-frequency property is missing or invalid\n");
+ ret = -EINVAL;
+ goto error;
+ }
+ mdata->clk_frequency = be32_to_cpup(iprop);
+
+ if (!mdata->clk_frequency) {
+ dev_err(&pdev->dev, "unknown clock frequency\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* Find the playback DMA channel to use. */
+ mdata->dai[0].platform_name = mdata->platform_name[0];
+ ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+ &mdata->dma_channel_id[0],
+ &mdata->dma_id[0]);
+ if (ret) {
+ dev_err(&pdev->dev, "missing/invalid playback DMA phandle (ret=%i)\n",
+ ret);
+ goto error;
+ }
+
+ /* Find the capture DMA channel to use. */
+ mdata->dai[1].platform_name = mdata->platform_name[1];
+ ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+ &mdata->dma_channel_id[1],
+ &mdata->dma_id[1]);
+ if (ret) {
+ dev_err(&pdev->dev, "missing/invalid capture DMA phandle (ret=%i)\n",
+ ret);
+ goto error;
+ }
+
+ /* Initialize our DAI data structure. */
+ mdata->dai[0].stream_name = "playback";
+ mdata->dai[1].stream_name = "capture";
+ mdata->dai[0].name = mdata->dai[0].stream_name;
+ mdata->dai[1].name = mdata->dai[1].stream_name;
+
+ mdata->card.probe = p1022_rdk_machine_probe;
+ mdata->card.remove = p1022_rdk_machine_remove;
+ mdata->card.name = pdev->name; /* The platform driver name */
+ mdata->card.owner = THIS_MODULE;
+ mdata->card.dev = &pdev->dev;
+ mdata->card.num_links = 2;
+ mdata->card.dai_link = mdata->dai;
+
+ /* Register with ASoC */
+ ret = snd_soc_register_card(&mdata->card);
+ if (ret) {
+ dev_err(&pdev->dev, "could not register card (ret=%i)\n", ret);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ kfree(mdata);
+error_put:
+ of_node_put(codec_np);
+ return ret;
+}
+
+/**
+ * p1022_rdk_remove: remove the platform device
+ *
+ * This function is called when the platform device is removed.
+ */
+static int p1022_rdk_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct machine_data *mdata =
+ container_of(card, struct machine_data, card);
+
+ snd_soc_unregister_card(card);
+ kfree(mdata);
+
+ return 0;
+}
+
+static struct platform_driver p1022_rdk_driver = {
+ .probe = p1022_rdk_probe,
+ .remove = p1022_rdk_remove,
+ .driver = {
+ /*
+ * The name must match 'compatible' property in the device tree,
+ * in lowercase letters.
+ */
+ .name = "snd-soc-p1022rdk",
+ .owner = THIS_MODULE,
+ },
+};
+
+/**
+ * p1022_rdk_init: machine driver initialization.
+ *
+ * This function is called when this module is loaded.
+ */
+static int __init p1022_rdk_init(void)
+{
+ struct device_node *guts_np;
+ struct resource res;
+
+ /* Get the physical address of the global utilities registers */
+ guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+ if (of_address_to_resource(guts_np, 0, &res)) {
+ pr_err("snd-soc-p1022rdk: missing/invalid global utils node\n");
+ of_node_put(guts_np);
+ return -EINVAL;
+ }
+ guts_phys = res.start;
+ of_node_put(guts_np);
+
+ return platform_driver_register(&p1022_rdk_driver);
+}
+
+/**
+ * p1022_rdk_exit: machine driver exit
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit p1022_rdk_exit(void)
+{
+ platform_driver_unregister(&p1022_rdk_driver);
+}
+
+late_initcall(p1022_rdk_init);
+module_exit(p1022_rdk_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale / iVeia P1022 RDK ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index 4b63ec8eb372..8e52c1485df3 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -29,14 +29,14 @@ struct pcm030_audio_data {
static struct snd_soc_dai_link pcm030_fabric_dai[] = {
{
- .name = "AC97",
+ .name = "AC97.0",
.stream_name = "AC97 Analog",
.codec_dai_name = "wm9712-hifi",
.cpu_dai_name = "mpc5200-psc-ac97.0",
.codec_name = "wm9712-codec",
},
{
- .name = "AC97",
+ .name = "AC97.1",
.stream_name = "AC97 IEC958",
.codec_dai_name = "wm9712-aux",
.cpu_dai_name = "mpc5200-psc-ac97.1",
@@ -101,7 +101,7 @@ static int __init pcm030_fabric_probe(struct platform_device *op)
return ret;
}
-static int __devexit pcm030_fabric_remove(struct platform_device *op)
+static int pcm030_fabric_remove(struct platform_device *op)
{
struct pcm030_audio_data *pdata = platform_get_drvdata(op);
int ret;
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match);
static struct platform_driver pcm030_fabric_driver = {
.probe = pcm030_fabric_probe,
- .remove = __devexit_p(pcm030_fabric_remove),
+ .remove = pcm030_fabric_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 41349670adab..6cef491f4823 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -425,7 +425,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
.resume = jz4740_i2s_resume,
};
-static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
+static int jz4740_i2s_dev_probe(struct platform_device *pdev)
{
struct jz4740_i2s *i2s;
int ret;
@@ -492,7 +492,7 @@ err_free:
return ret;
}
-static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
+static int jz4740_i2s_dev_remove(struct platform_device *pdev)
{
struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
@@ -512,7 +512,7 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
static struct platform_driver jz4740_i2s_driver = {
.probe = jz4740_i2s_dev_probe,
- .remove = __devexit_p(jz4740_i2s_dev_remove),
+ .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
index 9b8cf256847d..710059292318 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -335,12 +335,12 @@ static struct snd_soc_platform_driver jz4740_soc_platform = {
.pcm_free = jz4740_pcm_free,
};
-static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
+static int jz4740_pcm_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
}
-static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
+static int jz4740_pcm_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -348,7 +348,7 @@ static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
static struct platform_driver jz4740_pcm_driver = {
.probe = jz4740_pcm_probe,
- .remove = __devexit_p(jz4740_pcm_remove),
+ .remove = jz4740_pcm_remove,
.driver = {
.name = "jz4740-pcm-audio",
.owner = THIS_MODULE,
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index e8aaff18d7cc..55fd6b5df55f 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -96,7 +96,7 @@ static const struct gpio qi_lb60_gpios[] = {
{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
};
-static int __devinit qi_lb60_probe(struct platform_device *pdev)
+static int qi_lb60_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &qi_lb60;
int ret;
@@ -116,7 +116,7 @@ static int __devinit qi_lb60_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit qi_lb60_remove(struct platform_device *pdev)
+static int qi_lb60_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -131,7 +131,7 @@ static struct platform_driver qi_lb60_driver = {
.owner = THIS_MODULE,
},
.probe = qi_lb60_probe,
- .remove = __devexit_p(qi_lb60_remove),
+ .remove = qi_lb60_remove,
};
module_platform_driver(qi_lb60_driver);
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index 2ba08148655f..d3d4bdca1cc6 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -22,12 +22,16 @@
#include "kirkwood.h"
#define KIRKWOOD_RATES \
- (SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
+ (SNDRV_PCM_RATE_8000_192000 | \
+ SNDRV_PCM_RATE_CONTINUOUS | \
+ SNDRV_PCM_RATE_KNOT)
+
#define KIRKWOOD_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
+ SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
struct kirkwood_dma_priv {
struct snd_pcm_substream *play_stream;
@@ -43,10 +47,10 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
SNDRV_PCM_INFO_PAUSE),
.formats = KIRKWOOD_FORMATS,
.rates = KIRKWOOD_RATES,
- .rate_min = 44100,
- .rate_max = 96000,
+ .rate_min = 8000,
+ .rate_max = 384000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
.period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
.period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
@@ -368,12 +372,12 @@ static struct snd_soc_platform_driver kirkwood_soc_platform = {
.pcm_free = kirkwood_dma_free_dma_buffers,
};
-static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)
+static int kirkwood_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
}
-static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)
+static int kirkwood_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -386,7 +390,7 @@ static struct platform_driver kirkwood_pcm_driver = {
},
.probe = kirkwood_soc_platform_probe,
- .remove = __devexit_p(kirkwood_soc_platform_remove),
+ .remove = kirkwood_soc_platform_remove,
};
module_platform_driver(kirkwood_pcm_driver);
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 1d5db484d2df..282d8b1163ba 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -99,6 +99,29 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
} while (value == 0);
}
+static void kirkwood_set_rate(struct snd_soc_dai *dai,
+ struct kirkwood_dma_data *priv, unsigned long rate)
+{
+ uint32_t clks_ctrl;
+
+ if (rate == 44100 || rate == 48000 || rate == 96000) {
+ /* use internal dco for supported rates */
+ dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
+ __func__, rate);
+ kirkwood_set_dco(priv->io, rate);
+
+ clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
+ } else if (!IS_ERR(priv->extclk)) {
+ /* use optional external clk for other rates */
+ dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
+ __func__, rate, 256 * rate);
+ clk_set_rate(priv->extclk, 256 * rate);
+
+ clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
+ }
+ writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
+}
+
static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -113,26 +136,21 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
- unsigned int i2s_reg, reg;
- unsigned long i2s_value, value;
+ uint32_t ctl_play, ctl_rec;
+ unsigned int i2s_reg;
+ unsigned long i2s_value;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
i2s_reg = KIRKWOOD_I2S_PLAYCTL;
- reg = KIRKWOOD_PLAYCTL;
} else {
i2s_reg = KIRKWOOD_I2S_RECCTL;
- reg = KIRKWOOD_RECCTL;
}
- /* set dco conf */
- kirkwood_set_dco(priv->io, params_rate(params));
+ kirkwood_set_rate(dai, priv, params_rate(params));
i2s_value = readl(priv->io+i2s_reg);
i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
- value = readl(priv->io+reg);
- value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK;
-
/*
* Size settings in play/rec i2s control regs and play/rec control
* regs must be the same.
@@ -140,38 +158,57 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
- value |= KIRKWOOD_PLAYCTL_SIZE_16_C;
+ ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
+ KIRKWOOD_PLAYCTL_I2S_EN;
+ ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
+ KIRKWOOD_RECCTL_I2S_EN;
break;
/*
* doesn't work... S20_3LE != kirkwood 20bit format ?
*
case SNDRV_PCM_FORMAT_S20_3LE:
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
- value |= KIRKWOOD_PLAYCTL_SIZE_20;
+ ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
+ KIRKWOOD_PLAYCTL_I2S_EN;
+ ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
+ KIRKWOOD_RECCTL_I2S_EN;
break;
*/
case SNDRV_PCM_FORMAT_S24_LE:
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
- value |= KIRKWOOD_PLAYCTL_SIZE_24;
+ ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
+ KIRKWOOD_PLAYCTL_I2S_EN;
+ ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
+ KIRKWOOD_RECCTL_I2S_EN;
break;
case SNDRV_PCM_FORMAT_S32_LE:
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
- value |= KIRKWOOD_PLAYCTL_SIZE_32;
+ ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
+ KIRKWOOD_PLAYCTL_I2S_EN;
+ ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
+ KIRKWOOD_RECCTL_I2S_EN;
break;
default:
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- value &= ~KIRKWOOD_PLAYCTL_MONO_MASK;
if (params_channels(params) == 1)
- value |= KIRKWOOD_PLAYCTL_MONO_BOTH;
+ ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
else
- value |= KIRKWOOD_PLAYCTL_MONO_OFF;
+ ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
+
+ priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
+ KIRKWOOD_PLAYCTL_I2S_EN |
+ KIRKWOOD_PLAYCTL_SPDIF_EN |
+ KIRKWOOD_PLAYCTL_SIZE_MASK);
+ priv->ctl_play |= ctl_play;
+ } else {
+ priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
+ priv->ctl_rec |= ctl_rec;
}
writel(i2s_value, priv->io+i2s_reg);
- writel(value, priv->io+reg);
return 0;
}
@@ -205,20 +242,18 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ /* configure */
+ ctl = priv->ctl_play;
+ value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN |
+ KIRKWOOD_PLAYCTL_SPDIF_EN);
+ writel(value, priv->io + KIRKWOOD_PLAYCTL);
+
+ /* enable interrupts */
value = readl(priv->io + KIRKWOOD_INT_MASK);
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
- /* configure audio & enable i2s playback */
- ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
- ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
- | KIRKWOOD_PLAYCTL_SPDIF_EN);
-
- if (priv->burst == 32)
- ctl |= KIRKWOOD_PLAYCTL_BURST_32;
- else
- ctl |= KIRKWOOD_PLAYCTL_BURST_128;
- ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+ /* enable playback */
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break;
@@ -259,30 +294,24 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
- unsigned long value;
+ uint32_t ctl, value;
value = readl(priv->io + KIRKWOOD_RECCTL);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ /* configure */
+ ctl = priv->ctl_rec;
+ value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
+ writel(value, priv->io + KIRKWOOD_RECCTL);
+
+ /* enable interrupts */
value = readl(priv->io + KIRKWOOD_INT_MASK);
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
- /* configure audio & enable i2s record */
- value = readl(priv->io + KIRKWOOD_RECCTL);
- value &= ~KIRKWOOD_RECCTL_BURST_MASK;
- value &= ~KIRKWOOD_RECCTL_MONO;
- value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE
- | KIRKWOOD_RECCTL_SPDIF_EN);
-
- if (priv->burst == 32)
- value |= KIRKWOOD_RECCTL_BURST_32;
- else
- value |= KIRKWOOD_RECCTL_BURST_128;
- value |= KIRKWOOD_RECCTL_I2S_EN;
-
- writel(value, priv->io + KIRKWOOD_RECCTL);
+ /* enable record */
+ writel(ctl, priv->io + KIRKWOOD_RECCTL);
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -389,112 +418,146 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
.channels_min = 1,
.channels_max = 2,
.rates = KIRKWOOD_I2S_RATES,
- .formats = KIRKWOOD_I2S_FORMATS,},
+ .formats = KIRKWOOD_I2S_FORMATS,
+ },
.capture = {
.channels_min = 1,
.channels_max = 2,
.rates = KIRKWOOD_I2S_RATES,
- .formats = KIRKWOOD_I2S_FORMATS,},
+ .formats = KIRKWOOD_I2S_FORMATS,
+ },
.ops = &kirkwood_i2s_dai_ops,
};
-static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
+static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
+ .probe = kirkwood_i2s_probe,
+ .remove = kirkwood_i2s_remove,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000 |
+ SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_KNOT,
+ .formats = KIRKWOOD_I2S_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000 |
+ SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_KNOT,
+ .formats = KIRKWOOD_I2S_FORMATS,
+ },
+ .ops = &kirkwood_i2s_dai_ops,
+};
+
+static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
{
- struct resource *mem;
- struct kirkwood_asoc_platform_data *data =
- pdev->dev.platform_data;
+ struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
+ struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
struct kirkwood_dma_data *priv;
+ struct resource *mem;
int err;
- priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "allocation failed\n");
- err = -ENOMEM;
- goto error;
+ return -ENOMEM;
}
dev_set_drvdata(&pdev->dev, priv);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "platform_get_resource failed\n");
- err = -ENXIO;
- goto err_alloc;
- }
-
- priv->mem = request_mem_region(mem->start, SZ_16K, DRV_NAME);
- if (!priv->mem) {
- dev_err(&pdev->dev, "request_mem_region failed\n");
- err = -EBUSY;
- goto err_alloc;
+ return -ENXIO;
}
- priv->io = ioremap(priv->mem->start, SZ_16K);
+ priv->io = devm_request_and_ioremap(&pdev->dev, mem);
if (!priv->io) {
- dev_err(&pdev->dev, "ioremap failed\n");
- err = -ENOMEM;
- goto err_iomem;
+ dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
+ return -ENOMEM;
}
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq <= 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
- err = -ENXIO;
- goto err_ioremap;
+ return -ENXIO;
}
if (!data) {
dev_err(&pdev->dev, "no platform data ?!\n");
- err = -EINVAL;
- goto err_ioremap;
+ return -EINVAL;
}
priv->burst = data->burst;
- priv->clk = clk_get(&pdev->dev, NULL);
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "no clock\n");
- err = PTR_ERR(priv->clk);
- goto err_ioremap;
+ return PTR_ERR(priv->clk);
+ }
+
+ err = clk_prepare_enable(priv->clk);
+ if (err < 0)
+ return err;
+
+ priv->extclk = clk_get(&pdev->dev, "extclk");
+ if (!IS_ERR(priv->extclk)) {
+ if (priv->extclk == priv->clk) {
+ clk_put(priv->extclk);
+ priv->extclk = ERR_PTR(-EINVAL);
+ } else {
+ dev_info(&pdev->dev, "found external clock\n");
+ clk_prepare_enable(priv->extclk);
+ soc_dai = &kirkwood_i2s_dai_extclk;
+ }
+ }
+
+ /* Some sensible defaults - this reflects the powerup values */
+ priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
+ priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
+
+ /* Select the burst size */
+ if (data->burst == 32) {
+ priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
+ priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
+ } else {
+ priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
+ priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
}
- clk_prepare_enable(priv->clk);
- err = snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
+ err = snd_soc_register_dai(&pdev->dev, soc_dai);
if (!err)
return 0;
dev_err(&pdev->dev, "snd_soc_register_dai failed\n");
+ if (!IS_ERR(priv->extclk)) {
+ clk_disable_unprepare(priv->extclk);
+ clk_put(priv->extclk);
+ }
clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
-
-err_ioremap:
- iounmap(priv->io);
-err_iomem:
- release_mem_region(priv->mem->start, SZ_16K);
-err_alloc:
- kfree(priv);
-error:
+
return err;
}
-static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
+static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
{
struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
+ if (!IS_ERR(priv->extclk)) {
+ clk_disable_unprepare(priv->extclk);
+ clk_put(priv->extclk);
+ }
clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
-
- iounmap(priv->io);
- release_mem_region(priv->mem->start, SZ_16K);
- kfree(priv);
return 0;
}
static struct platform_driver kirkwood_i2s_driver = {
.probe = kirkwood_i2s_dev_probe,
- .remove = __devexit_p(kirkwood_i2s_dev_remove),
+ .remove = kirkwood_i2s_dev_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index c28540aeea25..b979c7154715 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -71,7 +71,7 @@ static struct snd_soc_card openrd_client = {
.num_links = ARRAY_SIZE(openrd_client_dai),
};
-static int __devinit openrd_probe(struct platform_device *pdev)
+static int openrd_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &openrd_client;
int ret;
@@ -85,7 +85,7 @@ static int __devinit openrd_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit openrd_remove(struct platform_device *pdev)
+static int openrd_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -99,7 +99,7 @@ static struct platform_driver openrd_driver = {
.owner = THIS_MODULE,
},
.probe = openrd_probe,
- .remove = __devexit_p(openrd_remove),
+ .remove = openrd_remove,
};
module_platform_driver(openrd_driver);
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index c67bbc574987..1d0ed6f8add7 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -92,7 +92,7 @@ static struct snd_soc_card t5325 = {
.num_dapm_routes = ARRAY_SIZE(t5325_route),
};
-static int __devinit t5325_probe(struct platform_device *pdev)
+static int t5325_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &t5325;
int ret;
@@ -106,7 +106,7 @@ static int __devinit t5325_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit t5325_remove(struct platform_device *pdev)
+static int t5325_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -120,7 +120,7 @@ static struct platform_driver t5325_driver = {
.owner = THIS_MODULE,
},
.probe = t5325_probe,
- .remove = __devexit_p(t5325_remove),
+ .remove = t5325_remove,
};
module_platform_driver(t5325_driver);
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index f9084d83e6bd..4d92637ddb3f 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -77,6 +77,11 @@
#define KIRKWOOD_DCO_SPCR_STATUS 0x120c
#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16)
+#define KIRKWOOD_CLOCKS_CTRL 0x1230
+#define KIRKWOOD_MCLK_SOURCE_MASK (3<<0)
+#define KIRKWOOD_MCLK_SOURCE_DCO (0<<0)
+#define KIRKWOOD_MCLK_SOURCE_EXTCLK (3<<0)
+
#define KIRKWOOD_ERR_CAUSE 0x1300
#define KIRKWOOD_ERR_MASK 0x1304
@@ -119,11 +124,13 @@
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
struct kirkwood_dma_data {
- struct resource *mem;
void __iomem *io;
+ struct clk *clk;
+ struct clk *extclk;
+ uint32_t ctl_play;
+ uint32_t ctl_rec;
int irq;
int burst;
- struct clk *clk;
};
#endif
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 2cc7782714b5..4139116c33b5 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -358,7 +358,7 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
return IRQ_HANDLED;
}
-static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
+static int snd_mfld_mc_probe(struct platform_device *pdev)
{
int ret_val = 0, irq;
struct mfld_mc_private *mc_drv_ctx;
@@ -417,7 +417,7 @@ unalloc:
return ret_val;
}
-static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
+static int snd_mfld_mc_remove(struct platform_device *pdev)
{
struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
@@ -435,7 +435,7 @@ static struct platform_driver snd_mfld_mc_driver = {
.name = "msic_audio",
},
.probe = snd_mfld_mc_probe,
- .remove = __devexit_p(snd_mfld_mc_remove),
+ .remove = snd_mfld_mc_remove,
};
module_platform_driver(snd_mfld_mc_driver);
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index f82d766cbf9e..564b5b60319d 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -220,13 +220,13 @@ static struct snd_soc_platform_driver mxs_soc_platform = {
.pcm_free = mxs_pcm_free,
};
-int __devinit mxs_pcm_platform_register(struct device *dev)
+int mxs_pcm_platform_register(struct device *dev)
{
return snd_soc_register_platform(dev, &mxs_soc_platform);
}
EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
-void __devexit mxs_pcm_platform_unregister(struct device *dev)
+void mxs_pcm_platform_unregister(struct device *dev)
{
snd_soc_unregister_platform(dev);
}
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index c294fbb523fc..365d9d27a321 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -229,6 +229,7 @@ int mxs_saif_put_mclk(unsigned int saif_id)
saif->mclk_in_use = 0;
return 0;
}
+EXPORT_SYMBOL_GPL(mxs_saif_put_mclk);
/*
* Get MCLK and set clock rate, then enable it
@@ -282,6 +283,7 @@ int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
return 0;
}
+EXPORT_SYMBOL_GPL(mxs_saif_get_mclk);
/*
* SAIF DAI format configuration.
@@ -655,7 +657,7 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit mxs_saif_probe(struct platform_device *pdev)
+static int mxs_saif_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *iores, *dmares;
@@ -790,7 +792,7 @@ failed_pdev_alloc:
return ret;
}
-static int __devexit mxs_saif_remove(struct platform_device *pdev)
+static int mxs_saif_remove(struct platform_device *pdev)
{
mxs_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
@@ -806,7 +808,7 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
static struct platform_driver mxs_saif_driver = {
.probe = mxs_saif_probe,
- .remove = __devexit_p(mxs_saif_remove),
+ .remove = mxs_saif_remove,
.driver = {
.name = "mxs-saif",
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 215113b05f7d..b1d9b5ebeeeb 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -112,7 +112,7 @@ static struct snd_soc_card mxs_sgtl5000 = {
.num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
};
-static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *saif_np[2], *codec_np;
@@ -145,7 +145,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
return ret;
}
-static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
+static int mxs_sgtl5000_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mxs_sgtl5000;
int ret;
@@ -176,7 +176,7 @@ static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
+static int mxs_sgtl5000_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -200,7 +200,7 @@ static struct platform_driver mxs_sgtl5000_audio_driver = {
.of_match_table = mxs_sgtl5000_dt_ids,
},
.probe = mxs_sgtl5000_probe,
- .remove = __devexit_p(mxs_sgtl5000_remove),
+ .remove = mxs_sgtl5000_remove,
};
module_platform_driver(mxs_sgtl5000_audio_driver);
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 946020a647db..0418467a4848 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -314,7 +314,7 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
.ops = &nuc900_ac97_dai_ops,
};
-static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
+static int nuc900_ac97_drvprobe(struct platform_device *pdev)
{
struct nuc900_audio *nuc900_audio;
int ret;
@@ -382,7 +382,7 @@ out0:
return ret;
}
-static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
+static int nuc900_ac97_drvremove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
@@ -403,7 +403,7 @@ static struct platform_driver nuc900_ac97_driver = {
.owner = THIS_MODULE,
},
.probe = nuc900_ac97_drvprobe,
- .remove = __devexit_p(nuc900_ac97_drvremove),
+ .remove = nuc900_ac97_drvremove,
};
module_platform_driver(nuc900_ac97_driver);
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index 37585b47f4e3..c894ff0f2580 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -337,12 +337,12 @@ static struct snd_soc_platform_driver nuc900_soc_platform = {
.pcm_free = nuc900_dma_free_dma_buffers,
};
-static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
+static int nuc900_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);
}
-static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)
+static int nuc900_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -355,7 +355,7 @@ static struct platform_driver nuc900_pcm_driver = {
},
.probe = nuc900_soc_platform_probe,
- .remove = __devexit_p(nuc900_soc_platform_remove),
+ .remove = nuc900_soc_platform_remove,
};
module_platform_driver(nuc900_pcm_driver);
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index d8e96b2cd03e..2600447fa74f 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -575,7 +575,7 @@ static struct snd_soc_card ams_delta_audio_card = {
};
/* Module init/exit */
-static __devinit int ams_delta_probe(struct platform_device *pdev)
+static int ams_delta_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &ams_delta_audio_card;
int ret;
@@ -591,7 +591,7 @@ static __devinit int ams_delta_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ams_delta_remove(struct platform_device *pdev)
+static int ams_delta_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -616,7 +616,7 @@ static struct platform_driver ams_delta_driver = {
.owner = THIS_MODULE,
},
.probe = ams_delta_probe,
- .remove = __devexit_p(ams_delta_remove),
+ .remove = ams_delta_remove,
};
module_platform_driver(ams_delta_driver);
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index afb8d4f1bedf..285c8368cb47 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -28,8 +28,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
-#include <plat/cpu.h>
-
#include "mcbsp.h"
static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
@@ -612,7 +610,7 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
* system will refuse to enter idle if the CLKS pin source is not reset
* back to internal source.
*/
- if (!cpu_class_is_omap1())
+ if (!mcbsp_omap1())
omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
spin_lock(&mcbsp->lock);
@@ -932,8 +930,7 @@ static const struct attribute_group sidetone_attr_group = {
.attrs = (struct attribute **)sidetone_attrs,
};
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
- struct resource *res)
+static int omap_st_add(struct omap_mcbsp *mcbsp, struct resource *res)
{
struct omap_mcbsp_st_data *st_data;
int err;
@@ -959,7 +956,7 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
* McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
* 730 has only 2 McBSP, and both of them are MPU peripherals.
*/
-int __devinit omap_mcbsp_init(struct platform_device *pdev)
+int omap_mcbsp_init(struct platform_device *pdev)
{
struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
struct resource *res;
@@ -1087,7 +1084,7 @@ err_thres:
return ret;
}
-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
{
if (mcbsp->pdata->buffer_size)
sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index 49a67259ce5a..f93e0b0af303 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -26,6 +26,12 @@
#include "omap-pcm.h"
+#ifdef CONFIG_ARCH_OMAP1
+#define mcbsp_omap1() 1
+#else
+#define mcbsp_omap1() 0
+#endif
+
/* McBSP register numbers. Register address offset = num * reg_step */
enum {
/* Common registers */
@@ -341,7 +347,7 @@ int omap_st_enable(struct omap_mcbsp *mcbsp);
int omap_st_disable(struct omap_mcbsp *mcbsp);
int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
-int __devinit omap_mcbsp_init(struct platform_device *pdev);
-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_init(struct platform_device *pdev);
+void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
#endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index a57a4e68dcc6..e7d93fa412a9 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -273,7 +273,7 @@ static struct snd_soc_card omap_abe_card = {
.num_dapm_routes = ARRAY_SIZE(audio_map),
};
-static __devinit int omap_abe_probe(struct platform_device *pdev)
+static int omap_abe_probe(struct platform_device *pdev)
{
struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
@@ -331,8 +331,8 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
num_links = 1;
}
- of_property_read_u32(node, "ti,jack-detection",
- &priv->jack_detection);
+ priv->jack_detection = of_property_read_bool(node,
+ "ti,jack-detection");
of_property_read_u32(node, "ti,mclk-freq",
&priv->mclk_freq);
if (!priv->mclk_freq) {
@@ -390,7 +390,7 @@ err_unregister:
return ret;
}
-static int __devexit omap_abe_remove(struct platform_device *pdev)
+static int omap_abe_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
@@ -417,7 +417,7 @@ static struct platform_driver omap_abe_driver = {
.of_match_table = omap_abe_of_match,
},
.probe = omap_abe_probe,
- .remove = __devexit_p(omap_abe_remove),
+ .remove = omap_abe_remove,
};
module_platform_driver(omap_abe_driver);
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 5a6aeaf552a8..ba49ccd9eed9 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -448,7 +448,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
.ops = &omap_dmic_dai_ops,
};
-static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+static int asoc_dmic_probe(struct platform_device *pdev)
{
struct omap_dmic *dmic;
struct resource *res;
@@ -518,7 +518,7 @@ err_put_clk:
return ret;
}
-static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+static int asoc_dmic_remove(struct platform_device *pdev)
{
struct omap_dmic *dmic = platform_get_drvdata(pdev);
@@ -541,7 +541,7 @@ static struct platform_driver asoc_dmic_driver = {
.of_match_table = omap_dmic_of_match,
},
.probe = asoc_dmic_probe,
- .remove = __devexit_p(asoc_dmic_remove),
+ .remove = asoc_dmic_remove,
};
module_platform_driver(asoc_dmic_driver);
diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
index eaa2ea0e3f81..d4eaa92e518e 100644
--- a/sound/soc/omap/omap-hdmi-card.c
+++ b/sound/soc/omap/omap-hdmi-card.c
@@ -45,7 +45,7 @@ static struct snd_soc_card snd_soc_omap_hdmi = {
.num_links = 1,
};
-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+static int omap_hdmi_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_omap_hdmi;
int ret;
@@ -61,7 +61,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+static int omap_hdmi_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -76,7 +76,7 @@ static struct platform_driver omap_hdmi_driver = {
.owner = THIS_MODULE,
},
.probe = omap_hdmi_probe,
- .remove = __devexit_p(omap_hdmi_remove),
+ .remove = omap_hdmi_remove,
};
module_platform_driver(omap_hdmi_driver);
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index f59c69fb400e..7ea24819d570 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -262,7 +262,7 @@ static struct snd_soc_dai_driver omap_hdmi_dai = {
.ops = &omap_hdmi_dai_ops,
};
-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+static int omap_hdmi_probe(struct platform_device *pdev)
{
int ret;
struct resource *hdmi_rsrc;
@@ -324,7 +324,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+static int omap_hdmi_remove(struct platform_device *pdev)
{
struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
@@ -345,7 +345,7 @@ static struct platform_driver hdmi_dai_driver = {
.owner = THIS_MODULE,
},
.probe = omap_hdmi_probe,
- .remove = __devexit_p(omap_hdmi_remove),
+ .remove = omap_hdmi_remove,
};
module_platform_driver(hdmi_dai_driver);
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index a6ee15747859..8d2defd6fdbe 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -34,7 +34,6 @@
#include <sound/initval.h>
#include <sound/soc.h>
-#include <plat/cpu.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "mcbsp.h"
#include "omap-mcbsp.h"
@@ -512,7 +511,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
regs->srgr2 |= CLKSM;
break;
case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
- if (cpu_class_is_omap1()) {
+ if (mcbsp_omap1()) {
err = -EINVAL;
break;
}
@@ -520,7 +519,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
MCBSP_CLKS_PRCM_SRC);
break;
case OMAP_MCBSP_SYSCLK_CLKS_EXT:
- if (cpu_class_is_omap1()) {
+ if (mcbsp_omap1()) {
err = 0;
break;
}
@@ -758,7 +757,7 @@ static const struct of_device_id omap_mcbsp_of_match[] = {
};
MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match);
-static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+static int asoc_mcbsp_probe(struct platform_device *pdev)
{
struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct omap_mcbsp *mcbsp;
@@ -799,7 +798,7 @@ static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
+static int asoc_mcbsp_remove(struct platform_device *pdev)
{
struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
@@ -825,7 +824,7 @@ static struct platform_driver asoc_mcbsp_driver = {
},
.probe = asoc_mcbsp_probe,
- .remove = __devexit_p(asoc_mcbsp_remove),
+ .remove = asoc_mcbsp_remove,
};
module_platform_driver(asoc_mcbsp_driver);
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 56965bb3275c..2fe8be209452 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -429,7 +429,7 @@ void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
}
EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
-static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
+static int asoc_mcpdm_probe(struct platform_device *pdev)
{
struct omap_mcpdm *mcpdm;
struct resource *res;
@@ -487,7 +487,7 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
}
-static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
+static int asoc_mcpdm_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -507,7 +507,7 @@ static struct platform_driver asoc_mcpdm_driver = {
},
.probe = asoc_mcpdm_probe,
- .remove = __devexit_p(asoc_mcpdm_remove),
+ .remove = asoc_mcpdm_remove,
};
module_platform_driver(asoc_mcpdm_driver);
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 52977aa30355..47bdbd415ad8 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -302,13 +302,13 @@ static struct snd_soc_platform_driver omap_soc_platform = {
.pcm_free = omap_pcm_free_dma_buffers,
};
-static __devinit int omap_pcm_probe(struct platform_device *pdev)
+static int omap_pcm_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev,
&omap_soc_platform);
}
-static int __devexit omap_pcm_remove(struct platform_device *pdev)
+static int omap_pcm_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -321,7 +321,7 @@ static struct platform_driver omap_pcm_driver = {
},
.probe = omap_pcm_probe,
- .remove = __devexit_p(omap_pcm_remove),
+ .remove = omap_pcm_remove,
};
module_platform_driver(omap_pcm_driver);
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 3b97b87971f5..4541d28b5314 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -107,7 +107,7 @@ static struct snd_soc_card omap_twl4030_card = {
.num_links = ARRAY_SIZE(omap_twl4030_dai_links),
};
-static __devinit int omap_twl4030_probe(struct platform_device *pdev)
+static int omap_twl4030_probe(struct platform_device *pdev)
{
struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
@@ -154,7 +154,7 @@ static __devinit int omap_twl4030_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit omap_twl4030_remove(struct platform_device *pdev)
+static int omap_twl4030_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -177,7 +177,7 @@ static struct platform_driver omap_twl4030_driver = {
.of_match_table = omap_twl4030_of_match,
},
.probe = omap_twl4030_probe,
- .remove = __devexit_p(omap_twl4030_remove),
+ .remove = omap_twl4030_remove,
};
module_platform_driver(omap_twl4030_driver);
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 1ff6bb9ade5c..771bff27ac3e 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -37,8 +37,6 @@
#include "omap-mcbsp.h"
#include "omap-pcm.h"
-#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
-
static int zoom2_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -187,9 +185,6 @@ static int __init zoom2_soc_init(void)
if (ret)
goto err1;
- BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
- gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
-
return 0;
err1:
@@ -202,8 +197,6 @@ module_init(zoom2_soc_init);
static void __exit zoom2_soc_exit(void)
{
- gpio_free(ZOOM2_HEADSET_MUX_GPIO);
-
platform_device_unregister(zoom2_snd_device);
}
module_exit(zoom2_soc_exit);
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index 5e666e03d333..4ad76099dd43 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -140,7 +140,7 @@ static struct snd_soc_card brownstone = {
.num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
};
-static int __devinit brownstone_probe(struct platform_device *pdev)
+static int brownstone_probe(struct platform_device *pdev)
{
int ret;
@@ -152,7 +152,7 @@ static int __devinit brownstone_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit brownstone_remove(struct platform_device *pdev)
+static int brownstone_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&brownstone);
return 0;
@@ -164,7 +164,7 @@ static struct platform_driver mmp_driver = {
.owner = THIS_MODULE,
},
.probe = brownstone_probe,
- .remove = __devexit_p(brownstone_remove),
+ .remove = brownstone_remove,
};
module_platform_driver(mmp_driver);
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 863367ad89ce..f4cce1e80112 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -303,7 +303,7 @@ static struct snd_soc_card corgi = {
.num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
};
-static int __devinit corgi_probe(struct platform_device *pdev)
+static int corgi_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &corgi;
int ret;
@@ -317,7 +317,7 @@ static int __devinit corgi_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit corgi_remove(struct platform_device *pdev)
+static int corgi_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -331,7 +331,7 @@ static struct platform_driver corgi_driver = {
.owner = THIS_MODULE,
},
.probe = corgi_probe,
- .remove = __devexit_p(corgi_remove),
+ .remove = corgi_remove,
};
module_platform_driver(corgi_driver);
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
index 7b1bc2390039..70d799b13f0d 100644
--- a/sound/soc/pxa/e740_wm9705.c
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -144,7 +144,7 @@ static struct gpio e740_audio_gpios[] = {
{ GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH, "Audio power" },
};
-static int __devinit e740_probe(struct platform_device *pdev)
+static int e740_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &e740;
int ret;
@@ -165,7 +165,7 @@ static int __devinit e740_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit e740_remove(struct platform_device *pdev)
+static int e740_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -180,7 +180,7 @@ static struct platform_driver e740_driver = {
.owner = THIS_MODULE,
},
.probe = e740_probe,
- .remove = __devexit_p(e740_remove),
+ .remove = e740_remove,
};
module_platform_driver(e740_driver);
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
index 47b89d71e287..f94d2ab51351 100644
--- a/sound/soc/pxa/e750_wm9705.c
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -126,7 +126,7 @@ static struct gpio e750_audio_gpios[] = {
{ GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
};
-static int __devinit e750_probe(struct platform_device *pdev)
+static int e750_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &e750;
int ret;
@@ -147,7 +147,7 @@ static int __devinit e750_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit e750_remove(struct platform_device *pdev)
+static int e750_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -162,7 +162,7 @@ static struct platform_driver e750_driver = {
.owner = THIS_MODULE,
},
.probe = e750_probe,
- .remove = __devexit_p(e750_remove),
+ .remove = e750_remove,
};
module_platform_driver(e750_driver);
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index ea9707ec6f28..8768a640dd71 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -116,7 +116,7 @@ static struct gpio e800_audio_gpios[] = {
{ GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
};
-static int __devinit e800_probe(struct platform_device *pdev)
+static int e800_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &e800;
int ret;
@@ -137,7 +137,7 @@ static int __devinit e800_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit e800_remove(struct platform_device *pdev)
+static int e800_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -152,7 +152,7 @@ static struct platform_driver e800_driver = {
.owner = THIS_MODULE,
},
.probe = e800_probe,
- .remove = __devexit_p(e800_remove),
+ .remove = e800_remove,
};
module_platform_driver(e800_driver);
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c
index 2a342c92d829..dcc9b04bd92c 100644
--- a/sound/soc/pxa/hx4700.c
+++ b/sound/soc/pxa/hx4700.c
@@ -183,7 +183,7 @@ static struct gpio hx4700_audio_gpios[] = {
{ GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" },
};
-static int __devinit hx4700_audio_probe(struct platform_device *pdev)
+static int hx4700_audio_probe(struct platform_device *pdev)
{
int ret;
@@ -204,7 +204,7 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit hx4700_audio_remove(struct platform_device *pdev)
+static int hx4700_audio_remove(struct platform_device *pdev)
{
snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio);
snd_soc_unregister_card(&snd_soc_card_hx4700);
@@ -223,7 +223,7 @@ static struct platform_driver hx4700_audio_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = hx4700_audio_probe,
- .remove = __devexit_p(hx4700_audio_remove),
+ .remove = hx4700_audio_remove,
};
module_platform_driver(hx4700_audio_driver);
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
index b93dafd32b80..eef1f7b7b38e 100644
--- a/sound/soc/pxa/imote2.c
+++ b/sound/soc/pxa/imote2.c
@@ -65,7 +65,7 @@ static struct snd_soc_card imote2 = {
.num_links = 1,
};
-static int __devinit imote2_probe(struct platform_device *pdev)
+static int imote2_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &imote2;
int ret;
@@ -79,7 +79,7 @@ static int __devinit imote2_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit imote2_remove(struct platform_device *pdev)
+static int imote2_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -93,7 +93,7 @@ static struct platform_driver imote2_driver = {
.owner = THIS_MODULE,
},
.probe = imote2_probe,
- .remove = __devexit_p(imote2_remove),
+ .remove = imote2_remove,
};
module_platform_driver(imote2_driver);
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 8687c1c65d29..97b711e12821 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -186,7 +186,7 @@ static struct snd_soc_card mioa701 = {
.num_links = ARRAY_SIZE(mioa701_dai),
};
-static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
+static int mioa701_wm9713_probe(struct platform_device *pdev)
{
int rc;
@@ -202,7 +202,7 @@ static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
return rc;
}
-static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
+static int mioa701_wm9713_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -212,7 +212,7 @@ static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
static struct platform_driver mioa701_wm9713_driver = {
.probe = mioa701_wm9713_probe,
- .remove = __devexit_p(mioa701_wm9713_remove),
+ .remove = mioa701_wm9713_remove,
.driver = {
.name = "mioa701-wm9713",
.owner = THIS_MODULE,
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index e834faf859fd..190eb0bccf5f 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -257,7 +257,7 @@ struct snd_soc_platform_driver mmp_soc_platform = {
.pcm_free = mmp_pcm_free_dma_buffers,
};
-static __devinit int mmp_pcm_probe(struct platform_device *pdev)
+static int mmp_pcm_probe(struct platform_device *pdev)
{
struct mmp_audio_platdata *pdata = pdev->dev.platform_data;
@@ -274,7 +274,7 @@ static __devinit int mmp_pcm_probe(struct platform_device *pdev)
return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform);
}
-static int __devexit mmp_pcm_remove(struct platform_device *pdev)
+static int mmp_pcm_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -287,7 +287,7 @@ static struct platform_driver mmp_pcm_driver = {
},
.probe = mmp_pcm_probe,
- .remove = __devexit_p(mmp_pcm_remove),
+ .remove = mmp_pcm_remove,
};
module_platform_driver(mmp_pcm_driver);
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 4d6cb8a30fc8..41c3a09b53ea 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -405,7 +405,7 @@ struct snd_soc_dai_driver mmp_sspa_dai = {
.ops = &mmp_sspa_dai_ops,
};
-static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
+static int asoc_mmp_sspa_probe(struct platform_device *pdev)
{
struct sspa_priv *priv;
struct resource *res;
@@ -453,7 +453,7 @@ static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
}
-static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
+static int asoc_mmp_sspa_remove(struct platform_device *pdev)
{
struct sspa_priv *priv = platform_get_drvdata(pdev);
@@ -470,7 +470,7 @@ static struct platform_driver asoc_mmp_sspa_driver = {
.owner = THIS_MODULE,
},
.probe = asoc_mmp_sspa_probe,
- .remove = __devexit_p(asoc_mmp_sspa_remove),
+ .remove = asoc_mmp_sspa_remove,
};
module_platform_driver(asoc_mmp_sspa_driver);
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index aa3da91907c6..2074e2daf9c6 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -187,7 +187,7 @@ put_device:
return ret;
}
-static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
+static int palm27x_asoc_remove(struct platform_device *pdev)
{
platform_device_unregister(palm27x_snd_device);
return 0;
@@ -195,7 +195,7 @@ static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
static struct platform_driver palm27x_wm9712_driver = {
.probe = palm27x_asoc_probe,
- .remove = __devexit_p(palm27x_asoc_remove),
+ .remove = palm27x_asoc_remove,
.driver = {
.name = "palm27x-asoc",
.owner = THIS_MODULE,
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index d2cc81735036..fafe46355c31 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -269,7 +269,7 @@ static struct snd_soc_card poodle = {
.num_dapm_routes = ARRAY_SIZE(poodle_audio_map),
};
-static int __devinit poodle_probe(struct platform_device *pdev)
+static int poodle_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &poodle;
int ret;
@@ -291,7 +291,7 @@ static int __devinit poodle_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit poodle_remove(struct platform_device *pdev)
+static int poodle_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -305,7 +305,7 @@ static struct platform_driver poodle_driver = {
.owner = THIS_MODULE,
},
.probe = poodle_probe,
- .remove = __devexit_p(poodle_remove),
+ .remove = poodle_remove,
};
module_platform_driver(poodle_driver);
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 4da5fc55c7ee..d3eb0c2eec77 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -794,12 +794,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
.ops = &pxa_ssp_dai_ops,
};
-static __devinit int asoc_ssp_probe(struct platform_device *pdev)
+static int asoc_ssp_probe(struct platform_device *pdev)
{
return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
}
-static int __devexit asoc_ssp_remove(struct platform_device *pdev)
+static int asoc_ssp_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -812,7 +812,7 @@ static struct platform_driver asoc_ssp_driver = {
},
.probe = asoc_ssp_probe,
- .remove = __devexit_p(asoc_ssp_remove),
+ .remove = asoc_ssp_remove,
};
module_platform_driver(asoc_ssp_driver);
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 06ea2744cc88..4b0a009bd683 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -104,7 +104,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
#define pxa2xx_ac97_resume NULL
#endif
-static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
}
@@ -234,7 +234,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
-static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
{
if (pdev->id != -1) {
dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
@@ -249,7 +249,7 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
ARRAY_SIZE(pxa_ac97_dai_driver));
}
-static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
+static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
return 0;
@@ -257,7 +257,7 @@ static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
static struct platform_driver pxa2xx_ac97_driver = {
.probe = pxa2xx_ac97_dev_probe,
- .remove = __devexit_p(pxa2xx_ac97_dev_remove),
+ .remove = pxa2xx_ac97_dev_remove,
.driver = {
.name = "pxa2xx-ac97",
.owner = THIS_MODULE,
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 3075a426124c..6b1a06f67564 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -365,7 +365,7 @@ static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
}
-static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
+static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -373,7 +373,7 @@ static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
static struct platform_driver pxa2xx_i2s_driver = {
.probe = pxa2xx_i2s_drv_probe,
- .remove = __devexit_p(pxa2xx_i2s_drv_remove),
+ .remove = pxa2xx_i2s_drv_remove,
.driver = {
.name = "pxa2xx-i2s",
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index fdd6bedef9bd..ecff116cb7b0 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -120,12 +120,12 @@ static struct snd_soc_platform_driver pxa2xx_soc_platform = {
.pcm_free = pxa2xx_pcm_free_dma_buffers,
};
-static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
+static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
}
-static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
+static int pxa2xx_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -138,7 +138,7 @@ static struct platform_driver pxa_pcm_driver = {
},
.probe = pxa2xx_soc_platform_probe,
- .remove = __devexit_p(pxa2xx_soc_platform_remove),
+ .remove = pxa2xx_soc_platform_remove,
};
module_platform_driver(pxa_pcm_driver);
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 2aec63f3706a..a3fe19123f07 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -241,7 +241,7 @@ static struct snd_soc_card tosa = {
.num_links = ARRAY_SIZE(tosa_dai),
};
-static int __devinit tosa_probe(struct platform_device *pdev)
+static int tosa_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &tosa;
int ret;
@@ -262,7 +262,7 @@ static int __devinit tosa_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit tosa_remove(struct platform_device *pdev)
+static int tosa_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -277,7 +277,7 @@ static struct platform_driver tosa_driver = {
.owner = THIS_MODULE,
},
.probe = tosa_probe,
- .remove = __devexit_p(tosa_remove),
+ .remove = tosa_remove,
};
module_platform_driver(tosa_driver);
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
index 935491a8a770..f4ea4f6663a2 100644
--- a/sound/soc/pxa/ttc-dkb.c
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -131,7 +131,7 @@ static struct snd_soc_card ttc_dkb_card = {
.num_dapm_routes = ARRAY_SIZE(ttc_audio_map),
};
-static int __devinit ttc_dkb_probe(struct platform_device *pdev)
+static int ttc_dkb_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &ttc_dkb_card;
int ret;
@@ -146,7 +146,7 @@ static int __devinit ttc_dkb_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit ttc_dkb_remove(struct platform_device *pdev)
+static int ttc_dkb_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -161,7 +161,7 @@ static struct platform_driver ttc_dkb_driver = {
.owner = THIS_MODULE,
},
.probe = ttc_dkb_probe,
- .remove = __devexit_p(ttc_dkb_remove),
+ .remove = ttc_dkb_remove,
};
module_platform_driver(ttc_dkb_driver);
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index aaabdbaec19c..fee4d477a49c 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -436,7 +436,7 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
.ops = &s6000_i2s_dai_ops,
};
-static int __devinit s6000_i2s_probe(struct platform_device *pdev)
+static int s6000_i2s_probe(struct platform_device *pdev)
{
struct s6000_i2s_dev *dev;
struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
@@ -566,7 +566,7 @@ err_release_none:
return ret;
}
-static void __devexit s6000_i2s_remove(struct platform_device *pdev)
+static void s6000_i2s_remove(struct platform_device *pdev)
{
struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
struct resource *region;
@@ -597,7 +597,7 @@ static void __devexit s6000_i2s_remove(struct platform_device *pdev)
static struct platform_driver s6000_i2s_driver = {
.probe = s6000_i2s_probe,
- .remove = __devexit_p(s6000_i2s_remove),
+ .remove = s6000_i2s_remove,
.driver = {
.name = "s6000-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 716da861c629..1358c7de2521 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -500,12 +500,12 @@ static struct snd_soc_platform_driver s6000_soc_platform = {
.pcm_free = s6000_pcm_free,
};
-static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
+static int s6000_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
}
-static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
+static int s6000_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -518,7 +518,7 @@ static struct platform_driver s6000_pcm_driver = {
},
.probe = s6000_soc_platform_probe,
- .remove = __devexit_p(s6000_soc_platform_remove),
+ .remove = s6000_soc_platform_remove,
};
module_platform_driver(s6000_pcm_driver);
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 14fbcd30cae5..0df3c5644cfa 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -370,7 +370,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
},
};
-static __devinit int s3c_ac97_probe(struct platform_device *pdev)
+static int s3c_ac97_probe(struct platform_device *pdev)
{
struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
struct s3c_audio_pdata *ac97_pdata;
@@ -442,7 +442,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err2;
}
- clk_enable(s3c_ac97.ac97_clk);
+ clk_prepare_enable(s3c_ac97.ac97_clk);
if (ac97_pdata->cfg_gpio(pdev)) {
dev_err(&pdev->dev, "Unable to configure gpio\n");
@@ -462,13 +462,20 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
if (ret)
goto err5;
- return 0;
+ ret = asoc_dma_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
+ goto err6;
+ }
+ return 0;
+err6:
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
err5:
free_irq(irq_res->start, NULL);
err4:
err3:
- clk_disable(s3c_ac97.ac97_clk);
+ clk_disable_unprepare(s3c_ac97.ac97_clk);
clk_put(s3c_ac97.ac97_clk);
err2:
iounmap(s3c_ac97.regs);
@@ -478,17 +485,18 @@ err1:
return ret;
}
-static __devexit int s3c_ac97_remove(struct platform_device *pdev)
+static int s3c_ac97_remove(struct platform_device *pdev)
{
struct resource *mem_res, *irq_res;
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_res)
free_irq(irq_res->start, NULL);
- clk_disable(s3c_ac97.ac97_clk);
+ clk_disable_unprepare(s3c_ac97.ac97_clk);
clk_put(s3c_ac97.ac97_clk);
iounmap(s3c_ac97.regs);
@@ -502,7 +510,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
static struct platform_driver s3c_ac97_driver = {
.probe = s3c_ac97_probe,
- .remove = __devexit_p(s3c_ac97_remove),
+ .remove = s3c_ac97_remove,
.driver = {
.name = "samsung-ac97",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index a2ca1567b9e4..ceed466af9ff 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -18,15 +18,6 @@
#include "../codecs/wm5102.h"
#include "../codecs/wm9081.h"
-/*
- * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
- * to allow all the DSP functionality to be enabled if desired.
- */
-#define SYSCLK_RATE (44100 * 1024)
-
-/* 48kHz based clocks for the ASYNC domain */
-#define ASYNCCLK_RATE (48000 * 512)
-
/* BCLK2 is fixed at this currently */
#define BCLK2_RATE (64 * 8000)
@@ -36,15 +27,40 @@
*/
#define MCLK_RATE 24576000
-#define WM9081_AUDIO_RATE 44100
-#define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256)
+#define SYS_AUDIO_RATE 44100
+#define SYS_MCLK_RATE (SYS_AUDIO_RATE * 512)
+
+#define DAI_AP_DSP 0
+#define DAI_DSP_CODEC 1
+#define DAI_CODEC_CP 2
+#define DAI_CODEC_SUB 3
+
+struct bells_drvdata {
+ int sysclk_rate;
+ int asyncclk_rate;
+};
+
+static struct bells_drvdata wm2200_drvdata = {
+ .sysclk_rate = 22579200,
+};
+
+static struct bells_drvdata wm5102_drvdata = {
+ .sysclk_rate = 45158400,
+ .asyncclk_rate = 49152000,
+};
+
+static struct bells_drvdata wm5110_drvdata = {
+ .sysclk_rate = 135475200,
+ .asyncclk_rate = 147456000,
+};
static int bells_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
struct snd_soc_codec *codec = codec_dai->codec;
+ struct bells_drvdata *bells = card->drvdata;
int ret;
if (dapm->dev != codec_dai->dev)
@@ -52,18 +68,21 @@ static int bells_set_bias_level(struct snd_soc_card *card,
switch (level) {
case SND_SOC_BIAS_PREPARE:
- if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
- ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
- ARIZONA_FLL_SRC_MCLK1,
- MCLK_RATE,
- SYSCLK_RATE);
- if (ret < 0)
- pr_err("Failed to start FLL: %d\n", ret);
+ if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
+ break;
+ ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
+ ARIZONA_FLL_SRC_MCLK1,
+ MCLK_RATE,
+ bells->sysclk_rate);
+ if (ret < 0)
+ pr_err("Failed to start FLL: %d\n", ret);
+
+ if (bells->asyncclk_rate) {
ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
ARIZONA_FLL_SRC_AIF2BCLK,
BCLK2_RATE,
- ASYNCCLK_RATE);
+ bells->asyncclk_rate);
if (ret < 0)
pr_err("Failed to start FLL: %d\n", ret);
}
@@ -80,8 +99,9 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
struct snd_soc_codec *codec = codec_dai->codec;
+ struct bells_drvdata *bells = card->drvdata;
int ret;
if (dapm->dev != codec_dai->dev)
@@ -95,10 +115,13 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
return ret;
}
- ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0);
- if (ret < 0) {
- pr_err("Failed to stop FLL: %d\n", ret);
- return ret;
+ if (bells->asyncclk_rate) {
+ ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
+ 0, 0, 0);
+ if (ret < 0) {
+ pr_err("Failed to stop FLL: %d\n", ret);
+ return ret;
+ }
}
break;
@@ -113,56 +136,73 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
static int bells_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_codec *codec = card->rtd[0].codec;
- struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
- struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
- struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai;
- struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai;
+ struct bells_drvdata *bells = card->drvdata;
+ struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
+ struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
+ struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
+ struct snd_soc_dai *aif2_dai;
+ struct snd_soc_dai *aif3_dai;
+ struct snd_soc_dai *wm9081_dai;
int ret;
- ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+ ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
+ ARIZONA_CLK_SRC_FLL1,
+ bells->sysclk_rate,
+ SND_SOC_CLOCK_IN);
if (ret != 0) {
- dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
+ dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
return ret;
}
- ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
+ ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
if (ret != 0) {
- dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
+ dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
return ret;
}
- ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
- if (ret != 0) {
+ ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+ if (ret != 0)
dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
- return ret;
- }
- ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
- ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE,
+ ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
+ SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+
+ if (card->num_rtd == DAI_CODEC_CP)
+ return 0;
+
+ ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
+ ARIZONA_CLK_SRC_FLL2,
+ bells->asyncclk_rate,
SND_SOC_CLOCK_IN);
if (ret != 0) {
- dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+ dev_err(codec->dev, "Failed to set ASYNCCLK: %d\n", ret);
return ret;
}
- ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
- WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT);
+ aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
+
+ ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
if (ret != 0) {
- dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+ dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
return ret;
}
- ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
- ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE,
- SND_SOC_CLOCK_IN);
+ if (card->num_rtd == DAI_CODEC_SUB)
+ return 0;
+
+ aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
+ wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
+
+ ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
if (ret != 0) {
- dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+ dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
return ret;
}
ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK,
- 0, WM9081_MCLK_RATE, 0);
+ 0, SYS_MCLK_RATE, 0);
if (ret != 0) {
dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
return ret;
@@ -181,22 +221,57 @@ static const struct snd_soc_pcm_stream baseband_params = {
static const struct snd_soc_pcm_stream sub_params = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
- .rate_min = WM9081_AUDIO_RATE,
- .rate_max = WM9081_AUDIO_RATE,
+ .rate_min = SYS_AUDIO_RATE,
+ .rate_max = SYS_AUDIO_RATE,
.channels_min = 2,
.channels_max = 2,
};
+static struct snd_soc_dai_link bells_dai_wm2200[] = {
+ {
+ .name = "CPU-DSP",
+ .stream_name = "CPU-DSP",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm0010-sdi1",
+ .platform_name = "samsung-i2s.0",
+ .codec_name = "spi0.0",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ },
+ {
+ .name = "DSP-CODEC",
+ .stream_name = "DSP-CODEC",
+ .cpu_dai_name = "wm0010-sdi2",
+ .codec_dai_name = "wm2200",
+ .codec_name = "wm2200.1-003a",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .params = &sub_params,
+ .ignore_suspend = 1,
+ },
+};
+
static struct snd_soc_dai_link bells_dai_wm5102[] = {
{
- .name = "CPU",
- .stream_name = "CPU",
+ .name = "CPU-DSP",
+ .stream_name = "CPU-DSP",
.cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm0010-sdi1",
+ .platform_name = "samsung-i2s.0",
+ .codec_name = "spi0.0",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ },
+ {
+ .name = "DSP-CODEC",
+ .stream_name = "DSP-CODEC",
+ .cpu_dai_name = "wm0010-sdi2",
.codec_dai_name = "wm5102-aif1",
- .platform_name = "samsung-audio",
.codec_name = "wm5102-codec",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
+ .params = &sub_params,
+ .ignore_suspend = 1,
},
{
.name = "Baseband",
@@ -224,14 +299,25 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
static struct snd_soc_dai_link bells_dai_wm5110[] = {
{
- .name = "CPU",
- .stream_name = "CPU",
+ .name = "CPU-DSP",
+ .stream_name = "CPU-DSP",
.cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm0010-sdi1",
+ .platform_name = "samsung-i2s.0",
+ .codec_name = "spi0.0",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ },
+ {
+ .name = "DSP-CODEC",
+ .stream_name = "DSP-CODEC",
+ .cpu_dai_name = "wm0010-sdi2",
.codec_dai_name = "wm5110-aif1",
- .platform_name = "samsung-audio",
.codec_name = "wm5110-codec",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
+ .params = &sub_params,
+ .ignore_suspend = 1,
},
{
.name = "Baseband",
@@ -270,6 +356,24 @@ static struct snd_soc_dapm_route bells_routes[] = {
static struct snd_soc_card bells_cards[] = {
{
+ .name = "Bells WM2200",
+ .owner = THIS_MODULE,
+ .dai_link = bells_dai_wm2200,
+ .num_links = ARRAY_SIZE(bells_dai_wm2200),
+ .codec_conf = bells_codec_conf,
+ .num_configs = ARRAY_SIZE(bells_codec_conf),
+
+ .late_probe = bells_late_probe,
+
+ .dapm_routes = bells_routes,
+ .num_dapm_routes = ARRAY_SIZE(bells_routes),
+
+ .set_bias_level = bells_set_bias_level,
+ .set_bias_level_post = bells_set_bias_level_post,
+
+ .drvdata = &wm2200_drvdata,
+ },
+ {
.name = "Bells WM5102",
.owner = THIS_MODULE,
.dai_link = bells_dai_wm5102,
@@ -284,6 +388,8 @@ static struct snd_soc_card bells_cards[] = {
.set_bias_level = bells_set_bias_level,
.set_bias_level_post = bells_set_bias_level_post,
+
+ .drvdata = &wm5102_drvdata,
},
{
.name = "Bells WM5110",
@@ -300,11 +406,13 @@ static struct snd_soc_card bells_cards[] = {
.set_bias_level = bells_set_bias_level,
.set_bias_level_post = bells_set_bias_level_post,
+
+ .drvdata = &wm5110_drvdata,
},
};
-static __devinit int bells_probe(struct platform_device *pdev)
+static int bells_probe(struct platform_device *pdev)
{
int ret;
@@ -321,7 +429,7 @@ static __devinit int bells_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bells_remove(struct platform_device *pdev)
+static int bells_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&bells_cards[pdev->id]);
@@ -335,7 +443,7 @@ static struct platform_driver bells_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = bells_probe,
- .remove = __devexit_p(bells_remove),
+ .remove = bells_remove,
};
module_platform_driver(bells_driver);
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index b70964ea448c..db87628d7630 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -432,30 +432,18 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
.pcm_free = dma_free_dma_buffers,
};
-static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)
+int asoc_dma_platform_register(struct device *dev)
{
- return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);
+ return snd_soc_register_platform(dev, &samsung_asoc_platform);
}
+EXPORT_SYMBOL_GPL(asoc_dma_platform_register);
-static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev)
+void asoc_dma_platform_unregister(struct device *dev)
{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
+ snd_soc_unregister_platform(dev);
}
-
-static struct platform_driver asoc_dma_driver = {
- .driver = {
- .name = "samsung-audio",
- .owner = THIS_MODULE,
- },
-
- .probe = samsung_asoc_platform_probe,
- .remove = __devexit_p(samsung_asoc_platform_remove),
-};
-
-module_platform_driver(asoc_dma_driver);
+EXPORT_SYMBOL_GPL(asoc_dma_platform_unregister);
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-audio");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 7d1ead77ef21..73d8c7c8a1e8 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -21,4 +21,7 @@ struct s3c_dma_params {
struct samsung_dma_ops *ops;
};
+int asoc_dma_platform_register(struct device *dev);
+void asoc_dma_platform_unregister(struct device *dev);
+
#endif
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index c23c2ae91f58..d37ede58e0a8 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -228,7 +228,7 @@ static struct snd_soc_dai_link goni_dai[] = {
.stream_name = "WM8994 HiFi",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8994-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8994-codec.0-001a",
.init = goni_wm8994_init,
.ops = &goni_hifi_ops,
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index 6e3257717c54..3870e9678b5d 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -207,7 +207,7 @@ static struct snd_soc_dai_link h1940_uda1380_dai[] = {
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "uda1380-hifi",
.init = h1940_uda1380_init,
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
.codec_name = "uda1380-codec.0-001a",
.ops = &h1940_ops,
},
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 40b00a13dcd1..d2d124f1dd1b 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -49,8 +49,6 @@ struct i2s_dai {
struct clk *clk;
/* Clock for generating I2S signals */
struct clk *op_clk;
- /* Array of clock names for op_clk */
- const char **src_clk;
/* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */
struct i2s_dai *pri_dai;
/* Pointer to the Secondary_Fifo if it has one, NULL otherwise */
@@ -423,7 +421,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
if (i2s->op_clk) {
if ((clk_id && !(mod & MOD_IMS_SYSMUX)) ||
(!clk_id && (mod & MOD_IMS_SYSMUX))) {
- clk_disable(i2s->op_clk);
+ clk_disable_unprepare(i2s->op_clk);
clk_put(i2s->op_clk);
} else {
i2s->rclk_srcrate =
@@ -432,9 +430,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
}
}
- i2s->op_clk = clk_get(&i2s->pdev->dev,
- i2s->src_clk[clk_id]);
- clk_enable(i2s->op_clk);
+ if (clk_id)
+ i2s->op_clk = clk_get(&i2s->pdev->dev,
+ "i2s_opclk1");
+ else
+ i2s->op_clk = clk_get(&i2s->pdev->dev,
+ "i2s_opclk0");
+ clk_prepare_enable(i2s->op_clk);
i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
/* Over-ride the other's */
@@ -880,7 +882,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
iounmap(i2s->addr);
return -ENOENT;
}
- clk_enable(i2s->clk);
+ clk_prepare_enable(i2s->clk);
if (other) {
other->addr = i2s->addr;
@@ -922,7 +924,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
if (i2s->quirks & QUIRK_NEED_RSTCLR)
writel(0, i2s->addr + I2SCON);
- clk_disable(i2s->clk);
+ clk_disable_unprepare(i2s->clk);
clk_put(i2s->clk);
iounmap(i2s->addr);
@@ -950,8 +952,7 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE)
-static __devinit
-struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
+static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
{
struct i2s_dai *i2s;
@@ -992,7 +993,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
return i2s;
}
-static __devinit int samsung_i2s_probe(struct platform_device *pdev)
+static int samsung_i2s_probe(struct platform_device *pdev)
{
u32 dma_pl_chan, dma_cp_chan, dma_pl_sec_chan;
struct i2s_dai *pri_dai, *sec_dai = NULL;
@@ -1007,6 +1008,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
sec_dai = dev_get_drvdata(&pdev->dev);
snd_soc_register_dai(&sec_dai->pdev->dev,
&sec_dai->i2s_dai_drv);
+ asoc_dma_platform_register(&pdev->dev);
return 0;
}
@@ -1067,7 +1069,6 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
(struct s3c2410_dma_client *)&pri_dai->dma_capture;
pri_dai->dma_playback.channel = dma_pl_chan;
pri_dai->dma_capture.channel = dma_cp_chan;
- pri_dai->src_clk = i2s_cfg->src_clk;
pri_dai->dma_playback.dma_size = 4;
pri_dai->dma_capture.dma_size = 4;
pri_dai->base = regs_base;
@@ -1088,7 +1089,6 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
(struct s3c2410_dma_client *)&sec_dai->dma_playback;
/* Use iDMA always if SysDMA not provided */
sec_dai->dma_playback.channel = dma_pl_sec_chan ? : -1;
- sec_dai->src_clk = i2s_cfg->src_clk;
sec_dai->dma_playback.dma_size = 4;
sec_dai->base = regs_base;
sec_dai->quirks = quirks;
@@ -1107,6 +1107,8 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
+ asoc_dma_platform_register(&pdev->dev);
+
return 0;
err:
release_mem_region(regs_base, resource_size(res));
@@ -1114,7 +1116,7 @@ err:
return ret;
}
-static __devexit int samsung_i2s_remove(struct platform_device *pdev)
+static int samsung_i2s_remove(struct platform_device *pdev)
{
struct i2s_dai *i2s, *other;
struct resource *res;
@@ -1135,6 +1137,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
i2s->pri_dai = NULL;
i2s->sec_dai = NULL;
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -1142,7 +1145,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
static struct platform_driver samsung_i2s_driver = {
.probe = samsung_i2s_probe,
- .remove = __devexit_p(samsung_i2s_remove),
+ .remove = samsung_i2s_remove,
.driver = {
.name = "samsung-i2s",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index c227c3163cae..a07950b0c8ce 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -416,12 +416,12 @@ static struct snd_soc_platform_driver asoc_idma_platform = {
.pcm_free = idma_free,
};
-static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
+static int asoc_idma_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
}
-static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
+static int asoc_idma_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -434,7 +434,7 @@ static struct platform_driver asoc_idma_driver = {
},
.probe = asoc_idma_platform_probe,
- .remove = __devexit_p(asoc_idma_platform_remove),
+ .remove = asoc_idma_platform_remove,
};
module_platform_driver(asoc_idma_driver);
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index 1578663a1faa..b5f6abd9d221 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -118,7 +118,7 @@ static struct snd_soc_dai_link jive_dai = {
.stream_name = "WM8750",
.cpu_dai_name = "s3c2412-i2s",
.codec_dai_name = "wm8750-hifi",
- .platform_name = "samsung-audio",
+ .platform_name = "s3c2412-i2s",
.codec_name = "wm8750.0-001a",
.init = jive_wm8750_init,
.ops = &jive_ops,
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index ee52c8a00779..bfb91f34a22a 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -145,7 +145,7 @@ static struct snd_soc_dai_link littlemill_dai[] = {
.stream_name = "CPU",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8994-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8994-codec",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
@@ -270,7 +270,7 @@ static int littlemill_late_probe(struct snd_soc_card *card)
return ret;
/* This will check device compatibility itself */
- wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+ wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL, NULL, NULL);
/* As will this */
wm8994_mic_detect(codec, &littlemill_headset, 1);
@@ -297,7 +297,7 @@ static struct snd_soc_card littlemill = {
.late_probe = littlemill_late_probe,
};
-static __devinit int littlemill_probe(struct platform_device *pdev)
+static int littlemill_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &littlemill;
int ret;
@@ -314,7 +314,7 @@ static __devinit int littlemill_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit littlemill_remove(struct platform_device *pdev)
+static int littlemill_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -330,7 +330,7 @@ static struct platform_driver littlemill_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = littlemill_probe,
- .remove = __devexit_p(littlemill_remove),
+ .remove = littlemill_remove,
};
module_platform_driver(littlemill_driver);
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c
index 69c4a5934a4d..9342fc270c2b 100644
--- a/sound/soc/samsung/ln2440sbc_alc650.c
+++ b/sound/soc/samsung/ln2440sbc_alc650.c
@@ -28,7 +28,7 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
.cpu_dai_name = "samsung-ac97",
.codec_dai_name = "ac97-hifi",
.codec_name = "ac97-codec",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-ac97",
},
};
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
index 6abf341c4a2a..570cf5229508 100644
--- a/sound/soc/samsung/lowland.c
+++ b/sound/soc/samsung/lowland.c
@@ -99,7 +99,7 @@ static struct snd_soc_dai_link lowland_dai[] = {
.stream_name = "CPU",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm5100-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm5100.1-001a",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
@@ -180,7 +180,7 @@ static struct snd_soc_card lowland = {
.num_dapm_routes = ARRAY_SIZE(audio_paths),
};
-static __devinit int lowland_probe(struct platform_device *pdev)
+static int lowland_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &lowland;
int ret;
@@ -197,7 +197,7 @@ static __devinit int lowland_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lowland_remove(struct platform_device *pdev)
+static int lowland_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -213,7 +213,7 @@ static struct platform_driver lowland_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = lowland_probe,
- .remove = __devexit_p(lowland_remove),
+ .remove = lowland_remove,
};
module_platform_driver(lowland_driver);
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 321d51134e47..c7e965f80d2e 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -364,7 +364,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
{ /* Hifi Playback - for similatious use with voice below */
.name = "WM8753",
.stream_name = "WM8753 HiFi",
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "wm8753-hifi",
.codec_name = "wm8753.0-001a",
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index c86081992dfd..13bab79ad93d 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver s3c_pcm_dai[] = {
},
};
-static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
+static int s3c_pcm_dev_probe(struct platform_device *pdev)
{
struct s3c_pcm_info *pcm;
struct resource *mem_res, *dmatx_res, *dmarx_res;
@@ -543,7 +543,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
ret = PTR_ERR(pcm->cclk);
goto err1;
}
- clk_enable(pcm->cclk);
+ clk_prepare_enable(pcm->cclk);
/* record our pcm structure for later use in the callbacks */
dev_set_drvdata(&pdev->dev, pcm);
@@ -568,7 +568,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err4;
}
- clk_enable(pcm->pclk);
+ clk_prepare_enable(pcm->pclk);
s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
+ S3C_PCM_RXFIFO;
@@ -589,27 +589,36 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
goto err5;
}
+ ret = asoc_dma_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
+ goto err6;
+ }
+
return 0;
+err6:
+ snd_soc_unregister_dai(&pdev->dev);
err5:
- clk_disable(pcm->pclk);
+ clk_disable_unprepare(pcm->pclk);
clk_put(pcm->pclk);
err4:
iounmap(pcm->regs);
err3:
release_mem_region(mem_res->start, resource_size(mem_res));
err2:
- clk_disable(pcm->cclk);
+ clk_disable_unprepare(pcm->cclk);
clk_put(pcm->cclk);
err1:
return ret;
}
-static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
+static int s3c_pcm_dev_remove(struct platform_device *pdev)
{
struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
struct resource *mem_res;
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -619,8 +628,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem_res->start, resource_size(mem_res));
- clk_disable(pcm->cclk);
- clk_disable(pcm->pclk);
+ clk_disable_unprepare(pcm->cclk);
+ clk_disable_unprepare(pcm->pclk);
clk_put(pcm->pclk);
clk_put(pcm->cclk);
@@ -629,7 +638,7 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
static struct platform_driver s3c_pcm_driver = {
.probe = s3c_pcm_dev_probe,
- .remove = __devexit_p(s3c_pcm_dev_remove),
+ .remove = s3c_pcm_dev_remove,
.driver = {
.name = "samsung-pcm",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index 21e12361a9cd..a5826ea9cad6 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -85,7 +85,7 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "uda1380-hifi",
.init = rx1950_uda1380_init,
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
.codec_name = "uda1380-codec.0-001a",
.ops = &rx1950_ops,
},
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index ac7701b3c5dc..221337716393 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -160,20 +160,38 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
.ops = &s3c2412_i2s_dai_ops,
};
-static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
+static int s3c2412_iis_dev_probe(struct platform_device *pdev)
{
- return s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+ int ret = 0;
+
+ ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+ if (ret) {
+ pr_err("failed to register the dai\n");
+ return ret;
+ }
+
+ ret = asoc_dma_platform_register(&pdev->dev);
+ if (ret) {
+ pr_err("failed to register the DMA: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+err:
+ snd_soc_unregister_dai(&pdev->dev);
+ return ret;
}
-static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
+static int s3c2412_iis_dev_remove(struct platform_device *pdev)
{
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
return 0;
}
static struct platform_driver s3c2412_iis_driver = {
.probe = s3c2412_iis_dev_probe,
- .remove = __devexit_p(s3c2412_iis_dev_remove),
+ .remove = s3c2412_iis_dev_remove,
.driver = {
.name = "s3c2412-iis",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 0aae3a3883dc..ee10e8704e97 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -465,20 +465,38 @@ static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
.ops = &s3c24xx_i2s_dai_ops,
};
-static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
+static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
{
- return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
+ int ret = 0;
+
+ ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+ if (ret) {
+ pr_err("failed to register the dai\n");
+ return ret;
+ }
+
+ ret = asoc_dma_platform_register(&pdev->dev);
+ if (ret) {
+ pr_err("failed to register the dma: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+err:
+ snd_soc_unregister_dai(&pdev->dev);
+ return ret;
}
-static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
+static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
{
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
return 0;
}
static struct platform_driver s3c24xx_iis_driver = {
.probe = s3c24xx_iis_dev_probe,
- .remove = __devexit_p(s3c24xx_iis_dev_remove),
+ .remove = s3c24xx_iis_dev_remove,
.driver = {
.name = "s3c24xx-iis",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index 335a7d8a4a8d..2c015f62ead6 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -313,8 +313,8 @@ const struct dev_pm_ops simtec_audio_pmops = {
EXPORT_SYMBOL_GPL(simtec_audio_pmops);
#endif
-int __devinit simtec_audio_core_probe(struct platform_device *pdev,
- struct snd_soc_card *card)
+int simtec_audio_core_probe(struct platform_device *pdev,
+ struct snd_soc_card *card)
{
struct platform_device *snd_dev;
int ret;
@@ -371,7 +371,7 @@ err_clk:
}
EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
-int __devexit simtec_audio_remove(struct platform_device *pdev)
+int simtec_audio_remove(struct platform_device *pdev)
{
struct platform_device *snd_dev = platform_get_drvdata(pdev);
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index 7ace6a87f41b..d8a0543cae5e 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -82,7 +82,7 @@ static struct snd_soc_dai_link simtec_dai_aic33 = {
.codec_name = "tlv320aic3x-codec.0-001a",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "tlv320aic3x-hifi",
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
.init = simtec_hermes_init,
};
@@ -99,7 +99,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
.num_dapm_routes = ARRAY_SIZE(base_map),
};
-static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
+static int simtec_audio_hermes_probe(struct platform_device *pd)
{
dev_info(&pd->dev, "probing....\n");
return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
@@ -112,7 +112,7 @@ static struct platform_driver simtec_audio_hermes_platdrv = {
.pm = simtec_audio_pm,
},
.probe = simtec_audio_hermes_probe,
- .remove = __devexit_p(simtec_audio_remove),
+ .remove = simtec_audio_remove,
};
module_platform_driver(simtec_audio_hermes_platdrv);
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index c42d5f00b0e1..1ac0d7a63a3a 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -71,7 +71,7 @@ static struct snd_soc_dai_link simtec_dai_aic23 = {
.codec_name = "tlv320aic3x-codec.0-001a",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "tlv320aic3x-hifi",
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
.init = simtec_tlv320aic23_init,
};
@@ -88,7 +88,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
.num_dapm_routes = ARRAY_SIZE(base_map),
};
-static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
+static int simtec_audio_tlv320aic23_probe(struct platform_device *pd)
{
return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
}
@@ -100,7 +100,7 @@ static struct platform_driver simtec_audio_tlv320aic23_driver = {
.pm = simtec_audio_pm,
},
.probe = simtec_audio_tlv320aic23_probe,
- .remove = __devexit_p(simtec_audio_remove),
+ .remove = simtec_audio_remove,
};
module_platform_driver(simtec_audio_tlv320aic23_driver);
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index d731042e51b0..333e1b7f06c7 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -224,7 +224,7 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
.codec_dai_name = "uda134x-hifi",
.cpu_dai_name = "s3c24xx-iis",
.ops = &s3c24xx_uda134x_ops,
- .platform_name = "samsung-audio",
+ .platform_name = "s3c24xx-iis",
};
static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index f2dcb424ea25..58ae3237ef69 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -189,7 +189,7 @@ static struct snd_soc_dai_link smartq_dai[] = {
.stream_name = "SmartQ Hi-Fi",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8750-hifi",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8750.0-0x1a",
.init = smartq_wm8987_init,
.ops = &smartq_hifi_ops,
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c
index 720ba29bb7e4..c390aad68cfb 100644
--- a/sound/soc/samsung/smdk2443_wm9710.c
+++ b/sound/soc/samsung/smdk2443_wm9710.c
@@ -24,7 +24,7 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
.cpu_dai_name = "samsung-ac97",
.codec_dai_name = "ac97-hifi",
.codec_name = "ac97-codec",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-ac97",
},
};
diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c
index beaa9c15d697..a2f2363fe1c2 100644
--- a/sound/soc/samsung/smdk_spdif.c
+++ b/sound/soc/samsung/smdk_spdif.c
@@ -151,7 +151,7 @@ static struct snd_soc_ops smdk_spdif_ops = {
static struct snd_soc_dai_link smdk_dai = {
.name = "S/PDIF",
.stream_name = "S/PDIF PCM Playback",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-spdif",
.cpu_dai_name = "samsung-spdif",
.codec_dai_name = "dit-hifi",
.codec_name = "spdif-dit",
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index ade2809cf393..7e2b710763be 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -176,7 +176,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Playback",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8580-hifi-playback",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8580.0-001b",
.ops = &smdk_ops,
},
@@ -185,7 +185,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Capture",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8580-hifi-capture",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8580.0-001b",
.init = smdk_wm8580_init_paiftx,
.ops = &smdk_ops,
@@ -195,7 +195,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Playback",
.cpu_dai_name = "samsung-i2s.x",
.codec_dai_name = "wm8580-hifi-playback",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.x",
.codec_name = "wm8580.0-001b",
.ops = &smdk_ops,
},
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
index fab5322e9f05..e43bd4294f99 100644
--- a/sound/soc/samsung/smdk_wm8580pcm.c
+++ b/sound/soc/samsung/smdk_wm8580pcm.c
@@ -135,7 +135,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Capture",
.cpu_dai_name = "samsung-pcm.0",
.codec_dai_name = "wm8580-hifi-capture",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-pcm.0",
.codec_name = "wm8580.0-001b",
.ops = &smdk_wm8580_pcm_ops,
},
@@ -153,7 +153,7 @@ static struct snd_soc_card smdk_pcm = {
* is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4),
* 2.0484Mhz, directly with MCLK both Codec and SoC.
*/
-static int __devinit snd_smdk_probe(struct platform_device *pdev)
+static int snd_smdk_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -173,7 +173,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit snd_smdk_remove(struct platform_device *pdev)
+static int snd_smdk_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&smdk_pcm);
platform_set_drvdata(pdev, NULL);
@@ -186,7 +186,7 @@ static struct platform_driver snd_smdk_driver = {
.name = "samsung-smdk-pcm",
},
.probe = snd_smdk_probe,
- .remove = __devexit_p(snd_smdk_remove),
+ .remove = snd_smdk_remove,
};
module_platform_driver(snd_smdk_driver);
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 48dd4dd9ee08..b0d0ab8bff5a 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -127,7 +127,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Pri_Dai",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8994-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8994-codec",
.init = smdk_wm8994_init_paiftx,
.ops = &smdk_ops,
@@ -136,7 +136,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Sec_Dai",
.cpu_dai_name = "samsung-i2s.4",
.codec_dai_name = "wm8994-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.4",
.codec_name = "wm8994-codec",
.ops = &smdk_ops,
},
@@ -150,7 +150,7 @@ static struct snd_soc_card smdk = {
};
-static int __devinit smdk_audio_probe(struct platform_device *pdev)
+static int smdk_audio_probe(struct platform_device *pdev)
{
int ret;
struct snd_soc_card *card = &smdk;
@@ -164,7 +164,7 @@ static int __devinit smdk_audio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit smdk_audio_remove(struct platform_device *pdev)
+static int smdk_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -179,7 +179,7 @@ static struct platform_driver smdk_audio_driver = {
.owner = THIS_MODULE,
},
.probe = smdk_audio_probe,
- .remove = __devexit_p(smdk_audio_remove),
+ .remove = smdk_audio_remove,
};
module_platform_driver(smdk_audio_driver);
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index 77ecba935119..3688a32000a2 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -116,7 +116,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.stream_name = "Primary PCM",
.cpu_dai_name = "samsung-pcm.0",
.codec_dai_name = "wm8994-aif1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-pcm.0",
.codec_name = "wm8994-codec",
.ops = &smdk_wm8994_pcm_ops,
},
@@ -129,7 +129,7 @@ static struct snd_soc_card smdk_pcm = {
.num_links = 1,
};
-static int __devinit snd_smdk_probe(struct platform_device *pdev)
+static int snd_smdk_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -143,7 +143,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit snd_smdk_remove(struct platform_device *pdev)
+static int snd_smdk_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&smdk_pcm);
platform_set_drvdata(pdev, NULL);
@@ -156,7 +156,7 @@ static struct platform_driver snd_smdk_driver = {
.name = "samsung-smdk-pcm",
},
.probe = snd_smdk_probe,
- .remove = __devexit_p(snd_smdk_remove),
+ .remove = snd_smdk_remove,
};
module_platform_driver(snd_smdk_driver);
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index 55b2ca7f3290..0d20e4ed27aa 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -42,7 +42,7 @@ static struct snd_soc_card smdk;
static struct snd_soc_dai_link smdk_dai = {
.name = "AC97",
.stream_name = "AC97 PCM",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-ac97",
.cpu_dai_name = "samsung-ac97",
.codec_dai_name = "wm9713-hifi",
.codec_name = "wm9713-codec",
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index bc24c7af02b2..5008e5bd6ed8 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -357,7 +357,7 @@ static struct snd_soc_dai_driver samsung_spdif_dai = {
.resume = spdif_resume,
};
-static __devinit int spdif_probe(struct platform_device *pdev)
+static int spdif_probe(struct platform_device *pdev)
{
struct s3c_audio_pdata *spdif_pdata;
struct resource *mem_res, *dma_res;
@@ -397,7 +397,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err0;
}
- clk_enable(spdif->pclk);
+ clk_prepare_enable(spdif->pclk);
spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
if (IS_ERR(spdif->sclk)) {
@@ -405,7 +405,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err1;
}
- clk_enable(spdif->sclk);
+ clk_prepare_enable(spdif->sclk);
/* Request S/PDIF Register's memory region */
if (!request_mem_region(mem_res->start,
@@ -437,27 +437,35 @@ static __devinit int spdif_probe(struct platform_device *pdev)
spdif->dma_playback = &spdif_stereo_out;
- return 0;
+ ret = asoc_dma_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register DMA: %d\n", ret);
+ goto err5;
+ }
+ return 0;
+err5:
+ snd_soc_unregister_dai(&pdev->dev);
err4:
iounmap(spdif->regs);
err3:
release_mem_region(mem_res->start, resource_size(mem_res));
err2:
- clk_disable(spdif->sclk);
+ clk_disable_unprepare(spdif->sclk);
clk_put(spdif->sclk);
err1:
- clk_disable(spdif->pclk);
+ clk_disable_unprepare(spdif->pclk);
clk_put(spdif->pclk);
err0:
return ret;
}
-static __devexit int spdif_remove(struct platform_device *pdev)
+static int spdif_remove(struct platform_device *pdev)
{
struct samsung_spdif_info *spdif = &spdif_info;
struct resource *mem_res;
+ asoc_dma_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
iounmap(spdif->regs);
@@ -466,9 +474,9 @@ static __devexit int spdif_remove(struct platform_device *pdev)
if (mem_res)
release_mem_region(mem_res->start, resource_size(mem_res));
- clk_disable(spdif->sclk);
+ clk_disable_unprepare(spdif->sclk);
clk_put(spdif->sclk);
- clk_disable(spdif->pclk);
+ clk_disable_unprepare(spdif->pclk);
clk_put(spdif->pclk);
return 0;
@@ -476,7 +484,7 @@ static __devexit int spdif_remove(struct platform_device *pdev)
static struct platform_driver samsung_spdif_driver = {
.probe = spdif_probe,
- .remove = __devexit_p(spdif_remove),
+ .remove = spdif_remove,
.driver = {
.name = "samsung-spdif",
.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index c7e1c28528a4..57df90d6b7c1 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -198,7 +198,7 @@ static struct snd_soc_dai_link speyside_dai[] = {
.stream_name = "CPU-DSP",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm0010-sdi1",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "spi0.0",
.init = speyside_wm0010_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@@ -320,7 +320,7 @@ static struct snd_soc_card speyside = {
.late_probe = speyside_late_probe,
};
-static __devinit int speyside_probe(struct platform_device *pdev)
+static int speyside_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &speyside;
int ret;
@@ -337,7 +337,7 @@ static __devinit int speyside_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit speyside_remove(struct platform_device *pdev)
+static int speyside_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -353,7 +353,7 @@ static struct platform_driver speyside_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = speyside_probe,
- .remove = __devexit_p(speyside_remove),
+ .remove = speyside_remove,
};
module_platform_driver(speyside_driver);
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index 9199649bf786..f21ff608a819 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -110,7 +110,7 @@ static struct snd_soc_dai_link tobermory_dai[] = {
.stream_name = "CPU",
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8962",
- .platform_name = "samsung-audio",
+ .platform_name = "samsung-i2s.0",
.codec_name = "wm8962.1-001a",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
@@ -214,7 +214,7 @@ static struct snd_soc_card tobermory = {
.late_probe = tobermory_late_probe,
};
-static __devinit int tobermory_probe(struct platform_device *pdev)
+static int tobermory_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &tobermory;
int ret;
@@ -231,7 +231,7 @@ static __devinit int tobermory_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit tobermory_remove(struct platform_device *pdev)
+static int tobermory_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -247,7 +247,7 @@ static struct platform_driver tobermory_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = tobermory_probe,
- .remove = __devexit_p(tobermory_remove),
+ .remove = tobermory_remove,
};
module_platform_driver(tobermory_driver);
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 7da20186b19e..19eff8fc4fdd 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -348,12 +348,12 @@ static struct snd_soc_platform sh7760_soc_platform = {
.pcm_free = camelot_pcm_free,
};
-static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)
+static int sh7760_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);
}
-static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)
+static int sh7760_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -366,7 +366,7 @@ static struct platform_driver sh7760_pcm_driver = {
},
.probe = sh7760_soc_platform_probe,
- .remove = __devexit_p(sh7760_soc_platform_remove),
+ .remove = sh7760_soc_platform_remove,
};
module_platform_driver(sh7760_pcm_driver);
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 9d7f30774a44..a606d0f93d1c 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
+#include <sound/pcm_params.h>
#include <sound/sh_fsi.h>
/* PortA/PortB register */
@@ -189,6 +190,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
*/
/*
+ * FSI clock
+ *
+ * FSIxCLK [CPG] (ick) -------> |
+ * |-> FSI_DIV (div)-> FSI2
+ * FSIxCK [external] (xck) ---> |
+ */
+
+/*
* struct
*/
@@ -228,6 +237,20 @@ struct fsi_stream {
dma_addr_t dma;
};
+struct fsi_clk {
+ /* see [FSI clock] */
+ struct clk *own;
+ struct clk *xck;
+ struct clk *ick;
+ struct clk *div;
+ int (*set_rate)(struct device *dev,
+ struct fsi_priv *fsi,
+ unsigned long rate);
+
+ unsigned long rate;
+ unsigned int count;
+};
+
struct fsi_priv {
void __iomem *base;
struct fsi_master *master;
@@ -236,11 +259,17 @@ struct fsi_priv {
struct fsi_stream playback;
struct fsi_stream capture;
+ struct fsi_clk clock;
+
u32 fmt;
int chan_num:16;
int clk_master:1;
+ int clk_cpg:1;
int spdif:1;
+ int enable_stream:1;
+ int bit_clk_inv:1;
+ int lr_clk_inv:1;
long rate;
};
@@ -370,6 +399,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
return fsi->spdif;
}
+static int fsi_is_enable_stream(struct fsi_priv *fsi)
+{
+ return fsi->enable_stream;
+}
+
static int fsi_is_play(struct snd_pcm_substream *substream)
{
return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
@@ -717,14 +751,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
/*
* clock function
*/
+static int fsi_clk_init(struct device *dev,
+ struct fsi_priv *fsi,
+ int xck,
+ int ick,
+ int div,
+ int (*set_rate)(struct device *dev,
+ struct fsi_priv *fsi,
+ unsigned long rate))
+{
+ struct fsi_clk *clock = &fsi->clock;
+ int is_porta = fsi_is_port_a(fsi);
+
+ clock->xck = NULL;
+ clock->ick = NULL;
+ clock->div = NULL;
+ clock->rate = 0;
+ clock->count = 0;
+ clock->set_rate = set_rate;
+
+ clock->own = devm_clk_get(dev, NULL);
+ if (IS_ERR(clock->own))
+ return -EINVAL;
+
+ /* external clock */
+ if (xck) {
+ clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
+ if (IS_ERR(clock->xck)) {
+ dev_err(dev, "can't get xck clock\n");
+ return -EINVAL;
+ }
+ if (clock->xck == clock->own) {
+ dev_err(dev, "cpu doesn't support xck clock\n");
+ return -EINVAL;
+ }
+ }
+
+ /* FSIACLK/FSIBCLK */
+ if (ick) {
+ clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb");
+ if (IS_ERR(clock->ick)) {
+ dev_err(dev, "can't get ick clock\n");
+ return -EINVAL;
+ }
+ if (clock->ick == clock->own) {
+ dev_err(dev, "cpu doesn't support ick clock\n");
+ return -EINVAL;
+ }
+ }
+
+ /* FSI-DIV */
+ if (div) {
+ clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb");
+ if (IS_ERR(clock->div)) {
+ dev_err(dev, "can't get div clock\n");
+ return -EINVAL;
+ }
+ if (clock->div == clock->own) {
+ dev_err(dev, "cpu doens't support div clock\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
+static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
+{
+ fsi->clock.rate = rate;
+}
+
+static int fsi_clk_is_valid(struct fsi_priv *fsi)
+{
+ return fsi->clock.set_rate &&
+ fsi->clock.rate;
+}
+
+static int fsi_clk_enable(struct device *dev,
+ struct fsi_priv *fsi,
+ unsigned long rate)
+{
+ struct fsi_clk *clock = &fsi->clock;
+ int ret = -EINVAL;
+
+ if (!fsi_clk_is_valid(fsi))
+ return ret;
+
+ if (0 == clock->count) {
+ ret = clock->set_rate(dev, fsi, rate);
+ if (ret < 0) {
+ fsi_clk_invalid(fsi);
+ return ret;
+ }
+
+ if (clock->xck)
+ clk_enable(clock->xck);
+ if (clock->ick)
+ clk_enable(clock->ick);
+ if (clock->div)
+ clk_enable(clock->div);
+
+ clock->count++;
+ }
+
+ return ret;
+}
+
+static int fsi_clk_disable(struct device *dev,
+ struct fsi_priv *fsi)
+{
+ struct fsi_clk *clock = &fsi->clock;
+
+ if (!fsi_clk_is_valid(fsi))
+ return -EINVAL;
+
+ if (1 == clock->count--) {
+ if (clock->xck)
+ clk_disable(clock->xck);
+ if (clock->ick)
+ clk_disable(clock->ick);
+ if (clock->div)
+ clk_disable(clock->div);
+ }
+
+ return 0;
+}
+
+static int fsi_clk_set_ackbpf(struct device *dev,
+ struct fsi_priv *fsi,
+ int ackmd, int bpfmd)
+{
+ u32 data = 0;
+
+ /* check ackmd/bpfmd relationship */
+ if (bpfmd > ackmd) {
+ dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd);
+ return -EINVAL;
+ }
+
+ /* ACKMD */
+ switch (ackmd) {
+ case 512:
+ data |= (0x0 << 12);
+ break;
+ case 256:
+ data |= (0x1 << 12);
+ break;
+ case 128:
+ data |= (0x2 << 12);
+ break;
+ case 64:
+ data |= (0x3 << 12);
+ break;
+ case 32:
+ data |= (0x4 << 12);
+ break;
+ default:
+ dev_err(dev, "unsupported ackmd (%d)\n", ackmd);
+ return -EINVAL;
+ }
+
+ /* BPFMD */
+ switch (bpfmd) {
+ case 32:
+ data |= (0x0 << 8);
+ break;
+ case 64:
+ data |= (0x1 << 8);
+ break;
+ case 128:
+ data |= (0x2 << 8);
+ break;
+ case 256:
+ data |= (0x3 << 8);
+ break;
+ case 512:
+ data |= (0x4 << 8);
+ break;
+ case 16:
+ data |= (0x7 << 8);
+ break;
+ default:
+ dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd);
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd);
+
+ fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
+ udelay(10);
+
+ return 0;
+}
+
+static int fsi_clk_set_rate_external(struct device *dev,
+ struct fsi_priv *fsi,
+ unsigned long rate)
+{
+ struct clk *xck = fsi->clock.xck;
+ struct clk *ick = fsi->clock.ick;
+ unsigned long xrate;
+ int ackmd, bpfmd;
+ int ret = 0;
+
+ /* check clock rate */
+ xrate = clk_get_rate(xck);
+ if (xrate % rate) {
+ dev_err(dev, "unsupported clock rate\n");
+ return -EINVAL;
+ }
+
+ clk_set_parent(ick, xck);
+ clk_set_rate(ick, xrate);
+
+ bpfmd = fsi->chan_num * 32;
+ ackmd = xrate / rate;
+
+ dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate);
+
+ ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+ if (ret < 0)
+ dev_err(dev, "%s failed", __func__);
+
+ return ret;
+}
+
+static int fsi_clk_set_rate_cpg(struct device *dev,
+ struct fsi_priv *fsi,
+ unsigned long rate)
+{
+ struct clk *ick = fsi->clock.ick;
+ struct clk *div = fsi->clock.div;
+ unsigned long target = 0; /* 12288000 or 11289600 */
+ unsigned long actual, cout;
+ unsigned long diff, min;
+ unsigned long best_cout, best_act;
+ int adj;
+ int ackmd, bpfmd;
+ int ret = -EINVAL;
+
+ if (!(12288000 % rate))
+ target = 12288000;
+ if (!(11289600 % rate))
+ target = 11289600;
+ if (!target) {
+ dev_err(dev, "unsupported rate\n");
+ return ret;
+ }
+
+ bpfmd = fsi->chan_num * 32;
+ ackmd = target / rate;
+ ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+ if (ret < 0) {
+ dev_err(dev, "%s failed", __func__);
+ return ret;
+ }
+
+ /*
+ * The clock flow is
+ *
+ * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
+ *
+ * But, it needs to find best match of CPG and FSI_DIV
+ * combination, since it is difficult to generate correct
+ * frequency of audio clock from ick clock only.
+ * Because ick is created from its parent clock.
+ *
+ * target = rate x [512/256/128/64]fs
+ * cout = round(target x adjustment)
+ * actual = cout / adjustment (by FSI-DIV) ~= target
+ * audio = actual
+ */
+ min = ~0;
+ best_cout = 0;
+ best_act = 0;
+ for (adj = 1; adj < 0xffff; adj++) {
+
+ cout = target * adj;
+ if (cout > 100000000) /* max clock = 100MHz */
+ break;
+
+ /* cout/actual audio clock */
+ cout = clk_round_rate(ick, cout);
+ actual = cout / adj;
+
+ /* find best frequency */
+ diff = abs(actual - target);
+ if (diff < min) {
+ min = diff;
+ best_cout = cout;
+ best_act = actual;
+ }
+ }
+
+ ret = clk_set_rate(ick, best_cout);
+ if (ret < 0) {
+ dev_err(dev, "ick clock failed\n");
+ return -EIO;
+ }
+
+ ret = clk_set_rate(div, clk_round_rate(div, best_act));
+ if (ret < 0) {
+ dev_err(dev, "div clock failed\n");
+ return -EIO;
+ }
+
+ dev_dbg(dev, "ick/div = %ld/%ld\n",
+ clk_get_rate(ick), clk_get_rate(div));
+
+ return ret;
+}
+
static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
set_rate_func set_rate = fsi_get_info_set_rate(fsi);
int ret;
- if (!set_rate)
- return 0;
+ /*
+ * CAUTION
+ *
+ * set_rate will be deleted
+ */
+ if (!set_rate) {
+ if (enable)
+ return fsi_clk_enable(dev, fsi, rate);
+ else
+ return fsi_clk_disable(dev, fsi);
+ }
ret = set_rate(dev, rate, enable);
if (ret < 0) /* error */
@@ -792,10 +1147,9 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
*/
static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
int i;
- if (enable_stream) {
+ if (fsi_is_enable_stream(fsi)) {
/*
* stream mode
* see
@@ -953,8 +1307,6 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
-
/*
* we can use 16bit stream mode
* when "playback" and "16bit data"
@@ -962,7 +1314,7 @@ static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
* see
* fsi_pio_push16()
*/
- if (enable_stream)
+ if (fsi_is_enable_stream(fsi))
io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
else
@@ -1296,6 +1648,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
/* clock inversion (CKG2) */
data = 0;
+ if (fsi->bit_clk_inv)
+ data |= (1 << 0);
+ if (fsi->lr_clk_inv)
+ data |= (1 << 4);
+ if (fsi_is_clk_master(fsi))
+ data <<= 8;
+ /* FIXME
+ *
+ * SH_FSI_xxx_INV style will be removed
+ */
if (SH_FSI_LRM_INV & flags)
data |= 1 << 12;
if (SH_FSI_BRM_INV & flags)
@@ -1334,14 +1696,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
/* fifo init */
fsi_fifo_init(fsi, io, dev);
+ /* start master clock */
+ if (fsi_is_clk_master(fsi))
+ return fsi_set_master_clk(dev, fsi, fsi->rate, 1);
+
return 0;
}
-static void fsi_hw_shutdown(struct fsi_priv *fsi,
+static int fsi_hw_shutdown(struct fsi_priv *fsi,
struct device *dev)
{
+ /* stop master clock */
if (fsi_is_clk_master(fsi))
- fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+ return fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+
+ return 0;
}
static int fsi_dai_startup(struct snd_pcm_substream *substream,
@@ -1349,6 +1718,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
+ fsi_clk_invalid(fsi);
fsi->rate = 0;
return 0;
@@ -1359,6 +1729,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
+ fsi_clk_invalid(fsi);
fsi->rate = 0;
}
@@ -1372,13 +1743,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
fsi_stream_init(fsi, io, substream);
- fsi_hw_startup(fsi, io, dai->dev);
- ret = fsi_stream_transfer(io);
- if (0 == ret)
+ if (!ret)
+ ret = fsi_hw_startup(fsi, io, dai->dev);
+ if (!ret)
+ ret = fsi_stream_transfer(io);
+ if (!ret)
fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
- fsi_hw_shutdown(fsi, dai->dev);
+ if (!ret)
+ ret = fsi_hw_shutdown(fsi, dai->dev);
fsi_stream_stop(fsi, io);
fsi_stream_quit(fsi, io);
break;
@@ -1414,7 +1788,6 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
fsi->chan_num = 2;
- fsi->spdif = 1;
return 0;
}
@@ -1423,7 +1796,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
set_rate_func set_rate = fsi_get_info_set_rate(fsi);
- u32 flags = fsi_get_info_flags(fsi);
int ret;
/* set master/slave audio interface */
@@ -1437,23 +1809,50 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
}
- if (fsi_is_clk_master(fsi) && !set_rate) {
- dev_err(dai->dev, "platform doesn't have set_rate\n");
- return -EINVAL;
- }
-
- /* set format */
- switch (flags & SH_FSI_FMT_MASK) {
- case SH_FSI_FMT_DAI:
- ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ /* set clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_IF:
+ fsi->bit_clk_inv = 0;
+ fsi->lr_clk_inv = 1;
break;
- case SH_FSI_FMT_SPDIF:
- ret = fsi_set_fmt_spdif(fsi);
+ case SND_SOC_DAIFMT_IB_NF:
+ fsi->bit_clk_inv = 1;
+ fsi->lr_clk_inv = 0;
break;
+ case SND_SOC_DAIFMT_IB_IF:
+ fsi->bit_clk_inv = 1;
+ fsi->lr_clk_inv = 1;
+ break;
+ case SND_SOC_DAIFMT_NB_NF:
default:
- ret = -EINVAL;
+ fsi->bit_clk_inv = 0;
+ fsi->lr_clk_inv = 0;
+ break;
+ }
+
+ if (fsi_is_clk_master(fsi)) {
+ /*
+ * CAUTION
+ *
+ * set_rate will be deleted
+ */
+ if (set_rate)
+ dev_warn(dai->dev, "set_rate will be removed soon\n");
+
+ if (fsi->clk_cpg)
+ fsi_clk_init(dai->dev, fsi, 0, 1, 1,
+ fsi_clk_set_rate_cpg);
+ else
+ fsi_clk_init(dai->dev, fsi, 1, 1, 0,
+ fsi_clk_set_rate_external);
}
+ /* set format */
+ if (fsi_is_spdif(fsi))
+ ret = fsi_set_fmt_spdif(fsi);
+ else
+ ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+
return ret;
}
@@ -1462,19 +1861,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- long rate = params_rate(params);
- int ret;
- if (!fsi_is_clk_master(fsi))
- return 0;
-
- ret = fsi_set_master_clk(dai->dev, fsi, rate, 1);
- if (ret < 0)
- return ret;
-
- fsi->rate = rate;
+ if (fsi_is_clk_master(fsi)) {
+ fsi->rate = params_rate(params);
+ fsi_clk_valid(fsi, fsi->rate);
+ }
- return ret;
+ return 0;
}
static const struct snd_soc_dai_ops fsi_dai_ops = {
@@ -1498,7 +1891,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
.rates = FSI_RATES,
.rate_min = 8000,
.rate_max = 192000,
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = 64 * 1024,
.period_bytes_min = 32,
@@ -1586,14 +1979,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
.playback = {
.rates = FSI_RATES,
.formats = FSI_FMTS,
- .channels_min = 1,
- .channels_max = 8,
+ .channels_min = 2,
+ .channels_max = 2,
},
.capture = {
.rates = FSI_RATES,
.formats = FSI_FMTS,
- .channels_min = 1,
- .channels_max = 8,
+ .channels_min = 2,
+ .channels_max = 2,
},
.ops = &fsi_dai_ops,
},
@@ -1602,14 +1995,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
.playback = {
.rates = FSI_RATES,
.formats = FSI_FMTS,
- .channels_min = 1,
- .channels_max = 8,
+ .channels_min = 2,
+ .channels_max = 2,
},
.capture = {
.rates = FSI_RATES,
.formats = FSI_FMTS,
- .channels_min = 1,
- .channels_max = 8,
+ .channels_min = 2,
+ .channels_max = 2,
},
.ops = &fsi_dai_ops,
},
@@ -1624,15 +2017,29 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/*
* platform function
*/
-static void fsi_handler_init(struct fsi_priv *fsi)
+static void fsi_port_info_init(struct fsi_priv *fsi,
+ struct sh_fsi_port_info *info)
+{
+ if (info->flags & SH_FSI_FMT_SPDIF)
+ fsi->spdif = 1;
+
+ if (info->flags & SH_FSI_CLK_CPG)
+ fsi->clk_cpg = 1;
+
+ if (info->flags & SH_FSI_ENABLE_STREAM_MODE)
+ fsi->enable_stream = 1;
+}
+
+static void fsi_handler_init(struct fsi_priv *fsi,
+ struct sh_fsi_port_info *info)
{
fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */
fsi->playback.priv = fsi;
fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */
fsi->capture.priv = fsi;
- if (fsi->info->tx_id) {
- fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
+ if (info->tx_id) {
+ fsi->playback.slave.shdma_slave.slave_id = info->tx_id;
fsi->playback.handler = &fsi_dma_push_handler;
}
}
@@ -1642,10 +2049,16 @@ static int fsi_probe(struct platform_device *pdev)
struct fsi_master *master;
const struct platform_device_id *id_entry;
struct sh_fsi_platform_info *info = pdev->dev.platform_data;
+ struct sh_fsi_port_info nul_info, *pinfo;
+ struct fsi_priv *fsi;
struct resource *res;
unsigned int irq;
int ret;
+ nul_info.flags = 0;
+ nul_info.tx_id = 0;
+ nul_info.rx_id = 0;
+
id_entry = pdev->id_entry;
if (!id_entry) {
dev_err(&pdev->dev, "unknown fsi device\n");
@@ -1678,22 +2091,28 @@ static int fsi_probe(struct platform_device *pdev)
spin_lock_init(&master->lock);
/* FSI A setting */
- master->fsia.base = master->base;
- master->fsia.master = master;
- master->fsia.info = &info->port_a;
- fsi_handler_init(&master->fsia);
- ret = fsi_stream_probe(&master->fsia, &pdev->dev);
+ pinfo = (info) ? &info->port_a : &nul_info;
+ fsi = &master->fsia;
+ fsi->base = master->base;
+ fsi->master = master;
+ fsi->info = pinfo;
+ fsi_port_info_init(fsi, pinfo);
+ fsi_handler_init(fsi, pinfo);
+ ret = fsi_stream_probe(fsi, &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "FSIA stream probe failed\n");
return ret;
}
/* FSI B setting */
- master->fsib.base = master->base + 0x40;
- master->fsib.master = master;
- master->fsib.info = &info->port_b;
- fsi_handler_init(&master->fsib);
- ret = fsi_stream_probe(&master->fsib, &pdev->dev);
+ pinfo = (info) ? &info->port_b : &nul_info;
+ fsi = &master->fsib;
+ fsi->base = master->base + 0x40;
+ fsi->master = master;
+ fsi->info = pinfo;
+ fsi_port_info_init(fsi, pinfo);
+ fsi_handler_init(fsi, pinfo);
+ ret = fsi_stream_probe(fsi, &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "FSIB stream probe failed\n");
goto exit_fsia;
@@ -1702,7 +2121,7 @@ static int fsi_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
dev_set_drvdata(&pdev->dev, master);
- ret = request_irq(irq, &fsi_interrupt, 0,
+ ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
id_entry->name, master);
if (ret) {
dev_err(&pdev->dev, "irq request err\n");
@@ -1712,7 +2131,7 @@ static int fsi_probe(struct platform_device *pdev)
ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
if (ret < 0) {
dev_err(&pdev->dev, "cannot snd soc register\n");
- goto exit_free_irq;
+ goto exit_fsib;
}
ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
@@ -1726,8 +2145,6 @@ static int fsi_probe(struct platform_device *pdev)
exit_snd_soc:
snd_soc_unregister_platform(&pdev->dev);
-exit_free_irq:
- free_irq(irq, master);
exit_fsib:
pm_runtime_disable(&pdev->dev);
fsi_stream_remove(&master->fsib);
@@ -1743,7 +2160,6 @@ static int fsi_remove(struct platform_device *pdev)
master = dev_get_drvdata(&pdev->dev);
- free_irq(master->irq, master);
pm_runtime_disable(&pdev->dev);
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
@@ -1774,10 +2190,6 @@ static void __fsi_resume(struct fsi_priv *fsi,
return;
fsi_hw_startup(fsi, io, dev);
-
- if (fsi_is_clk_master(fsi) && fsi->rate)
- fsi_set_master_clk(dev, fsi, fsi->rate, 1);
-
fsi_stream_start(fsi, io);
}
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index 3474d7befe5a..4cc2d64ef476 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -310,13 +310,13 @@ static struct snd_soc_dai_driver sh4_hac_dai[] = {
#endif
};
-static int __devinit hac_soc_platform_probe(struct platform_device *pdev)
+static int hac_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
ARRAY_SIZE(sh4_hac_dai));
}
-static int __devexit hac_soc_platform_remove(struct platform_device *pdev)
+static int hac_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
return 0;
@@ -329,7 +329,7 @@ static struct platform_driver hac_pcm_driver = {
},
.probe = hac_soc_platform_probe,
- .remove = __devexit_p(hac_soc_platform_remove),
+ .remove = hac_soc_platform_remove,
};
module_platform_driver(hac_pcm_driver);
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 52d4c17b1232..34facdc9e4ac 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -726,7 +726,7 @@ static struct snd_soc_dai_driver siu_i2s_dai = {
.ops = &siu_dai_ops,
};
-static int __devinit siu_probe(struct platform_device *pdev)
+static int siu_probe(struct platform_device *pdev)
{
const struct firmware *fw_entry;
struct resource *res, *region;
@@ -815,7 +815,7 @@ ereqfw:
return ret;
}
-static int __devexit siu_remove(struct platform_device *pdev)
+static int siu_remove(struct platform_device *pdev)
{
struct siu_info *info = dev_get_drvdata(&pdev->dev);
struct resource *res;
@@ -843,7 +843,7 @@ static struct platform_driver siu_driver = {
.name = "siu-pcm-audio",
},
.probe = siu_probe,
- .remove = __devexit_p(siu_remove),
+ .remove = siu_remove,
};
module_platform_driver(siu_driver);
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index ff82b56a8860..c8e73a703934 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -379,13 +379,13 @@ static struct snd_soc_dai_driver sh4_ssi_dai[] = {
#endif
};
-static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
+static int sh4_soc_dai_probe(struct platform_device *pdev)
{
return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
ARRAY_SIZE(sh4_ssi_dai));
}
-static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
+static int sh4_soc_dai_remove(struct platform_device *pdev)
{
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
return 0;
@@ -398,7 +398,7 @@ static struct platform_driver sh4_ssi_driver = {
},
.probe = sh4_soc_dai_probe,
- .remove = __devexit_p(sh4_soc_dai_remove),
+ .remove = sh4_soc_dai_remove,
};
module_platform_driver(sh4_ssi_driver);
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 9d56f0218f41..e72f55428f0b 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -88,7 +88,7 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
ret = snd_soc_write(codec, i, val);
if (ret)
return ret;
- dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
+ dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
i, val);
}
return 0;
@@ -156,7 +156,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
/* Fall back to flat compression */
if (i == ARRAY_SIZE(cache_types)) {
- dev_warn(codec->dev, "Could not match compress type: %d\n",
+ dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
codec->compress_type);
i = 0;
}
@@ -166,7 +166,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
if (codec->cache_ops->init) {
if (codec->cache_ops->name)
- dev_dbg(codec->dev, "Initializing %s cache for %s codec\n",
+ dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
codec->cache_ops->name, codec->name);
return codec->cache_ops->init(codec);
}
@@ -181,7 +181,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
{
if (codec->cache_ops && codec->cache_ops->exit) {
if (codec->cache_ops->name)
- dev_dbg(codec->dev, "Destroying %s cache for %s codec\n",
+ dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
codec->cache_ops->name, codec->name);
return codec->cache_ops->exit(codec);
}
@@ -265,7 +265,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
name = "unknown";
if (codec->cache_ops->name)
- dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
+ dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
codec->cache_ops->name, codec->name);
trace_snd_soc_cache_sync(codec, name, "start");
ret = codec->cache_ops->sync(codec);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 10d21be383f6..9c768bcb98a6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -271,7 +271,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root = debugfs_create_dir(codec->name,
debugfs_card_root);
if (!codec->debugfs_codec_root) {
- dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
+ dev_warn(codec->dev, "ASoC: Failed to create codec debugfs"
+ " directory\n");
return;
}
@@ -284,7 +285,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root,
codec, &codec_reg_fops);
if (!codec->debugfs_reg)
- dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
+ dev_warn(codec->dev, "ASoC: Failed to create codec register"
+ " debugfs file\n");
snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
}
@@ -302,7 +304,7 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
debugfs_card_root);
if (!platform->debugfs_platform_root) {
dev_warn(platform->dev,
- "Failed to create platform debugfs directory\n");
+ "ASoC: Failed to create platform debugfs directory\n");
return;
}
@@ -430,7 +432,7 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
&card->pop_time);
if (!card->debugfs_pop_time)
dev_warn(card->dev,
- "Failed to create pop time debugfs file\n");
+ "ASoC: Failed to create pop time debugfs file\n");
}
static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
@@ -475,7 +477,7 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
!strcmp(card->rtd[i].dai_link->name, dai_link))
return card->rtd[i].pcm->streams[stream].substream;
}
- dev_dbg(card->dev, "failed to find dai link %s\n", dai_link);
+ dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link);
return NULL;
}
EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
@@ -489,7 +491,7 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
if (!strcmp(card->rtd[i].dai_link->name, dai_link))
return &card->rtd[i];
}
- dev_dbg(card->dev, "failed to find rtd %s\n", dai_link);
+ dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link);
return NULL;
}
EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
@@ -519,7 +521,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
codec->card->snd_card->number, 0, codec->name);
err = device_register(&codec->ac97->dev);
if (err < 0) {
- snd_printk(KERN_ERR "Can't register ac97 bus\n");
+ dev_err(codec->dev, "ASoC: Can't register ac97 bus\n");
codec->ac97->dev.bus = NULL;
return err;
}
@@ -628,7 +630,8 @@ int snd_soc_suspend(struct device *dev)
*/
if (codec->dapm.idle_bias_off) {
dev_dbg(codec->dev,
- "idle_bias_off CODEC on over suspend\n");
+ "ASoC: idle_bias_off CODEC on"
+ " over suspend\n");
break;
}
case SND_SOC_BIAS_OFF:
@@ -639,7 +642,8 @@ int snd_soc_suspend(struct device *dev)
regcache_mark_dirty(codec->control_data);
break;
default:
- dev_dbg(codec->dev, "CODEC is on over suspend\n");
+ dev_dbg(codec->dev, "ASoC: CODEC is on"
+ " over suspend\n");
break;
}
}
@@ -676,7 +680,7 @@ static void soc_resume_deferred(struct work_struct *work)
* so userspace apps are blocked from touching us
*/
- dev_dbg(card->dev, "starting resume work\n");
+ dev_dbg(card->dev, "ASoC: starting resume work\n");
/* Bring us up into D2 so that DAPM starts enabling things */
snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
@@ -708,7 +712,8 @@ static void soc_resume_deferred(struct work_struct *work)
codec->suspended = 0;
break;
default:
- dev_dbg(codec->dev, "CODEC was on over suspend\n");
+ dev_dbg(codec->dev, "ASoC: CODEC was on over"
+ " suspend\n");
break;
}
}
@@ -758,7 +763,7 @@ static void soc_resume_deferred(struct work_struct *work)
if (card->resume_post)
card->resume_post(card);
- dev_dbg(card->dev, "resume work completed\n");
+ dev_dbg(card->dev, "ASoC: resume work completed\n");
/* userspace can access us now we are back as we were before */
snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
@@ -790,12 +795,12 @@ int snd_soc_resume(struct device *dev)
ac97_control |= cpu_dai->driver->ac97_control;
}
if (ac97_control) {
- dev_dbg(dev, "Resuming AC97 immediately\n");
+ dev_dbg(dev, "ASoC: Resuming AC97 immediately\n");
soc_resume_deferred(&card->deferred_resume_work);
} else {
- dev_dbg(dev, "Scheduling resume work\n");
+ dev_dbg(dev, "ASoC: Scheduling resume work\n");
if (!schedule_work(&card->deferred_resume_work))
- dev_err(dev, "resume work item may be lost\n");
+ dev_err(dev, "ASoC: resume work item may be lost\n");
}
return 0;
@@ -818,7 +823,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
struct snd_soc_dai *codec_dai, *cpu_dai;
const char *platform_name;
- dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
+ dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
/* Find CPU DAI from registered DAIs*/
list_for_each_entry(cpu_dai, &dai_list, list) {
@@ -836,7 +841,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}
if (!rtd->cpu_dai) {
- dev_err(card->dev, "CPU DAI %s not registered\n",
+ dev_err(card->dev, "ASoC: CPU DAI %s not registered\n",
dai_link->cpu_dai_name);
return -EPROBE_DEFER;
}
@@ -867,14 +872,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}
if (!rtd->codec_dai) {
- dev_err(card->dev, "CODEC DAI %s not registered\n",
+ dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
dai_link->codec_dai_name);
return -EPROBE_DEFER;
}
}
if (!rtd->codec) {
- dev_err(card->dev, "CODEC %s not registered\n",
+ dev_err(card->dev, "ASoC: CODEC %s not registered\n",
dai_link->codec_name);
return -EPROBE_DEFER;
}
@@ -898,7 +903,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
rtd->platform = platform;
}
if (!rtd->platform) {
- dev_err(card->dev, "platform %s not registered\n",
+ dev_err(card->dev, "ASoC: platform %s not registered\n",
dai_link->platform_name);
return -EPROBE_DEFER;
}
@@ -915,8 +920,8 @@ static int soc_remove_platform(struct snd_soc_platform *platform)
if (platform->driver->remove) {
ret = platform->driver->remove(platform);
if (ret < 0)
- pr_err("asoc: failed to remove %s: %d\n",
- platform->name, ret);
+ dev_err(platform->dev, "ASoC: failed to remove %d\n",
+ ret);
}
/* Make sure all DAPM widgets are freed */
@@ -937,9 +942,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
if (codec->driver->remove) {
err = codec->driver->remove(codec);
if (err < 0)
- dev_err(codec->dev,
- "asoc: failed to remove %s: %d\n",
- codec->name, err);
+ dev_err(codec->dev, "ASoC: failed to remove %d\n", err);
}
/* Make sure all DAPM widgets are freed */
@@ -971,8 +974,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
- pr_err("asoc: failed to remove %s: %d\n",
- codec_dai->name, err);
+ dev_err(codec_dai->dev,
+ "ASoC: failed to remove %s: %d\n",
+ codec_dai->name, err);
}
codec_dai->probed = 0;
list_del(&codec_dai->card_list);
@@ -984,8 +988,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
- pr_err("asoc: failed to remove %s: %d\n",
- cpu_dai->name, err);
+ dev_err(cpu_dai->dev,
+ "ASoC: failed to remove %s: %d\n",
+ cpu_dai->name, err);
}
cpu_dai->probed = 0;
list_del(&cpu_dai->card_list);
@@ -1099,8 +1104,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
ret = driver->probe(codec);
if (ret < 0) {
dev_err(codec->dev,
- "asoc: failed to probe CODEC %s: %d\n",
- codec->name, ret);
+ "ASoC: failed to probe CODEC %d\n", ret);
goto err_probe;
}
}
@@ -1163,8 +1167,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
ret = driver->probe(platform);
if (ret < 0) {
dev_err(platform->dev,
- "asoc: failed to probe platform %s: %d\n",
- platform->name, ret);
+ "ASoC: failed to probe platform %d\n", ret);
goto err_probe;
}
}
@@ -1229,7 +1232,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
else if (dailess && aux_dev->init)
ret = aux_dev->init(&codec->dapm);
if (ret < 0) {
- dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret);
+ dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret);
return ret;
}
codec->name_prefix = temp;
@@ -1253,7 +1256,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
ret = device_add(rtd->dev);
if (ret < 0) {
dev_err(card->dev,
- "asoc: failed to register runtime device: %d\n", ret);
+ "ASoC: failed to register runtime device: %d\n", ret);
return ret;
}
rtd->dev_registered = 1;
@@ -1262,14 +1265,13 @@ static int soc_post_component_init(struct snd_soc_card *card,
ret = snd_soc_dapm_sys_add(rtd->dev);
if (ret < 0)
dev_err(codec->dev,
- "asoc: failed to add codec dapm sysfs entries: %d\n",
- ret);
+ "ASoC: failed to add codec dapm sysfs entries: %d\n", ret);
/* add codec sysfs entries */
ret = device_create_file(rtd->dev, &dev_attr_codec_reg);
if (ret < 0)
dev_err(codec->dev,
- "asoc: failed to add codec sysfs files: %d\n", ret);
+ "ASoC: failed to add codec sysfs files: %d\n", ret);
#ifdef CONFIG_DEBUG_FS
/* add DPCM sysfs entries */
@@ -1278,7 +1280,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
ret = soc_dpcm_debugfs_add(rtd);
if (ret < 0)
- dev_err(rtd->dev, "asoc: failed to add dpcm sysfs entries: %d\n", ret);
+ dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret);
out:
#endif
@@ -1333,7 +1335,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
struct snd_soc_dapm_widget *play_w, *capture_w;
int ret;
- dev_dbg(card->dev, "probe %s dai link %d late %d\n",
+ dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
card->name, num, order);
/* config components */
@@ -1359,8 +1361,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->probe) {
ret = cpu_dai->driver->probe(cpu_dai);
if (ret < 0) {
- pr_err("asoc: failed to probe CPU DAI %s: %d\n",
- cpu_dai->name, ret);
+ dev_err(cpu_dai->dev,
+ "ASoC: failed to probe CPU DAI %s: %d\n",
+ cpu_dai->name, ret);
module_put(cpu_dai->dev->driver->owner);
return ret;
}
@@ -1375,8 +1378,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
- pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
- codec_dai->name, ret);
+ dev_err(codec_dai->dev,
+ "ASoC: failed to probe CODEC DAI %s: %d\n",
+ codec_dai->name, ret);
return ret;
}
}
@@ -1396,13 +1400,14 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
if (ret < 0)
- pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
+ dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n",
+ ret);
if (cpu_dai->driver->compress_dai) {
/*create compress_device"*/
ret = soc_new_compress(rtd, num);
if (ret < 0) {
- pr_err("asoc: can't create compress %s\n",
+ dev_err(card->dev, "ASoC: can't create compress %s\n",
dai_link->stream_name);
return ret;
}
@@ -1412,7 +1417,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
/* create the pcm */
ret = soc_new_pcm(rtd, num);
if (ret < 0) {
- pr_err("asoc: can't create pcm %s :%d\n",
+ dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
dai_link->stream_name, ret);
return ret;
}
@@ -1424,7 +1429,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
capture_w, play_w);
if (ret != 0) {
- dev_err(card->dev, "Can't link %s to %s: %d\n",
+ dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
play_w->name, capture_w->name, ret);
return ret;
}
@@ -1436,7 +1441,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
capture_w, play_w);
if (ret != 0) {
- dev_err(card->dev, "Can't link %s to %s: %d\n",
+ dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
play_w->name, capture_w->name, ret);
return ret;
}
@@ -1473,7 +1478,8 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
ret = soc_ac97_dev_register(rtd->codec);
if (ret < 0) {
- pr_err("asoc: AC97 device register failed:%d\n", ret);
+ dev_err(rtd->codec->dev,
+ "ASoC: AC97 device register failed: %d\n", ret);
return ret;
}
@@ -1502,7 +1508,7 @@ static int soc_check_aux_dev(struct snd_soc_card *card, int num)
return 0;
}
- dev_err(card->dev, "%s not registered\n", aux_dev->codec_name);
+ dev_err(card->dev, "ASoC: %s not registered\n", aux_dev->codec_name);
return -EPROBE_DEFER;
}
@@ -1518,7 +1524,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
if (!strcmp(codec->name, aux_dev->codec_name)) {
if (codec->probed) {
dev_err(codec->dev,
- "asoc: codec already probed");
+ "ASoC: codec already probed");
ret = -EBUSY;
goto out;
}
@@ -1526,7 +1532,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
}
}
/* codec not found */
- dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
+ dev_err(card->dev, "ASoC: codec %s not found", aux_dev->codec_name);
return -EPROBE_DEFER;
found:
@@ -1569,8 +1575,8 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
codec->compress_type = compress_type;
ret = snd_soc_cache_init(codec);
if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache compression type: %d\n",
- ret);
+ dev_err(codec->dev, "ASoC: Failed to set cache compression"
+ " type: %d\n", ret);
return ret;
}
codec->cache_init = 1;
@@ -1626,8 +1632,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
card->owner, 0, &card->snd_card);
if (ret < 0) {
- pr_err("asoc: can't create sound card for card %s: %d\n",
- card->name, ret);
+ dev_err(card->dev, "ASoC: can't create sound card for"
+ " card %s: %d\n", card->name, ret);
goto base_error;
}
card->snd_card->dev = card->dev;
@@ -1663,8 +1669,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_links; i++) {
ret = soc_probe_link_components(card, i, order);
if (ret < 0) {
- pr_err("asoc: failed to instantiate card %s: %d\n",
- card->name, ret);
+ dev_err(card->dev,
+ "ASoC: failed to instantiate card %d\n",
+ ret);
goto probe_dai_err;
}
}
@@ -1676,8 +1683,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_links; i++) {
ret = soc_probe_link_dais(card, i, order);
if (ret < 0) {
- pr_err("asoc: failed to instantiate card %s: %d\n",
- card->name, ret);
+ dev_err(card->dev,
+ "ASoC: failed to instantiate card %d\n",
+ ret);
goto probe_dai_err;
}
}
@@ -1686,8 +1694,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_aux_devs; i++) {
ret = soc_probe_aux_dev(card, i);
if (ret < 0) {
- pr_err("asoc: failed to add auxiliary devices %s: %d\n",
- card->name, ret);
+ dev_err(card->dev,
+ "ASoC: failed to add auxiliary devices %d\n",
+ ret);
goto probe_aux_dev_err;
}
}
@@ -1712,7 +1721,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
dai_fmt);
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].codec_dai->dev,
- "Failed to set DAI format: %d\n",
+ "ASoC: Failed to set DAI format: %d\n",
ret);
}
@@ -1723,7 +1732,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
dai_fmt);
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].cpu_dai->dev,
- "Failed to set DAI format: %d\n",
+ "ASoC: Failed to set DAI format: %d\n",
ret);
} else if (dai_fmt) {
/* Flip the polarity for the "CPU" end */
@@ -1748,7 +1757,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
dai_fmt);
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].cpu_dai->dev,
- "Failed to set DAI format: %d\n",
+ "ASoC: Failed to set DAI format: %d\n",
ret);
}
}
@@ -1775,7 +1784,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
if (card->late_probe) {
ret = card->late_probe(card);
if (ret < 0) {
- dev_err(card->dev, "%s late_probe() failed: %d\n",
+ dev_err(card->dev, "ASoC: %s late_probe() failed: %d\n",
card->name, ret);
goto probe_aux_dev_err;
}
@@ -1789,8 +1798,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_register(card->snd_card);
if (ret < 0) {
- pr_err("asoc: failed to register soundcard for %s: %d\n",
- card->name, ret);
+ dev_err(card->dev, "ASoC: failed to register soundcard %d\n",
+ ret);
goto probe_aux_dev_err;
}
@@ -1799,8 +1808,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_rtd; i++) {
ret = soc_register_ac97_dai_link(&card->rtd[i]);
if (ret < 0) {
- pr_err("asoc: failed to register AC97 %s: %d\n",
- card->name, ret);
+ dev_err(card->dev, "ASoC: failed to register AC97:"
+ " %d\n", ret);
while (--i >= 0)
soc_unregister_ac97_dai_link(card->rtd[i].codec);
goto probe_aux_dev_err;
@@ -1846,7 +1855,7 @@ static int soc_probe(struct platform_device *pdev)
return -EINVAL;
dev_warn(&pdev->dev,
- "ASoC machine %s should use snd_soc_register_card()\n",
+ "ASoC: machine %s should use snd_soc_register_card()\n",
card->name);
/* Bodge while we unpick instantiation */
@@ -1996,7 +2005,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform,
unsigned int ret;
if (!platform->driver->read) {
- dev_err(platform->dev, "platform has no read back\n");
+ dev_err(platform->dev, "ASoC: platform has no read back\n");
return -1;
}
@@ -2012,7 +2021,7 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
unsigned int reg, unsigned int val)
{
if (!platform->driver->write) {
- dev_err(platform->dev, "platform has no write back\n");
+ dev_err(platform->dev, "ASoC: platform has no write back\n");
return -1;
}
@@ -2283,7 +2292,8 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
err = snd_ctl_add(card, snd_soc_cnew(control, data,
control->name, prefix));
if (err < 0) {
- dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+ dev_err(dev, "ASoC: Failed to add %s: %d\n",
+ control->name, err);
return err;
}
}
@@ -3534,15 +3544,14 @@ int snd_soc_register_card(struct snd_soc_card *card)
* not both or neither.
*/
if (!!link->codec_name == !!link->codec_of_node) {
- dev_err(card->dev,
- "Neither/both codec name/of_node are set for %s\n",
- link->name);
+ dev_err(card->dev, "ASoC: Neither/both codec"
+ " name/of_node are set for %s\n", link->name);
return -EINVAL;
}
/* Codec DAI name must be specified */
if (!link->codec_dai_name) {
- dev_err(card->dev, "codec_dai_name not set for %s\n",
- link->name);
+ dev_err(card->dev, "ASoC: codec_dai_name not"
+ " set for %s\n", link->name);
return -EINVAL;
}
@@ -3551,8 +3560,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
* can be left unspecified, and a dummy platform will be used.
*/
if (link->platform_name && link->platform_of_node) {
- dev_err(card->dev,
- "Both platform name/of_node are set for %s\n", link->name);
+ dev_err(card->dev, "ASoC: Both platform name/of_node"
+ " are set for %s\n", link->name);
return -EINVAL;
}
@@ -3562,9 +3571,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
* name alone..
*/
if (link->cpu_name && link->cpu_of_node) {
- dev_err(card->dev,
- "Neither/both cpu name/of_node are set for %s\n",
- link->name);
+ dev_err(card->dev, "ASoC: Neither/both "
+ "cpu name/of_node are set for %s\n",link->name);
return -EINVAL;
}
/*
@@ -3573,9 +3581,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
*/
if (!link->cpu_dai_name &&
!(link->cpu_name || link->cpu_of_node)) {
- dev_err(card->dev,
- "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
- link->name);
+ dev_err(card->dev, "ASoC: Neither cpu_dai_name nor "
+ "cpu_name/of_node are set for %s\n", link->name);
return -EINVAL;
}
}
@@ -3622,7 +3629,7 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
{
if (card->instantiated)
soc_cleanup_card_resources(card);
- dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
+ dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
return 0;
}
@@ -3679,8 +3686,8 @@ static inline char *fmt_multiple_name(struct device *dev,
struct snd_soc_dai_driver *dai_drv)
{
if (dai_drv->name == NULL) {
- pr_err("asoc: error - multiple DAI %s registered with no name\n",
- dev_name(dev));
+ dev_err(dev, "ASoC: error - multiple DAI %s registered with"
+ " no name\n", dev_name(dev));
return NULL;
}
@@ -3698,7 +3705,7 @@ int snd_soc_register_dai(struct device *dev,
struct snd_soc_codec *codec;
struct snd_soc_dai *dai;
- dev_dbg(dev, "dai register %s\n", dev_name(dev));
+ dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev));
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
if (dai == NULL)
@@ -3721,7 +3728,7 @@ int snd_soc_register_dai(struct device *dev,
list_for_each_entry(codec, &codec_list, list) {
if (codec->dev == dev) {
- dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
+ dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n",
dai->name, codec->name);
dai->codec = codec;
break;
@@ -3735,7 +3742,7 @@ int snd_soc_register_dai(struct device *dev,
mutex_unlock(&client_mutex);
- pr_debug("Registered DAI '%s'\n", dai->name);
+ dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
return 0;
}
@@ -3761,7 +3768,7 @@ found:
list_del(&dai->list);
mutex_unlock(&client_mutex);
- pr_debug("Unregistered DAI '%s'\n", dai->name);
+ dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name);
kfree(dai->name);
kfree(dai);
}
@@ -3780,7 +3787,7 @@ int snd_soc_register_dais(struct device *dev,
struct snd_soc_dai *dai;
int i, ret = 0;
- dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
+ dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
for (i = 0; i < count; i++) {
@@ -3812,8 +3819,8 @@ int snd_soc_register_dais(struct device *dev,
list_for_each_entry(codec, &codec_list, list) {
if (codec->dev == dev) {
- dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
- dai->name, codec->name);
+ dev_dbg(dev, "ASoC: Mapped DAI %s to "
+ "CODEC %s\n", dai->name, codec->name);
dai->codec = codec;
break;
}
@@ -3826,7 +3833,7 @@ int snd_soc_register_dais(struct device *dev,
mutex_unlock(&client_mutex);
- pr_debug("Registered DAI '%s'\n", dai->name);
+ dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name);
}
return 0;
@@ -3864,7 +3871,7 @@ int snd_soc_register_platform(struct device *dev,
{
struct snd_soc_platform *platform;
- dev_dbg(dev, "platform register %s\n", dev_name(dev));
+ dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
if (platform == NULL)
@@ -3888,7 +3895,7 @@ int snd_soc_register_platform(struct device *dev,
list_add(&platform->list, &platform_list);
mutex_unlock(&client_mutex);
- pr_debug("Registered platform '%s'\n", platform->name);
+ dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name);
return 0;
}
@@ -3914,7 +3921,7 @@ found:
list_del(&platform->list);
mutex_unlock(&client_mutex);
- pr_debug("Unregistered platform '%s'\n", platform->name);
+ dev_dbg(dev, "ASoC: Unregistered platform '%s'\n", platform->name);
kfree(platform->name);
kfree(platform);
}
@@ -4007,7 +4014,7 @@ int snd_soc_register_codec(struct device *dev,
codec->reg_size = reg_size;
/* it is necessary to make a copy of the default register cache
* because in the case of using a compression type that requires
- * the default register cache to be marked as __devinitconst the
+ * the default register cache to be marked as the
* kernel might have freed the array by the time we initialize
* the cache.
*/
@@ -4043,11 +4050,11 @@ int snd_soc_register_codec(struct device *dev,
if (num_dai) {
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
if (ret < 0)
- dev_err(codec->dev, "Failed to regster DAIs: %d\n",
- ret);
+ dev_err(codec->dev, "ASoC: Failed to regster"
+ " DAIs: %d\n", ret);
}
- pr_debug("Registered codec '%s'\n", codec->name);
+ dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
return 0;
fail:
@@ -4082,7 +4089,7 @@ found:
list_del(&codec->list);
mutex_unlock(&client_mutex);
- pr_debug("Unregistered codec '%s'\n", codec->name);
+ dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
snd_soc_cache_exit(codec);
kfree(codec->reg_def_copy);
@@ -4106,7 +4113,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
*/
if (ret < 0 && ret != -EINVAL) {
dev_err(card->dev,
- "Property '%s' could not be read: %d\n",
+ "ASoC: Property '%s' could not be read: %d\n",
propname, ret);
return ret;
}
@@ -4125,15 +4132,13 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
num_routes = of_property_count_strings(np, propname);
if (num_routes < 0 || num_routes & 1) {
- dev_err(card->dev,
- "Property '%s' does not exist or its length is not even\n",
- propname);
+ dev_err(card->dev, "ASoC: Property '%s' does not exist or its"
+ " length is not even\n", propname);
return -EINVAL;
}
num_routes /= 2;
if (!num_routes) {
- dev_err(card->dev,
- "Property '%s's length is zero\n",
+ dev_err(card->dev, "ASoC: Property '%s's length is zero\n",
propname);
return -EINVAL;
}
@@ -4142,7 +4147,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
GFP_KERNEL);
if (!routes) {
dev_err(card->dev,
- "Could not allocate DAPM route table\n");
+ "ASoC: Could not allocate DAPM route table\n");
return -EINVAL;
}
@@ -4150,9 +4155,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
ret = of_property_read_string_index(np, propname,
2 * i, &routes[i].sink);
if (ret) {
- dev_err(card->dev,
- "Property '%s' index %d could not be read: %d\n",
- propname, 2 * i, ret);
+ dev_err(card->dev, "ASoC: Property '%s' index %d"
+ " could not be read: %d\n", propname, 2 * i,
+ ret);
kfree(routes);
return -EINVAL;
}
@@ -4160,8 +4165,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
(2 * i) + 1, &routes[i].source);
if (ret) {
dev_err(card->dev,
- "Property '%s' index %d could not be read: %d\n",
- propname, (2 * i) + 1, ret);
+ "ASoC: Property '%s' index %d could not be"
+ " read: %d\n", propname, (2 * i) + 1, ret);
kfree(routes);
return -EINVAL;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 6e35bcae02df..1e36bc81e5af 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -220,7 +220,7 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
else if (w->platform)
return snd_soc_platform_read(w->platform, reg);
- dev_err(w->dapm->dev, "no valid widget read method\n");
+ dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
return -1;
}
@@ -231,7 +231,7 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
else if (w->platform)
return snd_soc_platform_write(w->platform, reg, val);
- dev_err(w->dapm->dev, "no valid widget write method\n");
+ dev_err(w->dapm->dev, "ASoC: no valid widget write method\n");
return -1;
}
@@ -546,7 +546,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
wlist = kzalloc(wlistsize, GFP_KERNEL);
if (wlist == NULL) {
dev_err(dapm->dev,
- "asoc: can't allocate widget list for %s\n",
+ "ASoC: can't allocate widget list for %s\n",
w->name);
return -ENOMEM;
}
@@ -595,9 +595,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
prefix);
ret = snd_ctl_add(card, path->kcontrol);
if (ret < 0) {
- dev_err(dapm->dev,
- "asoc: failed to add dapm kcontrol %s: %d\n",
- path->long_name, ret);
+ dev_err(dapm->dev, "ASoC: failed to add widget"
+ " %s dapm kcontrol %s: %d\n",
+ w->name, path->long_name, ret);
kfree(wlist);
kfree(path->long_name);
path->long_name = NULL;
@@ -626,7 +626,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
if (w->num_kcontrols != 1) {
dev_err(dapm->dev,
- "asoc: mux %s has incorrect number of controls\n",
+ "ASoC: mux %s has incorrect number of controls\n",
w->name);
return -EINVAL;
}
@@ -645,7 +645,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
if (wlist == NULL) {
dev_err(dapm->dev,
- "asoc: can't allocate widget list for %s\n", w->name);
+ "ASoC: can't allocate widget list for %s\n", w->name);
return -ENOMEM;
}
wlist->num_widgets = wlistentries;
@@ -677,7 +677,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
name + prefix_len, prefix);
ret = snd_ctl_add(card, kcontrol);
if (ret < 0) {
- dev_err(dapm->dev, "failed to add kcontrol %s: %d\n",
+ dev_err(dapm->dev, "ASoC: failed to add kcontrol %s: %d\n",
w->name, ret);
kfree(wlist);
return ret;
@@ -699,7 +699,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
{
if (w->num_kcontrols)
dev_err(w->dapm->dev,
- "asoc: PGA controls not supported: '%s'\n", w->name);
+ "ASoC: PGA controls not supported: '%s'\n", w->name);
return 0;
}
@@ -725,7 +725,7 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
case SNDRV_CTL_POWER_D3hot:
case SNDRV_CTL_POWER_D3cold:
if (widget->ignore_suspend)
- dev_dbg(widget->dapm->dev, "%s ignoring suspend\n",
+ dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
widget->name);
return widget->ignore_suspend;
default:
@@ -757,14 +757,14 @@ static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
wlistentries * sizeof(struct snd_soc_dapm_widget *);
*list = krealloc(wlist, wlistsize, GFP_KERNEL);
if (*list == NULL) {
- dev_err(w->dapm->dev, "can't allocate widget list for %s\n",
+ dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
w->name);
return -ENOMEM;
}
wlist = *list;
/* insert the widget */
- dev_dbg(w->dapm->dev, "added %s in widget list pos %d\n",
+ dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n",
w->name, wlist->num_widgets);
wlist->widgets[wlist->num_widgets] = w;
@@ -844,7 +844,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
int err;
err = dapm_list_add_widget(list, path->sink);
if (err < 0) {
- dev_err(widget->dapm->dev, "could not add widget %s\n",
+ dev_err(widget->dapm->dev,
+ "ASoC: could not add widget %s\n",
widget->name);
return con;
}
@@ -943,7 +944,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
int err;
err = dapm_list_add_widget(list, path->source);
if (err < 0) {
- dev_err(widget->dapm->dev, "could not add widget %s\n",
+ dev_err(widget->dapm->dev,
+ "ASoC: could not add widget %s\n",
widget->name);
return con;
}
@@ -1024,7 +1026,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
ret = regulator_allow_bypass(w->regulator, true);
if (ret != 0)
dev_warn(w->dapm->dev,
- "Failed to bypass %s: %d\n",
+ "ASoC: Failed to bypass %s: %d\n",
w->name, ret);
}
@@ -1034,7 +1036,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
ret = regulator_allow_bypass(w->regulator, false);
if (ret != 0)
dev_warn(w->dapm->dev,
- "Failed to unbypass %s: %d\n",
+ "ASoC: Failed to unbypass %s: %d\n",
w->name, ret);
}
@@ -1253,7 +1255,7 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
ret = w->event(w, NULL, event);
trace_snd_soc_dapm_widget_event_done(w, event);
if (ret < 0)
- pr_err("%s: %s event failed: %d\n",
+ dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n",
ev_name, w->name, ret);
}
}
@@ -1402,7 +1404,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
if (ret < 0)
dev_err(w->dapm->dev,
- "Failed to apply widget power: %d\n", ret);
+ "ASoC: Failed to apply widget power: %d\n", ret);
}
if (!list_empty(&pending))
@@ -1431,20 +1433,21 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
(w->event_flags & SND_SOC_DAPM_PRE_REG)) {
ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
if (ret != 0)
- pr_err("%s DAPM pre-event failed: %d\n",
+ dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
w->name, ret);
}
ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
update->val);
if (ret < 0)
- pr_err("%s DAPM update failed: %d\n", w->name, ret);
+ dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n",
+ w->name, ret);
if (w->event &&
(w->event_flags & SND_SOC_DAPM_POST_REG)) {
ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
if (ret != 0)
- pr_err("%s DAPM post-event failed: %d\n",
+ dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
w->name, ret);
}
}
@@ -1466,7 +1469,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
if (ret != 0)
dev_err(d->dev,
- "Failed to turn on bias: %d\n", ret);
+ "ASoC: Failed to turn on bias: %d\n", ret);
}
/* Prepare for a STADDBY->ON or ON->STANDBY transition */
@@ -1474,7 +1477,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
if (ret != 0)
dev_err(d->dev,
- "Failed to prepare bias: %d\n", ret);
+ "ASoC: Failed to prepare bias: %d\n", ret);
}
}
@@ -1492,7 +1495,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
d->target_bias_level == SND_SOC_BIAS_OFF)) {
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
if (ret != 0)
- dev_err(d->dev, "Failed to apply standby bias: %d\n",
+ dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
ret);
}
@@ -1501,7 +1504,8 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
d->target_bias_level == SND_SOC_BIAS_OFF) {
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
if (ret != 0)
- dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
+ dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
+ ret);
if (d->dev)
pm_runtime_put(d->dev);
@@ -1512,7 +1516,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
d->target_bias_level == SND_SOC_BIAS_ON) {
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
if (ret != 0)
- dev_err(d->dev, "Failed to apply active bias: %d\n",
+ dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
ret);
}
}
@@ -1838,7 +1842,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
if (!dapm->debugfs_dapm) {
dev_warn(dapm->dev,
- "Failed to create DAPM debugfs directory\n");
+ "ASoC: Failed to create DAPM debugfs directory\n");
return;
}
@@ -2123,7 +2127,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
if (!w) {
- dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+ dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
return -EINVAL;
}
@@ -2212,8 +2216,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
if (!wsource)
wsource = wtsource;
- if (wsource == NULL || wsink == NULL)
+ if (wsource == NULL) {
+ dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
+ route->source);
return -ENODEV;
+ }
+ if (wsink == NULL) {
+ dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
+ route->sink);
+ return -ENODEV;
+ }
path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
if (!path)
@@ -2308,7 +2320,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
return 0;
err:
- dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n",
+ dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
source, control, sink);
kfree(path);
return ret;
@@ -2325,7 +2337,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
if (route->control) {
dev_err(dapm->dev,
- "Removal of routes with controls not supported\n");
+ "ASoC: Removal of routes with controls not supported\n");
return -EINVAL;
}
@@ -2360,7 +2372,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
list_del(&path->list_source);
kfree(path);
} else {
- dev_warn(dapm->dev, "Route %s->%s does not exist\n",
+ dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
source, sink);
}
@@ -2389,8 +2401,10 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
for (i = 0; i < num; i++) {
r = snd_soc_dapm_add_route(dapm, route);
if (r < 0) {
- dev_err(dapm->dev, "Failed to add route %s->%s\n",
- route->source, route->sink);
+ dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
+ route->source,
+ route->control ? route->control : "direct",
+ route->sink);
ret = r;
}
route++;
@@ -2438,19 +2452,19 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
int count = 0;
if (!source) {
- dev_err(dapm->dev, "Unable to find source %s for weak route\n",
+ dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
route->source);
return -ENODEV;
}
if (!sink) {
- dev_err(dapm->dev, "Unable to find sink %s for weak route\n",
+ dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
route->sink);
return -ENODEV;
}
if (route->control || route->connected)
- dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n",
+ dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
route->source, route->sink);
list_for_each_entry(path, &source->sinks, list_source) {
@@ -2461,10 +2475,10 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
}
if (count == 0)
- dev_err(dapm->dev, "No path found for weak route %s->%s\n",
+ dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
route->source, route->sink);
if (count > 1)
- dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n",
+ dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
count, route->source, route->sink);
return 0;
@@ -2601,7 +2615,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
if (snd_soc_volsw_is_stereo(mc))
dev_warn(widget->dapm->dev,
- "Control '%s' is stereo, which is not supported\n",
+ "ASoC: Control '%s' is stereo, which is not supported\n",
kcontrol->id.name);
ucontrol->value.integer.value[0] =
@@ -2644,7 +2658,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
if (snd_soc_volsw_is_stereo(mc))
dev_warn(widget->dapm->dev,
- "Control '%s' is stereo, which is not supported\n",
+ "ASoC: Control '%s' is stereo, which is not supported\n",
kcontrol->id.name);
val = (ucontrol->value.integer.value[0] & mask);
@@ -3021,7 +3035,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->regulator = devm_regulator_get(dapm->dev, w->name);
if (IS_ERR(w->regulator)) {
ret = PTR_ERR(w->regulator);
- dev_err(dapm->dev, "Failed to request %s: %d\n",
+ dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
w->name, ret);
return NULL;
}
@@ -3031,7 +3045,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->clk = devm_clk_get(dapm->dev, w->name);
if (IS_ERR(w->clk)) {
ret = PTR_ERR(w->clk);
- dev_err(dapm->dev, "Failed to request %s: %d\n",
+ dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
w->name, ret);
return NULL;
}
@@ -3182,7 +3196,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
if (config->formats) {
fmt = ffs(config->formats) - 1;
} else {
- dev_warn(w->dapm->dev, "Invalid format %llx specified\n",
+ dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
config->formats);
fmt = 0;
}
@@ -3215,7 +3229,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
params, source);
if (ret != 0) {
dev_err(source->dev,
- "hw_params() failed: %d\n", ret);
+ "ASoC: hw_params() failed: %d\n", ret);
goto out;
}
}
@@ -3226,7 +3240,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
sink);
if (ret != 0) {
dev_err(sink->dev,
- "hw_params() failed: %d\n", ret);
+ "ASoC: hw_params() failed: %d\n", ret);
goto out;
}
}
@@ -3235,14 +3249,14 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU:
ret = snd_soc_dai_digital_mute(sink, 0);
if (ret != 0 && ret != -ENOTSUPP)
- dev_warn(sink->dev, "Failed to unmute: %d\n", ret);
+ dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
ret = 0;
break;
case SND_SOC_DAPM_PRE_PMD:
ret = snd_soc_dai_digital_mute(sink, 1);
if (ret != 0 && ret != -ENOTSUPP)
- dev_warn(sink->dev, "Failed to mute: %d\n", ret);
+ dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
ret = 0;
break;
@@ -3281,11 +3295,11 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD;
- dev_dbg(card->dev, "adding %s widget\n", link_name);
+ dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
w = snd_soc_dapm_new_control(&card->dapm, &template);
if (!w) {
- dev_err(card->dev, "Failed to create %s widget\n",
+ dev_err(card->dev, "ASoC: Failed to create %s widget\n",
link_name);
return -ENOMEM;
}
@@ -3319,12 +3333,12 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
template.name = dai->driver->playback.stream_name;
template.sname = dai->driver->playback.stream_name;
- dev_dbg(dai->dev, "adding %s widget\n",
+ dev_dbg(dai->dev, "ASoC: adding %s widget\n",
template.name);
w = snd_soc_dapm_new_control(dapm, &template);
if (!w) {
- dev_err(dapm->dev, "Failed to create %s widget\n",
+ dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
dai->driver->playback.stream_name);
}
@@ -3337,12 +3351,12 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
template.name = dai->driver->capture.stream_name;
template.sname = dai->driver->capture.stream_name;
- dev_dbg(dai->dev, "adding %s widget\n",
+ dev_dbg(dai->dev, "ASoC: adding %s widget\n",
template.name);
w = snd_soc_dapm_new_control(dapm, &template);
if (!w) {
- dev_err(dapm->dev, "Failed to create %s widget\n",
+ dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
dai->driver->capture.stream_name);
}
@@ -3518,11 +3532,11 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
if (!w) {
- dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+ dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
return -EINVAL;
}
- dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
+ dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
w->connected = 1;
w->force = 1;
dapm_mark_dirty(w, "force enable");
@@ -3605,7 +3619,7 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
if (!w) {
- dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+ dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
return -EINVAL;
}
@@ -3664,7 +3678,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_dapm_widget *w;
- dev_dbg(codec->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+ dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n",
&card->dapm, &codec->dapm);
list_for_each_entry(w, &card->widgets, list) {
@@ -3674,7 +3688,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
case snd_soc_dapm_input:
case snd_soc_dapm_output:
case snd_soc_dapm_micbias:
- dev_dbg(codec->dev, "Auto NC: Checking widget %s\n",
+ dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n",
w->name);
if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
dev_dbg(codec->dev,
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index bbc125748a38..111b7d921e89 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -317,3 +317,5 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
return 0;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 1ab5fe04bfcc..0bb5cccd7766 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -66,7 +66,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
struct snd_soc_dapm_context *dapm;
struct snd_soc_jack_pin *pin;
int enable;
- int oldstatus;
trace_snd_soc_jack_report(jack, mask, status);
@@ -78,8 +77,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
mutex_lock(&jack->mutex);
- oldstatus = jack->status;
-
jack->status &= ~mask;
jack->status |= status & mask;
@@ -172,12 +169,13 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) {
if (!pins[i].pin) {
- printk(KERN_ERR "No name for pin %d\n", i);
+ dev_err(jack->codec->dev, "ASoC: No name for pin %d\n",
+ i);
return -EINVAL;
}
if (!pins[i].mask) {
- printk(KERN_ERR "No mask for pin %d (%s)\n", i,
- pins[i].pin);
+ dev_err(jack->codec->dev, "ASoC: No mask for pin %d"
+ " (%s)\n", i, pins[i].pin);
return -EINVAL;
}
@@ -297,13 +295,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
for (i = 0; i < count; i++) {
if (!gpio_is_valid(gpios[i].gpio)) {
- printk(KERN_ERR "Invalid gpio %d\n",
+ dev_err(jack->codec->dev, "ASoC: Invalid gpio %d\n",
gpios[i].gpio);
ret = -EINVAL;
goto undo;
}
if (!gpios[i].name) {
- printk(KERN_ERR "No name for gpio %d\n",
+ dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n",
gpios[i].gpio);
ret = -EINVAL;
goto undo;
@@ -332,7 +330,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
if (gpios[i].wake) {
ret = irq_set_irq_wake(gpio_to_irq(gpios[i].gpio), 1);
if (ret != 0)
- printk(KERN_ERR
+ dev_err(jack->codec->dev, "ASoC: "
"Failed to mark GPIO %d as wake source: %d\n",
gpios[i].gpio, ret);
}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ef22d0bd9e9e..5c3ca2a34661 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -43,7 +43,7 @@ static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
struct snd_soc_pcm_runtime *be = dpcm->be;
- dev_dbg(be->dev, "pm: BE %s event %d dir %d\n",
+ dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n",
be->dai_link->name, event, dir);
snd_soc_dapm_stream_event(be, dir, event);
@@ -70,18 +70,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
*/
if (!soc_dai->rate) {
dev_warn(soc_dai->dev,
- "Not enforcing symmetric_rates due to race\n");
+ "ASoC: Not enforcing symmetric_rates due to race\n");
return 0;
}
- dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
+ 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,
- "Unable to apply rate symmetry constraint: %d\n", ret);
+ "ASoC: Unable to apply rate symmetry constraint: %d\n",
+ ret);
return ret;
}
@@ -118,7 +119,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
sample_sizes[i], bits);
if (ret != 0)
dev_warn(dai->dev,
- "Failed to set MSB %d/%d: %d\n",
+ "ASoC: Failed to set MSB %d/%d: %d\n",
bits, sample_sizes[i], ret);
}
}
@@ -149,8 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
if (ret < 0) {
- dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
- cpu_dai->name, ret);
+ dev_err(cpu_dai->dev, "ASoC: can't open interface"
+ " %s: %d\n", cpu_dai->name, ret);
goto out;
}
}
@@ -158,8 +159,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->open) {
ret = platform->driver->ops->open(substream);
if (ret < 0) {
- dev_err(platform->dev, "can't open platform %s: %d\n",
- platform->name, ret);
+ dev_err(platform->dev, "ASoC: can't open platform"
+ " %s: %d\n", platform->name, ret);
goto platform_err;
}
}
@@ -167,8 +168,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->startup) {
ret = codec_dai->driver->ops->startup(substream, codec_dai);
if (ret < 0) {
- dev_err(codec_dai->dev, "can't open codec %s: %d\n",
- codec_dai->name, ret);
+ dev_err(codec_dai->dev, "ASoC: can't open codec"
+ " %s: %d\n", codec_dai->name, ret);
goto codec_dai_err;
}
}
@@ -176,7 +177,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
ret = rtd->dai_link->ops->startup(substream);
if (ret < 0) {
- pr_err("asoc: %s startup failed: %d\n",
+ pr_err("ASoC: %s startup failed: %d\n",
rtd->dai_link->name, ret);
goto machine_err;
}
@@ -238,18 +239,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
ret = -EINVAL;
snd_pcm_limit_hw_rates(runtime);
if (!runtime->hw.rates) {
- printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
+ printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
codec_dai->name, cpu_dai->name);
goto config_err;
}
if (!runtime->hw.formats) {
- printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
+ printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
codec_dai->name, cpu_dai->name);
goto config_err;
}
if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
runtime->hw.channels_min > runtime->hw.channels_max) {
- printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
+ printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
codec_dai->name, cpu_dai->name);
goto config_err;
}
@@ -270,12 +271,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto config_err;
}
- pr_debug("asoc: %s <-> %s info:\n",
+ pr_debug("ASoC: %s <-> %s info:\n",
codec_dai->name, cpu_dai->name);
- pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
- pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+ pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
+ pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
runtime->hw.channels_max);
- pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+ pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min,
runtime->hw.rate_max);
dynamic:
@@ -330,7 +331,7 @@ static void close_delayed_work(struct work_struct *work)
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
- pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+ dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
codec_dai->driver->playback.stream_name,
codec_dai->playback_active ? "active" : "inactive",
codec_dai->pop_wait ? "yes" : "no");
@@ -444,7 +445,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
ret = rtd->dai_link->ops->prepare(substream);
if (ret < 0) {
- pr_err("asoc: machine prepare error: %d\n", ret);
+ dev_err(rtd->card->dev, "ASoC: machine prepare error:"
+ " %d\n", ret);
goto out;
}
}
@@ -452,8 +454,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->prepare) {
ret = platform->driver->ops->prepare(substream);
if (ret < 0) {
- dev_err(platform->dev, "platform prepare error: %d\n",
- ret);
+ dev_err(platform->dev, "ASoC: platform prepare error:"
+ " %d\n", ret);
goto out;
}
}
@@ -461,7 +463,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->prepare) {
ret = codec_dai->driver->ops->prepare(substream, codec_dai);
if (ret < 0) {
- dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+ dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
ret);
goto out;
}
@@ -470,7 +472,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->prepare) {
ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
if (ret < 0) {
- dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+ dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
ret);
goto out;
}
@@ -512,7 +514,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
ret = rtd->dai_link->ops->hw_params(substream, params);
if (ret < 0) {
- pr_err("asoc: machine hw_params failed: %d\n", ret);
+ dev_err(rtd->card->dev, "ASoC: machine hw_params"
+ " failed: %d\n", ret);
goto out;
}
}
@@ -520,8 +523,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (codec_dai->driver->ops->hw_params) {
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
if (ret < 0) {
- dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
- codec_dai->name, ret);
+ dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
+ " %d\n", codec_dai->name, ret);
goto codec_err;
}
}
@@ -529,7 +532,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (cpu_dai->driver->ops->hw_params) {
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) {
- dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+ dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
cpu_dai->name, ret);
goto interface_err;
}
@@ -538,7 +541,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (platform->driver->ops && platform->driver->ops->hw_params) {
ret = platform->driver->ops->hw_params(substream, params);
if (ret < 0) {
- dev_err(platform->dev, "%s hw params failed: %d\n",
+ dev_err(platform->dev, "ASoC: %s hw params failed: %d\n",
platform->name, ret);
goto platform_err;
}
@@ -760,7 +763,7 @@ static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
struct snd_soc_dpcm *dpcm, *d;
list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
- dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
+ dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
stream ? "capture" : "playback",
dpcm->be->dai_link->name);
@@ -815,7 +818,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
}
}
- dev_err(card->dev, "can't get %s BE for %s\n",
+ dev_err(card->dev, "ASoC: can't get %s BE for %s\n",
stream ? "capture" : "playback", widget->name);
return NULL;
}
@@ -866,7 +869,7 @@ static int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
/* get number of valid DAI paths and their widgets */
paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
- dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
+ dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
stream ? "capture" : "playback");
*list_ = list;
@@ -903,7 +906,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
if (widget && widget_in_list(list, widget))
continue;
- dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
+ dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
stream ? "capture" : "playback",
dpcm->be->dai_link->name, fe->dai_link->name);
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
@@ -911,7 +914,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
prune++;
}
- dev_dbg(fe->dev, "found %d old BE paths for pruning\n", prune);
+ dev_dbg(fe->dev, "ASoC: found %d old BE paths for pruning\n", prune);
return prune;
}
@@ -932,7 +935,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* is there a valid BE rtd for this widget */
be = dpcm_get_be(card, list->widgets[i], stream);
if (!be) {
- dev_err(fe->dev, "no BE found for %s\n",
+ dev_err(fe->dev, "ASoC: no BE found for %s\n",
list->widgets[i]->name);
continue;
}
@@ -948,7 +951,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* newly connected FE and BE */
err = dpcm_be_connect(fe, be, stream);
if (err < 0) {
- dev_err(fe->dev, "can't connect %s\n",
+ dev_err(fe->dev, "ASoC: can't connect %s\n",
list->widgets[i]->name);
break;
} else if (err == 0) /* already connected */
@@ -959,7 +962,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
new++;
}
- dev_dbg(fe->dev, "found %d new BE paths\n", new);
+ dev_dbg(fe->dev, "ASoC: found %d new BE paths\n", new);
return new;
}
@@ -998,7 +1001,7 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
snd_soc_dpcm_get_substream(be, stream);
if (be->dpcm[stream].users == 0)
- dev_err(be->dev, "no users %s at close - state %d\n",
+ dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
stream ? "capture" : "playback",
be->dpcm[stream].state);
@@ -1032,7 +1035,7 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
/* first time the dpcm is open ? */
if (be->dpcm[stream].users == DPCM_MAX_BE_USERS)
- dev_err(be->dev, "too many users %s at open %d\n",
+ dev_err(be->dev, "ASoC: too many users %s at open %d\n",
stream ? "capture" : "playback",
be->dpcm[stream].state);
@@ -1043,15 +1046,15 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
continue;
- dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
+ dev_dbg(be->dev, "ASoC: open BE %s\n", be->dai_link->name);
be_substream->runtime = be->dpcm[stream].runtime;
err = soc_pcm_open(be_substream);
if (err < 0) {
- dev_err(be->dev, "BE open failed %d\n", err);
+ dev_err(be->dev, "ASoC: BE open failed %d\n", err);
be->dpcm[stream].users--;
if (be->dpcm[stream].users < 0)
- dev_err(be->dev, "no users %s at unwind %d\n",
+ dev_err(be->dev, "ASoC: no users %s at unwind %d\n",
stream ? "capture" : "playback",
be->dpcm[stream].state);
@@ -1076,7 +1079,7 @@ unwind:
continue;
if (be->dpcm[stream].users == 0)
- dev_err(be->dev, "no users %s at close %d\n",
+ dev_err(be->dev, "ASoC: no users %s at close %d\n",
stream ? "capture" : "playback",
be->dpcm[stream].state);
@@ -1128,16 +1131,16 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
ret = dpcm_be_dai_startup(fe, fe_substream->stream);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
+ dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret);
goto be_err;
}
- dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
+ dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name);
/* start the DAI frontend */
ret = soc_pcm_open(fe_substream);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
+ dev_err(fe->dev,"ASoC: failed to start FE %d\n", ret);
goto unwind;
}
@@ -1172,7 +1175,7 @@ static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
continue;
if (be->dpcm[stream].users == 0)
- dev_err(be->dev, "no users %s at close - state %d\n",
+ dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
stream ? "capture" : "playback",
be->dpcm[stream].state);
@@ -1183,7 +1186,7 @@ static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
continue;
- dev_dbg(be->dev, "dpcm: close BE %s\n",
+ dev_dbg(be->dev, "ASoC: close BE %s\n",
dpcm->fe->dai_link->name);
soc_pcm_close(be_substream);
@@ -1204,7 +1207,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
/* shutdown the BEs */
dpcm_be_dai_shutdown(fe, substream->stream);
- dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
+ dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
/* now shutdown the frontend */
soc_pcm_close(substream);
@@ -1243,7 +1246,7 @@ static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
continue;
- dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
+ dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
dpcm->fe->dai_link->name);
soc_pcm_hw_free(be_substream);
@@ -1262,12 +1265,12 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
- dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
+ dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
/* call hw_free on the frontend */
err = soc_pcm_hw_free(substream);
if (err < 0)
- dev_err(fe->dev,"dpcm: hw_free FE %s failed\n",
+ dev_err(fe->dev,"ASoC: hw_free FE %s failed\n",
fe->dai_link->name);
/* only hw_params backends that are either sinks or sources
@@ -1305,7 +1308,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
continue;
- dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
+ dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
dpcm->fe->dai_link->name);
/* copy params for each dpcm */
@@ -1318,7 +1321,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
&dpcm->hw_params);
if (ret < 0) {
dev_err(be->dev,
- "dpcm: hw_params BE fixup failed %d\n",
+ "ASoC: hw_params BE fixup failed %d\n",
ret);
goto unwind;
}
@@ -1327,7 +1330,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
if (ret < 0) {
dev_err(dpcm->be->dev,
- "dpcm: hw_params BE failed %d\n", ret);
+ "ASoC: hw_params BE failed %d\n", ret);
goto unwind;
}
@@ -1374,18 +1377,18 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
sizeof(struct snd_pcm_hw_params));
ret = dpcm_be_dai_hw_params(fe, substream->stream);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: hw_params BE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret);
goto out;
}
- dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
+ dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n",
fe->dai_link->name, params_rate(params),
params_channels(params), params_format(params));
/* call hw_params on the frontend */
ret = soc_pcm_hw_params(substream, params);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: hw_params FE failed %d\n", ret);
dpcm_be_dai_hw_free(fe, stream);
} else
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
@@ -1401,12 +1404,12 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
{
int ret;
- dev_dbg(dpcm->be->dev, "dpcm: trigger BE %s cmd %d\n",
+ dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n",
dpcm->fe->dai_link->name, cmd);
ret = soc_pcm_trigger(substream, cmd);
if (ret < 0)
- dev_err(dpcm->be->dev,"dpcm: trigger BE failed %d\n", ret);
+ dev_err(dpcm->be->dev,"ASoC: trigger BE failed %d\n", ret);
return ret;
}
@@ -1517,12 +1520,12 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
case SND_SOC_DPCM_TRIGGER_PRE:
/* call trigger on the frontend before the backend. */
- dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
+ dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
fe->dai_link->name, cmd);
ret = soc_pcm_trigger(substream, cmd);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
goto out;
}
@@ -1533,11 +1536,11 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
goto out;
}
- dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
+ dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
fe->dai_link->name, cmd);
ret = soc_pcm_trigger(substream, cmd);
@@ -1545,17 +1548,17 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
case SND_SOC_DPCM_TRIGGER_BESPOKE:
/* bespoke trigger() - handles both FE and BEs */
- dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
+ dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
fe->dai_link->name, cmd);
ret = soc_pcm_bespoke_trigger(substream, cmd);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
goto out;
}
break;
default:
- dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
+ dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
fe->dai_link->name);
ret = -EINVAL;
goto out;
@@ -1598,12 +1601,12 @@ static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
continue;
- dev_dbg(be->dev, "dpcm: prepare BE %s\n",
+ dev_dbg(be->dev, "ASoC: prepare BE %s\n",
dpcm->fe->dai_link->name);
ret = soc_pcm_prepare(be_substream);
if (ret < 0) {
- dev_err(be->dev, "dpcm: backend prepare failed %d\n",
+ dev_err(be->dev, "ASoC: backend prepare failed %d\n",
ret);
break;
}
@@ -1620,13 +1623,13 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
- dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
+ dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
/* there is no point preparing this FE if there are no BEs */
if (list_empty(&fe->dpcm[stream].be_clients)) {
- dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
+ dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
fe->dai_link->name);
ret = -EINVAL;
goto out;
@@ -1639,7 +1642,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
/* call prepare on the frontend */
ret = soc_pcm_prepare(substream);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: prepare FE %s failed\n",
+ dev_err(fe->dev,"ASoC: prepare FE %s failed\n",
fe->dai_link->name);
goto out;
}
@@ -1673,33 +1676,33 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
int err;
- dev_dbg(fe->dev, "runtime %s close on FE %s\n",
+ dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n",
stream ? "capture" : "playback", fe->dai_link->name);
if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
/* call bespoke trigger - FE takes care of all BE triggers */
- dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
+ dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
fe->dai_link->name);
err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
if (err < 0)
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
} else {
- dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
+ dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n",
fe->dai_link->name);
err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
if (err < 0)
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
}
err = dpcm_be_dai_hw_free(fe, stream);
if (err < 0)
- dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
+ dev_err(fe->dev,"ASoC: hw_free FE failed %d\n", err);
err = dpcm_be_dai_shutdown(fe, stream);
if (err < 0)
- dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
+ dev_err(fe->dev,"ASoC: shutdown FE failed %d\n", err);
/* run the stream event for each BE */
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
@@ -1715,7 +1718,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
int ret;
- dev_dbg(fe->dev, "runtime %s open on FE %s\n",
+ dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
stream ? "capture" : "playback", fe->dai_link->name);
/* Only start the BE if the FE is ready */
@@ -1761,22 +1764,22 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
/* call trigger on the frontend - FE takes care of all BE triggers */
- dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
+ dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
fe->dai_link->name);
ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret);
goto hw_free;
}
} else {
- dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
+ dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n",
fe->dai_link->name);
ret = dpcm_be_dai_trigger(fe, stream,
SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
- dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
goto hw_free;
}
}
@@ -1805,7 +1808,7 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
ret = dpcm_run_update_startup(fe, stream);
if (ret < 0)
- dev_err(fe->dev, "failed to startup some BEs\n");
+ dev_err(fe->dev, "ASoC: failed to startup some BEs\n");
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
return ret;
@@ -1818,7 +1821,7 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
ret = dpcm_run_update_shutdown(fe, stream);
if (ret < 0)
- dev_err(fe->dev, "failed to shutdown some BEs\n");
+ dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
return ret;
@@ -1853,7 +1856,7 @@ int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
continue;
/* DAPM sync will call this to update DSP paths */
- dev_dbg(fe->dev, "DPCM runtime update for FE %s\n",
+ dev_dbg(fe->dev, "ASoC: DPCM runtime update for FE %s\n",
fe->dai_link->name);
/* skip if FE doesn't have playback capability */
@@ -1862,7 +1865,7 @@ int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
if (paths < 0) {
- dev_warn(fe->dev, "%s no valid %s path\n",
+ dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
fe->dai_link->name, "playback");
mutex_unlock(&card->mutex);
return paths;
@@ -1891,7 +1894,7 @@ capture:
paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
if (paths < 0) {
- dev_warn(fe->dev, "%s no valid %s path\n",
+ dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
fe->dai_link->name, "capture");
mutex_unlock(&card->mutex);
return paths;
@@ -1934,7 +1937,7 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
if (be->dai_link->ignore_suspend)
continue;
- dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
+ dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
if (drv->ops->digital_mute && dai->playback_active)
drv->ops->digital_mute(dai, mute);
@@ -1955,7 +1958,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
fe->dpcm[stream].runtime = fe_substream->runtime;
if (dpcm_path_get(fe, stream, &list) <= 0) {
- dev_dbg(fe->dev, "asoc: %s no valid %s route\n",
+ dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
fe->dai_link->name, stream ? "capture" : "playback");
}
@@ -2039,11 +2042,11 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
capture, &pcm);
}
if (ret < 0) {
- dev_err(rtd->card->dev, "can't create pcm for %s\n",
+ dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n",
rtd->dai_link->name);
return ret;
}
- dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
+ dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
@@ -2097,7 +2100,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (platform->driver->pcm_new) {
ret = platform->driver->pcm_new(rtd);
if (ret < 0) {
- dev_err(platform->dev, "pcm constructor failed\n");
+ dev_err(platform->dev,
+ "ASoC: pcm constructor failed: %d\n",
+ ret);
return ret;
}
}
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 60053709e417..fe4541df498c 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -94,7 +94,7 @@ static struct snd_soc_dai_driver dummy_dai = {
.name = "snd-soc-dummy-dai",
};
-static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
+static int snd_soc_dummy_probe(struct platform_device *pdev)
{
int ret;
@@ -111,7 +111,7 @@ static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
return ret;
}
-static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
+static int snd_soc_dummy_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
@@ -125,7 +125,7 @@ static struct platform_driver soc_dummy_driver = {
.owner = THIS_MODULE,
},
.probe = snd_soc_dummy_probe,
- .remove = __devexit_p(snd_soc_dummy_remove),
+ .remove = snd_soc_dummy_remove,
};
static struct platform_device *soc_dummy_dev;
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 8c7f23729446..9b76cc5a1148 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -184,12 +184,12 @@ struct snd_soc_platform_driver spear_soc_platform = {
.pcm_free = spear_pcm_free,
};
-static int __devinit spear_soc_platform_probe(struct platform_device *pdev)
+static int spear_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &spear_soc_platform);
}
-static int __devexit spear_soc_platform_remove(struct platform_device *pdev)
+static int spear_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
@@ -203,7 +203,7 @@ static struct platform_driver spear_pcm_driver = {
},
.probe = spear_soc_platform_probe,
- .remove = __devexit_p(spear_soc_platform_remove),
+ .remove = spear_soc_platform_remove,
};
module_platform_driver(spear_pcm_driver);
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
index bf99296bce95..654318483877 100644
--- a/sound/soc/tegra/tegra20_das.c
+++ b/sound/soc/tegra/tegra20_das.c
@@ -131,7 +131,7 @@ static const struct regmap_config tegra20_das_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit tegra20_das_probe(struct platform_device *pdev)
+static int tegra20_das_probe(struct platform_device *pdev)
{
struct resource *res, *region;
void __iomem *regs;
@@ -200,7 +200,7 @@ err:
return ret;
}
-static int __devexit tegra20_das_remove(struct platform_device *pdev)
+static int tegra20_das_remove(struct platform_device *pdev)
{
if (!das)
return -ENODEV;
@@ -210,14 +210,14 @@ static int __devexit tegra20_das_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra20_das_of_match[] __devinitconst = {
+static const struct of_device_id tegra20_das_of_match[] = {
{ .compatible = "nvidia,tegra20-das", },
{},
};
static struct platform_driver tegra20_das_driver = {
.probe = tegra20_das_probe,
- .remove = __devexit_p(tegra20_das_remove),
+ .remove = tegra20_das_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 0832e8afd73c..caa772de5a18 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -331,7 +331,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
+static int tegra20_i2s_platform_probe(struct platform_device *pdev)
{
struct tegra20_i2s *i2s;
struct resource *mem, *memregion, *dmareq;
@@ -447,7 +447,7 @@ err:
return ret;
}
-static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
+static int tegra20_i2s_platform_remove(struct platform_device *pdev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
@@ -463,12 +463,12 @@ static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra20_i2s_of_match[] __devinitconst = {
+static const struct of_device_id tegra20_i2s_of_match[] = {
{ .compatible = "nvidia,tegra20-i2s", },
{},
};
-static const struct dev_pm_ops tegra20_i2s_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra20_i2s_pm_ops = {
SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
tegra20_i2s_runtime_resume, NULL)
};
@@ -481,7 +481,7 @@ static struct platform_driver tegra20_i2s_driver = {
.pm = &tegra20_i2s_pm_ops,
},
.probe = tegra20_i2s_platform_probe,
- .remove = __devexit_p(tegra20_i2s_platform_remove),
+ .remove = tegra20_i2s_platform_remove,
};
module_platform_driver(tegra20_i2s_driver);
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 3ebc8670ba00..04771d14d343 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -257,7 +257,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
+static int tegra20_spdif_platform_probe(struct platform_device *pdev)
{
struct tegra20_spdif *spdif;
struct resource *mem, *memregion, *dmareq;
@@ -357,7 +357,7 @@ err:
return ret;
}
-static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
+static int tegra20_spdif_platform_remove(struct platform_device *pdev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev);
@@ -373,7 +373,7 @@ static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
return 0;
}
-static const struct dev_pm_ops tegra20_spdif_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra20_spdif_pm_ops = {
SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
tegra20_spdif_runtime_resume, NULL)
};
@@ -385,7 +385,7 @@ static struct platform_driver tegra20_spdif_driver = {
.pm = &tegra20_spdif_pm_ops,
},
.probe = tegra20_spdif_platform_probe,
- .remove = __devexit_p(tegra20_spdif_platform_remove),
+ .remove = tegra20_spdif_platform_remove,
};
module_platform_driver(tegra20_spdif_driver);
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 64b67a309196..f354dc390a0b 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -287,7 +287,7 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
}
EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
-static const char * const configlink_clocks[] __devinitconst = {
+static const char * const configlink_clocks[] = {
"i2s0",
"i2s1",
"i2s2",
@@ -299,7 +299,7 @@ static const char * const configlink_clocks[] __devinitconst = {
"spdif_in",
};
-struct of_dev_auxdata ahub_auxdata[] __devinitdata = {
+struct of_dev_auxdata ahub_auxdata[] = {
OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
@@ -433,7 +433,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
+static int tegra30_ahub_probe(struct platform_device *pdev)
{
struct clk *clk;
int i;
@@ -585,7 +585,7 @@ err:
return ret;
}
-static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
+static int tegra30_ahub_remove(struct platform_device *pdev)
{
if (!ahub)
return -ENODEV;
@@ -602,19 +602,19 @@ static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra30_ahub_of_match[] __devinitconst = {
+static const struct of_device_id tegra30_ahub_of_match[] = {
{ .compatible = "nvidia,tegra30-ahub", },
{},
};
-static const struct dev_pm_ops tegra30_ahub_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra30_ahub_pm_ops = {
SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
tegra30_ahub_runtime_resume, NULL)
};
static struct platform_driver tegra30_ahub_driver = {
.probe = tegra30_ahub_probe,
- .remove = __devexit_p(tegra30_ahub_remove),
+ .remove = tegra30_ahub_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 44184228d1f0..27e91dd0b91c 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -391,7 +391,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
+static int tegra30_i2s_platform_probe(struct platform_device *pdev)
{
struct tegra30_i2s *i2s;
u32 cif_ids[2];
@@ -492,7 +492,7 @@ err:
return ret;
}
-static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
+static int tegra30_i2s_platform_remove(struct platform_device *pdev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
@@ -508,12 +508,12 @@ static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra30_i2s_of_match[] __devinitconst = {
+static const struct of_device_id tegra30_i2s_of_match[] = {
{ .compatible = "nvidia,tegra30-i2s", },
{},
};
-static const struct dev_pm_ops tegra30_i2s_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra30_i2s_pm_ops = {
SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
tegra30_i2s_runtime_resume, NULL)
};
@@ -526,7 +526,7 @@ static struct platform_driver tegra30_i2s_driver = {
.pm = &tegra30_i2s_pm_ops,
},
.probe = tegra30_i2s_platform_probe,
- .remove = __devexit_p(tegra30_i2s_platform_remove),
+ .remove = tegra30_i2s_platform_remove,
};
module_platform_driver(tegra30_i2s_driver);
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 76cb1b363b71..c80adb9da472 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -150,7 +150,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
.fully_routed = true,
};
-static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
+static int tegra_alc5632_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &snd_soc_tegra_alc5632;
@@ -227,7 +227,7 @@ err:
return ret;
}
-static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
+static int tegra_alc5632_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
@@ -242,7 +242,7 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+static const struct of_device_id tegra_alc5632_of_match[] = {
{ .compatible = "nvidia,tegra-audio-alc5632", },
{},
};
@@ -255,7 +255,7 @@ static struct platform_driver tegra_alc5632_driver = {
.of_match_table = tegra_alc5632_of_match,
},
.probe = tegra_alc5632_probe,
- .remove = __devexit_p(tegra_alc5632_remove),
+ .remove = tegra_alc5632_remove,
};
module_platform_driver(tegra_alc5632_driver);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index e18733963cb4..c925ab0adeb6 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -253,13 +253,13 @@ static struct snd_soc_platform_driver tegra_pcm_platform = {
.pcm_free = tegra_pcm_free,
};
-int __devinit tegra_pcm_platform_register(struct device *dev)
+int tegra_pcm_platform_register(struct device *dev)
{
return snd_soc_register_platform(dev, &tegra_pcm_platform);
}
EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
-void __devexit tegra_pcm_platform_unregister(struct device *dev)
+void tegra_pcm_platform_unregister(struct device *dev)
{
snd_soc_unregister_platform(dev);
}
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index ea9166d5c4eb..c8ef88a67c59 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -122,7 +122,7 @@ static struct snd_soc_card snd_soc_tegra_wm8753 = {
.fully_routed = true,
};
-static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
+static int tegra_wm8753_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_wm8753;
struct tegra_wm8753 *machine;
@@ -188,7 +188,7 @@ err:
return ret;
}
-static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
+static int tegra_wm8753_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
@@ -200,7 +200,7 @@ static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
+static const struct of_device_id tegra_wm8753_of_match[] = {
{ .compatible = "nvidia,tegra-audio-wm8753", },
{},
};
@@ -213,7 +213,7 @@ static struct platform_driver tegra_wm8753_driver = {
.of_match_table = tegra_wm8753_of_match,
},
.probe = tegra_wm8753_driver_probe,
- .remove = __devexit_p(tegra_wm8753_driver_remove),
+ .remove = tegra_wm8753_driver_remove,
};
module_platform_driver(tegra_wm8753_driver);
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index cee13b7bfb94..bbd79bf56303 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -252,7 +252,7 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
.fully_routed = true,
};
-static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
+static int tegra_wm8903_driver_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &snd_soc_tegra_wm8903;
@@ -402,7 +402,7 @@ err:
return ret;
}
-static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
+static int tegra_wm8903_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
@@ -417,7 +417,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = {
+static const struct of_device_id tegra_wm8903_of_match[] = {
{ .compatible = "nvidia,tegra-audio-wm8903", },
{},
};
@@ -430,7 +430,7 @@ static struct platform_driver tegra_wm8903_driver = {
.of_match_table = tegra_wm8903_of_match,
},
.probe = tegra_wm8903_driver_probe,
- .remove = __devexit_p(tegra_wm8903_driver_remove),
+ .remove = tegra_wm8903_driver_remove,
};
module_platform_driver(tegra_wm8903_driver);
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index e69a4f7000d6..7fcf6c2297db 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -120,7 +120,7 @@ static struct snd_soc_card snd_soc_trimslice = {
.fully_routed = true,
};
-static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
+static int tegra_snd_trimslice_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_trimslice;
struct tegra_trimslice *trimslice;
@@ -183,7 +183,7 @@ err:
return ret;
}
-static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
+static int tegra_snd_trimslice_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
@@ -195,7 +195,7 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id trimslice_of_match[] __devinitconst = {
+static const struct of_device_id trimslice_of_match[] = {
{ .compatible = "nvidia,tegra-audio-trimslice", },
{},
};
@@ -208,7 +208,7 @@ static struct platform_driver tegra_snd_trimslice_driver = {
.of_match_table = trimslice_of_match,
},
.probe = tegra_snd_trimslice_probe,
- .remove = __devexit_p(tegra_snd_trimslice_remove),
+ .remove = tegra_snd_trimslice_remove,
};
module_platform_driver(tegra_snd_trimslice_driver);
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 28db4ca997ca..16ab69635e2e 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -170,7 +170,7 @@ static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
},
};
-static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
+static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
{
struct txx9aclc_plat_drvdata *drvdata;
struct resource *r;
@@ -208,7 +208,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
}
-static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
+static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -216,7 +216,7 @@ static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
static struct platform_driver txx9aclc_ac97_driver = {
.probe = txx9aclc_ac97_dev_probe,
- .remove = __devexit_p(txx9aclc_ac97_dev_remove),
+ .remove = txx9aclc_ac97_dev_remove,
.driver = {
.name = "txx9aclc-ac97",
.owner = THIS_MODULE,
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index b609d2c64c55..45a6428cba8d 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -417,12 +417,12 @@ static struct snd_soc_platform_driver txx9aclc_soc_platform = {
.pcm_free = txx9aclc_pcm_free_dma_buffers,
};
-static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
+static int txx9aclc_soc_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
}
-static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
+static int txx9aclc_soc_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -435,7 +435,7 @@ static struct platform_driver txx9aclc_pcm_driver = {
},
.probe = txx9aclc_soc_platform_probe,
- .remove = __devexit_p(txx9aclc_soc_platform_remove),
+ .remove = txx9aclc_soc_platform_remove,
};
module_platform_driver(txx9aclc_pcm_driver);
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
index 54f7e25b6f7d..ae6990738783 100644
--- a/sound/soc/ux500/mop500.c
+++ b/sound/soc/ux500/mop500.c
@@ -33,7 +33,7 @@ struct snd_soc_dai_link mop500_dai_links[] = {
.stream_name = "ab8500_0",
.cpu_dai_name = "ux500-msp-i2s.1",
.codec_dai_name = "ab8500-codec-dai.0",
- .platform_name = "ux500-pcm.0",
+ .platform_name = "ux500-msp-i2s.1",
.codec_name = "ab8500-codec.0",
.init = mop500_ab8500_machine_init,
.ops = mop500_ab8500_ops,
@@ -43,7 +43,7 @@ struct snd_soc_dai_link mop500_dai_links[] = {
.stream_name = "ab8500_1",
.cpu_dai_name = "ux500-msp-i2s.3",
.codec_dai_name = "ab8500-codec-dai.1",
- .platform_name = "ux500-pcm.0",
+ .platform_name = "ux500-msp-i2s.3",
.codec_name = "ab8500-codec.0",
.init = NULL,
.ops = mop500_ab8500_ops,
@@ -71,8 +71,8 @@ static void mop500_of_node_put(void)
}
}
-static int __devinit mop500_of_probe(struct platform_device *pdev,
- struct device_node *np)
+static int mop500_of_probe(struct platform_device *pdev,
+ struct device_node *np)
{
struct device_node *codec_np, *msp_np[2];
int i;
@@ -99,7 +99,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
return 0;
}
-static int __devinit mop500_probe(struct platform_device *pdev)
+static int mop500_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int ret;
@@ -136,7 +136,7 @@ static int __devinit mop500_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit mop500_remove(struct platform_device *pdev)
+static int mop500_remove(struct platform_device *pdev)
{
struct snd_soc_card *mop500_card = platform_get_drvdata(pdev);
@@ -161,7 +161,7 @@ static struct platform_driver snd_soc_mop500_driver = {
.of_match_table = snd_soc_mop500_match,
},
.probe = mop500_probe,
- .remove = __devexit_p(mop500_remove),
+ .remove = mop500_remove,
};
module_platform_driver(snd_soc_mop500_driver);
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index be94bf9bf94f..94a3e5705aaa 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -28,6 +28,7 @@
#include "ux500_msp_i2s.h"
#include "ux500_msp_dai.h"
+#include "ux500_pcm.h"
static int setup_pcm_multichan(struct snd_soc_dai *dai,
struct ux500_msp_config *msp_config)
@@ -398,11 +399,28 @@ static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
return ret;
}
- /* Enable clock */
- dev_dbg(dai->dev, "%s: Enabling MSP-clock.\n", __func__);
- clk_enable(drvdata->clk);
+ /* Prepare and enable clocks */
+ dev_dbg(dai->dev, "%s: Enabling MSP-clocks.\n", __func__);
+ ret = clk_prepare_enable(drvdata->pclk);
+ if (ret) {
+ dev_err(drvdata->msp->dev,
+ "%s: Failed to prepare/enable pclk!\n", __func__);
+ goto err_pclk;
+ }
- return 0;
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret) {
+ dev_err(drvdata->msp->dev,
+ "%s: Failed to prepare/enable clk!\n", __func__);
+ goto err_clk;
+ }
+
+ return ret;
+err_clk:
+ clk_disable_unprepare(drvdata->pclk);
+err_pclk:
+ regulator_disable(drvdata->reg_vape);
+ return ret;
}
static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
@@ -428,8 +446,9 @@ static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
__func__, dai->id, snd_pcm_stream_str(substream));
}
- /* Disable clock */
- clk_disable(drvdata->clk);
+ /* Disable and unprepare clocks */
+ clk_disable_unprepare(drvdata->clk);
+ clk_disable_unprepare(drvdata->pclk);
/* Disable regulator */
ret = regulator_disable(drvdata->reg_vape);
@@ -749,7 +768,7 @@ static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
},
};
-static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
+static int ux500_msp_drv_probe(struct platform_device *pdev)
{
struct ux500_msp_i2s_drvdata *drvdata;
int ret = 0;
@@ -780,6 +799,14 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
}
prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
+ drvdata->pclk = clk_get(&pdev->dev, "apb_pclk");
+ if (IS_ERR(drvdata->pclk)) {
+ ret = (int)PTR_ERR(drvdata->pclk);
+ dev_err(&pdev->dev, "%s: ERROR: clk_get of pclk failed (%d)!\n",
+ __func__, ret);
+ goto err_pclk;
+ }
+
drvdata->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->clk)) {
ret = (int)PTR_ERR(drvdata->clk);
@@ -806,27 +833,41 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
goto err_init_msp;
}
+ ret = ux500_pcm_register_platform(pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Error: %s: Failed to register PCM platform device!\n",
+ __func__);
+ goto err_reg_plat;
+ }
+
return 0;
+err_reg_plat:
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
err_init_msp:
clk_put(drvdata->clk);
-
err_clk:
+ clk_put(drvdata->pclk);
+err_pclk:
devm_regulator_put(drvdata->reg_vape);
return ret;
}
-static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
+static int ux500_msp_drv_remove(struct platform_device *pdev)
{
struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+ ux500_pcm_unregister_platform(pdev);
+
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
devm_regulator_put(drvdata->reg_vape);
prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
clk_put(drvdata->clk);
+ clk_put(drvdata->pclk);
ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
index 98202a34a5dd..9c778d9c3838 100644
--- a/sound/soc/ux500/ux500_msp_dai.h
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -69,6 +69,7 @@ struct ux500_msp_i2s_drvdata {
/* Clocks */
unsigned int master_clk;
struct clk *clk;
+ struct clk *pclk;
/* Regulators */
int vape_opp_constraint;
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index 1a04e248453c..846fa82a58d0 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -18,8 +18,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/slab.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -282,7 +281,7 @@ static struct snd_soc_platform_driver ux500_pcm_soc_drv = {
.pcm_new = ux500_pcm_new,
};
-static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev)
+int ux500_pcm_register_platform(struct platform_device *pdev)
{
int ret;
@@ -296,23 +295,12 @@ static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev)
return 0;
}
+EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
-static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev)
+int ux500_pcm_unregister_platform(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
}
-
-static struct platform_driver ux500_pcm_driver = {
- .driver = {
- .name = "ux500-pcm",
- .owner = THIS_MODULE,
- },
-
- .probe = ux500_pcm_drv_probe,
- .remove = __devexit_p(ux500_pcm_drv_remove),
-};
-module_platform_driver(ux500_pcm_driver);
-
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform);
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h
index 77ed44d371e9..76d344476afc 100644
--- a/sound/soc/ux500/ux500_pcm.h
+++ b/sound/soc/ux500/ux500_pcm.h
@@ -32,4 +32,7 @@
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
+int ux500_pcm_register_platform(struct platform_device *pdev);
+int ux500_pcm_unregister_platform(struct platform_device *pdev);
+
#endif
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 5701787c0e6b..174d21fb56e2 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -755,7 +755,7 @@ static struct snd_pcm_ops snd_amd7930_capture_ops = {
.pointer = snd_amd7930_capture_pointer,
};
-static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd)
+static int snd_amd7930_pcm(struct snd_amd7930 *amd)
{
struct snd_pcm *pcm;
int err;
@@ -854,7 +854,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
return change;
}
-static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
+static struct snd_kcontrol_new amd7930_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitor Volume",
@@ -884,7 +884,7 @@ static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
},
};
-static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd)
+static int snd_amd7930_mixer(struct snd_amd7930 *amd)
{
struct snd_card *card;
int idx, err;
@@ -933,10 +933,10 @@ static struct snd_device_ops snd_amd7930_dev_ops = {
.dev_free = snd_amd7930_dev_free,
};
-static int __devinit snd_amd7930_create(struct snd_card *card,
- struct platform_device *op,
- int irq, int dev,
- struct snd_amd7930 **ramd)
+static int snd_amd7930_create(struct snd_card *card,
+ struct platform_device *op,
+ int irq, int dev,
+ struct snd_amd7930 **ramd)
{
struct snd_amd7930 *amd;
unsigned long flags;
@@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
return 0;
}
-static int __devinit amd7930_sbus_probe(struct platform_device *op)
+static int amd7930_sbus_probe(struct platform_device *op)
{
struct resource *rp = &op->resource[0];
static int dev_num;
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index f2eabd3f22fd..54aaad2a10f5 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -702,7 +702,7 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer)
return 0;
}
-static void __devinit snd_cs4231_init(struct snd_cs4231 *chip)
+static void snd_cs4231_init(struct snd_cs4231 *chip)
{
unsigned long flags;
@@ -1019,7 +1019,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(
return bytes_to_frames(substream->runtime, ptr);
}
-static int __devinit snd_cs4231_probe(struct snd_cs4231 *chip)
+static int snd_cs4231_probe(struct snd_cs4231 *chip)
{
unsigned long flags;
int i;
@@ -1218,7 +1218,7 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = {
.pointer = snd_cs4231_capture_pointer,
};
-static int __devinit snd_cs4231_pcm(struct snd_card *card)
+static int snd_cs4231_pcm(struct snd_card *card)
{
struct snd_cs4231 *chip = card->private_data;
struct snd_pcm *pcm;
@@ -1247,7 +1247,7 @@ static int __devinit snd_cs4231_pcm(struct snd_card *card)
return 0;
}
-static int __devinit snd_cs4231_timer(struct snd_card *card)
+static int snd_cs4231_timer(struct snd_card *card)
{
struct snd_cs4231 *chip = card->private_data;
struct snd_timer *timer;
@@ -1498,7 +1498,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
.private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \
((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }
-static struct snd_kcontrol_new snd_cs4231_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cs4231_controls[] = {
CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,
CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,
@@ -1537,7 +1537,7 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
};
-static int __devinit snd_cs4231_mixer(struct snd_card *card)
+static int snd_cs4231_mixer(struct snd_card *card)
{
struct snd_cs4231 *chip = card->private_data;
int err, idx;
@@ -1558,7 +1558,7 @@ static int __devinit snd_cs4231_mixer(struct snd_card *card)
static int dev;
-static int __devinit cs4231_attach_begin(struct snd_card **rcard)
+static int cs4231_attach_begin(struct snd_card **rcard)
{
struct snd_card *card;
struct snd_cs4231 *chip;
@@ -1589,7 +1589,7 @@ static int __devinit cs4231_attach_begin(struct snd_card **rcard)
return 0;
}
-static int __devinit cs4231_attach_finish(struct snd_card *card)
+static int cs4231_attach_finish(struct snd_card *card)
{
struct snd_cs4231 *chip = card->private_data;
int err;
@@ -1793,9 +1793,9 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
.dev_free = snd_cs4231_sbus_dev_free,
};
-static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
- struct platform_device *op,
- int dev)
+static int snd_cs4231_sbus_create(struct snd_card *card,
+ struct platform_device *op,
+ int dev)
{
struct snd_cs4231 *chip = card->private_data;
int err;
@@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
return 0;
}
-static int __devinit cs4231_sbus_probe(struct platform_device *op)
+static int cs4231_sbus_probe(struct platform_device *op)
{
struct resource *rp = &op->resource[0];
struct snd_card *card;
@@ -1959,9 +1959,9 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
.dev_free = snd_cs4231_ebus_dev_free,
};
-static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
- struct platform_device *op,
- int dev)
+static int snd_cs4231_ebus_create(struct snd_card *card,
+ struct platform_device *op,
+ int dev)
{
struct snd_cs4231 *chip = card->private_data;
int err;
@@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
return 0;
}
-static int __devinit cs4231_ebus_probe(struct platform_device *op)
+static int cs4231_ebus_probe(struct platform_device *op)
{
struct snd_card *card;
int err;
@@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct platform_device *op)
}
#endif
-static int __devinit cs4231_probe(struct platform_device *op)
+static int cs4231_probe(struct platform_device *op)
{
#ifdef EBUS_SUPPORT
if (!strcmp(op->dev.of_node->parent->name, "ebus"))
@@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct platform_device *op)
return -ENODEV;
}
-static int __devexit cs4231_remove(struct platform_device *op)
+static int cs4231_remove(struct platform_device *op)
{
struct snd_cs4231 *chip = dev_get_drvdata(&op->dev);
@@ -2115,7 +2115,7 @@ static struct platform_driver cs4231_driver = {
.of_match_table = cs4231_match,
},
.probe = cs4231_probe,
- .remove = __devexit_p(cs4231_remove),
+ .remove = cs4231_remove,
};
module_platform_driver(cs4231_driver);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index ae35f5342e10..75e6016d3efe 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -745,7 +745,7 @@ static void dbri_reset(struct snd_dbri *dbri)
}
/* Lock must not be held before calling this */
-static void __devinit dbri_initialize(struct snd_dbri *dbri)
+static void dbri_initialize(struct snd_dbri *dbri)
{
s32 *cmd;
u32 dma_addr;
@@ -1305,7 +1305,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins.
* Lock must not be held before calling it.
*/
-static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
+static void cs4215_setup_pipes(struct snd_dbri *dbri)
{
unsigned long flags;
@@ -1338,7 +1338,7 @@ static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
dbri_cmdwait(dbri);
}
-static __devinit int cs4215_init_data(struct cs4215 *mm)
+static int cs4215_init_data(struct cs4215 *mm)
{
/*
* No action, memory resetting only.
@@ -1630,7 +1630,7 @@ static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
/*
*
*/
-static __devinit int cs4215_init(struct snd_dbri *dbri)
+static int cs4215_init(struct snd_dbri *dbri)
{
u32 reg2 = sbus_readl(dbri->regs + REG2);
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
@@ -2217,7 +2217,7 @@ static struct snd_pcm_ops snd_dbri_ops = {
.pointer = snd_dbri_pointer,
};
-static int __devinit snd_dbri_pcm(struct snd_card *card)
+static int snd_dbri_pcm(struct snd_card *card)
{
struct snd_pcm *pcm;
int err;
@@ -2409,7 +2409,7 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
.private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \
((invert) << 24) },
-static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
+static struct snd_kcontrol_new dbri_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Playback Volume",
@@ -2436,7 +2436,7 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
};
-static int __devinit snd_dbri_mixer(struct snd_card *card)
+static int snd_dbri_mixer(struct snd_card *card)
{
int idx, err;
struct snd_dbri *dbri;
@@ -2500,7 +2500,7 @@ static void dbri_debug_read(struct snd_info_entry *entry,
}
#endif
-static void __devinit snd_dbri_proc(struct snd_card *card)
+static void snd_dbri_proc(struct snd_card *card)
{
struct snd_dbri *dbri = card->private_data;
struct snd_info_entry *entry;
@@ -2523,9 +2523,9 @@ static void __devinit snd_dbri_proc(struct snd_card *card)
*/
static void snd_dbri_free(struct snd_dbri *dbri);
-static int __devinit snd_dbri_create(struct snd_card *card,
- struct platform_device *op,
- int irq, int dev)
+static int snd_dbri_create(struct snd_card *card,
+ struct platform_device *op,
+ int irq, int dev)
{
struct snd_dbri *dbri = card->private_data;
int err;
@@ -2593,7 +2593,7 @@ static void snd_dbri_free(struct snd_dbri *dbri)
(void *)dbri->dma, dbri->dma_dvma);
}
-static int __devinit dbri_probe(struct platform_device *op)
+static int dbri_probe(struct platform_device *op)
{
struct snd_dbri *dbri;
struct resource *rp;
@@ -2663,7 +2663,7 @@ _err:
return err;
}
-static int __devexit dbri_remove(struct platform_device *op)
+static int dbri_remove(struct platform_device *op)
{
struct snd_card *card = dev_get_drvdata(&op->dev);
@@ -2694,7 +2694,7 @@ static struct platform_driver dbri_sbus_driver = {
.of_match_table = dbri_match,
},
.probe = dbri_probe,
- .remove = __devexit_p(dbri_remove),
+ .remove = dbri_remove,
};
module_platform_driver(dbri_sbus_driver);
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index c6500d00053b..4dd60d8a4889 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -330,7 +330,7 @@ static struct snd_pcm_ops at73c213_playback_ops = {
.pointer = snd_at73c213_pcm_pointer,
};
-static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+static int snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
{
struct snd_pcm *pcm;
int retval;
@@ -665,7 +665,7 @@ static int snd_at73c213_aux_capture_volume_info(
| (mask << 24) | (invert << 22)) \
}
-static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_at73c213_controls[] = {
AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1),
AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1),
AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1),
@@ -709,7 +709,7 @@ AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN,
AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0),
};
-static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip)
+static int snd_at73c213_mixer(struct snd_at73c213 *chip)
{
struct snd_card *card;
int errval, idx;
@@ -744,7 +744,7 @@ cleanup:
/*
* Device functions
*/
-static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
{
/*
* Continuous clock output.
@@ -774,7 +774,7 @@ static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
return 0;
}
-static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
+static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
{
int retval;
unsigned char dac_ctrl = 0;
@@ -879,8 +879,8 @@ static int snd_at73c213_dev_free(struct snd_device *device)
return 0;
}
-static int __devinit snd_at73c213_dev_init(struct snd_card *card,
- struct spi_device *spi)
+static int snd_at73c213_dev_init(struct snd_card *card,
+ struct spi_device *spi)
{
static struct snd_device_ops ops = {
.dev_free = snd_at73c213_dev_free,
@@ -940,7 +940,7 @@ out:
return retval;
}
-static int __devinit snd_at73c213_probe(struct spi_device *spi)
+static int snd_at73c213_probe(struct spi_device *spi)
{
struct snd_card *card;
struct snd_at73c213 *chip;
@@ -1007,7 +1007,7 @@ out:
return retval;
}
-static int __devexit snd_at73c213_remove(struct spi_device *spi)
+static int snd_at73c213_remove(struct spi_device *spi)
{
struct snd_card *card = dev_get_drvdata(&spi->dev);
struct snd_at73c213 *chip = card->private_data;
@@ -1109,7 +1109,7 @@ static struct spi_driver at73c213_driver = {
.probe = snd_at73c213_probe,
.suspend = snd_at73c213_suspend,
.resume = snd_at73c213_resume,
- .remove = __devexit_p(snd_at73c213_remove),
+ .remove = snd_at73c213_remove,
};
module_spi_driver(at73c213_driver);
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index fc8cc823e438..4394ae796356 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -82,8 +82,8 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
}
}
-static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
- const struct usb_device_id *usb_id)
+static int usb6fire_chip_probe(struct usb_interface *intf,
+ const struct usb_device_id *usb_id)
{
int ret;
int i;
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index 6c3d531a250e..9e6e3ffd86bb 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -125,16 +125,17 @@ static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
}
-int __devinit usb6fire_comm_init(struct sfire_chip *chip)
+int usb6fire_comm_init(struct sfire_chip *chip)
{
struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
GFP_KERNEL);
- struct urb *urb = &rt->receiver;
+ struct urb *urb;
int ret;
if (!rt)
return -ENOMEM;
+ urb = &rt->receiver;
rt->serial = 1;
rt->chip = chip;
usb_init_urb(urb);
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
index d2af0a5ddcf3..6a0840b0dcff 100644
--- a/sound/usb/6fire/comm.h
+++ b/sound/usb/6fire/comm.h
@@ -36,7 +36,7 @@ struct comm_runtime {
u8 vh, u8 vl);
};
-int __devinit usb6fire_comm_init(struct sfire_chip *chip);
+int usb6fire_comm_init(struct sfire_chip *chip);
void usb6fire_comm_abort(struct sfire_chip *chip);
void usb6fire_comm_destroy(struct sfire_chip *chip);
#endif /* USB6FIRE_COMM_H */
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index 07ed914d5e71..f6434c245720 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -411,7 +411,7 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct __devinitdata snd_kcontrol_new vol_elements[] = {
+static struct snd_kcontrol_new vol_elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Playback Volume",
@@ -451,7 +451,7 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = {
{}
};
-static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+static struct snd_kcontrol_new mute_elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Playback Switch",
@@ -485,7 +485,7 @@ static struct __devinitdata snd_kcontrol_new mute_elements[] = {
{}
};
-static struct __devinitdata snd_kcontrol_new elements[] = {
+static struct snd_kcontrol_new elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line/Phono Capture Route",
@@ -561,7 +561,7 @@ static int usb6fire_control_add_virtual(
return 0;
}
-int __devinit usb6fire_control_init(struct sfire_chip *chip)
+int usb6fire_control_init(struct sfire_chip *chip)
{
int i;
int ret;
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
index 9a596d95474a..5a40ba143489 100644
--- a/sound/usb/6fire/control.h
+++ b/sound/usb/6fire/control.h
@@ -50,7 +50,7 @@ struct control_runtime {
u8 ivol_updated;
};
-int __devinit usb6fire_control_init(struct sfire_chip *chip);
+int usb6fire_control_init(struct sfire_chip *chip);
void usb6fire_control_abort(struct sfire_chip *chip);
void usb6fire_control_destroy(struct sfire_chip *chip);
#endif /* USB6FIRE_CONTROL_H */
diff --git a/sound/usb/6fire/firmware.h b/sound/usb/6fire/firmware.h
index 008569895381..c109c4f75aba 100644
--- a/sound/usb/6fire/firmware.h
+++ b/sound/usb/6fire/firmware.h
@@ -22,6 +22,6 @@ enum /* firmware state of device */
FW_NOT_READY = 1
};
-int __devinit usb6fire_fw_init(struct usb_interface *intf);
+int usb6fire_fw_init(struct usb_interface *intf);
#endif /* USB6FIRE_FIRMWARE_H */
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index f0e5179b242b..26722423330d 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -146,7 +146,7 @@ static struct snd_rawmidi_ops in_ops = {
.trigger = usb6fire_midi_in_trigger
};
-int __devinit usb6fire_midi_init(struct sfire_chip *chip)
+int usb6fire_midi_init(struct sfire_chip *chip)
{
int ret;
struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
index 5114eccc1d8e..c321006e5430 100644
--- a/sound/usb/6fire/midi.h
+++ b/sound/usb/6fire/midi.h
@@ -38,7 +38,7 @@ struct midi_runtime {
void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
};
-int __devinit usb6fire_midi_init(struct sfire_chip *chip);
+int usb6fire_midi_init(struct sfire_chip *chip);
void usb6fire_midi_abort(struct sfire_chip *chip);
void usb6fire_midi_destroy(struct sfire_chip *chip);
#endif /* USB6FIRE_MIDI_H */
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index c97d05f0e966..e2ca12fe92e9 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -135,6 +135,9 @@ static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
struct control_runtime *ctrl_rt = rt->chip->control;
if (rt->stream_state != STREAM_DISABLED) {
+
+ rt->stream_state = STREAM_STOPPING;
+
for (i = 0; i < PCM_N_URBS; i++) {
usb_kill_urb(&rt->in_urbs[i].instance);
usb_kill_urb(&rt->out_urbs[i].instance);
@@ -559,9 +562,9 @@ static struct snd_pcm_ops pcm_ops = {
.pointer = usb6fire_pcm_pointer,
};
-static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
- struct sfire_chip *chip, bool in, int ep,
- void (*handler)(struct urb *))
+static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
+ struct sfire_chip *chip, bool in, int ep,
+ void (*handler)(struct urb *))
{
urb->chip = chip;
usb_init_urb(&urb->instance);
@@ -578,7 +581,7 @@ static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
}
-int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
+int usb6fire_pcm_init(struct sfire_chip *chip)
{
int i;
int ret;
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
index 3104301b257d..9b01133ee3fe 100644
--- a/sound/usb/6fire/pcm.h
+++ b/sound/usb/6fire/pcm.h
@@ -69,7 +69,7 @@ struct pcm_runtime {
bool stream_wait_cond;
};
-int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
+int usb6fire_pcm_init(struct sfire_chip *chip);
void usb6fire_pcm_abort(struct sfire_chip *chip);
void usb6fire_pcm_destroy(struct sfire_chip *chip);
#endif /* USB6FIRE_PCM_H */
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index ff77b28f3da1..225dfd737265 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -90,7 +90,7 @@ config SND_USB_CAIAQ_INPUT
config SND_USB_US122L
tristate "Tascam US-122L USB driver"
- depends on X86 && EXPERIMENTAL
+ depends on X86
select SND_HWDEP
select SND_RAWMIDI
help
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index 00e5d0a469e1..adb8d03267a0 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -137,7 +137,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new kcontrol_template __devinitdata = {
+static struct snd_kcontrol_new kcontrol_template = {
.iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.index = 0,
@@ -489,8 +489,8 @@ static struct caiaq_controller kontrols4_controller[] = {
{ "LED: FX2: Mode", 133 | CNT_INTVAL },
};
-static int __devinit add_controls(struct caiaq_controller *c, int num,
- struct snd_usb_caiaqdev *dev)
+static int add_controls(struct caiaq_controller *c, int num,
+ struct snd_usb_caiaqdev *dev)
{
int i, ret;
struct snd_kcontrol *kc;
@@ -507,7 +507,7 @@ static int __devinit add_controls(struct caiaq_controller *c, int num,
return 0;
}
-int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
{
int ret = 0;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 7da0d0aa72cb..c828f8189c25 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -289,7 +289,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *dev,
tmp, sizeof(tmp));
}
-static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
+static void setup_card(struct snd_usb_caiaqdev *dev)
{
int ret;
char val[4];
@@ -407,7 +407,7 @@ static int create_card(struct usb_device *usb_dev,
return 0;
}
-static int __devinit init_card(struct snd_usb_caiaqdev *dev)
+static int init_card(struct snd_usb_caiaqdev *dev)
{
char *c, usbpath[32];
struct usb_device *usb_dev = dev->chip.dev;
@@ -481,7 +481,7 @@ static int __devinit init_card(struct snd_usb_caiaqdev *dev)
return 0;
}
-static int __devinit snd_probe(struct usb_interface *intf,
+static int snd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int ret;
diff --git a/sound/usb/card.c b/sound/usb/card.c
index dbf7999d18b4..ccf95cfe186f 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -25,9 +25,6 @@
*
* NOTES:
*
- * - async unlink should be used for avoiding the sleep inside lock.
- * 2.4.22 usb-uhci seems buggy for async unlinking and results in
- * oops. in such a cse, pass async_unlink=0 option.
* - the linked URBs would be preferred but not used so far because of
* the instability of unlinking.
* - type II is not supported properly. there is no device which supports
@@ -83,7 +80,6 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card *
static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int nrpacks = 8; /* max. number of packets per urb */
-static bool async_unlink = 1;
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
static bool ignore_ctl_error;
@@ -99,8 +95,6 @@ module_param_array(pid, int, NULL, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
module_param(nrpacks, int, 0644);
MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
-module_param(async_unlink, bool, 0444);
-MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
module_param_array(device_setup, int, NULL, 0444);
MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
module_param(ignore_ctl_error, bool, 0444);
@@ -345,7 +339,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->card = card;
chip->setup = device_setup[idx];
chip->nrpacks = nrpacks;
- chip->async_unlink = async_unlink;
chip->probing = 1;
chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 814cb357ff88..8a751b4887ea 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -27,6 +27,7 @@ struct audioformat {
unsigned int nr_rates; /* number of rate table entries */
unsigned int *rate_table; /* rate table */
unsigned char clock; /* associated clock */
+ struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */
};
struct snd_usb_substream;
@@ -109,6 +110,7 @@ struct snd_usb_substream {
struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */
snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */
unsigned int channels; /* current number of channels (for hw_params callback) */
+ unsigned int channels_max; /* max channels in the all audiofmts */
unsigned int cur_rate; /* current rate (for hw_params callback) */
unsigned int period_bytes; /* current period bytes (for hw_params callback) */
unsigned int altset_idx; /* USB data format: index of alternate setting */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 34de6f2faf61..21049b882ee6 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -485,15 +485,10 @@ __exit_unlock:
static int wait_clear_urbs(struct snd_usb_endpoint *ep)
{
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
- unsigned int i;
int alive;
do {
- alive = 0;
- for (i = 0; i < ep->nurbs; i++)
- if (test_bit(i, &ep->active_mask))
- alive++;
-
+ alive = bitmap_weight(&ep->active_mask, ep->nurbs);
if (!alive)
break;
@@ -520,33 +515,24 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
/*
* unlink active urbs.
*/
-static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep)
+static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
{
unsigned int i;
- int async;
if (!force && ep->chip->shutdown) /* to be sure... */
return -EBADFD;
- async = !can_sleep && ep->chip->async_unlink;
-
clear_bit(EP_FLAG_RUNNING, &ep->flags);
INIT_LIST_HEAD(&ep->ready_playback_urbs);
ep->next_packet_read_pos = 0;
ep->next_packet_write_pos = 0;
- if (!async && in_interrupt())
- return 0;
-
for (i = 0; i < ep->nurbs; i++) {
if (test_bit(i, &ep->active_mask)) {
if (!test_and_set_bit(i, &ep->unlink_mask)) {
struct urb *u = ep->urb[i].urb;
- if (async)
- usb_unlink_urb(u);
- else
- usb_kill_urb(u);
+ usb_unlink_urb(u);
}
}
}
@@ -566,7 +552,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
ep->prepare_data_urb = NULL;
/* stop urbs */
- deactivate_urbs(ep, force, 1);
+ deactivate_urbs(ep, force);
wait_clear_urbs(ep);
for (i = 0; i < ep->nurbs; i++)
@@ -829,7 +815,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
*
* Returns an error if the URB submission failed, 0 in all other cases.
*/
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
{
int err;
unsigned int i;
@@ -842,7 +828,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
return 0;
/* just to be sure */
- deactivate_urbs(ep, 0, can_sleep);
+ deactivate_urbs(ep, false);
if (can_sleep)
wait_clear_urbs(ep);
@@ -896,7 +882,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
__error:
clear_bit(EP_FLAG_RUNNING, &ep->flags);
ep->use_count--;
- deactivate_urbs(ep, 0, 0);
+ deactivate_urbs(ep, false);
return -EPIPE;
}
@@ -910,9 +896,11 @@ __error:
* actually be deactivated.
*
* Must be balanced to calls of snd_usb_endpoint_start().
+ *
+ * The caller needs to synchronize the pending stop operation via
+ * snd_usb_endpoint_sync_pending_stop().
*/
-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
- int force, int can_sleep, int wait)
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
{
if (!ep)
return;
@@ -921,16 +909,12 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
return;
if (--ep->use_count == 0) {
- deactivate_urbs(ep, force, can_sleep);
+ deactivate_urbs(ep, false);
ep->data_subs = NULL;
ep->sync_slave = NULL;
ep->retire_data_urb = NULL;
ep->prepare_data_urb = NULL;
-
- if (wait)
- wait_clear_urbs(ep);
- else
- set_bit(EP_FLAG_STOPPING, &ep->flags);
+ set_bit(EP_FLAG_STOPPING, &ep->flags);
}
}
@@ -952,7 +936,7 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
if (!ep)
return -EINVAL;
- deactivate_urbs(ep, 1, 1);
+ deactivate_urbs(ep, true);
wait_clear_urbs(ep);
if (ep->use_count != 0)
@@ -1034,15 +1018,18 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
/*
* Iterate through the inbound packet and prepare the lengths
* for the output packet. The OUT packet we are about to send
- * will have the same amount of payload bytes than the IN
- * packet we just received.
+ * will have the same amount of payload bytes per stride as the
+ * IN packet we just received. Since the actual size is scaled
+ * by the stride, use the sender stride to calculate the length
+ * in case the number of channels differ between the implicitly
+ * fed-back endpoint and the synchronizing endpoint.
*/
out_packet->packets = in_ctx->packets;
for (i = 0; i < in_ctx->packets; i++) {
if (urb->iso_frame_desc[i].status == 0)
out_packet->packet_size[i] =
- urb->iso_frame_desc[i].actual_length / ep->stride;
+ urb->iso_frame_desc[i].actual_length / sender->stride;
else
out_packet->packet_size[i] = 0;
}
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 3d4c9705041f..447902dd8a4a 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -16,9 +16,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep);
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
- int force, int can_sleep, int wait);
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep);
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/format.c b/sound/usb/format.c
index ddfef57c4c9f..e831ee4238bb 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -155,7 +155,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
chip->dev->devnum, fp->iface, fp->altsetting);
- return -1;
+ return -EINVAL;
}
if (nr_rates) {
@@ -167,7 +167,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
if (fp->rate_table == NULL) {
snd_printk(KERN_ERR "cannot malloc\n");
- return -1;
+ return -ENOMEM;
}
fp->nr_rates = 0;
@@ -198,7 +198,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
}
if (!fp->nr_rates) {
hwc_debug("All rates were zero. Skipping format!\n");
- return -1;
+ return -EINVAL;
}
} else {
/* continuous rates */
@@ -383,7 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
fp->formats = parse_audio_format_i_type(chip, fp, format,
fmt, protocol);
if (!fp->formats)
- return -1;
+ return -EINVAL;
}
/* gather possible sample rates */
@@ -409,7 +409,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
if (fp->channels < 1) {
snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
- return -1;
+ return -EINVAL;
}
return ret;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index eeefbce3873c..34b9bb7fe87c 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -116,6 +116,7 @@ struct snd_usb_midi {
struct list_head list;
struct timer_list error_timer;
spinlock_t disc_lock;
+ struct rw_semaphore disc_rwsem;
struct mutex mutex;
u32 usb_id;
int next_midi_device;
@@ -125,8 +126,10 @@ struct snd_usb_midi {
struct snd_usb_midi_in_endpoint *in;
} endpoints[MIDI_MAX_ENDPOINTS];
unsigned long input_triggered;
- unsigned int opened;
+ bool autopm_reference;
+ unsigned int opened[2];
unsigned char disconnected;
+ unsigned char input_running;
struct snd_kcontrol *roland_load_ctl;
};
@@ -148,7 +151,6 @@ struct snd_usb_midi_out_endpoint {
struct snd_usb_midi_out_endpoint* ep;
struct snd_rawmidi_substream *substream;
int active;
- bool autopm_reference;
uint8_t cable; /* cable number << 4 */
uint8_t state;
#define STATE_UNKNOWN 0
@@ -1033,29 +1035,58 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi)
snd_usbmidi_input_start(&umidi->list);
}
-static void substream_open(struct snd_rawmidi_substream *substream, int open)
+static int substream_open(struct snd_rawmidi_substream *substream, int dir,
+ int open)
{
struct snd_usb_midi* umidi = substream->rmidi->private_data;
struct snd_kcontrol *ctl;
+ int err;
+
+ down_read(&umidi->disc_rwsem);
+ if (umidi->disconnected) {
+ up_read(&umidi->disc_rwsem);
+ return open ? -ENODEV : 0;
+ }
mutex_lock(&umidi->mutex);
if (open) {
- if (umidi->opened++ == 0 && umidi->roland_load_ctl) {
- ctl = umidi->roland_load_ctl;
- ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- snd_ctl_notify(umidi->card,
+ if (!umidi->opened[0] && !umidi->opened[1]) {
+ err = usb_autopm_get_interface(umidi->iface);
+ umidi->autopm_reference = err >= 0;
+ if (err < 0 && err != -EACCES) {
+ mutex_unlock(&umidi->mutex);
+ up_read(&umidi->disc_rwsem);
+ return -EIO;
+ }
+ if (umidi->roland_load_ctl) {
+ ctl = umidi->roland_load_ctl;
+ ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(umidi->card,
SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
- update_roland_altsetting(umidi);
+ update_roland_altsetting(umidi);
+ }
}
+ umidi->opened[dir]++;
+ if (umidi->opened[1])
+ snd_usbmidi_input_start(&umidi->list);
} else {
- if (--umidi->opened == 0 && umidi->roland_load_ctl) {
- ctl = umidi->roland_load_ctl;
- ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- snd_ctl_notify(umidi->card,
+ umidi->opened[dir]--;
+ if (!umidi->opened[1])
+ snd_usbmidi_input_stop(&umidi->list);
+ if (!umidi->opened[0] && !umidi->opened[1]) {
+ if (umidi->roland_load_ctl) {
+ ctl = umidi->roland_load_ctl;
+ ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(umidi->card,
SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+ }
+ if (umidi->autopm_reference)
+ usb_autopm_put_interface(umidi->iface);
}
}
mutex_unlock(&umidi->mutex);
+ up_read(&umidi->disc_rwsem);
+ return 0;
}
static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
@@ -1063,7 +1094,6 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
struct snd_usb_midi* umidi = substream->rmidi->private_data;
struct usbmidi_out_port* port = NULL;
int i, j;
- int err;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
if (umidi->endpoints[i].out)
@@ -1076,25 +1106,15 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
snd_BUG();
return -ENXIO;
}
- err = usb_autopm_get_interface(umidi->iface);
- port->autopm_reference = err >= 0;
- if (err < 0 && err != -EACCES)
- return -EIO;
+
substream->runtime->private_data = port;
port->state = STATE_UNKNOWN;
- substream_open(substream, 1);
- return 0;
+ return substream_open(substream, 0, 1);
}
static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
{
- struct snd_usb_midi* umidi = substream->rmidi->private_data;
- struct usbmidi_out_port *port = substream->runtime->private_data;
-
- substream_open(substream, 0);
- if (port->autopm_reference)
- usb_autopm_put_interface(umidi->iface);
- return 0;
+ return substream_open(substream, 0, 0);
}
static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1147,14 +1167,12 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
{
- substream_open(substream, 1);
- return 0;
+ return substream_open(substream, 1, 1);
}
static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
{
- substream_open(substream, 0);
- return 0;
+ return substream_open(substream, 1, 0);
}
static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1403,9 +1421,12 @@ void snd_usbmidi_disconnect(struct list_head* p)
* a timer may submit an URB. To reliably break the cycle
* a flag under lock must be used
*/
+ down_write(&umidi->disc_rwsem);
spin_lock_irq(&umidi->disc_lock);
umidi->disconnected = 1;
spin_unlock_irq(&umidi->disc_lock);
+ up_write(&umidi->disc_rwsem);
+
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
if (ep->out)
@@ -2060,12 +2081,15 @@ void snd_usbmidi_input_stop(struct list_head* p)
unsigned int i, j;
umidi = list_entry(p, struct snd_usb_midi, list);
+ if (!umidi->input_running)
+ return;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
if (ep->in)
for (j = 0; j < INPUT_URBS; ++j)
usb_kill_urb(ep->in->urbs[j]);
}
+ umidi->input_running = 0;
}
static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
@@ -2090,8 +2114,11 @@ void snd_usbmidi_input_start(struct list_head* p)
int i;
umidi = list_entry(p, struct snd_usb_midi, list);
+ if (umidi->input_running || !umidi->opened[1])
+ return;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+ umidi->input_running = 1;
}
/*
@@ -2117,6 +2144,7 @@ int snd_usbmidi_create(struct snd_card *card,
umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
init_timer(&umidi->error_timer);
spin_lock_init(&umidi->disc_lock);
+ init_rwsem(&umidi->disc_rwsem);
mutex_init(&umidi->mutex);
umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
le16_to_cpu(umidi->dev->descriptor.idProduct));
@@ -2229,9 +2257,6 @@ int snd_usbmidi_create(struct snd_card *card,
}
list_add_tail(&umidi->list, midi_list);
-
- for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
- snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
return 0;
}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 298070e8f2d4..ed4d89c8b52a 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -382,6 +382,8 @@ error:
static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
{
+ validx += cval->idx_off;
+
return (cval->mixer->protocol == UAC_VERSION_1) ?
get_ctl_value_v1(cval, request, validx, value_ret) :
get_ctl_value_v2(cval, request, validx, value_ret);
@@ -432,6 +434,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
unsigned char buf[2];
int idx = 0, val_len, err, timeout = 10;
+ validx += cval->idx_off;
+
if (cval->mixer->protocol == UAC_VERSION_1) {
val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
} else { /* UAC_VERSION_2 */
@@ -719,8 +723,19 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
return 0;
}
case UAC1_PROCESSING_UNIT:
- case UAC1_EXTENSION_UNIT: {
+ case UAC1_EXTENSION_UNIT:
+ /* UAC2_PROCESSING_UNIT_V2 */
+ /* UAC2_EFFECT_UNIT */ {
struct uac_processing_unit_descriptor *d = p1;
+
+ if (state->mixer->protocol == UAC_VERSION_2 &&
+ hdr[2] == UAC2_EFFECT_UNIT) {
+ /* UAC2/UAC1 unit IDs overlap here in an
+ * uncompatible way. Ignore this unit for now.
+ */
+ return 0;
+ }
+
if (d->bNrInPins) {
id = d->baSourceID[0];
break; /* continue to parse */
@@ -791,6 +806,33 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
switch (cval->mixer->chip->usb_id) {
+ case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+ if (strcmp(kctl->id.name, "Effect Duration") == 0) {
+ cval->min = 0x0000;
+ cval->max = 0xffff;
+ cval->res = 0x00e6;
+ break;
+ }
+ if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
+ strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
+ cval->min = 0x00;
+ cval->max = 0xff;
+ break;
+ }
+ if (strstr(kctl->id.name, "Effect Return") != NULL) {
+ cval->min = 0xb706;
+ cval->max = 0xff7b;
+ cval->res = 0x0073;
+ break;
+ }
+ if ((strstr(kctl->id.name, "Playback Volume") != NULL) ||
+ (strstr(kctl->id.name, "Effect Send") != NULL)) {
+ cval->min = 0xb5fb; /* -73 dB = 0xb6ff */
+ cval->max = 0xfcfe;
+ cval->res = 0x0073;
+ }
+ break;
+
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
if (strcmp(kctl->id.name, "Effect Duration") == 0) {
@@ -1094,6 +1136,32 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
}
+/* A lot of headsets/headphones have a "Speaker" mixer. Make sure we
+ rename it to "Headphone". We determine if something is a headphone
+ similar to how udev determines form factor. */
+static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
+ struct snd_card *card)
+{
+ const char *names_to_check[] = {
+ "Headset", "headset", "Headphone", "headphone", NULL};
+ const char **s;
+ bool found = 0;
+
+ if (strcmp("Speaker", kctl->id.name))
+ return;
+
+ for (s = names_to_check; *s; s++)
+ if (strstr(card->shortname, *s)) {
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ return;
+
+ strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
+}
+
static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
unsigned int ctl_mask, int control,
struct usb_audio_term *iterm, int unitid,
@@ -1180,6 +1248,10 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = snprintf(kctl->id.name, sizeof(kctl->id.name),
"Feature %d", unitid);
}
+
+ if (!mapped_name)
+ check_no_speaker_on_headset(kctl, state->mixer->chip->card);
+
/* determine the stream direction:
* if the connected output is USB stream, then it's likely a
* capture stream. otherwise it should be playback (hopefully :)
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index a7f3d45a8acf..aab80df201bd 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -43,6 +43,7 @@ struct usb_mixer_elem_info {
unsigned int id;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
+ unsigned int idx_off; /* Control index offset */
unsigned int ch_readonly;
unsigned int master_readonly;
int channels;
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index ae2b71435220..0422b1360af3 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -63,11 +63,12 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
* Since there doesn't seem to be a devices that needs a multichannel
* version, we keep it mono for simplicity.
*/
-static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
+static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer,
unsigned int unitid,
unsigned int control,
unsigned int cmask,
int val_type,
+ unsigned int idx_off,
const char *name,
snd_kcontrol_tlv_rw_t *tlv_callback)
{
@@ -85,6 +86,7 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
cval->channels = 1;
cval->control = control;
cval->cmask = cmask;
+ cval->idx_off = idx_off;
/* get_min_max() is called only for integer volumes later,
* so provide a short-cut for booleans */
@@ -120,6 +122,18 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
return 0;
}
+static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
+ unsigned int unitid,
+ unsigned int control,
+ unsigned int cmask,
+ int val_type,
+ const char *name,
+ snd_kcontrol_tlv_rw_t *tlv_callback)
+{
+ return snd_create_std_mono_ctl_offset(mixer, unitid, control, cmask,
+ val_type, 0 /* Offset */, name, tlv_callback);
+}
+
/*
* Create a set of standard UAC controls from a table
*/
@@ -416,6 +430,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
}
}
+/* ASUS Xonar U1 / U3 controls */
+
static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -621,11 +637,13 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
}
/* M-Audio FastTrack Ultra quirks */
-/* FTU Effect switch */
+/* FTU Effect switch (also used by C400) */
struct snd_ftu_eff_switch_priv_val {
struct usb_mixer_interface *mixer;
int cached_value;
int is_cached;
+ int bUnitID;
+ int validx;
};
static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
@@ -660,9 +678,8 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
struct snd_ftu_eff_switch_priv_val *pval;
int err;
unsigned char value[2];
+ int id, validx;
- const int id = 6;
- const int validx = 1;
const int val_len = 2;
value[0] = 0x00;
@@ -684,6 +701,8 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
if (snd_BUG_ON(!chip))
return -EINVAL;
+ id = pval->bUnitID;
+ validx = pval->validx;
down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
@@ -714,10 +733,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
struct usb_mixer_interface *mixer;
int changed, cur_val, err, new_val;
unsigned char value[2];
+ int id, validx;
-
- const int id = 6;
- const int validx = 1;
const int val_len = 2;
changed = 0;
@@ -735,6 +752,9 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
if (snd_BUG_ON(!chip))
return -EINVAL;
+ id = pval->bUnitID;
+ validx = pval->validx;
+
if (!pval->is_cached) {
/* Read current value */
down_read(&mixer->chip->shutdown_rwsem);
@@ -779,7 +799,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
return changed;
}
-static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
+static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
+ int validx, int bUnitID)
{
static struct snd_kcontrol_new template = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -802,6 +823,8 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
pval->cached_value = 0;
pval->is_cached = 0;
pval->mixer = mixer;
+ pval->bUnitID = bUnitID;
+ pval->validx = validx;
template.private_value = (unsigned long) pval;
kctl = snd_ctl_new1(&template, mixer->chip);
@@ -960,9 +983,10 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
- err = snd_ftu_create_effect_switch(mixer);
+ err = snd_ftu_create_effect_switch(mixer, 1, 6);
if (err < 0)
return err;
+
err = snd_ftu_create_effect_volume_ctl(mixer);
if (err < 0)
return err;
@@ -1005,6 +1029,178 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
}
}
+/* M-Audio Fast Track C400 */
+/* C400 volume controls, this control needs a volume quirk, see mixer.c */
+static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer)
+{
+ char name[64];
+ unsigned int cmask, offset;
+ int out, chan, err;
+
+ const unsigned int id = 0x40;
+ const int val_type = USB_MIXER_S16;
+ const int control = 1;
+
+ for (chan = 0; chan < 10; chan++) {
+ for (out = 0; out < 6; out++) {
+ if (chan < 6) {
+ snprintf(name, sizeof(name),
+ "PCM%d-Out%d Playback Volume",
+ chan + 1, out + 1);
+ } else {
+ snprintf(name, sizeof(name),
+ "In%d-Out%d Playback Volume",
+ chan - 5, out + 1);
+ }
+
+ cmask = (out == 0) ? 0 : 1 << (out - 1);
+ offset = chan * 6;
+ err = snd_create_std_mono_ctl_offset(mixer, id, control,
+ cmask, val_type, offset, name,
+ &snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_volume_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Volume";
+ const unsigned int id = 0x43;
+ const int val_type = USB_MIXER_U8;
+ const unsigned int control = 3;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_duration_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Duration";
+ const unsigned int id = 0x43;
+ const int val_type = USB_MIXER_S16;
+ const unsigned int control = 4;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_feedback_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Feedback Volume";
+ const unsigned int id = 0x43;
+ const int val_type = USB_MIXER_U8;
+ const unsigned int control = 5;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, NULL);
+}
+
+static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer)
+{
+ char name[64];
+ unsigned int cmask;
+ int chan, err;
+
+ const unsigned int id = 0x42;
+ const int val_type = USB_MIXER_S16;
+ const int control = 1;
+
+ for (chan = 0; chan < 10; chan++) {
+ if (chan < 6) {
+ snprintf(name, sizeof(name),
+ "Effect Send DOut%d",
+ chan + 1);
+ } else {
+ snprintf(name, sizeof(name),
+ "Effect Send AIn%d",
+ chan - 5);
+ }
+
+ cmask = (chan == 0) ? 0 : 1 << (chan - 1);
+ err = snd_create_std_mono_ctl(mixer, id, control,
+ cmask, val_type, name,
+ &snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer)
+{
+ char name[64];
+ unsigned int cmask;
+ int chan, err;
+
+ const unsigned int id = 0x40;
+ const int val_type = USB_MIXER_S16;
+ const int control = 1;
+ const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb };
+ const unsigned int offset = 0x3c;
+ /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
+
+ for (chan = 0; chan < 6; chan++) {
+ snprintf(name, sizeof(name),
+ "Effect Return %d",
+ chan + 1);
+
+ cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1);
+ err = snd_create_std_mono_ctl_offset(mixer, id, control,
+ cmask, val_type, offset, name,
+ &snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
+{
+ int err;
+
+ err = snd_c400_create_vol_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_c400_create_effect_vol_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_c400_create_effect_ret_vol_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_switch(mixer, 2, 0x43);
+ if (err < 0)
+ return err;
+
+ err = snd_c400_create_effect_volume_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_c400_create_effect_duration_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_c400_create_effect_feedback_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
/*
* The mixer units for Ebox-44 are corrupt, and even where they
* are valid they presents mono controls as L and R channels of
@@ -1102,13 +1298,18 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
snd_audigy2nx_proc_read);
break;
+ case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+ err = snd_c400_create_mixer(mixer);
+ break;
+
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
err = snd_ftu_create_mixer(mixer);
break;
- case USB_ID(0x0b05, 0x1739):
- case USB_ID(0x0b05, 0x1743):
+ case USB_ID(0x0b05, 0x1739): /* ASUS Xonar U1 */
+ case USB_ID(0x0b05, 0x1743): /* ASUS Xonar U1 (2) */
+ case USB_ID(0x0b05, 0x17a0): /* ASUS Xonar U3 */
err = snd_xonar_u1_controls_create(mixer);
break;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index ef6fa24fc473..c6593101c049 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -46,6 +46,9 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
int frame_diff;
int est_delay;
+ if (!subs->last_delay)
+ return 0; /* short path */
+
current_frame_number = usb_get_current_frame_number(subs->dev);
/*
* HCD implementations use different widths, use lower 8 bits.
@@ -75,7 +78,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
return SNDRV_PCM_POS_XRUN;
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
- substream->runtime->delay = snd_usb_pcm_delay(subs,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ substream->runtime->delay = snd_usb_pcm_delay(subs,
substream->runtime->rate);
spin_unlock(&subs->lock);
return hwptr_done / (substream->runtime->frame_bits >> 3);
@@ -173,11 +177,8 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
{
struct usb_device *dev = chip->dev;
unsigned char data[1];
- unsigned int ep;
int err;
- ep = get_endpoint(alts, 0)->bEndpointAddress;
-
data[0] = 1;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
@@ -214,7 +215,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
}
}
-static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
+static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
{
int err;
@@ -266,16 +267,18 @@ static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
return 0;
}
-static void stop_endpoints(struct snd_usb_substream *subs,
- int force, int can_sleep, int wait)
+static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
{
if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
- snd_usb_endpoint_stop(subs->sync_endpoint,
- force, can_sleep, wait);
+ snd_usb_endpoint_stop(subs->sync_endpoint);
if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
- snd_usb_endpoint_stop(subs->data_endpoint,
- force, can_sleep, wait);
+ snd_usb_endpoint_stop(subs->data_endpoint);
+
+ if (wait) {
+ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
+ }
}
static int deactivate_endpoints(struct snd_usb_substream *subs)
@@ -359,6 +362,19 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
switch (subs->stream->chip->usb_id) {
+ case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+ if (is_playback) {
+ implicit_fb = 1;
+ ep = 0x81;
+ iface = usb_ifnum_to_if(dev, 3);
+
+ if (!iface || iface->num_altsetting == 0)
+ return -EINVAL;
+
+ alts = &iface->altsetting[1];
+ goto add_sync_ep;
+ }
+ break;
case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
case USB_ID(0x0763, 0x2081):
if (is_playback) {
@@ -381,7 +397,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
/* ... and check descriptor size before accessing bSynchAddress
because there is a version of the SB Audigy 2 NX firmware lacking
the audio fields in the endpoint descriptors */
- if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 ||
+ if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
(get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
get_endpoint(alts, 1)->bSynchAddress != 0 &&
!implicit_fb)) {
@@ -438,6 +454,103 @@ add_sync_ep:
}
/*
+ * Return the score of matching two audioformats.
+ * Veto the audioformat if:
+ * - It has no channels for some reason.
+ * - Requested PCM format is not supported.
+ * - Requested sample rate is not supported.
+ */
+static int match_endpoint_audioformats(struct audioformat *fp,
+ struct audioformat *match, int rate,
+ snd_pcm_format_t pcm_format)
+{
+ int i;
+ int score = 0;
+
+ if (fp->channels < 1) {
+ snd_printdd("%s: (fmt @%p) no channels\n", __func__, fp);
+ return 0;
+ }
+
+ if (!(fp->formats & (1ULL << pcm_format))) {
+ snd_printdd("%s: (fmt @%p) no match for format %d\n", __func__,
+ fp, pcm_format);
+ return 0;
+ }
+
+ for (i = 0; i < fp->nr_rates; i++) {
+ if (fp->rate_table[i] == rate) {
+ score++;
+ break;
+ }
+ }
+ if (!score) {
+ snd_printdd("%s: (fmt @%p) no match for rate %d\n", __func__,
+ fp, rate);
+ return 0;
+ }
+
+ if (fp->channels == match->channels)
+ score++;
+
+ snd_printdd("%s: (fmt @%p) score %d\n", __func__, fp, score);
+
+ return score;
+}
+
+/*
+ * Configure the sync ep using the rate and pcm format of the data ep.
+ */
+static int configure_sync_endpoint(struct snd_usb_substream *subs)
+{
+ int ret;
+ struct audioformat *fp;
+ struct audioformat *sync_fp = NULL;
+ int cur_score = 0;
+ int sync_period_bytes = subs->period_bytes;
+ struct snd_usb_substream *sync_subs =
+ &subs->stream->substream[subs->direction ^ 1];
+
+ /* Try to find the best matching audioformat. */
+ list_for_each_entry(fp, &sync_subs->fmt_list, list) {
+ int score = match_endpoint_audioformats(fp, subs->cur_audiofmt,
+ subs->cur_rate, subs->pcm_format);
+
+ if (score > cur_score) {
+ sync_fp = fp;
+ cur_score = score;
+ }
+ }
+
+ if (unlikely(sync_fp == NULL)) {
+ snd_printk(KERN_ERR "%s: no valid audioformat for sync ep %x found\n",
+ __func__, sync_subs->ep_num);
+ return -EINVAL;
+ }
+
+ /*
+ * Recalculate the period bytes if channel number differ between
+ * data and sync ep audioformat.
+ */
+ if (sync_fp->channels != subs->channels) {
+ sync_period_bytes = (subs->period_bytes / subs->channels) *
+ sync_fp->channels;
+ snd_printdd("%s: adjusted sync ep period bytes (%d -> %d)\n",
+ __func__, subs->period_bytes, sync_period_bytes);
+ }
+
+ ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
+ subs->pcm_format,
+ sync_fp->channels,
+ sync_period_bytes,
+ subs->cur_rate,
+ sync_fp,
+ NULL);
+
+ return ret;
+}
+
+/*
* configure endpoint params
*
* called during initial setup and upon resume
@@ -447,7 +560,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
int ret;
/* format changed */
- stop_endpoints(subs, 0, 0, 0);
+ stop_endpoints(subs, true);
ret = snd_usb_endpoint_set_params(subs->data_endpoint,
subs->pcm_format,
subs->channels,
@@ -459,13 +572,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
return ret;
if (subs->sync_endpoint)
- ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
- subs->pcm_format,
- subs->channels,
- subs->period_bytes,
- subs->cur_rate,
- subs->cur_audiofmt,
- NULL);
+ ret = configure_sync_endpoint(subs);
+
return ret;
}
@@ -533,7 +641,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
subs->period_bytes = 0;
down_read(&subs->stream->chip->shutdown_rwsem);
if (!subs->stream->chip->shutdown) {
- stop_endpoints(subs, 0, 1, 1);
+ stop_endpoints(subs, true);
deactivate_endpoints(subs);
}
up_read(&subs->stream->chip->shutdown_rwsem);
@@ -608,7 +716,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
/* for playback, submit the URBs now; otherwise, the first hwptr_done
* updates for all URBs would happen at the same time when starting */
if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
- ret = start_endpoints(subs, 1);
+ ret = start_endpoints(subs, true);
unlock:
up_read(&subs->stream->chip->shutdown_rwsem);
@@ -1013,7 +1121,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction];
- stop_endpoints(subs, 0, 0, 0);
+ stop_endpoints(subs, true);
if (!as->chip->shutdown && subs->interface >= 0) {
usb_set_interface(subs->dev, subs->interface, 0);
@@ -1195,6 +1303,9 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
return;
spin_lock_irqsave(&subs->lock, flags);
+ if (!subs->last_delay)
+ goto out; /* short path */
+
est_delay = snd_usb_pcm_delay(subs, runtime->rate);
/* update delay with exact number of samples played */
if (processed > subs->last_delay)
@@ -1212,6 +1323,15 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
est_delay, subs->last_delay);
+ if (!subs->running) {
+ /* update last_frame_number for delay counting here since
+ * prepare_playback_urb won't be called during pause
+ */
+ subs->last_frame_number =
+ usb_get_current_frame_number(subs->dev) & 0xff;
+ }
+
+ out:
spin_unlock_irqrestore(&subs->lock, flags);
}
@@ -1248,12 +1368,13 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
subs->running = 1;
return 0;
case SNDRV_PCM_TRIGGER_STOP:
- stop_endpoints(subs, 0, 0, 0);
+ stop_endpoints(subs, false);
subs->running = 0;
return 0;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
subs->data_endpoint->prepare_data_urb = NULL;
- subs->data_endpoint->retire_data_urb = NULL;
+ /* keep retire_data_urb for delay calculation */
+ subs->data_endpoint->retire_data_urb = retire_playback_urb;
subs->running = 0;
return 0;
}
@@ -1269,7 +1390,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- err = start_endpoints(subs, 0);
+ err = start_endpoints(subs, false);
if (err < 0)
return err;
@@ -1277,7 +1398,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
subs->running = 1;
return 0;
case SNDRV_PCM_TRIGGER_STOP:
- stop_endpoints(subs, 0, 0, 0);
+ stop_endpoints(subs, false);
subs->running = 0;
return 0;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 88d8cebbb244..49f9af995d7a 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -1457,6 +1457,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /* Advanced mode of the Roland VG-99, with MIDI and 24-bit PCM at 44.1
+ * kHz. In standard mode, the device has ID 0582:00b3, and offers
+ * 16-bit PCM at 44.1 kHz with no MIDI.
+ */
+ USB_DEVICE(0x0582, 0x00b2),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Roland",
+ .product_name = "VG-99",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+{
/* Roland SonicCell */
USB_DEVICE(0x0582, 0x00c2),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -2163,6 +2197,77 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ /* .vendor_name = "M-Audio", */
+ /* .product_name = "Fast Track C400", */
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = &(const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_MIXER,
+ },
+ /* Playback */
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 6,
+ .iface = 2,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+ .endpoint = 0x01,
+ .ep_attr = 0x09,
+ .rates = SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 4,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 88200, 96000
+ },
+ .clock = 0x81,
+ }
+ },
+ /* Capture */
+ {
+ .ifnum = 3,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 4,
+ .iface = 3,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+ .endpoint = 0x81,
+ .ep_attr = 0x05,
+ .rates = SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000,
+ .rate_min = 44100,
+ .rate_max = 96000,
+ .nr_rates = 4,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000, 88200, 96000
+ },
+ .clock = 0x81,
+ }
+ },
+ /* MIDI */
+ {
+ .ifnum = -1 /* Interface = 4 */
+ }
+ }
+ }
+},
+{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "M-Audio", */
@@ -2880,6 +2985,99 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* Reloop Play */
+{
+ USB_DEVICE(0x200c, 0x100b),
+ .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = &(const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_MIXER,
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 4,
+ .iface = 1,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+ .endpoint = 0x01,
+ .ep_attr = USB_ENDPOINT_SYNC_ADAPTIVE,
+ .rates = SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .rate_min = 44100,
+ .rate_max = 48000,
+ .nr_rates = 2,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000
+ }
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+
+{
+ /*
+ * Focusrite Scarlett 18i6
+ *
+ * Avoid mixer creation, which otherwise fails because some of
+ * the interface descriptor subtypes for interface 0 are
+ * unknown. That should be fixed or worked-around but this at
+ * least allows the device to be used successfully with a DAW
+ * and an external mixer. See comments below about other
+ * ignored interfaces.
+ */
+ USB_DEVICE(0x1235, 0x8004),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Focusrite",
+ .product_name = "Scarlett 18i6",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const struct snd_usb_audio_quirk[]) {
+ {
+ /* InterfaceSubClass 1 (Control Device) */
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ /* InterfaceSubClass 1 (Control Device) */
+ .ifnum = 3,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 4,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ },
+ {
+ /* InterfaceSubClass 1 (Device Firmware Update) */
+ .ifnum = 5,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+
{
/*
* Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0f58b4b6d702..007fcecdf5cd 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -675,7 +675,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
*/
int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
{
- /* it depends on altsetting wether the device is big-endian or not */
+ /* it depends on altsetting whether the device is big-endian or not */
switch (chip->usb_id) {
case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
if (fp->altsetting == 2 || fp->altsetting == 3 ||
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 1de0c8c002a8..ad181d538bd9 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -23,6 +23,8 @@
#include <sound/core.h>
#include <sound/pcm.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
#include "usbaudio.h"
#include "card.h"
@@ -47,6 +49,7 @@ static void free_substream(struct snd_usb_substream *subs)
list_for_each_safe(p, n, &subs->fmt_list) {
struct audioformat *fp = list_entry(p, struct audioformat, list);
kfree(fp->rate_table);
+ kfree(fp->chmap);
kfree(fp);
}
kfree(subs->rate_list.list);
@@ -99,6 +102,206 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
subs->num_formats++;
subs->fmt_type = fp->fmt_type;
subs->ep_num = fp->endpoint;
+ if (fp->channels > subs->channels_max)
+ subs->channels_max = fp->channels;
+}
+
+/* kctl callbacks for usb-audio channel maps */
+static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+ struct snd_usb_substream *subs = info->private_data;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = subs->channels_max;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = SNDRV_CHMAP_LAST;
+ return 0;
+}
+
+/* check whether a duplicated entry exists in the audiofmt list */
+static bool have_dup_chmap(struct snd_usb_substream *subs,
+ struct audioformat *fp)
+{
+ struct list_head *p;
+
+ for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) {
+ struct audioformat *prev;
+ prev = list_entry(p, struct audioformat, list);
+ if (prev->chmap &&
+ !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
+ return true;
+ }
+ return false;
+}
+
+static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+ struct snd_usb_substream *subs = info->private_data;
+ struct audioformat *fp;
+ unsigned int __user *dst;
+ int count = 0;
+
+ if (size < 8)
+ return -ENOMEM;
+ if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
+ return -EFAULT;
+ size -= 8;
+ dst = tlv + 2;
+ list_for_each_entry(fp, &subs->fmt_list, list) {
+ int i, ch_bytes;
+
+ if (!fp->chmap)
+ continue;
+ if (have_dup_chmap(subs, fp))
+ continue;
+ /* copy the entry */
+ ch_bytes = fp->chmap->channels * 4;
+ if (size < 8 + ch_bytes)
+ return -ENOMEM;
+ if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
+ put_user(ch_bytes, dst + 1))
+ return -EFAULT;
+ dst += 2;
+ for (i = 0; i < fp->chmap->channels; i++, dst++) {
+ if (put_user(fp->chmap->map[i], dst))
+ return -EFAULT;
+ }
+
+ count += 8 + ch_bytes;
+ size -= 8 + ch_bytes;
+ }
+ if (put_user(count, tlv + 1))
+ return -EFAULT;
+ return 0;
+}
+
+static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+ struct snd_usb_substream *subs = info->private_data;
+ struct snd_pcm_chmap_elem *chmap = NULL;
+ int i;
+
+ memset(ucontrol->value.integer.value, 0,
+ sizeof(ucontrol->value.integer.value));
+ if (subs->cur_audiofmt)
+ chmap = subs->cur_audiofmt->chmap;
+ if (chmap) {
+ for (i = 0; i < chmap->channels; i++)
+ ucontrol->value.integer.value[i] = chmap->map[i];
+ }
+ return 0;
+}
+
+/* create a chmap kctl assigned to the given USB substream */
+static int add_chmap(struct snd_pcm *pcm, int stream,
+ struct snd_usb_substream *subs)
+{
+ struct audioformat *fp;
+ struct snd_pcm_chmap *chmap;
+ struct snd_kcontrol *kctl;
+ int err;
+
+ list_for_each_entry(fp, &subs->fmt_list, list)
+ if (fp->chmap)
+ goto ok;
+ /* no chmap is found */
+ return 0;
+
+ ok:
+ err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
+ if (err < 0)
+ return err;
+
+ /* override handlers */
+ chmap->private_data = subs;
+ kctl = chmap->kctl;
+ kctl->info = usb_chmap_ctl_info;
+ kctl->get = usb_chmap_ctl_get;
+ kctl->tlv.c = usb_chmap_ctl_tlv;
+
+ return 0;
+}
+
+/* convert from USB ChannelConfig bits to ALSA chmap element */
+static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
+ int protocol)
+{
+ static unsigned int uac1_maps[] = {
+ SNDRV_CHMAP_FL, /* left front */
+ SNDRV_CHMAP_FR, /* right front */
+ SNDRV_CHMAP_FC, /* center front */
+ SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_SL, /* left surround */
+ SNDRV_CHMAP_SR, /* right surround */
+ SNDRV_CHMAP_FLC, /* left of center */
+ SNDRV_CHMAP_FRC, /* right of center */
+ SNDRV_CHMAP_RC, /* surround */
+ SNDRV_CHMAP_SL, /* side left */
+ SNDRV_CHMAP_SR, /* side right */
+ SNDRV_CHMAP_TC, /* top */
+ 0 /* terminator */
+ };
+ static unsigned int uac2_maps[] = {
+ SNDRV_CHMAP_FL, /* front left */
+ SNDRV_CHMAP_FR, /* front right */
+ SNDRV_CHMAP_FC, /* front center */
+ SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_RL, /* back left */
+ SNDRV_CHMAP_RR, /* back right */
+ SNDRV_CHMAP_FLC, /* front left of center */
+ SNDRV_CHMAP_FRC, /* front right of center */
+ SNDRV_CHMAP_RC, /* back center */
+ SNDRV_CHMAP_SL, /* side left */
+ SNDRV_CHMAP_SR, /* side right */
+ SNDRV_CHMAP_TC, /* top center */
+ SNDRV_CHMAP_TFL, /* top front left */
+ SNDRV_CHMAP_TFC, /* top front center */
+ SNDRV_CHMAP_TFR, /* top front right */
+ SNDRV_CHMAP_TRL, /* top back left */
+ SNDRV_CHMAP_TRC, /* top back center */
+ SNDRV_CHMAP_TRR, /* top back right */
+ SNDRV_CHMAP_TFLC, /* top front left of center */
+ SNDRV_CHMAP_TFRC, /* top front right of center */
+ SNDRV_CHMAP_LLFE, /* left LFE */
+ SNDRV_CHMAP_RLFE, /* right LFE */
+ SNDRV_CHMAP_TSL, /* top side left */
+ SNDRV_CHMAP_TSR, /* top side right */
+ SNDRV_CHMAP_BC, /* bottom center */
+ SNDRV_CHMAP_BLC, /* bottom left center */
+ SNDRV_CHMAP_BRC, /* bottom right center */
+ 0 /* terminator */
+ };
+ struct snd_pcm_chmap_elem *chmap;
+ const unsigned int *maps;
+ int c;
+
+ if (!bits)
+ return NULL;
+ if (channels > ARRAY_SIZE(chmap->map))
+ return NULL;
+
+ chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
+ if (!chmap)
+ return NULL;
+
+ maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
+ chmap->channels = channels;
+ c = 0;
+ for (; bits && *maps; maps++, bits >>= 1) {
+ if (bits & 1)
+ chmap->map[c++] = *maps;
+ }
+
+ for (; c < channels; c++)
+ chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
+
+ return chmap;
}
/*
@@ -140,7 +343,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
if (err < 0)
return err;
snd_usb_init_substream(as, stream, fp);
- return 0;
+ return add_chmap(as->pcm, stream, subs);
}
/* create a new pcm */
@@ -174,7 +377,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
snd_usb_proc_pcm_format_add(as);
- return 0;
+ return add_chmap(pcm, stream, &as->substream[stream]);
}
static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
@@ -218,8 +421,11 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
return attributes;
}
-static struct uac2_input_terminal_descriptor *
- snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+/* find an input terminal descriptor (either UAC1 or UAC2) with the given
+ * terminal id
+ */
+static void *
+snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
int terminal_id)
{
struct uac2_input_terminal_descriptor *term = NULL;
@@ -261,6 +467,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
struct audioformat *fp = NULL;
int num, protocol, clock = 0;
struct uac_format_type_i_continuous_descriptor *fmt;
+ unsigned int chconfig;
dev = chip->dev;
@@ -300,6 +507,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
continue;
+ chconfig = 0;
/* get audio formats */
switch (protocol) {
default:
@@ -311,6 +519,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
case UAC_VERSION_1: {
struct uac1_as_header_descriptor *as =
snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+ struct uac_input_terminal_descriptor *iterm;
if (!as) {
snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
@@ -325,6 +534,14 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
}
format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+
+ iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (iterm) {
+ num_channels = iterm->bNrChannels;
+ chconfig = le16_to_cpu(iterm->wChannelConfig);
+ }
+
break;
}
@@ -355,6 +572,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
as->bTerminalLink);
if (input_term) {
clock = input_term->bCSourceID;
+ chconfig = le32_to_cpu(input_term->bmChannelConfig);
break;
}
@@ -413,13 +631,13 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
fp->datainterval = snd_usb_parse_datainterval(chip, alts);
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
- /* num_channels is only set for v2 interfaces */
fp->channels = num_channels;
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
fp->clock = clock;
+ fp->chmap = convert_chmap(num_channels, chconfig, protocol);
/* some quirks for attributes here */
@@ -455,6 +673,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* ok, let's parse further... */
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
kfree(fp->rate_table);
+ kfree(fp->chmap);
kfree(fp);
fp = NULL;
continue;
@@ -464,6 +683,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
kfree(fp->rate_table);
+ kfree(fp->chmap);
kfree(fp);
return err;
}
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index ef42797f56fb..1ac3fd9cc5a6 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -56,7 +56,6 @@ struct snd_usb_audio {
int setup; /* from the 'device_setup' module param */
int nrpacks; /* from the 'nrpacks' module param */
- int async_unlink; /* from the 'async_unlink' module param */
struct usb_host_interface *ctrl_intf; /* the audio control interface */
};
diff --git a/tools/firewire/nosy-dump.c b/tools/firewire/nosy-dump.c
index f93b776370b6..3179c711bd65 100644
--- a/tools/firewire/nosy-dump.c
+++ b/tools/firewire/nosy-dump.c
@@ -150,6 +150,8 @@ subaction_create(uint32_t *data, size_t length)
/* we put the ack in the subaction struct for easy access. */
sa = malloc(sizeof *sa - sizeof sa->packet + length);
+ if (!sa)
+ exit(EXIT_FAILURE);
sa->ack = data[length / 4 - 1];
sa->length = length;
memcpy(&sa->packet, data, length);
@@ -180,6 +182,8 @@ link_transaction_lookup(int request_node, int response_node, int tlabel)
}
t = malloc(sizeof *t);
+ if (!t)
+ exit(EXIT_FAILURE);
t->request_node = request_node;
t->response_node = response_node;
t->tlabel = tlabel;
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index b38a1f9ad460..938e8904f64d 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -175,7 +175,7 @@ following filters are defined:
+
The option requires at least one branch type among any, any_call, any_ret, ind_call.
-The privilege levels may be ommitted, in which case, the privilege levels of the associated
+The privilege levels may be omitted, in which case, the privilege levels of the associated
event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
levels are subject to permissions. When sampling on multiple events, branch stack sampling
is enabled for all the sampling events. The sampled branch type is the same for all events.
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index e626fa553c5a..6d25dcd2e97a 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -232,7 +232,7 @@ const struct option longopts[] = {
}
};
-static void help()
+static void help(void)
{
fprintf(stderr, "Usage: virtio_test [--help]"
" [--no-indirect]"
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index aca6edcbbc6f..af8c925e93eb 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -405,7 +405,6 @@ static char *cpio_replace_env(char *new_location)
return new_location;
}
-
static int cpio_mkfile_line(const char *line)
{
char name[PATH_MAX + 1];